Coverage Report

Created: 2026-06-10 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ada-url/build/singleheader/ada.cpp
Line
Count
Source
1
/* auto-generated on 2026-06-03 08:26:49 -0400. Do not edit! */
2
/* begin file src/ada.cpp */
3
#include "ada.h"
4
/* begin file src/checkers.cpp */
5
6
#include <algorithm>
7
#include <array>
8
#include <string_view>
9
10
namespace ada::checkers {
11
12
604k
ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept {
13
  // The string is not empty and does not contain upper case ASCII characters.
14
  //
15
  // Optimization. To be considered as a possible ipv4, the string must end
16
  // with 'x' or a lowercase hex character.
17
  // Most of the time, this will be false so this simple check will save a lot
18
  // of effort.
19
  // If the address ends with a dot, we need to prune it (special case).
20
604k
  if (view.ends_with('.')) {
21
25.5k
    view.remove_suffix(1);
22
25.5k
    if (view.empty()) {
23
13.9k
      return false;
24
13.9k
    }
25
25.5k
  }
26
590k
  char last_char = view.back();
27
590k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
529k
                       (last_char >= 'a' && last_char <= 'f') ||
29
485k
                       last_char == 'x';
30
590k
  if (!possible_ipv4) {
31
478k
    return false;
32
478k
  }
33
  // From the last character, find the last dot.
34
111k
  size_t last_dot = view.rfind('.');
35
111k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
23.0k
    view.remove_prefix(last_dot + 1);
38
23.0k
  }
39
  /** Optimization opportunity: we have basically identified the last number of
40
     the ipv4 if we return true here. We might as well parse it and have at
41
     least one number parsed when we get to parse_ipv4. */
42
111k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
49.0k
    return true;
44
49.0k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
62.4k
  if (view.size() == 1) {
47
14.9k
    return false;
48
14.9k
  }
49
  // It must start with 0x.
50
47.4k
  if (!view.starts_with("0x")) {
51
30.1k
    return false;
52
30.1k
  }
53
  // We must allow "0x".
54
17.3k
  if (view.size() == 2) {
55
1.46k
    return true;
56
1.46k
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
15.8k
  view.remove_prefix(2);
60
15.8k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
17.3k
}
62
63
// for use with path_signature, we include all characters that need percent
64
// encoding.
65
static constexpr std::array<uint8_t, 256> path_signature_table =
66
    []() consteval {
67
      std::array<uint8_t, 256> result{};
68
      for (size_t i = 0; i < 256; i++) {
69
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
70
            i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d ||
71
            i > 0x7e) {
72
          result[i] = 1;
73
        } else if (i == 0x25) {
74
          result[i] = 8;
75
        } else if (i == 0x2e) {
76
          result[i] = 4;
77
        } else if (i == 0x5c) {
78
          result[i] = 2;
79
        } else {
80
          result[i] = 0;
81
        }
82
      }
83
      return result;
84
    }();
85
86
ada_really_inline constexpr uint8_t path_signature(
87
519k
    std::string_view input) noexcept {
88
  // The path percent-encode set is the query percent-encode set and U+003F (?),
89
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
90
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
91
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
92
  // controls and all code points greater than U+007E (~).
93
519k
  size_t i = 0;
94
519k
  uint8_t accumulator{};
95
1.10M
  for (; i + 7 < input.size(); i += 8) {
96
590k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
590k
                           path_signature_table[uint8_t(input[i + 1])] |
98
590k
                           path_signature_table[uint8_t(input[i + 2])] |
99
590k
                           path_signature_table[uint8_t(input[i + 3])] |
100
590k
                           path_signature_table[uint8_t(input[i + 4])] |
101
590k
                           path_signature_table[uint8_t(input[i + 5])] |
102
590k
                           path_signature_table[uint8_t(input[i + 6])] |
103
590k
                           path_signature_table[uint8_t(input[i + 7])]);
104
590k
  }
105
1.60M
  for (; i < input.size(); i++) {
106
1.08M
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
1.08M
  }
108
519k
  return accumulator;
109
519k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
67.0k
    std::string_view input) noexcept {
113
67.0k
  if (input.empty()) return false;
114
60.4k
  if (input.back() == '.') {
115
3.25k
    if (input.size() > 254) return false;
116
57.2k
  } else if (input.size() > 253)
117
579
    return false;
118
119
59.6k
  size_t start = 0;
120
182k
  while (start < input.size()) {
121
127k
    auto dot_location = input.find('.', start);
122
    // If not found, it's likely the end of the domain
123
127k
    if (dot_location == std::string_view::npos) dot_location = input.size();
124
125
127k
    auto label_size = dot_location - start;
126
127k
    if (label_size > 63 || label_size == 0) return false;
127
128
122k
    start = dot_location + 1;
129
122k
  }
130
131
55.1k
  return true;
132
59.6k
}
133
134
}  // namespace ada::checkers
135
/* end file src/checkers.cpp */
136
/* begin file src/unicode.cpp */
137
138
139
ADA_PUSH_DISABLE_ALL_WARNINGS
140
/* begin file src/ada_idna.cpp */
141
/* auto-generated on 2026-05-25 17:39:11 -0400. Do not edit! */
142
/* begin file src/idna.cpp */
143
/* begin file src/unicode_transcoding.cpp */
144
145
#include <algorithm>
146
#include <cstdint>
147
#include <cstring>
148
149
namespace ada::idna {
150
151
74.3k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
152
74.3k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
153
74.3k
  size_t pos = 0;
154
74.3k
  const char32_t* start{utf32_output};
155
791k
  while (pos < len) {
156
    // try to convert the next block of 16 ASCII bytes
157
733k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
158
                            // bytes, check that they are ascii
159
361k
      uint64_t v1;
160
361k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
161
361k
      uint64_t v2;
162
361k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
163
361k
      uint64_t v{v1 | v2};
164
361k
      if ((v & 0x8080808080808080) == 0) {
165
19.3k
        size_t final_pos = pos + 16;
166
328k
        while (pos < final_pos) {
167
309k
          *utf32_output++ = char32_t(buf[pos]);
168
309k
          pos++;
169
309k
        }
170
19.3k
        continue;
171
19.3k
      }
172
361k
    }
173
714k
    uint8_t leading_byte = data[pos];  // leading byte
174
714k
    if (leading_byte < 0b10000000) {
175
      // converting one ASCII byte !!!
176
435k
      *utf32_output++ = char32_t(leading_byte);
177
435k
      pos++;
178
435k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
179
      // We have a two-byte UTF-8
180
60.2k
      if (pos + 1 >= len) {
181
1.07k
        return 0;
182
1.07k
      }  // minimal bound checking
183
59.1k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
184
1.72k
        return 0;
185
1.72k
      }
186
      // range check
187
57.4k
      uint32_t code_point =
188
57.4k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
189
57.4k
      if (code_point < 0x80 || 0x7ff < code_point) {
190
162
        return 0;
191
162
      }
192
57.3k
      *utf32_output++ = char32_t(code_point);
193
57.3k
      pos += 2;
194
218k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
195
      // We have a three-byte UTF-8
196
202k
      if (pos + 2 >= len) {
197
2.07k
        return 0;
198
2.07k
      }  // minimal bound checking
199
200
200k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
201
940
        return 0;
202
940
      }
203
199k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
204
330
        return 0;
205
330
      }
206
      // range check
207
199k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
208
199k
                            (data[pos + 1] & 0b00111111) << 6 |
209
199k
                            (data[pos + 2] & 0b00111111);
210
199k
      if (code_point < 0x800 || 0xffff < code_point ||
211
198k
          (0xd7ff < code_point && code_point < 0xe000)) {
212
567
        return 0;
213
567
      }
214
198k
      *utf32_output++ = char32_t(code_point);
215
198k
      pos += 3;
216
198k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
217
      // we have a 4-byte UTF-8 word.
218
9.00k
      if (pos + 3 >= len) {
219
546
        return 0;
220
546
      }  // minimal bound checking
221
8.45k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
222
752
        return 0;
223
752
      }
224
7.70k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
225
289
        return 0;
226
289
      }
227
7.41k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
228
293
        return 0;
229
293
      }
230
231
      // range check
232
7.12k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
233
7.12k
                            (data[pos + 1] & 0b00111111) << 12 |
234
7.12k
                            (data[pos + 2] & 0b00111111) << 6 |
235
7.12k
                            (data[pos + 3] & 0b00111111);
236
7.12k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
237
746
        return 0;
238
746
      }
239
6.37k
      *utf32_output++ = char32_t(code_point);
240
6.37k
      pos += 4;
241
6.54k
    } else {
242
6.54k
      return 0;
243
6.54k
    }
244
714k
  }
245
58.2k
  return utf32_output - start;
246
74.3k
}
247
248
9.41k
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
249
  // We are not BOM aware.
250
9.41k
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
251
9.41k
  size_t counter{0};
252
175k
  for (size_t i = 0; i != len; ++i) {
253
165k
    ++counter;                                      // ASCII
254
165k
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
255
165k
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
256
165k
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
257
165k
  }
258
9.41k
  return counter;
259
9.41k
}
260
261
74.4k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
262
74.4k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
263
1.83M
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
1.83M
    return c > -65;
267
1.83M
  });
idna.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Line
Count
Source
263
469k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
469k
    return c > -65;
267
469k
  });
ada.cpp:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Line
Count
Source
263
502k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
502k
    return c > -65;
267
502k
  });
serializers.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Line
Count
Source
263
32.0k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
32.0k
    return c > -65;
267
32.0k
  });
Unexecuted instantiation: can_parse.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Unexecuted instantiation: unicode.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
parse.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Line
Count
Source
263
490k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
490k
    return c > -65;
267
490k
  });
url_pattern.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
Line
Count
Source
263
342k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
264
    // -65 is 0b10111111, anything larger in two-complement's
265
    // should start a new code point.
266
342k
    return c > -65;
267
342k
  });
Unexecuted instantiation: url_search_params.cc:ada::idna::utf32_length_from_utf8(char const*, unsigned long)::$_0::operator()(signed char) const
268
74.4k
}
269
270
9.41k
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
271
9.41k
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
272
9.41k
  size_t pos = 0;
273
9.41k
  const char* start{utf8_output};
274
139k
  while (pos < len) {
275
    // try to convert the next block of 2 ASCII characters
276
130k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
277
                           // bytes, check that they are ascii
278
121k
      uint64_t v;
279
121k
      std::memcpy(&v, data + pos, sizeof(uint64_t));
280
121k
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
281
35.6k
        *utf8_output++ = char(buf[pos]);
282
35.6k
        *utf8_output++ = char(buf[pos + 1]);
283
35.6k
        pos += 2;
284
35.6k
        continue;
285
35.6k
      }
286
121k
    }
287
94.3k
    uint32_t word = data[pos];
288
94.3k
    if ((word & 0xFFFFFF80) == 0) {
289
      // will generate one UTF-8 bytes
290
13.1k
      *utf8_output++ = char(word);
291
13.1k
      pos++;
292
81.2k
    } else if ((word & 0xFFFFF800) == 0) {
293
      // will generate two UTF-8 bytes
294
      // we have 0b110XXXXX 0b10XXXXXX
295
49.7k
      *utf8_output++ = char((word >> 6) | 0b11000000);
296
49.7k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
297
49.7k
      pos++;
298
49.7k
    } else if ((word & 0xFFFF0000) == 0) {
299
      // will generate three UTF-8 bytes
300
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
301
27.7k
      if (word >= 0xD800 && word <= 0xDFFF) {
302
0
        return 0;
303
0
      }
304
27.7k
      *utf8_output++ = char((word >> 12) | 0b11100000);
305
27.7k
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
306
27.7k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
307
27.7k
      pos++;
308
27.7k
    } else {
309
      // will generate four UTF-8 bytes
310
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
311
      // 0b10XXXXXX
312
3.66k
      if (word > 0x10FFFF) {
313
0
        return 0;
314
0
      }
315
3.66k
      *utf8_output++ = char((word >> 18) | 0b11110000);
316
3.66k
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
317
3.66k
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
318
3.66k
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
319
3.66k
      pos++;
320
3.66k
    }
321
94.3k
  }
322
9.41k
  return utf8_output - start;
323
9.41k
}
324
}  // namespace ada::idna
325
/* end file src/unicode_transcoding.cpp */
326
/* begin file src/mapping.cpp */
327
328
#include <array>
329
#include <cstring>
330
#include <cstdint>
331
#include <string>
332
333
/* begin file src/mapping_tables.cpp */
334
// IDNA 17.0.0
335
// Two-level compressed mapping table.
336
// All constants are derived from the table data; no hardcoded boundaries.
337
// Total binary size: 48659 bytes (47.5 KB)
338
//   stage1:        6564 bytes  (3282 uint16_t entries)
339
//   stage2:       22912 bytes  (179 mixed blocks x 64)
340
//   bool_blocks:   1800 bytes  (225 uint64_t words)
341
//   utf8 maps:    17383 bytes
342
343
// clang-format off
344
#ifndef ADA_IDNA_MAPPING_TABLE_H
345
#define ADA_IDNA_MAPPING_TABLE_H
346
#include <cstdint>
347
348
namespace ada::idna {
349
350
// Block size for two-level table (2^6 = 64 code points per block).
351
constexpr uint32_t IDNA_BLOCK_BITS = 6u;
352
constexpr uint32_t IDNA_BLOCK_SIZE = 64u;
353
constexpr uint32_t IDNA_BLOCK_MASK = 63u;
354
355
// Sentinel values stored in stage2 / returned by lookup.
356
constexpr uint16_t IDNA_VALID      = 0xFFFF;  // code point is valid as-is
357
constexpr uint16_t IDNA_DISALLOWED = 0xFFFE;  // code point is disallowed
358
constexpr uint16_t IDNA_IGNORED    = 0x0000;    // ignored (index into empty UTF-8 entry)
359
360
// Bit 15 of a stage1 entry: set = boolean block, clear = mixed block.
361
constexpr uint16_t IDNA_BOOL_FLAG  = 0x8000;
362
363
// Two-level table covers code points [0, IDNA_LOW_RANGE_END).
364
// Derived from the highest non-disallowed code point below the high-ignored range,
365
// rounded up to the next 64-code-point block boundary.
366
constexpr uint32_t IDNA_LOW_RANGE_END    = 0x00033480;
367
368
// Variation selectors supplement: U+E0100..U+E01EF are all ignored.
369
// These are handled with a simple range check; everything else above
370
// IDNA_LOW_RANGE_END is disallowed.
371
constexpr uint32_t IDNA_HIGH_IGNORED_START = 0x000E0100;
372
constexpr uint32_t IDNA_HIGH_IGNORED_END   = 0x000E01F0;  // exclusive
373
374
// idna_stage1[cp >> 6]: one entry per 64-code-point block.
375
// Bit 15 set  -> lower 15 bits = index into idna_bool_blocks[].
376
// Bit 15 clear -> value = base offset into idna_stage2[] for this block.
377
const uint16_t idna_stage1[3282] = {
378
  0x8000, 0x0000, 0x0040, 0x0080, 0x00C0, 0x0100, 0x0140, 0x0180, 0x01C0, 0x0200, 0x0240, 0x0280,
379
  0x8000, 0x02C0, 0x0300, 0x0340, 0x0380, 0x03C0, 0x0400, 0x0440, 0x0480, 0x04C0, 0x0500, 0x8001,
380
  0x8002, 0x0540, 0x8000, 0x8003, 0x8004, 0x8005, 0x8006, 0x8007, 0x8008, 0x8009, 0x800A, 0x800B,
381
  0x8000, 0x0580, 0x800C, 0x05C0, 0x0600, 0x0640, 0x800D, 0x800E, 0x800F, 0x0680, 0x8010, 0x8011,
382
  0x8012, 0x8013, 0x8014, 0x8015, 0x8016, 0x8017, 0x8018, 0x8019, 0x06C0, 0x801A, 0x0700, 0x0740,
383
  0x0780, 0x07C0, 0x0800, 0x801B, 0x8000, 0x8000, 0x0840, 0x0880, 0x8000, 0x08C0, 0x8000, 0x8000,
384
  0x8000, 0x801C, 0x801D, 0x801E, 0x801F, 0x8020, 0x8021, 0x0900, 0x8000, 0x8000, 0x8000, 0x8000,
385
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8022, 0x8023, 0x8024, 0x8025, 0x0940, 0x8026,
386
  0x0980, 0x8023, 0x8027, 0x8028, 0x8029, 0x802A, 0x802B, 0x802C, 0x802D, 0x802E, 0x802F, 0x8030,
387
  0x8000, 0x8031, 0x8000, 0x8032, 0x8033, 0x8034, 0x09C0, 0x8035, 0x0A00, 0x0A40, 0x0A80, 0x8000,
388
  0x0AC0, 0x0B00, 0x0B40, 0x0B80, 0x0BC0, 0x0C00, 0x0C40, 0x0C80, 0x0CC0, 0x0D00, 0x0D40, 0x8036,
389
  0x0D80, 0x0DC0, 0x0E00, 0x8000, 0x0E40, 0x8000, 0x8000, 0x8000, 0x0E80, 0x8000, 0x8000, 0x8000,
390
  0x8037, 0x0EC0, 0x0F00, 0x0F40, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
391
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
392
  0x0F80, 0x0FC0, 0x8000, 0x1000, 0x8000, 0x8038, 0x8000, 0x8000, 0x1040, 0x1080, 0x10C0, 0x1100,
393
  0x8039, 0x1140, 0x803A, 0x803B, 0x8000, 0x803C, 0x1180, 0x11C0, 0x1200, 0x1240, 0x1280, 0x12C0,
394
  0x1300, 0x803D, 0x1340, 0x1380, 0x13C0, 0x1400, 0x1440, 0x803E, 0x1480, 0x14C0, 0x1500, 0x1540,
395
  0x1580, 0x15C0, 0x1600, 0x1640, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
396
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
397
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
398
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
399
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
400
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
401
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
402
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
403
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
404
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
405
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
406
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
407
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
408
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
409
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
410
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
411
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
412
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
413
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
414
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
415
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
416
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
417
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
418
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
419
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
420
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
421
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
422
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
423
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
424
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
425
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
426
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
427
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
428
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
429
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
430
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
431
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
432
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x803F, 0x8040,
433
  0x8000, 0x8000, 0x8000, 0x8000, 0x8041, 0x1680, 0x16C0, 0x8042, 0x1700, 0x1740, 0x1780, 0x17C0,
434
  0x8043, 0x8042, 0x8000, 0x8044, 0x8000, 0x8045, 0x8000, 0x8046, 0x8047, 0x8048, 0x8000, 0x8049,
435
  0x804A, 0x1800, 0x1840, 0x804B, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
436
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
437
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
438
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
439
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
440
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
441
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
442
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
443
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
444
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
445
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
446
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
447
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
448
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
449
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x804C, 0x804D,
450
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
451
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
452
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
453
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
454
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
455
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
456
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
457
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
458
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
459
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
460
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
461
  0x1880, 0x18C0, 0x1900, 0x1940, 0x1980, 0x19C0, 0x1A00, 0x1A40, 0x1A80, 0x1AC0, 0x1B00, 0x1B40,
462
  0x1B80, 0x1BC0, 0x1C00, 0x1C40, 0x1C80, 0x1CC0, 0x1D00, 0x1D40, 0x1D80, 0x1DC0, 0x1E00, 0x1E40,
463
  0x1E80, 0x1EC0, 0x1F00, 0x1F40, 0x804F, 0x8050, 0x8000, 0x8051, 0x8052, 0x8000, 0x8053, 0x8054,
464
  0x804E, 0x804E, 0x8055, 0x8056, 0x8057, 0x8058, 0x8059, 0x805A, 0x1F80, 0x8000, 0x1FC0, 0x2000,
465
  0x805B, 0x2040, 0x2080, 0x805C, 0x8000, 0x8000, 0x8000, 0x8000, 0x8047, 0x805D, 0x20C0, 0x804E,
466
  0x805E, 0x805F, 0x8060, 0x8061, 0x8062, 0x8063, 0x8064, 0x8065, 0x8066, 0x8067, 0x8068, 0x8069,
467
  0x806A, 0x806B, 0x806C, 0x804E, 0x8000, 0x806D, 0x2100, 0x806E, 0x806F, 0x2140, 0x8070, 0x804E,
468
  0x804E, 0x8071, 0x8072, 0x8073, 0x805B, 0x8074, 0x8075, 0x8076, 0x8000, 0x8077, 0x8078, 0x8079,
469
  0x807A, 0x807B, 0x8000, 0x807C, 0x807D, 0x807E, 0x807F, 0x8080, 0x8081, 0x8082, 0x8083, 0x8084,
470
  0x8000, 0x8085, 0x8000, 0x8086, 0x804E, 0x804E, 0x8087, 0x803C, 0x8000, 0x8088, 0x8089, 0x808A,
471
  0x808B, 0x808C, 0x804E, 0x804E, 0x808D, 0x804E, 0x2180, 0x808E, 0x808F, 0x8090, 0x8091, 0x8092,
472
  0x8000, 0x8093, 0x8094, 0x8023, 0x8095, 0x8096, 0x804E, 0x8097, 0x8098, 0x8099, 0x809A, 0x804E,
473
  0x809B, 0x809C, 0x809D, 0x809E, 0x804E, 0x804E, 0x804E, 0x809F, 0x80A0, 0x80A1, 0x80A2, 0x80A3,
474
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
475
  0x8000, 0x8000, 0x8063, 0x804E, 0x8000, 0x80A4, 0x8000, 0x8000, 0x8000, 0x80A5, 0x804E, 0x804E,
476
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
477
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
478
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
479
  0x804E, 0x804E, 0x80A6, 0x80A7, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
480
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x80A8, 0x80A9, 0x8000, 0x8000,
481
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
482
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
483
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
484
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
485
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8051,
486
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x808C, 0x804E, 0x804E,
487
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
488
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
489
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
490
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
491
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
492
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
493
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
494
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
495
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x8089, 0x804E, 0x804E, 0x804E,
496
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
497
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
498
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8023, 0x80AA, 0x80AB, 0x80AC,
499
  0x8000, 0x80AD, 0x80AE, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x8089, 0x804E, 0x804E,
500
  0x804E, 0x21C0, 0x2200, 0x80AF, 0x8000, 0x80B0, 0x80B1, 0x80B2, 0x8000, 0x8000, 0x8000, 0x8000,
501
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
502
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
503
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
504
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
505
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
506
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
507
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
508
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
509
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
510
  0x8000, 0x8000, 0x8000, 0x80B3, 0x80B4, 0x804E, 0x8000, 0x80A7, 0x804E, 0x804E, 0x804E, 0x804E,
511
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
512
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
513
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
514
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
515
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
516
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
517
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
518
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
519
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
520
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
521
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x80B5,
522
  0x8000, 0x8000, 0x8000, 0x8000, 0x80B6, 0x80B7, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x808D,
523
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
524
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
525
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
526
  0x8000, 0x80B8, 0x2240, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
527
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
528
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
529
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
530
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
531
  0x804E, 0x804E, 0x804E, 0x804E, 0x8000, 0x8000, 0x8000, 0x2280, 0x8000, 0x8000, 0x8000, 0x8000,
532
  0x8000, 0x8000, 0x80B9, 0x80BA, 0x80BB, 0x8040, 0x8000, 0x80A5, 0x8000, 0x8000, 0x8000, 0x8028,
533
  0x80BC, 0x22C0, 0x2300, 0x2340, 0x8000, 0x80BD, 0x804E, 0x80BE, 0x8000, 0x80BF, 0x804E, 0x804E,
534
  0x2380, 0x23C0, 0x2400, 0x2440, 0x2480, 0x24C0, 0x2500, 0x2540, 0x2580, 0x25C0, 0x2600, 0x2640,
535
  0x2680, 0x26C0, 0x2700, 0x2740, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
536
  0x8000, 0x8000, 0x80C0, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
537
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x80C1, 0x804E, 0x804E, 0x804E,
538
  0x2780, 0x27C0, 0x80C2, 0x804E, 0x80C3, 0x80C4, 0x804E, 0x804E, 0x804E, 0x804E, 0x80C5, 0x80C6,
539
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x80C7, 0x804E, 0x804E, 0x804E, 0x80C8,
540
  0x804E, 0x804E, 0x804E, 0x80C9, 0x804E, 0x804E, 0x804E, 0x80CA, 0x8000, 0x8000, 0x8000, 0x80CB,
541
  0x2800, 0x80CC, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
542
  0x804E, 0x80CD, 0x80CE, 0x804E, 0x80CF, 0x804E, 0x804E, 0x804E, 0x2840, 0x2880, 0x28C0, 0x80D0,
543
  0x804E, 0x804E, 0x804E, 0x804E, 0x802B, 0x8000, 0x80D1, 0x80D2, 0x2900, 0x2940, 0x2980, 0x80D3,
544
  0x29C0, 0x2A00, 0x804E, 0x804E, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
545
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x80D4, 0x8000, 0x8000, 0x8000, 0x80D5,
546
  0x80D6, 0x80D7, 0x80D8, 0x80D9, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x80DA, 0x80DB, 0x80DC,
547
  0x8000, 0x8000, 0x80DD, 0x2A40, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
548
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x8000, 0x8000, 0x8000, 0x8000,
549
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
550
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
551
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
552
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
553
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
554
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
555
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
556
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
557
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
558
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
559
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
560
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
561
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
562
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
563
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
564
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
565
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
566
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
567
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
568
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
569
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
570
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
571
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
572
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
573
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
574
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
575
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
576
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
577
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
578
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
579
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
580
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
581
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
582
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
583
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
584
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
585
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
586
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
587
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
588
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
589
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
590
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
591
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
592
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
593
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
594
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
595
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
596
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
597
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
598
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
599
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
600
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
601
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
602
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
603
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
604
  0x8000, 0x8000, 0x8000, 0x8068, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
605
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
606
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
607
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
608
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
609
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
610
  0x80DE, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
611
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
612
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
613
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
614
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
615
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
616
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
617
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x80BB, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
618
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
619
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
620
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
621
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
622
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
623
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
624
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
625
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
626
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
627
  0x8000, 0x8000, 0x8000, 0x80DF, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
628
  0x8000, 0x803C, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
629
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
630
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
631
  0x804E, 0x804E, 0x804E, 0x804E, 0x2A80, 0x2AC0, 0x2B00, 0x2B40, 0x2B80, 0x2BC0, 0x2C00, 0x2C40,
632
  0x2C80, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
633
  0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E, 0x804E,
634
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
635
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
636
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
637
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
638
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
639
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
640
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x80E0, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
641
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
642
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
643
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
644
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
645
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
646
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
647
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
648
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
649
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
650
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
651
  0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8089
652
};
653
654
// idna_stage2[]: mixed blocks. Each entry is IDNA_VALID, IDNA_DISALLOWED,
655
// IDNA_IGNORED, or a byte offset into idna_utf8_mappings[].
656
const uint16_t idna_stage2[11456] = {
657
  0xFFFF, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015,
658
  0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D,
659
  0x002F, 0x0031, 0x0033, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
660
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
661
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
662
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
663
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
664
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
665
  0x0035, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0037, 0xFFFF, 0x0001, 0xFFFF,
666
  0xFFFF, 0x0000, 0xFFFF, 0x003B, 0xFFFF, 0xFFFF, 0x003F, 0x0041, 0x0043, 0x0047, 0xFFFF, 0xFFFF,
667
  0x004A, 0x004E, 0x001D, 0xFFFF, 0x0050, 0x0056, 0x005C, 0xFFFF, 0x0062, 0x0065, 0x0068, 0x006B,
668
  0x006E, 0x0071, 0x0074, 0x0077, 0x007A, 0x007D, 0x0080, 0x0083, 0x0086, 0x0089, 0x008C, 0x008F,
669
  0x0092, 0x0095, 0x0098, 0x009B, 0x009E, 0x00A1, 0x00A4, 0xFFFF, 0x00A7, 0x00AA, 0x00AD, 0x00B0,
670
  0x00B3, 0x00B6, 0x00B9, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
671
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
672
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
673
  0x00BC, 0xFFFF, 0x00BF, 0xFFFF, 0x00C2, 0xFFFF, 0x00C5, 0xFFFF, 0x00C8, 0xFFFF, 0x00CB, 0xFFFF,
674
  0x00CE, 0xFFFF, 0x00D1, 0xFFFF, 0x00D4, 0xFFFF, 0x00D7, 0xFFFF, 0x00DA, 0xFFFF, 0x00DD, 0xFFFF,
675
  0x00E0, 0xFFFF, 0x00E3, 0xFFFF, 0x00E6, 0xFFFF, 0x00E9, 0xFFFF, 0x00EC, 0xFFFF, 0x00EF, 0xFFFF,
676
  0x00F2, 0xFFFF, 0x00F5, 0xFFFF, 0x00F8, 0xFFFF, 0x00FB, 0xFFFF, 0x00FE, 0xFFFF, 0x0101, 0xFFFF,
677
  0x0104, 0xFFFF, 0x0108, 0x0108, 0x010B, 0xFFFF, 0x010E, 0xFFFF, 0xFFFF, 0x0111, 0xFFFF, 0x0114,
678
  0xFFFF, 0x0117, 0xFFFF, 0x011A, 0x011A, 0x011E, 0xFFFF, 0x0121, 0xFFFF, 0x0124, 0xFFFF, 0x0127,
679
  0xFFFF, 0x012A, 0x012E, 0xFFFF, 0x0131, 0xFFFF, 0x0134, 0xFFFF, 0x0137, 0xFFFF, 0x013A, 0xFFFF,
680
  0x013D, 0xFFFF, 0x0140, 0xFFFF, 0x0143, 0xFFFF, 0x0146, 0xFFFF, 0x0149, 0xFFFF, 0x014C, 0xFFFF,
681
  0x014F, 0xFFFF, 0x0152, 0xFFFF, 0x0155, 0xFFFF, 0x0158, 0xFFFF, 0x015B, 0xFFFF, 0x015E, 0xFFFF,
682
  0x0161, 0xFFFF, 0x0164, 0xFFFF, 0x0167, 0xFFFF, 0x016A, 0xFFFF, 0x016D, 0xFFFF, 0x0170, 0xFFFF,
683
  0x0173, 0x0176, 0xFFFF, 0x0179, 0xFFFF, 0x017C, 0xFFFF, 0x0025, 0xFFFF, 0x017F, 0x0182, 0xFFFF,
684
  0x0185, 0xFFFF, 0x0188, 0x018B, 0xFFFF, 0x018E, 0x0191, 0x0194, 0xFFFF, 0xFFFF, 0x0197, 0x019A,
685
  0x019D, 0x01A0, 0xFFFF, 0x01A3, 0x01A6, 0xFFFF, 0x01A9, 0x01AC, 0x01AF, 0xFFFF, 0xFFFF, 0xFFFF,
686
  0x01B2, 0x01B5, 0xFFFF, 0x01B8, 0x01BB, 0xFFFF, 0x01BE, 0xFFFF, 0x01C1, 0xFFFF, 0x01C4, 0x01C7,
687
  0xFFFF, 0x01CA, 0xFFFF, 0xFFFF, 0x01CD, 0xFFFF, 0x01D0, 0x01D3, 0xFFFF, 0x01D6, 0x01D9, 0x01DC,
688
  0xFFFF, 0x01DF, 0xFFFF, 0x01E2, 0x01E5, 0xFFFF, 0xFFFF, 0xFFFF, 0x01E8, 0xFFFF, 0xFFFF, 0xFFFF,
689
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x01EB, 0x01EB, 0x01EB, 0x01EF, 0x01EF, 0x01EF, 0x01F2, 0x01F2,
690
  0x01F2, 0x01F5, 0xFFFF, 0x01F8, 0xFFFF, 0x01FB, 0xFFFF, 0x01FE, 0xFFFF, 0x0201, 0xFFFF, 0x0204,
691
  0xFFFF, 0x0207, 0xFFFF, 0x020A, 0xFFFF, 0xFFFF, 0x020D, 0xFFFF, 0x0210, 0xFFFF, 0x0213, 0xFFFF,
692
  0x0216, 0xFFFF, 0x0219, 0xFFFF, 0x021C, 0xFFFF, 0x021F, 0xFFFF, 0x0222, 0xFFFF, 0x0225, 0xFFFF,
693
  0xFFFF, 0x0228, 0x0228, 0x0228, 0x022B, 0xFFFF, 0x022E, 0x0231, 0x0234, 0xFFFF, 0x0237, 0xFFFF,
694
  0x023A, 0xFFFF, 0x023D, 0xFFFF, 0x0240, 0xFFFF, 0x0243, 0xFFFF, 0x0246, 0xFFFF, 0x0249, 0xFFFF,
695
  0x024C, 0xFFFF, 0x024F, 0xFFFF, 0x0252, 0xFFFF, 0x0255, 0xFFFF, 0x0258, 0xFFFF, 0x025B, 0xFFFF,
696
  0x025E, 0xFFFF, 0x0261, 0xFFFF, 0x0264, 0xFFFF, 0x0267, 0xFFFF, 0x026A, 0xFFFF, 0x026D, 0xFFFF,
697
  0x0270, 0xFFFF, 0x0273, 0xFFFF, 0x0276, 0xFFFF, 0x0279, 0xFFFF, 0x027C, 0xFFFF, 0x027F, 0xFFFF,
698
  0x0282, 0xFFFF, 0x0285, 0xFFFF, 0x0288, 0xFFFF, 0x028B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
699
  0xFFFF, 0xFFFF, 0x028E, 0x0292, 0xFFFF, 0x0295, 0x0298, 0xFFFF, 0xFFFF, 0x029C, 0xFFFF, 0x029F,
700
  0x02A2, 0x02A5, 0x02A8, 0xFFFF, 0x02AB, 0xFFFF, 0x02AE, 0xFFFF, 0x02B1, 0xFFFF, 0x02B4, 0xFFFF,
701
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
702
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
703
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
704
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
705
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
706
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
707
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
708
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
709
  0x000F, 0x02B7, 0x0013, 0x0023, 0x02BA, 0x02BD, 0x02C0, 0x002D, 0x0031, 0xFFFF, 0xFFFF, 0xFFFF,
710
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
711
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
712
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x02C3, 0x02C7, 0x02CB, 0x02CF, 0x02D3, 0x02D7, 0xFFFF, 0xFFFF,
713
  0x01A6, 0x0017, 0x0025, 0x002F, 0x02DB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
714
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
715
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x02DE, 0x02E1, 0xFFFF, 0x02E4,
716
  0x02E7, 0x02EC, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
717
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
718
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
719
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x02EF, 0xFFFF, 0x02F2, 0xFFFF,
720
  0x02F5, 0xFFFF, 0x02F8, 0xFFFF, 0xFFFE, 0xFFFE, 0x02FB, 0xFFFF, 0xFFFF, 0xFFFF, 0x02FF, 0x0301,
721
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0043, 0x0304, 0x030A, 0x030D, 0x0310, 0x0313, 0x0316, 0xFFFE,
722
  0x0319, 0xFFFE, 0x031C, 0x031F, 0xFFFF, 0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331, 0x0334,
723
  0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0xFFFE, 0x034F,
724
  0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x0364, 0x0367, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
725
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
726
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
727
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x036A, 0x0325, 0x0337, 0x0355, 0x031C,
728
  0x0367, 0x0358, 0x0349, 0xFFFF, 0x036D, 0xFFFF, 0x0370, 0xFFFF, 0x0373, 0xFFFF, 0x0376, 0xFFFF,
729
  0x0379, 0xFFFF, 0x037C, 0xFFFF, 0x037F, 0xFFFF, 0x0382, 0xFFFF, 0x0385, 0xFFFF, 0x0388, 0xFFFF,
730
  0x038B, 0xFFFF, 0x038E, 0xFFFF, 0x033A, 0x034C, 0x034F, 0xFFFF, 0x0337, 0x032E, 0xFFFF, 0x0391,
731
  0xFFFF, 0x034F, 0x0394, 0xFFFF, 0xFFFF, 0x0397, 0x039A, 0x039D, 0x03A0, 0x03A3, 0x03A6, 0x03A9,
732
  0x03AC, 0x03AF, 0x03B2, 0x03B5, 0x03B8, 0x03BB, 0x03BE, 0x03C1, 0x03C4, 0x03C7, 0x03CA, 0x03CD,
733
  0x03D0, 0x03D3, 0x03D6, 0x03D9, 0x03DC, 0x03DF, 0x03E2, 0x03E5, 0x03E8, 0x03EB, 0x03EE, 0x03F1,
734
  0x03F4, 0x03F7, 0x03FA, 0x03FD, 0x0400, 0x0403, 0x0406, 0x0409, 0x040C, 0x040F, 0x0412, 0x0415,
735
  0x0418, 0x041B, 0x041E, 0x0421, 0x0424, 0x0427, 0x042A, 0x042D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
736
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
737
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
738
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
739
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0430, 0xFFFF, 0x0433, 0xFFFF,
740
  0x0436, 0xFFFF, 0x0439, 0xFFFF, 0x043C, 0xFFFF, 0x043F, 0xFFFF, 0x0442, 0xFFFF, 0x0445, 0xFFFF,
741
  0x0448, 0xFFFF, 0x044B, 0xFFFF, 0x044E, 0xFFFF, 0x0451, 0xFFFF, 0x0454, 0xFFFF, 0x0457, 0xFFFF,
742
  0x045A, 0xFFFF, 0x045D, 0xFFFF, 0x0460, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
743
  0xFFFF, 0xFFFF, 0x0463, 0xFFFF, 0x0466, 0xFFFF, 0x0469, 0xFFFF, 0x046C, 0xFFFF, 0x046F, 0xFFFF,
744
  0x0472, 0xFFFF, 0x0475, 0xFFFF, 0x0478, 0xFFFF, 0x047B, 0xFFFF, 0x047E, 0xFFFF, 0x0481, 0xFFFF,
745
  0x0484, 0xFFFF, 0x0487, 0xFFFF, 0x048A, 0xFFFF, 0x048D, 0xFFFF, 0x0490, 0xFFFF, 0x0493, 0xFFFF,
746
  0x0496, 0xFFFF, 0x0499, 0xFFFF, 0x049C, 0xFFFF, 0x049F, 0xFFFF, 0x04A2, 0xFFFF, 0x04A5, 0xFFFF,
747
  0x04A8, 0xFFFF, 0x04AB, 0xFFFF, 0x04AE, 0xFFFF, 0x04B1, 0xFFFF, 0x04B4, 0x04B7, 0xFFFF, 0x04BA,
748
  0xFFFF, 0x04BD, 0xFFFF, 0x04C0, 0xFFFF, 0x04C3, 0xFFFF, 0x04C6, 0xFFFF, 0x04C9, 0xFFFF, 0xFFFF,
749
  0x04CC, 0xFFFF, 0x04CF, 0xFFFF, 0x04D2, 0xFFFF, 0x04D5, 0xFFFF, 0x04D8, 0xFFFF, 0x04DB, 0xFFFF,
750
  0x04DE, 0xFFFF, 0x04E1, 0xFFFF, 0x04E4, 0xFFFF, 0x04E7, 0xFFFF, 0x04EA, 0xFFFF, 0x04ED, 0xFFFF,
751
  0x04F0, 0xFFFF, 0x04F3, 0xFFFF, 0x04F6, 0xFFFF, 0x04F9, 0xFFFF, 0x04FC, 0xFFFF, 0x04FF, 0xFFFF,
752
  0x0502, 0xFFFF, 0x0505, 0xFFFF, 0x0508, 0xFFFF, 0x050B, 0xFFFF, 0x050E, 0xFFFF, 0x0511, 0xFFFF,
753
  0x0514, 0xFFFF, 0x0517, 0xFFFF, 0x051A, 0xFFFF, 0x051D, 0xFFFF, 0x0520, 0xFFFF, 0x0523, 0xFFFF,
754
  0x0526, 0xFFFF, 0x0529, 0xFFFF, 0x052C, 0xFFFF, 0x052F, 0xFFFF, 0x0532, 0xFFFF, 0x0535, 0xFFFF,
755
  0x0538, 0xFFFF, 0x053B, 0xFFFF, 0x053E, 0xFFFF, 0x0541, 0xFFFF, 0x0544, 0xFFFF, 0x0547, 0xFFFF,
756
  0x054A, 0xFFFF, 0x054D, 0xFFFF, 0x0550, 0xFFFF, 0x0553, 0xFFFF, 0x0556, 0xFFFF, 0x0559, 0xFFFF,
757
  0xFFFE, 0x055C, 0x055F, 0x0562, 0x0565, 0x0568, 0x056B, 0x056E, 0x0571, 0x0574, 0x0577, 0x057A,
758
  0x057D, 0x0580, 0x0583, 0x0586, 0x0589, 0x058C, 0x058F, 0x0592, 0x0595, 0x0598, 0x059B, 0x059E,
759
  0x05A1, 0x05A4, 0x05A7, 0x05AA, 0x05AD, 0x05B0, 0x05B3, 0x05B6, 0x05B9, 0x05BC, 0x05BF, 0x05C2,
760
  0x05C5, 0x05C8, 0x05CB, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
761
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
762
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
763
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
764
  0xFFFF, 0xFFFF, 0xFFFF, 0x05CE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF,
765
  0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
766
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
767
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
768
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
769
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
770
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
771
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
772
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
773
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x05D3, 0x05D8, 0x05DD, 0x05E2, 0xFFFF, 0xFFFF, 0xFFFF,
774
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
775
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
776
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x05E7, 0x05EE, 0x05F5, 0x05FC, 0x0603, 0x060A, 0x0611, 0x0618,
777
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
778
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
779
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
780
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
781
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
782
  0x061F, 0x0626, 0xFFFE, 0x062D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF,
783
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
784
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
785
  0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
786
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
787
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
788
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
789
  0xFFFF, 0xFFFE, 0xFFFF, 0x0634, 0xFFFE, 0xFFFF, 0x063B, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
790
  0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF,
791
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFE,
792
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0642, 0x0649, 0x0650, 0xFFFF, 0xFFFE, 0x0657, 0xFFFE,
793
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
794
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
795
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
796
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
797
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
798
  0x065E, 0x0665, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF,
799
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
800
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
801
  0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
802
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
803
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
804
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
805
  0xFFFF, 0xFFFF, 0xFFFF, 0x066C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
806
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF,
807
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
808
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
809
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
810
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0673, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
811
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
812
  0xFFFF, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE,
813
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
814
  0x067A, 0x0681, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
815
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
816
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
817
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
818
  0x0688, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
819
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
820
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
821
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
822
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x068C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
823
  0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0693, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x069A, 0xFFFF,
824
  0xFFFF, 0xFFFF, 0xFFFF, 0x06A1, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06A8, 0xFFFF, 0xFFFF, 0xFFFF,
825
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06AF, 0xFFFF, 0xFFFF,
826
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0x06B6, 0xFFFF, 0x06BD, 0x06C4, 0x06CB,
827
  0x06D5, 0x06DC, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06E6, 0xFFFF, 0xFFFF,
828
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
829
  0xFFFF, 0xFFFF, 0xFFFF, 0x06ED, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF,
830
  0xFFFF, 0x06F4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x06FB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0702,
831
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0709, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
832
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0710, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF,
833
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
834
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
835
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0717, 0x071B, 0x071F, 0x0723,
836
  0x0727, 0x072B, 0x072F, 0x0733, 0x0737, 0x073B, 0x073F, 0x0743, 0x0747, 0x074B, 0x074F, 0x0753,
837
  0x0757, 0x075B, 0x075F, 0x0763, 0x0767, 0x076B, 0x076F, 0x0773, 0x0777, 0x077B, 0x077F, 0x0783,
838
  0x0787, 0x078B, 0x078F, 0x0793, 0x0797, 0x079B, 0x079F, 0x07A3, 0x07A7, 0x07AB, 0xFFFE, 0x07AF,
839
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x07B3, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
840
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
841
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
842
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
843
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x07B7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
844
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
845
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
846
  0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
847
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
848
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
849
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
850
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
851
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
852
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
853
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0x07BB, 0x07BF, 0x07C3, 0x07C7,
854
  0x07CB, 0x07CF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
855
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
856
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
857
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
858
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF,
859
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
860
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
861
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
862
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
863
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
864
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
865
  0x03D6, 0x03DC, 0x03FA, 0x0403, 0x0406, 0x0406, 0x041E, 0x0433, 0x07D3, 0x07D7, 0xFFFF, 0xFFFE,
866
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x07DB, 0x07DF, 0x07E3, 0x07E7, 0x07EB, 0x07EF, 0x07F3, 0x07F7,
867
  0x07FB, 0x07FF, 0x0803, 0x0807, 0x07B7, 0x080B, 0x080F, 0x0813, 0x0817, 0x081B, 0x081F, 0x0823,
868
  0x0827, 0x082B, 0x082F, 0x0833, 0x0837, 0x083B, 0x083F, 0x0843, 0x0847, 0x084B, 0x084F, 0x0853,
869
  0x0857, 0x085B, 0x085F, 0x0863, 0x0867, 0x086B, 0x086F, 0x0873, 0x0877, 0x087B, 0x087F, 0xFFFE,
870
  0xFFFE, 0x0883, 0x0887, 0x088B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
871
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
872
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
873
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
874
  0x0001, 0x0074, 0x0003, 0xFFFF, 0x0007, 0x0009, 0x0197, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015,
875
  0x0017, 0x0019, 0x001B, 0xFFFF, 0x001D, 0x0273, 0x001F, 0x0023, 0x0027, 0x0029, 0x002D, 0x0001,
876
  0x088F, 0x0892, 0x0895, 0x0003, 0x0007, 0x0009, 0x019A, 0x019D, 0x0899, 0x000D, 0xFFFF, 0x0015,
877
  0x0019, 0x012E, 0x001D, 0x0188, 0x089C, 0x08A0, 0x001F, 0x0027, 0x0029, 0x08A4, 0x01B2, 0x002B,
878
  0x08A8, 0x0325, 0x0328, 0x032B, 0x0358, 0x035B, 0x0011, 0x0023, 0x0029, 0x002B, 0x0325, 0x0328,
879
  0x034C, 0x0358, 0x035B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
880
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x03F7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
881
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
882
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
883
  0xFFFF, 0xFFFF, 0xFFFF, 0x08AC, 0x0005, 0x08AF, 0x0092, 0x0899, 0x000B, 0x08B2, 0x08B5, 0x08B8,
884
  0x01AC, 0x01A9, 0x08BB, 0x08BE, 0x08C2, 0x08C5, 0x08C8, 0x08CC, 0x08CF, 0x08D2, 0x01B5, 0x08D5,
885
  0x08D8, 0x01B8, 0x08DB, 0x08DE, 0x01CA, 0x08E1, 0x02A2, 0x01D6, 0x08E4, 0x01D9, 0x02A5, 0x0033,
886
  0x08E8, 0x08EB, 0x01E2, 0x0337, 0x08EE, 0xFFFF, 0x08F2, 0xFFFF, 0x08F6, 0xFFFF, 0x08FA, 0xFFFF,
887
  0x08FE, 0xFFFF, 0x0902, 0xFFFF, 0x0906, 0xFFFF, 0x090A, 0xFFFF, 0x090E, 0xFFFF, 0x0912, 0xFFFF,
888
  0x0916, 0xFFFF, 0x091A, 0xFFFF, 0x091E, 0xFFFF, 0x0922, 0xFFFF, 0x0926, 0xFFFF, 0x092A, 0xFFFF,
889
  0x092E, 0xFFFF, 0x0932, 0xFFFF, 0x0936, 0xFFFF, 0x093A, 0xFFFF, 0x093E, 0xFFFF, 0x0942, 0xFFFF,
890
  0x0946, 0xFFFF, 0x094A, 0xFFFF, 0x094E, 0xFFFF, 0x0952, 0xFFFF, 0x0956, 0xFFFF, 0x095A, 0xFFFF,
891
  0x095E, 0xFFFF, 0x0962, 0xFFFF, 0x0966, 0xFFFF, 0x096A, 0xFFFF, 0x096E, 0xFFFF, 0x0972, 0xFFFF,
892
  0x0976, 0xFFFF, 0x097A, 0xFFFF, 0x097E, 0xFFFF, 0x0982, 0xFFFF, 0x0986, 0xFFFF, 0x098A, 0xFFFF,
893
  0x098E, 0xFFFF, 0x0992, 0xFFFF, 0x0996, 0xFFFF, 0x099A, 0xFFFF, 0x099E, 0xFFFF, 0x09A2, 0xFFFF,
894
  0x09A6, 0xFFFF, 0x09AA, 0xFFFF, 0x09AE, 0xFFFF, 0x09B2, 0xFFFF, 0x09B6, 0xFFFF, 0x09BA, 0xFFFF,
895
  0x09BE, 0xFFFF, 0x09C2, 0xFFFF, 0x09C6, 0xFFFF, 0x09CA, 0xFFFF, 0x09CE, 0xFFFF, 0x09D2, 0xFFFF,
896
  0x09D6, 0xFFFF, 0x09DA, 0xFFFF, 0x09DE, 0xFFFF, 0x09E2, 0xFFFF, 0x09E6, 0xFFFF, 0x09EA, 0xFFFF,
897
  0x09EE, 0xFFFF, 0x09F2, 0xFFFF, 0x09F6, 0xFFFF, 0x09FA, 0xFFFF, 0x09FE, 0xFFFF, 0x0A02, 0xFFFF,
898
  0x0A06, 0xFFFF, 0x0A0A, 0xFFFF, 0x0A0E, 0xFFFF, 0x0A12, 0xFFFF, 0x0A16, 0xFFFF, 0xFFFF, 0xFFFF,
899
  0xFFFF, 0xFFFF, 0x0A1A, 0x09AE, 0xFFFF, 0xFFFF, 0x0A1E, 0xFFFF, 0x0A21, 0xFFFF, 0x0A25, 0xFFFF,
900
  0x0A29, 0xFFFF, 0x0A2D, 0xFFFF, 0x0A31, 0xFFFF, 0x0A35, 0xFFFF, 0x0A39, 0xFFFF, 0x0A3D, 0xFFFF,
901
  0x0A41, 0xFFFF, 0x0A45, 0xFFFF, 0x0A49, 0xFFFF, 0x0A4D, 0xFFFF, 0x0A51, 0xFFFF, 0x0A55, 0xFFFF,
902
  0x0A59, 0xFFFF, 0x0A5D, 0xFFFF, 0x0A61, 0xFFFF, 0x0A65, 0xFFFF, 0x0A69, 0xFFFF, 0x0A6D, 0xFFFF,
903
  0x0A71, 0xFFFF, 0x0A75, 0xFFFF, 0x0A79, 0xFFFF, 0x0A7D, 0xFFFF, 0x0A81, 0xFFFF, 0x0A85, 0xFFFF,
904
  0x0A89, 0xFFFF, 0x0A8D, 0xFFFF, 0x0A91, 0xFFFF, 0x0A95, 0xFFFF, 0x0A99, 0xFFFF, 0x0A9D, 0xFFFF,
905
  0x0AA1, 0xFFFF, 0x0AA5, 0xFFFF, 0x0AA9, 0xFFFF, 0x0AAD, 0xFFFF, 0x0AB1, 0xFFFF, 0x0AB5, 0xFFFF,
906
  0x0AB9, 0xFFFF, 0x0ABD, 0xFFFF, 0x0AC1, 0xFFFF, 0x0AC5, 0xFFFF, 0x0AC9, 0xFFFF, 0x0ACD, 0xFFFF,
907
  0x0AD1, 0xFFFF, 0x0AD5, 0xFFFF, 0x0AD9, 0xFFFF, 0x0ADD, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
908
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0AE1, 0x0AE5, 0x0AE9, 0x0AED, 0x0AF1, 0x0AF5, 0x0AF9, 0x0AFD,
909
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0x0B01, 0x0B05, 0x0B09, 0x0B0D,
910
  0x0B11, 0x0B15, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
911
  0x0B19, 0x0B1D, 0x0B21, 0x0B25, 0x0B29, 0x0B2D, 0x0B31, 0x0B35, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
912
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0B39, 0x0B3D, 0x0B41, 0x0B45, 0x0B49, 0x0B4D, 0x0B51, 0x0B55,
913
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0x0B59, 0x0B5D, 0x0B61, 0x0B65,
914
  0x0B69, 0x0B6D, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
915
  0xFFFE, 0x0B71, 0xFFFE, 0x0B75, 0xFFFE, 0x0B79, 0xFFFE, 0x0B7D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
916
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0B81, 0x0B85, 0x0B89, 0x0B8D, 0x0B91, 0x0B95, 0x0B99, 0x0B9D,
917
  0xFFFF, 0x030A, 0xFFFF, 0x0310, 0xFFFF, 0x0313, 0xFFFF, 0x0316, 0xFFFF, 0x0319, 0xFFFF, 0x031C,
918
  0xFFFF, 0x031F, 0xFFFE, 0xFFFE, 0x0BA1, 0x0BA7, 0x0BAD, 0x0BB3, 0x0BB9, 0x0BBF, 0x0BC5, 0x0BCB,
919
  0x0BA1, 0x0BA7, 0x0BAD, 0x0BB3, 0x0BB9, 0x0BBF, 0x0BC5, 0x0BCB, 0x0BD1, 0x0BD7, 0x0BDD, 0x0BE3,
920
  0x0BE9, 0x0BEF, 0x0BF5, 0x0BFB, 0x0BD1, 0x0BD7, 0x0BDD, 0x0BE3, 0x0BE9, 0x0BEF, 0x0BF5, 0x0BFB,
921
  0x0C01, 0x0C07, 0x0C0D, 0x0C13, 0x0C19, 0x0C1F, 0x0C25, 0x0C2B, 0x0C01, 0x0C07, 0x0C0D, 0x0C13,
922
  0x0C19, 0x0C1F, 0x0C25, 0x0C2B, 0xFFFF, 0xFFFF, 0x0C31, 0x0C37, 0x0C3C, 0xFFFE, 0xFFFF, 0x0C41,
923
  0x0C47, 0x0C4B, 0x0C4F, 0x030A, 0x0C37, 0x0C53, 0x02EC, 0x0C53, 0x0C57, 0x0C5B, 0x0C61, 0x0C67,
924
  0x0C6C, 0xFFFE, 0xFFFF, 0x0C71, 0x0C77, 0x0310, 0x0C7B, 0x0313, 0x0C67, 0x0C7F, 0x0C85, 0x0C8B,
925
  0xFFFF, 0xFFFF, 0xFFFF, 0x0C91, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0x0C94, 0x0C98, 0x0C9C, 0x0316,
926
  0xFFFE, 0x0CA0, 0x0CA6, 0x0CAC, 0xFFFF, 0xFFFF, 0xFFFF, 0x0CB2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
927
  0x0CB5, 0x0CB9, 0x0CBD, 0x031C, 0x0CC1, 0x0CC5, 0x0304, 0x0CCB, 0xFFFE, 0xFFFE, 0x0CCD, 0x0CD3,
928
  0x0CD8, 0xFFFE, 0xFFFF, 0x0CDD, 0x0CE3, 0x0319, 0x0CE7, 0x031F, 0x0CD3, 0x0043, 0x0CEB, 0xFFFE,
929
  0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0035, 0x0000,
930
  0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0x0CEF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0CF3,
931
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
932
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0035,
933
  0xFFFF, 0xFFFF, 0xFFFF, 0x0CF7, 0x0CFE, 0xFFFF, 0x0D08, 0x0D0F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
934
  0x0D19, 0xFFFF, 0x0D1C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0D20,
935
  0x0D23, 0x0D26, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
936
  0xFFFF, 0xFFFF, 0xFFFF, 0x0D29, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0035,
937
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0000, 0x0000,
938
  0x0000, 0x0000, 0x0000, 0x0000, 0x0D36, 0x0011, 0xFFFE, 0xFFFE, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E,
939
  0x0D40, 0x0D42, 0x0D44, 0x0D46, 0x0D4A, 0x0D4C, 0x0D4E, 0x001B, 0x0D36, 0x004E, 0x003F, 0x0041,
940
  0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0x0D44, 0x0D46, 0x0D4A, 0x0D4C, 0x0D4E, 0xFFFE,
941
  0x0001, 0x0009, 0x001D, 0x002F, 0x019A, 0x000F, 0x0015, 0x0017, 0x0019, 0x001B, 0x001F, 0x0025,
942
  0x0027, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
943
  0x0D50, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
944
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
945
  0x0D53, 0x0D57, 0x0005, 0x0D5B, 0xFFFF, 0x0D5F, 0x0D63, 0x019D, 0xFFFF, 0x0D67, 0x000D, 0x000F,
946
  0x000F, 0x000F, 0x000F, 0x00F5, 0x0011, 0x0011, 0x0017, 0x0017, 0xFFFF, 0x001B, 0x0D6B, 0xFFFF,
947
  0xFFFF, 0x001F, 0x0021, 0x0023, 0x0023, 0x0023, 0xFFFF, 0xFFFF, 0x0D6E, 0x0D71, 0x0D75, 0xFFFF,
948
  0x0033, 0xFFFF, 0x0361, 0xFFFF, 0x0033, 0xFFFF, 0x0015, 0x0071, 0x0003, 0x0005, 0xFFFF, 0x0009,
949
  0x0009, 0x000B, 0x0D78, 0x0019, 0x001D, 0x0D7C, 0x0D7F, 0x0D82, 0x0D85, 0x0011, 0xFFFF, 0x0D88,
950
  0x0349, 0x0328, 0x0328, 0x0349, 0x0D8C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007, 0x0007, 0x0009,
951
  0x0011, 0x0013, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0D90, 0x0D96, 0x0D9C, 0x0DA3,
952
  0x0DA9, 0x0DAF, 0x0DB5, 0x0DBB, 0x0DC1, 0x0DC7, 0x0DCD, 0x0DD3, 0x0DD9, 0x0DDF, 0x0DE5, 0x0DEB,
953
  0x0011, 0x0DF0, 0x0DF3, 0x0DF7, 0x002B, 0x0DFA, 0x0DFD, 0x0E01, 0x0E06, 0x002F, 0x0E09, 0x0E0C,
954
  0x0017, 0x0005, 0x0007, 0x0019, 0x0011, 0x0DF0, 0x0DF3, 0x0DF7, 0x002B, 0x0DFA, 0x0DFD, 0x0E01,
955
  0x0E06, 0x002F, 0x0E09, 0x0E0C, 0x0017, 0x0005, 0x0007, 0x0019, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E10,
956
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E14, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
957
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
958
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
959
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
960
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
961
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
962
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
963
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
964
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E1A, 0x0E21, 0xFFFF, 0x0E2B,
965
  0x0E32, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
966
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
967
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
968
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
969
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0E3C, 0x0E40, 0xFFFF,
970
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
971
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
972
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
973
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
974
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40,
975
  0x0D42, 0x0E44, 0x0E47, 0x0E4A, 0x0E4D, 0x0E50, 0x0E53, 0x0E56, 0x0E59, 0x0E5C, 0x0E5F, 0x0E62,
976
  0x0E65, 0x0E69, 0x0E6D, 0x0E71, 0x0E75, 0x0E79, 0x0E7D, 0x0E81, 0x0E85, 0x0E89, 0x0E8E, 0x0E93,
977
  0x0E98, 0x0E9D, 0x0EA2, 0x0EA7, 0x0EAC, 0x0EB1, 0x0EB6, 0x0EBB, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
978
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
979
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0EC0, 0x0EC4, 0x0EC8, 0x0ECC, 0x0ED0, 0x0ED4, 0x0ED8, 0x0EDC,
980
  0x0EE0, 0x0EE4, 0x0EE8, 0x0EEC, 0x0EF0, 0x0EF4, 0x0EF8, 0x0EFC, 0x0F00, 0x0F04, 0x0F08, 0x0F0C,
981
  0x0F10, 0x0F14, 0x0F18, 0x0F1C, 0x0F20, 0x0F24, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B,
982
  0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023,
983
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007,
984
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
985
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0D36, 0xFFFF,
986
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
987
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
988
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F28, 0xFFFF, 0xFFFF, 0xFFFF,
989
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
990
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
991
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
992
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
993
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
994
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
995
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
996
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
997
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F35, 0x0F39, 0x0F3C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
998
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
999
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1000
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F40, 0xFFFF, 0xFFFF, 0xFFFF,
1001
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1002
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1003
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0F46, 0x0F4A, 0x0F4E, 0x0F52,
1004
  0x0F56, 0x0F5A, 0x0F5E, 0x0F62, 0x0F66, 0x0F6A, 0x0F6E, 0x0F72, 0x0F76, 0x0F7A, 0x0F7E, 0x0F82,
1005
  0x0F86, 0x0F8A, 0x0F8E, 0x0F92, 0x0F96, 0x0F9A, 0x0F9E, 0x0FA2, 0x0FA6, 0x0FAA, 0x0FAE, 0x0FB2,
1006
  0x0FB6, 0x0FBA, 0x0FBE, 0x0FC2, 0x0FC6, 0x0FCA, 0x0FCE, 0x0FD2, 0x0FD6, 0x0FDA, 0x0FDE, 0x0FE2,
1007
  0x0FE6, 0x0FEA, 0x0FEE, 0x0FF2, 0x0FF6, 0x0FFA, 0x0FFE, 0x1002, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1008
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1009
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1010
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1011
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1006, 0xFFFF, 0x100A, 0x100D,
1012
  0x1011, 0xFFFF, 0xFFFF, 0x1014, 0xFFFF, 0x1018, 0xFFFF, 0x101C, 0xFFFF, 0x0892, 0x08CF, 0x088F,
1013
  0x08AC, 0xFFFF, 0x1020, 0xFFFF, 0xFFFF, 0x1024, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1014
  0x0013, 0x002B, 0x1028, 0x102B, 0x102E, 0xFFFF, 0x1032, 0xFFFF, 0x1036, 0xFFFF, 0x103A, 0xFFFF,
1015
  0x103E, 0xFFFF, 0x1042, 0xFFFF, 0x1046, 0xFFFF, 0x104A, 0xFFFF, 0x104E, 0xFFFF, 0x1052, 0xFFFF,
1016
  0x1056, 0xFFFF, 0x105A, 0xFFFF, 0x105E, 0xFFFF, 0x1062, 0xFFFF, 0x1066, 0xFFFF, 0x106A, 0xFFFF,
1017
  0x106E, 0xFFFF, 0x1072, 0xFFFF, 0x1076, 0xFFFF, 0x107A, 0xFFFF, 0x107E, 0xFFFF, 0x1082, 0xFFFF,
1018
  0x1086, 0xFFFF, 0x108A, 0xFFFF, 0x108E, 0xFFFF, 0x1092, 0xFFFF, 0x1096, 0xFFFF, 0x109A, 0xFFFF,
1019
  0x109E, 0xFFFF, 0x10A2, 0xFFFF, 0x10A6, 0xFFFF, 0x10AA, 0xFFFF, 0x10AE, 0xFFFF, 0x10B2, 0xFFFF,
1020
  0x10B6, 0xFFFF, 0x10BA, 0xFFFF, 0x10BE, 0xFFFF, 0x10C2, 0xFFFF, 0x10C6, 0xFFFF, 0x10CA, 0xFFFF,
1021
  0x10CE, 0xFFFF, 0x10D2, 0xFFFF, 0x10D6, 0xFFFF, 0x10DA, 0xFFFF, 0x10DE, 0xFFFF, 0x10E2, 0xFFFF,
1022
  0x10E6, 0xFFFF, 0x10EA, 0xFFFF, 0x10EE, 0xFFFF, 0x10F2, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1023
  0xFFFF, 0xFFFF, 0xFFFF, 0x10F6, 0xFFFF, 0x10FA, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x10FE, 0xFFFF,
1024
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1025
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1026
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1027
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1028
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x1102,
1029
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1030
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1031
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1032
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1106,
1033
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1034
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1035
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1036
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1037
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1038
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1039
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x110A,
1040
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1041
  0x110E, 0x1112, 0x1116, 0x111A, 0x111E, 0x1122, 0x1126, 0x112A, 0x112E, 0x1132, 0x1136, 0x113A,
1042
  0x113E, 0x1142, 0x1146, 0x114A, 0x114E, 0x1152, 0x1156, 0x115A, 0x115E, 0x1162, 0x1166, 0x116A,
1043
  0x116E, 0x1172, 0x1176, 0x117A, 0x117E, 0x1182, 0x1186, 0x118A, 0x118E, 0x1192, 0x1196, 0x119A,
1044
  0x119E, 0x11A2, 0x11A6, 0x11AA, 0x11AE, 0x11B2, 0x11B6, 0x11BA, 0x11BE, 0x11C2, 0x11C6, 0x11CA,
1045
  0x11CE, 0x11D2, 0x11D6, 0x11DA, 0x11DE, 0x11E2, 0x11E6, 0x11EA, 0x11EE, 0x11F2, 0x11F6, 0x11FA,
1046
  0x11FE, 0x1202, 0x1206, 0x120A, 0x120E, 0x1212, 0x1216, 0x121A, 0x121E, 0x1222, 0x1226, 0x122A,
1047
  0x122E, 0x1232, 0x1236, 0x123A, 0x123E, 0x1242, 0x1246, 0x124A, 0x124E, 0x1252, 0x1256, 0x125A,
1048
  0x125E, 0x1262, 0x1266, 0x126A, 0x126E, 0x1272, 0x1276, 0x127A, 0x127E, 0x1282, 0x1286, 0x128A,
1049
  0x128E, 0x1292, 0x1296, 0x129A, 0x129E, 0x12A2, 0x12A6, 0x12AA, 0x12AE, 0x12B2, 0x12B6, 0x12BA,
1050
  0x12BE, 0x12C2, 0x12C6, 0x12CA, 0x12CE, 0x12D2, 0x12D6, 0x12DA, 0x12DE, 0x12E2, 0x12E6, 0x12EA,
1051
  0x12EE, 0x12F2, 0x12F6, 0x12FA, 0x12FE, 0x1302, 0x1306, 0x130A, 0x130E, 0x1312, 0x1316, 0x131A,
1052
  0x131E, 0x1322, 0x1326, 0x132A, 0x132E, 0x1332, 0x1336, 0x133A, 0x133E, 0x1342, 0x1346, 0x134A,
1053
  0x134E, 0x1352, 0x1356, 0x135A, 0x135E, 0x1362, 0x1366, 0x136A, 0x136E, 0x1372, 0x1376, 0x137A,
1054
  0x137E, 0x1382, 0x1386, 0x138A, 0x138E, 0x1392, 0x1396, 0x139A, 0x139E, 0x13A2, 0x13A6, 0x13AA,
1055
  0x13AE, 0x13B2, 0x13B6, 0x13BA, 0x13BE, 0x13C2, 0x13C6, 0x13CA, 0x13CE, 0x13D2, 0x13D6, 0x13DA,
1056
  0x13DE, 0x13E2, 0x13E6, 0x13EA, 0x13EE, 0x13F2, 0x13F6, 0x13FA, 0x13FE, 0x1402, 0x1406, 0x140A,
1057
  0x140E, 0x1412, 0x1416, 0x141A, 0x141E, 0x1422, 0x1426, 0x142A, 0x142E, 0x1432, 0x1436, 0x143A,
1058
  0x143E, 0x1442, 0x1446, 0x144A, 0x144E, 0x1452, 0x1456, 0x145A, 0x145E, 0x1462, 0xFFFE, 0xFFFE,
1059
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1060
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1061
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1062
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0035, 0xFFFF, 0x1466, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1063
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1064
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1065
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1066
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1468, 0xFFFF,
1067
  0x116A, 0x146C, 0x1470, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1068
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1069
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0x1474,
1070
  0x1479, 0xFFFF, 0xFFFF, 0x147E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1071
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1072
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1073
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1074
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1075
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1076
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1077
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1078
  0xFFFF, 0xFFFF, 0xFFFF, 0x1485, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF,
1079
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1080
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1081
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1082
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0x148C, 0x1490, 0x1494, 0x1498, 0x149C, 0x14A0, 0x14A4,
1083
  0x14A8, 0x14AC, 0x14B0, 0x14B4, 0x14B8, 0x14BC, 0x14C0, 0x14C4, 0x14C8, 0x14CC, 0x14D0, 0x14D4,
1084
  0x14D8, 0x14DC, 0x14E0, 0x14E4, 0x14E8, 0x14EC, 0x14F0, 0x14F4, 0x14F8, 0x14FC, 0x1500, 0x1504,
1085
  0x1508, 0x150C, 0x1510, 0x1514, 0x1518, 0x151C, 0x1520, 0x1524, 0x1528, 0x152C, 0x1530, 0x1534,
1086
  0x1538, 0x153C, 0x1540, 0x1544, 0x1548, 0x154C, 0x1550, 0x1554, 0x0000, 0x1558, 0x155C, 0x1560,
1087
  0x1564, 0x1568, 0x156C, 0x1570, 0x1574, 0x1578, 0x157C, 0x1580, 0x1584, 0x1588, 0x158C, 0x1590,
1088
  0x1594, 0x1598, 0x159C, 0x15A0, 0x15A4, 0x15A8, 0x15AC, 0x15B0, 0x15B4, 0x15B8, 0x15BC, 0x15C0,
1089
  0x15C4, 0x15C8, 0x15CC, 0x15D0, 0x15D4, 0x15D8, 0x15DC, 0x15E0, 0x15E4, 0x15E8, 0x15EC, 0x15F0,
1090
  0x15F4, 0x15F8, 0x15FC, 0xFFFE, 0xFFFF, 0xFFFF, 0x110E, 0x1126, 0x1600, 0x1604, 0x1608, 0x160C,
1091
  0x1610, 0x1614, 0x111E, 0x1618, 0x161C, 0x1620, 0x1624, 0x112E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1092
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1093
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1094
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x1628, 0x162E, 0x1634, 0x163A, 0x1640, 0x1646, 0x164C, 0x1652,
1095
  0x1658, 0x165E, 0x1664, 0x166A, 0x1670, 0x1676, 0x167C, 0x1682, 0x1688, 0x168E, 0x1694, 0x169A,
1096
  0x16A0, 0x16A6, 0x16AC, 0x16B2, 0x16B8, 0x16BE, 0x16C4, 0x16CA, 0x16D0, 0x16D6, 0x16DF, 0xFFFE,
1097
  0x16E8, 0x16EE, 0x16F4, 0x16FA, 0x1700, 0x1706, 0x170C, 0x1712, 0x1718, 0x171E, 0x1724, 0x172A,
1098
  0x1730, 0x1736, 0x173C, 0x1742, 0x1748, 0x174E, 0x1754, 0x175A, 0x1760, 0x1766, 0x176C, 0x1772,
1099
  0x1778, 0x177E, 0x1784, 0x178A, 0x1790, 0x1796, 0x179C, 0x17A2, 0x17A8, 0x17AE, 0x17B4, 0x17BA,
1100
  0x17C0, 0x17C4, 0x1216, 0x17C8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1101
  0x17CC, 0x17D0, 0x17D3, 0x17D6, 0x17D9, 0x17DC, 0x17DF, 0x17E2, 0x17E5, 0x17E8, 0x17EB, 0x17EE,
1102
  0x17F1, 0x17F4, 0x17F7, 0x17FA, 0x148C, 0x1498, 0x14A4, 0x14AC, 0x14CC, 0x14D0, 0x14DC, 0x14E4,
1103
  0x14E8, 0x14F0, 0x14F4, 0x14F8, 0x14FC, 0x1500, 0x17FD, 0x1801, 0x1805, 0x1809, 0x180D, 0x1811,
1104
  0x1815, 0x1819, 0x181D, 0x1821, 0x1825, 0x1829, 0x182D, 0x1831, 0x1835, 0x183C, 0x1843, 0xFFFF,
1105
  0x110E, 0x1126, 0x1600, 0x1604, 0x1847, 0x184B, 0x184F, 0x113A, 0x1853, 0x116A, 0x1232, 0x1262,
1106
  0x125E, 0x1236, 0x13A6, 0x118A, 0x122A, 0x1857, 0x185B, 0x185F, 0x1863, 0x1867, 0x186B, 0x186F,
1107
  0x1873, 0x1877, 0x187B, 0x11A2, 0x187F, 0x1883, 0x1887, 0x188B, 0x188F, 0x1893, 0x1897, 0x189B,
1108
  0x1608, 0x160C, 0x1610, 0x189F, 0x18A3, 0x18A7, 0x18AB, 0x18AF, 0x18B3, 0x18B7, 0x18BB, 0x18BF,
1109
  0x18C3, 0x18C7, 0x18CA, 0x18CD, 0x18D0, 0x18D3, 0x18D6, 0x18D9, 0x18DC, 0x18DF, 0x18E2, 0x18E5,
1110
  0x18E8, 0x18EB, 0x18EE, 0x18F1, 0x18F4, 0x18F9, 0x18FE, 0x1903, 0x1908, 0x190D, 0x1912, 0x1917,
1111
  0x191C, 0x1921, 0x1927, 0x192D, 0x1933, 0x1936, 0x193A, 0x193D, 0x1941, 0x1945, 0x1949, 0x194D,
1112
  0x1951, 0x1955, 0x1959, 0x195D, 0x1961, 0x1965, 0x1969, 0x196D, 0x1971, 0x1975, 0x1979, 0x197D,
1113
  0x1981, 0x1985, 0x1989, 0x198D, 0x1991, 0x1995, 0x1999, 0x199D, 0x19A1, 0x19A5, 0x19A9, 0x19AD,
1114
  0x19B1, 0x19B5, 0x19B9, 0x19BD, 0x19C1, 0x19C5, 0x19C9, 0x19CD, 0x19D1, 0x19D5, 0x19D9, 0x19DD,
1115
  0x19E1, 0x19E5, 0x19E9, 0x19ED, 0x19F1, 0x19F5, 0x19F9, 0x19FD, 0x1A04, 0x1A11, 0x1A1E, 0x1A2B,
1116
  0x1A35, 0x1A42, 0x1A4C, 0x1A56, 0x1A66, 0x1A73, 0x1A7D, 0x1A87, 0x1A91, 0x1A9E, 0x1AAB, 0x1AB5,
1117
  0x1ABF, 0x1AC6, 0x1AD0, 0x1ADD, 0x1AEA, 0x1AF1, 0x1B01, 0x1B14, 0x1B24, 0x1B2E, 0x1B3E, 0x1B4E,
1118
  0x1B5B, 0x1B65, 0x1B6F, 0x1B79, 0x1B86, 0x1B96, 0x1BA3, 0x1BAD, 0x1BB7, 0x1BC1, 0x1BC8, 0x1BCF,
1119
  0x1BD6, 0x1BDD, 0x1BE7, 0x1BF1, 0x1C01, 0x1C0B, 0x1C18, 0x1C28, 0x1C32, 0x1C39, 0x1C40, 0x1C50,
1120
  0x1C5D, 0x1C6D, 0x1C77, 0x1C87, 0x1C8E, 0x1C98, 0x1CA2, 0x1CAC, 0x1CB6, 0x1CC0, 0x1CCD, 0x1CD7,
1121
  0x1CDE, 0x1CE8, 0x1CF2, 0x1CFC, 0x1D09, 0x1D13, 0x1D1D, 0x1D27, 0x1D37, 0x1D44, 0x1D4B, 0x1D5B,
1122
  0x1D62, 0x1D6F, 0x1D7C, 0x1D86, 0x1D90, 0x1D9A, 0x1DA7, 0x1DAE, 0x1DB8, 0x1DC5, 0x1DCC, 0x1DDC,
1123
  0x1DE6, 0x1DEB, 0x1DF0, 0x1DF5, 0x1DFA, 0x1DFF, 0x1E04, 0x1E09, 0x1E0E, 0x1E13, 0x1E18, 0x1E1E,
1124
  0x1E24, 0x1E2A, 0x1E30, 0x1E36, 0x1E3C, 0x1E42, 0x1E48, 0x1E4E, 0x1E54, 0x1E5A, 0x1E60, 0x1E66,
1125
  0x1E6C, 0x1E72, 0x1E76, 0x1E79, 0x1E7C, 0x1E80, 0x1E83, 0x1E86, 0x1E89, 0x1E8D, 0x1E91, 0x1E94,
1126
  0x1E9B, 0x1EA2, 0x1EA9, 0x1EB0, 0x1EBD, 0x1EC0, 0x1EC3, 0x1EC7, 0x1ECA, 0x1ECD, 0x1ED0, 0x1ED3,
1127
  0x1ED6, 0x1EDA, 0x1EDF, 0x1EE2, 0x1EE5, 0x1EE9, 0x1EED, 0x1EF0, 0x1EF3, 0x1EF6, 0x1EFA, 0x1EFE,
1128
  0x1F02, 0x1F06, 0x1F0A, 0x1F0D, 0x1F10, 0x1F13, 0x1F16, 0x1F19, 0x1F1D, 0x1F20, 0x1F23, 0x1F26,
1129
  0x1F2A, 0x1F2E, 0x1F31, 0x1F35, 0x1F39, 0x1F3D, 0x1F40, 0x1F44, 0x1F4A, 0x1EBD, 0x1F51, 0x1F55,
1130
  0x1F59, 0x1F5D, 0x1F61, 0x1F69, 0x1F72, 0x1F75, 0x1F78, 0x1F7C, 0x1F7F, 0x1F82, 0x1F85, 0x1F89,
1131
  0x1F8C, 0x1F89, 0x1F8F, 0x1F92, 0x1F95, 0x1F99, 0x1F9C, 0x1F99, 0x1F9F, 0x1FA3, 0xFFFE, 0x1FA7,
1132
  0x1FAA, 0x1FAD, 0x1FB0, 0xFFFE, 0x1FB7, 0x1FBA, 0x1FBD, 0x1FC0, 0x1FC3, 0x1FC6, 0x1F23, 0x1FC9,
1133
  0x1FCC, 0x1FCF, 0x1FD2, 0x1FD6, 0x1ED0, 0x1FD9, 0x1FDD, 0x1FE1, 0xFFFE, 0x1FE4, 0x1FE8, 0x1FEB,
1134
  0x1FEE, 0x1FF1, 0x1FF4, 0x1FFA, 0x2000, 0x2005, 0x200A, 0x200F, 0x2014, 0x2019, 0x201E, 0x2023,
1135
  0x2028, 0x202D, 0x2033, 0x2039, 0x203F, 0x2045, 0x204B, 0x2051, 0x2057, 0x205D, 0x2063, 0x2069,
1136
  0x206F, 0x2075, 0x207B, 0x2081, 0x2087, 0x208D, 0x2093, 0x2099, 0x209F, 0x20A5, 0x20AB, 0x20B1,
1137
  0x20B5, 0xFFFF, 0x20B9, 0xFFFF, 0x20BD, 0xFFFF, 0x20C1, 0xFFFF, 0x20C5, 0xFFFF, 0x07D3, 0xFFFF,
1138
  0x20C9, 0xFFFF, 0x20CD, 0xFFFF, 0x20D1, 0xFFFF, 0x20D5, 0xFFFF, 0x20D9, 0xFFFF, 0x20DD, 0xFFFF,
1139
  0x20E1, 0xFFFF, 0x20E5, 0xFFFF, 0x20E9, 0xFFFF, 0x20ED, 0xFFFF, 0x20F1, 0xFFFF, 0x20F5, 0xFFFF,
1140
  0x20F9, 0xFFFF, 0x20FD, 0xFFFF, 0x2101, 0xFFFF, 0x2105, 0xFFFF, 0x2109, 0xFFFF, 0xFFFF, 0xFFFF,
1141
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1142
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x210D, 0xFFFF, 0x2111, 0xFFFF, 0x2115, 0xFFFF, 0x2119, 0xFFFF,
1143
  0x211D, 0xFFFF, 0x2121, 0xFFFF, 0x2125, 0xFFFF, 0x2129, 0xFFFF, 0x212D, 0xFFFF, 0x2131, 0xFFFF,
1144
  0x2135, 0xFFFF, 0x2139, 0xFFFF, 0x213D, 0xFFFF, 0x2141, 0xFFFF, 0x041E, 0x0424, 0xFFFF, 0xFFFF,
1145
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1146
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1147
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1148
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1149
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1150
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2145, 0xFFFF, 0x2149, 0xFFFF, 0x214D, 0xFFFF,
1151
  0x2151, 0xFFFF, 0x2155, 0xFFFF, 0x2159, 0xFFFF, 0x215D, 0xFFFF, 0xFFFF, 0xFFFF, 0x2161, 0xFFFF,
1152
  0x2165, 0xFFFF, 0x2169, 0xFFFF, 0x216D, 0xFFFF, 0x2171, 0xFFFF, 0x2175, 0xFFFF, 0x2179, 0xFFFF,
1153
  0x217D, 0xFFFF, 0x2181, 0xFFFF, 0x2185, 0xFFFF, 0x2189, 0xFFFF, 0x218D, 0xFFFF, 0x2191, 0xFFFF,
1154
  0x2195, 0xFFFF, 0x2199, 0xFFFF, 0x219D, 0xFFFF, 0x21A1, 0xFFFF, 0x21A5, 0xFFFF, 0x21A9, 0xFFFF,
1155
  0x21AD, 0xFFFF, 0x21B1, 0xFFFF, 0x21B5, 0xFFFF, 0x21B9, 0xFFFF, 0x21BD, 0xFFFF, 0x21C1, 0xFFFF,
1156
  0x21C5, 0xFFFF, 0x21C9, 0xFFFF, 0x21CD, 0xFFFF, 0x21D1, 0xFFFF, 0x21D5, 0xFFFF, 0x21D9, 0xFFFF,
1157
  0x21D9, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x21DD, 0xFFFF, 0x21E1,
1158
  0xFFFF, 0x21E5, 0x21E9, 0xFFFF, 0x21ED, 0xFFFF, 0x21F1, 0xFFFF, 0x21F5, 0xFFFF, 0x21F9, 0xFFFF,
1159
  0xFFFF, 0xFFFF, 0xFFFF, 0x21FD, 0xFFFF, 0x08B8, 0xFFFF, 0xFFFF, 0x2201, 0xFFFF, 0x2205, 0xFFFF,
1160
  0xFFFF, 0xFFFF, 0x2209, 0xFFFF, 0x220D, 0xFFFF, 0x2211, 0xFFFF, 0x2215, 0xFFFF, 0x2219, 0xFFFF,
1161
  0x221D, 0xFFFF, 0x2221, 0xFFFF, 0x2225, 0xFFFF, 0x2229, 0xFFFF, 0x222D, 0xFFFF, 0x02B7, 0x0899,
1162
  0x08B5, 0x2231, 0x08BB, 0xFFFF, 0x2234, 0x2237, 0x08C2, 0x223A, 0x223E, 0xFFFF, 0x2242, 0xFFFF,
1163
  0x2246, 0xFFFF, 0x224A, 0xFFFF, 0x224E, 0xFFFF, 0x2252, 0xFFFF, 0x2256, 0xFFFF, 0x225A, 0xFFFF,
1164
  0x225E, 0x08DE, 0x2262, 0x2266, 0xFFFF, 0x226A, 0xFFFF, 0x226E, 0x2271, 0xFFFF, 0x2275, 0xFFFF,
1165
  0x2279, 0xFFFF, 0x227D, 0xFFFF, 0x2281, 0xFFFF, 0x2285, 0xFFFF, 0x2289, 0xFFFF, 0x228D, 0xFFFF,
1166
  0x2291, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1167
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0025, 0x0005, 0x000B,
1168
  0x0021, 0x2294, 0xFFFF, 0xFFFF, 0x00F5, 0x013A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1169
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1170
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1171
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x214D, 0x2298, 0x100A, 0x229C, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1172
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x22A0, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1173
  0x22A3, 0x22A7, 0x22AB, 0x22AF, 0x22B3, 0x22B7, 0x22BB, 0x22BF, 0x22C3, 0x22C7, 0x22CB, 0x22CF,
1174
  0x22D3, 0x22D7, 0x22DB, 0x22DF, 0x22E3, 0x22E7, 0x22EB, 0x22EF, 0x22F3, 0x22F7, 0x22FB, 0x22FF,
1175
  0x2303, 0x2307, 0x230B, 0x230F, 0x2313, 0x2317, 0x231B, 0x231F, 0x2323, 0x2327, 0x232B, 0x232F,
1176
  0x2333, 0x2337, 0x233B, 0x233F, 0x2343, 0x2347, 0x234B, 0x234F, 0x2353, 0x2357, 0x235B, 0x235F,
1177
  0x2363, 0x2367, 0x236B, 0x236F, 0x2373, 0x2377, 0x237B, 0x237F, 0x2383, 0x2387, 0x238B, 0x238F,
1178
  0x2393, 0x2397, 0x239B, 0x239F, 0x23A3, 0x23A7, 0x23AB, 0x23AF, 0x23B3, 0x23B7, 0x23BB, 0x23BF,
1179
  0x23C3, 0x23C7, 0x23CB, 0x23CF, 0x23D3, 0x23D7, 0x23DB, 0x23DF, 0x23E3, 0x23E7, 0x1386, 0x23EB,
1180
  0x23EF, 0x23F3, 0x23F7, 0x145E, 0x145E, 0x23FB, 0x13A6, 0x23FF, 0x2403, 0x2407, 0x240B, 0x240F,
1181
  0x2413, 0x2417, 0x241B, 0x241F, 0x2423, 0x2427, 0x242B, 0x242F, 0x2433, 0x2437, 0x243B, 0x243F,
1182
  0x2443, 0x2447, 0x244B, 0x244F, 0x2453, 0x2457, 0x245B, 0x245F, 0x2463, 0x2467, 0x246B, 0x246F,
1183
  0x2473, 0x2477, 0x247B, 0x247F, 0x2483, 0x2487, 0x248B, 0x248F, 0x2493, 0x2497, 0x249B, 0x249F,
1184
  0x12FE, 0x24A3, 0x24A7, 0x24AB, 0x24AF, 0x24B3, 0x24B7, 0x24BB, 0x24BF, 0x24C3, 0x24C7, 0x24CB,
1185
  0x1422, 0x24CF, 0x24D3, 0x24D7, 0x24DB, 0x24DF, 0x24E3, 0x24E7, 0x24EB, 0x24EF, 0x24F3, 0x24F7,
1186
  0x24FB, 0x24FF, 0x2503, 0x2507, 0x250B, 0x250F, 0x2513, 0x2517, 0x251B, 0x251F, 0x2523, 0x2527,
1187
  0x252B, 0x252F, 0x2533, 0x2537, 0x2423, 0x253B, 0x253F, 0x2543, 0x2547, 0x254B, 0x254F, 0x2553,
1188
  0x2557, 0x255B, 0x255F, 0x2563, 0x2567, 0x256B, 0x256F, 0x2573, 0x2577, 0x257B, 0x257F, 0x2583,
1189
  0x2587, 0x138E, 0x258B, 0x258F, 0x2593, 0x2597, 0x259B, 0x259F, 0x25A3, 0x25A7, 0x25AB, 0x25AF,
1190
  0x25B3, 0x25B7, 0x25BB, 0x25BF, 0x25C3, 0x11A2, 0x25C7, 0x25CB, 0x25CF, 0x25D3, 0x25D7, 0x25DB,
1191
  0x25DF, 0x25E3, 0x1156, 0x25E7, 0x25EB, 0x25EF, 0x25F3, 0x25F7, 0x25FB, 0x25FF, 0x2603, 0x2607,
1192
  0x260B, 0x260F, 0x2613, 0x2617, 0x261B, 0x261F, 0x2623, 0x2627, 0x262B, 0x262F, 0x2633, 0x2637,
1193
  0x263B, 0x2583, 0x263F, 0x2643, 0x2647, 0x264B, 0x264F, 0x2653, 0x2657, 0x265B, 0x2543, 0x265F,
1194
  0x2663, 0x2667, 0x266B, 0x266F, 0x2673, 0x2677, 0x267B, 0x267F, 0x2683, 0x2687, 0x268B, 0x268F,
1195
  0x2693, 0x2697, 0x269B, 0x269F, 0x26A3, 0x26A7, 0x26AB, 0x2423, 0x26AF, 0x26B3, 0x26B7, 0x26BB,
1196
  0x145A, 0x26BF, 0x26C3, 0x26C7, 0x26CB, 0x26CF, 0x26D3, 0x26D7, 0x26DB, 0x26DF, 0x26E3, 0x26E7,
1197
  0x26EB, 0x184B, 0x26EF, 0x26F3, 0x26F7, 0x26FB, 0x26FF, 0x2703, 0x2707, 0x270B, 0x270F, 0x254B,
1198
  0x2713, 0x2717, 0x271B, 0x271F, 0x2723, 0x2727, 0x272B, 0x272F, 0x2733, 0x2737, 0x273B, 0x273F,
1199
  0x2743, 0x13A2, 0x2747, 0x274B, 0x274F, 0x2753, 0x2757, 0x275B, 0x275F, 0x2763, 0x2767, 0x276B,
1200
  0x276F, 0x2773, 0x2777, 0x12DE, 0x277B, 0x277F, 0x2783, 0x2787, 0x278B, 0x278F, 0x2793, 0x2797,
1201
  0x279B, 0x279F, 0x27A3, 0x27A7, 0x27AB, 0x27AF, 0x27B3, 0x27B7, 0x134A, 0x27BB, 0x1356, 0x27BF,
1202
  0x27C3, 0x27C7, 0xFFFF, 0xFFFF, 0x27CB, 0xFFFF, 0x27CF, 0xFFFF, 0xFFFF, 0x27D3, 0x27D7, 0x27DB,
1203
  0x27DF, 0x27E3, 0x27E7, 0x27EB, 0x27EF, 0x27F3, 0x12FA, 0xFFFF, 0x27F7, 0xFFFF, 0x27FB, 0xFFFF,
1204
  0xFFFF, 0x27FF, 0x2803, 0xFFFF, 0xFFFF, 0xFFFF, 0x2807, 0x280B, 0x280F, 0x2813, 0x2817, 0x281B,
1205
  0x281F, 0x2823, 0x2827, 0x282B, 0x282F, 0x2833, 0x2837, 0x283B, 0x283F, 0x2843, 0x2847, 0x284B,
1206
  0x11BE, 0x284F, 0x2853, 0x2857, 0x285B, 0x285F, 0x2863, 0x2867, 0x286B, 0x286F, 0x2873, 0x2877,
1207
  0x287B, 0x287F, 0x2883, 0x2887, 0x185F, 0x288B, 0x288F, 0x2893, 0x2897, 0x186F, 0x289B, 0x289F,
1208
  0x28A3, 0x28A7, 0x28AB, 0x2613, 0x28AF, 0x28B3, 0x28B7, 0x28BB, 0x28BF, 0x28C3, 0x28C3, 0x28C7,
1209
  0x28CB, 0x28CF, 0x28D3, 0x28D7, 0x28DB, 0x28DF, 0x28E3, 0x27FF, 0x28E7, 0x28EB, 0x28EF, 0x28F3,
1210
  0x28F7, 0x28FC, 0xFFFE, 0xFFFE, 0x2900, 0x2904, 0x2908, 0x290C, 0x2910, 0x2914, 0x2918, 0x291C,
1211
  0x2837, 0x2920, 0x2924, 0x2928, 0x27CB, 0x292C, 0x2930, 0x2934, 0x2938, 0x293C, 0x2940, 0x2944,
1212
  0x2948, 0x294C, 0x2950, 0x2954, 0x2958, 0x2857, 0x295C, 0x285B, 0x2960, 0x2964, 0x2968, 0x296C,
1213
  0x2970, 0x27CF, 0x2477, 0x2974, 0x2978, 0x1242, 0x2587, 0x26D3, 0x297C, 0x2980, 0x2877, 0x2984,
1214
  0x287B, 0x2988, 0x298C, 0x2990, 0x27D7, 0x2994, 0x2998, 0x299C, 0x29A0, 0x29A4, 0x27DB, 0x29A8,
1215
  0x29AC, 0x29B0, 0x29B4, 0x29B8, 0x29BC, 0x28AB, 0x29C0, 0x29C4, 0x2613, 0x29C8, 0x28BB, 0x29CC,
1216
  0x29D0, 0x29D4, 0x29D8, 0x29DC, 0x28CF, 0x29E0, 0x27FB, 0x29E4, 0x28D3, 0x253B, 0x29E8, 0x28D7,
1217
  0x29EC, 0x28DF, 0x29F0, 0x29F4, 0x29F8, 0x29FC, 0x2A00, 0x28E7, 0x27EF, 0x2A04, 0x28EB, 0x2A08,
1218
  0x28EF, 0x2A0C, 0x145E, 0x2A10, 0x2A15, 0x2A1A, 0x2A1F, 0x2A23, 0x2A27, 0x2A2B, 0x2A30, 0x2A35,
1219
  0x2A3A, 0x2A3E, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1220
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1221
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1222
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x2A42, 0x2A45, 0x2A48, 0x2A4B, 0x2A4F, 0x2A53, 0x2A53, 0xFFFE,
1223
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x2A56,
1224
  0x2A5B, 0x2A60, 0x2A65, 0x2A6A, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x2A6F, 0xFFFF, 0x2A74,
1225
  0x2A79, 0x0D7C, 0x0D85, 0x2A7C, 0x2A7F, 0x2A82, 0x2A85, 0x2A88, 0x2A8B, 0x0D44, 0x2A8E, 0x2A93,
1226
  0x2A98, 0x2A9F, 0x2AA6, 0x2AAB, 0x2AB0, 0x2AB5, 0x2ABA, 0x2ABF, 0x2AC4, 0x2AC9, 0x2ACE, 0xFFFE,
1227
  0x2AD3, 0x2AD8, 0x2ADD, 0x2AE2, 0x2AE7, 0xFFFE, 0x2AEC, 0xFFFE, 0x2AF1, 0x2AF6, 0xFFFE, 0x2AFB,
1228
  0x2B00, 0xFFFE, 0x2B05, 0x2B0A, 0x2B0F, 0x2B14, 0x2B19, 0x2B1E, 0x2B23, 0x2B28, 0x2B2D, 0x2B32,
1229
  0x2B37, 0x2B37, 0x2B3A, 0x2B3A, 0x2B3A, 0x2B3A, 0x2B3D, 0x2B3D, 0x2B3D, 0x2B3D, 0x2B40, 0x2B40,
1230
  0x2B40, 0x2B40, 0x2B43, 0x2B43, 0x2B43, 0x2B43, 0x2B46, 0x2B46, 0x2B46, 0x2B46, 0x2B49, 0x2B49,
1231
  0x2B49, 0x2B49, 0x2B4C, 0x2B4C, 0x2B4C, 0x2B4C, 0x2B4F, 0x2B4F, 0x2B4F, 0x2B4F, 0x2B52, 0x2B52,
1232
  0x2B52, 0x2B52, 0x2B55, 0x2B55, 0x2B55, 0x2B55, 0x2B58, 0x2B58, 0x2B58, 0x2B58, 0x2B5B, 0x2B5B,
1233
  0x2B5B, 0x2B5B, 0x2B5E, 0x2B5E, 0x2B61, 0x2B61, 0x2B64, 0x2B64, 0x2B67, 0x2B67, 0x2B6A, 0x2B6A,
1234
  0x2B6D, 0x2B6D, 0x2B70, 0x2B70, 0x2B70, 0x2B70, 0x2B73, 0x2B73, 0x2B73, 0x2B73, 0x2B76, 0x2B76,
1235
  0x2B76, 0x2B76, 0x2B79, 0x2B79, 0x2B79, 0x2B79, 0x2B7C, 0x2B7C, 0x2B7F, 0x2B7F, 0x2B7F, 0x2B7F,
1236
  0x2B82, 0x2B82, 0x2B85, 0x2B85, 0x2B85, 0x2B85, 0x2B88, 0x2B88, 0x2B88, 0x2B88, 0x2B8B, 0x2B8B,
1237
  0x2B8E, 0x2B8E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1238
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1239
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2B91,
1240
  0x2B91, 0x2B91, 0x2B91, 0x2B94, 0x2B94, 0x2B97, 0x2B97, 0x2B9A, 0x2B9A, 0x05DD, 0x2B9D, 0x2B9D,
1241
  0x2BA0, 0x2BA0, 0x2BA3, 0x2BA3, 0x2BA6, 0x2BA6, 0x2BA6, 0x2BA6, 0x2BA9, 0x2BA9, 0x2BAC, 0x2BAC,
1242
  0x2BB1, 0x2BB1, 0x2BB6, 0x2BB6, 0x2BBB, 0x2BBB, 0x2BC0, 0x2BC0, 0x2BC5, 0x2BC5, 0x2BCA, 0x2BCA,
1243
  0x2BCA, 0x2BCF, 0x2BCF, 0x2BCF, 0x2BD4, 0x2BD4, 0x2BD4, 0x2BD4, 0x2BD7, 0x2BDC, 0x2BE1, 0x2BCF,
1244
  0x2BE6, 0x2BEB, 0x2BF0, 0x2BF5, 0x2BFA, 0x2BFF, 0x2C04, 0x2C09, 0x2C0E, 0x2C13, 0x2C18, 0x2C1D,
1245
  0x2C22, 0x2C27, 0x2C2C, 0x2C31, 0x2C36, 0x2C3B, 0x2C40, 0x2C45, 0x2C4A, 0x2C4F, 0x2C54, 0x2C59,
1246
  0x2C5E, 0x2C63, 0x2C68, 0x2C6D, 0x2C72, 0x2C77, 0x2C7C, 0x2C81, 0x2C86, 0x2C8B, 0x2C90, 0x2C95,
1247
  0x2C9A, 0x2C9F, 0x2CA4, 0x2CA9, 0x2CAE, 0x2CB3, 0x2CB8, 0x2CBD, 0x2CC2, 0x2CC7, 0x2CCC, 0x2CD1,
1248
  0x2CD6, 0x2CDB, 0x2CE0, 0x2CE5, 0x2CEA, 0x2CEF, 0x2CF4, 0x2CF9, 0x2CFE, 0x2D03, 0x2D08, 0x2D0D,
1249
  0x2D12, 0x2D17, 0x2D1C, 0x2D21, 0x2D26, 0x2D2B, 0x2D30, 0x2D35, 0x2D3A, 0x2D3F, 0x2D44, 0x2D49,
1250
  0x2D4E, 0x2D53, 0x2D58, 0x2D5D, 0x2D62, 0x2D67, 0x2D6C, 0x2D71, 0x2D76, 0x2D7B, 0x2D80, 0x2D85,
1251
  0x2D8A, 0x2D8F, 0x2D94, 0x2D99, 0x2D9E, 0x2DA3, 0x2DA8, 0x2DAE, 0x2DB4, 0x2DBA, 0x2DC0, 0x2DC6,
1252
  0x2DCC, 0x2DD1, 0x2BE1, 0x2DD6, 0x2BCF, 0x2BE6, 0x2DDB, 0x2DE0, 0x2BFA, 0x2DE5, 0x2BFF, 0x2C04,
1253
  0x2DEA, 0x2DEF, 0x2C18, 0x2DF4, 0x2C1D, 0x2C22, 0x2DF9, 0x2DFE, 0x2C2C, 0x2E03, 0x2C31, 0x2C36,
1254
  0x2CC7, 0x2CCC, 0x2CDB, 0x2CE0, 0x2CE5, 0x2CF9, 0x2CFE, 0x2D03, 0x2D08, 0x2D1C, 0x2D21, 0x2D26,
1255
  0x2E08, 0x2D3A, 0x2E0D, 0x2E12, 0x2D58, 0x2E17, 0x2D5D, 0x2D62, 0x2DA3, 0x2E1C, 0x2E21, 0x2D8A,
1256
  0x2E26, 0x2D8F, 0x2D94, 0x2BD7, 0x2BDC, 0x2E2B, 0x2BE1, 0x2E30, 0x2BEB, 0x2BF0, 0x2BF5, 0x2BFA,
1257
  0x2E35, 0x2C09, 0x2C0E, 0x2C13, 0x2C18, 0x2E3A, 0x2C2C, 0x2C3B, 0x2C40, 0x2C45, 0x2C4A, 0x2C4F,
1258
  0x2C59, 0x2C5E, 0x2C63, 0x2C68, 0x2C6D, 0x2C72, 0x2E3F, 0x2C77, 0x2C7C, 0x2C81, 0x2C86, 0x2C8B,
1259
  0x2C90, 0x2C9A, 0x2C9F, 0x2CA4, 0x2CA9, 0x2CAE, 0x2CB3, 0x2CB8, 0x2CBD, 0x2CC2, 0x2CD1, 0x2CD6,
1260
  0x2CEA, 0x2CEF, 0x2CF4, 0x2CF9, 0x2CFE, 0x2D0D, 0x2D12, 0x2D17, 0x2D1C, 0x2E44, 0x2D2B, 0x2D30,
1261
  0x2D35, 0x2D3A, 0x2D49, 0x2D4E, 0x2D53, 0x2D58, 0x2E49, 0x2D67, 0x2D6C, 0x2E4E, 0x2D7B, 0x2D80,
1262
  0x2D85, 0x2D8A, 0x2E53, 0x2BE1, 0x2E30, 0x2BFA, 0x2E35, 0x2C18, 0x2E3A, 0x2C2C, 0x2E58, 0x2C6D,
1263
  0x2E5D, 0x2E62, 0x2E67, 0x2CF9, 0x2CFE, 0x2D1C, 0x2D58, 0x2E49, 0x2D8A, 0x2E53, 0x2E6C, 0x2E73,
1264
  0x2E7A, 0x2E81, 0x2E86, 0x2E8B, 0x2E90, 0x2E95, 0x2E9A, 0x2E9F, 0x2EA4, 0x2EA9, 0x2EAE, 0x2EB3,
1265
  0x2EB8, 0x2EBD, 0x2EC2, 0x2EC7, 0x2ECC, 0x2ED1, 0x2ED6, 0x2EDB, 0x2EE0, 0x2EE5, 0x2EEA, 0x2EEF,
1266
  0x2E62, 0x2EF4, 0x2EF9, 0x2EFE, 0x2F03, 0x2E81, 0x2E86, 0x2E8B, 0x2E90, 0x2E95, 0x2E9A, 0x2E9F,
1267
  0x2EA4, 0x2EA9, 0x2EAE, 0x2EB3, 0x2EB8, 0x2EBD, 0x2EC2, 0x2EC7, 0x2ECC, 0x2ED1, 0x2ED6, 0x2EDB,
1268
  0x2EE0, 0x2EE5, 0x2EEA, 0x2EEF, 0x2E62, 0x2EF4, 0x2EF9, 0x2EFE, 0x2F03, 0x2EE5, 0x2EEA, 0x2EEF,
1269
  0x2E62, 0x2E5D, 0x2E67, 0x2C95, 0x2C5E, 0x2C63, 0x2C68, 0x2EE5, 0x2EEA, 0x2EEF, 0x2C95, 0x2C9A,
1270
  0x2F08, 0x2F08, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1271
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x2F0D, 0x2F14, 0x2F14, 0x2F1B,
1272
  0x2F22, 0x2F29, 0x2F30, 0x2F37, 0x2F3E, 0x2F3E, 0x2F45, 0x2F4C, 0x2F53, 0x2F5A, 0x2F61, 0x2F68,
1273
  0x2F68, 0x2F6F, 0x2F76, 0x2F76, 0x2F7D, 0x2F7D, 0x2F84, 0x2F8B, 0x2F8B, 0x2F92, 0x2F99, 0x2F99,
1274
  0x2FA0, 0x2FA0, 0x2FA7, 0x2FAE, 0x2FAE, 0x2FB5, 0x2FB5, 0x2FBC, 0x2FC3, 0x2FCA, 0x2FD1, 0x2FD1,
1275
  0x2FD8, 0x2FDF, 0x2FE6, 0x2FED, 0x2FF4, 0x2FF4, 0x2FFB, 0x3002, 0x3009, 0x3010, 0x3017, 0x301E,
1276
  0x301E, 0x3025, 0x3025, 0x302C, 0x302C, 0x3033, 0x303A, 0x3041, 0x3048, 0x304F, 0x3056, 0x305D,
1277
  0xFFFF, 0xFFFF, 0x3064, 0x306B, 0x3072, 0x3079, 0x3080, 0x3087, 0x3087, 0x308E, 0x3095, 0x309C,
1278
  0x30A3, 0x30A3, 0x30AA, 0x30B1, 0x30B8, 0x30BF, 0x30C6, 0x30CD, 0x30D4, 0x30DB, 0x30E2, 0x30E9,
1279
  0x30F0, 0x30F7, 0x30FE, 0x3105, 0x310C, 0x3113, 0x311A, 0x3121, 0x3128, 0x312F, 0x3136, 0x313D,
1280
  0x2FFB, 0x3009, 0x3144, 0x314B, 0x3152, 0x3159, 0x3160, 0x3167, 0x3160, 0x3152, 0x316E, 0x3175,
1281
  0x317C, 0x3183, 0x318A, 0x3167, 0x2FCA, 0x2F84, 0x3191, 0x3198, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1282
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1283
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1284
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1285
  0x319F, 0x31A6, 0x31AD, 0x31B6, 0x31BF, 0x31C8, 0x31D1, 0x31DA, 0x31E3, 0x31EC, 0x31F3, 0x3215,
1286
  0x3225, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1287
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x322E, 0x3230, 0xFFFE, 0x3234,
1288
  0x02FF, 0x3236, 0x3238, 0x323A, 0x323E, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1289
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1290
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0x3242, 0x3246, 0x324A, 0x324A, 0x0D4C, 0x0D4E, 0x324C,
1291
  0x324E, 0x3250, 0x3254, 0x3258, 0x325C, 0x3260, 0x3264, 0x0E3C, 0x0E40, 0x3268, 0x326C, 0x3270,
1292
  0x3274, 0xFFFF, 0xFFFF, 0x3278, 0x327A, 0x0D1C, 0x0D1C, 0x0D1C, 0x0D1C, 0x324A, 0x324A, 0x324A,
1293
  0x322E, 0x3230, 0xFFFE, 0xFFFE, 0x02FF, 0x3234, 0x3238, 0x3236, 0x3242, 0x0D4C, 0x0D4E, 0x324C,
1294
  0x324E, 0x3250, 0x3254, 0x327C, 0x327E, 0x3280, 0x0D44, 0x3282, 0x3284, 0x3286, 0x0D4A, 0xFFFE,
1295
  0x3288, 0x328A, 0x328C, 0x328E, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3290, 0x3294, 0x3299, 0xFFFF,
1296
  0x329D, 0xFFFE, 0x32A1, 0x32A5, 0x32AA, 0x32AE, 0x32B3, 0x32B7, 0x32BC, 0x32C0, 0x32C5, 0x32C9,
1297
  0x32CE, 0x32D1, 0x32D1, 0x32D4, 0x32D4, 0x32D7, 0x32D7, 0x32DA, 0x32DA, 0x32DD, 0x32DD, 0x32DD,
1298
  0x32DD, 0x32E0, 0x32E0, 0x32E3, 0x32E3, 0x32E3, 0x32E3, 0x32E6, 0x32E6, 0x32E9, 0x32E9, 0x32E9,
1299
  0x32E9, 0x32EC, 0x32EC, 0x32EC, 0x32EC, 0x32EF, 0x32EF, 0x32EF, 0x32EF, 0x32F2, 0x32F2, 0x32F2,
1300
  0x32F2, 0x32F5, 0x32F5, 0x32F5, 0x32F5, 0x32F8, 0x32F8, 0x32FB, 0x32FB, 0x32FE, 0x32FE, 0x3301,
1301
  0x3301, 0x3304, 0x3304, 0x3304, 0x3304, 0x3307, 0x3307, 0x3307, 0x3307, 0x330A, 0x330A, 0x330A,
1302
  0x330A, 0x330D, 0x330D, 0x330D, 0x330D, 0x3310, 0x3310, 0x3310, 0x3310, 0x3313, 0x3313, 0x3313,
1303
  0x3313, 0x3316, 0x3316, 0x3316, 0x3316, 0x3319, 0x3319, 0x3319, 0x3319, 0x331C, 0x331C, 0x331C,
1304
  0x331C, 0x331F, 0x331F, 0x331F, 0x331F, 0x3322, 0x3322, 0x3322, 0x3322, 0x3325, 0x3325, 0x3325,
1305
  0x3325, 0x3328, 0x3328, 0x3328, 0x3328, 0x332B, 0x332B, 0x332B, 0x332B, 0x332E, 0x332E, 0x332E,
1306
  0x332E, 0x3331, 0x3331, 0x2BA9, 0x2BA9, 0x3334, 0x3334, 0x3334, 0x3334, 0x3337, 0x3337, 0x333C,
1307
  0x333C, 0x3341, 0x3341, 0x3346, 0x3346, 0xFFFE, 0xFFFE, 0x0000, 0xFFFE, 0x3236, 0x334B, 0x327C,
1308
  0x328A, 0x328C, 0x327E, 0x334D, 0x0D4C, 0x0D4E, 0x3280, 0x0D44, 0x322E, 0x3282, 0x1466, 0x334F,
1309
  0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0x3234, 0x02FF,
1310
  0x3284, 0x0D4A, 0x3286, 0x3238, 0x328E, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D,
1311
  0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025,
1312
  0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x3278, 0x3288, 0x327A, 0x3351, 0x324A,
1313
  0x0CCB, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015,
1314
  0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D,
1315
  0x002F, 0x0031, 0x0033, 0x324C, 0x3353, 0x324E, 0x3355, 0x3357, 0x335B, 0x1466, 0x3268, 0x326C,
1316
  0x3230, 0x335F, 0x19F9, 0x3363, 0x3367, 0x336B, 0x336F, 0x3373, 0x3377, 0x337B, 0x337F, 0x3383,
1317
  0x3387, 0x1941, 0x1945, 0x1949, 0x194D, 0x1951, 0x1955, 0x1959, 0x195D, 0x1961, 0x1965, 0x1969,
1318
  0x196D, 0x1971, 0x1975, 0x1979, 0x197D, 0x1981, 0x1985, 0x1989, 0x198D, 0x1991, 0x1995, 0x1999,
1319
  0x199D, 0x19A1, 0x19A5, 0x19A9, 0x19AD, 0x19B1, 0x19B5, 0x19B9, 0x19BD, 0x19C1, 0x19C5, 0x19C9,
1320
  0x19CD, 0x19D1, 0x19D5, 0x19D9, 0x19DD, 0x19E1, 0x19E5, 0x19E9, 0x19ED, 0x338B, 0x338F, 0x3393,
1321
  0x0000, 0x148C, 0x1490, 0x1494, 0x1498, 0x149C, 0x14A0, 0x14A4, 0x14A8, 0x14AC, 0x14B0, 0x14B4,
1322
  0x14B8, 0x14BC, 0x14C0, 0x14C4, 0x14C8, 0x14CC, 0x14D0, 0x14D4, 0x14D8, 0x14DC, 0x14E0, 0x14E4,
1323
  0x14E8, 0x14EC, 0x14F0, 0x14F4, 0x14F8, 0x14FC, 0x1500, 0xFFFE, 0xFFFE, 0xFFFE, 0x1504, 0x1508,
1324
  0x150C, 0x1510, 0x1514, 0x1518, 0xFFFE, 0xFFFE, 0x151C, 0x1520, 0x1524, 0x1528, 0x152C, 0x1530,
1325
  0xFFFE, 0xFFFE, 0x1534, 0x1538, 0x153C, 0x1540, 0x1544, 0x1548, 0xFFFE, 0xFFFE, 0x154C, 0x1550,
1326
  0x1554, 0xFFFE, 0xFFFE, 0xFFFE, 0x3397, 0x339A, 0x339D, 0x003B, 0x33A0, 0x33A3, 0x33A6, 0xFFFE,
1327
  0x33AA, 0x33AE, 0x33B2, 0x33B6, 0x33BA, 0x33BE, 0x33C2, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1328
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1329
  0x33C6, 0x33CB, 0x33D0, 0x33D5, 0x33DA, 0x33DF, 0x33E4, 0x33E9, 0x33EE, 0x33F3, 0x33F8, 0x33FD,
1330
  0x3402, 0x3407, 0x340C, 0x3411, 0x3416, 0x341B, 0x3420, 0x3425, 0x342A, 0x342F, 0x3434, 0x3439,
1331
  0x343E, 0x3443, 0x3448, 0x344D, 0x3452, 0x3457, 0x345C, 0x3461, 0x3466, 0x346B, 0x3470, 0x3475,
1332
  0x347A, 0x347F, 0x3484, 0x3489, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1333
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1334
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1335
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1336
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
1337
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
1338
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x348E, 0x3493, 0x3498, 0x349D, 0x34A2, 0x34A7, 0x34AC, 0x34B1,
1339
  0x34B6, 0x34BB, 0x34C0, 0x34C5, 0x34CA, 0x34CF, 0x34D4, 0x34D9, 0x34DE, 0x34E3, 0x34E8, 0x34ED,
1340
  0x34F2, 0x34F7, 0x34FC, 0x3501, 0x3506, 0x350B, 0x3510, 0x3515, 0x351A, 0x351F, 0x3524, 0x3529,
1341
  0x352E, 0x3533, 0x3538, 0x353D, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1342
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1343
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1344
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1345
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1346
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1347
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1348
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF,
1349
  0x3542, 0x3547, 0x354C, 0x3551, 0x3556, 0x355B, 0x3560, 0x3565, 0x356A, 0x356F, 0x3574, 0xFFFE,
1350
  0x3579, 0x357E, 0x3583, 0x3588, 0x358D, 0x3592, 0x3597, 0x359C, 0x35A1, 0x35A6, 0x35AB, 0x35B0,
1351
  0x35B5, 0x35BA, 0x35BF, 0xFFFE, 0x35C4, 0x35C9, 0x35CE, 0x35D3, 0x35D8, 0x35DD, 0x35E2, 0xFFFE,
1352
  0x35E7, 0x35EC, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1353
  0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1354
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1355
  0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0x35F1, 0x35F4, 0x0074,
1356
  0x35F7, 0x017F, 0xFFFE, 0x35FA, 0x35FD, 0x3601, 0x3604, 0x018E, 0x0191, 0x3607, 0x360B, 0x360E,
1357
  0x3611, 0x226E, 0x3614, 0x01A3, 0x3617, 0x00F5, 0x361A, 0x361D, 0x3620, 0x3623, 0x3626, 0x2231,
1358
  0x3629, 0x362E, 0x3632, 0x3635, 0x363A, 0x363D, 0x00A7, 0x3642, 0x3645, 0x0021, 0x3648, 0x364B,
1359
  0x1011, 0x3650, 0x01C4, 0x3653, 0x3656, 0x3659, 0x365D, 0x01D0, 0x3660, 0xFFFE, 0x3664, 0x3667,
1360
  0x366A, 0x366D, 0x3670, 0x3673, 0x3676, 0x3679, 0x367E, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1361
  0x3683, 0x3688, 0x368D, 0x3692, 0x3697, 0x369C, 0x36A1, 0x36A6, 0x36AB, 0x36B0, 0x36B5, 0x36BA,
1362
  0x36BF, 0x36C4, 0x36C9, 0x36CE, 0x36D3, 0x36D8, 0x36DD, 0x36E2, 0x36E7, 0x36EC, 0x36F1, 0x36F6,
1363
  0x36FB, 0x3700, 0x3705, 0x370A, 0x370F, 0x3714, 0x3719, 0x371E, 0x3723, 0x3728, 0x372D, 0x3732,
1364
  0x3737, 0x373C, 0x3741, 0x3746, 0x374B, 0x3750, 0x3755, 0x375A, 0x375F, 0x3764, 0x3769, 0x376E,
1365
  0x3773, 0x3778, 0x377D, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1366
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1367
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3782, 0x3787, 0x378C, 0x3791,
1368
  0x3796, 0x379B, 0x37A0, 0x37A5, 0x37AA, 0x37AF, 0x37B4, 0x37B9, 0x37BE, 0x37C3, 0x37C8, 0x37CD,
1369
  0x37D2, 0x37D7, 0x37DC, 0x37E1, 0x37E6, 0x37EB, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF,
1370
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1371
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1372
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1373
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1374
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x37F0, 0x37F5, 0x37FA, 0x37FF, 0x3804, 0x3809, 0x380E, 0x3813,
1375
  0x3818, 0x381D, 0x3822, 0x3827, 0x382C, 0x3831, 0x3836, 0x383B, 0x3840, 0x3845, 0x384A, 0x384F,
1376
  0x3854, 0x3859, 0x385E, 0x3863, 0x3868, 0x386D, 0x3872, 0x3877, 0x387C, 0x3881, 0x3886, 0x388B,
1377
  0x3890, 0x3895, 0x389A, 0x389F, 0x38A4, 0x38A9, 0x38AE, 0x38B3, 0x38B8, 0x38BD, 0x38C2, 0x38C7,
1378
  0x38CC, 0x38D1, 0x38D6, 0x38DB, 0x38E0, 0x38E5, 0x38EA, 0x38EF, 0x38F4, 0x38F9, 0x38FE, 0x3903,
1379
  0x3908, 0x390D, 0x3912, 0x3917, 0x391C, 0x3921, 0x3926, 0x392B, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1380
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1381
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1382
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1383
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1384
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1385
  0x3930, 0x3935, 0x393A, 0x393F, 0x3944, 0x3949, 0x394E, 0x3953, 0x3958, 0x395D, 0x3962, 0x3967,
1386
  0x396C, 0x3971, 0x3976, 0x397B, 0x3980, 0x3985, 0x398A, 0x398F, 0x3994, 0x3999, 0x399E, 0x39A3,
1387
  0x39A8, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1388
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1389
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE,
1390
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1391
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1392
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1393
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1394
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0003,
1395
  0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B,
1396
  0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033,
1397
  0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0xFFFF, 0xFFFF,
1398
  0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1399
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1400
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x39AD, 0x39B6,
1401
  0x39BF, 0x39CC, 0x39D9, 0x39E6, 0x39F3, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1402
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1403
  0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1404
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1405
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1406
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1407
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1408
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3A00, 0x3A09, 0x3A12, 0x3A1F, 0x3A2C,
1409
  0x3A39, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1410
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1411
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1412
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1413
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1414
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F,
1415
  0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027,
1416
  0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B,
1417
  0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023,
1418
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007,
1419
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
1420
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003,
1421
  0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0xFFFE, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B,
1422
  0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033,
1423
  0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017,
1424
  0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F,
1425
  0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013,
1426
  0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B,
1427
  0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0xFFFE, 0x0005, 0x0007, 0xFFFE, 0xFFFE, 0x000D, 0xFFFE,
1428
  0xFFFE, 0x0013, 0x0015, 0xFFFE, 0xFFFE, 0x001B, 0x001D, 0x001F, 0x0021, 0xFFFE, 0x0025, 0x0027,
1429
  0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0xFFFE, 0x000B,
1430
  0xFFFE, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0xFFFE, 0x001F, 0x0021, 0x0023,
1431
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007,
1432
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
1433
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003,
1434
  0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B,
1435
  0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033,
1436
  0x0001, 0x0003, 0xFFFE, 0x0007, 0x0009, 0x000B, 0x000D, 0xFFFE, 0xFFFE, 0x0013, 0x0015, 0x0017,
1437
  0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0xFFFE, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F,
1438
  0x0031, 0xFFFE, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013,
1439
  0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B,
1440
  0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0xFFFE, 0x0007, 0x0009, 0x000B, 0x000D, 0xFFFE,
1441
  0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0xFFFE, 0x001D, 0xFFFE, 0xFFFE, 0xFFFE, 0x0025, 0x0027,
1442
  0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0xFFFE, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B,
1443
  0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023,
1444
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007,
1445
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
1446
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003,
1447
  0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B,
1448
  0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033,
1449
  0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017,
1450
  0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F,
1451
  0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013,
1452
  0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B,
1453
  0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F,
1454
  0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027,
1455
  0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B,
1456
  0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023,
1457
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007,
1458
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
1459
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003,
1460
  0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B,
1461
  0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033,
1462
  0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017,
1463
  0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F,
1464
  0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013,
1465
  0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B,
1466
  0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B, 0x000D, 0x000F,
1467
  0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023, 0x0025, 0x0027,
1468
  0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0001, 0x0003, 0x0005, 0x0007, 0x0009, 0x000B,
1469
  0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F, 0x0021, 0x0023,
1470
  0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x3A46, 0x3A49, 0xFFFE, 0xFFFE,
1471
  0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047,
1472
  0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x0337, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E,
1473
  0x0361, 0x3A4C, 0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A,
1474
  0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x034F, 0x034F, 0x0352, 0x0355, 0x0358,
1475
  0x035B, 0x035E, 0x0361, 0x3A50, 0x032E, 0x0337, 0x033A, 0x0358, 0x034C, 0x0349, 0x0322, 0x0325,
1476
  0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343,
1477
  0x0346, 0x0349, 0x034C, 0x0337, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A4C,
1478
  0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047,
1479
  0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x034F, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E,
1480
  0x0361, 0x3A50, 0x032E, 0x0337, 0x033A, 0x0358, 0x034C, 0x0349, 0x0322, 0x0325, 0x0328, 0x032B,
1481
  0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349,
1482
  0x034C, 0x0337, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A4C, 0x0322, 0x0325,
1483
  0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343,
1484
  0x0346, 0x0349, 0x034C, 0x034F, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A50,
1485
  0x032E, 0x0337, 0x033A, 0x0358, 0x034C, 0x0349, 0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331,
1486
  0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x0337,
1487
  0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A4C, 0x0322, 0x0325, 0x0328, 0x032B,
1488
  0x032E, 0x0331, 0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349,
1489
  0x034C, 0x034F, 0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A50, 0x032E, 0x0337,
1490
  0x033A, 0x0358, 0x034C, 0x0349, 0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331, 0x0334, 0x0337,
1491
  0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x0337, 0x034F, 0x0352,
1492
  0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A4C, 0x0322, 0x0325, 0x0328, 0x032B, 0x032E, 0x0331,
1493
  0x0334, 0x0337, 0x02EC, 0x033A, 0x033D, 0x0047, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x034F,
1494
  0x034F, 0x0352, 0x0355, 0x0358, 0x035B, 0x035E, 0x0361, 0x3A50, 0x032E, 0x0337, 0x033A, 0x0358,
1495
  0x034C, 0x0349, 0x0373, 0x0373, 0xFFFE, 0xFFFE, 0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A,
1496
  0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E,
1497
  0x0D40, 0x0D42, 0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42,
1498
  0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0x0D36, 0x004E,
1499
  0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E, 0x0D40, 0x0D42, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1500
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1501
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFF,
1502
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF, 0xFFFF,
1503
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x03D0, 0x03D3, 0x03D6, 0x03D9,
1504
  0x03DC, 0x03DF, 0x03E2, 0x03E5, 0x03E8, 0x03EE, 0x03F1, 0x03F4, 0x03FA, 0x03FD, 0x0400, 0x0403,
1505
  0x0406, 0x0409, 0x040C, 0x040F, 0x0412, 0x0415, 0x0418, 0x0421, 0x0427, 0x042A, 0x211D, 0x04D8,
1506
  0x03B2, 0x03B8, 0x04F0, 0x0499, 0x04B4, 0x03D0, 0x03D3, 0x03D6, 0x03D9, 0x03DC, 0x03DF, 0x03E2,
1507
  0x03E5, 0x03E8, 0x03EE, 0x03F1, 0x03FA, 0x03FD, 0x0403, 0x0409, 0x040C, 0x040F, 0x0412, 0x0415,
1508
  0x0418, 0x041E, 0x0421, 0x046C, 0x03B2, 0x03AF, 0x03CD, 0x0493, 0x20D1, 0x049C, 0xFFFE, 0xFFFE,
1509
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1510
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3A54, 0x3A59, 0x3A5E, 0x3A63, 0x3A68, 0x3A6D, 0x3A72, 0x3A77,
1511
  0x3A7C, 0x3A81, 0x3A86, 0x3A8B, 0x3A90, 0x3A95, 0x3A9A, 0x3A9F, 0x3AA4, 0x3AA9, 0x3AAE, 0x3AB3,
1512
  0x3AB8, 0x3ABD, 0x3AC2, 0x3AC7, 0x3ACC, 0x3AD1, 0x3AD6, 0x3ADB, 0x3AE0, 0x3AE5, 0x3AEA, 0x3AEF,
1513
  0x3AF4, 0x3AF9, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1514
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1515
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x32E0, 0x32E3, 0x32EF, 0x32F8,
1516
  0xFFFE, 0x3331, 0x3301, 0x32F2, 0x3310, 0x3334, 0x3322, 0x3325, 0x3328, 0x332B, 0x3304, 0x3316,
1517
  0x331C, 0x330A, 0x331F, 0x32FE, 0x3307, 0x32E9, 0x32EC, 0x32F5, 0x32FB, 0x330D, 0x3313, 0x3319,
1518
  0x3AFE, 0x2B7C, 0x3B01, 0x3B04, 0xFFFE, 0x32E3, 0x32EF, 0xFFFE, 0x332E, 0xFFFE, 0xFFFE, 0x32F2,
1519
  0xFFFE, 0x3334, 0x3322, 0x3325, 0x3328, 0x332B, 0x3304, 0x3316, 0x331C, 0x330A, 0x331F, 0xFFFE,
1520
  0x3307, 0x32E9, 0x32EC, 0x32F5, 0xFFFE, 0x330D, 0xFFFE, 0x3319, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1521
  0xFFFE, 0xFFFE, 0x32EF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x32F2, 0xFFFE, 0x3334, 0xFFFE, 0x3325,
1522
  0xFFFE, 0x332B, 0x3304, 0x3316, 0xFFFE, 0x330A, 0x331F, 0xFFFE, 0x3307, 0xFFFE, 0xFFFE, 0x32F5,
1523
  0xFFFE, 0x330D, 0xFFFE, 0x3319, 0xFFFE, 0x2B7C, 0xFFFE, 0x3B04, 0xFFFE, 0x32E3, 0x32EF, 0xFFFE,
1524
  0x332E, 0xFFFE, 0xFFFE, 0x32F2, 0x3310, 0x3334, 0x3322, 0xFFFE, 0x3328, 0x332B, 0x3304, 0x3316,
1525
  0x331C, 0x330A, 0x331F, 0xFFFE, 0x3307, 0x32E9, 0x32EC, 0x32F5, 0xFFFE, 0x330D, 0x3313, 0x3319,
1526
  0x3AFE, 0xFFFE, 0x3B01, 0xFFFE, 0x32E0, 0x32E3, 0x32EF, 0x32F8, 0x332E, 0x3331, 0x3301, 0x32F2,
1527
  0x3310, 0x3334, 0xFFFE, 0x3325, 0x3328, 0x332B, 0x3304, 0x3316, 0x331C, 0x330A, 0x331F, 0x32FE,
1528
  0x3307, 0x32E9, 0x32EC, 0x32F5, 0x32FB, 0x330D, 0x3313, 0x3319, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1529
  0xFFFE, 0x32E3, 0x32EF, 0x32F8, 0xFFFE, 0x3331, 0x3301, 0x32F2, 0x3310, 0x3334, 0xFFFE, 0x3325,
1530
  0x3328, 0x332B, 0x3304, 0x3316, 0x331C, 0x330A, 0x331F, 0x32FE, 0x3307, 0x32E9, 0x32EC, 0x32F5,
1531
  0x32FB, 0x330D, 0x3313, 0x3319, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3B07, 0x3B0A, 0x3B0D,
1532
  0x3B10, 0x3B13, 0x3B16, 0x3B19, 0x3B1C, 0x3B1F, 0x3B22, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1533
  0x0EC0, 0x0EC4, 0x0EC8, 0x0ECC, 0x0ED0, 0x0ED4, 0x0ED8, 0x0EDC, 0x0EE0, 0x0EE4, 0x0EE8, 0x0EEC,
1534
  0x0EF0, 0x0EF4, 0x0EF8, 0x0EFC, 0x0F00, 0x0F04, 0x0F08, 0x0F0C, 0x0F10, 0x0F14, 0x0F18, 0x0F1C,
1535
  0x0F20, 0x0F24, 0x3B25, 0x0005, 0x0023, 0x1FAD, 0x3B2D, 0xFFFF, 0x0001, 0x0003, 0x0005, 0x0007,
1536
  0x0009, 0x000B, 0x000D, 0x000F, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001B, 0x001D, 0x001F,
1537
  0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x3B30, 0x1F89,
1538
  0x3B33, 0x3B36, 0x3B39, 0x3B3D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1539
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1540
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3B40, 0x3B43, 0x3B46, 0xFFFF, 0xFFFF, 0xFFFF,
1541
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1542
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1543
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x3B49, 0xFFFF, 0xFFFF, 0xFFFF,
1544
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1545
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1546
  0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1547
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3B4C, 0x3B53, 0x1969, 0xFFFE,
1548
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1549
  0x120A, 0x3B5A, 0x3B5E, 0x3B62, 0x1126, 0x3B66, 0x3B6A, 0x1620, 0x3B6E, 0x3B72, 0x3B76, 0x26AB,
1550
  0x3B7A, 0x3B7E, 0x3B82, 0x3B86, 0x3B8A, 0x3B8E, 0x129A, 0x3B92, 0x3B96, 0x3B9A, 0x3B9E, 0x3BA2,
1551
  0x3BA6, 0x110E, 0x1600, 0x3BAA, 0x189F, 0x160C, 0x18A3, 0x3BAE, 0x137A, 0x3BB2, 0x3BB6, 0x3BBA,
1552
  0x3BBE, 0x3BC2, 0x185B, 0x1232, 0x3BC6, 0x3BCA, 0x3BCE, 0x3BD2, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1553
  0x3BD6, 0x3BE0, 0x3BEA, 0x3BF4, 0x3BFE, 0x3C08, 0x3C12, 0x3C1C, 0x3C26, 0xFFFE, 0xFFFE, 0xFFFE,
1554
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3C30, 0x3C34, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1555
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1556
  0xFFFF, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1557
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1558
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1559
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1560
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1561
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
1562
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0D36, 0x004E, 0x003F, 0x0041, 0x0D38, 0x0D3A, 0x0D3C, 0x0D3E,
1563
  0x0D40, 0x0D42, 0xFFFF, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0x3C38, 0x3C3C, 0x3C40, 0x3C44,
1564
  0x3C49, 0x281F, 0x3C4D, 0x3C51, 0x3C55, 0x3C59, 0x2823, 0x3C5D, 0x3C61, 0x3C65, 0x2827, 0x3C6A,
1565
  0x3C6E, 0x3C72, 0x3C76, 0x3C7B, 0x3C7F, 0x3B82, 0x3C83, 0x3C88, 0x3C8C, 0x3C90, 0x3C94, 0x2904,
1566
  0x3C98, 0x114E, 0x3C9D, 0x3CA1, 0x3CA5, 0x3CA9, 0x3BCA, 0x3CAD, 0x3CB1, 0x2918, 0x282B, 0x282F,
1567
  0x291C, 0x3CB5, 0x3CB9, 0x2553, 0x3CBD, 0x2833, 0x3CC1, 0x3CC5, 0x3CC9, 0x3CCD, 0x3CCD, 0x3CCD,
1568
  0x3CD1, 0x3CD6, 0x3CDA, 0x3CDE, 0x3CE2, 0x3CE7, 0x3CEB, 0x3CEF, 0x3CF3, 0x3CF7, 0x3CFB, 0x3CFF,
1569
  0x3D03, 0x3D07, 0x3D0B, 0x3D0F, 0x3D13, 0x3D17, 0x3D17, 0x2924, 0x3D1B, 0x3D1F, 0x3D23, 0x3D27,
1570
  0x283B, 0x3D2B, 0x3D2F, 0x3D33, 0x279B, 0x3D37, 0x3D3B, 0x3D3F, 0x3D43, 0x3D47, 0x3D4B, 0x3D4F,
1571
  0x3D53, 0x3D57, 0x3D5C, 0x3D60, 0x3D64, 0x3B66, 0x3D68, 0x3D6C, 0x3D70, 0x3D75, 0x3D7A, 0x3D7E,
1572
  0x3D82, 0x3D86, 0x3D8A, 0x3D8E, 0x3D92, 0x3D96, 0x3D9A, 0x3D9A, 0x3D9E, 0x3DA3, 0x3DA7, 0x2543,
1573
  0x3DAB, 0x3DAF, 0x3DB4, 0x3DB8, 0x3DBC, 0x11B6, 0x3DC0, 0x3DC4, 0x11BE, 0x3DC8, 0x3DCC, 0x3DD0,
1574
  0x3DD5, 0x3DD9, 0x3DDE, 0x3DE2, 0x3DE6, 0x3DEA, 0x3DEE, 0x3DF2, 0x3DF6, 0x3DFA, 0x3DFE, 0x3E02,
1575
  0x3E06, 0x3E0A, 0x3E0F, 0x3E13, 0x3E17, 0x3E1B, 0x2473, 0x3E1F, 0x11E6, 0x3E24, 0x3E24, 0x3E29,
1576
  0x3E2D, 0x3E2D, 0x3E31, 0x3E35, 0x3E3A, 0x3E3F, 0x3E43, 0x3E47, 0x3E4B, 0x3E4F, 0x3E53, 0x3E57,
1577
  0x3E5B, 0x3E5F, 0x3E63, 0x284F, 0x3E67, 0x3E6C, 0x3E70, 0x3E74, 0x2954, 0x3E74, 0x3E78, 0x2857,
1578
  0x3E7C, 0x3E80, 0x3E84, 0x3E88, 0x285B, 0x2407, 0x3E8C, 0x3E90, 0x3E94, 0x3E98, 0x3E9C, 0x3EA0,
1579
  0x3EA4, 0x3EA9, 0x3EAD, 0x3EB1, 0x3EB5, 0x3EB9, 0x3EBD, 0x3EC2, 0x3EC6, 0x3ECA, 0x3ECE, 0x3ED2,
1580
  0x3ED6, 0x3EDA, 0x3EDE, 0x3EE2, 0x285F, 0x3EE6, 0x3EEA, 0x3EEF, 0x3EF3, 0x3EF7, 0x3EFB, 0x2867,
1581
  0x3EFF, 0x3F03, 0x3F07, 0x3F0B, 0x3F0F, 0x3F13, 0x3F17, 0x3F1B, 0x2477, 0x2974, 0x3F1F, 0x3F23,
1582
  0x3F27, 0x3F2B, 0x3F30, 0x3F34, 0x3F38, 0x3F3C, 0x286B, 0x3F40, 0x3F45, 0x3F49, 0x3F4D, 0x2A1F,
1583
  0x3F51, 0x3F55, 0x3F59, 0x3F5D, 0x3F61, 0x3F66, 0x3F6A, 0x3F6E, 0x3F72, 0x3F77, 0x3F7B, 0x3F7F,
1584
  0x3F83, 0x2587, 0x3F87, 0x3F8B, 0x3F90, 0x3F95, 0x3F9A, 0x3F9E, 0x3FA3, 0x3FA7, 0x3FAB, 0x3FAF,
1585
  0x3FB3, 0x286F, 0x26D3, 0x3FB7, 0x3FBB, 0x3FBF, 0x3FC3, 0x3FC8, 0x3FCC, 0x3FD0, 0x3FD4, 0x2980,
1586
  0x3FD8, 0x3FDC, 0x3FE1, 0x3FE5, 0x3FE9, 0x3FEE, 0x3FF3, 0x3FF7, 0x2984, 0x3FFB, 0x3FFF, 0x4003,
1587
  0x4007, 0x400B, 0x400F, 0x4013, 0x4018, 0x401C, 0x4021, 0x4025, 0x402A, 0x298C, 0x402E, 0x4032,
1588
  0x4037, 0x403B, 0x403F, 0x4044, 0x4049, 0x404D, 0x4051, 0x4055, 0x4059, 0x4059, 0x405D, 0x4061,
1589
  0x2994, 0x4065, 0x4069, 0x406D, 0x4071, 0x4075, 0x407A, 0x407E, 0x254F, 0x4083, 0x4088, 0x408C,
1590
  0x4091, 0x4096, 0x409B, 0x409F, 0x29AC, 0x40A3, 0x40A8, 0x40AD, 0x40B2, 0x40B7, 0x40BB, 0x40BB,
1591
  0x29B0, 0x2A27, 0x40BF, 0x40C3, 0x40C7, 0x40CB, 0x40D0, 0x24BB, 0x29B8, 0x40D4, 0x40D8, 0x2897,
1592
  0x40DD, 0x40E2, 0x27EB, 0x40E7, 0x40EB, 0x28A3, 0x40EF, 0x40F3, 0x40F7, 0x40FC, 0x40FC, 0x4101,
1593
  0x4105, 0x4109, 0x410E, 0x4112, 0x4116, 0x411A, 0x411F, 0x4123, 0x4127, 0x412B, 0x412F, 0x4133,
1594
  0x4138, 0x413C, 0x4140, 0x4144, 0x4148, 0x414C, 0x4150, 0x4155, 0x415A, 0x415E, 0x4163, 0x4167,
1595
  0x416C, 0x4170, 0x28BB, 0x4174, 0x4179, 0x417E, 0x4182, 0x4187, 0x418B, 0x4190, 0x4194, 0x4198,
1596
  0x419C, 0x41A0, 0x41A4, 0x41A8, 0x41AD, 0x41B2, 0x41B7, 0x3E29, 0x41BC, 0x41C0, 0x41C4, 0x41C8,
1597
  0x41CC, 0x41D0, 0x41D4, 0x41D8, 0x41DC, 0x41E0, 0x41E4, 0x41E8, 0x2593, 0x41ED, 0x41F1, 0x41F5,
1598
  0x41F9, 0x41FD, 0x4201, 0x28C7, 0x4205, 0x4209, 0x420D, 0x4211, 0x4215, 0x421A, 0x421F, 0x4224,
1599
  0x4228, 0x422C, 0x4230, 0x4234, 0x4239, 0x423D, 0x4242, 0x4246, 0x424A, 0x424F, 0x4254, 0x4258,
1600
  0x24A7, 0x425C, 0x4260, 0x4264, 0x4268, 0x426C, 0x4270, 0x29D4, 0x4274, 0x4278, 0x427C, 0x4280,
1601
  0x4284, 0x4288, 0x428C, 0x4290, 0x134E, 0x4294, 0x4299, 0x429D, 0x42A1, 0x42A5, 0x42A9, 0x42AD,
1602
  0x42B2, 0x42B7, 0x42BB, 0x42BF, 0x29E8, 0x29EC, 0x136A, 0x42C3, 0x42C8, 0x42CC, 0x42D0, 0x42D4,
1603
  0x42D8, 0x42DD, 0x42E2, 0x42E6, 0x42EA, 0x42EE, 0x42F3, 0x29F0, 0x42F7, 0x42FC, 0x4301, 0x4305,
1604
  0x4309, 0x430D, 0x4312, 0x4316, 0x431A, 0x431E, 0x4322, 0x4326, 0x432A, 0x432E, 0x4333, 0x4337,
1605
  0x433B, 0x433F, 0x4344, 0x4348, 0x434C, 0x4350, 0x4354, 0x4359, 0x435E, 0x4362, 0x4366, 0x436A,
1606
  0x436F, 0x4373, 0x2A08, 0x2A08, 0x4378, 0x437C, 0x4381, 0x4385, 0x4389, 0x438D, 0x4391, 0x4395,
1607
  0x4399, 0x439D, 0x2A0C, 0x43A2, 0x43A6, 0x43AA, 0x43AE, 0x43B2, 0x43B6, 0x43BB, 0x43BF, 0x43C4,
1608
  0x43C9, 0x142A, 0x43CE, 0x143A, 0x43D2, 0x43D6, 0x43DA, 0x43DE, 0x144E, 0x43E2, 0xFFFE, 0xFFFE,
1609
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1610
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE,
1611
  0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE
1612
};
1613
1614
// idna_bool_blocks[]: one uint64_t per boolean block.
1615
// Bit k (0 = LSB) = 1 -> (block_start + k) is VALID; 0 -> DISALLOWED.
1616
const uint64_t idna_bool_blocks[225] = {
1617
  0xFFFFFFFFFFFFFFFFULL, 0x001F87FFFFFF00FFULL, 0xFFFFFFFFEFFFFFC0ULL, 0xFFFFFFFFDFFFFFFFULL,
1618
  0xFFFFFFFFFFFF3FFFULL, 0xFFFFFFFFFFFFE7FFULL, 0x0003FFFFFFFFFFFFULL, 0xE7FFFFFFFFFFFFFFULL,
1619
  0x7FFF3FFFFFFFFFFFULL, 0xFFFF07FF4FFFFFFFULL, 0xFFFFFFFFFF80FFFFULL, 0xFFFFFFFBFFFFFFFFULL,
1620
  0xF3C5FDFFFFF99FEFULL, 0xF3EDFDFFFFFBBFEEULL, 0xFE03FFCF00013BBFULL, 0xF3EDFDFFFFF99FEEULL,
1621
  0xC3FFC718D63DC7ECULL, 0x07FFFFC000813DC7ULL, 0xF3FFFDFFFFFDDFFFULL, 0xFF80FFCF37603DDFULL,
1622
  0xF3EFFDFFFFFDDFFFULL, 0x000EFFCF70603DDFULL, 0xFFFFFFFFFFFDDFFFULL, 0xFFFFFFCFFFF0FDDFULL,
1623
  0x2FFBFFFFFC7FFFEEULL, 0x001CFFC0FF5F847FULL, 0x000000000FFFFFFFULL, 0x0000000007FFDFFFULL,
1624
  0xFFFFFFFF3D7F3DFFULL, 0x7F3DFFFFFFFF3DFFULL, 0xFFFFFFFFFF7FFF3DULL, 0xFFFFFFFFFF3DFFFFULL,
1625
  0x1FFFFFFFE7FFFFFFULL, 0xFFFFFFFF03FFFFFFULL, 0xFFFFFFFF1FFFFFFEULL, 0x01FFFFFFFFFFFFFFULL,
1626
  0x007FFFFF803FFFFFULL, 0x000DDFFF000FFFFFULL, 0x03FF03FF3FFFFFFFULL, 0xFFFF07FFFFFFFFFFULL,
1627
  0x003FFFFFFFFFFFFFULL, 0x0FFF0FFF7FFFFFFFULL, 0x001F3FFFFFFFFFF1ULL, 0xFFFF0FFFFFFFFFFFULL,
1628
  0xFFFFFFFFC7FF03FFULL, 0xFFFFFFFFCFFFFFFFULL, 0x9FFFFFFF7FFFFFFFULL, 0xFFFF3FFF03FF03FFULL,
1629
  0x00000FFF3FFFFFFFULL, 0xFFFFFFFFFFFFDFFFULL, 0xF00FFFFFFFFFFFFFULL, 0xF8FFFFFFFFFFFFFFULL,
1630
  0xFFFFFFFFFFFFE3FFULL, 0x07FFFFFFFFFF00FFULL, 0x0001FFFFFFFF0003ULL, 0x000003FFFFFFFFFFULL,
1631
  0xFFCFFFFFFFFFFFFFULL, 0xFFFF20BFFFFFFFFFULL, 0x7F7F7F7F007FFFFFULL, 0xFFFFFFFF7F7F7F7FULL,
1632
  0x000000003FFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFF003FFFFFFFFFULL, 0xFFFFFFFFFFFF1FFFULL,
1633
  0xFFFFFFFFFFFF007FULL, 0x00000FFFFFFFFFFFULL, 0x00FFFFFFFFFFFFFFULL, 0x03FF1FFFFFFFFFFFULL,
1634
  0xFFFFFFFF03FFC03FULL, 0x1FFFFFFF800FFFFFULL, 0x7FFFFFFFC3FFBFFFULL, 0x007FFFFFFFFFFFFFULL,
1635
  0xFFFFFFFFF3FF3FFFULL, 0x007FFFFFF8000007ULL, 0xFFFF7F7F007E7E7EULL, 0x03FF3FFFFFFFFFFFULL,
1636
  0xFFFF000FFFFFFFFFULL, 0x0FFFFFFFFFFFF87FULL, 0x0000000000000000ULL, 0xB7FFFF7FFFFFEFFFULL,
1637
  0x000000003FFF3FFFULL, 0x07FFFFFFFFFFFFFFULL, 0xFF8FFFFFFFFFFF87ULL, 0x000000011FFF7FFFULL,
1638
  0x3FFFFFFFFFFF0000ULL, 0xFFFFFFFF1FFFFFFFULL, 0x0FFFFFFF0001FFFFULL, 0xFFFFE00FFFFFFFFFULL,
1639
  0x07FFFFFFFFFF07FFULL, 0xFFFFFFFFBFFFFFFFULL, 0x00000000003FFF0FULL, 0xFFFF00FFFFFFFFFFULL,
1640
  0x000FFFFFFFFFFFFFULL, 0x000000FF003FFFFFULL, 0x91BFFFFFFFFFFD3FULL, 0xFFFFFFFFFFBFFFFFULL,
1641
  0x0000FF807FFFFFFFULL, 0xF837FFFF00000000ULL, 0x83FFFFFF8FFFFFFFULL, 0x0000000003FFFFFFULL,
1642
  0xF0FFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFCFFFFULL, 0x873FFFFFFEEFF06FULL, 0xFFFFFFFF01FF01FFULL,
1643
  0x00000000FFFFFFFFULL, 0x007FF87FFFFFFFFFULL, 0xFE3FFFFFFFFFFFFFULL, 0xFF07FFFFFF3FFFFFULL,
1644
  0x0000FE001E03FFFFULL, 0x00000000000001FFULL, 0xFC07FFFFFFFFFFFFULL, 0x03FF00FFFFFFFFFFULL,
1645
  0x000000000000C03FULL, 0x7FFFFFFF00000000ULL, 0x00033BFFFFFFFFFFULL, 0xFC00000001FF00FCULL,
1646
  0xFFFF000003FFFFFFULL, 0xFFFF0000000003FFULL, 0x007FFFFF00000FFFULL, 0x803FFFFFFFFC3FFFULL,
1647
  0xDFFFFFFFFFFFFFFFULL, 0x03FF01FFFFFF0007ULL, 0xFFDFFFFFFFFFFFFFULL, 0x007FFFFFFFFF00FFULL,
1648
  0x001FFFFEFFFFFFFFULL, 0xFFFFFFFFFFFBFFFFULL, 0x0000000000000003ULL, 0xFFFF03FFBFFFBD7FULL,
1649
  0x03FF07FFFFFFFFFFULL, 0xFBEDFDFFFFF99FEFULL, 0x001F1FCFE081399FULL, 0xFFBFFFFFFFFF4BFFULL,
1650
  0x0000000601BFF7A5ULL, 0x00000003EFFFFFFFULL, 0x0000000003FF00FFULL, 0xFF3FFFFFFFFFFFFFULL,
1651
  0x00001FFF03FF001FULL, 0x03FFFFFFFFFFFFFFULL, 0x0000000FFFFF03FFULL, 0xFFFF0FFFE7FFFFFFULL,
1652
  0x000000000000007FULL, 0x0FFFFFFFFFFFFFFFULL, 0x8007FFFFFFFFFFFFULL, 0xF9BFFFFFFF6FF27FULL,
1653
  0x0000000003FF007FULL, 0xFFFFFCFF00000000ULL, 0x0000001FFCFFFFFFULL, 0xFFFFFFFFFFFF00FFULL,
1654
  0xFFFF0007FFFFFFFFULL, 0x00000000000003FFULL, 0x000000FF00000000ULL, 0x03FF0003FFFFFFFFULL,
1655
  0xFF7FFFFFFFFFFDFFULL, 0xFFFF1FFFFFFF003FULL, 0x007FFEFFFFFCFFFFULL, 0xB47FFFFFFFFFFB7FULL,
1656
  0xFFFFFDBF03FF00FFULL, 0xFFFF03FF01FB7FFFULL, 0x000003FF0FFFFFFFULL, 0x01FFFFFF00000000ULL,
1657
  0xC7FFFFFFFFFDFFFFULL, 0x0000000007FFFFFFULL, 0x0001000000000000ULL, 0x8003FFFFFFFFFFFFULL,
1658
  0x001F7FFFFFFFFFFFULL, 0x000000000000000FULL, 0xFFFFFFFFFFFF0000ULL, 0x0007FFFFFFFFFFFFULL,
1659
  0x0000FFFFFFFFFFFFULL, 0xFFFFFFFF003FFFFFULL, 0xFFFFC3FF7FFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL,
1660
  0x003F3FFFFFFF03FFULL, 0xE0FFFFFBFBFF003FULL, 0x000000000000FFFFULL, 0x00000000000FFFFFULL,
1661
  0xFFFFFFFFFFFF87FFULL, 0x00000000FFFF80FFULL, 0x007F001F00000000ULL, 0x80000000003FFFFFULL,
1662
  0x000000007FFFFFFFULL, 0x6FEF000000000000ULL, 0x00040007FFFFFFFFULL, 0xFFFF00F000270000ULL,
1663
  0x1FFF07FFFFFFFFFFULL, 0xFC0FFFFFFFFFFFFFULL, 0x0001FFFF0001FFFFULL, 0xFFFF3FFFFFFFFFFFULL,
1664
  0xFFFFFE7FFFFFFFFFULL, 0x000000000000003FULL, 0x000FFFFF000FFFFFULL, 0x01FFFFFF007FFFFFULL,
1665
  0x0000FFFEF8000FFFULL, 0x000007E07FFFFFFFULL, 0x0000000000008000ULL, 0x3FFF1FFFFFFFFFFFULL,
1666
  0x000000000000C3FFULL, 0x00007FFFFFFF0000ULL, 0x83FFFFFFFFFFFFFFULL, 0x03FFFFFFFFFF0000ULL,
1667
  0x87FFFFFFFFFF0000ULL, 0xC03FFFFF7FFFFFFFULL, 0x7FFF6F7F00000000ULL, 0x00000000007FFF9FULL,
1668
  0x00000000C3FF0FFFULL, 0xFFFE000000000000ULL, 0x001FFFFFFFFFFFFFULL, 0x3FFFFFFFFFFFFFFEULL,
1669
  0x0003000000000000ULL, 0xFFFE7FFF000FFFFFULL, 0x003FFFFFFFFEFFFEULL, 0xFFFFFFC000000000ULL,
1670
  0x1FFF1FFFF1FFFFFFULL, 0x00010FFF03FFFFFFULL, 0xFFFFFFFFFFFF0FFFULL, 0xFFFFFFFF03FF00FFULL,
1671
  0x0FFF3FFFFFFF00FFULL, 0x0000000001FF0003ULL, 0x1FFF3FFF00FFFFFFULL, 0xFFFFFFFFFFFFC7FFULL,
1672
  0x01FF87FF9FFFE17FULL, 0xFFFFFFFFFFF7FFFFULL, 0xFFFFFFFF3FFFFFFFULL, 0xFFFF0001FFFFFFFFULL,
1673
  0xFFFFFFFFFFFF07FFULL
1674
};
1675
1676
// idna_utf8_mappings[]: null-terminated UTF-8 mapping strings.
1677
// Byte offset 0 is the empty string (for ignored code points).
1678
const uint8_t idna_utf8_mappings[17383] = {
1679
  0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x68,
1680
  0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B, 0x00, 0x6C, 0x00, 0x6D, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0x70,
1681
  0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x76, 0x00, 0x77, 0x00, 0x78,
1682
  0x00, 0x79, 0x00, 0x7A, 0x00, 0x20, 0x00, 0x20, 0xCC, 0x88, 0x00, 0x20, 0xCC, 0x84, 0x00, 0x32,
1683
  0x00, 0x33, 0x00, 0x20, 0xCC, 0x81, 0x00, 0xCE, 0xBC, 0x00, 0x20, 0xCC, 0xA7, 0x00, 0x31, 0x00,
1684
  0x31, 0xE2, 0x81, 0x84, 0x34, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x32, 0x00, 0x33, 0xE2, 0x81, 0x84,
1685
  0x34, 0x00, 0xC3, 0xA0, 0x00, 0xC3, 0xA1, 0x00, 0xC3, 0xA2, 0x00, 0xC3, 0xA3, 0x00, 0xC3, 0xA4,
1686
  0x00, 0xC3, 0xA5, 0x00, 0xC3, 0xA6, 0x00, 0xC3, 0xA7, 0x00, 0xC3, 0xA8, 0x00, 0xC3, 0xA9, 0x00,
1687
  0xC3, 0xAA, 0x00, 0xC3, 0xAB, 0x00, 0xC3, 0xAC, 0x00, 0xC3, 0xAD, 0x00, 0xC3, 0xAE, 0x00, 0xC3,
1688
  0xAF, 0x00, 0xC3, 0xB0, 0x00, 0xC3, 0xB1, 0x00, 0xC3, 0xB2, 0x00, 0xC3, 0xB3, 0x00, 0xC3, 0xB4,
1689
  0x00, 0xC3, 0xB5, 0x00, 0xC3, 0xB6, 0x00, 0xC3, 0xB8, 0x00, 0xC3, 0xB9, 0x00, 0xC3, 0xBA, 0x00,
1690
  0xC3, 0xBB, 0x00, 0xC3, 0xBC, 0x00, 0xC3, 0xBD, 0x00, 0xC3, 0xBE, 0x00, 0xC4, 0x81, 0x00, 0xC4,
1691
  0x83, 0x00, 0xC4, 0x85, 0x00, 0xC4, 0x87, 0x00, 0xC4, 0x89, 0x00, 0xC4, 0x8B, 0x00, 0xC4, 0x8D,
1692
  0x00, 0xC4, 0x8F, 0x00, 0xC4, 0x91, 0x00, 0xC4, 0x93, 0x00, 0xC4, 0x95, 0x00, 0xC4, 0x97, 0x00,
1693
  0xC4, 0x99, 0x00, 0xC4, 0x9B, 0x00, 0xC4, 0x9D, 0x00, 0xC4, 0x9F, 0x00, 0xC4, 0xA1, 0x00, 0xC4,
1694
  0xA3, 0x00, 0xC4, 0xA5, 0x00, 0xC4, 0xA7, 0x00, 0xC4, 0xA9, 0x00, 0xC4, 0xAB, 0x00, 0xC4, 0xAD,
1695
  0x00, 0xC4, 0xAF, 0x00, 0x69, 0xCC, 0x87, 0x00, 0x69, 0x6A, 0x00, 0xC4, 0xB5, 0x00, 0xC4, 0xB7,
1696
  0x00, 0xC4, 0xBA, 0x00, 0xC4, 0xBC, 0x00, 0xC4, 0xBE, 0x00, 0x6C, 0xC2, 0xB7, 0x00, 0xC5, 0x82,
1697
  0x00, 0xC5, 0x84, 0x00, 0xC5, 0x86, 0x00, 0xC5, 0x88, 0x00, 0xCA, 0xBC, 0x6E, 0x00, 0xC5, 0x8B,
1698
  0x00, 0xC5, 0x8D, 0x00, 0xC5, 0x8F, 0x00, 0xC5, 0x91, 0x00, 0xC5, 0x93, 0x00, 0xC5, 0x95, 0x00,
1699
  0xC5, 0x97, 0x00, 0xC5, 0x99, 0x00, 0xC5, 0x9B, 0x00, 0xC5, 0x9D, 0x00, 0xC5, 0x9F, 0x00, 0xC5,
1700
  0xA1, 0x00, 0xC5, 0xA3, 0x00, 0xC5, 0xA5, 0x00, 0xC5, 0xA7, 0x00, 0xC5, 0xA9, 0x00, 0xC5, 0xAB,
1701
  0x00, 0xC5, 0xAD, 0x00, 0xC5, 0xAF, 0x00, 0xC5, 0xB1, 0x00, 0xC5, 0xB3, 0x00, 0xC5, 0xB5, 0x00,
1702
  0xC5, 0xB7, 0x00, 0xC3, 0xBF, 0x00, 0xC5, 0xBA, 0x00, 0xC5, 0xBC, 0x00, 0xC5, 0xBE, 0x00, 0xC9,
1703
  0x93, 0x00, 0xC6, 0x83, 0x00, 0xC6, 0x85, 0x00, 0xC9, 0x94, 0x00, 0xC6, 0x88, 0x00, 0xC9, 0x96,
1704
  0x00, 0xC9, 0x97, 0x00, 0xC6, 0x8C, 0x00, 0xC7, 0x9D, 0x00, 0xC9, 0x99, 0x00, 0xC9, 0x9B, 0x00,
1705
  0xC6, 0x92, 0x00, 0xC9, 0xA0, 0x00, 0xC9, 0xA3, 0x00, 0xC9, 0xA9, 0x00, 0xC9, 0xA8, 0x00, 0xC6,
1706
  0x99, 0x00, 0xC9, 0xAF, 0x00, 0xC9, 0xB2, 0x00, 0xC9, 0xB5, 0x00, 0xC6, 0xA1, 0x00, 0xC6, 0xA3,
1707
  0x00, 0xC6, 0xA5, 0x00, 0xCA, 0x80, 0x00, 0xC6, 0xA8, 0x00, 0xCA, 0x83, 0x00, 0xC6, 0xAD, 0x00,
1708
  0xCA, 0x88, 0x00, 0xC6, 0xB0, 0x00, 0xCA, 0x8A, 0x00, 0xCA, 0x8B, 0x00, 0xC6, 0xB4, 0x00, 0xC6,
1709
  0xB6, 0x00, 0xCA, 0x92, 0x00, 0xC6, 0xB9, 0x00, 0xC6, 0xBD, 0x00, 0x64, 0xC5, 0xBE, 0x00, 0x6C,
1710
  0x6A, 0x00, 0x6E, 0x6A, 0x00, 0xC7, 0x8E, 0x00, 0xC7, 0x90, 0x00, 0xC7, 0x92, 0x00, 0xC7, 0x94,
1711
  0x00, 0xC7, 0x96, 0x00, 0xC7, 0x98, 0x00, 0xC7, 0x9A, 0x00, 0xC7, 0x9C, 0x00, 0xC7, 0x9F, 0x00,
1712
  0xC7, 0xA1, 0x00, 0xC7, 0xA3, 0x00, 0xC7, 0xA5, 0x00, 0xC7, 0xA7, 0x00, 0xC7, 0xA9, 0x00, 0xC7,
1713
  0xAB, 0x00, 0xC7, 0xAD, 0x00, 0xC7, 0xAF, 0x00, 0x64, 0x7A, 0x00, 0xC7, 0xB5, 0x00, 0xC6, 0x95,
1714
  0x00, 0xC6, 0xBF, 0x00, 0xC7, 0xB9, 0x00, 0xC7, 0xBB, 0x00, 0xC7, 0xBD, 0x00, 0xC7, 0xBF, 0x00,
1715
  0xC8, 0x81, 0x00, 0xC8, 0x83, 0x00, 0xC8, 0x85, 0x00, 0xC8, 0x87, 0x00, 0xC8, 0x89, 0x00, 0xC8,
1716
  0x8B, 0x00, 0xC8, 0x8D, 0x00, 0xC8, 0x8F, 0x00, 0xC8, 0x91, 0x00, 0xC8, 0x93, 0x00, 0xC8, 0x95,
1717
  0x00, 0xC8, 0x97, 0x00, 0xC8, 0x99, 0x00, 0xC8, 0x9B, 0x00, 0xC8, 0x9D, 0x00, 0xC8, 0x9F, 0x00,
1718
  0xC6, 0x9E, 0x00, 0xC8, 0xA3, 0x00, 0xC8, 0xA5, 0x00, 0xC8, 0xA7, 0x00, 0xC8, 0xA9, 0x00, 0xC8,
1719
  0xAB, 0x00, 0xC8, 0xAD, 0x00, 0xC8, 0xAF, 0x00, 0xC8, 0xB1, 0x00, 0xC8, 0xB3, 0x00, 0xE2, 0xB1,
1720
  0xA5, 0x00, 0xC8, 0xBC, 0x00, 0xC6, 0x9A, 0x00, 0xE2, 0xB1, 0xA6, 0x00, 0xC9, 0x82, 0x00, 0xC6,
1721
  0x80, 0x00, 0xCA, 0x89, 0x00, 0xCA, 0x8C, 0x00, 0xC9, 0x87, 0x00, 0xC9, 0x89, 0x00, 0xC9, 0x8B,
1722
  0x00, 0xC9, 0x8D, 0x00, 0xC9, 0x8F, 0x00, 0xC9, 0xA6, 0x00, 0xC9, 0xB9, 0x00, 0xC9, 0xBB, 0x00,
1723
  0xCA, 0x81, 0x00, 0x20, 0xCC, 0x86, 0x00, 0x20, 0xCC, 0x87, 0x00, 0x20, 0xCC, 0x8A, 0x00, 0x20,
1724
  0xCC, 0xA8, 0x00, 0x20, 0xCC, 0x83, 0x00, 0x20, 0xCC, 0x8B, 0x00, 0xCA, 0x95, 0x00, 0xCC, 0x80,
1725
  0x00, 0xCC, 0x81, 0x00, 0xCC, 0x93, 0x00, 0xCC, 0x88, 0xCC, 0x81, 0x00, 0xCE, 0xB9, 0x00, 0xCD,
1726
  0xB1, 0x00, 0xCD, 0xB3, 0x00, 0xCA, 0xB9, 0x00, 0xCD, 0xB7, 0x00, 0x20, 0xCE, 0xB9, 0x00, 0x3B,
1727
  0x00, 0xCF, 0xB3, 0x00, 0x20, 0xCC, 0x88, 0xCC, 0x81, 0x00, 0xCE, 0xAC, 0x00, 0xC2, 0xB7, 0x00,
1728
  0xCE, 0xAD, 0x00, 0xCE, 0xAE, 0x00, 0xCE, 0xAF, 0x00, 0xCF, 0x8C, 0x00, 0xCF, 0x8D, 0x00, 0xCF,
1729
  0x8E, 0x00, 0xCE, 0xB1, 0x00, 0xCE, 0xB2, 0x00, 0xCE, 0xB3, 0x00, 0xCE, 0xB4, 0x00, 0xCE, 0xB5,
1730
  0x00, 0xCE, 0xB6, 0x00, 0xCE, 0xB7, 0x00, 0xCE, 0xB8, 0x00, 0xCE, 0xBA, 0x00, 0xCE, 0xBB, 0x00,
1731
  0xCE, 0xBD, 0x00, 0xCE, 0xBE, 0x00, 0xCE, 0xBF, 0x00, 0xCF, 0x80, 0x00, 0xCF, 0x81, 0x00, 0xCF,
1732
  0x83, 0x00, 0xCF, 0x84, 0x00, 0xCF, 0x85, 0x00, 0xCF, 0x86, 0x00, 0xCF, 0x87, 0x00, 0xCF, 0x88,
1733
  0x00, 0xCF, 0x89, 0x00, 0xCF, 0x8A, 0x00, 0xCF, 0x8B, 0x00, 0xCF, 0x97, 0x00, 0xCF, 0x99, 0x00,
1734
  0xCF, 0x9B, 0x00, 0xCF, 0x9D, 0x00, 0xCF, 0x9F, 0x00, 0xCF, 0xA1, 0x00, 0xCF, 0xA3, 0x00, 0xCF,
1735
  0xA5, 0x00, 0xCF, 0xA7, 0x00, 0xCF, 0xA9, 0x00, 0xCF, 0xAB, 0x00, 0xCF, 0xAD, 0x00, 0xCF, 0xAF,
1736
  0x00, 0xCF, 0xB8, 0x00, 0xCF, 0xBB, 0x00, 0xCD, 0xBB, 0x00, 0xCD, 0xBC, 0x00, 0xCD, 0xBD, 0x00,
1737
  0xD1, 0x90, 0x00, 0xD1, 0x91, 0x00, 0xD1, 0x92, 0x00, 0xD1, 0x93, 0x00, 0xD1, 0x94, 0x00, 0xD1,
1738
  0x95, 0x00, 0xD1, 0x96, 0x00, 0xD1, 0x97, 0x00, 0xD1, 0x98, 0x00, 0xD1, 0x99, 0x00, 0xD1, 0x9A,
1739
  0x00, 0xD1, 0x9B, 0x00, 0xD1, 0x9C, 0x00, 0xD1, 0x9D, 0x00, 0xD1, 0x9E, 0x00, 0xD1, 0x9F, 0x00,
1740
  0xD0, 0xB0, 0x00, 0xD0, 0xB1, 0x00, 0xD0, 0xB2, 0x00, 0xD0, 0xB3, 0x00, 0xD0, 0xB4, 0x00, 0xD0,
1741
  0xB5, 0x00, 0xD0, 0xB6, 0x00, 0xD0, 0xB7, 0x00, 0xD0, 0xB8, 0x00, 0xD0, 0xB9, 0x00, 0xD0, 0xBA,
1742
  0x00, 0xD0, 0xBB, 0x00, 0xD0, 0xBC, 0x00, 0xD0, 0xBD, 0x00, 0xD0, 0xBE, 0x00, 0xD0, 0xBF, 0x00,
1743
  0xD1, 0x80, 0x00, 0xD1, 0x81, 0x00, 0xD1, 0x82, 0x00, 0xD1, 0x83, 0x00, 0xD1, 0x84, 0x00, 0xD1,
1744
  0x85, 0x00, 0xD1, 0x86, 0x00, 0xD1, 0x87, 0x00, 0xD1, 0x88, 0x00, 0xD1, 0x89, 0x00, 0xD1, 0x8A,
1745
  0x00, 0xD1, 0x8B, 0x00, 0xD1, 0x8C, 0x00, 0xD1, 0x8D, 0x00, 0xD1, 0x8E, 0x00, 0xD1, 0x8F, 0x00,
1746
  0xD1, 0xA1, 0x00, 0xD1, 0xA3, 0x00, 0xD1, 0xA5, 0x00, 0xD1, 0xA7, 0x00, 0xD1, 0xA9, 0x00, 0xD1,
1747
  0xAB, 0x00, 0xD1, 0xAD, 0x00, 0xD1, 0xAF, 0x00, 0xD1, 0xB1, 0x00, 0xD1, 0xB3, 0x00, 0xD1, 0xB5,
1748
  0x00, 0xD1, 0xB7, 0x00, 0xD1, 0xB9, 0x00, 0xD1, 0xBB, 0x00, 0xD1, 0xBD, 0x00, 0xD1, 0xBF, 0x00,
1749
  0xD2, 0x81, 0x00, 0xD2, 0x8B, 0x00, 0xD2, 0x8D, 0x00, 0xD2, 0x8F, 0x00, 0xD2, 0x91, 0x00, 0xD2,
1750
  0x93, 0x00, 0xD2, 0x95, 0x00, 0xD2, 0x97, 0x00, 0xD2, 0x99, 0x00, 0xD2, 0x9B, 0x00, 0xD2, 0x9D,
1751
  0x00, 0xD2, 0x9F, 0x00, 0xD2, 0xA1, 0x00, 0xD2, 0xA3, 0x00, 0xD2, 0xA5, 0x00, 0xD2, 0xA7, 0x00,
1752
  0xD2, 0xA9, 0x00, 0xD2, 0xAB, 0x00, 0xD2, 0xAD, 0x00, 0xD2, 0xAF, 0x00, 0xD2, 0xB1, 0x00, 0xD2,
1753
  0xB3, 0x00, 0xD2, 0xB5, 0x00, 0xD2, 0xB7, 0x00, 0xD2, 0xB9, 0x00, 0xD2, 0xBB, 0x00, 0xD2, 0xBD,
1754
  0x00, 0xD2, 0xBF, 0x00, 0xD3, 0x8F, 0x00, 0xD3, 0x82, 0x00, 0xD3, 0x84, 0x00, 0xD3, 0x86, 0x00,
1755
  0xD3, 0x88, 0x00, 0xD3, 0x8A, 0x00, 0xD3, 0x8C, 0x00, 0xD3, 0x8E, 0x00, 0xD3, 0x91, 0x00, 0xD3,
1756
  0x93, 0x00, 0xD3, 0x95, 0x00, 0xD3, 0x97, 0x00, 0xD3, 0x99, 0x00, 0xD3, 0x9B, 0x00, 0xD3, 0x9D,
1757
  0x00, 0xD3, 0x9F, 0x00, 0xD3, 0xA1, 0x00, 0xD3, 0xA3, 0x00, 0xD3, 0xA5, 0x00, 0xD3, 0xA7, 0x00,
1758
  0xD3, 0xA9, 0x00, 0xD3, 0xAB, 0x00, 0xD3, 0xAD, 0x00, 0xD3, 0xAF, 0x00, 0xD3, 0xB1, 0x00, 0xD3,
1759
  0xB3, 0x00, 0xD3, 0xB5, 0x00, 0xD3, 0xB7, 0x00, 0xD3, 0xB9, 0x00, 0xD3, 0xBB, 0x00, 0xD3, 0xBD,
1760
  0x00, 0xD3, 0xBF, 0x00, 0xD4, 0x81, 0x00, 0xD4, 0x83, 0x00, 0xD4, 0x85, 0x00, 0xD4, 0x87, 0x00,
1761
  0xD4, 0x89, 0x00, 0xD4, 0x8B, 0x00, 0xD4, 0x8D, 0x00, 0xD4, 0x8F, 0x00, 0xD4, 0x91, 0x00, 0xD4,
1762
  0x93, 0x00, 0xD4, 0x95, 0x00, 0xD4, 0x97, 0x00, 0xD4, 0x99, 0x00, 0xD4, 0x9B, 0x00, 0xD4, 0x9D,
1763
  0x00, 0xD4, 0x9F, 0x00, 0xD4, 0xA1, 0x00, 0xD4, 0xA3, 0x00, 0xD4, 0xA5, 0x00, 0xD4, 0xA7, 0x00,
1764
  0xD4, 0xA9, 0x00, 0xD4, 0xAB, 0x00, 0xD4, 0xAD, 0x00, 0xD4, 0xAF, 0x00, 0xD5, 0xA1, 0x00, 0xD5,
1765
  0xA2, 0x00, 0xD5, 0xA3, 0x00, 0xD5, 0xA4, 0x00, 0xD5, 0xA5, 0x00, 0xD5, 0xA6, 0x00, 0xD5, 0xA7,
1766
  0x00, 0xD5, 0xA8, 0x00, 0xD5, 0xA9, 0x00, 0xD5, 0xAA, 0x00, 0xD5, 0xAB, 0x00, 0xD5, 0xAC, 0x00,
1767
  0xD5, 0xAD, 0x00, 0xD5, 0xAE, 0x00, 0xD5, 0xAF, 0x00, 0xD5, 0xB0, 0x00, 0xD5, 0xB1, 0x00, 0xD5,
1768
  0xB2, 0x00, 0xD5, 0xB3, 0x00, 0xD5, 0xB4, 0x00, 0xD5, 0xB5, 0x00, 0xD5, 0xB6, 0x00, 0xD5, 0xB7,
1769
  0x00, 0xD5, 0xB8, 0x00, 0xD5, 0xB9, 0x00, 0xD5, 0xBA, 0x00, 0xD5, 0xBB, 0x00, 0xD5, 0xBC, 0x00,
1770
  0xD5, 0xBD, 0x00, 0xD5, 0xBE, 0x00, 0xD5, 0xBF, 0x00, 0xD6, 0x80, 0x00, 0xD6, 0x81, 0x00, 0xD6,
1771
  0x82, 0x00, 0xD6, 0x83, 0x00, 0xD6, 0x84, 0x00, 0xD6, 0x85, 0x00, 0xD6, 0x86, 0x00, 0xD5, 0xA5,
1772
  0xD6, 0x82, 0x00, 0xD8, 0xA7, 0xD9, 0xB4, 0x00, 0xD9, 0x88, 0xD9, 0xB4, 0x00, 0xDB, 0x87, 0xD9,
1773
  0xB4, 0x00, 0xD9, 0x8A, 0xD9, 0xB4, 0x00, 0xE0, 0xA4, 0x95, 0xE0, 0xA4, 0xBC, 0x00, 0xE0, 0xA4,
1774
  0x96, 0xE0, 0xA4, 0xBC, 0x00, 0xE0, 0xA4, 0x97, 0xE0, 0xA4, 0xBC, 0x00, 0xE0, 0xA4, 0x9C, 0xE0,
1775
  0xA4, 0xBC, 0x00, 0xE0, 0xA4, 0xA1, 0xE0, 0xA4, 0xBC, 0x00, 0xE0, 0xA4, 0xA2, 0xE0, 0xA4, 0xBC,
1776
  0x00, 0xE0, 0xA4, 0xAB, 0xE0, 0xA4, 0xBC, 0x00, 0xE0, 0xA4, 0xAF, 0xE0, 0xA4, 0xBC, 0x00, 0xE0,
1777
  0xA6, 0xA1, 0xE0, 0xA6, 0xBC, 0x00, 0xE0, 0xA6, 0xA2, 0xE0, 0xA6, 0xBC, 0x00, 0xE0, 0xA6, 0xAF,
1778
  0xE0, 0xA6, 0xBC, 0x00, 0xE0, 0xA8, 0xB2, 0xE0, 0xA8, 0xBC, 0x00, 0xE0, 0xA8, 0xB8, 0xE0, 0xA8,
1779
  0xBC, 0x00, 0xE0, 0xA8, 0x96, 0xE0, 0xA8, 0xBC, 0x00, 0xE0, 0xA8, 0x97, 0xE0, 0xA8, 0xBC, 0x00,
1780
  0xE0, 0xA8, 0x9C, 0xE0, 0xA8, 0xBC, 0x00, 0xE0, 0xA8, 0xAB, 0xE0, 0xA8, 0xBC, 0x00, 0xE0, 0xAC,
1781
  0xA1, 0xE0, 0xAC, 0xBC, 0x00, 0xE0, 0xAC, 0xA2, 0xE0, 0xAC, 0xBC, 0x00, 0xE0, 0xB9, 0x8D, 0xE0,
1782
  0xB8, 0xB2, 0x00, 0xE0, 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x00, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0x99,
1783
  0x00, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1, 0x00, 0xE0, 0xBC, 0x8B, 0x00, 0xE0, 0xBD, 0x82, 0xE0,
1784
  0xBE, 0xB7, 0x00, 0xE0, 0xBD, 0x8C, 0xE0, 0xBE, 0xB7, 0x00, 0xE0, 0xBD, 0x91, 0xE0, 0xBE, 0xB7,
1785
  0x00, 0xE0, 0xBD, 0x96, 0xE0, 0xBE, 0xB7, 0x00, 0xE0, 0xBD, 0x9B, 0xE0, 0xBE, 0xB7, 0x00, 0xE0,
1786
  0xBD, 0x80, 0xE0, 0xBE, 0xB5, 0x00, 0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB2, 0x00, 0xE0, 0xBD, 0xB1,
1787
  0xE0, 0xBD, 0xB4, 0x00, 0xE0, 0xBE, 0xB2, 0xE0, 0xBE, 0x80, 0x00, 0xE0, 0xBE, 0xB2, 0xE0, 0xBD,
1788
  0xB1, 0xE0, 0xBE, 0x80, 0x00, 0xE0, 0xBE, 0xB3, 0xE0, 0xBE, 0x80, 0x00, 0xE0, 0xBE, 0xB3, 0xE0,
1789
  0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x00, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x00, 0xE0, 0xBE, 0x92,
1790
  0xE0, 0xBE, 0xB7, 0x00, 0xE0, 0xBE, 0x9C, 0xE0, 0xBE, 0xB7, 0x00, 0xE0, 0xBE, 0xA1, 0xE0, 0xBE,
1791
  0xB7, 0x00, 0xE0, 0xBE, 0xA6, 0xE0, 0xBE, 0xB7, 0x00, 0xE0, 0xBE, 0xAB, 0xE0, 0xBE, 0xB7, 0x00,
1792
  0xE0, 0xBE, 0x90, 0xE0, 0xBE, 0xB5, 0x00, 0xE2, 0xB4, 0x80, 0x00, 0xE2, 0xB4, 0x81, 0x00, 0xE2,
1793
  0xB4, 0x82, 0x00, 0xE2, 0xB4, 0x83, 0x00, 0xE2, 0xB4, 0x84, 0x00, 0xE2, 0xB4, 0x85, 0x00, 0xE2,
1794
  0xB4, 0x86, 0x00, 0xE2, 0xB4, 0x87, 0x00, 0xE2, 0xB4, 0x88, 0x00, 0xE2, 0xB4, 0x89, 0x00, 0xE2,
1795
  0xB4, 0x8A, 0x00, 0xE2, 0xB4, 0x8B, 0x00, 0xE2, 0xB4, 0x8C, 0x00, 0xE2, 0xB4, 0x8D, 0x00, 0xE2,
1796
  0xB4, 0x8E, 0x00, 0xE2, 0xB4, 0x8F, 0x00, 0xE2, 0xB4, 0x90, 0x00, 0xE2, 0xB4, 0x91, 0x00, 0xE2,
1797
  0xB4, 0x92, 0x00, 0xE2, 0xB4, 0x93, 0x00, 0xE2, 0xB4, 0x94, 0x00, 0xE2, 0xB4, 0x95, 0x00, 0xE2,
1798
  0xB4, 0x96, 0x00, 0xE2, 0xB4, 0x97, 0x00, 0xE2, 0xB4, 0x98, 0x00, 0xE2, 0xB4, 0x99, 0x00, 0xE2,
1799
  0xB4, 0x9A, 0x00, 0xE2, 0xB4, 0x9B, 0x00, 0xE2, 0xB4, 0x9C, 0x00, 0xE2, 0xB4, 0x9D, 0x00, 0xE2,
1800
  0xB4, 0x9E, 0x00, 0xE2, 0xB4, 0x9F, 0x00, 0xE2, 0xB4, 0xA0, 0x00, 0xE2, 0xB4, 0xA1, 0x00, 0xE2,
1801
  0xB4, 0xA2, 0x00, 0xE2, 0xB4, 0xA3, 0x00, 0xE2, 0xB4, 0xA4, 0x00, 0xE2, 0xB4, 0xA5, 0x00, 0xE2,
1802
  0xB4, 0xA7, 0x00, 0xE2, 0xB4, 0xAD, 0x00, 0xE1, 0x83, 0x9C, 0x00, 0xE1, 0x8F, 0xB0, 0x00, 0xE1,
1803
  0x8F, 0xB1, 0x00, 0xE1, 0x8F, 0xB2, 0x00, 0xE1, 0x8F, 0xB3, 0x00, 0xE1, 0x8F, 0xB4, 0x00, 0xE1,
1804
  0x8F, 0xB5, 0x00, 0xEA, 0x99, 0x8B, 0x00, 0xE1, 0xB2, 0x8A, 0x00, 0xE1, 0x83, 0x90, 0x00, 0xE1,
1805
  0x83, 0x91, 0x00, 0xE1, 0x83, 0x92, 0x00, 0xE1, 0x83, 0x93, 0x00, 0xE1, 0x83, 0x94, 0x00, 0xE1,
1806
  0x83, 0x95, 0x00, 0xE1, 0x83, 0x96, 0x00, 0xE1, 0x83, 0x97, 0x00, 0xE1, 0x83, 0x98, 0x00, 0xE1,
1807
  0x83, 0x99, 0x00, 0xE1, 0x83, 0x9A, 0x00, 0xE1, 0x83, 0x9B, 0x00, 0xE1, 0x83, 0x9D, 0x00, 0xE1,
1808
  0x83, 0x9E, 0x00, 0xE1, 0x83, 0x9F, 0x00, 0xE1, 0x83, 0xA0, 0x00, 0xE1, 0x83, 0xA1, 0x00, 0xE1,
1809
  0x83, 0xA2, 0x00, 0xE1, 0x83, 0xA3, 0x00, 0xE1, 0x83, 0xA4, 0x00, 0xE1, 0x83, 0xA5, 0x00, 0xE1,
1810
  0x83, 0xA6, 0x00, 0xE1, 0x83, 0xA7, 0x00, 0xE1, 0x83, 0xA8, 0x00, 0xE1, 0x83, 0xA9, 0x00, 0xE1,
1811
  0x83, 0xAA, 0x00, 0xE1, 0x83, 0xAB, 0x00, 0xE1, 0x83, 0xAC, 0x00, 0xE1, 0x83, 0xAD, 0x00, 0xE1,
1812
  0x83, 0xAE, 0x00, 0xE1, 0x83, 0xAF, 0x00, 0xE1, 0x83, 0xB0, 0x00, 0xE1, 0x83, 0xB1, 0x00, 0xE1,
1813
  0x83, 0xB2, 0x00, 0xE1, 0x83, 0xB3, 0x00, 0xE1, 0x83, 0xB4, 0x00, 0xE1, 0x83, 0xB5, 0x00, 0xE1,
1814
  0x83, 0xB6, 0x00, 0xE1, 0x83, 0xB7, 0x00, 0xE1, 0x83, 0xB8, 0x00, 0xE1, 0x83, 0xB9, 0x00, 0xE1,
1815
  0x83, 0xBA, 0x00, 0xE1, 0x83, 0xBD, 0x00, 0xE1, 0x83, 0xBE, 0x00, 0xE1, 0x83, 0xBF, 0x00, 0xC9,
1816
  0x90, 0x00, 0xC9, 0x91, 0x00, 0xE1, 0xB4, 0x82, 0x00, 0xC9, 0x9C, 0x00, 0xE1, 0xB4, 0x96, 0x00,
1817
  0xE1, 0xB4, 0x97, 0x00, 0xE1, 0xB4, 0x9D, 0x00, 0xE1, 0xB4, 0xA5, 0x00, 0xC9, 0x92, 0x00, 0xC9,
1818
  0x95, 0x00, 0xC9, 0x9F, 0x00, 0xC9, 0xA1, 0x00, 0xC9, 0xA5, 0x00, 0xC9, 0xAA, 0x00, 0xE1, 0xB5,
1819
  0xBB, 0x00, 0xCA, 0x9D, 0x00, 0xC9, 0xAD, 0x00, 0xE1, 0xB6, 0x85, 0x00, 0xCA, 0x9F, 0x00, 0xC9,
1820
  0xB1, 0x00, 0xC9, 0xB0, 0x00, 0xC9, 0xB3, 0x00, 0xC9, 0xB4, 0x00, 0xC9, 0xB8, 0x00, 0xCA, 0x82,
1821
  0x00, 0xC6, 0xAB, 0x00, 0xE1, 0xB4, 0x9C, 0x00, 0xCA, 0x90, 0x00, 0xCA, 0x91, 0x00, 0xE1, 0xB8,
1822
  0x81, 0x00, 0xE1, 0xB8, 0x83, 0x00, 0xE1, 0xB8, 0x85, 0x00, 0xE1, 0xB8, 0x87, 0x00, 0xE1, 0xB8,
1823
  0x89, 0x00, 0xE1, 0xB8, 0x8B, 0x00, 0xE1, 0xB8, 0x8D, 0x00, 0xE1, 0xB8, 0x8F, 0x00, 0xE1, 0xB8,
1824
  0x91, 0x00, 0xE1, 0xB8, 0x93, 0x00, 0xE1, 0xB8, 0x95, 0x00, 0xE1, 0xB8, 0x97, 0x00, 0xE1, 0xB8,
1825
  0x99, 0x00, 0xE1, 0xB8, 0x9B, 0x00, 0xE1, 0xB8, 0x9D, 0x00, 0xE1, 0xB8, 0x9F, 0x00, 0xE1, 0xB8,
1826
  0xA1, 0x00, 0xE1, 0xB8, 0xA3, 0x00, 0xE1, 0xB8, 0xA5, 0x00, 0xE1, 0xB8, 0xA7, 0x00, 0xE1, 0xB8,
1827
  0xA9, 0x00, 0xE1, 0xB8, 0xAB, 0x00, 0xE1, 0xB8, 0xAD, 0x00, 0xE1, 0xB8, 0xAF, 0x00, 0xE1, 0xB8,
1828
  0xB1, 0x00, 0xE1, 0xB8, 0xB3, 0x00, 0xE1, 0xB8, 0xB5, 0x00, 0xE1, 0xB8, 0xB7, 0x00, 0xE1, 0xB8,
1829
  0xB9, 0x00, 0xE1, 0xB8, 0xBB, 0x00, 0xE1, 0xB8, 0xBD, 0x00, 0xE1, 0xB8, 0xBF, 0x00, 0xE1, 0xB9,
1830
  0x81, 0x00, 0xE1, 0xB9, 0x83, 0x00, 0xE1, 0xB9, 0x85, 0x00, 0xE1, 0xB9, 0x87, 0x00, 0xE1, 0xB9,
1831
  0x89, 0x00, 0xE1, 0xB9, 0x8B, 0x00, 0xE1, 0xB9, 0x8D, 0x00, 0xE1, 0xB9, 0x8F, 0x00, 0xE1, 0xB9,
1832
  0x91, 0x00, 0xE1, 0xB9, 0x93, 0x00, 0xE1, 0xB9, 0x95, 0x00, 0xE1, 0xB9, 0x97, 0x00, 0xE1, 0xB9,
1833
  0x99, 0x00, 0xE1, 0xB9, 0x9B, 0x00, 0xE1, 0xB9, 0x9D, 0x00, 0xE1, 0xB9, 0x9F, 0x00, 0xE1, 0xB9,
1834
  0xA1, 0x00, 0xE1, 0xB9, 0xA3, 0x00, 0xE1, 0xB9, 0xA5, 0x00, 0xE1, 0xB9, 0xA7, 0x00, 0xE1, 0xB9,
1835
  0xA9, 0x00, 0xE1, 0xB9, 0xAB, 0x00, 0xE1, 0xB9, 0xAD, 0x00, 0xE1, 0xB9, 0xAF, 0x00, 0xE1, 0xB9,
1836
  0xB1, 0x00, 0xE1, 0xB9, 0xB3, 0x00, 0xE1, 0xB9, 0xB5, 0x00, 0xE1, 0xB9, 0xB7, 0x00, 0xE1, 0xB9,
1837
  0xB9, 0x00, 0xE1, 0xB9, 0xBB, 0x00, 0xE1, 0xB9, 0xBD, 0x00, 0xE1, 0xB9, 0xBF, 0x00, 0xE1, 0xBA,
1838
  0x81, 0x00, 0xE1, 0xBA, 0x83, 0x00, 0xE1, 0xBA, 0x85, 0x00, 0xE1, 0xBA, 0x87, 0x00, 0xE1, 0xBA,
1839
  0x89, 0x00, 0xE1, 0xBA, 0x8B, 0x00, 0xE1, 0xBA, 0x8D, 0x00, 0xE1, 0xBA, 0x8F, 0x00, 0xE1, 0xBA,
1840
  0x91, 0x00, 0xE1, 0xBA, 0x93, 0x00, 0xE1, 0xBA, 0x95, 0x00, 0x61, 0xCA, 0xBE, 0x00, 0xC3, 0x9F,
1841
  0x00, 0xE1, 0xBA, 0xA1, 0x00, 0xE1, 0xBA, 0xA3, 0x00, 0xE1, 0xBA, 0xA5, 0x00, 0xE1, 0xBA, 0xA7,
1842
  0x00, 0xE1, 0xBA, 0xA9, 0x00, 0xE1, 0xBA, 0xAB, 0x00, 0xE1, 0xBA, 0xAD, 0x00, 0xE1, 0xBA, 0xAF,
1843
  0x00, 0xE1, 0xBA, 0xB1, 0x00, 0xE1, 0xBA, 0xB3, 0x00, 0xE1, 0xBA, 0xB5, 0x00, 0xE1, 0xBA, 0xB7,
1844
  0x00, 0xE1, 0xBA, 0xB9, 0x00, 0xE1, 0xBA, 0xBB, 0x00, 0xE1, 0xBA, 0xBD, 0x00, 0xE1, 0xBA, 0xBF,
1845
  0x00, 0xE1, 0xBB, 0x81, 0x00, 0xE1, 0xBB, 0x83, 0x00, 0xE1, 0xBB, 0x85, 0x00, 0xE1, 0xBB, 0x87,
1846
  0x00, 0xE1, 0xBB, 0x89, 0x00, 0xE1, 0xBB, 0x8B, 0x00, 0xE1, 0xBB, 0x8D, 0x00, 0xE1, 0xBB, 0x8F,
1847
  0x00, 0xE1, 0xBB, 0x91, 0x00, 0xE1, 0xBB, 0x93, 0x00, 0xE1, 0xBB, 0x95, 0x00, 0xE1, 0xBB, 0x97,
1848
  0x00, 0xE1, 0xBB, 0x99, 0x00, 0xE1, 0xBB, 0x9B, 0x00, 0xE1, 0xBB, 0x9D, 0x00, 0xE1, 0xBB, 0x9F,
1849
  0x00, 0xE1, 0xBB, 0xA1, 0x00, 0xE1, 0xBB, 0xA3, 0x00, 0xE1, 0xBB, 0xA5, 0x00, 0xE1, 0xBB, 0xA7,
1850
  0x00, 0xE1, 0xBB, 0xA9, 0x00, 0xE1, 0xBB, 0xAB, 0x00, 0xE1, 0xBB, 0xAD, 0x00, 0xE1, 0xBB, 0xAF,
1851
  0x00, 0xE1, 0xBB, 0xB1, 0x00, 0xE1, 0xBB, 0xB3, 0x00, 0xE1, 0xBB, 0xB5, 0x00, 0xE1, 0xBB, 0xB7,
1852
  0x00, 0xE1, 0xBB, 0xB9, 0x00, 0xE1, 0xBB, 0xBB, 0x00, 0xE1, 0xBB, 0xBD, 0x00, 0xE1, 0xBB, 0xBF,
1853
  0x00, 0xE1, 0xBC, 0x80, 0x00, 0xE1, 0xBC, 0x81, 0x00, 0xE1, 0xBC, 0x82, 0x00, 0xE1, 0xBC, 0x83,
1854
  0x00, 0xE1, 0xBC, 0x84, 0x00, 0xE1, 0xBC, 0x85, 0x00, 0xE1, 0xBC, 0x86, 0x00, 0xE1, 0xBC, 0x87,
1855
  0x00, 0xE1, 0xBC, 0x90, 0x00, 0xE1, 0xBC, 0x91, 0x00, 0xE1, 0xBC, 0x92, 0x00, 0xE1, 0xBC, 0x93,
1856
  0x00, 0xE1, 0xBC, 0x94, 0x00, 0xE1, 0xBC, 0x95, 0x00, 0xE1, 0xBC, 0xA0, 0x00, 0xE1, 0xBC, 0xA1,
1857
  0x00, 0xE1, 0xBC, 0xA2, 0x00, 0xE1, 0xBC, 0xA3, 0x00, 0xE1, 0xBC, 0xA4, 0x00, 0xE1, 0xBC, 0xA5,
1858
  0x00, 0xE1, 0xBC, 0xA6, 0x00, 0xE1, 0xBC, 0xA7, 0x00, 0xE1, 0xBC, 0xB0, 0x00, 0xE1, 0xBC, 0xB1,
1859
  0x00, 0xE1, 0xBC, 0xB2, 0x00, 0xE1, 0xBC, 0xB3, 0x00, 0xE1, 0xBC, 0xB4, 0x00, 0xE1, 0xBC, 0xB5,
1860
  0x00, 0xE1, 0xBC, 0xB6, 0x00, 0xE1, 0xBC, 0xB7, 0x00, 0xE1, 0xBD, 0x80, 0x00, 0xE1, 0xBD, 0x81,
1861
  0x00, 0xE1, 0xBD, 0x82, 0x00, 0xE1, 0xBD, 0x83, 0x00, 0xE1, 0xBD, 0x84, 0x00, 0xE1, 0xBD, 0x85,
1862
  0x00, 0xE1, 0xBD, 0x91, 0x00, 0xE1, 0xBD, 0x93, 0x00, 0xE1, 0xBD, 0x95, 0x00, 0xE1, 0xBD, 0x97,
1863
  0x00, 0xE1, 0xBD, 0xA0, 0x00, 0xE1, 0xBD, 0xA1, 0x00, 0xE1, 0xBD, 0xA2, 0x00, 0xE1, 0xBD, 0xA3,
1864
  0x00, 0xE1, 0xBD, 0xA4, 0x00, 0xE1, 0xBD, 0xA5, 0x00, 0xE1, 0xBD, 0xA6, 0x00, 0xE1, 0xBD, 0xA7,
1865
  0x00, 0xE1, 0xBC, 0x80, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x81, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x82,
1866
  0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x83, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x84, 0xCE, 0xB9, 0x00, 0xE1,
1867
  0xBC, 0x85, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x86, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0x87, 0xCE, 0xB9,
1868
  0x00, 0xE1, 0xBC, 0xA0, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA1, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA2,
1869
  0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA3, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA4, 0xCE, 0xB9, 0x00, 0xE1,
1870
  0xBC, 0xA5, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA6, 0xCE, 0xB9, 0x00, 0xE1, 0xBC, 0xA7, 0xCE, 0xB9,
1871
  0x00, 0xE1, 0xBD, 0xA0, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA1, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA2,
1872
  0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA3, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA4, 0xCE, 0xB9, 0x00, 0xE1,
1873
  0xBD, 0xA5, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA6, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xA7, 0xCE, 0xB9,
1874
  0x00, 0xE1, 0xBD, 0xB0, 0xCE, 0xB9, 0x00, 0xCE, 0xB1, 0xCE, 0xB9, 0x00, 0xCE, 0xAC, 0xCE, 0xB9,
1875
  0x00, 0xE1, 0xBE, 0xB6, 0xCE, 0xB9, 0x00, 0xE1, 0xBE, 0xB0, 0x00, 0xE1, 0xBE, 0xB1, 0x00, 0xE1,
1876
  0xBD, 0xB0, 0x00, 0x20, 0xCC, 0x93, 0x00, 0x20, 0xCD, 0x82, 0x00, 0x20, 0xCC, 0x88, 0xCD, 0x82,
1877
  0x00, 0xE1, 0xBD, 0xB4, 0xCE, 0xB9, 0x00, 0xCE, 0xB7, 0xCE, 0xB9, 0x00, 0xCE, 0xAE, 0xCE, 0xB9,
1878
  0x00, 0xE1, 0xBF, 0x86, 0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xB2, 0x00, 0xE1, 0xBD, 0xB4, 0x00, 0x20,
1879
  0xCC, 0x93, 0xCC, 0x80, 0x00, 0x20, 0xCC, 0x93, 0xCC, 0x81, 0x00, 0x20, 0xCC, 0x93, 0xCD, 0x82,
1880
  0x00, 0xCE, 0x90, 0x00, 0xE1, 0xBF, 0x90, 0x00, 0xE1, 0xBF, 0x91, 0x00, 0xE1, 0xBD, 0xB6, 0x00,
1881
  0x20, 0xCC, 0x94, 0xCC, 0x80, 0x00, 0x20, 0xCC, 0x94, 0xCC, 0x81, 0x00, 0x20, 0xCC, 0x94, 0xCD,
1882
  0x82, 0x00, 0xCE, 0xB0, 0x00, 0xE1, 0xBF, 0xA0, 0x00, 0xE1, 0xBF, 0xA1, 0x00, 0xE1, 0xBD, 0xBA,
1883
  0x00, 0xE1, 0xBF, 0xA5, 0x00, 0x20, 0xCC, 0x88, 0xCC, 0x80, 0x00, 0x60, 0x00, 0xE1, 0xBD, 0xBC,
1884
  0xCE, 0xB9, 0x00, 0xCF, 0x89, 0xCE, 0xB9, 0x00, 0xCF, 0x8E, 0xCE, 0xB9, 0x00, 0xE1, 0xBF, 0xB6,
1885
  0xCE, 0xB9, 0x00, 0xE1, 0xBD, 0xB8, 0x00, 0xE1, 0xBD, 0xBC, 0x00, 0x20, 0xCC, 0x94, 0x00, 0xE2,
1886
  0x80, 0x90, 0x00, 0x20, 0xCC, 0xB3, 0x00, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0x00, 0xE2, 0x80,
1887
  0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0x00, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x00, 0xE2,
1888
  0x80, 0xB5, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x00, 0x21, 0x21, 0x00, 0x20, 0xCC, 0x85, 0x00,
1889
  0x3F, 0x3F, 0x00, 0x3F, 0x21, 0x00, 0x21, 0x3F, 0x00, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2,
1890
  0x80, 0xB2, 0xE2, 0x80, 0xB2, 0x00, 0x30, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00,
1891
  0x38, 0x00, 0x39, 0x00, 0x2B, 0x00, 0xE2, 0x88, 0x92, 0x00, 0x3D, 0x00, 0x28, 0x00, 0x29, 0x00,
1892
  0x72, 0x73, 0x00, 0x61, 0x2F, 0x63, 0x00, 0x61, 0x2F, 0x73, 0x00, 0xC2, 0xB0, 0x63, 0x00, 0x63,
1893
  0x2F, 0x6F, 0x00, 0x63, 0x2F, 0x75, 0x00, 0xC2, 0xB0, 0x66, 0x00, 0x6E, 0x6F, 0x00, 0x73, 0x6D,
1894
  0x00, 0x74, 0x65, 0x6C, 0x00, 0x74, 0x6D, 0x00, 0xE2, 0x85, 0x8E, 0x00, 0xD7, 0x90, 0x00, 0xD7,
1895
  0x91, 0x00, 0xD7, 0x92, 0x00, 0xD7, 0x93, 0x00, 0x66, 0x61, 0x78, 0x00, 0xE2, 0x88, 0x91, 0x00,
1896
  0x31, 0xE2, 0x81, 0x84, 0x37, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x39, 0x00, 0x31, 0xE2, 0x81, 0x84,
1897
  0x31, 0x30, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x33, 0x00, 0x32, 0xE2, 0x81, 0x84, 0x33, 0x00, 0x31,
1898
  0xE2, 0x81, 0x84, 0x35, 0x00, 0x32, 0xE2, 0x81, 0x84, 0x35, 0x00, 0x33, 0xE2, 0x81, 0x84, 0x35,
1899
  0x00, 0x34, 0xE2, 0x81, 0x84, 0x35, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x36, 0x00, 0x35, 0xE2, 0x81,
1900
  0x84, 0x36, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x38, 0x00, 0x33, 0xE2, 0x81, 0x84, 0x38, 0x00, 0x35,
1901
  0xE2, 0x81, 0x84, 0x38, 0x00, 0x37, 0xE2, 0x81, 0x84, 0x38, 0x00, 0x31, 0xE2, 0x81, 0x84, 0x00,
1902
  0x69, 0x69, 0x00, 0x69, 0x69, 0x69, 0x00, 0x69, 0x76, 0x00, 0x76, 0x69, 0x00, 0x76, 0x69, 0x69,
1903
  0x00, 0x76, 0x69, 0x69, 0x69, 0x00, 0x69, 0x78, 0x00, 0x78, 0x69, 0x00, 0x78, 0x69, 0x69, 0x00,
1904
  0xE2, 0x86, 0x84, 0x00, 0x30, 0xE2, 0x81, 0x84, 0x33, 0x00, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
1905
  0x00, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0x00, 0xE2, 0x88, 0xAE, 0xE2, 0x88,
1906
  0xAE, 0x00, 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0x00, 0xE3, 0x80, 0x88, 0x00,
1907
  0xE3, 0x80, 0x89, 0x00, 0x31, 0x30, 0x00, 0x31, 0x31, 0x00, 0x31, 0x32, 0x00, 0x31, 0x33, 0x00,
1908
  0x31, 0x34, 0x00, 0x31, 0x35, 0x00, 0x31, 0x36, 0x00, 0x31, 0x37, 0x00, 0x31, 0x38, 0x00, 0x31,
1909
  0x39, 0x00, 0x32, 0x30, 0x00, 0x28, 0x31, 0x29, 0x00, 0x28, 0x32, 0x29, 0x00, 0x28, 0x33, 0x29,
1910
  0x00, 0x28, 0x34, 0x29, 0x00, 0x28, 0x35, 0x29, 0x00, 0x28, 0x36, 0x29, 0x00, 0x28, 0x37, 0x29,
1911
  0x00, 0x28, 0x38, 0x29, 0x00, 0x28, 0x39, 0x29, 0x00, 0x28, 0x31, 0x30, 0x29, 0x00, 0x28, 0x31,
1912
  0x31, 0x29, 0x00, 0x28, 0x31, 0x32, 0x29, 0x00, 0x28, 0x31, 0x33, 0x29, 0x00, 0x28, 0x31, 0x34,
1913
  0x29, 0x00, 0x28, 0x31, 0x35, 0x29, 0x00, 0x28, 0x31, 0x36, 0x29, 0x00, 0x28, 0x31, 0x37, 0x29,
1914
  0x00, 0x28, 0x31, 0x38, 0x29, 0x00, 0x28, 0x31, 0x39, 0x29, 0x00, 0x28, 0x32, 0x30, 0x29, 0x00,
1915
  0x28, 0x61, 0x29, 0x00, 0x28, 0x62, 0x29, 0x00, 0x28, 0x63, 0x29, 0x00, 0x28, 0x64, 0x29, 0x00,
1916
  0x28, 0x65, 0x29, 0x00, 0x28, 0x66, 0x29, 0x00, 0x28, 0x67, 0x29, 0x00, 0x28, 0x68, 0x29, 0x00,
1917
  0x28, 0x69, 0x29, 0x00, 0x28, 0x6A, 0x29, 0x00, 0x28, 0x6B, 0x29, 0x00, 0x28, 0x6C, 0x29, 0x00,
1918
  0x28, 0x6D, 0x29, 0x00, 0x28, 0x6E, 0x29, 0x00, 0x28, 0x6F, 0x29, 0x00, 0x28, 0x70, 0x29, 0x00,
1919
  0x28, 0x71, 0x29, 0x00, 0x28, 0x72, 0x29, 0x00, 0x28, 0x73, 0x29, 0x00, 0x28, 0x74, 0x29, 0x00,
1920
  0x28, 0x75, 0x29, 0x00, 0x28, 0x76, 0x29, 0x00, 0x28, 0x77, 0x29, 0x00, 0x28, 0x78, 0x29, 0x00,
1921
  0x28, 0x79, 0x29, 0x00, 0x28, 0x7A, 0x29, 0x00, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
1922
  0xAB, 0xE2, 0x88, 0xAB, 0x00, 0x3A, 0x3A, 0x3D, 0x00, 0x3D, 0x3D, 0x00, 0x3D, 0x3D, 0x3D, 0x00,
1923
  0xE2, 0xAB, 0x9D, 0xCC, 0xB8, 0x00, 0xE2, 0xB0, 0xB0, 0x00, 0xE2, 0xB0, 0xB1, 0x00, 0xE2, 0xB0,
1924
  0xB2, 0x00, 0xE2, 0xB0, 0xB3, 0x00, 0xE2, 0xB0, 0xB4, 0x00, 0xE2, 0xB0, 0xB5, 0x00, 0xE2, 0xB0,
1925
  0xB6, 0x00, 0xE2, 0xB0, 0xB7, 0x00, 0xE2, 0xB0, 0xB8, 0x00, 0xE2, 0xB0, 0xB9, 0x00, 0xE2, 0xB0,
1926
  0xBA, 0x00, 0xE2, 0xB0, 0xBB, 0x00, 0xE2, 0xB0, 0xBC, 0x00, 0xE2, 0xB0, 0xBD, 0x00, 0xE2, 0xB0,
1927
  0xBE, 0x00, 0xE2, 0xB0, 0xBF, 0x00, 0xE2, 0xB1, 0x80, 0x00, 0xE2, 0xB1, 0x81, 0x00, 0xE2, 0xB1,
1928
  0x82, 0x00, 0xE2, 0xB1, 0x83, 0x00, 0xE2, 0xB1, 0x84, 0x00, 0xE2, 0xB1, 0x85, 0x00, 0xE2, 0xB1,
1929
  0x86, 0x00, 0xE2, 0xB1, 0x87, 0x00, 0xE2, 0xB1, 0x88, 0x00, 0xE2, 0xB1, 0x89, 0x00, 0xE2, 0xB1,
1930
  0x8A, 0x00, 0xE2, 0xB1, 0x8B, 0x00, 0xE2, 0xB1, 0x8C, 0x00, 0xE2, 0xB1, 0x8D, 0x00, 0xE2, 0xB1,
1931
  0x8E, 0x00, 0xE2, 0xB1, 0x8F, 0x00, 0xE2, 0xB1, 0x90, 0x00, 0xE2, 0xB1, 0x91, 0x00, 0xE2, 0xB1,
1932
  0x92, 0x00, 0xE2, 0xB1, 0x93, 0x00, 0xE2, 0xB1, 0x94, 0x00, 0xE2, 0xB1, 0x95, 0x00, 0xE2, 0xB1,
1933
  0x96, 0x00, 0xE2, 0xB1, 0x97, 0x00, 0xE2, 0xB1, 0x98, 0x00, 0xE2, 0xB1, 0x99, 0x00, 0xE2, 0xB1,
1934
  0x9A, 0x00, 0xE2, 0xB1, 0x9B, 0x00, 0xE2, 0xB1, 0x9C, 0x00, 0xE2, 0xB1, 0x9D, 0x00, 0xE2, 0xB1,
1935
  0x9E, 0x00, 0xE2, 0xB1, 0x9F, 0x00, 0xE2, 0xB1, 0xA1, 0x00, 0xC9, 0xAB, 0x00, 0xE1, 0xB5, 0xBD,
1936
  0x00, 0xC9, 0xBD, 0x00, 0xE2, 0xB1, 0xA8, 0x00, 0xE2, 0xB1, 0xAA, 0x00, 0xE2, 0xB1, 0xAC, 0x00,
1937
  0xE2, 0xB1, 0xB3, 0x00, 0xE2, 0xB1, 0xB6, 0x00, 0xC8, 0xBF, 0x00, 0xC9, 0x80, 0x00, 0xE2, 0xB2,
1938
  0x81, 0x00, 0xE2, 0xB2, 0x83, 0x00, 0xE2, 0xB2, 0x85, 0x00, 0xE2, 0xB2, 0x87, 0x00, 0xE2, 0xB2,
1939
  0x89, 0x00, 0xE2, 0xB2, 0x8B, 0x00, 0xE2, 0xB2, 0x8D, 0x00, 0xE2, 0xB2, 0x8F, 0x00, 0xE2, 0xB2,
1940
  0x91, 0x00, 0xE2, 0xB2, 0x93, 0x00, 0xE2, 0xB2, 0x95, 0x00, 0xE2, 0xB2, 0x97, 0x00, 0xE2, 0xB2,
1941
  0x99, 0x00, 0xE2, 0xB2, 0x9B, 0x00, 0xE2, 0xB2, 0x9D, 0x00, 0xE2, 0xB2, 0x9F, 0x00, 0xE2, 0xB2,
1942
  0xA1, 0x00, 0xE2, 0xB2, 0xA3, 0x00, 0xE2, 0xB2, 0xA5, 0x00, 0xE2, 0xB2, 0xA7, 0x00, 0xE2, 0xB2,
1943
  0xA9, 0x00, 0xE2, 0xB2, 0xAB, 0x00, 0xE2, 0xB2, 0xAD, 0x00, 0xE2, 0xB2, 0xAF, 0x00, 0xE2, 0xB2,
1944
  0xB1, 0x00, 0xE2, 0xB2, 0xB3, 0x00, 0xE2, 0xB2, 0xB5, 0x00, 0xE2, 0xB2, 0xB7, 0x00, 0xE2, 0xB2,
1945
  0xB9, 0x00, 0xE2, 0xB2, 0xBB, 0x00, 0xE2, 0xB2, 0xBD, 0x00, 0xE2, 0xB2, 0xBF, 0x00, 0xE2, 0xB3,
1946
  0x81, 0x00, 0xE2, 0xB3, 0x83, 0x00, 0xE2, 0xB3, 0x85, 0x00, 0xE2, 0xB3, 0x87, 0x00, 0xE2, 0xB3,
1947
  0x89, 0x00, 0xE2, 0xB3, 0x8B, 0x00, 0xE2, 0xB3, 0x8D, 0x00, 0xE2, 0xB3, 0x8F, 0x00, 0xE2, 0xB3,
1948
  0x91, 0x00, 0xE2, 0xB3, 0x93, 0x00, 0xE2, 0xB3, 0x95, 0x00, 0xE2, 0xB3, 0x97, 0x00, 0xE2, 0xB3,
1949
  0x99, 0x00, 0xE2, 0xB3, 0x9B, 0x00, 0xE2, 0xB3, 0x9D, 0x00, 0xE2, 0xB3, 0x9F, 0x00, 0xE2, 0xB3,
1950
  0xA1, 0x00, 0xE2, 0xB3, 0xA3, 0x00, 0xE2, 0xB3, 0xAC, 0x00, 0xE2, 0xB3, 0xAE, 0x00, 0xE2, 0xB3,
1951
  0xB3, 0x00, 0xE2, 0xB5, 0xA1, 0x00, 0xE6, 0xAF, 0x8D, 0x00, 0xE9, 0xBE, 0x9F, 0x00, 0xE4, 0xB8,
1952
  0x80, 0x00, 0xE4, 0xB8, 0xA8, 0x00, 0xE4, 0xB8, 0xB6, 0x00, 0xE4, 0xB8, 0xBF, 0x00, 0xE4, 0xB9,
1953
  0x99, 0x00, 0xE4, 0xBA, 0x85, 0x00, 0xE4, 0xBA, 0x8C, 0x00, 0xE4, 0xBA, 0xA0, 0x00, 0xE4, 0xBA,
1954
  0xBA, 0x00, 0xE5, 0x84, 0xBF, 0x00, 0xE5, 0x85, 0xA5, 0x00, 0xE5, 0x85, 0xAB, 0x00, 0xE5, 0x86,
1955
  0x82, 0x00, 0xE5, 0x86, 0x96, 0x00, 0xE5, 0x86, 0xAB, 0x00, 0xE5, 0x87, 0xA0, 0x00, 0xE5, 0x87,
1956
  0xB5, 0x00, 0xE5, 0x88, 0x80, 0x00, 0xE5, 0x8A, 0x9B, 0x00, 0xE5, 0x8B, 0xB9, 0x00, 0xE5, 0x8C,
1957
  0x95, 0x00, 0xE5, 0x8C, 0x9A, 0x00, 0xE5, 0x8C, 0xB8, 0x00, 0xE5, 0x8D, 0x81, 0x00, 0xE5, 0x8D,
1958
  0x9C, 0x00, 0xE5, 0x8D, 0xA9, 0x00, 0xE5, 0x8E, 0x82, 0x00, 0xE5, 0x8E, 0xB6, 0x00, 0xE5, 0x8F,
1959
  0x88, 0x00, 0xE5, 0x8F, 0xA3, 0x00, 0xE5, 0x9B, 0x97, 0x00, 0xE5, 0x9C, 0x9F, 0x00, 0xE5, 0xA3,
1960
  0xAB, 0x00, 0xE5, 0xA4, 0x82, 0x00, 0xE5, 0xA4, 0x8A, 0x00, 0xE5, 0xA4, 0x95, 0x00, 0xE5, 0xA4,
1961
  0xA7, 0x00, 0xE5, 0xA5, 0xB3, 0x00, 0xE5, 0xAD, 0x90, 0x00, 0xE5, 0xAE, 0x80, 0x00, 0xE5, 0xAF,
1962
  0xB8, 0x00, 0xE5, 0xB0, 0x8F, 0x00, 0xE5, 0xB0, 0xA2, 0x00, 0xE5, 0xB0, 0xB8, 0x00, 0xE5, 0xB1,
1963
  0xAE, 0x00, 0xE5, 0xB1, 0xB1, 0x00, 0xE5, 0xB7, 0x9B, 0x00, 0xE5, 0xB7, 0xA5, 0x00, 0xE5, 0xB7,
1964
  0xB1, 0x00, 0xE5, 0xB7, 0xBE, 0x00, 0xE5, 0xB9, 0xB2, 0x00, 0xE5, 0xB9, 0xBA, 0x00, 0xE5, 0xB9,
1965
  0xBF, 0x00, 0xE5, 0xBB, 0xB4, 0x00, 0xE5, 0xBB, 0xBE, 0x00, 0xE5, 0xBC, 0x8B, 0x00, 0xE5, 0xBC,
1966
  0x93, 0x00, 0xE5, 0xBD, 0x90, 0x00, 0xE5, 0xBD, 0xA1, 0x00, 0xE5, 0xBD, 0xB3, 0x00, 0xE5, 0xBF,
1967
  0x83, 0x00, 0xE6, 0x88, 0x88, 0x00, 0xE6, 0x88, 0xB6, 0x00, 0xE6, 0x89, 0x8B, 0x00, 0xE6, 0x94,
1968
  0xAF, 0x00, 0xE6, 0x94, 0xB4, 0x00, 0xE6, 0x96, 0x87, 0x00, 0xE6, 0x96, 0x97, 0x00, 0xE6, 0x96,
1969
  0xA4, 0x00, 0xE6, 0x96, 0xB9, 0x00, 0xE6, 0x97, 0xA0, 0x00, 0xE6, 0x97, 0xA5, 0x00, 0xE6, 0x9B,
1970
  0xB0, 0x00, 0xE6, 0x9C, 0x88, 0x00, 0xE6, 0x9C, 0xA8, 0x00, 0xE6, 0xAC, 0xA0, 0x00, 0xE6, 0xAD,
1971
  0xA2, 0x00, 0xE6, 0xAD, 0xB9, 0x00, 0xE6, 0xAE, 0xB3, 0x00, 0xE6, 0xAF, 0x8B, 0x00, 0xE6, 0xAF,
1972
  0x94, 0x00, 0xE6, 0xAF, 0x9B, 0x00, 0xE6, 0xB0, 0x8F, 0x00, 0xE6, 0xB0, 0x94, 0x00, 0xE6, 0xB0,
1973
  0xB4, 0x00, 0xE7, 0x81, 0xAB, 0x00, 0xE7, 0x88, 0xAA, 0x00, 0xE7, 0x88, 0xB6, 0x00, 0xE7, 0x88,
1974
  0xBB, 0x00, 0xE7, 0x88, 0xBF, 0x00, 0xE7, 0x89, 0x87, 0x00, 0xE7, 0x89, 0x99, 0x00, 0xE7, 0x89,
1975
  0x9B, 0x00, 0xE7, 0x8A, 0xAC, 0x00, 0xE7, 0x8E, 0x84, 0x00, 0xE7, 0x8E, 0x89, 0x00, 0xE7, 0x93,
1976
  0x9C, 0x00, 0xE7, 0x93, 0xA6, 0x00, 0xE7, 0x94, 0x98, 0x00, 0xE7, 0x94, 0x9F, 0x00, 0xE7, 0x94,
1977
  0xA8, 0x00, 0xE7, 0x94, 0xB0, 0x00, 0xE7, 0x96, 0x8B, 0x00, 0xE7, 0x96, 0x92, 0x00, 0xE7, 0x99,
1978
  0xB6, 0x00, 0xE7, 0x99, 0xBD, 0x00, 0xE7, 0x9A, 0xAE, 0x00, 0xE7, 0x9A, 0xBF, 0x00, 0xE7, 0x9B,
1979
  0xAE, 0x00, 0xE7, 0x9F, 0x9B, 0x00, 0xE7, 0x9F, 0xA2, 0x00, 0xE7, 0x9F, 0xB3, 0x00, 0xE7, 0xA4,
1980
  0xBA, 0x00, 0xE7, 0xA6, 0xB8, 0x00, 0xE7, 0xA6, 0xBE, 0x00, 0xE7, 0xA9, 0xB4, 0x00, 0xE7, 0xAB,
1981
  0x8B, 0x00, 0xE7, 0xAB, 0xB9, 0x00, 0xE7, 0xB1, 0xB3, 0x00, 0xE7, 0xB3, 0xB8, 0x00, 0xE7, 0xBC,
1982
  0xB6, 0x00, 0xE7, 0xBD, 0x91, 0x00, 0xE7, 0xBE, 0x8A, 0x00, 0xE7, 0xBE, 0xBD, 0x00, 0xE8, 0x80,
1983
  0x81, 0x00, 0xE8, 0x80, 0x8C, 0x00, 0xE8, 0x80, 0x92, 0x00, 0xE8, 0x80, 0xB3, 0x00, 0xE8, 0x81,
1984
  0xBF, 0x00, 0xE8, 0x82, 0x89, 0x00, 0xE8, 0x87, 0xA3, 0x00, 0xE8, 0x87, 0xAA, 0x00, 0xE8, 0x87,
1985
  0xB3, 0x00, 0xE8, 0x87, 0xBC, 0x00, 0xE8, 0x88, 0x8C, 0x00, 0xE8, 0x88, 0x9B, 0x00, 0xE8, 0x88,
1986
  0x9F, 0x00, 0xE8, 0x89, 0xAE, 0x00, 0xE8, 0x89, 0xB2, 0x00, 0xE8, 0x89, 0xB8, 0x00, 0xE8, 0x99,
1987
  0x8D, 0x00, 0xE8, 0x99, 0xAB, 0x00, 0xE8, 0xA1, 0x80, 0x00, 0xE8, 0xA1, 0x8C, 0x00, 0xE8, 0xA1,
1988
  0xA3, 0x00, 0xE8, 0xA5, 0xBE, 0x00, 0xE8, 0xA6, 0x8B, 0x00, 0xE8, 0xA7, 0x92, 0x00, 0xE8, 0xA8,
1989
  0x80, 0x00, 0xE8, 0xB0, 0xB7, 0x00, 0xE8, 0xB1, 0x86, 0x00, 0xE8, 0xB1, 0x95, 0x00, 0xE8, 0xB1,
1990
  0xB8, 0x00, 0xE8, 0xB2, 0x9D, 0x00, 0xE8, 0xB5, 0xA4, 0x00, 0xE8, 0xB5, 0xB0, 0x00, 0xE8, 0xB6,
1991
  0xB3, 0x00, 0xE8, 0xBA, 0xAB, 0x00, 0xE8, 0xBB, 0x8A, 0x00, 0xE8, 0xBE, 0x9B, 0x00, 0xE8, 0xBE,
1992
  0xB0, 0x00, 0xE8, 0xBE, 0xB5, 0x00, 0xE9, 0x82, 0x91, 0x00, 0xE9, 0x85, 0x89, 0x00, 0xE9, 0x87,
1993
  0x86, 0x00, 0xE9, 0x87, 0x8C, 0x00, 0xE9, 0x87, 0x91, 0x00, 0xE9, 0x95, 0xB7, 0x00, 0xE9, 0x96,
1994
  0x80, 0x00, 0xE9, 0x98, 0x9C, 0x00, 0xE9, 0x9A, 0xB6, 0x00, 0xE9, 0x9A, 0xB9, 0x00, 0xE9, 0x9B,
1995
  0xA8, 0x00, 0xE9, 0x9D, 0x91, 0x00, 0xE9, 0x9D, 0x9E, 0x00, 0xE9, 0x9D, 0xA2, 0x00, 0xE9, 0x9D,
1996
  0xA9, 0x00, 0xE9, 0x9F, 0x8B, 0x00, 0xE9, 0x9F, 0xAD, 0x00, 0xE9, 0x9F, 0xB3, 0x00, 0xE9, 0xA0,
1997
  0x81, 0x00, 0xE9, 0xA2, 0xA8, 0x00, 0xE9, 0xA3, 0x9B, 0x00, 0xE9, 0xA3, 0x9F, 0x00, 0xE9, 0xA6,
1998
  0x96, 0x00, 0xE9, 0xA6, 0x99, 0x00, 0xE9, 0xA6, 0xAC, 0x00, 0xE9, 0xAA, 0xA8, 0x00, 0xE9, 0xAB,
1999
  0x98, 0x00, 0xE9, 0xAB, 0x9F, 0x00, 0xE9, 0xAC, 0xA5, 0x00, 0xE9, 0xAC, 0xAF, 0x00, 0xE9, 0xAC,
2000
  0xB2, 0x00, 0xE9, 0xAC, 0xBC, 0x00, 0xE9, 0xAD, 0x9A, 0x00, 0xE9, 0xB3, 0xA5, 0x00, 0xE9, 0xB9,
2001
  0xB5, 0x00, 0xE9, 0xB9, 0xBF, 0x00, 0xE9, 0xBA, 0xA5, 0x00, 0xE9, 0xBA, 0xBB, 0x00, 0xE9, 0xBB,
2002
  0x83, 0x00, 0xE9, 0xBB, 0x8D, 0x00, 0xE9, 0xBB, 0x91, 0x00, 0xE9, 0xBB, 0xB9, 0x00, 0xE9, 0xBB,
2003
  0xBD, 0x00, 0xE9, 0xBC, 0x8E, 0x00, 0xE9, 0xBC, 0x93, 0x00, 0xE9, 0xBC, 0xA0, 0x00, 0xE9, 0xBC,
2004
  0xBB, 0x00, 0xE9, 0xBD, 0x8A, 0x00, 0xE9, 0xBD, 0x92, 0x00, 0xE9, 0xBE, 0x8D, 0x00, 0xE9, 0xBE,
2005
  0x9C, 0x00, 0xE9, 0xBE, 0xA0, 0x00, 0x2E, 0x00, 0xE3, 0x80, 0x92, 0x00, 0xE5, 0x8D, 0x84, 0x00,
2006
  0xE5, 0x8D, 0x85, 0x00, 0x20, 0xE3, 0x82, 0x99, 0x00, 0x20, 0xE3, 0x82, 0x9A, 0x00, 0xE3, 0x82,
2007
  0x88, 0xE3, 0x82, 0x8A, 0x00, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0x88, 0x00, 0xE1, 0x84, 0x80, 0x00,
2008
  0xE1, 0x84, 0x81, 0x00, 0xE1, 0x86, 0xAA, 0x00, 0xE1, 0x84, 0x82, 0x00, 0xE1, 0x86, 0xAC, 0x00,
2009
  0xE1, 0x86, 0xAD, 0x00, 0xE1, 0x84, 0x83, 0x00, 0xE1, 0x84, 0x84, 0x00, 0xE1, 0x84, 0x85, 0x00,
2010
  0xE1, 0x86, 0xB0, 0x00, 0xE1, 0x86, 0xB1, 0x00, 0xE1, 0x86, 0xB2, 0x00, 0xE1, 0x86, 0xB3, 0x00,
2011
  0xE1, 0x86, 0xB4, 0x00, 0xE1, 0x86, 0xB5, 0x00, 0xE1, 0x84, 0x9A, 0x00, 0xE1, 0x84, 0x86, 0x00,
2012
  0xE1, 0x84, 0x87, 0x00, 0xE1, 0x84, 0x88, 0x00, 0xE1, 0x84, 0xA1, 0x00, 0xE1, 0x84, 0x89, 0x00,
2013
  0xE1, 0x84, 0x8A, 0x00, 0xE1, 0x84, 0x8B, 0x00, 0xE1, 0x84, 0x8C, 0x00, 0xE1, 0x84, 0x8D, 0x00,
2014
  0xE1, 0x84, 0x8E, 0x00, 0xE1, 0x84, 0x8F, 0x00, 0xE1, 0x84, 0x90, 0x00, 0xE1, 0x84, 0x91, 0x00,
2015
  0xE1, 0x84, 0x92, 0x00, 0xE1, 0x85, 0xA1, 0x00, 0xE1, 0x85, 0xA2, 0x00, 0xE1, 0x85, 0xA3, 0x00,
2016
  0xE1, 0x85, 0xA4, 0x00, 0xE1, 0x85, 0xA5, 0x00, 0xE1, 0x85, 0xA6, 0x00, 0xE1, 0x85, 0xA7, 0x00,
2017
  0xE1, 0x85, 0xA8, 0x00, 0xE1, 0x85, 0xA9, 0x00, 0xE1, 0x85, 0xAA, 0x00, 0xE1, 0x85, 0xAB, 0x00,
2018
  0xE1, 0x85, 0xAC, 0x00, 0xE1, 0x85, 0xAD, 0x00, 0xE1, 0x85, 0xAE, 0x00, 0xE1, 0x85, 0xAF, 0x00,
2019
  0xE1, 0x85, 0xB0, 0x00, 0xE1, 0x85, 0xB1, 0x00, 0xE1, 0x85, 0xB2, 0x00, 0xE1, 0x85, 0xB3, 0x00,
2020
  0xE1, 0x85, 0xB4, 0x00, 0xE1, 0x85, 0xB5, 0x00, 0xE1, 0x84, 0x94, 0x00, 0xE1, 0x84, 0x95, 0x00,
2021
  0xE1, 0x87, 0x87, 0x00, 0xE1, 0x87, 0x88, 0x00, 0xE1, 0x87, 0x8C, 0x00, 0xE1, 0x87, 0x8E, 0x00,
2022
  0xE1, 0x87, 0x93, 0x00, 0xE1, 0x87, 0x97, 0x00, 0xE1, 0x87, 0x99, 0x00, 0xE1, 0x84, 0x9C, 0x00,
2023
  0xE1, 0x87, 0x9D, 0x00, 0xE1, 0x87, 0x9F, 0x00, 0xE1, 0x84, 0x9D, 0x00, 0xE1, 0x84, 0x9E, 0x00,
2024
  0xE1, 0x84, 0xA0, 0x00, 0xE1, 0x84, 0xA2, 0x00, 0xE1, 0x84, 0xA3, 0x00, 0xE1, 0x84, 0xA7, 0x00,
2025
  0xE1, 0x84, 0xA9, 0x00, 0xE1, 0x84, 0xAB, 0x00, 0xE1, 0x84, 0xAC, 0x00, 0xE1, 0x84, 0xAD, 0x00,
2026
  0xE1, 0x84, 0xAE, 0x00, 0xE1, 0x84, 0xAF, 0x00, 0xE1, 0x84, 0xB2, 0x00, 0xE1, 0x84, 0xB6, 0x00,
2027
  0xE1, 0x85, 0x80, 0x00, 0xE1, 0x85, 0x87, 0x00, 0xE1, 0x85, 0x8C, 0x00, 0xE1, 0x87, 0xB1, 0x00,
2028
  0xE1, 0x87, 0xB2, 0x00, 0xE1, 0x85, 0x97, 0x00, 0xE1, 0x85, 0x98, 0x00, 0xE1, 0x85, 0x99, 0x00,
2029
  0xE1, 0x86, 0x84, 0x00, 0xE1, 0x86, 0x85, 0x00, 0xE1, 0x86, 0x88, 0x00, 0xE1, 0x86, 0x91, 0x00,
2030
  0xE1, 0x86, 0x92, 0x00, 0xE1, 0x86, 0x94, 0x00, 0xE1, 0x86, 0x9E, 0x00, 0xE1, 0x86, 0xA1, 0x00,
2031
  0xE4, 0xB8, 0x89, 0x00, 0xE5, 0x9B, 0x9B, 0x00, 0xE4, 0xB8, 0x8A, 0x00, 0xE4, 0xB8, 0xAD, 0x00,
2032
  0xE4, 0xB8, 0x8B, 0x00, 0xE7, 0x94, 0xB2, 0x00, 0xE4, 0xB8, 0x99, 0x00, 0xE4, 0xB8, 0x81, 0x00,
2033
  0xE5, 0xA4, 0xA9, 0x00, 0xE5, 0x9C, 0xB0, 0x00, 0x28, 0xE1, 0x84, 0x80, 0x29, 0x00, 0x28, 0xE1,
2034
  0x84, 0x82, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x83, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x85, 0x29, 0x00,
2035
  0x28, 0xE1, 0x84, 0x86, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x87, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x89,
2036
  0x29, 0x00, 0x28, 0xE1, 0x84, 0x8B, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x8C, 0x29, 0x00, 0x28, 0xE1,
2037
  0x84, 0x8E, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x8F, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x90, 0x29, 0x00,
2038
  0x28, 0xE1, 0x84, 0x91, 0x29, 0x00, 0x28, 0xE1, 0x84, 0x92, 0x29, 0x00, 0x28, 0xEA, 0xB0, 0x80,
2039
  0x29, 0x00, 0x28, 0xEB, 0x82, 0x98, 0x29, 0x00, 0x28, 0xEB, 0x8B, 0xA4, 0x29, 0x00, 0x28, 0xEB,
2040
  0x9D, 0xBC, 0x29, 0x00, 0x28, 0xEB, 0xA7, 0x88, 0x29, 0x00, 0x28, 0xEB, 0xB0, 0x94, 0x29, 0x00,
2041
  0x28, 0xEC, 0x82, 0xAC, 0x29, 0x00, 0x28, 0xEC, 0x95, 0x84, 0x29, 0x00, 0x28, 0xEC, 0x9E, 0x90,
2042
  0x29, 0x00, 0x28, 0xEC, 0xB0, 0xA8, 0x29, 0x00, 0x28, 0xEC, 0xB9, 0xB4, 0x29, 0x00, 0x28, 0xED,
2043
  0x83, 0x80, 0x29, 0x00, 0x28, 0xED, 0x8C, 0x8C, 0x29, 0x00, 0x28, 0xED, 0x95, 0x98, 0x29, 0x00,
2044
  0x28, 0xEC, 0xA3, 0xBC, 0x29, 0x00, 0x28, 0xEC, 0x98, 0xA4, 0xEC, 0xA0, 0x84, 0x29, 0x00, 0x28,
2045
  0xEC, 0x98, 0xA4, 0xED, 0x9B, 0x84, 0x29, 0x00, 0x28, 0xE4, 0xB8, 0x80, 0x29, 0x00, 0x28, 0xE4,
2046
  0xBA, 0x8C, 0x29, 0x00, 0x28, 0xE4, 0xB8, 0x89, 0x29, 0x00, 0x28, 0xE5, 0x9B, 0x9B, 0x29, 0x00,
2047
  0x28, 0xE4, 0xBA, 0x94, 0x29, 0x00, 0x28, 0xE5, 0x85, 0xAD, 0x29, 0x00, 0x28, 0xE4, 0xB8, 0x83,
2048
  0x29, 0x00, 0x28, 0xE5, 0x85, 0xAB, 0x29, 0x00, 0x28, 0xE4, 0xB9, 0x9D, 0x29, 0x00, 0x28, 0xE5,
2049
  0x8D, 0x81, 0x29, 0x00, 0x28, 0xE6, 0x9C, 0x88, 0x29, 0x00, 0x28, 0xE7, 0x81, 0xAB, 0x29, 0x00,
2050
  0x28, 0xE6, 0xB0, 0xB4, 0x29, 0x00, 0x28, 0xE6, 0x9C, 0xA8, 0x29, 0x00, 0x28, 0xE9, 0x87, 0x91,
2051
  0x29, 0x00, 0x28, 0xE5, 0x9C, 0x9F, 0x29, 0x00, 0x28, 0xE6, 0x97, 0xA5, 0x29, 0x00, 0x28, 0xE6,
2052
  0xA0, 0xAA, 0x29, 0x00, 0x28, 0xE6, 0x9C, 0x89, 0x29, 0x00, 0x28, 0xE7, 0xA4, 0xBE, 0x29, 0x00,
2053
  0x28, 0xE5, 0x90, 0x8D, 0x29, 0x00, 0x28, 0xE7, 0x89, 0xB9, 0x29, 0x00, 0x28, 0xE8, 0xB2, 0xA1,
2054
  0x29, 0x00, 0x28, 0xE7, 0xA5, 0x9D, 0x29, 0x00, 0x28, 0xE5, 0x8A, 0xB4, 0x29, 0x00, 0x28, 0xE4,
2055
  0xBB, 0xA3, 0x29, 0x00, 0x28, 0xE5, 0x91, 0xBC, 0x29, 0x00, 0x28, 0xE5, 0xAD, 0xA6, 0x29, 0x00,
2056
  0x28, 0xE7, 0x9B, 0xA3, 0x29, 0x00, 0x28, 0xE4, 0xBC, 0x81, 0x29, 0x00, 0x28, 0xE8, 0xB3, 0x87,
2057
  0x29, 0x00, 0x28, 0xE5, 0x8D, 0x94, 0x29, 0x00, 0x28, 0xE7, 0xA5, 0xAD, 0x29, 0x00, 0x28, 0xE4,
2058
  0xBC, 0x91, 0x29, 0x00, 0x28, 0xE8, 0x87, 0xAA, 0x29, 0x00, 0x28, 0xE8, 0x87, 0xB3, 0x29, 0x00,
2059
  0xE5, 0x95, 0x8F, 0x00, 0xE5, 0xB9, 0xBC, 0x00, 0xE7, 0xAE, 0x8F, 0x00, 0x70, 0x74, 0x65, 0x00,
2060
  0x32, 0x31, 0x00, 0x32, 0x32, 0x00, 0x32, 0x33, 0x00, 0x32, 0x34, 0x00, 0x32, 0x35, 0x00, 0x32,
2061
  0x36, 0x00, 0x32, 0x37, 0x00, 0x32, 0x38, 0x00, 0x32, 0x39, 0x00, 0x33, 0x30, 0x00, 0x33, 0x31,
2062
  0x00, 0x33, 0x32, 0x00, 0x33, 0x33, 0x00, 0x33, 0x34, 0x00, 0x33, 0x35, 0x00, 0xEA, 0xB0, 0x80,
2063
  0x00, 0xEB, 0x82, 0x98, 0x00, 0xEB, 0x8B, 0xA4, 0x00, 0xEB, 0x9D, 0xBC, 0x00, 0xEB, 0xA7, 0x88,
2064
  0x00, 0xEB, 0xB0, 0x94, 0x00, 0xEC, 0x82, 0xAC, 0x00, 0xEC, 0x95, 0x84, 0x00, 0xEC, 0x9E, 0x90,
2065
  0x00, 0xEC, 0xB0, 0xA8, 0x00, 0xEC, 0xB9, 0xB4, 0x00, 0xED, 0x83, 0x80, 0x00, 0xED, 0x8C, 0x8C,
2066
  0x00, 0xED, 0x95, 0x98, 0x00, 0xEC, 0xB0, 0xB8, 0xEA, 0xB3, 0xA0, 0x00, 0xEC, 0xA3, 0xBC, 0xEC,
2067
  0x9D, 0x98, 0x00, 0xEC, 0x9A, 0xB0, 0x00, 0xE4, 0xBA, 0x94, 0x00, 0xE5, 0x85, 0xAD, 0x00, 0xE4,
2068
  0xB8, 0x83, 0x00, 0xE4, 0xB9, 0x9D, 0x00, 0xE6, 0xA0, 0xAA, 0x00, 0xE6, 0x9C, 0x89, 0x00, 0xE7,
2069
  0xA4, 0xBE, 0x00, 0xE5, 0x90, 0x8D, 0x00, 0xE7, 0x89, 0xB9, 0x00, 0xE8, 0xB2, 0xA1, 0x00, 0xE7,
2070
  0xA5, 0x9D, 0x00, 0xE5, 0x8A, 0xB4, 0x00, 0xE7, 0xA7, 0x98, 0x00, 0xE7, 0x94, 0xB7, 0x00, 0xE9,
2071
  0x81, 0xA9, 0x00, 0xE5, 0x84, 0xAA, 0x00, 0xE5, 0x8D, 0xB0, 0x00, 0xE6, 0xB3, 0xA8, 0x00, 0xE9,
2072
  0xA0, 0x85, 0x00, 0xE4, 0xBC, 0x91, 0x00, 0xE5, 0x86, 0x99, 0x00, 0xE6, 0xAD, 0xA3, 0x00, 0xE5,
2073
  0xB7, 0xA6, 0x00, 0xE5, 0x8F, 0xB3, 0x00, 0xE5, 0x8C, 0xBB, 0x00, 0xE5, 0xAE, 0x97, 0x00, 0xE5,
2074
  0xAD, 0xA6, 0x00, 0xE7, 0x9B, 0xA3, 0x00, 0xE4, 0xBC, 0x81, 0x00, 0xE8, 0xB3, 0x87, 0x00, 0xE5,
2075
  0x8D, 0x94, 0x00, 0xE5, 0xA4, 0x9C, 0x00, 0x33, 0x36, 0x00, 0x33, 0x37, 0x00, 0x33, 0x38, 0x00,
2076
  0x33, 0x39, 0x00, 0x34, 0x30, 0x00, 0x34, 0x31, 0x00, 0x34, 0x32, 0x00, 0x34, 0x33, 0x00, 0x34,
2077
  0x34, 0x00, 0x34, 0x35, 0x00, 0x34, 0x36, 0x00, 0x34, 0x37, 0x00, 0x34, 0x38, 0x00, 0x34, 0x39,
2078
  0x00, 0x35, 0x30, 0x00, 0x31, 0xE6, 0x9C, 0x88, 0x00, 0x32, 0xE6, 0x9C, 0x88, 0x00, 0x33, 0xE6,
2079
  0x9C, 0x88, 0x00, 0x34, 0xE6, 0x9C, 0x88, 0x00, 0x35, 0xE6, 0x9C, 0x88, 0x00, 0x36, 0xE6, 0x9C,
2080
  0x88, 0x00, 0x37, 0xE6, 0x9C, 0x88, 0x00, 0x38, 0xE6, 0x9C, 0x88, 0x00, 0x39, 0xE6, 0x9C, 0x88,
2081
  0x00, 0x31, 0x30, 0xE6, 0x9C, 0x88, 0x00, 0x31, 0x31, 0xE6, 0x9C, 0x88, 0x00, 0x31, 0x32, 0xE6,
2082
  0x9C, 0x88, 0x00, 0x68, 0x67, 0x00, 0x65, 0x72, 0x67, 0x00, 0x65, 0x76, 0x00, 0x6C, 0x74, 0x64,
2083
  0x00, 0xE3, 0x82, 0xA2, 0x00, 0xE3, 0x82, 0xA4, 0x00, 0xE3, 0x82, 0xA6, 0x00, 0xE3, 0x82, 0xA8,
2084
  0x00, 0xE3, 0x82, 0xAA, 0x00, 0xE3, 0x82, 0xAB, 0x00, 0xE3, 0x82, 0xAD, 0x00, 0xE3, 0x82, 0xAF,
2085
  0x00, 0xE3, 0x82, 0xB1, 0x00, 0xE3, 0x82, 0xB3, 0x00, 0xE3, 0x82, 0xB5, 0x00, 0xE3, 0x82, 0xB7,
2086
  0x00, 0xE3, 0x82, 0xB9, 0x00, 0xE3, 0x82, 0xBB, 0x00, 0xE3, 0x82, 0xBD, 0x00, 0xE3, 0x82, 0xBF,
2087
  0x00, 0xE3, 0x83, 0x81, 0x00, 0xE3, 0x83, 0x84, 0x00, 0xE3, 0x83, 0x86, 0x00, 0xE3, 0x83, 0x88,
2088
  0x00, 0xE3, 0x83, 0x8A, 0x00, 0xE3, 0x83, 0x8B, 0x00, 0xE3, 0x83, 0x8C, 0x00, 0xE3, 0x83, 0x8D,
2089
  0x00, 0xE3, 0x83, 0x8E, 0x00, 0xE3, 0x83, 0x8F, 0x00, 0xE3, 0x83, 0x92, 0x00, 0xE3, 0x83, 0x95,
2090
  0x00, 0xE3, 0x83, 0x98, 0x00, 0xE3, 0x83, 0x9B, 0x00, 0xE3, 0x83, 0x9E, 0x00, 0xE3, 0x83, 0x9F,
2091
  0x00, 0xE3, 0x83, 0xA0, 0x00, 0xE3, 0x83, 0xA1, 0x00, 0xE3, 0x83, 0xA2, 0x00, 0xE3, 0x83, 0xA4,
2092
  0x00, 0xE3, 0x83, 0xA6, 0x00, 0xE3, 0x83, 0xA8, 0x00, 0xE3, 0x83, 0xA9, 0x00, 0xE3, 0x83, 0xAA,
2093
  0x00, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0xAC, 0x00, 0xE3, 0x83, 0xAD, 0x00, 0xE3, 0x83, 0xAF,
2094
  0x00, 0xE3, 0x83, 0xB0, 0x00, 0xE3, 0x83, 0xB1, 0x00, 0xE3, 0x83, 0xB2, 0x00, 0xE4, 0xBB, 0xA4,
2095
  0xE5, 0x92, 0x8C, 0x00, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0x91, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88,
2096
  0x00, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA1, 0x00, 0xE3, 0x82,
2097
  0xA2, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x9A, 0xE3, 0x82, 0xA2, 0x00, 0xE3, 0x82, 0xA2, 0xE3, 0x83,
2098
  0xBC, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3, 0xE3, 0x82,
2099
  0xB0, 0x00, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x00, 0xE3, 0x82, 0xA6, 0xE3,
2100
  0x82, 0xA9, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x82, 0xA8, 0xE3, 0x82, 0xB9, 0xE3, 0x82, 0xAF, 0xE3,
2101
  0x83, 0xBC, 0xE3, 0x83, 0x89, 0x00, 0xE3, 0x82, 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
2102
  0x83, 0xBC, 0x00, 0xE3, 0x82, 0xAA, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB9, 0x00, 0xE3, 0x82, 0xAA,
2103
  0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x00, 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAA,
2104
  0x00, 0xE3, 0x82, 0xAB, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x82,
2105
  0xAB, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x00, 0xE3, 0x82, 0xAC, 0xE3, 0x83,
2106
  0xAD, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x82, 0xAC, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x9E, 0x00, 0xE3,
2107
  0x82, 0xAE, 0xE3, 0x82, 0xAC, 0x00, 0xE3, 0x82, 0xAE, 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xBC, 0x00,
2108
  0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x00, 0xE3, 0x82, 0xAE,
2109
  0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x80, 0xE3, 0x83, 0xBC, 0x00, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD,
2110
  0x00, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD, 0xE3, 0x82, 0xB0, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xA0,
2111
  0x00, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88,
2112
  0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3, 0x83, 0x83,
2113
  0xE3, 0x83, 0x88, 0x00, 0xE3, 0x82, 0xB0, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x00, 0xE3, 0x82,
2114
  0xB0, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x82,
2115
  0xAF, 0xE3, 0x83, 0xAB, 0xE3, 0x82, 0xBC, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x00, 0xE3, 0x82,
2116
  0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x8D, 0x00, 0xE3, 0x82, 0xB1, 0xE3, 0x83,
2117
  0xBC, 0xE3, 0x82, 0xB9, 0x00, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x8A, 0x00, 0xE3,
2118
  0x82, 0xB3, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x9D, 0x00, 0xE3, 0x82, 0xB5, 0xE3, 0x82, 0xA4, 0xE3,
2119
  0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x82, 0xB5, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3,
2120
  0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x00, 0xE3, 0x82, 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xB3, 0xE3,
2121
  0x82, 0xB0, 0x00, 0xE3, 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x00, 0xE3, 0x82, 0xBB,
2122
  0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x83, 0x80, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xB9,
2123
  0x00, 0xE3, 0x83, 0x87, 0xE3, 0x82, 0xB7, 0x00, 0xE3, 0x83, 0x89, 0xE3, 0x83, 0xAB, 0x00, 0xE3,
2124
  0x83, 0x88, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0x8A, 0xE3, 0x83, 0x8E, 0x00, 0xE3, 0x83, 0x8E,
2125
  0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x84,
2126
  0x00, 0xE3, 0x83, 0x91, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
2127
  0x00, 0xE3, 0x83, 0x91, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x84, 0x00, 0xE3, 0x83, 0x90, 0xE3, 0x83,
2128
  0xBC, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0x94, 0xE3, 0x82, 0xA2, 0xE3, 0x82,
2129
  0xB9, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0x94, 0xE3, 0x82, 0xAF, 0xE3, 0x83,
2130
  0xAB, 0x00, 0xE3, 0x83, 0x94, 0xE3, 0x82, 0xB3, 0x00, 0xE3, 0x83, 0x93, 0xE3, 0x83, 0xAB, 0x00,
2131
  0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x89, 0x00,
2132
  0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x83, 0x96,
2133
  0xE3, 0x83, 0x83, 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0x95,
2134
  0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF,
2135
  0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0x9A, 0xE3, 0x82, 0xBD, 0x00, 0xE3, 0x83,
2136
  0x9A, 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0x92, 0x00, 0xE3, 0x83, 0x98, 0xE3, 0x83, 0xAB, 0xE3, 0x83,
2137
  0x84, 0x00, 0xE3, 0x83, 0x9A, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB9, 0x00, 0xE3, 0x83, 0x9A, 0xE3,
2138
  0x83, 0xBC, 0xE3, 0x82, 0xB8, 0x00, 0xE3, 0x83, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBF, 0x00,
2139
  0xE3, 0x83, 0x9D, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x83, 0x9C,
2140
  0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88, 0x00, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83,
2141
  0x9D, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x89, 0x00, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
2142
  0xAB, 0x00, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0x9E, 0xE3,
2143
  0x82, 0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0x00, 0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3,
2144
  0x83, 0xAB, 0x00, 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x8F, 0x00, 0xE3, 0x83, 0x9E,
2145
  0xE3, 0x83, 0xAB, 0xE3, 0x82, 0xAF, 0x00, 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7,
2146
  0xE3, 0x83, 0xA7, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0x9F, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD,
2147
  0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0x00, 0xE3, 0x83, 0x9F, 0xE3, 0x83,
2148
  0xAA, 0xE3, 0x83, 0x90, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0xA1, 0xE3, 0x82,
2149
  0xAC, 0x00, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xB3, 0x00, 0xE3,
2150
  0x83, 0xA1, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0xA4, 0xE3,
2151
  0x83, 0xBC, 0xE3, 0x83, 0x89, 0x00, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x00,
2152
  0xE3, 0x83, 0xA6, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x83,
2153
  0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xA9, 0x00, 0xE3, 0x83,
2154
  0xAB, 0xE3, 0x83, 0x94, 0xE3, 0x83, 0xBC, 0x00, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
2155
  0x96, 0xE3, 0x83, 0xAB, 0x00, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xA0, 0x00, 0xE3, 0x83, 0xAC, 0xE3,
2156
  0x83, 0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB2, 0xE3, 0x83, 0xB3, 0x00, 0xE3, 0x83, 0xAF, 0xE3,
2157
  0x83, 0x83, 0xE3, 0x83, 0x88, 0x00, 0x30, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0xE7, 0x82, 0xB9, 0x00,
2158
  0x32, 0xE7, 0x82, 0xB9, 0x00, 0x33, 0xE7, 0x82, 0xB9, 0x00, 0x34, 0xE7, 0x82, 0xB9, 0x00, 0x35,
2159
  0xE7, 0x82, 0xB9, 0x00, 0x36, 0xE7, 0x82, 0xB9, 0x00, 0x37, 0xE7, 0x82, 0xB9, 0x00, 0x38, 0xE7,
2160
  0x82, 0xB9, 0x00, 0x39, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x30, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x31,
2161
  0xE7, 0x82, 0xB9, 0x00, 0x31, 0x32, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x33, 0xE7, 0x82, 0xB9, 0x00,
2162
  0x31, 0x34, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x35, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x36, 0xE7, 0x82,
2163
  0xB9, 0x00, 0x31, 0x37, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x38, 0xE7, 0x82, 0xB9, 0x00, 0x31, 0x39,
2164
  0xE7, 0x82, 0xB9, 0x00, 0x32, 0x30, 0xE7, 0x82, 0xB9, 0x00, 0x32, 0x31, 0xE7, 0x82, 0xB9, 0x00,
2165
  0x32, 0x32, 0xE7, 0x82, 0xB9, 0x00, 0x32, 0x33, 0xE7, 0x82, 0xB9, 0x00, 0x32, 0x34, 0xE7, 0x82,
2166
  0xB9, 0x00, 0x68, 0x70, 0x61, 0x00, 0x64, 0x61, 0x00, 0x61, 0x75, 0x00, 0x62, 0x61, 0x72, 0x00,
2167
  0x6F, 0x76, 0x00, 0x70, 0x63, 0x00, 0x64, 0x6D, 0x00, 0x64, 0x6D, 0x32, 0x00, 0x64, 0x6D, 0x33,
2168
  0x00, 0x69, 0x75, 0x00, 0xE5, 0xB9, 0xB3, 0xE6, 0x88, 0x90, 0x00, 0xE6, 0x98, 0xAD, 0xE5, 0x92,
2169
  0x8C, 0x00, 0xE5, 0xA4, 0xA7, 0xE6, 0xAD, 0xA3, 0x00, 0xE6, 0x98, 0x8E, 0xE6, 0xB2, 0xBB, 0x00,
2170
  0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F, 0xE4, 0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x00, 0x70, 0x61, 0x00,
2171
  0x6E, 0x61, 0x00, 0xCE, 0xBC, 0x61, 0x00, 0x6D, 0x61, 0x00, 0x6B, 0x61, 0x00, 0x6B, 0x62, 0x00,
2172
  0x6D, 0x62, 0x00, 0x67, 0x62, 0x00, 0x63, 0x61, 0x6C, 0x00, 0x6B, 0x63, 0x61, 0x6C, 0x00, 0x70,
2173
  0x66, 0x00, 0x6E, 0x66, 0x00, 0xCE, 0xBC, 0x66, 0x00, 0xCE, 0xBC, 0x67, 0x00, 0x6D, 0x67, 0x00,
2174
  0x6B, 0x67, 0x00, 0x68, 0x7A, 0x00, 0x6B, 0x68, 0x7A, 0x00, 0x6D, 0x68, 0x7A, 0x00, 0x67, 0x68,
2175
  0x7A, 0x00, 0x74, 0x68, 0x7A, 0x00, 0xCE, 0xBC, 0x6C, 0x00, 0x6D, 0x6C, 0x00, 0x64, 0x6C, 0x00,
2176
  0x6B, 0x6C, 0x00, 0x66, 0x6D, 0x00, 0x6E, 0x6D, 0x00, 0xCE, 0xBC, 0x6D, 0x00, 0x6D, 0x6D, 0x00,
2177
  0x63, 0x6D, 0x00, 0x6B, 0x6D, 0x00, 0x6D, 0x6D, 0x32, 0x00, 0x63, 0x6D, 0x32, 0x00, 0x6D, 0x32,
2178
  0x00, 0x6B, 0x6D, 0x32, 0x00, 0x6D, 0x6D, 0x33, 0x00, 0x63, 0x6D, 0x33, 0x00, 0x6D, 0x33, 0x00,
2179
  0x6B, 0x6D, 0x33, 0x00, 0x6D, 0xE2, 0x88, 0x95, 0x73, 0x00, 0x6D, 0xE2, 0x88, 0x95, 0x73, 0x32,
2180
  0x00, 0x6B, 0x70, 0x61, 0x00, 0x6D, 0x70, 0x61, 0x00, 0x67, 0x70, 0x61, 0x00, 0x72, 0x61, 0x64,
2181
  0x00, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73, 0x00, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73,
2182
  0x32, 0x00, 0x70, 0x73, 0x00, 0x6E, 0x73, 0x00, 0xCE, 0xBC, 0x73, 0x00, 0x6D, 0x73, 0x00, 0x70,
2183
  0x76, 0x00, 0x6E, 0x76, 0x00, 0xCE, 0xBC, 0x76, 0x00, 0x6D, 0x76, 0x00, 0x6B, 0x76, 0x00, 0x70,
2184
  0x77, 0x00, 0x6E, 0x77, 0x00, 0xCE, 0xBC, 0x77, 0x00, 0x6D, 0x77, 0x00, 0x6B, 0x77, 0x00, 0x6B,
2185
  0xCF, 0x89, 0x00, 0x6D, 0xCF, 0x89, 0x00, 0x62, 0x71, 0x00, 0x63, 0x63, 0x00, 0x63, 0x64, 0x00,
2186
  0x63, 0xE2, 0x88, 0x95, 0x6B, 0x67, 0x00, 0x64, 0x62, 0x00, 0x67, 0x79, 0x00, 0x68, 0x61, 0x00,
2187
  0x68, 0x70, 0x00, 0x69, 0x6E, 0x00, 0x6B, 0x6B, 0x00, 0x6B, 0x74, 0x00, 0x6C, 0x6D, 0x00, 0x6C,
2188
  0x6E, 0x00, 0x6C, 0x6F, 0x67, 0x00, 0x6C, 0x78, 0x00, 0x6D, 0x69, 0x6C, 0x00, 0x6D, 0x6F, 0x6C,
2189
  0x00, 0x70, 0x68, 0x00, 0x70, 0x70, 0x6D, 0x00, 0x70, 0x72, 0x00, 0x73, 0x72, 0x00, 0x73, 0x76,
2190
  0x00, 0x77, 0x62, 0x00, 0x76, 0xE2, 0x88, 0x95, 0x6D, 0x00, 0x61, 0xE2, 0x88, 0x95, 0x6D, 0x00,
2191
  0x31, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0xE6, 0x97, 0xA5, 0x00, 0x33, 0xE6, 0x97, 0xA5, 0x00, 0x34,
2192
  0xE6, 0x97, 0xA5, 0x00, 0x35, 0xE6, 0x97, 0xA5, 0x00, 0x36, 0xE6, 0x97, 0xA5, 0x00, 0x37, 0xE6,
2193
  0x97, 0xA5, 0x00, 0x38, 0xE6, 0x97, 0xA5, 0x00, 0x39, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x30, 0xE6,
2194
  0x97, 0xA5, 0x00, 0x31, 0x31, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x32, 0xE6, 0x97, 0xA5, 0x00, 0x31,
2195
  0x33, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x34, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x35, 0xE6, 0x97, 0xA5,
2196
  0x00, 0x31, 0x36, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x37, 0xE6, 0x97, 0xA5, 0x00, 0x31, 0x38, 0xE6,
2197
  0x97, 0xA5, 0x00, 0x31, 0x39, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x30, 0xE6, 0x97, 0xA5, 0x00, 0x32,
2198
  0x31, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x32, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x33, 0xE6, 0x97, 0xA5,
2199
  0x00, 0x32, 0x34, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x35, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x36, 0xE6,
2200
  0x97, 0xA5, 0x00, 0x32, 0x37, 0xE6, 0x97, 0xA5, 0x00, 0x32, 0x38, 0xE6, 0x97, 0xA5, 0x00, 0x32,
2201
  0x39, 0xE6, 0x97, 0xA5, 0x00, 0x33, 0x30, 0xE6, 0x97, 0xA5, 0x00, 0x33, 0x31, 0xE6, 0x97, 0xA5,
2202
  0x00, 0x67, 0x61, 0x6C, 0x00, 0xEA, 0x99, 0x81, 0x00, 0xEA, 0x99, 0x83, 0x00, 0xEA, 0x99, 0x85,
2203
  0x00, 0xEA, 0x99, 0x87, 0x00, 0xEA, 0x99, 0x89, 0x00, 0xEA, 0x99, 0x8D, 0x00, 0xEA, 0x99, 0x8F,
2204
  0x00, 0xEA, 0x99, 0x91, 0x00, 0xEA, 0x99, 0x93, 0x00, 0xEA, 0x99, 0x95, 0x00, 0xEA, 0x99, 0x97,
2205
  0x00, 0xEA, 0x99, 0x99, 0x00, 0xEA, 0x99, 0x9B, 0x00, 0xEA, 0x99, 0x9D, 0x00, 0xEA, 0x99, 0x9F,
2206
  0x00, 0xEA, 0x99, 0xA1, 0x00, 0xEA, 0x99, 0xA3, 0x00, 0xEA, 0x99, 0xA5, 0x00, 0xEA, 0x99, 0xA7,
2207
  0x00, 0xEA, 0x99, 0xA9, 0x00, 0xEA, 0x99, 0xAB, 0x00, 0xEA, 0x99, 0xAD, 0x00, 0xEA, 0x9A, 0x81,
2208
  0x00, 0xEA, 0x9A, 0x83, 0x00, 0xEA, 0x9A, 0x85, 0x00, 0xEA, 0x9A, 0x87, 0x00, 0xEA, 0x9A, 0x89,
2209
  0x00, 0xEA, 0x9A, 0x8B, 0x00, 0xEA, 0x9A, 0x8D, 0x00, 0xEA, 0x9A, 0x8F, 0x00, 0xEA, 0x9A, 0x91,
2210
  0x00, 0xEA, 0x9A, 0x93, 0x00, 0xEA, 0x9A, 0x95, 0x00, 0xEA, 0x9A, 0x97, 0x00, 0xEA, 0x9A, 0x99,
2211
  0x00, 0xEA, 0x9A, 0x9B, 0x00, 0xEA, 0x9C, 0xA3, 0x00, 0xEA, 0x9C, 0xA5, 0x00, 0xEA, 0x9C, 0xA7,
2212
  0x00, 0xEA, 0x9C, 0xA9, 0x00, 0xEA, 0x9C, 0xAB, 0x00, 0xEA, 0x9C, 0xAD, 0x00, 0xEA, 0x9C, 0xAF,
2213
  0x00, 0xEA, 0x9C, 0xB3, 0x00, 0xEA, 0x9C, 0xB5, 0x00, 0xEA, 0x9C, 0xB7, 0x00, 0xEA, 0x9C, 0xB9,
2214
  0x00, 0xEA, 0x9C, 0xBB, 0x00, 0xEA, 0x9C, 0xBD, 0x00, 0xEA, 0x9C, 0xBF, 0x00, 0xEA, 0x9D, 0x81,
2215
  0x00, 0xEA, 0x9D, 0x83, 0x00, 0xEA, 0x9D, 0x85, 0x00, 0xEA, 0x9D, 0x87, 0x00, 0xEA, 0x9D, 0x89,
2216
  0x00, 0xEA, 0x9D, 0x8B, 0x00, 0xEA, 0x9D, 0x8D, 0x00, 0xEA, 0x9D, 0x8F, 0x00, 0xEA, 0x9D, 0x91,
2217
  0x00, 0xEA, 0x9D, 0x93, 0x00, 0xEA, 0x9D, 0x95, 0x00, 0xEA, 0x9D, 0x97, 0x00, 0xEA, 0x9D, 0x99,
2218
  0x00, 0xEA, 0x9D, 0x9B, 0x00, 0xEA, 0x9D, 0x9D, 0x00, 0xEA, 0x9D, 0x9F, 0x00, 0xEA, 0x9D, 0xA1,
2219
  0x00, 0xEA, 0x9D, 0xA3, 0x00, 0xEA, 0x9D, 0xA5, 0x00, 0xEA, 0x9D, 0xA7, 0x00, 0xEA, 0x9D, 0xA9,
2220
  0x00, 0xEA, 0x9D, 0xAB, 0x00, 0xEA, 0x9D, 0xAD, 0x00, 0xEA, 0x9D, 0xAF, 0x00, 0xEA, 0x9D, 0xBA,
2221
  0x00, 0xEA, 0x9D, 0xBC, 0x00, 0xE1, 0xB5, 0xB9, 0x00, 0xEA, 0x9D, 0xBF, 0x00, 0xEA, 0x9E, 0x81,
2222
  0x00, 0xEA, 0x9E, 0x83, 0x00, 0xEA, 0x9E, 0x85, 0x00, 0xEA, 0x9E, 0x87, 0x00, 0xEA, 0x9E, 0x8C,
2223
  0x00, 0xEA, 0x9E, 0x91, 0x00, 0xEA, 0x9E, 0x93, 0x00, 0xEA, 0x9E, 0x97, 0x00, 0xEA, 0x9E, 0x99,
2224
  0x00, 0xEA, 0x9E, 0x9B, 0x00, 0xEA, 0x9E, 0x9D, 0x00, 0xEA, 0x9E, 0x9F, 0x00, 0xEA, 0x9E, 0xA1,
2225
  0x00, 0xEA, 0x9E, 0xA3, 0x00, 0xEA, 0x9E, 0xA5, 0x00, 0xEA, 0x9E, 0xA7, 0x00, 0xEA, 0x9E, 0xA9,
2226
  0x00, 0xC9, 0xAC, 0x00, 0xCA, 0x9E, 0x00, 0xCA, 0x87, 0x00, 0xEA, 0xAD, 0x93, 0x00, 0xEA, 0x9E,
2227
  0xB5, 0x00, 0xEA, 0x9E, 0xB7, 0x00, 0xEA, 0x9E, 0xB9, 0x00, 0xEA, 0x9E, 0xBB, 0x00, 0xEA, 0x9E,
2228
  0xBD, 0x00, 0xEA, 0x9E, 0xBF, 0x00, 0xEA, 0x9F, 0x81, 0x00, 0xEA, 0x9F, 0x83, 0x00, 0xEA, 0x9E,
2229
  0x94, 0x00, 0xE1, 0xB6, 0x8E, 0x00, 0xEA, 0x9F, 0x88, 0x00, 0xEA, 0x9F, 0x8A, 0x00, 0xC9, 0xA4,
2230
  0x00, 0xEA, 0x9F, 0x8D, 0x00, 0xEA, 0x9F, 0x8F, 0x00, 0xEA, 0x9F, 0x91, 0x00, 0xEA, 0x9F, 0x93,
2231
  0x00, 0xEA, 0x9F, 0x95, 0x00, 0xEA, 0x9F, 0x97, 0x00, 0xEA, 0x9F, 0x99, 0x00, 0xEA, 0x9F, 0x9B,
2232
  0x00, 0xC6, 0x9B, 0x00, 0xEA, 0x9F, 0xB6, 0x00, 0xEA, 0xAC, 0xB7, 0x00, 0xEA, 0xAD, 0x92, 0x00,
2233
  0xCA, 0x8D, 0x00, 0xE1, 0x8E, 0xA0, 0x00, 0xE1, 0x8E, 0xA1, 0x00, 0xE1, 0x8E, 0xA2, 0x00, 0xE1,
2234
  0x8E, 0xA3, 0x00, 0xE1, 0x8E, 0xA4, 0x00, 0xE1, 0x8E, 0xA5, 0x00, 0xE1, 0x8E, 0xA6, 0x00, 0xE1,
2235
  0x8E, 0xA7, 0x00, 0xE1, 0x8E, 0xA8, 0x00, 0xE1, 0x8E, 0xA9, 0x00, 0xE1, 0x8E, 0xAA, 0x00, 0xE1,
2236
  0x8E, 0xAB, 0x00, 0xE1, 0x8E, 0xAC, 0x00, 0xE1, 0x8E, 0xAD, 0x00, 0xE1, 0x8E, 0xAE, 0x00, 0xE1,
2237
  0x8E, 0xAF, 0x00, 0xE1, 0x8E, 0xB0, 0x00, 0xE1, 0x8E, 0xB1, 0x00, 0xE1, 0x8E, 0xB2, 0x00, 0xE1,
2238
  0x8E, 0xB3, 0x00, 0xE1, 0x8E, 0xB4, 0x00, 0xE1, 0x8E, 0xB5, 0x00, 0xE1, 0x8E, 0xB6, 0x00, 0xE1,
2239
  0x8E, 0xB7, 0x00, 0xE1, 0x8E, 0xB8, 0x00, 0xE1, 0x8E, 0xB9, 0x00, 0xE1, 0x8E, 0xBA, 0x00, 0xE1,
2240
  0x8E, 0xBB, 0x00, 0xE1, 0x8E, 0xBC, 0x00, 0xE1, 0x8E, 0xBD, 0x00, 0xE1, 0x8E, 0xBE, 0x00, 0xE1,
2241
  0x8E, 0xBF, 0x00, 0xE1, 0x8F, 0x80, 0x00, 0xE1, 0x8F, 0x81, 0x00, 0xE1, 0x8F, 0x82, 0x00, 0xE1,
2242
  0x8F, 0x83, 0x00, 0xE1, 0x8F, 0x84, 0x00, 0xE1, 0x8F, 0x85, 0x00, 0xE1, 0x8F, 0x86, 0x00, 0xE1,
2243
  0x8F, 0x87, 0x00, 0xE1, 0x8F, 0x88, 0x00, 0xE1, 0x8F, 0x89, 0x00, 0xE1, 0x8F, 0x8A, 0x00, 0xE1,
2244
  0x8F, 0x8B, 0x00, 0xE1, 0x8F, 0x8C, 0x00, 0xE1, 0x8F, 0x8D, 0x00, 0xE1, 0x8F, 0x8E, 0x00, 0xE1,
2245
  0x8F, 0x8F, 0x00, 0xE1, 0x8F, 0x90, 0x00, 0xE1, 0x8F, 0x91, 0x00, 0xE1, 0x8F, 0x92, 0x00, 0xE1,
2246
  0x8F, 0x93, 0x00, 0xE1, 0x8F, 0x94, 0x00, 0xE1, 0x8F, 0x95, 0x00, 0xE1, 0x8F, 0x96, 0x00, 0xE1,
2247
  0x8F, 0x97, 0x00, 0xE1, 0x8F, 0x98, 0x00, 0xE1, 0x8F, 0x99, 0x00, 0xE1, 0x8F, 0x9A, 0x00, 0xE1,
2248
  0x8F, 0x9B, 0x00, 0xE1, 0x8F, 0x9C, 0x00, 0xE1, 0x8F, 0x9D, 0x00, 0xE1, 0x8F, 0x9E, 0x00, 0xE1,
2249
  0x8F, 0x9F, 0x00, 0xE1, 0x8F, 0xA0, 0x00, 0xE1, 0x8F, 0xA1, 0x00, 0xE1, 0x8F, 0xA2, 0x00, 0xE1,
2250
  0x8F, 0xA3, 0x00, 0xE1, 0x8F, 0xA4, 0x00, 0xE1, 0x8F, 0xA5, 0x00, 0xE1, 0x8F, 0xA6, 0x00, 0xE1,
2251
  0x8F, 0xA7, 0x00, 0xE1, 0x8F, 0xA8, 0x00, 0xE1, 0x8F, 0xA9, 0x00, 0xE1, 0x8F, 0xAA, 0x00, 0xE1,
2252
  0x8F, 0xAB, 0x00, 0xE1, 0x8F, 0xAC, 0x00, 0xE1, 0x8F, 0xAD, 0x00, 0xE1, 0x8F, 0xAE, 0x00, 0xE1,
2253
  0x8F, 0xAF, 0x00, 0xE8, 0xB1, 0x88, 0x00, 0xE6, 0x9B, 0xB4, 0x00, 0xE8, 0xB3, 0x88, 0x00, 0xE6,
2254
  0xBB, 0x91, 0x00, 0xE4, 0xB8, 0xB2, 0x00, 0xE5, 0x8F, 0xA5, 0x00, 0xE5, 0xA5, 0x91, 0x00, 0xE5,
2255
  0x96, 0x87, 0x00, 0xE5, 0xA5, 0x88, 0x00, 0xE6, 0x87, 0xB6, 0x00, 0xE7, 0x99, 0xA9, 0x00, 0xE7,
2256
  0xBE, 0x85, 0x00, 0xE8, 0x98, 0xBF, 0x00, 0xE8, 0x9E, 0xBA, 0x00, 0xE8, 0xA3, 0xB8, 0x00, 0xE9,
2257
  0x82, 0x8F, 0x00, 0xE6, 0xA8, 0x82, 0x00, 0xE6, 0xB4, 0x9B, 0x00, 0xE7, 0x83, 0x99, 0x00, 0xE7,
2258
  0x8F, 0x9E, 0x00, 0xE8, 0x90, 0xBD, 0x00, 0xE9, 0x85, 0xAA, 0x00, 0xE9, 0xA7, 0xB1, 0x00, 0xE4,
2259
  0xBA, 0x82, 0x00, 0xE5, 0x8D, 0xB5, 0x00, 0xE6, 0xAC, 0x84, 0x00, 0xE7, 0x88, 0x9B, 0x00, 0xE8,
2260
  0x98, 0xAD, 0x00, 0xE9, 0xB8, 0x9E, 0x00, 0xE5, 0xB5, 0x90, 0x00, 0xE6, 0xBF, 0xAB, 0x00, 0xE8,
2261
  0x97, 0x8D, 0x00, 0xE8, 0xA5, 0xA4, 0x00, 0xE6, 0x8B, 0x89, 0x00, 0xE8, 0x87, 0x98, 0x00, 0xE8,
2262
  0xA0, 0x9F, 0x00, 0xE5, 0xBB, 0x8A, 0x00, 0xE6, 0x9C, 0x97, 0x00, 0xE6, 0xB5, 0xAA, 0x00, 0xE7,
2263
  0x8B, 0xBC, 0x00, 0xE9, 0x83, 0x8E, 0x00, 0xE4, 0xBE, 0x86, 0x00, 0xE5, 0x86, 0xB7, 0x00, 0xE5,
2264
  0x8B, 0x9E, 0x00, 0xE6, 0x93, 0x84, 0x00, 0xE6, 0xAB, 0x93, 0x00, 0xE7, 0x88, 0x90, 0x00, 0xE7,
2265
  0x9B, 0xA7, 0x00, 0xE8, 0x98, 0x86, 0x00, 0xE8, 0x99, 0x9C, 0x00, 0xE8, 0xB7, 0xAF, 0x00, 0xE9,
2266
  0x9C, 0xB2, 0x00, 0xE9, 0xAD, 0xAF, 0x00, 0xE9, 0xB7, 0xBA, 0x00, 0xE7, 0xA2, 0x8C, 0x00, 0xE7,
2267
  0xA5, 0xBF, 0x00, 0xE7, 0xB6, 0xA0, 0x00, 0xE8, 0x8F, 0x89, 0x00, 0xE9, 0x8C, 0x84, 0x00, 0xE8,
2268
  0xAB, 0x96, 0x00, 0xE5, 0xA3, 0x9F, 0x00, 0xE5, 0xBC, 0x84, 0x00, 0xE7, 0xB1, 0xA0, 0x00, 0xE8,
2269
  0x81, 0xBE, 0x00, 0xE7, 0x89, 0xA2, 0x00, 0xE7, 0xA3, 0x8A, 0x00, 0xE8, 0xB3, 0x82, 0x00, 0xE9,
2270
  0x9B, 0xB7, 0x00, 0xE5, 0xA3, 0x98, 0x00, 0xE5, 0xB1, 0xA2, 0x00, 0xE6, 0xA8, 0x93, 0x00, 0xE6,
2271
  0xB7, 0x9A, 0x00, 0xE6, 0xBC, 0x8F, 0x00, 0xE7, 0xB4, 0xAF, 0x00, 0xE7, 0xB8, 0xB7, 0x00, 0xE9,
2272
  0x99, 0x8B, 0x00, 0xE5, 0x8B, 0x92, 0x00, 0xE8, 0x82, 0x8B, 0x00, 0xE5, 0x87, 0x9C, 0x00, 0xE5,
2273
  0x87, 0x8C, 0x00, 0xE7, 0xA8, 0x9C, 0x00, 0xE7, 0xB6, 0xBE, 0x00, 0xE8, 0x8F, 0xB1, 0x00, 0xE9,
2274
  0x99, 0xB5, 0x00, 0xE8, 0xAE, 0x80, 0x00, 0xE6, 0x8B, 0x8F, 0x00, 0xE8, 0xAB, 0xBE, 0x00, 0xE4,
2275
  0xB8, 0xB9, 0x00, 0xE5, 0xAF, 0xA7, 0x00, 0xE6, 0x80, 0x92, 0x00, 0xE7, 0x8E, 0x87, 0x00, 0xE7,
2276
  0x95, 0xB0, 0x00, 0xE5, 0x8C, 0x97, 0x00, 0xE7, 0xA3, 0xBB, 0x00, 0xE4, 0xBE, 0xBF, 0x00, 0xE5,
2277
  0xBE, 0xA9, 0x00, 0xE4, 0xB8, 0x8D, 0x00, 0xE6, 0xB3, 0x8C, 0x00, 0xE6, 0x95, 0xB8, 0x00, 0xE7,
2278
  0xB4, 0xA2, 0x00, 0xE5, 0x8F, 0x83, 0x00, 0xE5, 0xA1, 0x9E, 0x00, 0xE7, 0x9C, 0x81, 0x00, 0xE8,
2279
  0x91, 0x89, 0x00, 0xE8, 0xAA, 0xAA, 0x00, 0xE6, 0xAE, 0xBA, 0x00, 0xE6, 0xB2, 0x88, 0x00, 0xE6,
2280
  0x8B, 0xBE, 0x00, 0xE8, 0x8B, 0xA5, 0x00, 0xE6, 0x8E, 0xA0, 0x00, 0xE7, 0x95, 0xA5, 0x00, 0xE4,
2281
  0xBA, 0xAE, 0x00, 0xE5, 0x85, 0xA9, 0x00, 0xE5, 0x87, 0x89, 0x00, 0xE6, 0xA2, 0x81, 0x00, 0xE7,
2282
  0xB3, 0xA7, 0x00, 0xE8, 0x89, 0xAF, 0x00, 0xE8, 0xAB, 0x92, 0x00, 0xE9, 0x87, 0x8F, 0x00, 0xE5,
2283
  0x8B, 0xB5, 0x00, 0xE5, 0x91, 0x82, 0x00, 0xE5, 0xBB, 0xAC, 0x00, 0xE6, 0x97, 0x85, 0x00, 0xE6,
2284
  0xBF, 0xBE, 0x00, 0xE7, 0xA4, 0xAA, 0x00, 0xE9, 0x96, 0xAD, 0x00, 0xE9, 0xA9, 0xAA, 0x00, 0xE9,
2285
  0xBA, 0x97, 0x00, 0xE9, 0xBB, 0x8E, 0x00, 0xE6, 0x9B, 0x86, 0x00, 0xE6, 0xAD, 0xB7, 0x00, 0xE8,
2286
  0xBD, 0xA2, 0x00, 0xE5, 0xB9, 0xB4, 0x00, 0xE6, 0x86, 0x90, 0x00, 0xE6, 0x88, 0x80, 0x00, 0xE6,
2287
  0x92, 0x9A, 0x00, 0xE6, 0xBC, 0xA3, 0x00, 0xE7, 0x85, 0x89, 0x00, 0xE7, 0x92, 0x89, 0x00, 0xE7,
2288
  0xA7, 0x8A, 0x00, 0xE7, 0xB7, 0xB4, 0x00, 0xE8, 0x81, 0xAF, 0x00, 0xE8, 0xBC, 0xA6, 0x00, 0xE8,
2289
  0x93, 0xAE, 0x00, 0xE9, 0x80, 0xA3, 0x00, 0xE9, 0x8D, 0x8A, 0x00, 0xE5, 0x88, 0x97, 0x00, 0xE5,
2290
  0x8A, 0xA3, 0x00, 0xE5, 0x92, 0xBD, 0x00, 0xE7, 0x83, 0x88, 0x00, 0xE8, 0xA3, 0x82, 0x00, 0xE5,
2291
  0xBB, 0x89, 0x00, 0xE5, 0xBF, 0xB5, 0x00, 0xE6, 0x8D, 0xBB, 0x00, 0xE6, 0xAE, 0xAE, 0x00, 0xE7,
2292
  0xB0, 0xBE, 0x00, 0xE7, 0x8D, 0xB5, 0x00, 0xE4, 0xBB, 0xA4, 0x00, 0xE5, 0x9B, 0xB9, 0x00, 0xE5,
2293
  0xB6, 0xBA, 0x00, 0xE6, 0x80, 0x9C, 0x00, 0xE7, 0x8E, 0xB2, 0x00, 0xE7, 0x91, 0xA9, 0x00, 0xE7,
2294
  0xBE, 0x9A, 0x00, 0xE8, 0x81, 0x86, 0x00, 0xE9, 0x88, 0xB4, 0x00, 0xE9, 0x9B, 0xB6, 0x00, 0xE9,
2295
  0x9D, 0x88, 0x00, 0xE9, 0xA0, 0x98, 0x00, 0xE4, 0xBE, 0x8B, 0x00, 0xE7, 0xA6, 0xAE, 0x00, 0xE9,
2296
  0x86, 0xB4, 0x00, 0xE9, 0x9A, 0xB8, 0x00, 0xE6, 0x83, 0xA1, 0x00, 0xE4, 0xBA, 0x86, 0x00, 0xE5,
2297
  0x83, 0x9A, 0x00, 0xE5, 0xAF, 0xAE, 0x00, 0xE5, 0xB0, 0xBF, 0x00, 0xE6, 0x96, 0x99, 0x00, 0xE7,
2298
  0x87, 0x8E, 0x00, 0xE7, 0x99, 0x82, 0x00, 0xE8, 0x93, 0xBC, 0x00, 0xE9, 0x81, 0xBC, 0x00, 0xE6,
2299
  0x9A, 0x88, 0x00, 0xE9, 0x98, 0xAE, 0x00, 0xE5, 0x8A, 0x89, 0x00, 0xE6, 0x9D, 0xBB, 0x00, 0xE6,
2300
  0x9F, 0xB3, 0x00, 0xE6, 0xB5, 0x81, 0x00, 0xE6, 0xBA, 0x9C, 0x00, 0xE7, 0x90, 0x89, 0x00, 0xE7,
2301
  0x95, 0x99, 0x00, 0xE7, 0xA1, 0xAB, 0x00, 0xE7, 0xB4, 0x90, 0x00, 0xE9, 0xA1, 0x9E, 0x00, 0xE6,
2302
  0x88, 0xAE, 0x00, 0xE9, 0x99, 0xB8, 0x00, 0xE5, 0x80, 0xAB, 0x00, 0xE5, 0xB4, 0x99, 0x00, 0xE6,
2303
  0xB7, 0xAA, 0x00, 0xE8, 0xBC, 0xAA, 0x00, 0xE5, 0xBE, 0x8B, 0x00, 0xE6, 0x85, 0x84, 0x00, 0xE6,
2304
  0xA0, 0x97, 0x00, 0xE9, 0x9A, 0x86, 0x00, 0xE5, 0x88, 0xA9, 0x00, 0xE5, 0x90, 0x8F, 0x00, 0xE5,
2305
  0xB1, 0xA5, 0x00, 0xE6, 0x98, 0x93, 0x00, 0xE6, 0x9D, 0x8E, 0x00, 0xE6, 0xA2, 0xA8, 0x00, 0xE6,
2306
  0xB3, 0xA5, 0x00, 0xE7, 0x90, 0x86, 0x00, 0xE7, 0x97, 0xA2, 0x00, 0xE7, 0xBD, 0xB9, 0x00, 0xE8,
2307
  0xA3, 0x8F, 0x00, 0xE8, 0xA3, 0xA1, 0x00, 0xE9, 0x9B, 0xA2, 0x00, 0xE5, 0x8C, 0xBF, 0x00, 0xE6,
2308
  0xBA, 0xBA, 0x00, 0xE5, 0x90, 0x9D, 0x00, 0xE7, 0x87, 0x90, 0x00, 0xE7, 0x92, 0x98, 0x00, 0xE8,
2309
  0x97, 0xBA, 0x00, 0xE9, 0x9A, 0xA3, 0x00, 0xE9, 0xB1, 0x97, 0x00, 0xE9, 0xBA, 0x9F, 0x00, 0xE6,
2310
  0x9E, 0x97, 0x00, 0xE6, 0xB7, 0x8B, 0x00, 0xE8, 0x87, 0xA8, 0x00, 0xE7, 0xAC, 0xA0, 0x00, 0xE7,
2311
  0xB2, 0x92, 0x00, 0xE7, 0x8B, 0x80, 0x00, 0xE7, 0x82, 0x99, 0x00, 0xE8, 0xAD, 0x98, 0x00, 0xE4,
2312
  0xBB, 0x80, 0x00, 0xE8, 0x8C, 0xB6, 0x00, 0xE5, 0x88, 0xBA, 0x00, 0xE5, 0x88, 0x87, 0x00, 0xE5,
2313
  0xBA, 0xA6, 0x00, 0xE6, 0x8B, 0x93, 0x00, 0xE7, 0xB3, 0x96, 0x00, 0xE5, 0xAE, 0x85, 0x00, 0xE6,
2314
  0xB4, 0x9E, 0x00, 0xE6, 0x9A, 0xB4, 0x00, 0xE8, 0xBC, 0xBB, 0x00, 0xE9, 0x99, 0x8D, 0x00, 0xE5,
2315
  0xBB, 0x93, 0x00, 0xE5, 0x85, 0x80, 0x00, 0xE5, 0x97, 0x80, 0x00, 0xE5, 0xA1, 0x9A, 0x00, 0xE6,
2316
  0x99, 0xB4, 0x00, 0xE5, 0x87, 0x9E, 0x00, 0xE7, 0x8C, 0xAA, 0x00, 0xE7, 0x9B, 0x8A, 0x00, 0xE7,
2317
  0xA4, 0xBC, 0x00, 0xE7, 0xA5, 0x9E, 0x00, 0xE7, 0xA5, 0xA5, 0x00, 0xE7, 0xA6, 0x8F, 0x00, 0xE9,
2318
  0x9D, 0x96, 0x00, 0xE7, 0xB2, 0xBE, 0x00, 0xE8, 0x98, 0x92, 0x00, 0xE8, 0xAB, 0xB8, 0x00, 0xE9,
2319
  0x80, 0xB8, 0x00, 0xE9, 0x83, 0xBD, 0x00, 0xE9, 0xA3, 0xAF, 0x00, 0xE9, 0xA3, 0xBC, 0x00, 0xE9,
2320
  0xA4, 0xA8, 0x00, 0xE9, 0xB6, 0xB4, 0x00, 0xE9, 0x83, 0x9E, 0x00, 0xE9, 0x9A, 0xB7, 0x00, 0xE4,
2321
  0xBE, 0xAE, 0x00, 0xE5, 0x83, 0xA7, 0x00, 0xE5, 0x85, 0x8D, 0x00, 0xE5, 0x8B, 0x89, 0x00, 0xE5,
2322
  0x8B, 0xA4, 0x00, 0xE5, 0x8D, 0x91, 0x00, 0xE5, 0x96, 0x9D, 0x00, 0xE5, 0x98, 0x86, 0x00, 0xE5,
2323
  0x99, 0xA8, 0x00, 0xE5, 0xA1, 0x80, 0x00, 0xE5, 0xA2, 0xA8, 0x00, 0xE5, 0xB1, 0xA4, 0x00, 0xE6,
2324
  0x82, 0x94, 0x00, 0xE6, 0x85, 0xA8, 0x00, 0xE6, 0x86, 0x8E, 0x00, 0xE6, 0x87, 0xB2, 0x00, 0xE6,
2325
  0x95, 0x8F, 0x00, 0xE6, 0x97, 0xA2, 0x00, 0xE6, 0x9A, 0x91, 0x00, 0xE6, 0xA2, 0x85, 0x00, 0xE6,
2326
  0xB5, 0xB7, 0x00, 0xE6, 0xB8, 0x9A, 0x00, 0xE6, 0xBC, 0xA2, 0x00, 0xE7, 0x85, 0xAE, 0x00, 0xE7,
2327
  0x88, 0xAB, 0x00, 0xE7, 0x90, 0xA2, 0x00, 0xE7, 0xA2, 0x91, 0x00, 0xE7, 0xA5, 0x89, 0x00, 0xE7,
2328
  0xA5, 0x88, 0x00, 0xE7, 0xA5, 0x90, 0x00, 0xE7, 0xA5, 0x96, 0x00, 0xE7, 0xA6, 0x8D, 0x00, 0xE7,
2329
  0xA6, 0x8E, 0x00, 0xE7, 0xA9, 0x80, 0x00, 0xE7, 0xAA, 0x81, 0x00, 0xE7, 0xAF, 0x80, 0x00, 0xE7,
2330
  0xB8, 0x89, 0x00, 0xE7, 0xB9, 0x81, 0x00, 0xE7, 0xBD, 0xB2, 0x00, 0xE8, 0x80, 0x85, 0x00, 0xE8,
2331
  0x87, 0xAD, 0x00, 0xE8, 0x89, 0xB9, 0x00, 0xE8, 0x91, 0x97, 0x00, 0xE8, 0xA4, 0x90, 0x00, 0xE8,
2332
  0xA6, 0x96, 0x00, 0xE8, 0xAC, 0x81, 0x00, 0xE8, 0xAC, 0xB9, 0x00, 0xE8, 0xB3, 0x93, 0x00, 0xE8,
2333
  0xB4, 0x88, 0x00, 0xE8, 0xBE, 0xB6, 0x00, 0xE9, 0x9B, 0xA3, 0x00, 0xE9, 0x9F, 0xBF, 0x00, 0xE9,
2334
  0xA0, 0xBB, 0x00, 0xE6, 0x81, 0xB5, 0x00, 0xF0, 0xA4, 0x8B, 0xAE, 0x00, 0xE8, 0x88, 0x98, 0x00,
2335
  0xE4, 0xB8, 0xA6, 0x00, 0xE5, 0x86, 0xB5, 0x00, 0xE5, 0x85, 0xA8, 0x00, 0xE4, 0xBE, 0x80, 0x00,
2336
  0xE5, 0x85, 0x85, 0x00, 0xE5, 0x86, 0x80, 0x00, 0xE5, 0x8B, 0x87, 0x00, 0xE5, 0x8B, 0xBA, 0x00,
2337
  0xE5, 0x95, 0x95, 0x00, 0xE5, 0x96, 0x99, 0x00, 0xE5, 0x97, 0xA2, 0x00, 0xE5, 0xA2, 0xB3, 0x00,
2338
  0xE5, 0xA5, 0x84, 0x00, 0xE5, 0xA5, 0x94, 0x00, 0xE5, 0xA9, 0xA2, 0x00, 0xE5, 0xAC, 0xA8, 0x00,
2339
  0xE5, 0xBB, 0x92, 0x00, 0xE5, 0xBB, 0x99, 0x00, 0xE5, 0xBD, 0xA9, 0x00, 0xE5, 0xBE, 0xAD, 0x00,
2340
  0xE6, 0x83, 0x98, 0x00, 0xE6, 0x85, 0x8E, 0x00, 0xE6, 0x84, 0x88, 0x00, 0xE6, 0x85, 0xA0, 0x00,
2341
  0xE6, 0x88, 0xB4, 0x00, 0xE6, 0x8F, 0x84, 0x00, 0xE6, 0x90, 0x9C, 0x00, 0xE6, 0x91, 0x92, 0x00,
2342
  0xE6, 0x95, 0x96, 0x00, 0xE6, 0x9C, 0x9B, 0x00, 0xE6, 0x9D, 0x96, 0x00, 0xE6, 0xBB, 0x9B, 0x00,
2343
  0xE6, 0xBB, 0x8B, 0x00, 0xE7, 0x80, 0x9E, 0x00, 0xE7, 0x9E, 0xA7, 0x00, 0xE7, 0x88, 0xB5, 0x00,
2344
  0xE7, 0x8A, 0xAF, 0x00, 0xE7, 0x91, 0xB1, 0x00, 0xE7, 0x94, 0x86, 0x00, 0xE7, 0x94, 0xBB, 0x00,
2345
  0xE7, 0x98, 0x9D, 0x00, 0xE7, 0x98, 0x9F, 0x00, 0xE7, 0x9B, 0x9B, 0x00, 0xE7, 0x9B, 0xB4, 0x00,
2346
  0xE7, 0x9D, 0x8A, 0x00, 0xE7, 0x9D, 0x80, 0x00, 0xE7, 0xA3, 0x8C, 0x00, 0xE7, 0xAA, 0xB1, 0x00,
2347
  0xE7, 0xB1, 0xBB, 0x00, 0xE7, 0xB5, 0x9B, 0x00, 0xE7, 0xBC, 0xBE, 0x00, 0xE8, 0x8D, 0x92, 0x00,
2348
  0xE8, 0x8F, 0xAF, 0x00, 0xE8, 0x9D, 0xB9, 0x00, 0xE8, 0xA5, 0x81, 0x00, 0xE8, 0xA6, 0x86, 0x00,
2349
  0xE8, 0xAA, 0xBF, 0x00, 0xE8, 0xAB, 0x8B, 0x00, 0xE8, 0xAB, 0xAD, 0x00, 0xE8, 0xAE, 0x8A, 0x00,
2350
  0xE8, 0xBC, 0xB8, 0x00, 0xE9, 0x81, 0xB2, 0x00, 0xE9, 0x86, 0x99, 0x00, 0xE9, 0x89, 0xB6, 0x00,
2351
  0xE9, 0x99, 0xBC, 0x00, 0xE9, 0x9F, 0x9B, 0x00, 0xE9, 0xA0, 0x8B, 0x00, 0xE9, 0xAC, 0x92, 0x00,
2352
  0xF0, 0xA2, 0xA1, 0x8A, 0x00, 0xF0, 0xA2, 0xA1, 0x84, 0x00, 0xF0, 0xA3, 0x8F, 0x95, 0x00, 0xE3,
2353
  0xAE, 0x9D, 0x00, 0xE4, 0x80, 0x98, 0x00, 0xE4, 0x80, 0xB9, 0x00, 0xF0, 0xA5, 0x89, 0x89, 0x00,
2354
  0xF0, 0xA5, 0xB3, 0x90, 0x00, 0xF0, 0xA7, 0xBB, 0x93, 0x00, 0xE9, 0xBD, 0x83, 0x00, 0xE9, 0xBE,
2355
  0x8E, 0x00, 0x66, 0x66, 0x00, 0x66, 0x69, 0x00, 0x66, 0x6C, 0x00, 0x66, 0x66, 0x69, 0x00, 0x66,
2356
  0x66, 0x6C, 0x00, 0x73, 0x74, 0x00, 0xD5, 0xB4, 0xD5, 0xB6, 0x00, 0xD5, 0xB4, 0xD5, 0xA5, 0x00,
2357
  0xD5, 0xB4, 0xD5, 0xAB, 0x00, 0xD5, 0xBE, 0xD5, 0xB6, 0x00, 0xD5, 0xB4, 0xD5, 0xAD, 0x00, 0xD7,
2358
  0x99, 0xD6, 0xB4, 0x00, 0xD7, 0xB2, 0xD6, 0xB7, 0x00, 0xD7, 0xA2, 0x00, 0xD7, 0x94, 0x00, 0xD7,
2359
  0x9B, 0x00, 0xD7, 0x9C, 0x00, 0xD7, 0x9D, 0x00, 0xD7, 0xA8, 0x00, 0xD7, 0xAA, 0x00, 0xD7, 0xA9,
2360
  0xD7, 0x81, 0x00, 0xD7, 0xA9, 0xD7, 0x82, 0x00, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7, 0x81, 0x00, 0xD7,
2361
  0xA9, 0xD6, 0xBC, 0xD7, 0x82, 0x00, 0xD7, 0x90, 0xD6, 0xB7, 0x00, 0xD7, 0x90, 0xD6, 0xB8, 0x00,
2362
  0xD7, 0x90, 0xD6, 0xBC, 0x00, 0xD7, 0x91, 0xD6, 0xBC, 0x00, 0xD7, 0x92, 0xD6, 0xBC, 0x00, 0xD7,
2363
  0x93, 0xD6, 0xBC, 0x00, 0xD7, 0x94, 0xD6, 0xBC, 0x00, 0xD7, 0x95, 0xD6, 0xBC, 0x00, 0xD7, 0x96,
2364
  0xD6, 0xBC, 0x00, 0xD7, 0x98, 0xD6, 0xBC, 0x00, 0xD7, 0x99, 0xD6, 0xBC, 0x00, 0xD7, 0x9A, 0xD6,
2365
  0xBC, 0x00, 0xD7, 0x9B, 0xD6, 0xBC, 0x00, 0xD7, 0x9C, 0xD6, 0xBC, 0x00, 0xD7, 0x9E, 0xD6, 0xBC,
2366
  0x00, 0xD7, 0xA0, 0xD6, 0xBC, 0x00, 0xD7, 0xA1, 0xD6, 0xBC, 0x00, 0xD7, 0xA3, 0xD6, 0xBC, 0x00,
2367
  0xD7, 0xA4, 0xD6, 0xBC, 0x00, 0xD7, 0xA6, 0xD6, 0xBC, 0x00, 0xD7, 0xA7, 0xD6, 0xBC, 0x00, 0xD7,
2368
  0xA8, 0xD6, 0xBC, 0x00, 0xD7, 0xA9, 0xD6, 0xBC, 0x00, 0xD7, 0xAA, 0xD6, 0xBC, 0x00, 0xD7, 0x95,
2369
  0xD6, 0xB9, 0x00, 0xD7, 0x91, 0xD6, 0xBF, 0x00, 0xD7, 0x9B, 0xD6, 0xBF, 0x00, 0xD7, 0xA4, 0xD6,
2370
  0xBF, 0x00, 0xD7, 0x90, 0xD7, 0x9C, 0x00, 0xD9, 0xB1, 0x00, 0xD9, 0xBB, 0x00, 0xD9, 0xBE, 0x00,
2371
  0xDA, 0x80, 0x00, 0xD9, 0xBA, 0x00, 0xD9, 0xBF, 0x00, 0xD9, 0xB9, 0x00, 0xDA, 0xA4, 0x00, 0xDA,
2372
  0xA6, 0x00, 0xDA, 0x84, 0x00, 0xDA, 0x83, 0x00, 0xDA, 0x86, 0x00, 0xDA, 0x87, 0x00, 0xDA, 0x8D,
2373
  0x00, 0xDA, 0x8C, 0x00, 0xDA, 0x8E, 0x00, 0xDA, 0x88, 0x00, 0xDA, 0x98, 0x00, 0xDA, 0x91, 0x00,
2374
  0xDA, 0xA9, 0x00, 0xDA, 0xAF, 0x00, 0xDA, 0xB3, 0x00, 0xDA, 0xB1, 0x00, 0xDA, 0xBA, 0x00, 0xDA,
2375
  0xBB, 0x00, 0xDB, 0x80, 0x00, 0xDB, 0x81, 0x00, 0xDA, 0xBE, 0x00, 0xDB, 0x92, 0x00, 0xDB, 0x93,
2376
  0x00, 0xDA, 0xAD, 0x00, 0xDB, 0x87, 0x00, 0xDB, 0x86, 0x00, 0xDB, 0x88, 0x00, 0xDB, 0x8B, 0x00,
2377
  0xDB, 0x85, 0x00, 0xDB, 0x89, 0x00, 0xDB, 0x90, 0x00, 0xD9, 0x89, 0x00, 0xD8, 0xA6, 0xD8, 0xA7,
2378
  0x00, 0xD8, 0xA6, 0xDB, 0x95, 0x00, 0xD8, 0xA6, 0xD9, 0x88, 0x00, 0xD8, 0xA6, 0xDB, 0x87, 0x00,
2379
  0xD8, 0xA6, 0xDB, 0x86, 0x00, 0xD8, 0xA6, 0xDB, 0x88, 0x00, 0xD8, 0xA6, 0xDB, 0x90, 0x00, 0xD8,
2380
  0xA6, 0xD9, 0x89, 0x00, 0xDB, 0x8C, 0x00, 0xD8, 0xA6, 0xD8, 0xAC, 0x00, 0xD8, 0xA6, 0xD8, 0xAD,
2381
  0x00, 0xD8, 0xA6, 0xD9, 0x85, 0x00, 0xD8, 0xA6, 0xD9, 0x8A, 0x00, 0xD8, 0xA8, 0xD8, 0xAC, 0x00,
2382
  0xD8, 0xA8, 0xD8, 0xAD, 0x00, 0xD8, 0xA8, 0xD8, 0xAE, 0x00, 0xD8, 0xA8, 0xD9, 0x85, 0x00, 0xD8,
2383
  0xA8, 0xD9, 0x89, 0x00, 0xD8, 0xA8, 0xD9, 0x8A, 0x00, 0xD8, 0xAA, 0xD8, 0xAC, 0x00, 0xD8, 0xAA,
2384
  0xD8, 0xAD, 0x00, 0xD8, 0xAA, 0xD8, 0xAE, 0x00, 0xD8, 0xAA, 0xD9, 0x85, 0x00, 0xD8, 0xAA, 0xD9,
2385
  0x89, 0x00, 0xD8, 0xAA, 0xD9, 0x8A, 0x00, 0xD8, 0xAB, 0xD8, 0xAC, 0x00, 0xD8, 0xAB, 0xD9, 0x85,
2386
  0x00, 0xD8, 0xAB, 0xD9, 0x89, 0x00, 0xD8, 0xAB, 0xD9, 0x8A, 0x00, 0xD8, 0xAC, 0xD8, 0xAD, 0x00,
2387
  0xD8, 0xAC, 0xD9, 0x85, 0x00, 0xD8, 0xAD, 0xD8, 0xAC, 0x00, 0xD8, 0xAD, 0xD9, 0x85, 0x00, 0xD8,
2388
  0xAE, 0xD8, 0xAC, 0x00, 0xD8, 0xAE, 0xD8, 0xAD, 0x00, 0xD8, 0xAE, 0xD9, 0x85, 0x00, 0xD8, 0xB3,
2389
  0xD8, 0xAC, 0x00, 0xD8, 0xB3, 0xD8, 0xAD, 0x00, 0xD8, 0xB3, 0xD8, 0xAE, 0x00, 0xD8, 0xB3, 0xD9,
2390
  0x85, 0x00, 0xD8, 0xB5, 0xD8, 0xAD, 0x00, 0xD8, 0xB5, 0xD9, 0x85, 0x00, 0xD8, 0xB6, 0xD8, 0xAC,
2391
  0x00, 0xD8, 0xB6, 0xD8, 0xAD, 0x00, 0xD8, 0xB6, 0xD8, 0xAE, 0x00, 0xD8, 0xB6, 0xD9, 0x85, 0x00,
2392
  0xD8, 0xB7, 0xD8, 0xAD, 0x00, 0xD8, 0xB7, 0xD9, 0x85, 0x00, 0xD8, 0xB8, 0xD9, 0x85, 0x00, 0xD8,
2393
  0xB9, 0xD8, 0xAC, 0x00, 0xD8, 0xB9, 0xD9, 0x85, 0x00, 0xD8, 0xBA, 0xD8, 0xAC, 0x00, 0xD8, 0xBA,
2394
  0xD9, 0x85, 0x00, 0xD9, 0x81, 0xD8, 0xAC, 0x00, 0xD9, 0x81, 0xD8, 0xAD, 0x00, 0xD9, 0x81, 0xD8,
2395
  0xAE, 0x00, 0xD9, 0x81, 0xD9, 0x85, 0x00, 0xD9, 0x81, 0xD9, 0x89, 0x00, 0xD9, 0x81, 0xD9, 0x8A,
2396
  0x00, 0xD9, 0x82, 0xD8, 0xAD, 0x00, 0xD9, 0x82, 0xD9, 0x85, 0x00, 0xD9, 0x82, 0xD9, 0x89, 0x00,
2397
  0xD9, 0x82, 0xD9, 0x8A, 0x00, 0xD9, 0x83, 0xD8, 0xA7, 0x00, 0xD9, 0x83, 0xD8, 0xAC, 0x00, 0xD9,
2398
  0x83, 0xD8, 0xAD, 0x00, 0xD9, 0x83, 0xD8, 0xAE, 0x00, 0xD9, 0x83, 0xD9, 0x84, 0x00, 0xD9, 0x83,
2399
  0xD9, 0x85, 0x00, 0xD9, 0x83, 0xD9, 0x89, 0x00, 0xD9, 0x83, 0xD9, 0x8A, 0x00, 0xD9, 0x84, 0xD8,
2400
  0xAC, 0x00, 0xD9, 0x84, 0xD8, 0xAD, 0x00, 0xD9, 0x84, 0xD8, 0xAE, 0x00, 0xD9, 0x84, 0xD9, 0x85,
2401
  0x00, 0xD9, 0x84, 0xD9, 0x89, 0x00, 0xD9, 0x84, 0xD9, 0x8A, 0x00, 0xD9, 0x85, 0xD8, 0xAC, 0x00,
2402
  0xD9, 0x85, 0xD8, 0xAD, 0x00, 0xD9, 0x85, 0xD8, 0xAE, 0x00, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD9,
2403
  0x85, 0xD9, 0x89, 0x00, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x86, 0xD8, 0xAC, 0x00, 0xD9, 0x86,
2404
  0xD8, 0xAD, 0x00, 0xD9, 0x86, 0xD8, 0xAE, 0x00, 0xD9, 0x86, 0xD9, 0x85, 0x00, 0xD9, 0x86, 0xD9,
2405
  0x89, 0x00, 0xD9, 0x86, 0xD9, 0x8A, 0x00, 0xD9, 0x87, 0xD8, 0xAC, 0x00, 0xD9, 0x87, 0xD9, 0x85,
2406
  0x00, 0xD9, 0x87, 0xD9, 0x89, 0x00, 0xD9, 0x87, 0xD9, 0x8A, 0x00, 0xD9, 0x8A, 0xD8, 0xAC, 0x00,
2407
  0xD9, 0x8A, 0xD8, 0xAD, 0x00, 0xD9, 0x8A, 0xD8, 0xAE, 0x00, 0xD9, 0x8A, 0xD9, 0x85, 0x00, 0xD9,
2408
  0x8A, 0xD9, 0x89, 0x00, 0xD9, 0x8A, 0xD9, 0x8A, 0x00, 0xD8, 0xB0, 0xD9, 0xB0, 0x00, 0xD8, 0xB1,
2409
  0xD9, 0xB0, 0x00, 0xD9, 0x89, 0xD9, 0xB0, 0x00, 0x20, 0xD9, 0x8C, 0xD9, 0x91, 0x00, 0x20, 0xD9,
2410
  0x8D, 0xD9, 0x91, 0x00, 0x20, 0xD9, 0x8E, 0xD9, 0x91, 0x00, 0x20, 0xD9, 0x8F, 0xD9, 0x91, 0x00,
2411
  0x20, 0xD9, 0x90, 0xD9, 0x91, 0x00, 0x20, 0xD9, 0x91, 0xD9, 0xB0, 0x00, 0xD8, 0xA6, 0xD8, 0xB1,
2412
  0x00, 0xD8, 0xA6, 0xD8, 0xB2, 0x00, 0xD8, 0xA6, 0xD9, 0x86, 0x00, 0xD8, 0xA8, 0xD8, 0xB1, 0x00,
2413
  0xD8, 0xA8, 0xD8, 0xB2, 0x00, 0xD8, 0xA8, 0xD9, 0x86, 0x00, 0xD8, 0xAA, 0xD8, 0xB1, 0x00, 0xD8,
2414
  0xAA, 0xD8, 0xB2, 0x00, 0xD8, 0xAA, 0xD9, 0x86, 0x00, 0xD8, 0xAB, 0xD8, 0xB1, 0x00, 0xD8, 0xAB,
2415
  0xD8, 0xB2, 0x00, 0xD8, 0xAB, 0xD9, 0x86, 0x00, 0xD9, 0x85, 0xD8, 0xA7, 0x00, 0xD9, 0x86, 0xD8,
2416
  0xB1, 0x00, 0xD9, 0x86, 0xD8, 0xB2, 0x00, 0xD9, 0x86, 0xD9, 0x86, 0x00, 0xD9, 0x8A, 0xD8, 0xB1,
2417
  0x00, 0xD9, 0x8A, 0xD8, 0xB2, 0x00, 0xD9, 0x8A, 0xD9, 0x86, 0x00, 0xD8, 0xA6, 0xD8, 0xAE, 0x00,
2418
  0xD8, 0xA6, 0xD9, 0x87, 0x00, 0xD8, 0xA8, 0xD9, 0x87, 0x00, 0xD8, 0xAA, 0xD9, 0x87, 0x00, 0xD8,
2419
  0xB5, 0xD8, 0xAE, 0x00, 0xD9, 0x84, 0xD9, 0x87, 0x00, 0xD9, 0x86, 0xD9, 0x87, 0x00, 0xD9, 0x87,
2420
  0xD9, 0xB0, 0x00, 0xD9, 0x8A, 0xD9, 0x87, 0x00, 0xD8, 0xAB, 0xD9, 0x87, 0x00, 0xD8, 0xB3, 0xD9,
2421
  0x87, 0x00, 0xD8, 0xB4, 0xD9, 0x85, 0x00, 0xD8, 0xB4, 0xD9, 0x87, 0x00, 0xD9, 0x80, 0xD9, 0x8E,
2422
  0xD9, 0x91, 0x00, 0xD9, 0x80, 0xD9, 0x8F, 0xD9, 0x91, 0x00, 0xD9, 0x80, 0xD9, 0x90, 0xD9, 0x91,
2423
  0x00, 0xD8, 0xB7, 0xD9, 0x89, 0x00, 0xD8, 0xB7, 0xD9, 0x8A, 0x00, 0xD8, 0xB9, 0xD9, 0x89, 0x00,
2424
  0xD8, 0xB9, 0xD9, 0x8A, 0x00, 0xD8, 0xBA, 0xD9, 0x89, 0x00, 0xD8, 0xBA, 0xD9, 0x8A, 0x00, 0xD8,
2425
  0xB3, 0xD9, 0x89, 0x00, 0xD8, 0xB3, 0xD9, 0x8A, 0x00, 0xD8, 0xB4, 0xD9, 0x89, 0x00, 0xD8, 0xB4,
2426
  0xD9, 0x8A, 0x00, 0xD8, 0xAD, 0xD9, 0x89, 0x00, 0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD8, 0xAC, 0xD9,
2427
  0x89, 0x00, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD8, 0xAE, 0xD9, 0x89, 0x00, 0xD8, 0xAE, 0xD9, 0x8A,
2428
  0x00, 0xD8, 0xB5, 0xD9, 0x89, 0x00, 0xD8, 0xB5, 0xD9, 0x8A, 0x00, 0xD8, 0xB6, 0xD9, 0x89, 0x00,
2429
  0xD8, 0xB6, 0xD9, 0x8A, 0x00, 0xD8, 0xB4, 0xD8, 0xAC, 0x00, 0xD8, 0xB4, 0xD8, 0xAD, 0x00, 0xD8,
2430
  0xB4, 0xD8, 0xAE, 0x00, 0xD8, 0xB4, 0xD8, 0xB1, 0x00, 0xD8, 0xB3, 0xD8, 0xB1, 0x00, 0xD8, 0xB5,
2431
  0xD8, 0xB1, 0x00, 0xD8, 0xB6, 0xD8, 0xB1, 0x00, 0xD8, 0xA7, 0xD9, 0x8B, 0x00, 0xD8, 0xAA, 0xD8,
2432
  0xAC, 0xD9, 0x85, 0x00, 0xD8, 0xAA, 0xD8, 0xAD, 0xD8, 0xAC, 0x00, 0xD8, 0xAA, 0xD8, 0xAD, 0xD9,
2433
  0x85, 0x00, 0xD8, 0xAA, 0xD8, 0xAE, 0xD9, 0x85, 0x00, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAC, 0x00,
2434
  0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAD, 0x00, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAE, 0x00, 0xD8, 0xAC,
2435
  0xD9, 0x85, 0xD8, 0xAD, 0x00, 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD8, 0xAD, 0xD9, 0x85,
2436
  0xD9, 0x89, 0x00, 0xD8, 0xB3, 0xD8, 0xAD, 0xD8, 0xAC, 0x00, 0xD8, 0xB3, 0xD8, 0xAC, 0xD8, 0xAD,
2437
  0x00, 0xD8, 0xB3, 0xD8, 0xAC, 0xD9, 0x89, 0x00, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAD, 0x00, 0xD8,
2438
  0xB3, 0xD9, 0x85, 0xD8, 0xAC, 0x00, 0xD8, 0xB3, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xB5, 0xD8,
2439
  0xAD, 0xD8, 0xAD, 0x00, 0xD8, 0xB5, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xB4, 0xD8, 0xAD, 0xD9,
2440
  0x85, 0x00, 0xD8, 0xB4, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD8, 0xB4, 0xD9, 0x85, 0xD8, 0xAE, 0x00,
2441
  0xD8, 0xB4, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9, 0x89, 0x00, 0xD8, 0xB6,
2442
  0xD8, 0xAE, 0xD9, 0x85, 0x00, 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD, 0x00, 0xD8, 0xB7, 0xD9, 0x85,
2443
  0xD9, 0x85, 0x00, 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD8, 0xB9, 0xD8, 0xAC, 0xD9, 0x85,
2444
  0x00, 0xD8, 0xB9, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xB9, 0xD9, 0x85, 0xD9, 0x89, 0x00, 0xD8,
2445
  0xBA, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD8, 0xBA, 0xD9,
2446
  0x85, 0xD9, 0x89, 0x00, 0xD9, 0x81, 0xD8, 0xAE, 0xD9, 0x85, 0x00, 0xD9, 0x82, 0xD9, 0x85, 0xD8,
2447
  0xAD, 0x00, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x85, 0x00,
2448
  0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x89, 0x00, 0xD9, 0x84,
2449
  0xD8, 0xAC, 0xD8, 0xAC, 0x00, 0xD9, 0x84, 0xD8, 0xAE, 0xD9, 0x85, 0x00, 0xD9, 0x84, 0xD9, 0x85,
2450
  0xD8, 0xAD, 0x00, 0xD9, 0x85, 0xD8, 0xAD, 0xD8, 0xAC, 0x00, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85,
2451
  0x00, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD9, 0x85, 0xD8, 0xAC, 0xD8, 0xAD, 0x00, 0xD9,
2452
  0x85, 0xD8, 0xAC, 0xD9, 0x85, 0x00, 0xD9, 0x85, 0xD8, 0xAE, 0xD8, 0xAC, 0x00, 0xD9, 0x85, 0xD8,
2453
  0xAE, 0xD9, 0x85, 0x00, 0xD9, 0x85, 0xD8, 0xAC, 0xD8, 0xAE, 0x00, 0xD9, 0x87, 0xD9, 0x85, 0xD8,
2454
  0xAC, 0x00, 0xD9, 0x87, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x85, 0x00,
2455
  0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x89, 0x00, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x85, 0x00, 0xD9, 0x86,
2456
  0xD8, 0xAC, 0xD9, 0x89, 0x00, 0xD9, 0x86, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x86, 0xD9, 0x85,
2457
  0xD9, 0x89, 0x00, 0xD9, 0x8A, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xA8, 0xD8, 0xAE, 0xD9, 0x8A,
2458
  0x00, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x89, 0x00, 0xD8,
2459
  0xAA, 0xD8, 0xAE, 0xD9, 0x8A, 0x00, 0xD8, 0xAA, 0xD8, 0xAE, 0xD9, 0x89, 0x00, 0xD8, 0xAA, 0xD9,
2460
  0x85, 0xD9, 0x8A, 0x00, 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x89, 0x00, 0xD8, 0xAC, 0xD9, 0x85, 0xD9,
2461
  0x8A, 0x00, 0xD8, 0xAC, 0xD8, 0xAD, 0xD9, 0x89, 0x00, 0xD8, 0xAC, 0xD9, 0x85, 0xD9, 0x89, 0x00,
2462
  0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x89, 0x00, 0xD8, 0xB5, 0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD8, 0xB4,
2463
  0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD9, 0x84, 0xD8, 0xAC,
2464
  0xD9, 0x8A, 0x00, 0xD9, 0x84, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x8A, 0xD8, 0xAD, 0xD9, 0x8A,
2465
  0x00, 0xD9, 0x8A, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD9, 0x8A, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9,
2466
  0x85, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x86, 0xD8,
2467
  0xAD, 0xD9, 0x8A, 0x00, 0xD8, 0xB9, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD9, 0x83, 0xD9, 0x85, 0xD9,
2468
  0x8A, 0x00, 0xD9, 0x86, 0xD8, 0xAC, 0xD8, 0xAD, 0x00, 0xD9, 0x85, 0xD8, 0xAE, 0xD9, 0x8A, 0x00,
2469
  0xD9, 0x84, 0xD8, 0xAC, 0xD9, 0x85, 0x00, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x85, 0x00, 0xD8, 0xAC,
2470
  0xD8, 0xAD, 0xD9, 0x8A, 0x00, 0xD8, 0xAD, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD9, 0x85, 0xD8, 0xAC,
2471
  0xD9, 0x8A, 0x00, 0xD9, 0x81, 0xD9, 0x85, 0xD9, 0x8A, 0x00, 0xD8, 0xA8, 0xD8, 0xAD, 0xD9, 0x8A,
2472
  0x00, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x8A, 0x00, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x8A, 0x00, 0xD8,
2473
  0xB5, 0xD9, 0x84, 0xDB, 0x92, 0x00, 0xD9, 0x82, 0xD9, 0x84, 0xDB, 0x92, 0x00, 0xD8, 0xA7, 0xD9,
2474
  0x84, 0xD9, 0x84, 0xD9, 0x87, 0x00, 0xD8, 0xA7, 0xD9, 0x83, 0xD8, 0xA8, 0xD8, 0xB1, 0x00, 0xD9,
2475
  0x85, 0xD8, 0xAD, 0xD9, 0x85, 0xD8, 0xAF, 0x00, 0xD8, 0xB5, 0xD9, 0x84, 0xD8, 0xB9, 0xD9, 0x85,
2476
  0x00, 0xD8, 0xB1, 0xD8, 0xB3, 0xD9, 0x88, 0xD9, 0x84, 0x00, 0xD8, 0xB9, 0xD9, 0x84, 0xD9, 0x8A,
2477
  0xD9, 0x87, 0x00, 0xD9, 0x88, 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x00, 0xD8, 0xB5, 0xD9, 0x84,
2478
  0xD9, 0x89, 0x00, 0xD8, 0xB5, 0xD9, 0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9, 0x84, 0xD9, 0x84,
2479
  0xD9, 0x87, 0x20, 0xD8, 0xB9, 0xD9, 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9, 0x88, 0xD8, 0xB3,
2480
  0xD9, 0x84, 0xD9, 0x85, 0x00, 0xD8, 0xAC, 0xD9, 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
2481
  0xD9, 0x84, 0xD9, 0x87, 0x00, 0xD8, 0xB1, 0xDB, 0x8C, 0xD8, 0xA7, 0xD9, 0x84, 0x00, 0x2C, 0x00,
2482
  0xE3, 0x80, 0x81, 0x00, 0x3A, 0x00, 0x21, 0x00, 0x3F, 0x00, 0xE3, 0x80, 0x96, 0x00, 0xE3, 0x80,
2483
  0x97, 0x00, 0xE2, 0x80, 0x94, 0x00, 0xE2, 0x80, 0x93, 0x00, 0x5F, 0x00, 0x7B, 0x00, 0x7D, 0x00,
2484
  0xE3, 0x80, 0x94, 0x00, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x90, 0x00, 0xE3, 0x80, 0x91, 0x00,
2485
  0xE3, 0x80, 0x8A, 0x00, 0xE3, 0x80, 0x8B, 0x00, 0xE3, 0x80, 0x8C, 0x00, 0xE3, 0x80, 0x8D, 0x00,
2486
  0xE3, 0x80, 0x8E, 0x00, 0xE3, 0x80, 0x8F, 0x00, 0x5B, 0x00, 0x5D, 0x00, 0x23, 0x00, 0x26, 0x00,
2487
  0x2A, 0x00, 0x2D, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x5C, 0x00, 0x24, 0x00, 0x25, 0x00, 0x40, 0x00,
2488
  0x20, 0xD9, 0x8B, 0x00, 0xD9, 0x80, 0xD9, 0x8B, 0x00, 0x20, 0xD9, 0x8C, 0x00, 0x20, 0xD9, 0x8D,
2489
  0x00, 0x20, 0xD9, 0x8E, 0x00, 0xD9, 0x80, 0xD9, 0x8E, 0x00, 0x20, 0xD9, 0x8F, 0x00, 0xD9, 0x80,
2490
  0xD9, 0x8F, 0x00, 0x20, 0xD9, 0x90, 0x00, 0xD9, 0x80, 0xD9, 0x90, 0x00, 0x20, 0xD9, 0x91, 0x00,
2491
  0xD9, 0x80, 0xD9, 0x91, 0x00, 0x20, 0xD9, 0x92, 0x00, 0xD9, 0x80, 0xD9, 0x92, 0x00, 0xD8, 0xA1,
2492
  0x00, 0xD8, 0xA2, 0x00, 0xD8, 0xA3, 0x00, 0xD8, 0xA4, 0x00, 0xD8, 0xA5, 0x00, 0xD8, 0xA6, 0x00,
2493
  0xD8, 0xA7, 0x00, 0xD8, 0xA8, 0x00, 0xD8, 0xA9, 0x00, 0xD8, 0xAA, 0x00, 0xD8, 0xAB, 0x00, 0xD8,
2494
  0xAC, 0x00, 0xD8, 0xAD, 0x00, 0xD8, 0xAE, 0x00, 0xD8, 0xAF, 0x00, 0xD8, 0xB0, 0x00, 0xD8, 0xB1,
2495
  0x00, 0xD8, 0xB2, 0x00, 0xD8, 0xB3, 0x00, 0xD8, 0xB4, 0x00, 0xD8, 0xB5, 0x00, 0xD8, 0xB6, 0x00,
2496
  0xD8, 0xB7, 0x00, 0xD8, 0xB8, 0x00, 0xD8, 0xB9, 0x00, 0xD8, 0xBA, 0x00, 0xD9, 0x81, 0x00, 0xD9,
2497
  0x82, 0x00, 0xD9, 0x83, 0x00, 0xD9, 0x84, 0x00, 0xD9, 0x85, 0x00, 0xD9, 0x86, 0x00, 0xD9, 0x87,
2498
  0x00, 0xD9, 0x88, 0x00, 0xD9, 0x8A, 0x00, 0xD9, 0x84, 0xD8, 0xA2, 0x00, 0xD9, 0x84, 0xD8, 0xA3,
2499
  0x00, 0xD9, 0x84, 0xD8, 0xA5, 0x00, 0xD9, 0x84, 0xD8, 0xA7, 0x00, 0x22, 0x00, 0x27, 0x00, 0x2F,
2500
  0x00, 0x5E, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0xE2, 0xA6, 0x85, 0x00, 0xE2, 0xA6, 0x86, 0x00, 0xE3,
2501
  0x83, 0xBB, 0x00, 0xE3, 0x82, 0xA1, 0x00, 0xE3, 0x82, 0xA3, 0x00, 0xE3, 0x82, 0xA5, 0x00, 0xE3,
2502
  0x82, 0xA7, 0x00, 0xE3, 0x82, 0xA9, 0x00, 0xE3, 0x83, 0xA3, 0x00, 0xE3, 0x83, 0xA5, 0x00, 0xE3,
2503
  0x83, 0xA7, 0x00, 0xE3, 0x83, 0x83, 0x00, 0xE3, 0x83, 0xBC, 0x00, 0xE3, 0x83, 0xB3, 0x00, 0xE3,
2504
  0x82, 0x99, 0x00, 0xE3, 0x82, 0x9A, 0x00, 0xC2, 0xA2, 0x00, 0xC2, 0xA3, 0x00, 0xC2, 0xAC, 0x00,
2505
  0xC2, 0xA6, 0x00, 0xC2, 0xA5, 0x00, 0xE2, 0x82, 0xA9, 0x00, 0xE2, 0x94, 0x82, 0x00, 0xE2, 0x86,
2506
  0x90, 0x00, 0xE2, 0x86, 0x91, 0x00, 0xE2, 0x86, 0x92, 0x00, 0xE2, 0x86, 0x93, 0x00, 0xE2, 0x96,
2507
  0xA0, 0x00, 0xE2, 0x97, 0x8B, 0x00, 0xF0, 0x90, 0x90, 0xA8, 0x00, 0xF0, 0x90, 0x90, 0xA9, 0x00,
2508
  0xF0, 0x90, 0x90, 0xAA, 0x00, 0xF0, 0x90, 0x90, 0xAB, 0x00, 0xF0, 0x90, 0x90, 0xAC, 0x00, 0xF0,
2509
  0x90, 0x90, 0xAD, 0x00, 0xF0, 0x90, 0x90, 0xAE, 0x00, 0xF0, 0x90, 0x90, 0xAF, 0x00, 0xF0, 0x90,
2510
  0x90, 0xB0, 0x00, 0xF0, 0x90, 0x90, 0xB1, 0x00, 0xF0, 0x90, 0x90, 0xB2, 0x00, 0xF0, 0x90, 0x90,
2511
  0xB3, 0x00, 0xF0, 0x90, 0x90, 0xB4, 0x00, 0xF0, 0x90, 0x90, 0xB5, 0x00, 0xF0, 0x90, 0x90, 0xB6,
2512
  0x00, 0xF0, 0x90, 0x90, 0xB7, 0x00, 0xF0, 0x90, 0x90, 0xB8, 0x00, 0xF0, 0x90, 0x90, 0xB9, 0x00,
2513
  0xF0, 0x90, 0x90, 0xBA, 0x00, 0xF0, 0x90, 0x90, 0xBB, 0x00, 0xF0, 0x90, 0x90, 0xBC, 0x00, 0xF0,
2514
  0x90, 0x90, 0xBD, 0x00, 0xF0, 0x90, 0x90, 0xBE, 0x00, 0xF0, 0x90, 0x90, 0xBF, 0x00, 0xF0, 0x90,
2515
  0x91, 0x80, 0x00, 0xF0, 0x90, 0x91, 0x81, 0x00, 0xF0, 0x90, 0x91, 0x82, 0x00, 0xF0, 0x90, 0x91,
2516
  0x83, 0x00, 0xF0, 0x90, 0x91, 0x84, 0x00, 0xF0, 0x90, 0x91, 0x85, 0x00, 0xF0, 0x90, 0x91, 0x86,
2517
  0x00, 0xF0, 0x90, 0x91, 0x87, 0x00, 0xF0, 0x90, 0x91, 0x88, 0x00, 0xF0, 0x90, 0x91, 0x89, 0x00,
2518
  0xF0, 0x90, 0x91, 0x8A, 0x00, 0xF0, 0x90, 0x91, 0x8B, 0x00, 0xF0, 0x90, 0x91, 0x8C, 0x00, 0xF0,
2519
  0x90, 0x91, 0x8D, 0x00, 0xF0, 0x90, 0x91, 0x8E, 0x00, 0xF0, 0x90, 0x91, 0x8F, 0x00, 0xF0, 0x90,
2520
  0x93, 0x98, 0x00, 0xF0, 0x90, 0x93, 0x99, 0x00, 0xF0, 0x90, 0x93, 0x9A, 0x00, 0xF0, 0x90, 0x93,
2521
  0x9B, 0x00, 0xF0, 0x90, 0x93, 0x9C, 0x00, 0xF0, 0x90, 0x93, 0x9D, 0x00, 0xF0, 0x90, 0x93, 0x9E,
2522
  0x00, 0xF0, 0x90, 0x93, 0x9F, 0x00, 0xF0, 0x90, 0x93, 0xA0, 0x00, 0xF0, 0x90, 0x93, 0xA1, 0x00,
2523
  0xF0, 0x90, 0x93, 0xA2, 0x00, 0xF0, 0x90, 0x93, 0xA3, 0x00, 0xF0, 0x90, 0x93, 0xA4, 0x00, 0xF0,
2524
  0x90, 0x93, 0xA5, 0x00, 0xF0, 0x90, 0x93, 0xA6, 0x00, 0xF0, 0x90, 0x93, 0xA7, 0x00, 0xF0, 0x90,
2525
  0x93, 0xA8, 0x00, 0xF0, 0x90, 0x93, 0xA9, 0x00, 0xF0, 0x90, 0x93, 0xAA, 0x00, 0xF0, 0x90, 0x93,
2526
  0xAB, 0x00, 0xF0, 0x90, 0x93, 0xAC, 0x00, 0xF0, 0x90, 0x93, 0xAD, 0x00, 0xF0, 0x90, 0x93, 0xAE,
2527
  0x00, 0xF0, 0x90, 0x93, 0xAF, 0x00, 0xF0, 0x90, 0x93, 0xB0, 0x00, 0xF0, 0x90, 0x93, 0xB1, 0x00,
2528
  0xF0, 0x90, 0x93, 0xB2, 0x00, 0xF0, 0x90, 0x93, 0xB3, 0x00, 0xF0, 0x90, 0x93, 0xB4, 0x00, 0xF0,
2529
  0x90, 0x93, 0xB5, 0x00, 0xF0, 0x90, 0x93, 0xB6, 0x00, 0xF0, 0x90, 0x93, 0xB7, 0x00, 0xF0, 0x90,
2530
  0x93, 0xB8, 0x00, 0xF0, 0x90, 0x93, 0xB9, 0x00, 0xF0, 0x90, 0x93, 0xBA, 0x00, 0xF0, 0x90, 0x93,
2531
  0xBB, 0x00, 0xF0, 0x90, 0x96, 0x97, 0x00, 0xF0, 0x90, 0x96, 0x98, 0x00, 0xF0, 0x90, 0x96, 0x99,
2532
  0x00, 0xF0, 0x90, 0x96, 0x9A, 0x00, 0xF0, 0x90, 0x96, 0x9B, 0x00, 0xF0, 0x90, 0x96, 0x9C, 0x00,
2533
  0xF0, 0x90, 0x96, 0x9D, 0x00, 0xF0, 0x90, 0x96, 0x9E, 0x00, 0xF0, 0x90, 0x96, 0x9F, 0x00, 0xF0,
2534
  0x90, 0x96, 0xA0, 0x00, 0xF0, 0x90, 0x96, 0xA1, 0x00, 0xF0, 0x90, 0x96, 0xA3, 0x00, 0xF0, 0x90,
2535
  0x96, 0xA4, 0x00, 0xF0, 0x90, 0x96, 0xA5, 0x00, 0xF0, 0x90, 0x96, 0xA6, 0x00, 0xF0, 0x90, 0x96,
2536
  0xA7, 0x00, 0xF0, 0x90, 0x96, 0xA8, 0x00, 0xF0, 0x90, 0x96, 0xA9, 0x00, 0xF0, 0x90, 0x96, 0xAA,
2537
  0x00, 0xF0, 0x90, 0x96, 0xAB, 0x00, 0xF0, 0x90, 0x96, 0xAC, 0x00, 0xF0, 0x90, 0x96, 0xAD, 0x00,
2538
  0xF0, 0x90, 0x96, 0xAE, 0x00, 0xF0, 0x90, 0x96, 0xAF, 0x00, 0xF0, 0x90, 0x96, 0xB0, 0x00, 0xF0,
2539
  0x90, 0x96, 0xB1, 0x00, 0xF0, 0x90, 0x96, 0xB3, 0x00, 0xF0, 0x90, 0x96, 0xB4, 0x00, 0xF0, 0x90,
2540
  0x96, 0xB5, 0x00, 0xF0, 0x90, 0x96, 0xB6, 0x00, 0xF0, 0x90, 0x96, 0xB7, 0x00, 0xF0, 0x90, 0x96,
2541
  0xB8, 0x00, 0xF0, 0x90, 0x96, 0xB9, 0x00, 0xF0, 0x90, 0x96, 0xBB, 0x00, 0xF0, 0x90, 0x96, 0xBC,
2542
  0x00, 0xCB, 0x90, 0x00, 0xCB, 0x91, 0x00, 0xCA, 0x99, 0x00, 0xCA, 0xA3, 0x00, 0xEA, 0xAD, 0xA6,
2543
  0x00, 0xCA, 0xA5, 0x00, 0xCA, 0xA4, 0x00, 0xE1, 0xB6, 0x91, 0x00, 0xC9, 0x98, 0x00, 0xC9, 0x9E,
2544
  0x00, 0xCA, 0xA9, 0x00, 0xC9, 0xA2, 0x00, 0xCA, 0x9B, 0x00, 0xCA, 0x9C, 0x00, 0xC9, 0xA7, 0x00,
2545
  0xCA, 0x84, 0x00, 0xCA, 0xAA, 0x00, 0xCA, 0xAB, 0x00, 0xF0, 0x9D, 0xBC, 0x84, 0x00, 0xEA, 0x9E,
2546
  0x8E, 0x00, 0xC9, 0xAE, 0x00, 0xF0, 0x9D, 0xBC, 0x85, 0x00, 0xCA, 0x8E, 0x00, 0xF0, 0x9D, 0xBC,
2547
  0x86, 0x00, 0xC9, 0xB6, 0x00, 0xC9, 0xB7, 0x00, 0xC9, 0xBA, 0x00, 0xF0, 0x9D, 0xBC, 0x88, 0x00,
2548
  0xC9, 0xBE, 0x00, 0xCA, 0xA8, 0x00, 0xCA, 0xA6, 0x00, 0xEA, 0xAD, 0xA7, 0x00, 0xCA, 0xA7, 0x00,
2549
  0xE2, 0xB1, 0xB1, 0x00, 0xCA, 0x8F, 0x00, 0xCA, 0xA1, 0x00, 0xCA, 0xA2, 0x00, 0xCA, 0x98, 0x00,
2550
  0xC7, 0x80, 0x00, 0xC7, 0x81, 0x00, 0xC7, 0x82, 0x00, 0xF0, 0x9D, 0xBC, 0x8A, 0x00, 0xF0, 0x9D,
2551
  0xBC, 0x9E, 0x00, 0xF0, 0x90, 0xB3, 0x80, 0x00, 0xF0, 0x90, 0xB3, 0x81, 0x00, 0xF0, 0x90, 0xB3,
2552
  0x82, 0x00, 0xF0, 0x90, 0xB3, 0x83, 0x00, 0xF0, 0x90, 0xB3, 0x84, 0x00, 0xF0, 0x90, 0xB3, 0x85,
2553
  0x00, 0xF0, 0x90, 0xB3, 0x86, 0x00, 0xF0, 0x90, 0xB3, 0x87, 0x00, 0xF0, 0x90, 0xB3, 0x88, 0x00,
2554
  0xF0, 0x90, 0xB3, 0x89, 0x00, 0xF0, 0x90, 0xB3, 0x8A, 0x00, 0xF0, 0x90, 0xB3, 0x8B, 0x00, 0xF0,
2555
  0x90, 0xB3, 0x8C, 0x00, 0xF0, 0x90, 0xB3, 0x8D, 0x00, 0xF0, 0x90, 0xB3, 0x8E, 0x00, 0xF0, 0x90,
2556
  0xB3, 0x8F, 0x00, 0xF0, 0x90, 0xB3, 0x90, 0x00, 0xF0, 0x90, 0xB3, 0x91, 0x00, 0xF0, 0x90, 0xB3,
2557
  0x92, 0x00, 0xF0, 0x90, 0xB3, 0x93, 0x00, 0xF0, 0x90, 0xB3, 0x94, 0x00, 0xF0, 0x90, 0xB3, 0x95,
2558
  0x00, 0xF0, 0x90, 0xB3, 0x96, 0x00, 0xF0, 0x90, 0xB3, 0x97, 0x00, 0xF0, 0x90, 0xB3, 0x98, 0x00,
2559
  0xF0, 0x90, 0xB3, 0x99, 0x00, 0xF0, 0x90, 0xB3, 0x9A, 0x00, 0xF0, 0x90, 0xB3, 0x9B, 0x00, 0xF0,
2560
  0x90, 0xB3, 0x9C, 0x00, 0xF0, 0x90, 0xB3, 0x9D, 0x00, 0xF0, 0x90, 0xB3, 0x9E, 0x00, 0xF0, 0x90,
2561
  0xB3, 0x9F, 0x00, 0xF0, 0x90, 0xB3, 0xA0, 0x00, 0xF0, 0x90, 0xB3, 0xA1, 0x00, 0xF0, 0x90, 0xB3,
2562
  0xA2, 0x00, 0xF0, 0x90, 0xB3, 0xA3, 0x00, 0xF0, 0x90, 0xB3, 0xA4, 0x00, 0xF0, 0x90, 0xB3, 0xA5,
2563
  0x00, 0xF0, 0x90, 0xB3, 0xA6, 0x00, 0xF0, 0x90, 0xB3, 0xA7, 0x00, 0xF0, 0x90, 0xB3, 0xA8, 0x00,
2564
  0xF0, 0x90, 0xB3, 0xA9, 0x00, 0xF0, 0x90, 0xB3, 0xAA, 0x00, 0xF0, 0x90, 0xB3, 0xAB, 0x00, 0xF0,
2565
  0x90, 0xB3, 0xAC, 0x00, 0xF0, 0x90, 0xB3, 0xAD, 0x00, 0xF0, 0x90, 0xB3, 0xAE, 0x00, 0xF0, 0x90,
2566
  0xB3, 0xAF, 0x00, 0xF0, 0x90, 0xB3, 0xB0, 0x00, 0xF0, 0x90, 0xB3, 0xB1, 0x00, 0xF0, 0x90, 0xB3,
2567
  0xB2, 0x00, 0xF0, 0x90, 0xB5, 0xB0, 0x00, 0xF0, 0x90, 0xB5, 0xB1, 0x00, 0xF0, 0x90, 0xB5, 0xB2,
2568
  0x00, 0xF0, 0x90, 0xB5, 0xB3, 0x00, 0xF0, 0x90, 0xB5, 0xB4, 0x00, 0xF0, 0x90, 0xB5, 0xB5, 0x00,
2569
  0xF0, 0x90, 0xB5, 0xB6, 0x00, 0xF0, 0x90, 0xB5, 0xB7, 0x00, 0xF0, 0x90, 0xB5, 0xB8, 0x00, 0xF0,
2570
  0x90, 0xB5, 0xB9, 0x00, 0xF0, 0x90, 0xB5, 0xBA, 0x00, 0xF0, 0x90, 0xB5, 0xBB, 0x00, 0xF0, 0x90,
2571
  0xB5, 0xBC, 0x00, 0xF0, 0x90, 0xB5, 0xBD, 0x00, 0xF0, 0x90, 0xB5, 0xBE, 0x00, 0xF0, 0x90, 0xB5,
2572
  0xBF, 0x00, 0xF0, 0x90, 0xB6, 0x80, 0x00, 0xF0, 0x90, 0xB6, 0x81, 0x00, 0xF0, 0x90, 0xB6, 0x82,
2573
  0x00, 0xF0, 0x90, 0xB6, 0x83, 0x00, 0xF0, 0x90, 0xB6, 0x84, 0x00, 0xF0, 0x90, 0xB6, 0x85, 0x00,
2574
  0xF0, 0x91, 0xA3, 0x80, 0x00, 0xF0, 0x91, 0xA3, 0x81, 0x00, 0xF0, 0x91, 0xA3, 0x82, 0x00, 0xF0,
2575
  0x91, 0xA3, 0x83, 0x00, 0xF0, 0x91, 0xA3, 0x84, 0x00, 0xF0, 0x91, 0xA3, 0x85, 0x00, 0xF0, 0x91,
2576
  0xA3, 0x86, 0x00, 0xF0, 0x91, 0xA3, 0x87, 0x00, 0xF0, 0x91, 0xA3, 0x88, 0x00, 0xF0, 0x91, 0xA3,
2577
  0x89, 0x00, 0xF0, 0x91, 0xA3, 0x8A, 0x00, 0xF0, 0x91, 0xA3, 0x8B, 0x00, 0xF0, 0x91, 0xA3, 0x8C,
2578
  0x00, 0xF0, 0x91, 0xA3, 0x8D, 0x00, 0xF0, 0x91, 0xA3, 0x8E, 0x00, 0xF0, 0x91, 0xA3, 0x8F, 0x00,
2579
  0xF0, 0x91, 0xA3, 0x90, 0x00, 0xF0, 0x91, 0xA3, 0x91, 0x00, 0xF0, 0x91, 0xA3, 0x92, 0x00, 0xF0,
2580
  0x91, 0xA3, 0x93, 0x00, 0xF0, 0x91, 0xA3, 0x94, 0x00, 0xF0, 0x91, 0xA3, 0x95, 0x00, 0xF0, 0x91,
2581
  0xA3, 0x96, 0x00, 0xF0, 0x91, 0xA3, 0x97, 0x00, 0xF0, 0x91, 0xA3, 0x98, 0x00, 0xF0, 0x91, 0xA3,
2582
  0x99, 0x00, 0xF0, 0x91, 0xA3, 0x9A, 0x00, 0xF0, 0x91, 0xA3, 0x9B, 0x00, 0xF0, 0x91, 0xA3, 0x9C,
2583
  0x00, 0xF0, 0x91, 0xA3, 0x9D, 0x00, 0xF0, 0x91, 0xA3, 0x9E, 0x00, 0xF0, 0x91, 0xA3, 0x9F, 0x00,
2584
  0xF0, 0x96, 0xB9, 0xA0, 0x00, 0xF0, 0x96, 0xB9, 0xA1, 0x00, 0xF0, 0x96, 0xB9, 0xA2, 0x00, 0xF0,
2585
  0x96, 0xB9, 0xA3, 0x00, 0xF0, 0x96, 0xB9, 0xA4, 0x00, 0xF0, 0x96, 0xB9, 0xA5, 0x00, 0xF0, 0x96,
2586
  0xB9, 0xA6, 0x00, 0xF0, 0x96, 0xB9, 0xA7, 0x00, 0xF0, 0x96, 0xB9, 0xA8, 0x00, 0xF0, 0x96, 0xB9,
2587
  0xA9, 0x00, 0xF0, 0x96, 0xB9, 0xAA, 0x00, 0xF0, 0x96, 0xB9, 0xAB, 0x00, 0xF0, 0x96, 0xB9, 0xAC,
2588
  0x00, 0xF0, 0x96, 0xB9, 0xAD, 0x00, 0xF0, 0x96, 0xB9, 0xAE, 0x00, 0xF0, 0x96, 0xB9, 0xAF, 0x00,
2589
  0xF0, 0x96, 0xB9, 0xB0, 0x00, 0xF0, 0x96, 0xB9, 0xB1, 0x00, 0xF0, 0x96, 0xB9, 0xB2, 0x00, 0xF0,
2590
  0x96, 0xB9, 0xB3, 0x00, 0xF0, 0x96, 0xB9, 0xB4, 0x00, 0xF0, 0x96, 0xB9, 0xB5, 0x00, 0xF0, 0x96,
2591
  0xB9, 0xB6, 0x00, 0xF0, 0x96, 0xB9, 0xB7, 0x00, 0xF0, 0x96, 0xB9, 0xB8, 0x00, 0xF0, 0x96, 0xB9,
2592
  0xB9, 0x00, 0xF0, 0x96, 0xB9, 0xBA, 0x00, 0xF0, 0x96, 0xB9, 0xBB, 0x00, 0xF0, 0x96, 0xB9, 0xBC,
2593
  0x00, 0xF0, 0x96, 0xB9, 0xBD, 0x00, 0xF0, 0x96, 0xB9, 0xBE, 0x00, 0xF0, 0x96, 0xB9, 0xBF, 0x00,
2594
  0xF0, 0x96, 0xBA, 0xBB, 0x00, 0xF0, 0x96, 0xBA, 0xBC, 0x00, 0xF0, 0x96, 0xBA, 0xBD, 0x00, 0xF0,
2595
  0x96, 0xBA, 0xBE, 0x00, 0xF0, 0x96, 0xBA, 0xBF, 0x00, 0xF0, 0x96, 0xBB, 0x80, 0x00, 0xF0, 0x96,
2596
  0xBB, 0x81, 0x00, 0xF0, 0x96, 0xBB, 0x82, 0x00, 0xF0, 0x96, 0xBB, 0x83, 0x00, 0xF0, 0x96, 0xBB,
2597
  0x84, 0x00, 0xF0, 0x96, 0xBB, 0x85, 0x00, 0xF0, 0x96, 0xBB, 0x86, 0x00, 0xF0, 0x96, 0xBB, 0x87,
2598
  0x00, 0xF0, 0x96, 0xBB, 0x88, 0x00, 0xF0, 0x96, 0xBB, 0x89, 0x00, 0xF0, 0x96, 0xBB, 0x8A, 0x00,
2599
  0xF0, 0x96, 0xBB, 0x8B, 0x00, 0xF0, 0x96, 0xBB, 0x8C, 0x00, 0xF0, 0x96, 0xBB, 0x8D, 0x00, 0xF0,
2600
  0x96, 0xBB, 0x8E, 0x00, 0xF0, 0x96, 0xBB, 0x8F, 0x00, 0xF0, 0x96, 0xBB, 0x90, 0x00, 0xF0, 0x96,
2601
  0xBB, 0x91, 0x00, 0xF0, 0x96, 0xBB, 0x92, 0x00, 0xF0, 0x96, 0xBB, 0x93, 0x00, 0xF0, 0x9D, 0x85,
2602
  0x97, 0xF0, 0x9D, 0x85, 0xA5, 0x00, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0x00, 0xF0,
2603
  0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0x00, 0xF0, 0x9D, 0x85, 0x98,
2604
  0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0x00, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
2605
  0xA5, 0xF0, 0x9D, 0x85, 0xB0, 0x00, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D,
2606
  0x85, 0xB1, 0x00, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB2, 0x00,
2607
  0xF0, 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0x00, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
2608
  0xA5, 0x00, 0xF0, 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0x00, 0xF0,
2609
  0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0x00, 0xF0, 0x9D, 0x86, 0xB9,
2610
  0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0x00, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
2611
  0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0x00, 0xC4, 0xB1, 0x00, 0xC8, 0xB7, 0x00, 0xE2, 0x88, 0x87, 0x00,
2612
  0xE2, 0x88, 0x82, 0x00, 0xF0, 0x9E, 0xA4, 0xA2, 0x00, 0xF0, 0x9E, 0xA4, 0xA3, 0x00, 0xF0, 0x9E,
2613
  0xA4, 0xA4, 0x00, 0xF0, 0x9E, 0xA4, 0xA5, 0x00, 0xF0, 0x9E, 0xA4, 0xA6, 0x00, 0xF0, 0x9E, 0xA4,
2614
  0xA7, 0x00, 0xF0, 0x9E, 0xA4, 0xA8, 0x00, 0xF0, 0x9E, 0xA4, 0xA9, 0x00, 0xF0, 0x9E, 0xA4, 0xAA,
2615
  0x00, 0xF0, 0x9E, 0xA4, 0xAB, 0x00, 0xF0, 0x9E, 0xA4, 0xAC, 0x00, 0xF0, 0x9E, 0xA4, 0xAD, 0x00,
2616
  0xF0, 0x9E, 0xA4, 0xAE, 0x00, 0xF0, 0x9E, 0xA4, 0xAF, 0x00, 0xF0, 0x9E, 0xA4, 0xB0, 0x00, 0xF0,
2617
  0x9E, 0xA4, 0xB1, 0x00, 0xF0, 0x9E, 0xA4, 0xB2, 0x00, 0xF0, 0x9E, 0xA4, 0xB3, 0x00, 0xF0, 0x9E,
2618
  0xA4, 0xB4, 0x00, 0xF0, 0x9E, 0xA4, 0xB5, 0x00, 0xF0, 0x9E, 0xA4, 0xB6, 0x00, 0xF0, 0x9E, 0xA4,
2619
  0xB7, 0x00, 0xF0, 0x9E, 0xA4, 0xB8, 0x00, 0xF0, 0x9E, 0xA4, 0xB9, 0x00, 0xF0, 0x9E, 0xA4, 0xBA,
2620
  0x00, 0xF0, 0x9E, 0xA4, 0xBB, 0x00, 0xF0, 0x9E, 0xA4, 0xBC, 0x00, 0xF0, 0x9E, 0xA4, 0xBD, 0x00,
2621
  0xF0, 0x9E, 0xA4, 0xBE, 0x00, 0xF0, 0x9E, 0xA4, 0xBF, 0x00, 0xF0, 0x9E, 0xA5, 0x80, 0x00, 0xF0,
2622
  0x9E, 0xA5, 0x81, 0x00, 0xF0, 0x9E, 0xA5, 0x82, 0x00, 0xF0, 0x9E, 0xA5, 0x83, 0x00, 0xD9, 0xAE,
2623
  0x00, 0xDA, 0xA1, 0x00, 0xD9, 0xAF, 0x00, 0x30, 0x2C, 0x00, 0x31, 0x2C, 0x00, 0x32, 0x2C, 0x00,
2624
  0x33, 0x2C, 0x00, 0x34, 0x2C, 0x00, 0x35, 0x2C, 0x00, 0x36, 0x2C, 0x00, 0x37, 0x2C, 0x00, 0x38,
2625
  0x2C, 0x00, 0x39, 0x2C, 0x00, 0xE3, 0x80, 0x94, 0x73, 0xE3, 0x80, 0x95, 0x00, 0x77, 0x7A, 0x00,
2626
  0x68, 0x76, 0x00, 0x73, 0x64, 0x00, 0x73, 0x73, 0x00, 0x70, 0x70, 0x76, 0x00, 0x77, 0x63, 0x00,
2627
  0x6D, 0x63, 0x00, 0x6D, 0x64, 0x00, 0x6D, 0x72, 0x00, 0x64, 0x6A, 0x00, 0xE3, 0x81, 0xBB, 0xE3,
2628
  0x81, 0x8B, 0x00, 0xE3, 0x82, 0xB3, 0xE3, 0x82, 0xB3, 0x00, 0xE5, 0xAD, 0x97, 0x00, 0xE5, 0x8F,
2629
  0x8C, 0x00, 0xE3, 0x83, 0x87, 0x00, 0xE5, 0xA4, 0x9A, 0x00, 0xE8, 0xA7, 0xA3, 0x00, 0xE4, 0xBA,
2630
  0xA4, 0x00, 0xE6, 0x98, 0xA0, 0x00, 0xE7, 0x84, 0xA1, 0x00, 0xE5, 0x89, 0x8D, 0x00, 0xE5, 0xBE,
2631
  0x8C, 0x00, 0xE5, 0x86, 0x8D, 0x00, 0xE6, 0x96, 0xB0, 0x00, 0xE5, 0x88, 0x9D, 0x00, 0xE7, 0xB5,
2632
  0x82, 0x00, 0xE8, 0xB2, 0xA9, 0x00, 0xE5, 0xA3, 0xB0, 0x00, 0xE5, 0x90, 0xB9, 0x00, 0xE6, 0xBC,
2633
  0x94, 0x00, 0xE6, 0x8A, 0x95, 0x00, 0xE6, 0x8D, 0x95, 0x00, 0xE9, 0x81, 0x8A, 0x00, 0xE6, 0x8C,
2634
  0x87, 0x00, 0xE6, 0x89, 0x93, 0x00, 0xE7, 0xA6, 0x81, 0x00, 0xE7, 0xA9, 0xBA, 0x00, 0xE5, 0x90,
2635
  0x88, 0x00, 0xE6, 0xBA, 0x80, 0x00, 0xE7, 0x94, 0xB3, 0x00, 0xE5, 0x89, 0xB2, 0x00, 0xE5, 0x96,
2636
  0xB6, 0x00, 0xE9, 0x85, 0x8D, 0x00, 0xE3, 0x80, 0x94, 0xE6, 0x9C, 0xAC, 0xE3, 0x80, 0x95, 0x00,
2637
  0xE3, 0x80, 0x94, 0xE4, 0xB8, 0x89, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x94, 0xE4, 0xBA, 0x8C,
2638
  0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x94, 0xE5, 0xAE, 0x89, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80,
2639
  0x94, 0xE7, 0x82, 0xB9, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x94, 0xE6, 0x89, 0x93, 0xE3, 0x80,
2640
  0x95, 0x00, 0xE3, 0x80, 0x94, 0xE7, 0x9B, 0x97, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x94, 0xE5,
2641
  0x8B, 0x9D, 0xE3, 0x80, 0x95, 0x00, 0xE3, 0x80, 0x94, 0xE6, 0x95, 0x97, 0xE3, 0x80, 0x95, 0x00,
2642
  0xE5, 0xBE, 0x97, 0x00, 0xE5, 0x8F, 0xAF, 0x00, 0xE4, 0xB8, 0xBD, 0x00, 0xE4, 0xB8, 0xB8, 0x00,
2643
  0xE4, 0xB9, 0x81, 0x00, 0xF0, 0xA0, 0x84, 0xA2, 0x00, 0xE4, 0xBD, 0xA0, 0x00, 0xE4, 0xBE, 0xBB,
2644
  0x00, 0xE5, 0x80, 0x82, 0x00, 0xE5, 0x81, 0xBA, 0x00, 0xE5, 0x82, 0x99, 0x00, 0xE5, 0x83, 0x8F,
2645
  0x00, 0xE3, 0x92, 0x9E, 0x00, 0xF0, 0xA0, 0x98, 0xBA, 0x00, 0xE5, 0x85, 0x94, 0x00, 0xE5, 0x85,
2646
  0xA4, 0x00, 0xE5, 0x85, 0xB7, 0x00, 0xF0, 0xA0, 0x94, 0x9C, 0x00, 0xE3, 0x92, 0xB9, 0x00, 0xE5,
2647
  0x85, 0xA7, 0x00, 0xF0, 0xA0, 0x95, 0x8B, 0x00, 0xE5, 0x86, 0x97, 0x00, 0xE5, 0x86, 0xA4, 0x00,
2648
  0xE4, 0xBB, 0x8C, 0x00, 0xE5, 0x86, 0xAC, 0x00, 0xF0, 0xA9, 0x87, 0x9F, 0x00, 0xE5, 0x88, 0x83,
2649
  0x00, 0xE3, 0x93, 0x9F, 0x00, 0xE5, 0x88, 0xBB, 0x00, 0xE5, 0x89, 0x86, 0x00, 0xE5, 0x89, 0xB7,
2650
  0x00, 0xE3, 0x94, 0x95, 0x00, 0xE5, 0x8C, 0x85, 0x00, 0xE5, 0x8C, 0x86, 0x00, 0xE5, 0x8D, 0x89,
2651
  0x00, 0xE5, 0x8D, 0x9A, 0x00, 0xE5, 0x8D, 0xB3, 0x00, 0xE5, 0x8D, 0xBD, 0x00, 0xE5, 0x8D, 0xBF,
2652
  0x00, 0xF0, 0xA0, 0xA8, 0xAC, 0x00, 0xE7, 0x81, 0xB0, 0x00, 0xE5, 0x8F, 0x8A, 0x00, 0xE5, 0x8F,
2653
  0x9F, 0x00, 0xF0, 0xA0, 0xAD, 0xA3, 0x00, 0xE5, 0x8F, 0xAB, 0x00, 0xE5, 0x8F, 0xB1, 0x00, 0xE5,
2654
  0x90, 0x86, 0x00, 0xE5, 0x92, 0x9E, 0x00, 0xE5, 0x90, 0xB8, 0x00, 0xE5, 0x91, 0x88, 0x00, 0xE5,
2655
  0x91, 0xA8, 0x00, 0xE5, 0x92, 0xA2, 0x00, 0xE5, 0x93, 0xB6, 0x00, 0xE5, 0x94, 0x90, 0x00, 0xE5,
2656
  0x95, 0x93, 0x00, 0xE5, 0x95, 0xA3, 0x00, 0xE5, 0x96, 0x84, 0x00, 0xE5, 0x96, 0xAB, 0x00, 0xE5,
2657
  0x96, 0xB3, 0x00, 0xE5, 0x97, 0x82, 0x00, 0xE5, 0x9C, 0x96, 0x00, 0xE5, 0x9C, 0x97, 0x00, 0xE5,
2658
  0x99, 0x91, 0x00, 0xE5, 0x99, 0xB4, 0x00, 0xE5, 0xA3, 0xAE, 0x00, 0xE5, 0x9F, 0x8E, 0x00, 0xE5,
2659
  0x9F, 0xB4, 0x00, 0xE5, 0xA0, 0x8D, 0x00, 0xE5, 0x9E, 0x8B, 0x00, 0xE5, 0xA0, 0xB2, 0x00, 0xE5,
2660
  0xA0, 0xB1, 0x00, 0xE5, 0xA2, 0xAC, 0x00, 0xF0, 0xA1, 0x93, 0xA4, 0x00, 0xE5, 0xA3, 0xB2, 0x00,
2661
  0xE5, 0xA3, 0xB7, 0x00, 0xE5, 0xA4, 0x86, 0x00, 0xE5, 0xA4, 0xA2, 0x00, 0xE5, 0xA5, 0xA2, 0x00,
2662
  0xF0, 0xA1, 0x9A, 0xA8, 0x00, 0xF0, 0xA1, 0x9B, 0xAA, 0x00, 0xE5, 0xA7, 0xAC, 0x00, 0xE5, 0xA8,
2663
  0x9B, 0x00, 0xE5, 0xA8, 0xA7, 0x00, 0xE5, 0xA7, 0x98, 0x00, 0xE5, 0xA9, 0xA6, 0x00, 0xE3, 0x9B,
2664
  0xAE, 0x00, 0xE3, 0x9B, 0xBC, 0x00, 0xE5, 0xAC, 0x88, 0x00, 0xE5, 0xAC, 0xBE, 0x00, 0xF0, 0xA1,
2665
  0xA7, 0x88, 0x00, 0xE5, 0xAF, 0x83, 0x00, 0xE5, 0xAF, 0x98, 0x00, 0xE5, 0xAF, 0xB3, 0x00, 0xF0,
2666
  0xA1, 0xAC, 0x98, 0x00, 0xE5, 0xAF, 0xBF, 0x00, 0xE5, 0xB0, 0x86, 0x00, 0xE5, 0xBD, 0x93, 0x00,
2667
  0xE3, 0x9E, 0x81, 0x00, 0xE5, 0xB1, 0xA0, 0x00, 0xE5, 0xB3, 0x80, 0x00, 0xE5, 0xB2, 0x8D, 0x00,
2668
  0xF0, 0xA1, 0xB7, 0xA4, 0x00, 0xE5, 0xB5, 0x83, 0x00, 0xF0, 0xA1, 0xB7, 0xA6, 0x00, 0xE5, 0xB5,
2669
  0xAE, 0x00, 0xE5, 0xB5, 0xAB, 0x00, 0xE5, 0xB5, 0xBC, 0x00, 0xE5, 0xB7, 0xA1, 0x00, 0xE5, 0xB7,
2670
  0xA2, 0x00, 0xE3, 0xA0, 0xAF, 0x00, 0xE5, 0xB7, 0xBD, 0x00, 0xE5, 0xB8, 0xA8, 0x00, 0xE5, 0xB8,
2671
  0xBD, 0x00, 0xE5, 0xB9, 0xA9, 0x00, 0xE3, 0xA1, 0xA2, 0x00, 0xF0, 0xA2, 0x86, 0x83, 0x00, 0xE3,
2672
  0xA1, 0xBC, 0x00, 0xE5, 0xBA, 0xB0, 0x00, 0xE5, 0xBA, 0xB3, 0x00, 0xE5, 0xBA, 0xB6, 0x00, 0xF0,
2673
  0xAA, 0x8E, 0x92, 0x00, 0xF0, 0xA2, 0x8C, 0xB1, 0x00, 0xE8, 0x88, 0x81, 0x00, 0xE5, 0xBC, 0xA2,
2674
  0x00, 0xE3, 0xA3, 0x87, 0x00, 0xF0, 0xA3, 0x8A, 0xB8, 0x00, 0xF0, 0xA6, 0x87, 0x9A, 0x00, 0xE5,
2675
  0xBD, 0xA2, 0x00, 0xE5, 0xBD, 0xAB, 0x00, 0xE3, 0xA3, 0xA3, 0x00, 0xE5, 0xBE, 0x9A, 0x00, 0xE5,
2676
  0xBF, 0x8D, 0x00, 0xE5, 0xBF, 0x97, 0x00, 0xE5, 0xBF, 0xB9, 0x00, 0xE6, 0x82, 0x81, 0x00, 0xE3,
2677
  0xA4, 0xBA, 0x00, 0xE3, 0xA4, 0x9C, 0x00, 0xF0, 0xA2, 0x9B, 0x94, 0x00, 0xE6, 0x83, 0x87, 0x00,
2678
  0xE6, 0x85, 0x88, 0x00, 0xE6, 0x85, 0x8C, 0x00, 0xE6, 0x85, 0xBA, 0x00, 0xE6, 0x86, 0xB2, 0x00,
2679
  0xE6, 0x86, 0xA4, 0x00, 0xE6, 0x86, 0xAF, 0x00, 0xE6, 0x87, 0x9E, 0x00, 0xE6, 0x88, 0x90, 0x00,
2680
  0xE6, 0x88, 0x9B, 0x00, 0xE6, 0x89, 0x9D, 0x00, 0xE6, 0x8A, 0xB1, 0x00, 0xE6, 0x8B, 0x94, 0x00,
2681
  0xE6, 0x8D, 0x90, 0x00, 0xF0, 0xA2, 0xAC, 0x8C, 0x00, 0xE6, 0x8C, 0xBD, 0x00, 0xE6, 0x8B, 0xBC,
2682
  0x00, 0xE6, 0x8D, 0xA8, 0x00, 0xE6, 0x8E, 0x83, 0x00, 0xE6, 0x8F, 0xA4, 0x00, 0xF0, 0xA2, 0xAF,
2683
  0xB1, 0x00, 0xE6, 0x90, 0xA2, 0x00, 0xE6, 0x8F, 0x85, 0x00, 0xE6, 0x8E, 0xA9, 0x00, 0xE3, 0xA8,
2684
  0xAE, 0x00, 0xE6, 0x91, 0xA9, 0x00, 0xE6, 0x91, 0xBE, 0x00, 0xE6, 0x92, 0x9D, 0x00, 0xE6, 0x91,
2685
  0xB7, 0x00, 0xE3, 0xA9, 0xAC, 0x00, 0xE6, 0x95, 0xAC, 0x00, 0xF0, 0xA3, 0x80, 0x8A, 0x00, 0xE6,
2686
  0x97, 0xA3, 0x00, 0xE6, 0x9B, 0xB8, 0x00, 0xE6, 0x99, 0x89, 0x00, 0xE3, 0xAC, 0x99, 0x00, 0xE3,
2687
  0xAC, 0x88, 0x00, 0xE3, 0xAB, 0xA4, 0x00, 0xE5, 0x86, 0x92, 0x00, 0xE5, 0x86, 0x95, 0x00, 0xE6,
2688
  0x9C, 0x80, 0x00, 0xE6, 0x9A, 0x9C, 0x00, 0xE8, 0x82, 0xAD, 0x00, 0xE4, 0x8F, 0x99, 0x00, 0xE6,
2689
  0x9C, 0xA1, 0x00, 0xE6, 0x9D, 0x9E, 0x00, 0xE6, 0x9D, 0x93, 0x00, 0xF0, 0xA3, 0x8F, 0x83, 0x00,
2690
  0xE3, 0xAD, 0x89, 0x00, 0xE6, 0x9F, 0xBA, 0x00, 0xE6, 0x9E, 0x85, 0x00, 0xE6, 0xA1, 0x92, 0x00,
2691
  0xF0, 0xA3, 0x91, 0xAD, 0x00, 0xE6, 0xA2, 0x8E, 0x00, 0xE6, 0xA0, 0x9F, 0x00, 0xE6, 0xA4, 0x94,
2692
  0x00, 0xE6, 0xA5, 0x82, 0x00, 0xE6, 0xA6, 0xA3, 0x00, 0xE6, 0xA7, 0xAA, 0x00, 0xE6, 0xAA, 0xA8,
2693
  0x00, 0xF0, 0xA3, 0x9A, 0xA3, 0x00, 0xE6, 0xAB, 0x9B, 0x00, 0xE3, 0xB0, 0x98, 0x00, 0xE6, 0xAC,
2694
  0xA1, 0x00, 0xF0, 0xA3, 0xA2, 0xA7, 0x00, 0xE6, 0xAD, 0x94, 0x00, 0xE3, 0xB1, 0x8E, 0x00, 0xE6,
2695
  0xAD, 0xB2, 0x00, 0xE6, 0xAE, 0x9F, 0x00, 0xE6, 0xAE, 0xBB, 0x00, 0xF0, 0xA3, 0xAA, 0x8D, 0x00,
2696
  0xF0, 0xA1, 0xB4, 0x8B, 0x00, 0xF0, 0xA3, 0xAB, 0xBA, 0x00, 0xE6, 0xB1, 0x8E, 0x00, 0xF0, 0xA3,
2697
  0xB2, 0xBC, 0x00, 0xE6, 0xB2, 0xBF, 0x00, 0xE6, 0xB3, 0x8D, 0x00, 0xE6, 0xB1, 0xA7, 0x00, 0xE6,
2698
  0xB4, 0x96, 0x00, 0xE6, 0xB4, 0xBE, 0x00, 0xE6, 0xB5, 0xA9, 0x00, 0xE6, 0xB5, 0xB8, 0x00, 0xE6,
2699
  0xB6, 0x85, 0x00, 0xF0, 0xA3, 0xB4, 0x9E, 0x00, 0xE6, 0xB4, 0xB4, 0x00, 0xE6, 0xB8, 0xAF, 0x00,
2700
  0xE6, 0xB9, 0xAE, 0x00, 0xE3, 0xB4, 0xB3, 0x00, 0xE6, 0xBB, 0x87, 0x00, 0xF0, 0xA3, 0xBB, 0x91,
2701
  0x00, 0xE6, 0xB7, 0xB9, 0x00, 0xE6, 0xBD, 0xAE, 0x00, 0xF0, 0xA3, 0xBD, 0x9E, 0x00, 0xF0, 0xA3,
2702
  0xBE, 0x8E, 0x00, 0xE6, 0xBF, 0x86, 0x00, 0xE7, 0x80, 0xB9, 0x00, 0xE7, 0x80, 0x9B, 0x00, 0xE3,
2703
  0xB6, 0x96, 0x00, 0xE7, 0x81, 0x8A, 0x00, 0xE7, 0x81, 0xBD, 0x00, 0xE7, 0x81, 0xB7, 0x00, 0xE7,
2704
  0x82, 0xAD, 0x00, 0xF0, 0xA0, 0x94, 0xA5, 0x00, 0xE7, 0x85, 0x85, 0x00, 0xF0, 0xA4, 0x89, 0xA3,
2705
  0x00, 0xE7, 0x86, 0x9C, 0x00, 0xF0, 0xA4, 0x8E, 0xAB, 0x00, 0xE7, 0x88, 0xA8, 0x00, 0xE7, 0x89,
2706
  0x90, 0x00, 0xF0, 0xA4, 0x98, 0x88, 0x00, 0xE7, 0x8A, 0x80, 0x00, 0xE7, 0x8A, 0x95, 0x00, 0xF0,
2707
  0xA4, 0x9C, 0xB5, 0x00, 0xF0, 0xA4, 0xA0, 0x94, 0x00, 0xE7, 0x8D, 0xBA, 0x00, 0xE7, 0x8E, 0x8B,
2708
  0x00, 0xE3, 0xBA, 0xAC, 0x00, 0xE7, 0x8E, 0xA5, 0x00, 0xE3, 0xBA, 0xB8, 0x00, 0xE7, 0x91, 0x87,
2709
  0x00, 0xE7, 0x91, 0x9C, 0x00, 0xE7, 0x92, 0x85, 0x00, 0xE7, 0x93, 0x8A, 0x00, 0xE3, 0xBC, 0x9B,
2710
  0x00, 0xE7, 0x94, 0xA4, 0x00, 0xF0, 0xA4, 0xB0, 0xB6, 0x00, 0xE7, 0x94, 0xBE, 0x00, 0xF0, 0xA4,
2711
  0xB2, 0x92, 0x00, 0xF0, 0xA2, 0x86, 0x9F, 0x00, 0xE7, 0x98, 0x90, 0x00, 0xF0, 0xA4, 0xBE, 0xA1,
2712
  0x00, 0xF0, 0xA4, 0xBE, 0xB8, 0x00, 0xF0, 0xA5, 0x81, 0x84, 0x00, 0xE3, 0xBF, 0xBC, 0x00, 0xE4,
2713
  0x80, 0x88, 0x00, 0xF0, 0xA5, 0x83, 0xB3, 0x00, 0xF0, 0xA5, 0x83, 0xB2, 0x00, 0xF0, 0xA5, 0x84,
2714
  0x99, 0x00, 0xF0, 0xA5, 0x84, 0xB3, 0x00, 0xE7, 0x9C, 0x9E, 0x00, 0xE7, 0x9C, 0x9F, 0x00, 0xE7,
2715
  0x9E, 0x8B, 0x00, 0xE4, 0x81, 0x86, 0x00, 0xE4, 0x82, 0x96, 0x00, 0xF0, 0xA5, 0x90, 0x9D, 0x00,
2716
  0xE7, 0xA1, 0x8E, 0x00, 0xE4, 0x83, 0xA3, 0x00, 0xF0, 0xA5, 0x98, 0xA6, 0x00, 0xF0, 0xA5, 0x9A,
2717
  0x9A, 0x00, 0xF0, 0xA5, 0x9B, 0x85, 0x00, 0xE7, 0xA7, 0xAB, 0x00, 0xE4, 0x84, 0xAF, 0x00, 0xE7,
2718
  0xA9, 0x8A, 0x00, 0xE7, 0xA9, 0x8F, 0x00, 0xF0, 0xA5, 0xA5, 0xBC, 0x00, 0xF0, 0xA5, 0xAA, 0xA7,
2719
  0x00, 0xE7, 0xAB, 0xAE, 0x00, 0xE4, 0x88, 0x82, 0x00, 0xF0, 0xA5, 0xAE, 0xAB, 0x00, 0xE7, 0xAF,
2720
  0x86, 0x00, 0xE7, 0xAF, 0x89, 0x00, 0xE4, 0x88, 0xA7, 0x00, 0xF0, 0xA5, 0xB2, 0x80, 0x00, 0xE7,
2721
  0xB3, 0x92, 0x00, 0xE4, 0x8A, 0xA0, 0x00, 0xE7, 0xB3, 0xA8, 0x00, 0xE7, 0xB3, 0xA3, 0x00, 0xE7,
2722
  0xB4, 0x80, 0x00, 0xF0, 0xA5, 0xBE, 0x86, 0x00, 0xE7, 0xB5, 0xA3, 0x00, 0xE4, 0x8C, 0x81, 0x00,
2723
  0xE7, 0xB7, 0x87, 0x00, 0xE7, 0xB8, 0x82, 0x00, 0xE7, 0xB9, 0x85, 0x00, 0xE4, 0x8C, 0xB4, 0x00,
2724
  0xF0, 0xA6, 0x88, 0xA8, 0x00, 0xF0, 0xA6, 0x89, 0x87, 0x00, 0xE4, 0x8D, 0x99, 0x00, 0xF0, 0xA6,
2725
  0x8B, 0x99, 0x00, 0xE7, 0xBD, 0xBA, 0x00, 0xF0, 0xA6, 0x8C, 0xBE, 0x00, 0xE7, 0xBE, 0x95, 0x00,
2726
  0xE7, 0xBF, 0xBA, 0x00, 0xF0, 0xA6, 0x93, 0x9A, 0x00, 0xF0, 0xA6, 0x94, 0xA3, 0x00, 0xE8, 0x81,
2727
  0xA0, 0x00, 0xF0, 0xA6, 0x96, 0xA8, 0x00, 0xE8, 0x81, 0xB0, 0x00, 0xF0, 0xA3, 0x8D, 0x9F, 0x00,
2728
  0xE4, 0x8F, 0x95, 0x00, 0xE8, 0x82, 0xB2, 0x00, 0xE8, 0x84, 0x83, 0x00, 0xE4, 0x90, 0x8B, 0x00,
2729
  0xE8, 0x84, 0xBE, 0x00, 0xE5, 0xAA, 0xB5, 0x00, 0xF0, 0xA6, 0x9E, 0xA7, 0x00, 0xF0, 0xA6, 0x9E,
2730
  0xB5, 0x00, 0xF0, 0xA3, 0x8E, 0x93, 0x00, 0xF0, 0xA3, 0x8E, 0x9C, 0x00, 0xE8, 0x88, 0x84, 0x00,
2731
  0xE8, 0xBE, 0x9E, 0x00, 0xE4, 0x91, 0xAB, 0x00, 0xE8, 0x8A, 0x91, 0x00, 0xE8, 0x8A, 0x8B, 0x00,
2732
  0xE8, 0x8A, 0x9D, 0x00, 0xE5, 0x8A, 0xB3, 0x00, 0xE8, 0x8A, 0xB1, 0x00, 0xE8, 0x8A, 0xB3, 0x00,
2733
  0xE8, 0x8A, 0xBD, 0x00, 0xE8, 0x8B, 0xA6, 0x00, 0xF0, 0xA6, 0xAC, 0xBC, 0x00, 0xE8, 0x8C, 0x9D,
2734
  0x00, 0xE8, 0x8D, 0xA3, 0x00, 0xE8, 0x8E, 0xAD, 0x00, 0xE8, 0x8C, 0xA3, 0x00, 0xE8, 0x8E, 0xBD,
2735
  0x00, 0xE8, 0x8F, 0xA7, 0x00, 0xE8, 0x8D, 0x93, 0x00, 0xE8, 0x8F, 0x8A, 0x00, 0xE8, 0x8F, 0x8C,
2736
  0x00, 0xE8, 0x8F, 0x9C, 0x00, 0xF0, 0xA6, 0xB0, 0xB6, 0x00, 0xF0, 0xA6, 0xB5, 0xAB, 0x00, 0xF0,
2737
  0xA6, 0xB3, 0x95, 0x00, 0xE4, 0x94, 0xAB, 0x00, 0xE8, 0x93, 0xB1, 0x00, 0xE8, 0x93, 0xB3, 0x00,
2738
  0xE8, 0x94, 0x96, 0x00, 0xF0, 0xA7, 0x8F, 0x8A, 0x00, 0xE8, 0x95, 0xA4, 0x00, 0xF0, 0xA6, 0xBC,
2739
  0xAC, 0x00, 0xE4, 0x95, 0x9D, 0x00, 0xE4, 0x95, 0xA1, 0x00, 0xF0, 0xA6, 0xBE, 0xB1, 0x00, 0xF0,
2740
  0xA7, 0x83, 0x92, 0x00, 0xE4, 0x95, 0xAB, 0x00, 0xE8, 0x99, 0x90, 0x00, 0xE8, 0x99, 0xA7, 0x00,
2741
  0xE8, 0x99, 0xA9, 0x00, 0xE8, 0x9A, 0xA9, 0x00, 0xE8, 0x9A, 0x88, 0x00, 0xE8, 0x9C, 0x8E, 0x00,
2742
  0xE8, 0x9B, 0xA2, 0x00, 0xE8, 0x9C, 0xA8, 0x00, 0xE8, 0x9D, 0xAB, 0x00, 0xE8, 0x9E, 0x86, 0x00,
2743
  0xE4, 0x97, 0x97, 0x00, 0xE8, 0x9F, 0xA1, 0x00, 0xE8, 0xA0, 0x81, 0x00, 0xE4, 0x97, 0xB9, 0x00,
2744
  0xE8, 0xA1, 0xA0, 0x00, 0xF0, 0xA7, 0x99, 0xA7, 0x00, 0xE8, 0xA3, 0x97, 0x00, 0xE8, 0xA3, 0x9E,
2745
  0x00, 0xE4, 0x98, 0xB5, 0x00, 0xE8, 0xA3, 0xBA, 0x00, 0xE3, 0x92, 0xBB, 0x00, 0xF0, 0xA7, 0xA2,
2746
  0xAE, 0x00, 0xF0, 0xA7, 0xA5, 0xA6, 0x00, 0xE4, 0x9A, 0xBE, 0x00, 0xE4, 0x9B, 0x87, 0x00, 0xE8,
2747
  0xAA, 0xA0, 0x00, 0xF0, 0xA7, 0xB2, 0xA8, 0x00, 0xE8, 0xB2, 0xAB, 0x00, 0xE8, 0xB3, 0x81, 0x00,
2748
  0xE8, 0xB4, 0x9B, 0x00, 0xE8, 0xB5, 0xB7, 0x00, 0xF0, 0xA7, 0xBC, 0xAF, 0x00, 0xF0, 0xA0, 0xA0,
2749
  0x84, 0x00, 0xE8, 0xB7, 0x8B, 0x00, 0xE8, 0xB6, 0xBC, 0x00, 0xE8, 0xB7, 0xB0, 0x00, 0xF0, 0xA0,
2750
  0xA3, 0x9E, 0x00, 0xE8, 0xBB, 0x94, 0x00, 0xF0, 0xA8, 0x97, 0x92, 0x00, 0xF0, 0xA8, 0x97, 0xAD,
2751
  0x00, 0xE9, 0x82, 0x94, 0x00, 0xE9, 0x83, 0xB1, 0x00, 0xE9, 0x84, 0x91, 0x00, 0xF0, 0xA8, 0x9C,
2752
  0xAE, 0x00, 0xE9, 0x84, 0x9B, 0x00, 0xE9, 0x88, 0xB8, 0x00, 0xE9, 0x8B, 0x97, 0x00, 0xE9, 0x8B,
2753
  0x98, 0x00, 0xE9, 0x89, 0xBC, 0x00, 0xE9, 0x8F, 0xB9, 0x00, 0xE9, 0x90, 0x95, 0x00, 0xF0, 0xA8,
2754
  0xAF, 0xBA, 0x00, 0xE9, 0x96, 0x8B, 0x00, 0xE4, 0xA6, 0x95, 0x00, 0xE9, 0x96, 0xB7, 0x00, 0xF0,
2755
  0xA8, 0xB5, 0xB7, 0x00, 0xE4, 0xA7, 0xA6, 0x00, 0xE9, 0x9B, 0x83, 0x00, 0xE5, 0xB6, 0xB2, 0x00,
2756
  0xE9, 0x9C, 0xA3, 0x00, 0xF0, 0xA9, 0x85, 0x85, 0x00, 0xF0, 0xA9, 0x88, 0x9A, 0x00, 0xE4, 0xA9,
2757
  0xAE, 0x00, 0xE4, 0xA9, 0xB6, 0x00, 0xE9, 0x9F, 0xA0, 0x00, 0xF0, 0xA9, 0x90, 0x8A, 0x00, 0xE4,
2758
  0xAA, 0xB2, 0x00, 0xF0, 0xA9, 0x92, 0x96, 0x00, 0xE9, 0xA0, 0xA9, 0x00, 0xF0, 0xA9, 0x96, 0xB6,
2759
  0x00, 0xE9, 0xA3, 0xA2, 0x00, 0xE4, 0xAC, 0xB3, 0x00, 0xE9, 0xA4, 0xA9, 0x00, 0xE9, 0xA6, 0xA7,
2760
  0x00, 0xE9, 0xA7, 0x82, 0x00, 0xE9, 0xA7, 0xBE, 0x00, 0xE4, 0xAF, 0x8E, 0x00, 0xF0, 0xA9, 0xAC,
2761
  0xB0, 0x00, 0xE9, 0xB1, 0x80, 0x00, 0xE9, 0xB3, 0xBD, 0x00, 0xE4, 0xB3, 0x8E, 0x00, 0xE4, 0xB3,
2762
  0xAD, 0x00, 0xE9, 0xB5, 0xA7, 0x00, 0xF0, 0xAA, 0x83, 0x8E, 0x00, 0xE4, 0xB3, 0xB8, 0x00, 0xF0,
2763
  0xAA, 0x84, 0x85, 0x00, 0xF0, 0xAA, 0x88, 0x8E, 0x00, 0xF0, 0xAA, 0x8A, 0x91, 0x00, 0xE4, 0xB5,
2764
  0x96, 0x00, 0xE9, 0xBB, 0xBE, 0x00, 0xE9, 0xBC, 0x85, 0x00, 0xE9, 0xBC, 0x8F, 0x00, 0xE9, 0xBC,
2765
  0x96, 0x00, 0xF0, 0xAA, 0x98, 0x80, 0x00
2766
};
2767
2768
} // namespace ada::idna
2769
#endif // ADA_IDNA_MAPPING_TABLE_H
2770
/* end file src/mapping_tables.cpp */
2771
2772
namespace ada::idna {
2773
2774
// --- O(1) two-level table lookup ---------------------------------------------
2775
//
2776
// Returns one of:
2777
//   IDNA_VALID      - keep code point in output unchanged
2778
//   IDNA_DISALLOWED - code point is not allowed (map() returns error)
2779
//   IDNA_IGNORED    - code point is ignored (index 0 = empty UTF-8 entry)
2780
//   other           - byte offset into idna_utf8_mappings[] (null-terminated)
2781
//
2782
// The two-level table covers [0, IDNA_LOW_RANGE_END).  All constants
2783
// (LOW_RANGE_END, HIGH_IGNORED_*) are generated from the IDNA table itself;
2784
// no Unicode version-specific values are hardcoded here.
2785
//
2786
1.19M
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
1.19M
  if (cp < IDNA_LOW_RANGE_END) {
2789
1.17M
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
1.17M
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
591k
      uint32_t bit_idx =
2793
591k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
591k
          (cp & IDNA_BLOCK_MASK);
2795
591k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
591k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
591k
    }
2798
587k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
1.17M
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
11.5k
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
3.09k
    return IDNA_IGNORED;
2805
3.09k
  }
2806
2807
8.47k
  return IDNA_DISALLOWED;
2808
11.5k
}
idna.cc:ada::idna::idna_lookup(unsigned int)
Line
Count
Source
2786
310k
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
310k
  if (cp < IDNA_LOW_RANGE_END) {
2789
309k
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
309k
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
141k
      uint32_t bit_idx =
2793
141k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
141k
          (cp & IDNA_BLOCK_MASK);
2795
141k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
141k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
141k
    }
2798
168k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
309k
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
587
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
0
    return IDNA_IGNORED;
2805
0
  }
2806
2807
587
  return IDNA_DISALLOWED;
2808
587
}
ada.cpp:ada::idna::idna_lookup(unsigned int)
Line
Count
Source
2786
169k
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
169k
  if (cp < IDNA_LOW_RANGE_END) {
2789
169k
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
169k
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
88.7k
      uint32_t bit_idx =
2793
88.7k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
88.7k
          (cp & IDNA_BLOCK_MASK);
2795
88.7k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
88.7k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
88.7k
    }
2798
80.5k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
169k
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
6
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
0
    return IDNA_IGNORED;
2805
0
  }
2806
2807
6
  return IDNA_DISALLOWED;
2808
6
}
serializers.cc:ada::idna::idna_lookup(unsigned int)
Line
Count
Source
2786
27.5k
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
27.5k
  if (cp < IDNA_LOW_RANGE_END) {
2789
27.4k
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
27.4k
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
16.8k
      uint32_t bit_idx =
2793
16.8k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
16.8k
          (cp & IDNA_BLOCK_MASK);
2795
16.8k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
16.8k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
16.8k
    }
2798
10.5k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
27.4k
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
76
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
13
    return IDNA_IGNORED;
2805
13
  }
2806
2807
63
  return IDNA_DISALLOWED;
2808
76
}
Unexecuted instantiation: can_parse.cc:ada::idna::idna_lookup(unsigned int)
Unexecuted instantiation: unicode.cc:ada::idna::idna_lookup(unsigned int)
parse.cc:ada::idna::idna_lookup(unsigned int)
Line
Count
Source
2786
247k
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
247k
  if (cp < IDNA_LOW_RANGE_END) {
2789
246k
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
246k
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
122k
      uint32_t bit_idx =
2793
122k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
122k
          (cp & IDNA_BLOCK_MASK);
2795
122k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
122k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
122k
    }
2798
123k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
246k
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
652
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
206
    return IDNA_IGNORED;
2805
206
  }
2806
2807
446
  return IDNA_DISALLOWED;
2808
652
}
url_pattern.cc:ada::idna::idna_lookup(unsigned int)
Line
Count
Source
2786
435k
static uint16_t idna_lookup(uint32_t cp) noexcept {
2787
  // -- Two-level table covers the full active code-point range ---------------
2788
435k
  if (cp < IDNA_LOW_RANGE_END) {
2789
425k
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
2790
425k
    if (ref & IDNA_BOOL_FLAG) {
2791
      // Boolean block: one bit per code point, 1 = VALID, 0 = DISALLOWED.
2792
221k
      uint32_t bit_idx =
2793
221k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
2794
221k
          (cp & IDNA_BLOCK_MASK);
2795
221k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
2796
221k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
2797
221k
    }
2798
203k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
2799
425k
  }
2800
2801
  // -- Variation selectors supplement (U+E0100-U+E01EF): all ignored ---------
2802
  // Everything else above IDNA_LOW_RANGE_END is disallowed.
2803
10.2k
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
2804
2.87k
    return IDNA_IGNORED;
2805
2.87k
  }
2806
2807
7.37k
  return IDNA_DISALLOWED;
2808
10.2k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::idna_lookup(unsigned int)
2809
2810
// --- Decode one UTF-8 code point ---------------------------------------------
2811
// Advances *ptr past the bytes consumed.  The mapping table is trusted to be
2812
// well-formed UTF-8, so no validity checking is performed.
2813
1.12M
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
1.12M
  uint8_t b0 = *ptr++;
2815
1.12M
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
906k
  if (b0 < 0xE0u) {
2817
525k
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
525k
    cp |= (*ptr++ & 0x3Fu);
2819
525k
    return static_cast<char32_t>(cp);
2820
525k
  }
2821
381k
  if (b0 < 0xF0u) {
2822
376k
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
376k
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
376k
    cp |= (*ptr++ & 0x3Fu);
2825
376k
    return static_cast<char32_t>(cp);
2826
376k
  }
2827
  // 4-byte sequence
2828
4.63k
  uint32_t cp = (b0 & 0x07u) << 18;
2829
4.63k
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
4.63k
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
4.63k
  cp |= (*ptr++ & 0x3Fu);
2832
4.63k
  return static_cast<char32_t>(cp);
2833
381k
}
idna.cc:ada::idna::utf8_next(unsigned char const*&)
Line
Count
Source
2813
297k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
297k
  uint8_t b0 = *ptr++;
2815
297k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
215k
  if (b0 < 0xE0u) {
2817
198k
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
198k
    cp |= (*ptr++ & 0x3Fu);
2819
198k
    return static_cast<char32_t>(cp);
2820
198k
  }
2821
17.0k
  if (b0 < 0xF0u) {
2822
16.1k
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
16.1k
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
16.1k
    cp |= (*ptr++ & 0x3Fu);
2825
16.1k
    return static_cast<char32_t>(cp);
2826
16.1k
  }
2827
  // 4-byte sequence
2828
906
  uint32_t cp = (b0 & 0x07u) << 18;
2829
906
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
906
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
906
  cp |= (*ptr++ & 0x3Fu);
2832
906
  return static_cast<char32_t>(cp);
2833
17.0k
}
ada.cpp:ada::idna::utf8_next(unsigned char const*&)
Line
Count
Source
2813
353k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
353k
  uint8_t b0 = *ptr++;
2815
353k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
297k
  if (b0 < 0xE0u) {
2817
189k
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
189k
    cp |= (*ptr++ & 0x3Fu);
2819
189k
    return static_cast<char32_t>(cp);
2820
189k
  }
2821
107k
  if (b0 < 0xF0u) {
2822
106k
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
106k
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
106k
    cp |= (*ptr++ & 0x3Fu);
2825
106k
    return static_cast<char32_t>(cp);
2826
106k
  }
2827
  // 4-byte sequence
2828
216
  uint32_t cp = (b0 & 0x07u) << 18;
2829
216
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
216
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
216
  cp |= (*ptr++ & 0x3Fu);
2832
216
  return static_cast<char32_t>(cp);
2833
107k
}
serializers.cc:ada::idna::utf8_next(unsigned char const*&)
Line
Count
Source
2813
4.23k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
4.23k
  uint8_t b0 = *ptr++;
2815
4.23k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
1.18k
  if (b0 < 0xE0u) {
2817
774
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
774
    cp |= (*ptr++ & 0x3Fu);
2819
774
    return static_cast<char32_t>(cp);
2820
774
  }
2821
410
  if (b0 < 0xF0u) {
2822
207
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
207
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
207
    cp |= (*ptr++ & 0x3Fu);
2825
207
    return static_cast<char32_t>(cp);
2826
207
  }
2827
  // 4-byte sequence
2828
203
  uint32_t cp = (b0 & 0x07u) << 18;
2829
203
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
203
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
203
  cp |= (*ptr++ & 0x3Fu);
2832
203
  return static_cast<char32_t>(cp);
2833
410
}
Unexecuted instantiation: can_parse.cc:ada::idna::utf8_next(unsigned char const*&)
Unexecuted instantiation: unicode.cc:ada::idna::utf8_next(unsigned char const*&)
parse.cc:ada::idna::utf8_next(unsigned char const*&)
Line
Count
Source
2813
378k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
378k
  uint8_t b0 = *ptr++;
2815
378k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
327k
  if (b0 < 0xE0u) {
2817
96.8k
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
96.8k
    cp |= (*ptr++ & 0x3Fu);
2819
96.8k
    return static_cast<char32_t>(cp);
2820
96.8k
  }
2821
230k
  if (b0 < 0xF0u) {
2822
228k
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
228k
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
228k
    cp |= (*ptr++ & 0x3Fu);
2825
228k
    return static_cast<char32_t>(cp);
2826
228k
  }
2827
  // 4-byte sequence
2828
1.99k
  uint32_t cp = (b0 & 0x07u) << 18;
2829
1.99k
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
1.99k
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
1.99k
  cp |= (*ptr++ & 0x3Fu);
2832
1.99k
  return static_cast<char32_t>(cp);
2833
230k
}
url_pattern.cc:ada::idna::utf8_next(unsigned char const*&)
Line
Count
Source
2813
94.9k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
2814
94.9k
  uint8_t b0 = *ptr++;
2815
94.9k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
2816
65.3k
  if (b0 < 0xE0u) {
2817
39.4k
    uint32_t cp = (b0 & 0x1Fu) << 6;
2818
39.4k
    cp |= (*ptr++ & 0x3Fu);
2819
39.4k
    return static_cast<char32_t>(cp);
2820
39.4k
  }
2821
25.8k
  if (b0 < 0xF0u) {
2822
24.5k
    uint32_t cp = (b0 & 0x0Fu) << 12;
2823
24.5k
    cp |= ((*ptr++ & 0x3Fu) << 6);
2824
24.5k
    cp |= (*ptr++ & 0x3Fu);
2825
24.5k
    return static_cast<char32_t>(cp);
2826
24.5k
  }
2827
  // 4-byte sequence
2828
1.32k
  uint32_t cp = (b0 & 0x07u) << 18;
2829
1.32k
  cp |= ((*ptr++ & 0x3Fu) << 12);
2830
1.32k
  cp |= ((*ptr++ & 0x3Fu) << 6);
2831
1.32k
  cp |= (*ptr++ & 0x3Fu);
2832
1.32k
  return static_cast<char32_t>(cp);
2833
25.8k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::utf8_next(unsigned char const*&)
2834
2835
// --- ASCII fast path
2836
// ----------------------------------------------------------
2837
172k
void ascii_map(char* input, size_t length) {
2838
517k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
517k
    return 0x101010101010101ull * v;
2840
517k
  };
idna.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Line
Count
Source
2838
36.2k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
36.2k
    return 0x101010101010101ull * v;
2840
36.2k
  };
ada.cpp:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Line
Count
Source
2838
62.1k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
62.1k
    return 0x101010101010101ull * v;
2840
62.1k
  };
serializers.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Line
Count
Source
2838
3.60k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
3.60k
    return 0x101010101010101ull * v;
2840
3.60k
  };
Unexecuted instantiation: can_parse.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Unexecuted instantiation: unicode.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
parse.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Line
Count
Source
2838
75.1k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
75.1k
    return 0x101010101010101ull * v;
2840
75.1k
  };
url_pattern.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
Line
Count
Source
2838
340k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
340k
    return 0x101010101010101ull * v;
2840
340k
  };
Unexecuted instantiation: url_search_params.cc:ada::idna::ascii_map(char*, unsigned long)::$_0::operator()(unsigned char) const
2841
172k
  uint64_t broadcast_80 = broadcast(0x80);
2842
172k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2843
172k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2844
172k
  size_t i = 0;
2845
2846
331k
  for (; i + 7 < length; i += 8) {
2847
159k
    uint64_t word{};
2848
159k
    std::memcpy(&word, input + i, sizeof(word));
2849
159k
    word ^=
2850
159k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2851
159k
    std::memcpy(input + i, &word, sizeof(word));
2852
159k
  }
2853
172k
  if (i < length) {
2854
156k
    uint64_t word{};
2855
156k
    std::memcpy(&word, input + i, length - i);
2856
156k
    word ^=
2857
156k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2858
156k
    std::memcpy(input + i, &word, length - i);
2859
156k
  }
2860
172k
}
2861
2862
// --- IDNA map
2863
// ----------------------------------------------------------------- Maps each
2864
// code point according to IDNA processing. Returns an empty string on error
2865
// (disallowed code point encountered).
2866
134k
bool map(std::u32string_view input, std::u32string& out) {
2867
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
2868
  //  For each code point in the domain_name string, look up the status
2869
  //  value in Section 5, [IDNA Mapping
2870
  //  Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table),
2871
  //  and take the following actions:
2872
  //    * disallowed: Leave the code point unchanged in the string, and
2873
  //    record that there was an error.
2874
  //    * ignored: Remove the code point from the string.
2875
  //    * mapped: Replace the code point in the string by the value for
2876
  //    the mapping in Section 5, [IDNA Mapping
2877
  //    Table](https://www.unicode.org/reports/tr46/#IDNA_Mapping_Table).
2878
  //    * valid: Leave the code point unchanged in the string.
2879
134k
  out.clear();
2880
134k
  out.reserve(input.size());
2881
1.19M
  for (char32_t x : input) {
2882
1.19M
    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
2883
1.19M
    if (status == IDNA_DISALLOWED) {
2884
11.4k
      return false;
2885
11.4k
    }
2886
1.17M
    if (status == IDNA_VALID) {
2887
952k
      out.push_back(x);
2888
952k
      continue;
2889
952k
    }
2890
    // IDNA_IGNORED (status==0) falls through: idna_utf8_mappings[0] == 0x00
2891
    // (null terminator), so the decode loop below produces nothing.
2892
2893
    // Mapped (or ignored): decode null-terminated UTF-8 from the mapping table.
2894
225k
    const uint8_t* ptr = idna_utf8_mappings + status;
2895
1.35M
    while (*ptr != 0) {
2896
1.12M
      out.push_back(utf8_next(ptr));
2897
1.12M
    }
2898
225k
  }
2899
122k
  return true;
2900
134k
}
2901
2902
3.49k
std::u32string map(std::u32string_view input) {
2903
3.49k
  std::u32string answer;
2904
3.49k
  if (!map(input, answer)) {
2905
24
    return {};
2906
24
  }
2907
3.47k
  return answer;
2908
3.49k
}
2909
2910
}  // namespace ada::idna
2911
/* end file src/mapping.cpp */
2912
/* begin file src/normalization.cpp */
2913
/* begin file src/normalization_tables.cpp */
2914
// IDNA  17.0.0
2915
2916
// clang-format off
2917
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
2918
#define ADA_IDNA_NORMALIZATION_TABLES_H
2919
#include <cstdint>
2920
2921
/**
2922
 * Unicode Standard Annex #15
2923
 *
2924
 * UNICODE NORMALIZATION FORMS
2925
 * https://www.unicode.org/reports/tr15/
2926
 *
2927
 * See https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/data/data_norm.h for reference.
2928
 */
2929
2930
namespace ada::idna {
2931
2932
const uint8_t decomposition_index[4352] = {
2933
    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  9,  10, 11, 12, 13, 14, 15, 7,  7,
2934
    7,  7,  7,  7,  7,  7,  7,  7,  16, 7,  17, 18, 19, 20, 21, 22, 23, 24, 7,
2935
    7,  7,  7,  7,  25, 7,  26, 27, 28, 29, 30, 31, 32, 33, 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,  34, 35, 7,  7,  7,
2942
    36, 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,  37, 38, 39, 40, 41, 42, 43, 7,  7,  7,  7,  7,  7,  7,  44, 7,  7,
2947
    7,  7,  7,  7,  7,  7,  45, 46, 7,  47, 48, 49, 7,  7,  7,  50, 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,  51, 7,  52, 53, 54, 55, 56, 7,  7,  7,
2958
    7,  7,  7,  7,  7,  57, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  58,
2959
    59, 7,  60, 61, 62, 7,  7,  7,  7,  7,  7,  7,  7,  63, 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
    64, 65, 66, 7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2974
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2975
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2976
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2977
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2978
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2979
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2980
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2981
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2982
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2983
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2984
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2985
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2986
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2987
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2988
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2989
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2990
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2991
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2992
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2993
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2994
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2995
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2996
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2997
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2998
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
2999
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3000
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3001
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3002
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3003
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3004
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3005
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3006
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3007
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3008
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3009
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3010
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3011
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3012
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3013
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3014
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3015
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3016
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3017
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3018
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3019
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3020
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3021
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3022
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3023
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3024
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3025
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3026
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3027
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3028
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3029
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3030
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3031
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3032
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3033
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3034
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3035
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3036
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3037
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3038
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3039
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3040
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3041
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3042
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3043
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3044
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3045
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3046
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3047
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3048
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3049
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3050
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3051
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3052
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3053
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3054
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3055
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3056
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3057
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3058
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3059
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3060
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3061
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3062
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3063
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3064
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3065
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3066
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3067
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3068
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3069
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3070
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3071
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3072
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3073
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3074
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3075
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3076
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3077
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3078
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3079
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3080
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3081
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3082
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3083
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3084
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3085
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3086
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3087
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3088
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3089
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3090
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3091
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3092
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3093
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3094
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3095
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3096
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3097
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3098
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3099
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3100
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3101
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3102
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3103
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3104
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3105
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3106
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3107
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3108
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3109
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3110
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3111
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3112
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3113
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3114
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3115
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3116
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3117
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3118
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3119
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3120
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3121
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3122
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3123
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3124
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3125
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3126
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3127
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3128
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3129
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3130
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3131
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3132
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3133
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3134
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3135
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3136
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3137
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3138
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3139
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3140
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3141
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3142
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3143
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3144
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3145
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3146
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3147
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3148
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3149
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3150
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3151
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3152
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3153
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3154
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3155
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3156
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3157
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3158
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3159
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3160
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3161
    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
3162
    7};
3163
3164
const uint16_t decomposition_block[67][257] = {
3165
    {4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3166
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3167
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3168
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3169
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3170
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3171
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3172
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3173
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3174
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
3175
     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   5,   8,   8,   8,   8,
3176
     8,   8,   8,   9,   16,  17,  20,  20,  20,  20,  21,  28,  28,  29,  33,
3177
     37,  45,  48,  48,  49,  57,  61,  64,  65,  77,  89,  100, 100, 108, 116,
3178
     124, 132, 140, 148, 148, 156, 164, 172, 180, 188, 196, 204, 212, 220, 220,
3179
     228, 236, 244, 252, 260, 268, 268, 268, 276, 284, 292, 300, 308, 308, 308,
3180
     316, 324, 332, 340, 348, 356, 356, 364, 372, 380, 388, 396, 404, 412, 420,
3181
     428, 428, 436, 444, 452, 460, 468, 476, 476, 476, 484, 492, 500, 508, 516,
3182
     516, 524},
3183
    {524,  532,  540,  548,  556,  564,  572,  580,  588,  596,  604,  612,
3184
     620,  628,  636,  644,  652,  652,  652,  660,  668,  676,  684,  692,
3185
     700,  708,  716,  724,  732,  740,  748,  756,  764,  772,  780,  788,
3186
     796,  804,  812,  812,  812,  820,  828,  836,  844,  852,  860,  868,
3187
     876,  884,  885,  893,  900,  908,  916,  924,  932,  932,  940,  948,
3188
     956,  964,  972,  981,  989,  996,  996,  996,  1004, 1012, 1020, 1028,
3189
     1036, 1045, 1052, 1052, 1052, 1060, 1068, 1076, 1084, 1092, 1100, 1100,
3190
     1100, 1108, 1116, 1124, 1132, 1140, 1148, 1156, 1164, 1172, 1180, 1188,
3191
     1196, 1204, 1212, 1220, 1228, 1236, 1244, 1244, 1244, 1252, 1260, 1268,
3192
     1276, 1284, 1292, 1300, 1308, 1316, 1324, 1332, 1340, 1348, 1356, 1364,
3193
     1372, 1380, 1388, 1396, 1404, 1412, 1420, 1429, 1432, 1432, 1432, 1432,
3194
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3195
     1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432, 1432,
3196
     1432, 1432, 1432, 1432, 1432, 1440, 1448, 1448, 1448, 1448, 1448, 1448,
3197
     1448, 1448, 1448, 1448, 1448, 1448, 1448, 1448, 1456, 1464, 1464, 1464,
3198
     1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464, 1464,
3199
     1464, 1464, 1464, 1464, 1465, 1477, 1489, 1501, 1509, 1517, 1525, 1533,
3200
     1541, 1548, 1556, 1564, 1572, 1580, 1588, 1596, 1604, 1612, 1624, 1636,
3201
     1648, 1660, 1672, 1684, 1696, 1708, 1708, 1720, 1732, 1744, 1756, 1764,
3202
     1772, 1772, 1772, 1780, 1788, 1796, 1804, 1812, 1820, 1832, 1844, 1852,
3203
     1860, 1869, 1877, 1885, 1892, 1900, 1908, 1908, 1908, 1916, 1924, 1936,
3204
     1948, 1956, 1964, 1972, 1980},
3205
    {1980, 1988, 1996, 2004, 2012, 2020, 2028, 2036, 2044, 2052, 2060, 2068,
3206
     2076, 2084, 2092, 2100, 2108, 2116, 2124, 2132, 2140, 2148, 2156, 2164,
3207
     2172, 2180, 2188, 2196, 2204, 2204, 2204, 2212, 2220, 2220, 2220, 2220,
3208
     2220, 2220, 2220, 2228, 2236, 2244, 2252, 2264, 2276, 2288, 2300, 2308,
3209
     2316, 2328, 2340, 2348, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3210
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3211
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3212
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3213
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3214
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3215
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3216
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3217
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3218
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356,
3219
     2356, 2356, 2356, 2356, 2356, 2356, 2356, 2356, 2357, 2361, 2365, 2369,
3220
     2373, 2377, 2381, 2385, 2389, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3221
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3222
     2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392, 2392,
3223
     2393, 2401, 2409, 2417, 2425, 2433, 2440, 2440, 2441, 2445, 2449, 2453,
3224
     2457, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3225
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3226
     2460, 2460, 2460, 2460, 2460},
3227
    {2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3228
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3229
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3230
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3231
     2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460, 2460,
3232
     2460, 2460, 2460, 2460, 2460, 2464, 2468, 2468, 2472, 2480, 2480, 2480,
3233
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3234
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3235
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480,
3236
     2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2480, 2484, 2484, 2484,
3237
     2484, 2484, 2485, 2492, 2492, 2492, 2492, 2496, 2496, 2496, 2496, 2496,
3238
     2497, 2506, 2512, 2520, 2524, 2532, 2540, 2548, 2548, 2556, 2556, 2564,
3239
     2572, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3240
     2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584, 2584,
3241
     2584, 2584, 2584, 2592, 2600, 2608, 2616, 2624, 2632, 2644, 2644, 2644,
3242
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644,
3243
     2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2644, 2652,
3244
     2660, 2668, 2676, 2684, 2685, 2689, 2693, 2698, 2706, 2713, 2717, 2720,
3245
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3246
     2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720, 2720,
3247
     2721, 2725, 2729, 2732, 2733, 2737, 2740, 2740, 2740, 2741, 2744, 2744,
3248
     2744, 2744, 2744, 2744, 2744},
3249
    {2744, 2752, 2760, 2760, 2768, 2768, 2768, 2768, 2776, 2776, 2776, 2776,
3250
     2776, 2784, 2792, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800, 2800,
3251
     2800, 2800, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3252
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808,
3253
     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2808, 2816, 2816,
3254
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816,
3255
     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2824, 2832, 2832,
3256
     2840, 2840, 2840, 2840, 2848, 2848, 2848, 2848, 2848, 2856, 2864, 2872,
3257
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872,
3258
     2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2872, 2880,
3259
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3260
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3261
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3262
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3263
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3264
     2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888, 2888,
3265
     2888, 2888, 2896, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904,
3266
     2904, 2904, 2904, 2904, 2904, 2912, 2920, 2928, 2936, 2936, 2936, 2944,
3267
     2952, 2952, 2952, 2960, 2968, 2976, 2984, 2992, 3000, 3000, 3000, 3008,
3268
     3016, 3024, 3032, 3040, 3048, 3048, 3048, 3056, 3064, 3072, 3080, 3088,
3269
     3096, 3104, 3112, 3120, 3128, 3136, 3144, 3144, 3144, 3152, 3160, 3160,
3270
     3160, 3160, 3160, 3160, 3160},
3271
    {3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3272
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3273
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3274
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3275
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3276
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3277
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3278
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3279
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3280
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3281
     3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160, 3160,
3282
     3160, 3160, 3160, 3161, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3283
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3284
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3285
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3286
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3287
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3288
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3289
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3290
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3291
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3292
     3168, 3168, 3168, 3168, 3168},
3293
    {3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3294
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168,
3295
     3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3168, 3176,
3296
     3184, 3192, 3200, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3297
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3298
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3299
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3300
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3301
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208,
3302
     3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3208, 3209, 3217, 3225,
3303
     3233, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3304
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3305
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3306
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3307
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3308
     3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240, 3240,
3309
     3240, 3248, 3248, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256,
3310
     3256, 3256, 3256, 3256, 3256, 3256, 3256, 3256, 3264, 3264, 3264, 3264,
3311
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3312
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3313
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3314
     3264, 3264, 3264, 3264, 3264},
3315
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3316
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3317
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3318
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3319
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3320
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3321
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3322
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3323
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3324
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3325
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3326
    {3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3327
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3328
     3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264, 3264,
3329
     3264, 3264, 3264, 3264, 3264, 3264, 3272, 3272, 3272, 3272, 3272, 3272,
3330
     3272, 3272, 3280, 3280, 3280, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3331
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3332
     3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288, 3288,
3333
     3288, 3288, 3288, 3288, 3288, 3296, 3304, 3312, 3320, 3328, 3336, 3344,
3334
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3335
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3336
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3337
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3338
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3339
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3340
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3341
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3342
     3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352, 3352,
3343
     3360, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368, 3368,
3344
     3368, 3368, 3368, 3368, 3368, 3376, 3384, 3384, 3392, 3392, 3392, 3392,
3345
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3346
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3347
     3392, 3392, 3392, 3392, 3392},
3348
    {3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3349
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3350
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3351
     3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392, 3392,
3352
     3392, 3392, 3392, 3392, 3400, 3400, 3400, 3408, 3408, 3408, 3408, 3408,
3353
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3354
     3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408, 3408,
3355
     3408, 3408, 3408, 3408, 3408, 3408, 3416, 3424, 3432, 3432, 3432, 3440,
3356
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3357
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3358
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3359
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3360
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3361
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3362
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3363
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3364
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3365
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3366
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3367
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3368
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3369
     3440, 3440, 3440, 3440, 3440},
3370
    {3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3371
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3372
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3373
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3374
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3375
     3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440,
3376
     3440, 3448, 3448, 3448, 3456, 3464, 3464, 3464, 3464, 3464, 3464, 3464,
3377
     3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3464, 3472, 3480, 3480,
3378
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3379
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3380
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3381
     3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480, 3480,
3382
     3480, 3480, 3480, 3480, 3480, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3383
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3384
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3385
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488,
3386
     3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3488, 3496,
3387
     3504, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3388
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3389
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3390
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3391
     3512, 3512, 3512, 3512, 3512},
3392
    {3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3393
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3394
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3395
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3396
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3397
     3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512, 3512,
3398
     3512, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3399
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3400
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3401
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3402
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3403
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3404
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3405
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3406
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3407
     3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520, 3520,
3408
     3520, 3528, 3528, 3528, 3528, 3528, 3528, 3528, 3536, 3544, 3544, 3552,
3409
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3410
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3411
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3412
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3413
     3564, 3564, 3564, 3564, 3564},
3414
    {3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3415
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3416
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3417
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3418
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3419
     3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564, 3564,
3420
     3564, 3564, 3564, 3572, 3580, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3421
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3422
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3423
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3424
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3425
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3426
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3427
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3428
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3429
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3430
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3431
     3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588, 3588,
3432
     3588, 3588, 3588, 3596, 3596, 3604, 3616, 3624, 3624, 3624, 3624, 3624,
3433
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3434
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3435
     3624, 3624, 3624, 3624, 3624},
3436
    {3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3437
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3438
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3439
     3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624, 3624,
3440
     3624, 3624, 3624, 3625, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3441
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3442
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3443
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3444
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3445
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3446
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3447
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3448
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3449
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632,
3450
     3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3632, 3633,
3451
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3452
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3453
     3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640, 3640,
3454
     3640, 3640, 3640, 3640, 3641, 3649, 3656, 3656, 3656, 3656, 3656, 3656,
3455
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3456
     3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3457
     3656, 3656, 3656, 3656, 3656},
3458
    {3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656, 3656,
3459
     3657, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3460
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3461
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3462
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660,
3463
     3660, 3660, 3660, 3660, 3660, 3660, 3660, 3660, 3668, 3668, 3668, 3668,
3464
     3668, 3668, 3668, 3668, 3668, 3668, 3676, 3676, 3676, 3676, 3676, 3684,
3465
     3684, 3684, 3684, 3684, 3692, 3692, 3692, 3692, 3692, 3700, 3700, 3700,
3466
     3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3700, 3708, 3708,
3467
     3708, 3708, 3708, 3708, 3708, 3708, 3708, 3708, 3716, 3716, 3724, 3733,
3468
     3744, 3753, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3764, 3772, 3772,
3469
     3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772, 3772,
3470
     3772, 3772, 3772, 3772, 3780, 3780, 3780, 3780, 3780, 3780, 3780, 3780,
3471
     3780, 3780, 3788, 3788, 3788, 3788, 3788, 3796, 3796, 3796, 3796, 3796,
3472
     3804, 3804, 3804, 3804, 3804, 3812, 3812, 3812, 3812, 3812, 3812, 3812,
3473
     3812, 3812, 3812, 3812, 3812, 3812, 3820, 3820, 3820, 3820, 3820, 3820,
3474
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3475
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3476
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3477
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3478
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3479
     3820, 3820, 3820, 3820, 3820},
3480
    {3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3481
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3482
     3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820, 3820,
3483
     3820, 3820, 3820, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3484
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3485
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3486
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3487
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3488
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3489
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3490
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3491
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3492
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3493
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3494
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3495
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3496
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3497
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3498
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3499
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3500
     3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828, 3828,
3501
     3829, 3832, 3832, 3832, 3832},
3502
    {3832, 3832, 3832, 3832, 3832, 3832, 3832, 3840, 3840, 3848, 3848, 3856,
3503
     3856, 3864, 3864, 3872, 3872, 3872, 3872, 3880, 3880, 3880, 3880, 3880,
3504
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3505
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3506
     3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880, 3880,
3507
     3888, 3888, 3896, 3896, 3896, 3904, 3912, 3912, 3920, 3920, 3920, 3920,
3508
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3509
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3510
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3511
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3512
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3513
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3514
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3515
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3516
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3517
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3518
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3519
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3520
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3521
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3522
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3523
     3920, 3920, 3920, 3920, 3920},
3524
    {3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3525
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3526
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920,
3527
     3920, 3920, 3920, 3920, 3920, 3920, 3920, 3920, 3921, 3925, 3929, 3932,
3528
     3933, 3937, 3941, 3945, 3949, 3953, 3957, 3961, 3965, 3969, 3973, 3976,
3529
     3977, 3981, 3985, 3989, 3993, 3997, 4001, 4005, 4009, 4013, 4017, 4021,
3530
     4025, 4029, 4033, 4037, 4041, 4045, 4048, 4049, 4053, 4057, 4061, 4065,
3531
     4069, 4073, 4077, 4081, 4085, 4089, 4093, 4097, 4101, 4105, 4109, 4113,
3532
     4117, 4121, 4125, 4129, 4133, 4137, 4141, 4145, 4149, 4153, 4157, 4160,
3533
     4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160, 4160,
3534
     4161, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3535
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164,
3536
     4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4164, 4165,
3537
     4169, 4173, 4177, 4181, 4185, 4189, 4193, 4197, 4201, 4205, 4209, 4213,
3538
     4217, 4221, 4225, 4229, 4233, 4237, 4241, 4245, 4249, 4253, 4257, 4261,
3539
     4265, 4269, 4273, 4277, 4281, 4285, 4289, 4293, 4297, 4301, 4305, 4309,
3540
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3541
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3542
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3543
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3544
     4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312, 4312,
3545
     4312, 4312, 4312, 4312, 4312},
3546
    {4312, 4320, 4328, 4336, 4344, 4352, 4360, 4368, 4376, 4388, 4400, 4408,
3547
     4416, 4424, 4432, 4440, 4448, 4456, 4464, 4472, 4480, 4492, 4504, 4516,
3548
     4528, 4536, 4544, 4552, 4560, 4572, 4584, 4592, 4600, 4608, 4616, 4624,
3549
     4632, 4640, 4648, 4656, 4664, 4672, 4680, 4688, 4696, 4704, 4712, 4724,
3550
     4736, 4744, 4752, 4760, 4768, 4776, 4784, 4792, 4800, 4812, 4824, 4832,
3551
     4840, 4848, 4856, 4864, 4872, 4880, 4888, 4896, 4904, 4912, 4920, 4928,
3552
     4936, 4944, 4952, 4960, 4968, 4980, 4992, 5004, 5016, 5028, 5040, 5052,
3553
     5064, 5072, 5080, 5088, 5096, 5104, 5112, 5120, 5128, 5140, 5152, 5160,
3554
     5168, 5176, 5184, 5192, 5200, 5212, 5224, 5236, 5248, 5260, 5272, 5280,
3555
     5288, 5296, 5304, 5312, 5320, 5328, 5336, 5344, 5352, 5360, 5368, 5376,
3556
     5384, 5396, 5408, 5420, 5432, 5440, 5448, 5456, 5464, 5472, 5480, 5488,
3557
     5496, 5504, 5512, 5520, 5528, 5536, 5544, 5552, 5560, 5568, 5576, 5584,
3558
     5592, 5600, 5608, 5616, 5624, 5632, 5640, 5648, 5656, 5664, 5673, 5682,
3559
     5688, 5688, 5688, 5688, 5688, 5696, 5704, 5712, 5720, 5732, 5744, 5756,
3560
     5768, 5780, 5792, 5804, 5816, 5828, 5840, 5852, 5864, 5876, 5888, 5900,
3561
     5912, 5924, 5936, 5948, 5960, 5968, 5976, 5984, 5992, 6000, 6008, 6020,
3562
     6032, 6044, 6056, 6068, 6080, 6092, 6104, 6116, 6128, 6136, 6144, 6152,
3563
     6160, 6168, 6176, 6184, 6192, 6204, 6216, 6228, 6240, 6252, 6264, 6276,
3564
     6288, 6300, 6312, 6324, 6336, 6348, 6360, 6372, 6384, 6396, 6408, 6420,
3565
     6432, 6440, 6448, 6456, 6464, 6476, 6488, 6500, 6512, 6524, 6536, 6548,
3566
     6560, 6572, 6584, 6592, 6600, 6608, 6616, 6624, 6632, 6640, 6648, 6648,
3567
     6648, 6648, 6648, 6648, 6648},
3568
    {6648, 6656, 6664, 6676, 6688, 6700, 6712, 6724, 6736, 6744, 6752, 6764,
3569
     6776, 6788, 6800, 6812, 6824, 6832, 6840, 6852, 6864, 6876, 6888, 6888,
3570
     6888, 6896, 6904, 6916, 6928, 6940, 6952, 6952, 6952, 6960, 6968, 6980,
3571
     6992, 7004, 7016, 7028, 7040, 7048, 7056, 7068, 7080, 7092, 7104, 7116,
3572
     7128, 7136, 7144, 7156, 7168, 7180, 7192, 7204, 7216, 7224, 7232, 7244,
3573
     7256, 7268, 7280, 7292, 7304, 7312, 7320, 7332, 7344, 7356, 7368, 7368,
3574
     7368, 7376, 7384, 7396, 7408, 7420, 7432, 7432, 7432, 7440, 7448, 7460,
3575
     7472, 7484, 7496, 7508, 7520, 7520, 7528, 7528, 7540, 7540, 7552, 7552,
3576
     7564, 7572, 7580, 7592, 7604, 7616, 7628, 7640, 7652, 7660, 7668, 7680,
3577
     7692, 7704, 7716, 7728, 7740, 7748, 7756, 7764, 7772, 7780, 7788, 7796,
3578
     7804, 7812, 7820, 7828, 7836, 7844, 7852, 7852, 7852, 7864, 7876, 7892,
3579
     7908, 7924, 7940, 7956, 7972, 7984, 7996, 8012, 8028, 8044, 8060, 8076,
3580
     8092, 8104, 8116, 8132, 8148, 8164, 8180, 8196, 8212, 8224, 8236, 8252,
3581
     8268, 8284, 8300, 8316, 8332, 8344, 8356, 8372, 8388, 8404, 8420, 8436,
3582
     8452, 8464, 8476, 8492, 8508, 8524, 8540, 8556, 8572, 8580, 8588, 8600,
3583
     8608, 8620, 8620, 8628, 8640, 8648, 8656, 8664, 8672, 8681, 8688, 8693,
3584
     8701, 8710, 8716, 8728, 8736, 8748, 8748, 8756, 8768, 8776, 8784, 8792,
3585
     8800, 8810, 8818, 8826, 8832, 8840, 8848, 8860, 8872, 8872, 8872, 8880,
3586
     8892, 8900, 8908, 8916, 8924, 8926, 8934, 8942, 8948, 8956, 8964, 8976,
3587
     8988, 8996, 9004, 9012, 9024, 9032, 9040, 9048, 9056, 9066, 9074, 9080,
3588
     9084, 9084, 9084, 9096, 9104, 9116, 9116, 9124, 9136, 9144, 9152, 9160,
3589
     9168, 9178, 9181, 9188, 9190},
3590
    {9190, 9194, 9197, 9201, 9205, 9209, 9213, 9217, 9221, 9225, 9229, 9232,
3591
     9232, 9232, 9232, 9232, 9232, 9233, 9236, 9236, 9236, 9236, 9236, 9237,
3592
     9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244, 9244,
3593
     9245, 9249, 9257, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9268, 9269,
3594
     9272, 9272, 9272, 9273, 9281, 9292, 9293, 9301, 9312, 9312, 9312, 9312,
3595
     9313, 9320, 9321, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9328, 9329,
3596
     9337, 9345, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352, 9352,
3597
     9352, 9352, 9352, 9353, 9368, 9368, 9368, 9368, 9368, 9368, 9368, 9369,
3598
     9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372, 9372,
3599
     9372, 9372, 9372, 9372, 9373, 9377, 9380, 9380, 9381, 9385, 9389, 9393,
3600
     9397, 9401, 9405, 9409, 9413, 9417, 9421, 9425, 9429, 9433, 9437, 9441,
3601
     9445, 9449, 9453, 9457, 9461, 9465, 9469, 9473, 9477, 9481, 9485, 9488,
3602
     9489, 9493, 9497, 9501, 9505, 9509, 9513, 9517, 9521, 9525, 9529, 9533,
3603
     9537, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540, 9540,
3604
     9541, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3605
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3606
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3607
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3608
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3609
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3610
     9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548, 9548,
3611
     9548, 9548, 9548, 9548, 9549},
3612
    {9549,  9561,  9573,  9577,  9584,  9585,  9597,  9609,  9612,  9613,
3613
     9621,  9625,  9629,  9633,  9637,  9641,  9645,  9649,  9653,  9657,
3614
     9660,  9661,  9665,  9672,  9672,  9673,  9677,  9681,  9685,  9689,
3615
     9692,  9692,  9693,  9701,  9713,  9720,  9721,  9724,  9724,  9728,
3616
     9729,  9732,  9732,  9736,  9745,  9749,  9752,  9753,  9757,  9761,
3617
     9764,  9765,  9769,  9773,  9777,  9781,  9785,  9789,  9792,  9793,
3618
     9805,  9809,  9813,  9817,  9821,  9824,  9824,  9824,  9824,  9825,
3619
     9829,  9833,  9837,  9841,  9844,  9844,  9844,  9844,  9844,  9844,
3620
     9845,  9857,  9869,  9885,  9897,  9909,  9921,  9933,  9945,  9957,
3621
     9969,  9981,  9993,  10005, 10017, 10029, 10037, 10041, 10049, 10061,
3622
     10069, 10073, 10081, 10093, 10109, 10117, 10121, 10129, 10141, 10145,
3623
     10149, 10153, 10157, 10161, 10169, 10181, 10189, 10193, 10201, 10213,
3624
     10229, 10237, 10241, 10249, 10261, 10265, 10269, 10273, 10276, 10276,
3625
     10276, 10276, 10276, 10276, 10276, 10276, 10276, 10277, 10288, 10288,
3626
     10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288, 10288,
3627
     10288, 10288, 10288, 10288, 10288, 10296, 10304, 10304, 10304, 10304,
3628
     10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304, 10304,
3629
     10304, 10304, 10304, 10304, 10304, 10312, 10312, 10312, 10312, 10312,
3630
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3631
     10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312, 10312,
3632
     10312, 10312, 10312, 10312, 10312, 10312, 10320, 10328, 10336, 10336,
3633
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3634
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3635
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3636
     10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336, 10336,
3637
     10336, 10336, 10336, 10336, 10336, 10336, 10336},
3638
    {10336, 10336, 10336, 10336, 10336, 10344, 10344, 10344, 10344, 10344,
3639
     10352, 10352, 10352, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3640
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360, 10360,
3641
     10360, 10360, 10360, 10360, 10360, 10360, 10360, 10368, 10368, 10376,
3642
     10376, 10376, 10376, 10376, 10377, 10385, 10396, 10397, 10405, 10416,
3643
     10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416, 10416,
3644
     10416, 10416, 10416, 10416, 10416, 10416, 10424, 10424, 10424, 10432,
3645
     10432, 10432, 10440, 10440, 10448, 10448, 10448, 10448, 10448, 10448,
3646
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448, 10448,
3647
     10448, 10448, 10448, 10448, 10448, 10448, 10448, 10456, 10456, 10464,
3648
     10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464, 10464,
3649
     10472, 10480, 10488, 10496, 10504, 10504, 10504, 10512, 10520, 10520,
3650
     10520, 10528, 10536, 10536, 10536, 10536, 10536, 10536, 10536, 10544,
3651
     10552, 10552, 10552, 10560, 10568, 10568, 10568, 10576, 10584, 10584,
3652
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3653
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3654
     10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584, 10584,
3655
     10584, 10584, 10584, 10592, 10600, 10608, 10616, 10616, 10616, 10616,
3656
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3657
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3658
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3659
     10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616, 10616,
3660
     10616, 10616, 10616, 10616, 10616, 10624, 10632, 10640, 10648, 10648,
3661
     10648, 10648, 10648, 10648, 10648, 10656, 10664, 10672, 10680, 10680,
3662
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3663
     10680, 10680, 10680, 10680, 10680, 10680, 10680},
3664
    {10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3665
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3666
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3667
     10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680, 10680,
3668
     10680, 10680, 10684, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3669
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3670
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3671
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3672
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3673
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3674
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3675
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3676
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3677
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3678
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3679
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3680
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3681
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3682
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3683
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3684
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3685
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3686
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3687
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3688
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3689
     10688, 10688, 10688, 10688, 10688, 10688, 10688},
3690
    {10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3691
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3692
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3693
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3694
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3695
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3696
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3697
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3698
     10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688, 10688,
3699
     10688, 10688, 10688, 10688, 10688, 10688, 10689, 10693, 10697, 10701,
3700
     10705, 10709, 10713, 10717, 10721, 10725, 10733, 10741, 10749, 10757,
3701
     10765, 10773, 10781, 10789, 10797, 10805, 10813, 10825, 10837, 10849,
3702
     10861, 10873, 10885, 10897, 10909, 10921, 10937, 10953, 10969, 10985,
3703
     11001, 11017, 11033, 11049, 11065, 11081, 11097, 11105, 11113, 11121,
3704
     11129, 11137, 11145, 11153, 11161, 11169, 11181, 11193, 11205, 11217,
3705
     11229, 11241, 11253, 11265, 11277, 11289, 11301, 11313, 11325, 11337,
3706
     11349, 11361, 11373, 11385, 11397, 11409, 11421, 11433, 11445, 11457,
3707
     11469, 11481, 11493, 11505, 11517, 11529, 11541, 11553, 11565, 11577,
3708
     11589, 11601, 11613, 11617, 11621, 11625, 11629, 11633, 11637, 11641,
3709
     11645, 11649, 11653, 11657, 11661, 11665, 11669, 11673, 11677, 11681,
3710
     11685, 11689, 11693, 11697, 11701, 11705, 11709, 11713, 11717, 11721,
3711
     11725, 11729, 11733, 11737, 11741, 11745, 11749, 11753, 11757, 11761,
3712
     11765, 11769, 11773, 11777, 11781, 11785, 11789, 11793, 11797, 11801,
3713
     11805, 11809, 11813, 11817, 11821, 11824, 11824, 11824, 11824, 11824,
3714
     11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3715
     11824, 11824, 11824, 11824, 11824, 11824, 11824},
3716
    {11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824, 11824,
3717
     11824, 11824, 11825, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3718
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3719
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3720
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3721
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3722
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3723
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3724
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3725
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3726
     11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840, 11840,
3727
     11840, 11840, 11840, 11840, 11840, 11840, 11841, 11853, 11861, 11872,
3728
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3729
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3730
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3731
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3732
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3733
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3734
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3735
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3736
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3737
     11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872, 11872,
3738
     11872, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3739
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3740
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3741
     11880, 11880, 11880, 11880, 11880, 11880, 11880},
3742
    {11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3743
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3744
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3745
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3746
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3747
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3748
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3749
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3750
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3751
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3752
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3753
     11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880, 11880,
3754
     11880, 11880, 11880, 11880, 11881, 11885, 11888, 11888, 11888, 11888,
3755
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3756
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3757
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3758
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3759
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3760
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3761
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3762
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3763
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3764
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3765
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3766
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3767
     11888, 11888, 11888, 11888, 11888, 11888, 11888},
3768
    {11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3769
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3770
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3771
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3772
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3773
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3774
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3775
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3776
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3777
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3778
     11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888, 11888,
3779
     11888, 11889, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3780
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3781
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3782
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3783
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3784
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3785
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3786
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3787
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3788
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3789
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3790
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3791
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3792
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3793
     11892, 11892, 11892, 11892, 11892, 11892, 11892},
3794
    {11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3795
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3796
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3797
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3798
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3799
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3800
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3801
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3802
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3803
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3804
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3805
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3806
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3807
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3808
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892,
3809
     11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11892, 11893,
3810
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3811
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3812
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3813
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3814
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3815
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3816
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3817
     11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896, 11896,
3818
     11896, 11896, 11896, 11897, 11900, 11900, 11900, 11900, 11900, 11900,
3819
     11900, 11900, 11900, 11900, 11900, 11900, 11901},
3820
    {11901, 11905, 11909, 11913, 11917, 11921, 11925, 11929, 11933, 11937,
3821
     11941, 11945, 11949, 11953, 11957, 11961, 11965, 11969, 11973, 11977,
3822
     11981, 11985, 11989, 11993, 11997, 12001, 12005, 12009, 12013, 12017,
3823
     12021, 12025, 12029, 12033, 12037, 12041, 12045, 12049, 12053, 12057,
3824
     12061, 12065, 12069, 12073, 12077, 12081, 12085, 12089, 12093, 12097,
3825
     12101, 12105, 12109, 12113, 12117, 12121, 12125, 12129, 12133, 12137,
3826
     12141, 12145, 12149, 12153, 12157, 12161, 12165, 12169, 12173, 12177,
3827
     12181, 12185, 12189, 12193, 12197, 12201, 12205, 12209, 12213, 12217,
3828
     12221, 12225, 12229, 12233, 12237, 12241, 12245, 12249, 12253, 12257,
3829
     12261, 12265, 12269, 12273, 12277, 12281, 12285, 12289, 12293, 12297,
3830
     12301, 12305, 12309, 12313, 12317, 12321, 12325, 12329, 12333, 12337,
3831
     12341, 12345, 12349, 12353, 12357, 12361, 12365, 12369, 12373, 12377,
3832
     12381, 12385, 12389, 12393, 12397, 12401, 12405, 12409, 12413, 12417,
3833
     12421, 12425, 12429, 12433, 12437, 12441, 12445, 12449, 12453, 12457,
3834
     12461, 12465, 12469, 12473, 12477, 12481, 12485, 12489, 12493, 12497,
3835
     12501, 12505, 12509, 12513, 12517, 12521, 12525, 12529, 12533, 12537,
3836
     12541, 12545, 12549, 12553, 12557, 12561, 12565, 12569, 12573, 12577,
3837
     12581, 12585, 12589, 12593, 12597, 12601, 12605, 12609, 12613, 12617,
3838
     12621, 12625, 12629, 12633, 12637, 12641, 12645, 12649, 12653, 12657,
3839
     12661, 12665, 12669, 12673, 12677, 12681, 12685, 12689, 12693, 12697,
3840
     12701, 12705, 12709, 12713, 12717, 12721, 12725, 12729, 12733, 12737,
3841
     12741, 12745, 12749, 12753, 12756, 12756, 12756, 12756, 12756, 12756,
3842
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3843
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3844
     12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756, 12756,
3845
     12756, 12756, 12756, 12756, 12756, 12756, 12757},
3846
    {12757, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3847
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3848
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3849
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3850
     12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760, 12760,
3851
     12760, 12760, 12760, 12760, 12761, 12764, 12765, 12769, 12773, 12776,
3852
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776, 12776,
3853
     12776, 12776, 12776, 12776, 12776, 12776, 12776, 12784, 12784, 12792,
3854
     12792, 12800, 12800, 12808, 12808, 12816, 12816, 12824, 12824, 12832,
3855
     12832, 12840, 12840, 12848, 12848, 12856, 12856, 12864, 12864, 12872,
3856
     12872, 12872, 12880, 12880, 12888, 12888, 12896, 12896, 12896, 12896,
3857
     12896, 12896, 12896, 12904, 12912, 12912, 12920, 12928, 12928, 12936,
3858
     12944, 12944, 12952, 12960, 12960, 12968, 12976, 12976, 12976, 12976,
3859
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976,
3860
     12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12976, 12984,
3861
     12984, 12984, 12984, 12984, 12984, 12985, 12993, 13000, 13000, 13009,
3862
     13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016, 13016,
3863
     13016, 13016, 13016, 13024, 13024, 13032, 13032, 13040, 13040, 13048,
3864
     13048, 13056, 13056, 13064, 13064, 13072, 13072, 13080, 13080, 13088,
3865
     13088, 13096, 13096, 13104, 13104, 13112, 13112, 13112, 13120, 13120,
3866
     13128, 13128, 13136, 13136, 13136, 13136, 13136, 13136, 13136, 13144,
3867
     13152, 13152, 13160, 13168, 13168, 13176, 13184, 13184, 13192, 13200,
3868
     13200, 13208, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3869
     13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216, 13216,
3870
     13216, 13216, 13216, 13216, 13216, 13224, 13224, 13224, 13232, 13240,
3871
     13248, 13256, 13256, 13256, 13256, 13265, 13272},
3872
    {13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3873
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3874
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3875
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272,
3876
     13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13272, 13273,
3877
     13277, 13281, 13285, 13289, 13293, 13297, 13301, 13305, 13309, 13313,
3878
     13317, 13321, 13325, 13329, 13333, 13337, 13341, 13345, 13349, 13353,
3879
     13357, 13361, 13365, 13369, 13373, 13377, 13381, 13385, 13389, 13393,
3880
     13397, 13401, 13405, 13409, 13413, 13417, 13421, 13425, 13429, 13433,
3881
     13437, 13441, 13445, 13449, 13453, 13457, 13461, 13465, 13469, 13473,
3882
     13477, 13481, 13485, 13489, 13493, 13497, 13501, 13505, 13509, 13513,
3883
     13517, 13521, 13525, 13529, 13533, 13537, 13541, 13545, 13549, 13553,
3884
     13557, 13561, 13565, 13569, 13573, 13577, 13581, 13585, 13589, 13593,
3885
     13597, 13601, 13605, 13609, 13613, 13617, 13621, 13625, 13629, 13633,
3886
     13637, 13641, 13645, 13648, 13648, 13648, 13649, 13653, 13657, 13661,
3887
     13665, 13669, 13673, 13677, 13681, 13685, 13689, 13693, 13697, 13701,
3888
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3889
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3890
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3891
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3892
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3893
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3894
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3895
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3896
     13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704, 13704,
3897
     13704, 13704, 13704, 13704, 13704, 13704, 13705},
3898
    {13705, 13717, 13729, 13741, 13753, 13765, 13777, 13789, 13801, 13813,
3899
     13825, 13837, 13849, 13861, 13873, 13889, 13905, 13921, 13937, 13953,
3900
     13969, 13985, 14001, 14017, 14033, 14049, 14065, 14081, 14097, 14113,
3901
     14141, 14164, 14165, 14177, 14189, 14201, 14213, 14225, 14237, 14249,
3902
     14261, 14273, 14285, 14297, 14309, 14321, 14333, 14345, 14357, 14369,
3903
     14381, 14393, 14405, 14417, 14429, 14441, 14453, 14465, 14477, 14489,
3904
     14501, 14513, 14525, 14537, 14549, 14561, 14573, 14585, 14597, 14601,
3905
     14605, 14609, 14612, 14612, 14612, 14612, 14612, 14612, 14612, 14612,
3906
     14613, 14625, 14633, 14641, 14649, 14657, 14665, 14673, 14681, 14689,
3907
     14697, 14705, 14713, 14721, 14729, 14737, 14745, 14749, 14753, 14757,
3908
     14761, 14765, 14769, 14773, 14777, 14781, 14785, 14789, 14793, 14797,
3909
     14801, 14809, 14817, 14825, 14833, 14841, 14849, 14857, 14865, 14873,
3910
     14881, 14889, 14897, 14905, 14913, 14933, 14949, 14956, 14957, 14961,
3911
     14965, 14969, 14973, 14977, 14981, 14985, 14989, 14993, 14997, 15001,
3912
     15005, 15009, 15013, 15017, 15021, 15025, 15029, 15033, 15037, 15041,
3913
     15045, 15049, 15053, 15057, 15061, 15065, 15069, 15073, 15077, 15081,
3914
     15085, 15089, 15093, 15097, 15101, 15105, 15109, 15113, 15117, 15121,
3915
     15125, 15129, 15133, 15137, 15141, 15145, 15149, 15153, 15161, 15169,
3916
     15177, 15185, 15193, 15201, 15209, 15217, 15225, 15233, 15241, 15249,
3917
     15257, 15265, 15273, 15281, 15289, 15297, 15305, 15313, 15321, 15329,
3918
     15337, 15345, 15357, 15369, 15381, 15389, 15401, 15409, 15421, 15425,
3919
     15429, 15433, 15437, 15441, 15445, 15449, 15453, 15457, 15461, 15465,
3920
     15469, 15473, 15477, 15481, 15485, 15489, 15493, 15497, 15501, 15505,
3921
     15509, 15513, 15517, 15521, 15525, 15529, 15533, 15537, 15541, 15545,
3922
     15549, 15553, 15557, 15561, 15565, 15569, 15573, 15577, 15581, 15585,
3923
     15589, 15593, 15597, 15601, 15605, 15609, 15617},
3924
    {15617, 15637, 15653, 15673, 15685, 15705, 15717, 15729, 15753, 15769,
3925
     15781, 15793, 15805, 15821, 15837, 15853, 15869, 15885, 15901, 15917,
3926
     15941, 15949, 15973, 15997, 16017, 16033, 16057, 16081, 16097, 16109,
3927
     16121, 16137, 16153, 16173, 16193, 16205, 16217, 16233, 16245, 16257,
3928
     16265, 16273, 16285, 16297, 16321, 16337, 16357, 16381, 16397, 16409,
3929
     16421, 16445, 16461, 16485, 16497, 16517, 16529, 16545, 16557, 16573,
3930
     16593, 16609, 16629, 16645, 16653, 16673, 16685, 16697, 16713, 16725,
3931
     16737, 16749, 16769, 16785, 16793, 16817, 16829, 16849, 16865, 16881,
3932
     16893, 16905, 16921, 16929, 16945, 16965, 16973, 16997, 17009, 17017,
3933
     17025, 17033, 17041, 17049, 17057, 17065, 17073, 17081, 17089, 17101,
3934
     17113, 17125, 17137, 17149, 17161, 17173, 17185, 17197, 17209, 17221,
3935
     17233, 17245, 17257, 17269, 17281, 17289, 17297, 17309, 17317, 17325,
3936
     17333, 17345, 17357, 17365, 17373, 17381, 17389, 17397, 17413, 17421,
3937
     17429, 17437, 17445, 17453, 17461, 17469, 17477, 17489, 17505, 17513,
3938
     17521, 17529, 17537, 17545, 17553, 17561, 17573, 17585, 17597, 17609,
3939
     17617, 17625, 17633, 17641, 17649, 17657, 17665, 17673, 17681, 17689,
3940
     17701, 17713, 17721, 17733, 17745, 17757, 17765, 17777, 17789, 17805,
3941
     17813, 17825, 17837, 17849, 17861, 17881, 17905, 17913, 17921, 17929,
3942
     17937, 17945, 17953, 17961, 17969, 17977, 17985, 17993, 18001, 18009,
3943
     18017, 18025, 18033, 18041, 18049, 18065, 18073, 18081, 18089, 18105,
3944
     18117, 18125, 18133, 18141, 18149, 18157, 18165, 18173, 18181, 18189,
3945
     18197, 18209, 18217, 18225, 18237, 18249, 18257, 18273, 18285, 18293,
3946
     18301, 18309, 18317, 18329, 18341, 18349, 18357, 18365, 18373, 18381,
3947
     18389, 18397, 18405, 18413, 18425, 18437, 18449, 18461, 18473, 18485,
3948
     18497, 18509, 18521, 18533, 18545, 18557, 18569, 18581, 18593, 18605,
3949
     18617, 18629, 18641, 18653, 18665, 18677, 18688},
3950
    {18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3951
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3952
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3953
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3954
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3955
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3956
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3957
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3958
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3959
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3960
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3961
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3962
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3963
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3964
     18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688, 18688,
3965
     18688, 18688, 18688, 18688, 18688, 18688, 18689, 18693, 18696, 18696,
3966
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3967
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3968
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3969
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3970
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3971
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3972
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3973
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3974
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3975
     18696, 18696, 18696, 18696, 18696, 18696, 18696},
3976
    {18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3977
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3978
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3979
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3980
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3981
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3982
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3983
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3984
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3985
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3986
     18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696, 18696,
3987
     18696, 18696, 18697, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3988
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3989
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3990
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3991
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3992
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3993
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3994
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3995
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3996
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3997
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3998
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
3999
     18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700, 18700,
4000
     18700, 18700, 18701, 18705, 18709, 18712, 18712, 18712, 18713, 18717,
4001
     18720, 18720, 18720, 18720, 18720, 18720, 18720},
4002
    {18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4003
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4004
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4005
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4006
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4007
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4008
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4009
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4010
     18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720, 18720,
4011
     18720, 18720, 18721, 18725, 18729, 18733, 18736, 18736, 18736, 18736,
4012
     18736, 18736, 18736, 18736, 18736, 18737, 18740, 18740, 18740, 18740,
4013
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4014
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4015
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4016
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4017
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4018
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4019
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4020
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4021
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4022
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4023
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4024
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4025
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4026
     18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740, 18740,
4027
     18740, 18740, 18740, 18740, 18740, 18740, 18740},
4028
    {18740, 18744, 18748, 18752, 18756, 18760, 18764, 18768, 18772, 18776,
4029
     18780, 18784, 18788, 18792, 18796, 18800, 18804, 18808, 18812, 18816,
4030
     18820, 18824, 18828, 18832, 18836, 18840, 18844, 18848, 18852, 18856,
4031
     18860, 18864, 18868, 18872, 18876, 18880, 18884, 18888, 18892, 18896,
4032
     18900, 18904, 18908, 18912, 18916, 18920, 18924, 18928, 18932, 18936,
4033
     18940, 18944, 18948, 18952, 18956, 18960, 18964, 18968, 18972, 18976,
4034
     18980, 18984, 18988, 18992, 18996, 19000, 19004, 19008, 19012, 19016,
4035
     19020, 19024, 19028, 19032, 19036, 19040, 19044, 19048, 19052, 19056,
4036
     19060, 19064, 19068, 19072, 19076, 19080, 19084, 19088, 19092, 19096,
4037
     19100, 19104, 19108, 19112, 19116, 19120, 19124, 19128, 19132, 19136,
4038
     19140, 19144, 19148, 19152, 19156, 19160, 19164, 19168, 19172, 19176,
4039
     19180, 19184, 19188, 19192, 19196, 19200, 19204, 19208, 19212, 19216,
4040
     19220, 19224, 19228, 19232, 19236, 19240, 19244, 19248, 19252, 19256,
4041
     19260, 19264, 19268, 19272, 19276, 19280, 19284, 19288, 19292, 19296,
4042
     19300, 19304, 19308, 19312, 19316, 19320, 19324, 19328, 19332, 19336,
4043
     19340, 19344, 19348, 19352, 19356, 19360, 19364, 19368, 19372, 19376,
4044
     19380, 19384, 19388, 19392, 19396, 19400, 19404, 19408, 19412, 19416,
4045
     19420, 19424, 19428, 19432, 19436, 19440, 19444, 19448, 19452, 19456,
4046
     19460, 19464, 19468, 19472, 19476, 19480, 19484, 19488, 19492, 19496,
4047
     19500, 19504, 19508, 19512, 19516, 19520, 19524, 19528, 19532, 19536,
4048
     19540, 19544, 19548, 19552, 19556, 19560, 19564, 19568, 19572, 19576,
4049
     19580, 19584, 19588, 19592, 19596, 19600, 19604, 19608, 19612, 19616,
4050
     19620, 19624, 19628, 19632, 19636, 19640, 19644, 19648, 19652, 19656,
4051
     19660, 19664, 19668, 19672, 19676, 19680, 19684, 19688, 19692, 19696,
4052
     19700, 19704, 19708, 19712, 19716, 19720, 19724, 19728, 19732, 19736,
4053
     19740, 19744, 19748, 19752, 19756, 19760, 19764},
4054
    {19764, 19768, 19772, 19776, 19780, 19784, 19788, 19792, 19796, 19800,
4055
     19804, 19808, 19812, 19816, 19820, 19820, 19820, 19824, 19824, 19828,
4056
     19828, 19828, 19832, 19836, 19840, 19844, 19848, 19852, 19856, 19860,
4057
     19864, 19868, 19868, 19872, 19872, 19876, 19876, 19876, 19880, 19884,
4058
     19884, 19884, 19884, 19888, 19892, 19896, 19900, 19904, 19908, 19912,
4059
     19916, 19920, 19924, 19928, 19932, 19936, 19940, 19944, 19948, 19952,
4060
     19956, 19960, 19964, 19968, 19972, 19976, 19980, 19984, 19988, 19992,
4061
     19996, 20000, 20004, 20008, 20012, 20016, 20020, 20024, 20028, 20032,
4062
     20036, 20040, 20044, 20048, 20052, 20056, 20060, 20064, 20068, 20072,
4063
     20076, 20080, 20084, 20088, 20092, 20096, 20100, 20104, 20108, 20112,
4064
     20116, 20120, 20124, 20128, 20132, 20136, 20140, 20144, 20148, 20152,
4065
     20156, 20156, 20156, 20160, 20164, 20168, 20172, 20176, 20180, 20184,
4066
     20188, 20192, 20196, 20200, 20204, 20208, 20212, 20216, 20220, 20224,
4067
     20228, 20232, 20236, 20240, 20244, 20248, 20252, 20256, 20260, 20264,
4068
     20268, 20272, 20276, 20280, 20284, 20288, 20292, 20296, 20300, 20304,
4069
     20308, 20312, 20316, 20320, 20324, 20328, 20332, 20336, 20340, 20344,
4070
     20348, 20352, 20356, 20360, 20364, 20368, 20372, 20376, 20380, 20384,
4071
     20388, 20392, 20396, 20400, 20404, 20408, 20412, 20416, 20420, 20424,
4072
     20428, 20432, 20436, 20440, 20444, 20448, 20452, 20456, 20460, 20464,
4073
     20468, 20472, 20476, 20480, 20484, 20488, 20492, 20496, 20500, 20504,
4074
     20508, 20512, 20516, 20520, 20524, 20528, 20532, 20536, 20540, 20544,
4075
     20548, 20552, 20556, 20560, 20564, 20568, 20572, 20576, 20580, 20580,
4076
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4077
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4078
     20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580, 20580,
4079
     20580, 20580, 20580, 20580, 20580, 20580, 20581},
4080
    {20581, 20589, 20597, 20605, 20617, 20629, 20637, 20644, 20644, 20644,
4081
     20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20644, 20645,
4082
     20653, 20661, 20669, 20677, 20684, 20684, 20684, 20684, 20684, 20684,
4083
     20692, 20692, 20701, 20705, 20709, 20713, 20717, 20721, 20725, 20729,
4084
     20733, 20737, 20740, 20748, 20756, 20768, 20780, 20788, 20796, 20804,
4085
     20812, 20820, 20828, 20836, 20844, 20852, 20852, 20860, 20868, 20876,
4086
     20884, 20892, 20892, 20900, 20900, 20908, 20916, 20916, 20924, 20932,
4087
     20932, 20940, 20948, 20956, 20964, 20972, 20980, 20988, 20996, 21005,
4088
     21013, 21017, 21021, 21025, 21029, 21033, 21037, 21041, 21045, 21049,
4089
     21053, 21057, 21061, 21065, 21069, 21073, 21077, 21081, 21085, 21089,
4090
     21093, 21097, 21101, 21105, 21109, 21113, 21117, 21121, 21125, 21129,
4091
     21133, 21137, 21141, 21145, 21149, 21153, 21157, 21161, 21165, 21169,
4092
     21173, 21177, 21181, 21185, 21189, 21193, 21197, 21201, 21205, 21209,
4093
     21213, 21217, 21221, 21225, 21229, 21233, 21237, 21241, 21245, 21249,
4094
     21253, 21257, 21261, 21265, 21269, 21273, 21277, 21281, 21285, 21289,
4095
     21293, 21297, 21301, 21305, 21309, 21313, 21317, 21321, 21325, 21329,
4096
     21333, 21337, 21341, 21345, 21349, 21357, 21365, 21369, 21373, 21377,
4097
     21381, 21385, 21389, 21393, 21397, 21401, 21405, 21413, 21420, 21420,
4098
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4099
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4100
     21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420, 21420,
4101
     21420, 21421, 21425, 21429, 21433, 21437, 21441, 21445, 21449, 21453,
4102
     21457, 21461, 21469, 21473, 21477, 21481, 21485, 21489, 21493, 21497,
4103
     21501, 21505, 21509, 21513, 21517, 21529, 21541, 21553, 21565, 21577,
4104
     21589, 21601, 21613, 21625, 21637, 21649, 21661, 21673, 21685, 21697,
4105
     21709, 21721, 21733, 21737, 21741, 21745, 21749},
4106
    {21749, 21761, 21773, 21785, 21797, 21809, 21817, 21825, 21833, 21841,
4107
     21849, 21857, 21865, 21873, 21881, 21889, 21897, 21905, 21913, 21921,
4108
     21929, 21937, 21945, 21953, 21961, 21969, 21977, 21985, 21993, 22001,
4109
     22009, 22017, 22025, 22033, 22041, 22049, 22057, 22065, 22073, 22081,
4110
     22089, 22097, 22105, 22113, 22121, 22129, 22137, 22145, 22153, 22161,
4111
     22169, 22177, 22185, 22193, 22201, 22209, 22217, 22225, 22233, 22241,
4112
     22249, 22257, 22265, 22273, 22281, 22289, 22297, 22305, 22313, 22321,
4113
     22329, 22337, 22345, 22353, 22361, 22369, 22377, 22385, 22393, 22401,
4114
     22409, 22417, 22425, 22433, 22441, 22449, 22457, 22465, 22473, 22481,
4115
     22489, 22497, 22505, 22513, 22521, 22533, 22545, 22557, 22569, 22581,
4116
     22593, 22605, 22617, 22629, 22641, 22653, 22665, 22673, 22681, 22689,
4117
     22697, 22705, 22713, 22721, 22729, 22737, 22745, 22753, 22761, 22769,
4118
     22777, 22785, 22793, 22801, 22809, 22817, 22825, 22833, 22841, 22849,
4119
     22857, 22865, 22873, 22881, 22889, 22897, 22905, 22913, 22921, 22929,
4120
     22937, 22945, 22953, 22961, 22969, 22977, 22985, 22993, 23001, 23009,
4121
     23017, 23025, 23037, 23049, 23061, 23073, 23085, 23093, 23101, 23109,
4122
     23117, 23125, 23133, 23141, 23149, 23157, 23165, 23173, 23181, 23189,
4123
     23197, 23205, 23213, 23221, 23229, 23237, 23245, 23253, 23261, 23269,
4124
     23277, 23285, 23293, 23301, 23309, 23317, 23325, 23333, 23341, 23349,
4125
     23357, 23365, 23373, 23381, 23389, 23397, 23405, 23413, 23421, 23429,
4126
     23437, 23445, 23453, 23461, 23469, 23477, 23485, 23493, 23501, 23509,
4127
     23517, 23525, 23533, 23541, 23549, 23557, 23565, 23573, 23581, 23589,
4128
     23597, 23605, 23613, 23621, 23633, 23645, 23653, 23661, 23669, 23677,
4129
     23685, 23693, 23701, 23709, 23717, 23725, 23733, 23741, 23749, 23757,
4130
     23765, 23773, 23781, 23793, 23805, 23817, 23825, 23833, 23841, 23849,
4131
     23857, 23865, 23873, 23881, 23889, 23897, 23905},
4132
    {23905, 23913, 23921, 23929, 23937, 23945, 23953, 23961, 23969, 23977,
4133
     23985, 23993, 24001, 24009, 24017, 24025, 24033, 24041, 24049, 24057,
4134
     24065, 24073, 24081, 24089, 24097, 24105, 24113, 24121, 24129, 24137,
4135
     24145, 24153, 24161, 24169, 24177, 24185, 24193, 24201, 24209, 24217,
4136
     24225, 24233, 24241, 24249, 24257, 24265, 24273, 24281, 24289, 24297,
4137
     24305, 24313, 24321, 24329, 24337, 24345, 24353, 24361, 24369, 24377,
4138
     24385, 24393, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4139
     24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400, 24400,
4140
     24401, 24413, 24425, 24437, 24449, 24461, 24473, 24485, 24497, 24509,
4141
     24521, 24533, 24545, 24557, 24569, 24581, 24593, 24605, 24617, 24629,
4142
     24641, 24653, 24665, 24677, 24689, 24701, 24713, 24725, 24737, 24749,
4143
     24761, 24773, 24785, 24797, 24809, 24821, 24833, 24845, 24857, 24869,
4144
     24881, 24893, 24905, 24917, 24929, 24941, 24953, 24965, 24977, 24989,
4145
     25001, 25013, 25025, 25037, 25049, 25061, 25073, 25085, 25097, 25109,
4146
     25121, 25133, 25145, 25157, 25168, 25168, 25169, 25181, 25193, 25205,
4147
     25217, 25229, 25241, 25253, 25265, 25277, 25289, 25301, 25313, 25325,
4148
     25337, 25349, 25361, 25373, 25385, 25397, 25409, 25421, 25433, 25445,
4149
     25457, 25469, 25481, 25493, 25505, 25517, 25529, 25541, 25553, 25565,
4150
     25577, 25589, 25601, 25613, 25625, 25637, 25649, 25661, 25673, 25685,
4151
     25697, 25709, 25721, 25733, 25745, 25757, 25769, 25781, 25793, 25805,
4152
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4153
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4154
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4155
     25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816, 25816,
4156
     25817, 25829, 25841, 25857, 25873, 25889, 25905, 25921, 25937, 25953,
4157
     25965, 26037, 26069, 26084, 26084, 26084, 26084},
4158
    {26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084, 26084,
4159
     26084, 26084, 26084, 26084, 26084, 26084, 26085, 26089, 26093, 26097,
4160
     26101, 26105, 26109, 26113, 26117, 26121, 26132, 26132, 26132, 26132,
4161
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132,
4162
     26132, 26132, 26132, 26132, 26132, 26132, 26132, 26132, 26133, 26141,
4163
     26145, 26149, 26153, 26157, 26161, 26165, 26169, 26173, 26177, 26181,
4164
     26185, 26189, 26193, 26197, 26201, 26205, 26209, 26213, 26217, 26220,
4165
     26220, 26221, 26225, 26229, 26237, 26245, 26253, 26261, 26265, 26269,
4166
     26273, 26277, 26281, 26284, 26285, 26289, 26293, 26297, 26301, 26305,
4167
     26309, 26313, 26317, 26321, 26325, 26329, 26333, 26337, 26341, 26345,
4168
     26349, 26353, 26357, 26360, 26361, 26365, 26369, 26373, 26376, 26376,
4169
     26376, 26376, 26377, 26385, 26393, 26400, 26401, 26408, 26409, 26417,
4170
     26425, 26433, 26441, 26449, 26457, 26465, 26473, 26481, 26489, 26493,
4171
     26501, 26509, 26517, 26525, 26533, 26541, 26549, 26557, 26565, 26573,
4172
     26581, 26589, 26593, 26597, 26601, 26605, 26609, 26613, 26617, 26621,
4173
     26625, 26629, 26633, 26637, 26641, 26645, 26649, 26653, 26657, 26661,
4174
     26665, 26669, 26673, 26677, 26681, 26685, 26689, 26693, 26697, 26701,
4175
     26705, 26709, 26713, 26717, 26721, 26725, 26729, 26733, 26737, 26741,
4176
     26745, 26749, 26753, 26757, 26761, 26765, 26769, 26773, 26777, 26781,
4177
     26785, 26789, 26793, 26797, 26801, 26805, 26809, 26813, 26817, 26821,
4178
     26825, 26829, 26833, 26837, 26841, 26845, 26849, 26853, 26857, 26861,
4179
     26865, 26869, 26873, 26877, 26881, 26885, 26889, 26893, 26897, 26901,
4180
     26905, 26909, 26913, 26917, 26921, 26925, 26929, 26933, 26937, 26941,
4181
     26945, 26949, 26953, 26957, 26961, 26965, 26969, 26973, 26977, 26981,
4182
     26985, 26989, 26993, 26997, 27001, 27005, 27017, 27029, 27041, 27053,
4183
     27065, 27077, 27085, 27092, 27092, 27092, 27092},
4184
    {27092, 27093, 27097, 27101, 27105, 27109, 27113, 27117, 27121, 27125,
4185
     27129, 27133, 27137, 27141, 27145, 27149, 27153, 27157, 27161, 27165,
4186
     27169, 27173, 27177, 27181, 27185, 27189, 27193, 27197, 27201, 27205,
4187
     27209, 27213, 27217, 27221, 27225, 27229, 27233, 27237, 27241, 27245,
4188
     27249, 27253, 27257, 27261, 27265, 27269, 27273, 27277, 27281, 27285,
4189
     27289, 27293, 27297, 27301, 27305, 27309, 27313, 27317, 27321, 27325,
4190
     27329, 27333, 27337, 27341, 27345, 27349, 27353, 27357, 27361, 27365,
4191
     27369, 27373, 27377, 27381, 27385, 27389, 27393, 27397, 27401, 27405,
4192
     27409, 27413, 27417, 27421, 27425, 27429, 27433, 27437, 27441, 27445,
4193
     27449, 27453, 27457, 27461, 27465, 27469, 27473, 27477, 27481, 27485,
4194
     27489, 27493, 27497, 27501, 27505, 27509, 27513, 27517, 27521, 27525,
4195
     27529, 27533, 27537, 27541, 27545, 27549, 27553, 27557, 27561, 27565,
4196
     27569, 27573, 27577, 27581, 27585, 27589, 27593, 27597, 27601, 27605,
4197
     27609, 27613, 27617, 27621, 27625, 27629, 27633, 27637, 27641, 27645,
4198
     27649, 27653, 27657, 27661, 27665, 27669, 27673, 27677, 27681, 27685,
4199
     27689, 27693, 27697, 27701, 27705, 27709, 27713, 27717, 27721, 27725,
4200
     27729, 27733, 27737, 27741, 27745, 27749, 27753, 27757, 27761, 27765,
4201
     27769, 27773, 27777, 27781, 27785, 27789, 27793, 27797, 27801, 27805,
4202
     27809, 27813, 27817, 27821, 27825, 27829, 27833, 27837, 27841, 27845,
4203
     27849, 27852, 27852, 27852, 27853, 27857, 27861, 27865, 27869, 27873,
4204
     27876, 27876, 27877, 27881, 27885, 27889, 27893, 27897, 27900, 27900,
4205
     27901, 27905, 27909, 27913, 27917, 27921, 27924, 27924, 27925, 27929,
4206
     27933, 27936, 27936, 27936, 27937, 27941, 27945, 27949, 27957, 27961,
4207
     27965, 27968, 27969, 27973, 27977, 27981, 27985, 27989, 27993, 27996,
4208
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4209
     27996, 27996, 27996, 27996, 27996, 27996, 27996},
4210
    {27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4211
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4212
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4213
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4214
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4215
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4216
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4217
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4218
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4219
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4220
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4221
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996,
4222
     27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27996, 27997,
4223
     28001, 28005, 28009, 28013, 28016, 28017, 28021, 28025, 28029, 28033,
4224
     28037, 28041, 28045, 28049, 28053, 28057, 28061, 28065, 28069, 28073,
4225
     28077, 28081, 28085, 28089, 28093, 28097, 28101, 28105, 28109, 28113,
4226
     28117, 28121, 28125, 28129, 28133, 28137, 28141, 28145, 28149, 28153,
4227
     28157, 28161, 28165, 28169, 28173, 28177, 28181, 28184, 28185, 28189,
4228
     28193, 28197, 28201, 28205, 28209, 28213, 28217, 28220, 28220, 28220,
4229
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4230
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4231
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4232
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4233
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4234
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4235
     28220, 28220, 28220, 28220, 28220, 28220, 28220},
4236
    {28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4237
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4238
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4239
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4240
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4241
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4242
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4243
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4244
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4245
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4246
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4247
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4248
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4249
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4250
     28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220, 28220,
4251
     28220, 28220, 28220, 28220, 28220, 28228, 28228, 28236, 28236, 28236,
4252
     28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236, 28236,
4253
     28236, 28236, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4254
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4255
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4256
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4257
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4258
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4259
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4260
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4261
     28244, 28244, 28244, 28244, 28244, 28244, 28244},
4262
    {28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4263
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4264
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4265
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244, 28244,
4266
     28244, 28244, 28244, 28244, 28244, 28244, 28244, 28252, 28260, 28260,
4267
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4268
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4269
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4270
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4271
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4272
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4273
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4274
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4275
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4276
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4277
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4278
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4279
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4280
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4281
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4282
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4283
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4284
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4285
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4286
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4287
     28260, 28260, 28260, 28260, 28260, 28260, 28260},
4288
    {28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4289
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4290
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4291
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4292
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4293
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4294
     28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260, 28260,
4295
     28260, 28260, 28260, 28260, 28260, 28260, 28268, 28276, 28276, 28276,
4296
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4297
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4298
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4299
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4300
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4301
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4302
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4303
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4304
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4305
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4306
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4307
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4308
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4309
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4310
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4311
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4312
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4313
     28276, 28276, 28276, 28276, 28276, 28276, 28276},
4314
    {28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4315
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4316
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4317
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4318
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4319
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4320
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4321
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4322
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4323
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4324
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4325
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4326
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4327
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4328
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4329
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4330
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4331
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276,
4332
     28276, 28276, 28276, 28276, 28276, 28276, 28276, 28276, 28284, 28292,
4333
     28292, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4334
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4335
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4336
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4337
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4338
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4339
     28300, 28300, 28300, 28300, 28300, 28300, 28300},
4340
    {28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4341
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4342
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4343
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4344
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4345
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4346
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4347
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4348
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4349
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4350
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4351
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4352
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4353
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4354
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4355
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4356
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4357
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300, 28300,
4358
     28300, 28300, 28300, 28300, 28300, 28300, 28300, 28308, 28316, 28316,
4359
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4360
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4361
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4362
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4363
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4364
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4365
     28316, 28316, 28316, 28316, 28316, 28316, 28316},
4366
    {28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4367
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4368
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4369
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4370
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316, 28316,
4371
     28316, 28316, 28316, 28316, 28316, 28316, 28316, 28324, 28324, 28324,
4372
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4373
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4374
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4375
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4376
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4377
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4378
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4379
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4380
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4381
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4382
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4383
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4384
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4385
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4386
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4387
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4388
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4389
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4390
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4391
     28324, 28324, 28324, 28324, 28324, 28324, 28324},
4392
    {28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4393
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4394
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4395
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4396
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4397
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4398
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4399
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4400
     28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324, 28324,
4401
     28324, 28324, 28324, 28324, 28324, 28332, 28340, 28352, 28364, 28376,
4402
     28388, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4403
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4404
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4405
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4406
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4407
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4408
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4409
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400,
4410
     28400, 28400, 28400, 28400, 28400, 28400, 28400, 28400, 28408, 28416,
4411
     28428, 28440, 28452, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4412
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4413
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4414
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4415
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4416
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4417
     28464, 28464, 28464, 28464, 28464, 28464, 28464},
4418
    {28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4419
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4420
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4421
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4422
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4423
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4424
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4425
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4426
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4427
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4428
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4429
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4430
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4431
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4432
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4433
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4434
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4435
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4436
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4437
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4438
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4439
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4440
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4441
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4442
     28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464, 28464,
4443
     28464, 28464, 28464, 28464, 28464, 28464, 28465},
4444
    {28465, 28469, 28473, 28477, 28481, 28485, 28489, 28493, 28497, 28501,
4445
     28505, 28509, 28513, 28517, 28521, 28525, 28529, 28533, 28537, 28541,
4446
     28545, 28549, 28553, 28557, 28561, 28565, 28569, 28573, 28577, 28581,
4447
     28585, 28589, 28593, 28597, 28601, 28605, 28609, 28613, 28617, 28621,
4448
     28625, 28629, 28633, 28637, 28641, 28645, 28649, 28653, 28657, 28661,
4449
     28665, 28669, 28673, 28677, 28681, 28685, 28689, 28693, 28697, 28701,
4450
     28705, 28709, 28713, 28717, 28721, 28725, 28729, 28733, 28737, 28741,
4451
     28745, 28749, 28753, 28757, 28761, 28765, 28769, 28773, 28777, 28781,
4452
     28785, 28789, 28793, 28797, 28801, 28804, 28805, 28809, 28813, 28817,
4453
     28821, 28825, 28829, 28833, 28837, 28841, 28845, 28849, 28853, 28857,
4454
     28861, 28865, 28869, 28873, 28877, 28881, 28885, 28889, 28893, 28897,
4455
     28901, 28905, 28909, 28913, 28917, 28921, 28925, 28929, 28933, 28937,
4456
     28941, 28945, 28949, 28953, 28957, 28961, 28965, 28969, 28973, 28977,
4457
     28981, 28985, 28989, 28993, 28997, 29001, 29005, 29009, 29013, 29017,
4458
     29021, 29025, 29029, 29033, 29037, 29041, 29045, 29049, 29053, 29057,
4459
     29061, 29065, 29069, 29073, 29077, 29081, 29085, 29088, 29089, 29093,
4460
     29096, 29096, 29097, 29100, 29100, 29101, 29105, 29108, 29108, 29109,
4461
     29113, 29117, 29121, 29124, 29125, 29129, 29133, 29137, 29141, 29145,
4462
     29149, 29153, 29157, 29161, 29165, 29169, 29172, 29173, 29176, 29177,
4463
     29181, 29185, 29189, 29193, 29197, 29201, 29204, 29205, 29209, 29213,
4464
     29217, 29221, 29225, 29229, 29233, 29237, 29241, 29245, 29249, 29253,
4465
     29257, 29261, 29265, 29269, 29273, 29277, 29281, 29285, 29289, 29293,
4466
     29297, 29301, 29305, 29309, 29313, 29317, 29321, 29325, 29329, 29333,
4467
     29337, 29341, 29345, 29349, 29353, 29357, 29361, 29365, 29369, 29373,
4468
     29377, 29381, 29385, 29389, 29393, 29397, 29401, 29405, 29409, 29413,
4469
     29417, 29421, 29425, 29429, 29433, 29437, 29441},
4470
    {29441, 29445, 29449, 29453, 29457, 29461, 29464, 29465, 29469, 29473,
4471
     29477, 29480, 29480, 29481, 29485, 29489, 29493, 29497, 29501, 29505,
4472
     29509, 29512, 29513, 29517, 29521, 29525, 29529, 29533, 29537, 29540,
4473
     29541, 29545, 29549, 29553, 29557, 29561, 29565, 29569, 29573, 29577,
4474
     29581, 29585, 29589, 29593, 29597, 29601, 29605, 29609, 29613, 29617,
4475
     29621, 29625, 29629, 29633, 29637, 29641, 29645, 29649, 29652, 29653,
4476
     29657, 29661, 29665, 29668, 29669, 29673, 29677, 29681, 29685, 29688,
4477
     29689, 29692, 29692, 29692, 29693, 29697, 29701, 29705, 29709, 29713,
4478
     29717, 29720, 29721, 29725, 29729, 29733, 29737, 29741, 29745, 29749,
4479
     29753, 29757, 29761, 29765, 29769, 29773, 29777, 29781, 29785, 29789,
4480
     29793, 29797, 29801, 29805, 29809, 29813, 29817, 29821, 29825, 29829,
4481
     29833, 29837, 29841, 29845, 29849, 29853, 29857, 29861, 29865, 29869,
4482
     29873, 29877, 29881, 29885, 29889, 29893, 29897, 29901, 29905, 29909,
4483
     29913, 29917, 29921, 29925, 29929, 29933, 29937, 29941, 29945, 29949,
4484
     29953, 29957, 29961, 29965, 29969, 29973, 29977, 29981, 29985, 29989,
4485
     29993, 29997, 30001, 30005, 30009, 30013, 30017, 30021, 30025, 30029,
4486
     30033, 30037, 30041, 30045, 30049, 30053, 30057, 30061, 30065, 30069,
4487
     30073, 30077, 30081, 30085, 30089, 30093, 30097, 30101, 30105, 30109,
4488
     30113, 30117, 30121, 30125, 30129, 30133, 30137, 30141, 30145, 30149,
4489
     30153, 30157, 30161, 30165, 30169, 30173, 30177, 30181, 30185, 30189,
4490
     30193, 30197, 30201, 30205, 30209, 30213, 30217, 30221, 30225, 30229,
4491
     30233, 30237, 30241, 30245, 30249, 30253, 30257, 30261, 30265, 30269,
4492
     30273, 30277, 30281, 30285, 30289, 30293, 30297, 30301, 30305, 30309,
4493
     30313, 30317, 30321, 30325, 30329, 30333, 30337, 30341, 30345, 30349,
4494
     30353, 30357, 30361, 30365, 30369, 30373, 30377, 30381, 30385, 30389,
4495
     30393, 30397, 30401, 30405, 30409, 30413, 30417},
4496
    {30417, 30421, 30425, 30429, 30433, 30437, 30441, 30445, 30449, 30453,
4497
     30457, 30461, 30465, 30469, 30473, 30477, 30481, 30485, 30489, 30493,
4498
     30497, 30501, 30505, 30509, 30513, 30517, 30521, 30525, 30529, 30533,
4499
     30537, 30541, 30545, 30549, 30553, 30557, 30561, 30565, 30569, 30573,
4500
     30577, 30581, 30585, 30589, 30593, 30597, 30601, 30605, 30609, 30613,
4501
     30617, 30621, 30625, 30629, 30633, 30637, 30641, 30645, 30649, 30653,
4502
     30657, 30661, 30665, 30669, 30673, 30677, 30681, 30685, 30689, 30693,
4503
     30697, 30701, 30705, 30709, 30713, 30717, 30721, 30725, 30729, 30733,
4504
     30737, 30741, 30745, 30749, 30753, 30757, 30761, 30765, 30769, 30773,
4505
     30777, 30781, 30785, 30789, 30793, 30797, 30801, 30805, 30809, 30813,
4506
     30817, 30821, 30825, 30829, 30833, 30837, 30841, 30845, 30849, 30853,
4507
     30857, 30861, 30865, 30869, 30873, 30877, 30881, 30885, 30889, 30893,
4508
     30897, 30901, 30905, 30909, 30913, 30917, 30921, 30925, 30929, 30933,
4509
     30937, 30941, 30945, 30949, 30953, 30957, 30961, 30965, 30969, 30973,
4510
     30977, 30981, 30985, 30989, 30993, 30997, 31001, 31005, 31009, 31013,
4511
     31017, 31021, 31025, 31029, 31033, 31037, 31041, 31045, 31049, 31053,
4512
     31057, 31061, 31065, 31069, 31073, 31077, 31080, 31080, 31081, 31085,
4513
     31089, 31093, 31097, 31101, 31105, 31109, 31113, 31117, 31121, 31125,
4514
     31129, 31133, 31137, 31141, 31145, 31149, 31153, 31157, 31161, 31165,
4515
     31169, 31173, 31177, 31181, 31185, 31189, 31193, 31197, 31201, 31205,
4516
     31209, 31213, 31217, 31221, 31225, 31229, 31233, 31237, 31241, 31245,
4517
     31249, 31253, 31257, 31261, 31265, 31269, 31273, 31277, 31281, 31285,
4518
     31289, 31293, 31297, 31301, 31305, 31309, 31313, 31317, 31321, 31325,
4519
     31329, 31333, 31337, 31341, 31345, 31349, 31353, 31357, 31361, 31365,
4520
     31369, 31373, 31377, 31381, 31385, 31389, 31393, 31397, 31401, 31405,
4521
     31409, 31413, 31417, 31421, 31425, 31429, 31433},
4522
    {31433, 31437, 31441, 31445, 31449, 31453, 31457, 31461, 31465, 31469,
4523
     31473, 31477, 31481, 31485, 31489, 31493, 31497, 31501, 31505, 31509,
4524
     31513, 31517, 31521, 31525, 31529, 31533, 31537, 31541, 31545, 31549,
4525
     31553, 31557, 31561, 31565, 31569, 31573, 31577, 31581, 31585, 31589,
4526
     31593, 31597, 31601, 31605, 31609, 31613, 31617, 31621, 31625, 31629,
4527
     31633, 31637, 31641, 31645, 31649, 31653, 31657, 31661, 31665, 31669,
4528
     31673, 31677, 31681, 31685, 31689, 31693, 31697, 31701, 31705, 31709,
4529
     31713, 31717, 31721, 31725, 31729, 31733, 31737, 31741, 31745, 31749,
4530
     31753, 31757, 31761, 31765, 31769, 31773, 31777, 31781, 31785, 31789,
4531
     31793, 31797, 31801, 31805, 31809, 31813, 31817, 31821, 31825, 31829,
4532
     31833, 31837, 31841, 31845, 31849, 31853, 31857, 31861, 31865, 31869,
4533
     31873, 31877, 31881, 31885, 31889, 31893, 31897, 31901, 31905, 31909,
4534
     31913, 31917, 31921, 31925, 31929, 31933, 31937, 31941, 31945, 31949,
4535
     31953, 31957, 31961, 31965, 31969, 31973, 31977, 31981, 31985, 31989,
4536
     31993, 31997, 32001, 32005, 32009, 32013, 32017, 32021, 32025, 32029,
4537
     32033, 32037, 32041, 32045, 32049, 32053, 32057, 32061, 32065, 32069,
4538
     32073, 32077, 32081, 32085, 32089, 32093, 32097, 32101, 32105, 32109,
4539
     32113, 32117, 32121, 32125, 32129, 32133, 32137, 32141, 32145, 32149,
4540
     32153, 32157, 32161, 32165, 32169, 32173, 32177, 32181, 32185, 32189,
4541
     32193, 32197, 32201, 32205, 32209, 32213, 32217, 32221, 32225, 32229,
4542
     32233, 32237, 32241, 32245, 32248, 32248, 32249, 32253, 32257, 32261,
4543
     32265, 32269, 32273, 32277, 32281, 32285, 32289, 32293, 32297, 32301,
4544
     32305, 32309, 32313, 32317, 32321, 32325, 32329, 32333, 32337, 32341,
4545
     32345, 32349, 32353, 32357, 32361, 32365, 32369, 32373, 32377, 32381,
4546
     32385, 32389, 32393, 32397, 32401, 32405, 32409, 32413, 32417, 32421,
4547
     32425, 32429, 32433, 32437, 32441, 32445, 32448},
4548
    {32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4549
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4550
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4551
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448,
4552
     32448, 32448, 32448, 32448, 32448, 32448, 32448, 32448, 32449, 32453,
4553
     32457, 32461, 32465, 32469, 32473, 32477, 32481, 32485, 32489, 32493,
4554
     32497, 32501, 32505, 32509, 32513, 32517, 32521, 32525, 32529, 32533,
4555
     32537, 32541, 32545, 32549, 32553, 32557, 32561, 32565, 32569, 32573,
4556
     32577, 32581, 32585, 32589, 32593, 32597, 32601, 32605, 32609, 32613,
4557
     32617, 32621, 32625, 32629, 32633, 32637, 32641, 32645, 32649, 32653,
4558
     32657, 32661, 32665, 32669, 32673, 32677, 32681, 32685, 32689, 32693,
4559
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4560
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4561
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4562
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4563
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4564
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4565
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4566
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4567
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4568
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4569
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4570
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4571
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4572
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4573
     32696, 32696, 32696, 32696, 32696, 32696, 32696},
4574
    {32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4575
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4576
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4577
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4578
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4579
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4580
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4581
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4582
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4583
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4584
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4585
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4586
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4587
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4588
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4589
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4590
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4591
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4592
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4593
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4594
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4595
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4596
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4597
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4598
     32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696, 32696,
4599
     32696, 32696, 32696, 32696, 32696, 32696, 32697},
4600
    {32697, 32701, 32705, 32709, 32712, 32713, 32717, 32721, 32725, 32729,
4601
     32733, 32737, 32741, 32745, 32749, 32753, 32757, 32761, 32765, 32769,
4602
     32773, 32777, 32781, 32785, 32789, 32793, 32797, 32801, 32805, 32809,
4603
     32813, 32817, 32820, 32821, 32825, 32828, 32829, 32832, 32832, 32833,
4604
     32836, 32837, 32841, 32845, 32849, 32853, 32857, 32861, 32865, 32869,
4605
     32873, 32876, 32877, 32881, 32885, 32889, 32892, 32893, 32896, 32897,
4606
     32900, 32900, 32900, 32900, 32900, 32900, 32901, 32904, 32904, 32904,
4607
     32904, 32905, 32908, 32909, 32912, 32913, 32916, 32917, 32921, 32925,
4608
     32928, 32929, 32933, 32936, 32937, 32940, 32940, 32941, 32944, 32945,
4609
     32948, 32949, 32952, 32953, 32956, 32957, 32960, 32961, 32965, 32968,
4610
     32969, 32972, 32972, 32973, 32977, 32981, 32985, 32988, 32989, 32993,
4611
     32997, 33001, 33005, 33009, 33013, 33016, 33017, 33021, 33025, 33029,
4612
     33032, 33033, 33037, 33041, 33045, 33048, 33049, 33052, 33053, 33057,
4613
     33061, 33065, 33069, 33073, 33077, 33081, 33085, 33089, 33092, 33093,
4614
     33097, 33101, 33105, 33109, 33113, 33117, 33121, 33125, 33129, 33133,
4615
     33137, 33141, 33145, 33149, 33153, 33157, 33160, 33160, 33160, 33160,
4616
     33160, 33161, 33165, 33169, 33172, 33173, 33177, 33181, 33185, 33189,
4617
     33192, 33193, 33197, 33201, 33205, 33209, 33213, 33217, 33221, 33225,
4618
     33229, 33233, 33237, 33241, 33245, 33249, 33253, 33257, 33260, 33260,
4619
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4620
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4621
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4622
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4623
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4624
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4625
     33260, 33260, 33260, 33260, 33260, 33260, 33260},
4626
    {33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4627
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4628
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4629
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4630
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4631
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4632
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4633
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4634
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4635
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4636
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4637
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4638
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4639
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4640
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4641
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4642
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4643
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4644
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4645
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4646
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4647
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4648
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4649
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4650
     33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260, 33260,
4651
     33260, 33260, 33260, 33260, 33260, 33260, 33261},
4652
    {33261, 33269, 33277, 33285, 33293, 33301, 33309, 33317, 33325, 33333,
4653
     33341, 33348, 33348, 33348, 33348, 33348, 33349, 33361, 33373, 33385,
4654
     33397, 33409, 33421, 33433, 33445, 33457, 33469, 33481, 33493, 33505,
4655
     33517, 33529, 33541, 33553, 33565, 33577, 33589, 33601, 33613, 33625,
4656
     33637, 33649, 33661, 33673, 33677, 33681, 33689, 33696, 33697, 33701,
4657
     33705, 33709, 33713, 33717, 33721, 33725, 33729, 33733, 33737, 33741,
4658
     33745, 33749, 33753, 33757, 33761, 33765, 33769, 33773, 33777, 33781,
4659
     33785, 33789, 33793, 33797, 33801, 33809, 33817, 33825, 33833, 33845,
4660
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4661
     33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852, 33852,
4662
     33852, 33852, 33852, 33852, 33852, 33852, 33853, 33861, 33869, 33876,
4663
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4664
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4665
     33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876, 33876,
4666
     33876, 33876, 33876, 33876, 33877, 33884, 33884, 33884, 33884, 33884,
4667
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4668
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4669
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4670
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4671
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4672
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4673
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4674
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4675
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4676
     33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884, 33884,
4677
     33884, 33884, 33884, 33884, 33884, 33884, 33885},
4678
    {33885, 33893, 33901, 33904, 33904, 33904, 33904, 33904, 33904, 33904,
4679
     33904, 33904, 33904, 33904, 33904, 33904, 33905, 33909, 33913, 33917,
4680
     33925, 33929, 33933, 33937, 33941, 33945, 33949, 33953, 33957, 33961,
4681
     33965, 33969, 33973, 33977, 33981, 33985, 33989, 33993, 33997, 34001,
4682
     34005, 34009, 34013, 34017, 34021, 34025, 34029, 34033, 34037, 34041,
4683
     34045, 34049, 34053, 34057, 34061, 34065, 34069, 34073, 34077, 34081,
4684
     34084, 34084, 34084, 34084, 34085, 34097, 34109, 34121, 34133, 34145,
4685
     34157, 34169, 34181, 34192, 34192, 34192, 34192, 34192, 34192, 34192,
4686
     34193, 34197, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4687
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4688
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4689
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4690
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4691
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4692
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4693
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4694
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4695
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4696
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4697
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4698
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4699
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4700
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4701
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4702
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4703
     34200, 34200, 34200, 34200, 34200, 34200, 34200},
4704
    {34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4705
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4706
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4707
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4708
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4709
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4710
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4711
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4712
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4713
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4714
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4715
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4716
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4717
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4718
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4719
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4720
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4721
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4722
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4723
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4724
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4725
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4726
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4727
     34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200, 34200,
4728
     34201, 34205, 34209, 34213, 34217, 34221, 34225, 34229, 34233, 34237,
4729
     34240, 34240, 34240, 34240, 34240, 34240, 34240},
4730
    {34240, 34244, 34248, 34252, 34256, 34260, 34264, 34268, 34272, 34276,
4731
     34280, 34284, 34288, 34292, 34296, 34300, 34304, 34308, 34312, 34316,
4732
     34320, 34324, 34328, 34332, 34336, 34340, 34344, 34348, 34352, 34356,
4733
     34360, 34364, 34368, 34372, 34376, 34380, 34384, 34388, 34392, 34396,
4734
     34400, 34404, 34408, 34412, 34416, 34420, 34424, 34428, 34432, 34436,
4735
     34440, 34444, 34448, 34452, 34456, 34460, 34464, 34468, 34472, 34476,
4736
     34480, 34484, 34488, 34492, 34496, 34500, 34504, 34508, 34512, 34516,
4737
     34520, 34524, 34528, 34532, 34536, 34540, 34544, 34548, 34552, 34556,
4738
     34560, 34564, 34568, 34572, 34576, 34580, 34584, 34588, 34592, 34596,
4739
     34600, 34604, 34608, 34612, 34616, 34620, 34624, 34628, 34632, 34636,
4740
     34640, 34644, 34648, 34652, 34656, 34660, 34664, 34668, 34672, 34676,
4741
     34680, 34684, 34688, 34692, 34696, 34700, 34704, 34708, 34712, 34716,
4742
     34720, 34724, 34728, 34732, 34736, 34740, 34744, 34748, 34752, 34756,
4743
     34760, 34764, 34768, 34772, 34776, 34780, 34784, 34788, 34792, 34796,
4744
     34800, 34804, 34808, 34812, 34816, 34820, 34824, 34828, 34832, 34836,
4745
     34840, 34844, 34848, 34852, 34856, 34860, 34864, 34868, 34872, 34876,
4746
     34880, 34884, 34888, 34892, 34896, 34900, 34904, 34908, 34912, 34916,
4747
     34920, 34924, 34928, 34932, 34936, 34940, 34944, 34948, 34952, 34956,
4748
     34960, 34964, 34968, 34972, 34976, 34980, 34984, 34988, 34992, 34996,
4749
     35000, 35004, 35008, 35012, 35016, 35020, 35024, 35028, 35032, 35036,
4750
     35040, 35044, 35048, 35052, 35056, 35060, 35064, 35068, 35072, 35076,
4751
     35080, 35084, 35088, 35092, 35096, 35100, 35104, 35108, 35112, 35116,
4752
     35120, 35124, 35128, 35132, 35136, 35140, 35144, 35148, 35152, 35156,
4753
     35160, 35164, 35168, 35172, 35176, 35180, 35184, 35188, 35192, 35196,
4754
     35200, 35204, 35208, 35212, 35216, 35220, 35224, 35228, 35232, 35236,
4755
     35240, 35244, 35248, 35252, 35256, 35260, 35264},
4756
    {35264, 35268, 35272, 35276, 35280, 35284, 35288, 35292, 35296, 35300,
4757
     35304, 35308, 35312, 35316, 35320, 35324, 35328, 35332, 35336, 35340,
4758
     35344, 35348, 35352, 35356, 35360, 35364, 35368, 35372, 35376, 35380,
4759
     35384, 35388, 35392, 35396, 35400, 35404, 35408, 35412, 35416, 35420,
4760
     35424, 35428, 35432, 35436, 35440, 35444, 35448, 35452, 35456, 35460,
4761
     35464, 35468, 35472, 35476, 35480, 35484, 35488, 35492, 35496, 35500,
4762
     35504, 35508, 35512, 35516, 35520, 35524, 35528, 35532, 35536, 35540,
4763
     35544, 35548, 35552, 35556, 35560, 35564, 35568, 35572, 35576, 35580,
4764
     35584, 35588, 35592, 35596, 35600, 35604, 35608, 35612, 35616, 35620,
4765
     35624, 35628, 35632, 35636, 35640, 35644, 35648, 35652, 35656, 35660,
4766
     35664, 35668, 35672, 35676, 35680, 35684, 35688, 35692, 35696, 35700,
4767
     35704, 35708, 35712, 35716, 35720, 35724, 35728, 35732, 35736, 35740,
4768
     35744, 35748, 35752, 35756, 35760, 35764, 35768, 35772, 35776, 35780,
4769
     35784, 35788, 35792, 35796, 35800, 35804, 35808, 35812, 35816, 35820,
4770
     35824, 35828, 35832, 35836, 35840, 35844, 35848, 35852, 35856, 35860,
4771
     35864, 35868, 35872, 35876, 35880, 35884, 35888, 35892, 35896, 35900,
4772
     35904, 35908, 35912, 35916, 35920, 35924, 35928, 35932, 35936, 35940,
4773
     35944, 35948, 35952, 35956, 35960, 35964, 35968, 35972, 35976, 35980,
4774
     35984, 35988, 35992, 35996, 36000, 36004, 36008, 36012, 36016, 36020,
4775
     36024, 36028, 36032, 36036, 36040, 36044, 36048, 36052, 36056, 36060,
4776
     36064, 36068, 36072, 36076, 36080, 36084, 36088, 36092, 36096, 36100,
4777
     36104, 36108, 36112, 36116, 36120, 36124, 36128, 36132, 36136, 36140,
4778
     36144, 36148, 36152, 36156, 36160, 36164, 36168, 36172, 36176, 36180,
4779
     36184, 36188, 36192, 36196, 36200, 36204, 36208, 36212, 36216, 36220,
4780
     36224, 36228, 36232, 36236, 36240, 36244, 36248, 36252, 36256, 36260,
4781
     36264, 36268, 36272, 36276, 36280, 36284, 36288},
4782
    {36288, 36292, 36296, 36300, 36304, 36308, 36312, 36316, 36320, 36324,
4783
     36328, 36332, 36336, 36340, 36344, 36348, 36352, 36356, 36360, 36364,
4784
     36368, 36372, 36376, 36380, 36384, 36388, 36392, 36396, 36400, 36404,
4785
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4786
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4787
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4788
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4789
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4790
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4791
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4792
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4793
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4794
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4795
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4796
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4797
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4798
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4799
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4800
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4801
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4802
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4803
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4804
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4805
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4806
     36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408, 36408,
4807
     36408, 36408, 36408, 36408, 36408, 36408, 36408}};
4808
const char32_t decomposition_data[9102] = {
4809
    0,      32,     32,     776,    97,     32,     772,    50,     51,
4810
    32,     769,    956,    32,     807,    49,     111,    49,     8260,
4811
    52,     49,     8260,   50,     51,     8260,   52,     65,     768,
4812
    65,     769,    65,     770,    65,     771,    65,     776,    65,
4813
    778,    67,     807,    69,     768,    69,     769,    69,     770,
4814
    69,     776,    73,     768,    73,     769,    73,     770,    73,
4815
    776,    78,     771,    79,     768,    79,     769,    79,     770,
4816
    79,     771,    79,     776,    85,     768,    85,     769,    85,
4817
    770,    85,     776,    89,     769,    97,     768,    97,     769,
4818
    97,     770,    97,     771,    97,     776,    97,     778,    99,
4819
    807,    101,    768,    101,    769,    101,    770,    101,    776,
4820
    105,    768,    105,    769,    105,    770,    105,    776,    110,
4821
    771,    111,    768,    111,    769,    111,    770,    111,    771,
4822
    111,    776,    117,    768,    117,    769,    117,    770,    117,
4823
    776,    121,    769,    121,    776,    65,     772,    97,     772,
4824
    65,     774,    97,     774,    65,     808,    97,     808,    67,
4825
    769,    99,     769,    67,     770,    99,     770,    67,     775,
4826
    99,     775,    67,     780,    99,     780,    68,     780,    100,
4827
    780,    69,     772,    101,    772,    69,     774,    101,    774,
4828
    69,     775,    101,    775,    69,     808,    101,    808,    69,
4829
    780,    101,    780,    71,     770,    103,    770,    71,     774,
4830
    103,    774,    71,     775,    103,    775,    71,     807,    103,
4831
    807,    72,     770,    104,    770,    73,     771,    105,    771,
4832
    73,     772,    105,    772,    73,     774,    105,    774,    73,
4833
    808,    105,    808,    73,     775,    73,     74,     105,    106,
4834
    74,     770,    106,    770,    75,     807,    107,    807,    76,
4835
    769,    108,    769,    76,     807,    108,    807,    76,     780,
4836
    108,    780,    76,     183,    108,    183,    78,     769,    110,
4837
    769,    78,     807,    110,    807,    78,     780,    110,    780,
4838
    700,    110,    79,     772,    111,    772,    79,     774,    111,
4839
    774,    79,     779,    111,    779,    82,     769,    114,    769,
4840
    82,     807,    114,    807,    82,     780,    114,    780,    83,
4841
    769,    115,    769,    83,     770,    115,    770,    83,     807,
4842
    115,    807,    83,     780,    115,    780,    84,     807,    116,
4843
    807,    84,     780,    116,    780,    85,     771,    117,    771,
4844
    85,     772,    117,    772,    85,     774,    117,    774,    85,
4845
    778,    117,    778,    85,     779,    117,    779,    85,     808,
4846
    117,    808,    87,     770,    119,    770,    89,     770,    121,
4847
    770,    89,     776,    90,     769,    122,    769,    90,     775,
4848
    122,    775,    90,     780,    122,    780,    115,    79,     795,
4849
    111,    795,    85,     795,    117,    795,    68,     90,     780,
4850
    68,     122,    780,    100,    122,    780,    76,     74,     76,
4851
    106,    108,    106,    78,     74,     78,     106,    110,    106,
4852
    65,     780,    97,     780,    73,     780,    105,    780,    79,
4853
    780,    111,    780,    85,     780,    117,    780,    85,     776,
4854
    772,    117,    776,    772,    85,     776,    769,    117,    776,
4855
    769,    85,     776,    780,    117,    776,    780,    85,     776,
4856
    768,    117,    776,    768,    65,     776,    772,    97,     776,
4857
    772,    65,     775,    772,    97,     775,    772,    198,    772,
4858
    230,    772,    71,     780,    103,    780,    75,     780,    107,
4859
    780,    79,     808,    111,    808,    79,     808,    772,    111,
4860
    808,    772,    439,    780,    658,    780,    106,    780,    68,
4861
    90,     68,     122,    100,    122,    71,     769,    103,    769,
4862
    78,     768,    110,    768,    65,     778,    769,    97,     778,
4863
    769,    198,    769,    230,    769,    216,    769,    248,    769,
4864
    65,     783,    97,     783,    65,     785,    97,     785,    69,
4865
    783,    101,    783,    69,     785,    101,    785,    73,     783,
4866
    105,    783,    73,     785,    105,    785,    79,     783,    111,
4867
    783,    79,     785,    111,    785,    82,     783,    114,    783,
4868
    82,     785,    114,    785,    85,     783,    117,    783,    85,
4869
    785,    117,    785,    83,     806,    115,    806,    84,     806,
4870
    116,    806,    72,     780,    104,    780,    65,     775,    97,
4871
    775,    69,     807,    101,    807,    79,     776,    772,    111,
4872
    776,    772,    79,     771,    772,    111,    771,    772,    79,
4873
    775,    111,    775,    79,     775,    772,    111,    775,    772,
4874
    89,     772,    121,    772,    104,    614,    106,    114,    633,
4875
    635,    641,    119,    121,    32,     774,    32,     775,    32,
4876
    778,    32,     808,    32,     771,    32,     779,    611,    108,
4877
    115,    120,    661,    768,    769,    787,    776,    769,    697,
4878
    32,     837,    59,     32,     769,    168,    769,    913,    769,
4879
    183,    917,    769,    919,    769,    921,    769,    927,    769,
4880
    933,    769,    937,    769,    953,    776,    769,    921,    776,
4881
    933,    776,    945,    769,    949,    769,    951,    769,    953,
4882
    769,    965,    776,    769,    953,    776,    965,    776,    959,
4883
    769,    965,    769,    969,    769,    946,    952,    933,    978,
4884
    769,    978,    776,    966,    960,    954,    961,    962,    920,
4885
    949,    931,    1045,   768,    1045,   776,    1043,   769,    1030,
4886
    776,    1050,   769,    1048,   768,    1059,   774,    1048,   774,
4887
    1080,   774,    1077,   768,    1077,   776,    1075,   769,    1110,
4888
    776,    1082,   769,    1080,   768,    1091,   774,    1140,   783,
4889
    1141,   783,    1046,   774,    1078,   774,    1040,   774,    1072,
4890
    774,    1040,   776,    1072,   776,    1045,   774,    1077,   774,
4891
    1240,   776,    1241,   776,    1046,   776,    1078,   776,    1047,
4892
    776,    1079,   776,    1048,   772,    1080,   772,    1048,   776,
4893
    1080,   776,    1054,   776,    1086,   776,    1256,   776,    1257,
4894
    776,    1069,   776,    1101,   776,    1059,   772,    1091,   772,
4895
    1059,   776,    1091,   776,    1059,   779,    1091,   779,    1063,
4896
    776,    1095,   776,    1067,   776,    1099,   776,    1381,   1410,
4897
    1575,   1619,   1575,   1620,   1608,   1620,   1575,   1621,   1610,
4898
    1620,   1575,   1652,   1608,   1652,   1735,   1652,   1610,   1652,
4899
    1749,   1620,   1729,   1620,   1746,   1620,   2344,   2364,   2352,
4900
    2364,   2355,   2364,   2325,   2364,   2326,   2364,   2327,   2364,
4901
    2332,   2364,   2337,   2364,   2338,   2364,   2347,   2364,   2351,
4902
    2364,   2503,   2494,   2503,   2519,   2465,   2492,   2466,   2492,
4903
    2479,   2492,   2610,   2620,   2616,   2620,   2582,   2620,   2583,
4904
    2620,   2588,   2620,   2603,   2620,   2887,   2902,   2887,   2878,
4905
    2887,   2903,   2849,   2876,   2850,   2876,   2962,   3031,   3014,
4906
    3006,   3015,   3006,   3014,   3031,   3142,   3158,   3263,   3285,
4907
    3270,   3285,   3270,   3286,   3270,   3266,   3270,   3266,   3285,
4908
    3398,   3390,   3399,   3390,   3398,   3415,   3545,   3530,   3545,
4909
    3535,   3545,   3535,   3530,   3545,   3551,   3661,   3634,   3789,
4910
    3762,   3755,   3737,   3755,   3745,   3851,   3906,   4023,   3916,
4911
    4023,   3921,   4023,   3926,   4023,   3931,   4023,   3904,   4021,
4912
    3953,   3954,   3953,   3956,   4018,   3968,   4018,   3953,   3968,
4913
    4019,   3968,   4019,   3953,   3968,   3953,   3968,   3986,   4023,
4914
    3996,   4023,   4001,   4023,   4006,   4023,   4011,   4023,   3984,
4915
    4021,   4133,   4142,   4316,   6917,   6965,   6919,   6965,   6921,
4916
    6965,   6923,   6965,   6925,   6965,   6929,   6965,   6970,   6965,
4917
    6972,   6965,   6974,   6965,   6975,   6965,   6978,   6965,   65,
4918
    198,    66,     68,     69,     398,    71,     72,     73,     74,
4919
    75,     76,     77,     78,     79,     546,    80,     82,     84,
4920
    85,     87,     97,     592,    593,    7426,   98,     100,    101,
4921
    601,    603,    604,    103,    107,    109,    331,    111,    596,
4922
    7446,   7447,   112,    116,    117,    7453,   623,    118,    7461,
4923
    946,    947,    948,    966,    967,    105,    114,    117,    118,
4924
    946,    947,    961,    966,    967,    1085,   594,    99,     597,
4925
    240,    604,    102,    607,    609,    613,    616,    617,    618,
4926
    7547,   669,    621,    7557,   671,    625,    624,    626,    627,
4927
    628,    629,    632,    642,    643,    427,    649,    650,    7452,
4928
    651,    652,    122,    656,    657,    658,    952,    65,     805,
4929
    97,     805,    66,     775,    98,     775,    66,     803,    98,
4930
    803,    66,     817,    98,     817,    67,     807,    769,    99,
4931
    807,    769,    68,     775,    100,    775,    68,     803,    100,
4932
    803,    68,     817,    100,    817,    68,     807,    100,    807,
4933
    68,     813,    100,    813,    69,     772,    768,    101,    772,
4934
    768,    69,     772,    769,    101,    772,    769,    69,     813,
4935
    101,    813,    69,     816,    101,    816,    69,     807,    774,
4936
    101,    807,    774,    70,     775,    102,    775,    71,     772,
4937
    103,    772,    72,     775,    104,    775,    72,     803,    104,
4938
    803,    72,     776,    104,    776,    72,     807,    104,    807,
4939
    72,     814,    104,    814,    73,     816,    105,    816,    73,
4940
    776,    769,    105,    776,    769,    75,     769,    107,    769,
4941
    75,     803,    107,    803,    75,     817,    107,    817,    76,
4942
    803,    108,    803,    76,     803,    772,    108,    803,    772,
4943
    76,     817,    108,    817,    76,     813,    108,    813,    77,
4944
    769,    109,    769,    77,     775,    109,    775,    77,     803,
4945
    109,    803,    78,     775,    110,    775,    78,     803,    110,
4946
    803,    78,     817,    110,    817,    78,     813,    110,    813,
4947
    79,     771,    769,    111,    771,    769,    79,     771,    776,
4948
    111,    771,    776,    79,     772,    768,    111,    772,    768,
4949
    79,     772,    769,    111,    772,    769,    80,     769,    112,
4950
    769,    80,     775,    112,    775,    82,     775,    114,    775,
4951
    82,     803,    114,    803,    82,     803,    772,    114,    803,
4952
    772,    82,     817,    114,    817,    83,     775,    115,    775,
4953
    83,     803,    115,    803,    83,     769,    775,    115,    769,
4954
    775,    83,     780,    775,    115,    780,    775,    83,     803,
4955
    775,    115,    803,    775,    84,     775,    116,    775,    84,
4956
    803,    116,    803,    84,     817,    116,    817,    84,     813,
4957
    116,    813,    85,     804,    117,    804,    85,     816,    117,
4958
    816,    85,     813,    117,    813,    85,     771,    769,    117,
4959
    771,    769,    85,     772,    776,    117,    772,    776,    86,
4960
    771,    118,    771,    86,     803,    118,    803,    87,     768,
4961
    119,    768,    87,     769,    119,    769,    87,     776,    119,
4962
    776,    87,     775,    119,    775,    87,     803,    119,    803,
4963
    88,     775,    120,    775,    88,     776,    120,    776,    89,
4964
    775,    121,    775,    90,     770,    122,    770,    90,     803,
4965
    122,    803,    90,     817,    122,    817,    104,    817,    116,
4966
    776,    119,    778,    121,    778,    97,     702,    383,    775,
4967
    65,     803,    97,     803,    65,     777,    97,     777,    65,
4968
    770,    769,    97,     770,    769,    65,     770,    768,    97,
4969
    770,    768,    65,     770,    777,    97,     770,    777,    65,
4970
    770,    771,    97,     770,    771,    65,     803,    770,    97,
4971
    803,    770,    65,     774,    769,    97,     774,    769,    65,
4972
    774,    768,    97,     774,    768,    65,     774,    777,    97,
4973
    774,    777,    65,     774,    771,    97,     774,    771,    65,
4974
    803,    774,    97,     803,    774,    69,     803,    101,    803,
4975
    69,     777,    101,    777,    69,     771,    101,    771,    69,
4976
    770,    769,    101,    770,    769,    69,     770,    768,    101,
4977
    770,    768,    69,     770,    777,    101,    770,    777,    69,
4978
    770,    771,    101,    770,    771,    69,     803,    770,    101,
4979
    803,    770,    73,     777,    105,    777,    73,     803,    105,
4980
    803,    79,     803,    111,    803,    79,     777,    111,    777,
4981
    79,     770,    769,    111,    770,    769,    79,     770,    768,
4982
    111,    770,    768,    79,     770,    777,    111,    770,    777,
4983
    79,     770,    771,    111,    770,    771,    79,     803,    770,
4984
    111,    803,    770,    79,     795,    769,    111,    795,    769,
4985
    79,     795,    768,    111,    795,    768,    79,     795,    777,
4986
    111,    795,    777,    79,     795,    771,    111,    795,    771,
4987
    79,     795,    803,    111,    795,    803,    85,     803,    117,
4988
    803,    85,     777,    117,    777,    85,     795,    769,    117,
4989
    795,    769,    85,     795,    768,    117,    795,    768,    85,
4990
    795,    777,    117,    795,    777,    85,     795,    771,    117,
4991
    795,    771,    85,     795,    803,    117,    795,    803,    89,
4992
    768,    121,    768,    89,     803,    121,    803,    89,     777,
4993
    121,    777,    89,     771,    121,    771,    945,    787,    945,
4994
    788,    945,    787,    768,    945,    788,    768,    945,    787,
4995
    769,    945,    788,    769,    945,    787,    834,    945,    788,
4996
    834,    913,    787,    913,    788,    913,    787,    768,    913,
4997
    788,    768,    913,    787,    769,    913,    788,    769,    913,
4998
    787,    834,    913,    788,    834,    949,    787,    949,    788,
4999
    949,    787,    768,    949,    788,    768,    949,    787,    769,
5000
    949,    788,    769,    917,    787,    917,    788,    917,    787,
5001
    768,    917,    788,    768,    917,    787,    769,    917,    788,
5002
    769,    951,    787,    951,    788,    951,    787,    768,    951,
5003
    788,    768,    951,    787,    769,    951,    788,    769,    951,
5004
    787,    834,    951,    788,    834,    919,    787,    919,    788,
5005
    919,    787,    768,    919,    788,    768,    919,    787,    769,
5006
    919,    788,    769,    919,    787,    834,    919,    788,    834,
5007
    953,    787,    953,    788,    953,    787,    768,    953,    788,
5008
    768,    953,    787,    769,    953,    788,    769,    953,    787,
5009
    834,    953,    788,    834,    921,    787,    921,    788,    921,
5010
    787,    768,    921,    788,    768,    921,    787,    769,    921,
5011
    788,    769,    921,    787,    834,    921,    788,    834,    959,
5012
    787,    959,    788,    959,    787,    768,    959,    788,    768,
5013
    959,    787,    769,    959,    788,    769,    927,    787,    927,
5014
    788,    927,    787,    768,    927,    788,    768,    927,    787,
5015
    769,    927,    788,    769,    965,    787,    965,    788,    965,
5016
    787,    768,    965,    788,    768,    965,    787,    769,    965,
5017
    788,    769,    965,    787,    834,    965,    788,    834,    933,
5018
    788,    933,    788,    768,    933,    788,    769,    933,    788,
5019
    834,    969,    787,    969,    788,    969,    787,    768,    969,
5020
    788,    768,    969,    787,    769,    969,    788,    769,    969,
5021
    787,    834,    969,    788,    834,    937,    787,    937,    788,
5022
    937,    787,    768,    937,    788,    768,    937,    787,    769,
5023
    937,    788,    769,    937,    787,    834,    937,    788,    834,
5024
    945,    768,    945,    769,    949,    768,    949,    769,    951,
5025
    768,    951,    769,    953,    768,    953,    769,    959,    768,
5026
    959,    769,    965,    768,    965,    769,    969,    768,    969,
5027
    769,    945,    787,    837,    945,    788,    837,    945,    787,
5028
    768,    837,    945,    788,    768,    837,    945,    787,    769,
5029
    837,    945,    788,    769,    837,    945,    787,    834,    837,
5030
    945,    788,    834,    837,    913,    787,    837,    913,    788,
5031
    837,    913,    787,    768,    837,    913,    788,    768,    837,
5032
    913,    787,    769,    837,    913,    788,    769,    837,    913,
5033
    787,    834,    837,    913,    788,    834,    837,    951,    787,
5034
    837,    951,    788,    837,    951,    787,    768,    837,    951,
5035
    788,    768,    837,    951,    787,    769,    837,    951,    788,
5036
    769,    837,    951,    787,    834,    837,    951,    788,    834,
5037
    837,    919,    787,    837,    919,    788,    837,    919,    787,
5038
    768,    837,    919,    788,    768,    837,    919,    787,    769,
5039
    837,    919,    788,    769,    837,    919,    787,    834,    837,
5040
    919,    788,    834,    837,    969,    787,    837,    969,    788,
5041
    837,    969,    787,    768,    837,    969,    788,    768,    837,
5042
    969,    787,    769,    837,    969,    788,    769,    837,    969,
5043
    787,    834,    837,    969,    788,    834,    837,    937,    787,
5044
    837,    937,    788,    837,    937,    787,    768,    837,    937,
5045
    788,    768,    837,    937,    787,    769,    837,    937,    788,
5046
    769,    837,    937,    787,    834,    837,    937,    788,    834,
5047
    837,    945,    774,    945,    772,    945,    768,    837,    945,
5048
    837,    945,    769,    837,    945,    834,    945,    834,    837,
5049
    913,    774,    913,    772,    913,    768,    913,    769,    913,
5050
    837,    32,     787,    953,    32,     787,    32,     834,    168,
5051
    834,    951,    768,    837,    951,    837,    951,    769,    837,
5052
    951,    834,    951,    834,    837,    917,    768,    917,    769,
5053
    919,    768,    919,    769,    919,    837,    8127,   768,    8127,
5054
    769,    8127,   834,    953,    774,    953,    772,    953,    776,
5055
    768,    953,    776,    769,    953,    834,    953,    776,    834,
5056
    921,    774,    921,    772,    921,    768,    921,    769,    8190,
5057
    768,    8190,   769,    8190,   834,    965,    774,    965,    772,
5058
    965,    776,    768,    965,    776,    769,    961,    787,    961,
5059
    788,    965,    834,    965,    776,    834,    933,    774,    933,
5060
    772,    933,    768,    933,    769,    929,    788,    168,    768,
5061
    168,    769,    96,     969,    768,    837,    969,    837,    969,
5062
    769,    837,    969,    834,    969,    834,    837,    927,    768,
5063
    927,    769,    937,    768,    937,    769,    937,    837,    180,
5064
    32,     788,    8194,   8195,   32,     32,     32,     32,     32,
5065
    32,     32,     32,     32,     8208,   32,     819,    46,     46,
5066
    46,     46,     46,     46,     32,     8242,   8242,   8242,   8242,
5067
    8242,   8245,   8245,   8245,   8245,   8245,   33,     33,     32,
5068
    773,    63,     63,     63,     33,     33,     63,     8242,   8242,
5069
    8242,   8242,   32,     48,     105,    52,     53,     54,     55,
5070
    56,     57,     43,     8722,   61,     40,     41,     110,    48,
5071
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5072
    43,     8722,   61,     40,     41,     97,     101,    111,    120,
5073
    601,    104,    107,    108,    109,    110,    112,    115,    116,
5074
    82,     115,    97,     47,     99,     97,     47,     115,    67,
5075
    176,    67,     99,     47,     111,    99,     47,     117,    400,
5076
    176,    70,     103,    72,     72,     72,     104,    295,    73,
5077
    73,     76,     108,    78,     78,     111,    80,     81,     82,
5078
    82,     82,     83,     77,     84,     69,     76,     84,     77,
5079
    90,     937,    90,     75,     65,     778,    66,     67,     101,
5080
    69,     70,     77,     111,    1488,   1489,   1490,   1491,   105,
5081
    70,     65,     88,     960,    947,    915,    928,    8721,   68,
5082
    100,    101,    105,    106,    49,     8260,   55,     49,     8260,
5083
    57,     49,     8260,   49,     48,     49,     8260,   51,     50,
5084
    8260,   51,     49,     8260,   53,     50,     8260,   53,     51,
5085
    8260,   53,     52,     8260,   53,     49,     8260,   54,     53,
5086
    8260,   54,     49,     8260,   56,     51,     8260,   56,     53,
5087
    8260,   56,     55,     8260,   56,     49,     8260,   73,     73,
5088
    73,     73,     73,     73,     73,     86,     86,     86,     73,
5089
    86,     73,     73,     86,     73,     73,     73,     73,     88,
5090
    88,     88,     73,     88,     73,     73,     76,     67,     68,
5091
    77,     105,    105,    105,    105,    105,    105,    105,    118,
5092
    118,    118,    105,    118,    105,    105,    118,    105,    105,
5093
    105,    105,    120,    120,    120,    105,    120,    105,    105,
5094
    108,    99,     100,    109,    48,     8260,   51,     8592,   824,
5095
    8594,   824,    8596,   824,    8656,   824,    8660,   824,    8658,
5096
    824,    8707,   824,    8712,   824,    8715,   824,    8739,   824,
5097
    8741,   824,    8747,   8747,   8747,   8747,   8747,   8750,   8750,
5098
    8750,   8750,   8750,   8764,   824,    8771,   824,    8773,   824,
5099
    8776,   824,    61,     824,    8801,   824,    8781,   824,    60,
5100
    824,    62,     824,    8804,   824,    8805,   824,    8818,   824,
5101
    8819,   824,    8822,   824,    8823,   824,    8826,   824,    8827,
5102
    824,    8834,   824,    8835,   824,    8838,   824,    8839,   824,
5103
    8866,   824,    8872,   824,    8873,   824,    8875,   824,    8828,
5104
    824,    8829,   824,    8849,   824,    8850,   824,    8882,   824,
5105
    8883,   824,    8884,   824,    8885,   824,    12296,  12297,  49,
5106
    50,     51,     52,     53,     54,     55,     56,     57,     49,
5107
    48,     49,     49,     49,     50,     49,     51,     49,     52,
5108
    49,     53,     49,     54,     49,     55,     49,     56,     49,
5109
    57,     50,     48,     40,     49,     41,     40,     50,     41,
5110
    40,     51,     41,     40,     52,     41,     40,     53,     41,
5111
    40,     54,     41,     40,     55,     41,     40,     56,     41,
5112
    40,     57,     41,     40,     49,     48,     41,     40,     49,
5113
    49,     41,     40,     49,     50,     41,     40,     49,     51,
5114
    41,     40,     49,     52,     41,     40,     49,     53,     41,
5115
    40,     49,     54,     41,     40,     49,     55,     41,     40,
5116
    49,     56,     41,     40,     49,     57,     41,     40,     50,
5117
    48,     41,     49,     46,     50,     46,     51,     46,     52,
5118
    46,     53,     46,     54,     46,     55,     46,     56,     46,
5119
    57,     46,     49,     48,     46,     49,     49,     46,     49,
5120
    50,     46,     49,     51,     46,     49,     52,     46,     49,
5121
    53,     46,     49,     54,     46,     49,     55,     46,     49,
5122
    56,     46,     49,     57,     46,     50,     48,     46,     40,
5123
    97,     41,     40,     98,     41,     40,     99,     41,     40,
5124
    100,    41,     40,     101,    41,     40,     102,    41,     40,
5125
    103,    41,     40,     104,    41,     40,     105,    41,     40,
5126
    106,    41,     40,     107,    41,     40,     108,    41,     40,
5127
    109,    41,     40,     110,    41,     40,     111,    41,     40,
5128
    112,    41,     40,     113,    41,     40,     114,    41,     40,
5129
    115,    41,     40,     116,    41,     40,     117,    41,     40,
5130
    118,    41,     40,     119,    41,     40,     120,    41,     40,
5131
    121,    41,     40,     122,    41,     65,     66,     67,     68,
5132
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5133
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5134
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5135
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5136
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5137
    120,    121,    122,    48,     8747,   8747,   8747,   8747,   58,
5138
    58,     61,     61,     61,     61,     61,     61,     10973,  824,
5139
    106,    86,     11617,  27597,  40863,  19968,  20008,  20022,  20031,
5140
    20057,  20101,  20108,  20128,  20154,  20799,  20837,  20843,  20866,
5141
    20886,  20907,  20960,  20981,  20992,  21147,  21241,  21269,  21274,
5142
    21304,  21313,  21340,  21353,  21378,  21430,  21448,  21475,  22231,
5143
    22303,  22763,  22786,  22794,  22805,  22823,  22899,  23376,  23424,
5144
    23544,  23567,  23586,  23608,  23662,  23665,  24027,  24037,  24049,
5145
    24062,  24178,  24186,  24191,  24308,  24318,  24331,  24339,  24400,
5146
    24417,  24435,  24515,  25096,  25142,  25163,  25903,  25908,  25991,
5147
    26007,  26020,  26041,  26080,  26085,  26352,  26376,  26408,  27424,
5148
    27490,  27513,  27571,  27595,  27604,  27611,  27663,  27668,  27700,
5149
    28779,  29226,  29238,  29243,  29247,  29255,  29273,  29275,  29356,
5150
    29572,  29577,  29916,  29926,  29976,  29983,  29992,  30000,  30091,
5151
    30098,  30326,  30333,  30382,  30399,  30446,  30683,  30690,  30707,
5152
    31034,  31160,  31166,  31348,  31435,  31481,  31859,  31992,  32566,
5153
    32593,  32650,  32701,  32769,  32780,  32786,  32819,  32895,  32905,
5154
    33251,  33258,  33267,  33276,  33292,  33307,  33311,  33390,  33394,
5155
    33400,  34381,  34411,  34880,  34892,  34915,  35198,  35211,  35282,
5156
    35328,  35895,  35910,  35925,  35960,  35997,  36196,  36208,  36275,
5157
    36523,  36554,  36763,  36784,  36789,  37009,  37193,  37318,  37324,
5158
    37329,  38263,  38272,  38428,  38582,  38585,  38632,  38737,  38750,
5159
    38754,  38761,  38859,  38893,  38899,  38913,  39080,  39131,  39135,
5160
    39318,  39321,  39340,  39592,  39640,  39647,  39717,  39727,  39730,
5161
    39740,  39770,  40165,  40565,  40575,  40613,  40635,  40643,  40653,
5162
    40657,  40697,  40701,  40718,  40723,  40736,  40763,  40778,  40786,
5163
    40845,  40860,  40864,  32,     12306,  21313,  21316,  21317,  12363,
5164
    12441,  12365,  12441,  12367,  12441,  12369,  12441,  12371,  12441,
5165
    12373,  12441,  12375,  12441,  12377,  12441,  12379,  12441,  12381,
5166
    12441,  12383,  12441,  12385,  12441,  12388,  12441,  12390,  12441,
5167
    12392,  12441,  12399,  12441,  12399,  12442,  12402,  12441,  12402,
5168
    12442,  12405,  12441,  12405,  12442,  12408,  12441,  12408,  12442,
5169
    12411,  12441,  12411,  12442,  12358,  12441,  32,     12441,  32,
5170
    12442,  12445,  12441,  12424,  12426,  12459,  12441,  12461,  12441,
5171
    12463,  12441,  12465,  12441,  12467,  12441,  12469,  12441,  12471,
5172
    12441,  12473,  12441,  12475,  12441,  12477,  12441,  12479,  12441,
5173
    12481,  12441,  12484,  12441,  12486,  12441,  12488,  12441,  12495,
5174
    12441,  12495,  12442,  12498,  12441,  12498,  12442,  12501,  12441,
5175
    12501,  12442,  12504,  12441,  12504,  12442,  12507,  12441,  12507,
5176
    12442,  12454,  12441,  12527,  12441,  12528,  12441,  12529,  12441,
5177
    12530,  12441,  12541,  12441,  12467,  12488,  4352,   4353,   4522,
5178
    4354,   4524,   4525,   4355,   4356,   4357,   4528,   4529,   4530,
5179
    4531,   4532,   4533,   4378,   4358,   4359,   4360,   4385,   4361,
5180
    4362,   4363,   4364,   4365,   4366,   4367,   4368,   4369,   4370,
5181
    4449,   4450,   4451,   4452,   4453,   4454,   4455,   4456,   4457,
5182
    4458,   4459,   4460,   4461,   4462,   4463,   4464,   4465,   4466,
5183
    4467,   4468,   4469,   4448,   4372,   4373,   4551,   4552,   4556,
5184
    4558,   4563,   4567,   4569,   4380,   4573,   4575,   4381,   4382,
5185
    4384,   4386,   4387,   4391,   4393,   4395,   4396,   4397,   4398,
5186
    4399,   4402,   4406,   4416,   4423,   4428,   4593,   4594,   4439,
5187
    4440,   4441,   4484,   4485,   4488,   4497,   4498,   4500,   4510,
5188
    4513,   19968,  20108,  19977,  22235,  19978,  20013,  19979,  30002,
5189
    20057,  19993,  19969,  22825,  22320,  20154,  40,     4352,   41,
5190
    40,     4354,   41,     40,     4355,   41,     40,     4357,   41,
5191
    40,     4358,   41,     40,     4359,   41,     40,     4361,   41,
5192
    40,     4363,   41,     40,     4364,   41,     40,     4366,   41,
5193
    40,     4367,   41,     40,     4368,   41,     40,     4369,   41,
5194
    40,     4370,   41,     40,     4352,   4449,   41,     40,     4354,
5195
    4449,   41,     40,     4355,   4449,   41,     40,     4357,   4449,
5196
    41,     40,     4358,   4449,   41,     40,     4359,   4449,   41,
5197
    40,     4361,   4449,   41,     40,     4363,   4449,   41,     40,
5198
    4364,   4449,   41,     40,     4366,   4449,   41,     40,     4367,
5199
    4449,   41,     40,     4368,   4449,   41,     40,     4369,   4449,
5200
    41,     40,     4370,   4449,   41,     40,     4364,   4462,   41,
5201
    40,     4363,   4457,   4364,   4453,   4523,   41,     40,     4363,
5202
    4457,   4370,   4462,   41,     40,     19968,  41,     40,     20108,
5203
    41,     40,     19977,  41,     40,     22235,  41,     40,     20116,
5204
    41,     40,     20845,  41,     40,     19971,  41,     40,     20843,
5205
    41,     40,     20061,  41,     40,     21313,  41,     40,     26376,
5206
    41,     40,     28779,  41,     40,     27700,  41,     40,     26408,
5207
    41,     40,     37329,  41,     40,     22303,  41,     40,     26085,
5208
    41,     40,     26666,  41,     40,     26377,  41,     40,     31038,
5209
    41,     40,     21517,  41,     40,     29305,  41,     40,     36001,
5210
    41,     40,     31069,  41,     40,     21172,  41,     40,     20195,
5211
    41,     40,     21628,  41,     40,     23398,  41,     40,     30435,
5212
    41,     40,     20225,  41,     40,     36039,  41,     40,     21332,
5213
    41,     40,     31085,  41,     40,     20241,  41,     40,     33258,
5214
    41,     40,     33267,  41,     21839,  24188,  25991,  31631,  80,
5215
    84,     69,     50,     49,     50,     50,     50,     51,     50,
5216
    52,     50,     53,     50,     54,     50,     55,     50,     56,
5217
    50,     57,     51,     48,     51,     49,     51,     50,     51,
5218
    51,     51,     52,     51,     53,     4352,   4354,   4355,   4357,
5219
    4358,   4359,   4361,   4363,   4364,   4366,   4367,   4368,   4369,
5220
    4370,   4352,   4449,   4354,   4449,   4355,   4449,   4357,   4449,
5221
    4358,   4449,   4359,   4449,   4361,   4449,   4363,   4449,   4364,
5222
    4449,   4366,   4449,   4367,   4449,   4368,   4449,   4369,   4449,
5223
    4370,   4449,   4366,   4449,   4535,   4352,   4457,   4364,   4462,
5224
    4363,   4468,   4363,   4462,   19968,  20108,  19977,  22235,  20116,
5225
    20845,  19971,  20843,  20061,  21313,  26376,  28779,  27700,  26408,
5226
    37329,  22303,  26085,  26666,  26377,  31038,  21517,  29305,  36001,
5227
    31069,  21172,  31192,  30007,  22899,  36969,  20778,  21360,  27880,
5228
    38917,  20241,  20889,  27491,  19978,  20013,  19979,  24038,  21491,
5229
    21307,  23447,  23398,  30435,  20225,  36039,  21332,  22812,  51,
5230
    54,     51,     55,     51,     56,     51,     57,     52,     48,
5231
    52,     49,     52,     50,     52,     51,     52,     52,     52,
5232
    53,     52,     54,     52,     55,     52,     56,     52,     57,
5233
    53,     48,     49,     26376,  50,     26376,  51,     26376,  52,
5234
    26376,  53,     26376,  54,     26376,  55,     26376,  56,     26376,
5235
    57,     26376,  49,     48,     26376,  49,     49,     26376,  49,
5236
    50,     26376,  72,     103,    101,    114,    103,    101,    86,
5237
    76,     84,     68,     12450,  12452,  12454,  12456,  12458,  12459,
5238
    12461,  12463,  12465,  12467,  12469,  12471,  12473,  12475,  12477,
5239
    12479,  12481,  12484,  12486,  12488,  12490,  12491,  12492,  12493,
5240
    12494,  12495,  12498,  12501,  12504,  12507,  12510,  12511,  12512,
5241
    12513,  12514,  12516,  12518,  12520,  12521,  12522,  12523,  12524,
5242
    12525,  12527,  12528,  12529,  12530,  20196,  21644,  12450,  12495,
5243
    12442,  12540,  12488,  12450,  12523,  12501,  12449,  12450,  12531,
5244
    12504,  12442,  12450,  12450,  12540,  12523,  12452,  12491,  12531,
5245
    12463,  12441,  12452,  12531,  12481,  12454,  12457,  12531,  12456,
5246
    12473,  12463,  12540,  12488,  12441,  12456,  12540,  12459,  12540,
5247
    12458,  12531,  12473,  12458,  12540,  12512,  12459,  12452,  12522,
5248
    12459,  12521,  12483,  12488,  12459,  12525,  12522,  12540,  12459,
5249
    12441,  12525,  12531,  12459,  12441,  12531,  12510,  12461,  12441,
5250
    12459,  12441,  12461,  12441,  12491,  12540,  12461,  12517,  12522,
5251
    12540,  12461,  12441,  12523,  12479,  12441,  12540,  12461,  12525,
5252
    12461,  12525,  12463,  12441,  12521,  12512,  12461,  12525,  12513,
5253
    12540,  12488,  12523,  12461,  12525,  12527,  12483,  12488,  12463,
5254
    12441,  12521,  12512,  12463,  12441,  12521,  12512,  12488,  12531,
5255
    12463,  12523,  12475,  12441,  12452,  12525,  12463,  12525,  12540,
5256
    12493,  12465,  12540,  12473,  12467,  12523,  12490,  12467,  12540,
5257
    12507,  12442,  12469,  12452,  12463,  12523,  12469,  12531,  12481,
5258
    12540,  12512,  12471,  12522,  12531,  12463,  12441,  12475,  12531,
5259
    12481,  12475,  12531,  12488,  12479,  12441,  12540,  12473,  12486,
5260
    12441,  12471,  12488,  12441,  12523,  12488,  12531,  12490,  12494,
5261
    12494,  12483,  12488,  12495,  12452,  12484,  12495,  12442,  12540,
5262
    12475,  12531,  12488,  12495,  12442,  12540,  12484,  12495,  12441,
5263
    12540,  12524,  12523,  12498,  12442,  12450,  12473,  12488,  12523,
5264
    12498,  12442,  12463,  12523,  12498,  12442,  12467,  12498,  12441,
5265
    12523,  12501,  12449,  12521,  12483,  12488,  12441,  12501,  12451,
5266
    12540,  12488,  12501,  12441,  12483,  12471,  12455,  12523,  12501,
5267
    12521,  12531,  12504,  12463,  12479,  12540,  12523,  12504,  12442,
5268
    12477,  12504,  12442,  12491,  12498,  12504,  12523,  12484,  12504,
5269
    12442,  12531,  12473,  12504,  12442,  12540,  12471,  12441,  12504,
5270
    12441,  12540,  12479,  12507,  12442,  12452,  12531,  12488,  12507,
5271
    12441,  12523,  12488,  12507,  12531,  12507,  12442,  12531,  12488,
5272
    12441,  12507,  12540,  12523,  12507,  12540,  12531,  12510,  12452,
5273
    12463,  12525,  12510,  12452,  12523,  12510,  12483,  12495,  12510,
5274
    12523,  12463,  12510,  12531,  12471,  12519,  12531,  12511,  12463,
5275
    12525,  12531,  12511,  12522,  12511,  12522,  12495,  12441,  12540,
5276
    12523,  12513,  12459,  12441,  12513,  12459,  12441,  12488,  12531,
5277
    12513,  12540,  12488,  12523,  12516,  12540,  12488,  12441,  12516,
5278
    12540,  12523,  12518,  12450,  12531,  12522,  12483,  12488,  12523,
5279
    12522,  12521,  12523,  12498,  12442,  12540,  12523,  12540,  12501,
5280
    12441,  12523,  12524,  12512,  12524,  12531,  12488,  12465,  12441,
5281
    12531,  12527,  12483,  12488,  48,     28857,  49,     28857,  50,
5282
    28857,  51,     28857,  52,     28857,  53,     28857,  54,     28857,
5283
    55,     28857,  56,     28857,  57,     28857,  49,     48,     28857,
5284
    49,     49,     28857,  49,     50,     28857,  49,     51,     28857,
5285
    49,     52,     28857,  49,     53,     28857,  49,     54,     28857,
5286
    49,     55,     28857,  49,     56,     28857,  49,     57,     28857,
5287
    50,     48,     28857,  50,     49,     28857,  50,     50,     28857,
5288
    50,     51,     28857,  50,     52,     28857,  104,    80,     97,
5289
    100,    97,     65,     85,     98,     97,     114,    111,    86,
5290
    112,    99,     100,    109,    100,    109,    50,     100,    109,
5291
    51,     73,     85,     24179,  25104,  26157,  21644,  22823,  27491,
5292
    26126,  27835,  26666,  24335,  20250,  31038,  112,    65,     110,
5293
    65,     956,    65,     109,    65,     107,    65,     75,     66,
5294
    77,     66,     71,     66,     99,     97,     108,    107,    99,
5295
    97,     108,    112,    70,     110,    70,     956,    70,     956,
5296
    103,    109,    103,    107,    103,    72,     122,    107,    72,
5297
    122,    77,     72,     122,    71,     72,     122,    84,     72,
5298
    122,    956,    108,    109,    108,    100,    108,    107,    108,
5299
    102,    109,    110,    109,    956,    109,    109,    109,    99,
5300
    109,    107,    109,    109,    109,    50,     99,     109,    50,
5301
    109,    50,     107,    109,    50,     109,    109,    51,     99,
5302
    109,    51,     109,    51,     107,    109,    51,     109,    8725,
5303
    115,    109,    8725,   115,    50,     80,     97,     107,    80,
5304
    97,     77,     80,     97,     71,     80,     97,     114,    97,
5305
    100,    114,    97,     100,    8725,   115,    114,    97,     100,
5306
    8725,   115,    50,     112,    115,    110,    115,    956,    115,
5307
    109,    115,    112,    86,     110,    86,     956,    86,     109,
5308
    86,     107,    86,     77,     86,     112,    87,     110,    87,
5309
    956,    87,     109,    87,     107,    87,     77,     87,     107,
5310
    937,    77,     937,    97,     46,     109,    46,     66,     113,
5311
    99,     99,     99,     100,    67,     8725,   107,    103,    67,
5312
    111,    46,     100,    66,     71,     121,    104,    97,     72,
5313
    80,     105,    110,    75,     75,     75,     77,     107,    116,
5314
    108,    109,    108,    110,    108,    111,    103,    108,    120,
5315
    109,    98,     109,    105,    108,    109,    111,    108,    80,
5316
    72,     112,    46,     109,    46,     80,     80,     77,     80,
5317
    82,     115,    114,    83,     118,    87,     98,     86,     8725,
5318
    109,    65,     8725,   109,    49,     26085,  50,     26085,  51,
5319
    26085,  52,     26085,  53,     26085,  54,     26085,  55,     26085,
5320
    56,     26085,  57,     26085,  49,     48,     26085,  49,     49,
5321
    26085,  49,     50,     26085,  49,     51,     26085,  49,     52,
5322
    26085,  49,     53,     26085,  49,     54,     26085,  49,     55,
5323
    26085,  49,     56,     26085,  49,     57,     26085,  50,     48,
5324
    26085,  50,     49,     26085,  50,     50,     26085,  50,     51,
5325
    26085,  50,     52,     26085,  50,     53,     26085,  50,     54,
5326
    26085,  50,     55,     26085,  50,     56,     26085,  50,     57,
5327
    26085,  51,     48,     26085,  51,     49,     26085,  103,    97,
5328
    108,    1098,   1100,   42863,  67,     70,     81,     294,    339,
5329
    42791,  43831,  619,    43858,  653,    35912,  26356,  36554,  36040,
5330
    28369,  20018,  21477,  40860,  40860,  22865,  37329,  21895,  22856,
5331
    25078,  30313,  32645,  34367,  34746,  35064,  37007,  27138,  27931,
5332
    28889,  29662,  33853,  37226,  39409,  20098,  21365,  27396,  29211,
5333
    34349,  40478,  23888,  28651,  34253,  35172,  25289,  33240,  34847,
5334
    24266,  26391,  28010,  29436,  37070,  20358,  20919,  21214,  25796,
5335
    27347,  29200,  30439,  32769,  34310,  34396,  36335,  38706,  39791,
5336
    40442,  30860,  31103,  32160,  33737,  37636,  40575,  35542,  22751,
5337
    24324,  31840,  32894,  29282,  30922,  36034,  38647,  22744,  23650,
5338
    27155,  28122,  28431,  32047,  32311,  38475,  21202,  32907,  20956,
5339
    20940,  31260,  32190,  33777,  38517,  35712,  25295,  27138,  35582,
5340
    20025,  23527,  24594,  29575,  30064,  21271,  30971,  20415,  24489,
5341
    19981,  27852,  25976,  32034,  21443,  22622,  30465,  33865,  35498,
5342
    27578,  36784,  27784,  25342,  33509,  25504,  30053,  20142,  20841,
5343
    20937,  26753,  31975,  33391,  35538,  37327,  21237,  21570,  22899,
5344
    24300,  26053,  28670,  31018,  38317,  39530,  40599,  40654,  21147,
5345
    26310,  27511,  36706,  24180,  24976,  25088,  25754,  28451,  29001,
5346
    29833,  31178,  32244,  32879,  36646,  34030,  36899,  37706,  21015,
5347
    21155,  21693,  28872,  35010,  35498,  24265,  24565,  25467,  27566,
5348
    31806,  29557,  20196,  22265,  23527,  23994,  24604,  29618,  29801,
5349
    32666,  32838,  37428,  38646,  38728,  38936,  20363,  31150,  37300,
5350
    38584,  24801,  20102,  20698,  23534,  23615,  26009,  27138,  29134,
5351
    30274,  34044,  36988,  40845,  26248,  38446,  21129,  26491,  26611,
5352
    27969,  28316,  29705,  30041,  30827,  32016,  39006,  20845,  25134,
5353
    38520,  20523,  23833,  28138,  36650,  24459,  24900,  26647,  29575,
5354
    38534,  21033,  21519,  23653,  26131,  26446,  26792,  27877,  29702,
5355
    30178,  32633,  35023,  35041,  37324,  38626,  21311,  28346,  21533,
5356
    29136,  29848,  34298,  38563,  40023,  40607,  26519,  28107,  33256,
5357
    31435,  31520,  31890,  29376,  28825,  35672,  20160,  33590,  21050,
5358
    20999,  24230,  25299,  31958,  23429,  27934,  26292,  36667,  34892,
5359
    38477,  35211,  24275,  20800,  21952,  22618,  26228,  20958,  29482,
5360
    30410,  31036,  31070,  31077,  31119,  38742,  31934,  32701,  34322,
5361
    35576,  36920,  37117,  39151,  39164,  39208,  40372,  37086,  38583,
5362
    20398,  20711,  20813,  21193,  21220,  21329,  21917,  22022,  22120,
5363
    22592,  22696,  23652,  23662,  24724,  24936,  24974,  25074,  25935,
5364
    26082,  26257,  26757,  28023,  28186,  28450,  29038,  29227,  29730,
5365
    30865,  31038,  31049,  31048,  31056,  31062,  31069,  31117,  31118,
5366
    31296,  31361,  31680,  32244,  32265,  32321,  32626,  32773,  33261,
5367
    33401,  33401,  33879,  35088,  35222,  35585,  35641,  36051,  36104,
5368
    36790,  36920,  38627,  38911,  38971,  24693,  148206, 33304,  20006,
5369
    20917,  20840,  20352,  20805,  20864,  21191,  21242,  21917,  21845,
5370
    21913,  21986,  22618,  22707,  22852,  22868,  23138,  23336,  24274,
5371
    24281,  24425,  24493,  24792,  24910,  24840,  24974,  24928,  25074,
5372
    25140,  25540,  25628,  25682,  25942,  26228,  26391,  26395,  26454,
5373
    27513,  27578,  27969,  28379,  28363,  28450,  28702,  29038,  30631,
5374
    29237,  29359,  29482,  29809,  29958,  30011,  30237,  30239,  30410,
5375
    30427,  30452,  30538,  30528,  30924,  31409,  31680,  31867,  32091,
5376
    32244,  32574,  32773,  33618,  33775,  34681,  35137,  35206,  35222,
5377
    35519,  35576,  35531,  35585,  35582,  35565,  35641,  35722,  36104,
5378
    36664,  36978,  37273,  37494,  38524,  38627,  38742,  38875,  38911,
5379
    38923,  38971,  39698,  40860,  141386, 141380, 144341, 15261,  16408,
5380
    16441,  152137, 154832, 163539, 40771,  40846,  102,    102,    102,
5381
    105,    102,    108,    102,    102,    105,    102,    102,    108,
5382
    115,    116,    115,    116,    1396,   1398,   1396,   1381,   1396,
5383
    1387,   1406,   1398,   1396,   1389,   1497,   1460,   1522,   1463,
5384
    1506,   1488,   1491,   1492,   1499,   1500,   1501,   1512,   1514,
5385
    43,     1513,   1473,   1513,   1474,   1513,   1468,   1473,   1513,
5386
    1468,   1474,   1488,   1463,   1488,   1464,   1488,   1468,   1489,
5387
    1468,   1490,   1468,   1491,   1468,   1492,   1468,   1493,   1468,
5388
    1494,   1468,   1496,   1468,   1497,   1468,   1498,   1468,   1499,
5389
    1468,   1500,   1468,   1502,   1468,   1504,   1468,   1505,   1468,
5390
    1507,   1468,   1508,   1468,   1510,   1468,   1511,   1468,   1512,
5391
    1468,   1513,   1468,   1514,   1468,   1493,   1465,   1489,   1471,
5392
    1499,   1471,   1508,   1471,   1488,   1500,   1649,   1649,   1659,
5393
    1659,   1659,   1659,   1662,   1662,   1662,   1662,   1664,   1664,
5394
    1664,   1664,   1658,   1658,   1658,   1658,   1663,   1663,   1663,
5395
    1663,   1657,   1657,   1657,   1657,   1700,   1700,   1700,   1700,
5396
    1702,   1702,   1702,   1702,   1668,   1668,   1668,   1668,   1667,
5397
    1667,   1667,   1667,   1670,   1670,   1670,   1670,   1671,   1671,
5398
    1671,   1671,   1677,   1677,   1676,   1676,   1678,   1678,   1672,
5399
    1672,   1688,   1688,   1681,   1681,   1705,   1705,   1705,   1705,
5400
    1711,   1711,   1711,   1711,   1715,   1715,   1715,   1715,   1713,
5401
    1713,   1713,   1713,   1722,   1722,   1723,   1723,   1723,   1723,
5402
    1749,   1620,   1749,   1620,   1729,   1729,   1729,   1729,   1726,
5403
    1726,   1726,   1726,   1746,   1746,   1746,   1620,   1746,   1620,
5404
    1709,   1709,   1709,   1709,   1735,   1735,   1734,   1734,   1736,
5405
    1736,   1735,   1652,   1739,   1739,   1733,   1733,   1737,   1737,
5406
    1744,   1744,   1744,   1744,   1609,   1609,   1610,   1620,   1575,
5407
    1610,   1620,   1575,   1610,   1620,   1749,   1610,   1620,   1749,
5408
    1610,   1620,   1608,   1610,   1620,   1608,   1610,   1620,   1735,
5409
    1610,   1620,   1735,   1610,   1620,   1734,   1610,   1620,   1734,
5410
    1610,   1620,   1736,   1610,   1620,   1736,   1610,   1620,   1744,
5411
    1610,   1620,   1744,   1610,   1620,   1744,   1610,   1620,   1609,
5412
    1610,   1620,   1609,   1610,   1620,   1609,   1740,   1740,   1740,
5413
    1740,   1610,   1620,   1580,   1610,   1620,   1581,   1610,   1620,
5414
    1605,   1610,   1620,   1609,   1610,   1620,   1610,   1576,   1580,
5415
    1576,   1581,   1576,   1582,   1576,   1605,   1576,   1609,   1576,
5416
    1610,   1578,   1580,   1578,   1581,   1578,   1582,   1578,   1605,
5417
    1578,   1609,   1578,   1610,   1579,   1580,   1579,   1605,   1579,
5418
    1609,   1579,   1610,   1580,   1581,   1580,   1605,   1581,   1580,
5419
    1581,   1605,   1582,   1580,   1582,   1581,   1582,   1605,   1587,
5420
    1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,   1581,
5421
    1589,   1605,   1590,   1580,   1590,   1581,   1590,   1582,   1590,
5422
    1605,   1591,   1581,   1591,   1605,   1592,   1605,   1593,   1580,
5423
    1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,   1601,
5424
    1581,   1601,   1582,   1601,   1605,   1601,   1609,   1601,   1610,
5425
    1602,   1581,   1602,   1605,   1602,   1609,   1602,   1610,   1603,
5426
    1575,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5427
    1603,   1605,   1603,   1609,   1603,   1610,   1604,   1580,   1604,
5428
    1581,   1604,   1582,   1604,   1605,   1604,   1609,   1604,   1610,
5429
    1605,   1580,   1605,   1581,   1605,   1582,   1605,   1605,   1605,
5430
    1609,   1605,   1610,   1606,   1580,   1606,   1581,   1606,   1582,
5431
    1606,   1605,   1606,   1609,   1606,   1610,   1607,   1580,   1607,
5432
    1605,   1607,   1609,   1607,   1610,   1610,   1580,   1610,   1581,
5433
    1610,   1582,   1610,   1605,   1610,   1609,   1610,   1610,   1584,
5434
    1648,   1585,   1648,   1609,   1648,   32,     1612,   1617,   32,
5435
    1613,   1617,   32,     1614,   1617,   32,     1615,   1617,   32,
5436
    1616,   1617,   32,     1617,   1648,   1610,   1620,   1585,   1610,
5437
    1620,   1586,   1610,   1620,   1605,   1610,   1620,   1606,   1610,
5438
    1620,   1609,   1610,   1620,   1610,   1576,   1585,   1576,   1586,
5439
    1576,   1605,   1576,   1606,   1576,   1609,   1576,   1610,   1578,
5440
    1585,   1578,   1586,   1578,   1605,   1578,   1606,   1578,   1609,
5441
    1578,   1610,   1579,   1585,   1579,   1586,   1579,   1605,   1579,
5442
    1606,   1579,   1609,   1579,   1610,   1601,   1609,   1601,   1610,
5443
    1602,   1609,   1602,   1610,   1603,   1575,   1603,   1604,   1603,
5444
    1605,   1603,   1609,   1603,   1610,   1604,   1605,   1604,   1609,
5445
    1604,   1610,   1605,   1575,   1605,   1605,   1606,   1585,   1606,
5446
    1586,   1606,   1605,   1606,   1606,   1606,   1609,   1606,   1610,
5447
    1609,   1648,   1610,   1585,   1610,   1586,   1610,   1605,   1610,
5448
    1606,   1610,   1609,   1610,   1610,   1610,   1620,   1580,   1610,
5449
    1620,   1581,   1610,   1620,   1582,   1610,   1620,   1605,   1610,
5450
    1620,   1607,   1576,   1580,   1576,   1581,   1576,   1582,   1576,
5451
    1605,   1576,   1607,   1578,   1580,   1578,   1581,   1578,   1582,
5452
    1578,   1605,   1578,   1607,   1579,   1605,   1580,   1581,   1580,
5453
    1605,   1581,   1580,   1581,   1605,   1582,   1580,   1582,   1605,
5454
    1587,   1580,   1587,   1581,   1587,   1582,   1587,   1605,   1589,
5455
    1581,   1589,   1582,   1589,   1605,   1590,   1580,   1590,   1581,
5456
    1590,   1582,   1590,   1605,   1591,   1581,   1592,   1605,   1593,
5457
    1580,   1593,   1605,   1594,   1580,   1594,   1605,   1601,   1580,
5458
    1601,   1581,   1601,   1582,   1601,   1605,   1602,   1581,   1602,
5459
    1605,   1603,   1580,   1603,   1581,   1603,   1582,   1603,   1604,
5460
    1603,   1605,   1604,   1580,   1604,   1581,   1604,   1582,   1604,
5461
    1605,   1604,   1607,   1605,   1580,   1605,   1581,   1605,   1582,
5462
    1605,   1605,   1606,   1580,   1606,   1581,   1606,   1582,   1606,
5463
    1605,   1606,   1607,   1607,   1580,   1607,   1605,   1607,   1648,
5464
    1610,   1580,   1610,   1581,   1610,   1582,   1610,   1605,   1610,
5465
    1607,   1610,   1620,   1605,   1610,   1620,   1607,   1576,   1605,
5466
    1576,   1607,   1578,   1605,   1578,   1607,   1579,   1605,   1579,
5467
    1607,   1587,   1605,   1587,   1607,   1588,   1605,   1588,   1607,
5468
    1603,   1604,   1603,   1605,   1604,   1605,   1606,   1605,   1606,
5469
    1607,   1610,   1605,   1610,   1607,   1600,   1614,   1617,   1600,
5470
    1615,   1617,   1600,   1616,   1617,   1591,   1609,   1591,   1610,
5471
    1593,   1609,   1593,   1610,   1594,   1609,   1594,   1610,   1587,
5472
    1609,   1587,   1610,   1588,   1609,   1588,   1610,   1581,   1609,
5473
    1581,   1610,   1580,   1609,   1580,   1610,   1582,   1609,   1582,
5474
    1610,   1589,   1609,   1589,   1610,   1590,   1609,   1590,   1610,
5475
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1588,
5476
    1585,   1587,   1585,   1589,   1585,   1590,   1585,   1591,   1609,
5477
    1591,   1610,   1593,   1609,   1593,   1610,   1594,   1609,   1594,
5478
    1610,   1587,   1609,   1587,   1610,   1588,   1609,   1588,   1610,
5479
    1581,   1609,   1581,   1610,   1580,   1609,   1580,   1610,   1582,
5480
    1609,   1582,   1610,   1589,   1609,   1589,   1610,   1590,   1609,
5481
    1590,   1610,   1588,   1580,   1588,   1581,   1588,   1582,   1588,
5482
    1605,   1588,   1585,   1587,   1585,   1589,   1585,   1590,   1585,
5483
    1588,   1580,   1588,   1581,   1588,   1582,   1588,   1605,   1587,
5484
    1607,   1588,   1607,   1591,   1605,   1587,   1580,   1587,   1581,
5485
    1587,   1582,   1588,   1580,   1588,   1581,   1588,   1582,   1591,
5486
    1605,   1592,   1605,   1575,   1611,   1575,   1611,   1578,   1580,
5487
    1605,   1578,   1581,   1580,   1578,   1581,   1580,   1578,   1581,
5488
    1605,   1578,   1582,   1605,   1578,   1605,   1580,   1578,   1605,
5489
    1581,   1578,   1605,   1582,   1580,   1605,   1581,   1580,   1605,
5490
    1581,   1581,   1605,   1610,   1581,   1605,   1609,   1587,   1581,
5491
    1580,   1587,   1580,   1581,   1587,   1580,   1609,   1587,   1605,
5492
    1581,   1587,   1605,   1581,   1587,   1605,   1580,   1587,   1605,
5493
    1605,   1587,   1605,   1605,   1589,   1581,   1581,   1589,   1581,
5494
    1581,   1589,   1605,   1605,   1588,   1581,   1605,   1588,   1581,
5495
    1605,   1588,   1580,   1610,   1588,   1605,   1582,   1588,   1605,
5496
    1582,   1588,   1605,   1605,   1588,   1605,   1605,   1590,   1581,
5497
    1609,   1590,   1582,   1605,   1590,   1582,   1605,   1591,   1605,
5498
    1581,   1591,   1605,   1581,   1591,   1605,   1605,   1591,   1605,
5499
    1610,   1593,   1580,   1605,   1593,   1605,   1605,   1593,   1605,
5500
    1605,   1593,   1605,   1609,   1594,   1605,   1605,   1594,   1605,
5501
    1610,   1594,   1605,   1609,   1601,   1582,   1605,   1601,   1582,
5502
    1605,   1602,   1605,   1581,   1602,   1605,   1605,   1604,   1581,
5503
    1605,   1604,   1581,   1610,   1604,   1581,   1609,   1604,   1580,
5504
    1580,   1604,   1580,   1580,   1604,   1582,   1605,   1604,   1582,
5505
    1605,   1604,   1605,   1581,   1604,   1605,   1581,   1605,   1581,
5506
    1580,   1605,   1581,   1605,   1605,   1581,   1610,   1605,   1580,
5507
    1581,   1605,   1580,   1605,   1605,   1582,   1580,   1605,   1582,
5508
    1605,   1605,   1580,   1582,   1607,   1605,   1580,   1607,   1605,
5509
    1605,   1606,   1581,   1605,   1606,   1581,   1609,   1606,   1580,
5510
    1605,   1606,   1580,   1605,   1606,   1580,   1609,   1606,   1605,
5511
    1610,   1606,   1605,   1609,   1610,   1605,   1605,   1610,   1605,
5512
    1605,   1576,   1582,   1610,   1578,   1580,   1610,   1578,   1580,
5513
    1609,   1578,   1582,   1610,   1578,   1582,   1609,   1578,   1605,
5514
    1610,   1578,   1605,   1609,   1580,   1605,   1610,   1580,   1581,
5515
    1609,   1580,   1605,   1609,   1587,   1582,   1609,   1589,   1581,
5516
    1610,   1588,   1581,   1610,   1590,   1581,   1610,   1604,   1580,
5517
    1610,   1604,   1605,   1610,   1610,   1581,   1610,   1610,   1580,
5518
    1610,   1610,   1605,   1610,   1605,   1605,   1610,   1602,   1605,
5519
    1610,   1606,   1581,   1610,   1602,   1605,   1581,   1604,   1581,
5520
    1605,   1593,   1605,   1610,   1603,   1605,   1610,   1606,   1580,
5521
    1581,   1605,   1582,   1610,   1604,   1580,   1605,   1603,   1605,
5522
    1605,   1604,   1580,   1605,   1606,   1580,   1581,   1580,   1581,
5523
    1610,   1581,   1580,   1610,   1605,   1580,   1610,   1601,   1605,
5524
    1610,   1576,   1581,   1610,   1603,   1605,   1605,   1593,   1580,
5525
    1605,   1589,   1605,   1605,   1587,   1582,   1610,   1606,   1580,
5526
    1610,   1589,   1604,   1746,   1602,   1604,   1746,   1575,   1604,
5527
    1604,   1607,   1575,   1603,   1576,   1585,   1605,   1581,   1605,
5528
    1583,   1589,   1604,   1593,   1605,   1585,   1587,   1608,   1604,
5529
    1593,   1604,   1610,   1607,   1608,   1587,   1604,   1605,   1589,
5530
    1604,   1609,   1589,   1604,   1609,   32,     1575,   1604,   1604,
5531
    1607,   32,     1593,   1604,   1610,   1607,   32,     1608,   1587,
5532
    1604,   1605,   1580,   1604,   32,     1580,   1604,   1575,   1604,
5533
    1607,   1585,   1740,   1575,   1604,   44,     12289,  12290,  58,
5534
    59,     33,     63,     12310,  12311,  46,     46,     46,     46,
5535
    46,     8212,   8211,   95,     95,     40,     41,     123,    125,
5536
    12308,  12309,  12304,  12305,  12298,  12299,  12296,  12297,  12300,
5537
    12301,  12302,  12303,  91,     93,     32,     773,    32,     773,
5538
    32,     773,    32,     773,    95,     95,     95,     44,     12289,
5539
    46,     59,     58,     63,     33,     8212,   40,     41,     123,
5540
    125,    12308,  12309,  35,     38,     42,     43,     45,     60,
5541
    62,     61,     92,     36,     37,     64,     32,     1611,   1600,
5542
    1611,   32,     1612,   32,     1613,   32,     1614,   1600,   1614,
5543
    32,     1615,   1600,   1615,   32,     1616,   1600,   1616,   32,
5544
    1617,   1600,   1617,   32,     1618,   1600,   1618,   1569,   1575,
5545
    1619,   1575,   1619,   1575,   1620,   1575,   1620,   1608,   1620,
5546
    1608,   1620,   1575,   1621,   1575,   1621,   1610,   1620,   1610,
5547
    1620,   1610,   1620,   1610,   1620,   1575,   1575,   1576,   1576,
5548
    1576,   1576,   1577,   1577,   1578,   1578,   1578,   1578,   1579,
5549
    1579,   1579,   1579,   1580,   1580,   1580,   1580,   1581,   1581,
5550
    1581,   1581,   1582,   1582,   1582,   1582,   1583,   1583,   1584,
5551
    1584,   1585,   1585,   1586,   1586,   1587,   1587,   1587,   1587,
5552
    1588,   1588,   1588,   1588,   1589,   1589,   1589,   1589,   1590,
5553
    1590,   1590,   1590,   1591,   1591,   1591,   1591,   1592,   1592,
5554
    1592,   1592,   1593,   1593,   1593,   1593,   1594,   1594,   1594,
5555
    1594,   1601,   1601,   1601,   1601,   1602,   1602,   1602,   1602,
5556
    1603,   1603,   1603,   1603,   1604,   1604,   1604,   1604,   1605,
5557
    1605,   1605,   1605,   1606,   1606,   1606,   1606,   1607,   1607,
5558
    1607,   1607,   1608,   1608,   1609,   1609,   1610,   1610,   1610,
5559
    1610,   1604,   1575,   1619,   1604,   1575,   1619,   1604,   1575,
5560
    1620,   1604,   1575,   1620,   1604,   1575,   1621,   1604,   1575,
5561
    1621,   1604,   1575,   1604,   1575,   33,     34,     35,     36,
5562
    37,     38,     39,     40,     41,     42,     43,     44,     45,
5563
    46,     47,     48,     49,     50,     51,     52,     53,     54,
5564
    55,     56,     57,     58,     59,     60,     61,     62,     63,
5565
    64,     65,     66,     67,     68,     69,     70,     71,     72,
5566
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5567
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5568
    91,     92,     93,     94,     95,     96,     97,     98,     99,
5569
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5570
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5571
    118,    119,    120,    121,    122,    123,    124,    125,    126,
5572
    10629,  10630,  12290,  12300,  12301,  12289,  12539,  12530,  12449,
5573
    12451,  12453,  12455,  12457,  12515,  12517,  12519,  12483,  12540,
5574
    12450,  12452,  12454,  12456,  12458,  12459,  12461,  12463,  12465,
5575
    12467,  12469,  12471,  12473,  12475,  12477,  12479,  12481,  12484,
5576
    12486,  12488,  12490,  12491,  12492,  12493,  12494,  12495,  12498,
5577
    12501,  12504,  12507,  12510,  12511,  12512,  12513,  12514,  12516,
5578
    12518,  12520,  12521,  12522,  12523,  12524,  12525,  12527,  12531,
5579
    12441,  12442,  4448,   4352,   4353,   4522,   4354,   4524,   4525,
5580
    4355,   4356,   4357,   4528,   4529,   4530,   4531,   4532,   4533,
5581
    4378,   4358,   4359,   4360,   4385,   4361,   4362,   4363,   4364,
5582
    4365,   4366,   4367,   4368,   4369,   4370,   4449,   4450,   4451,
5583
    4452,   4453,   4454,   4455,   4456,   4457,   4458,   4459,   4460,
5584
    4461,   4462,   4463,   4464,   4465,   4466,   4467,   4468,   4469,
5585
    162,    163,    172,    32,     772,    166,    165,    8361,   9474,
5586
    8592,   8593,   8594,   8595,   9632,   9675,   720,    721,    230,
5587
    665,    595,    675,    43878,  677,    676,    598,    599,    7569,
5588
    600,    606,    681,    612,    610,    608,    667,    295,    668,
5589
    615,    644,    682,    683,    620,    122628, 42894,  622,    122629,
5590
    654,    122630, 248,    630,    631,    113,    634,    122632, 637,
5591
    638,    640,    680,    678,    43879,  679,    648,    11377,  655,
5592
    673,    674,    664,    448,    449,    450,    122634, 122654, 69785,
5593
    69818,  69787,  69818,  69797,  69818,  69937,  69927,  69938,  69927,
5594
    70471,  70462,  70471,  70487,  70841,  70842,  70841,  70832,  70841,
5595
    70845,  71096,  71087,  71097,  71087,  71989,  71984,  119127, 119141,
5596
    119128, 119141, 119128, 119141, 119150, 119128, 119141, 119151, 119128,
5597
    119141, 119152, 119128, 119141, 119153, 119128, 119141, 119154, 119225,
5598
    119141, 119226, 119141, 119225, 119141, 119150, 119226, 119141, 119150,
5599
    119225, 119141, 119151, 119226, 119141, 119151, 65,     66,     67,
5600
    68,     69,     70,     71,     72,     73,     74,     75,     76,
5601
    77,     78,     79,     80,     81,     82,     83,     84,     85,
5602
    86,     87,     88,     89,     90,     97,     98,     99,     100,
5603
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5604
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5605
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5606
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5607
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5608
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5609
    103,    105,    106,    107,    108,    109,    110,    111,    112,
5610
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5611
    122,    65,     66,     67,     68,     69,     70,     71,     72,
5612
    73,     74,     75,     76,     77,     78,     79,     80,     81,
5613
    82,     83,     84,     85,     86,     87,     88,     89,     90,
5614
    97,     98,     99,     100,    101,    102,    103,    104,    105,
5615
    106,    107,    108,    109,    110,    111,    112,    113,    114,
5616
    115,    116,    117,    118,    119,    120,    121,    122,    65,
5617
    67,     68,     71,     74,     75,     78,     79,     80,     81,
5618
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5619
    98,     99,     100,    102,    104,    105,    106,    107,    108,
5620
    109,    110,    112,    113,    114,    115,    116,    117,    118,
5621
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5622
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5623
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5624
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5625
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5626
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5627
    121,    122,    65,     66,     68,     69,     70,     71,     74,
5628
    75,     76,     77,     78,     79,     80,     81,     83,     84,
5629
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5630
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5631
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5632
    119,    120,    121,    122,    65,     66,     68,     69,     70,
5633
    71,     73,     74,     75,     76,     77,     79,     83,     84,
5634
    85,     86,     87,     88,     89,     97,     98,     99,     100,
5635
    101,    102,    103,    104,    105,    106,    107,    108,    109,
5636
    110,    111,    112,    113,    114,    115,    116,    117,    118,
5637
    119,    120,    121,    122,    65,     66,     67,     68,     69,
5638
    70,     71,     72,     73,     74,     75,     76,     77,     78,
5639
    79,     80,     81,     82,     83,     84,     85,     86,     87,
5640
    88,     89,     90,     97,     98,     99,     100,    101,    102,
5641
    103,    104,    105,    106,    107,    108,    109,    110,    111,
5642
    112,    113,    114,    115,    116,    117,    118,    119,    120,
5643
    121,    122,    65,     66,     67,     68,     69,     70,     71,
5644
    72,     73,     74,     75,     76,     77,     78,     79,     80,
5645
    81,     82,     83,     84,     85,     86,     87,     88,     89,
5646
    90,     97,     98,     99,     100,    101,    102,    103,    104,
5647
    105,    106,    107,    108,    109,    110,    111,    112,    113,
5648
    114,    115,    116,    117,    118,    119,    120,    121,    122,
5649
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5650
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5651
    83,     84,     85,     86,     87,     88,     89,     90,     97,
5652
    98,     99,     100,    101,    102,    103,    104,    105,    106,
5653
    107,    108,    109,    110,    111,    112,    113,    114,    115,
5654
    116,    117,    118,    119,    120,    121,    122,    65,     66,
5655
    67,     68,     69,     70,     71,     72,     73,     74,     75,
5656
    76,     77,     78,     79,     80,     81,     82,     83,     84,
5657
    85,     86,     87,     88,     89,     90,     97,     98,     99,
5658
    100,    101,    102,    103,    104,    105,    106,    107,    108,
5659
    109,    110,    111,    112,    113,    114,    115,    116,    117,
5660
    118,    119,    120,    121,    122,    65,     66,     67,     68,
5661
    69,     70,     71,     72,     73,     74,     75,     76,     77,
5662
    78,     79,     80,     81,     82,     83,     84,     85,     86,
5663
    87,     88,     89,     90,     97,     98,     99,     100,    101,
5664
    102,    103,    104,    105,    106,    107,    108,    109,    110,
5665
    111,    112,    113,    114,    115,    116,    117,    118,    119,
5666
    120,    121,    122,    65,     66,     67,     68,     69,     70,
5667
    71,     72,     73,     74,     75,     76,     77,     78,     79,
5668
    80,     81,     82,     83,     84,     85,     86,     87,     88,
5669
    89,     90,     97,     98,     99,     100,    101,    102,    103,
5670
    104,    105,    106,    107,    108,    109,    110,    111,    112,
5671
    113,    114,    115,    116,    117,    118,    119,    120,    121,
5672
    122,    305,    567,    913,    914,    915,    916,    917,    918,
5673
    919,    920,    921,    922,    923,    924,    925,    926,    927,
5674
    928,    929,    920,    931,    932,    933,    934,    935,    936,
5675
    937,    8711,   945,    946,    947,    948,    949,    950,    951,
5676
    952,    953,    954,    955,    956,    957,    958,    959,    960,
5677
    961,    962,    963,    964,    965,    966,    967,    968,    969,
5678
    8706,   949,    952,    954,    966,    961,    960,    913,    914,
5679
    915,    916,    917,    918,    919,    920,    921,    922,    923,
5680
    924,    925,    926,    927,    928,    929,    920,    931,    932,
5681
    933,    934,    935,    936,    937,    8711,   945,    946,    947,
5682
    948,    949,    950,    951,    952,    953,    954,    955,    956,
5683
    957,    958,    959,    960,    961,    962,    963,    964,    965,
5684
    966,    967,    968,    969,    8706,   949,    952,    954,    966,
5685
    961,    960,    913,    914,    915,    916,    917,    918,    919,
5686
    920,    921,    922,    923,    924,    925,    926,    927,    928,
5687
    929,    920,    931,    932,    933,    934,    935,    936,    937,
5688
    8711,   945,    946,    947,    948,    949,    950,    951,    952,
5689
    953,    954,    955,    956,    957,    958,    959,    960,    961,
5690
    962,    963,    964,    965,    966,    967,    968,    969,    8706,
5691
    949,    952,    954,    966,    961,    960,    913,    914,    915,
5692
    916,    917,    918,    919,    920,    921,    922,    923,    924,
5693
    925,    926,    927,    928,    929,    920,    931,    932,    933,
5694
    934,    935,    936,    937,    8711,   945,    946,    947,    948,
5695
    949,    950,    951,    952,    953,    954,    955,    956,    957,
5696
    958,    959,    960,    961,    962,    963,    964,    965,    966,
5697
    967,    968,    969,    8706,   949,    952,    954,    966,    961,
5698
    960,    913,    914,    915,    916,    917,    918,    919,    920,
5699
    921,    922,    923,    924,    925,    926,    927,    928,    929,
5700
    920,    931,    932,    933,    934,    935,    936,    937,    8711,
5701
    945,    946,    947,    948,    949,    950,    951,    952,    953,
5702
    954,    955,    956,    957,    958,    959,    960,    961,    962,
5703
    963,    964,    965,    966,    967,    968,    969,    8706,   949,
5704
    952,    954,    966,    961,    960,    988,    989,    48,     49,
5705
    50,     51,     52,     53,     54,     55,     56,     57,     48,
5706
    49,     50,     51,     52,     53,     54,     55,     56,     57,
5707
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5708
    57,     48,     49,     50,     51,     52,     53,     54,     55,
5709
    56,     57,     48,     49,     50,     51,     52,     53,     54,
5710
    55,     56,     57,     1072,   1073,   1074,   1075,   1076,   1077,
5711
    1078,   1079,   1080,   1082,   1083,   1084,   1086,   1087,   1088,
5712
    1089,   1090,   1091,   1092,   1093,   1094,   1095,   1096,   1099,
5713
    1101,   1102,   42633,  1241,   1110,   1112,   1257,   1199,   1231,
5714
    1072,   1073,   1074,   1075,   1076,   1077,   1078,   1079,   1080,
5715
    1082,   1083,   1086,   1087,   1089,   1091,   1092,   1093,   1094,
5716
    1095,   1096,   1098,   1099,   1169,   1110,   1109,   1119,   1195,
5717
    42577,  1201,   1575,   1576,   1580,   1583,   1608,   1586,   1581,
5718
    1591,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5719
    1589,   1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,
5720
    1592,   1594,   1646,   1722,   1697,   1647,   1576,   1580,   1607,
5721
    1581,   1610,   1603,   1604,   1605,   1606,   1587,   1593,   1601,
5722
    1589,   1602,   1588,   1578,   1579,   1582,   1590,   1594,   1580,
5723
    1581,   1610,   1604,   1606,   1587,   1593,   1589,   1602,   1588,
5724
    1582,   1590,   1594,   1722,   1647,   1576,   1580,   1607,   1581,
5725
    1591,   1610,   1603,   1605,   1606,   1587,   1593,   1601,   1589,
5726
    1602,   1588,   1578,   1579,   1582,   1590,   1592,   1594,   1646,
5727
    1697,   1575,   1576,   1580,   1583,   1607,   1608,   1586,   1581,
5728
    1591,   1610,   1604,   1605,   1606,   1587,   1593,   1601,   1589,
5729
    1602,   1585,   1588,   1578,   1579,   1582,   1584,   1590,   1592,
5730
    1594,   1576,   1580,   1583,   1608,   1586,   1581,   1591,   1610,
5731
    1604,   1605,   1606,   1587,   1593,   1601,   1589,   1602,   1585,
5732
    1588,   1578,   1579,   1582,   1584,   1590,   1592,   1594,   48,
5733
    46,     48,     44,     49,     44,     50,     44,     51,     44,
5734
    52,     44,     53,     44,     54,     44,     55,     44,     56,
5735
    44,     57,     44,     40,     65,     41,     40,     66,     41,
5736
    40,     67,     41,     40,     68,     41,     40,     69,     41,
5737
    40,     70,     41,     40,     71,     41,     40,     72,     41,
5738
    40,     73,     41,     40,     74,     41,     40,     75,     41,
5739
    40,     76,     41,     40,     77,     41,     40,     78,     41,
5740
    40,     79,     41,     40,     80,     41,     40,     81,     41,
5741
    40,     82,     41,     40,     83,     41,     40,     84,     41,
5742
    40,     85,     41,     40,     86,     41,     40,     87,     41,
5743
    40,     88,     41,     40,     89,     41,     40,     90,     41,
5744
    12308,  83,     12309,  67,     82,     67,     68,     87,     90,
5745
    65,     66,     67,     68,     69,     70,     71,     72,     73,
5746
    74,     75,     76,     77,     78,     79,     80,     81,     82,
5747
    83,     84,     85,     86,     87,     88,     89,     90,     72,
5748
    86,     77,     86,     83,     68,     83,     83,     80,     80,
5749
    86,     87,     67,     77,     67,     77,     68,     77,     82,
5750
    68,     74,     12411,  12363,  12467,  12467,  12469,  25163,  23383,
5751
    21452,  12486,  12441,  20108,  22810,  35299,  22825,  20132,  26144,
5752
    28961,  26009,  21069,  24460,  20877,  26032,  21021,  32066,  29983,
5753
    36009,  22768,  21561,  28436,  25237,  25429,  19968,  19977,  36938,
5754
    24038,  20013,  21491,  25351,  36208,  25171,  31105,  31354,  21512,
5755
    28288,  26377,  26376,  30003,  21106,  21942,  37197,  12308,  26412,
5756
    12309,  12308,  19977,  12309,  12308,  20108,  12309,  12308,  23433,
5757
    12309,  12308,  28857,  12309,  12308,  25171,  12309,  12308,  30423,
5758
    12309,  12308,  21213,  12309,  12308,  25943,  12309,  24471,  21487,
5759
    48,     49,     50,     51,     52,     53,     54,     55,     56,
5760
    57,     20029,  20024,  20033,  131362, 20320,  20398,  20411,  20482,
5761
    20602,  20633,  20711,  20687,  13470,  132666, 20813,  20820,  20836,
5762
    20855,  132380, 13497,  20839,  20877,  132427, 20887,  20900,  20172,
5763
    20908,  20917,  168415, 20981,  20995,  13535,  21051,  21062,  21106,
5764
    21111,  13589,  21191,  21193,  21220,  21242,  21253,  21254,  21271,
5765
    21321,  21329,  21338,  21363,  21373,  21375,  21375,  21375,  133676,
5766
    28784,  21450,  21471,  133987, 21483,  21489,  21510,  21662,  21560,
5767
    21576,  21608,  21666,  21750,  21776,  21843,  21859,  21892,  21892,
5768
    21913,  21931,  21939,  21954,  22294,  22022,  22295,  22097,  22132,
5769
    20999,  22766,  22478,  22516,  22541,  22411,  22578,  22577,  22700,
5770
    136420, 22770,  22775,  22790,  22810,  22818,  22882,  136872, 136938,
5771
    23020,  23067,  23079,  23000,  23142,  14062,  14076,  23304,  23358,
5772
    23358,  137672, 23491,  23512,  23527,  23539,  138008, 23551,  23558,
5773
    24403,  23586,  14209,  23648,  23662,  23744,  23693,  138724, 23875,
5774
    138726, 23918,  23915,  23932,  24033,  24034,  14383,  24061,  24104,
5775
    24125,  24169,  14434,  139651, 14460,  24240,  24243,  24246,  24266,
5776
    172946, 24318,  140081, 140081, 33281,  24354,  24354,  14535,  144056,
5777
    156122, 24418,  24427,  14563,  24474,  24525,  24535,  24569,  24705,
5778
    14650,  14620,  24724,  141012, 24775,  24904,  24908,  24910,  24908,
5779
    24954,  24974,  25010,  24996,  25007,  25054,  25074,  25078,  25104,
5780
    25115,  25181,  25265,  25300,  25424,  142092, 25405,  25340,  25448,
5781
    25475,  25572,  142321, 25634,  25541,  25513,  14894,  25705,  25726,
5782
    25757,  25719,  14956,  25935,  25964,  143370, 26083,  26360,  26185,
5783
    15129,  26257,  15112,  15076,  20882,  20885,  26368,  26268,  32941,
5784
    17369,  26391,  26395,  26401,  26462,  26451,  144323, 15177,  26618,
5785
    26501,  26706,  26757,  144493, 26766,  26655,  26900,  15261,  26946,
5786
    27043,  27114,  27304,  145059, 27355,  15384,  27425,  145575, 27476,
5787
    15438,  27506,  27551,  27578,  27579,  146061, 138507, 146170, 27726,
5788
    146620, 27839,  27853,  27751,  27926,  27966,  28023,  27969,  28009,
5789
    28024,  28037,  146718, 27956,  28207,  28270,  15667,  28363,  28359,
5790
    147153, 28153,  28526,  147294, 147342, 28614,  28729,  28702,  28699,
5791
    15766,  28746,  28797,  28791,  28845,  132389, 28997,  148067, 29084,
5792
    148395, 29224,  29237,  29264,  149000, 29312,  29333,  149301, 149524,
5793
    29562,  29579,  16044,  29605,  16056,  16056,  29767,  29788,  29809,
5794
    29829,  29898,  16155,  29988,  150582, 30014,  150674, 30064,  139679,
5795
    30224,  151457, 151480, 151620, 16380,  16392,  30452,  151795, 151794,
5796
    151833, 151859, 30494,  30495,  30495,  30538,  16441,  30603,  16454,
5797
    16534,  152605, 30798,  30860,  30924,  16611,  153126, 31062,  153242,
5798
    153285, 31119,  31211,  16687,  31296,  31306,  31311,  153980, 154279,
5799
    154279, 31470,  16898,  154539, 31686,  31689,  16935,  154752, 31954,
5800
    17056,  31976,  31971,  32000,  155526, 32099,  17153,  32199,  32258,
5801
    32325,  17204,  156200, 156231, 17241,  156377, 32634,  156478, 32661,
5802
    32762,  32773,  156890, 156963, 32864,  157096, 32880,  144223, 17365,
5803
    32946,  33027,  17419,  33086,  23221,  157607, 157621, 144275, 144284,
5804
    33281,  33284,  36766,  17515,  33425,  33419,  33437,  21171,  33457,
5805
    33459,  33469,  33510,  158524, 33509,  33565,  33635,  33709,  33571,
5806
    33725,  33767,  33879,  33619,  33738,  33740,  33756,  158774, 159083,
5807
    158933, 17707,  34033,  34035,  34070,  160714, 34148,  159532, 17757,
5808
    17761,  159665, 159954, 17771,  34384,  34396,  34407,  34409,  34473,
5809
    34440,  34574,  34530,  34681,  34600,  34667,  34694,  17879,  34785,
5810
    34817,  17913,  34912,  34915,  161383, 35031,  35038,  17973,  35066,
5811
    13499,  161966, 162150, 18110,  18119,  35488,  35565,  35722,  35925,
5812
    162984, 36011,  36033,  36123,  36215,  163631, 133124, 36299,  36284,
5813
    36336,  133342, 36564,  36664,  165330, 165357, 37012,  37105,  37137,
5814
    165678, 37147,  37432,  37591,  37592,  37500,  37881,  37909,  166906,
5815
    38283,  18837,  38327,  167287, 18918,  38595,  23986,  38691,  168261,
5816
    168474, 19054,  19062,  38880,  168970, 19122,  169110, 38923,  38923,
5817
    38953,  169398, 39138,  19251,  39209,  39335,  39362,  39422,  19406,
5818
    170800, 39698,  40000,  40189,  19662,  19693,  40295,  172238, 19704,
5819
    172293, 172558, 172689, 40635,  19798,  40697,  40702,  40709,  40719,
5820
    40726,  40763,  173568};
5821
5822
const uint8_t canonical_combining_class_index[4352] = {
5823
    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 0,  0,
5824
    15, 0,  0,  0,  16, 17, 18, 19, 20, 21, 22, 0,  0,  23, 0,  0,  0,  0,  0,
5825
    0,  0,  0,  0,  0,  0,  24, 25, 0,  0,  26, 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,  27, 0,  28, 29, 30,
5832
    31, 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,  32, 0,  0,  33, 0,  0,  34, 35, 36, 0,  0,  0,  0,  0,  0,
5837
    37, 0,  0,  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0,  52,
5838
    53, 0,  54, 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,  55, 56, 0,  0,  0,  57, 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,  58, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5847
    0,  0,  0,  0,  0,  0,  0,  0,  0,  59, 60, 0,  0,  0,  0,  0,  0,  0,  0,
5848
    0,  0,  0,  0,  0,  61, 56, 62, 0,  63, 0,  0,  0,  64, 65, 0,  0,  0,  0,
5849
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5850
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5851
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5852
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5853
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5854
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5855
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5856
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5857
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5858
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5859
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5860
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5861
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5862
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5863
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5864
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5865
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5866
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5867
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5868
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5869
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5870
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5871
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5872
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5873
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5874
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5875
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5876
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5877
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5878
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5879
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5880
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5881
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5882
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5883
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5884
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5885
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5886
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5887
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5888
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5889
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5890
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5891
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5892
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5893
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5894
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5895
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5896
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5897
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5898
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5899
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5900
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5901
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5902
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5903
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5904
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5905
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5906
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5907
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5908
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5909
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5910
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5911
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5912
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5913
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5914
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5915
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5916
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5917
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5918
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5919
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5920
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5921
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5922
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5923
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5924
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5925
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5926
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5927
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5928
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5929
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5930
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5931
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5932
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5933
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5934
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5935
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5936
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5937
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5938
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5939
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5940
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5941
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5942
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5943
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5944
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5945
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5946
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5947
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5948
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5949
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5950
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5951
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5952
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5953
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5954
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5955
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5956
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5957
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5958
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5959
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5960
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5961
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5962
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5963
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5964
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5965
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5966
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5967
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5968
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5969
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5970
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5971
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5972
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5973
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5974
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5975
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5976
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5977
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5978
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5979
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5980
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5981
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5982
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5983
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5984
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5985
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5986
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5987
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5988
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5989
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5990
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5991
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5992
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5993
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5994
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5995
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5996
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5997
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5998
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
5999
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6000
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6001
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6002
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6003
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6004
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6005
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6006
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6007
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6008
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6009
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6010
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6011
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6012
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6014
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6015
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6016
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6017
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6018
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6019
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6020
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6021
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6022
    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,
6024
    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,
6026
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6027
    0,  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,
6029
    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,
6031
    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,  0,  0,  0,  0,  0,
6033
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6035
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6037
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6039
    0,  0,  0,  0,  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,  0,  0,  0,  0,
6041
    0,  0,  0,  0,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6043
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6044
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6045
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6046
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6047
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6048
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6049
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6050
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6051
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
6052
    0};
6053
const uint8_t canonical_combining_class_block[67][256] = {
6054
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6056
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6057
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6058
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6059
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 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, 0},
6065
    {230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6066
     230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220,
6067
     220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220,
6068
     220, 220, 220, 220, 220, 220, 220, 1,   1,   1,   1,   1,   220, 220, 220,
6069
     220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
6070
     230, 230, 220, 220, 0,   230, 230, 230, 220, 220, 220, 220, 230, 232, 220,
6071
     220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, 230, 230,
6072
     230, 230, 230, 230, 230, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,
6073
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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},
6083
    {0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6084
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6085
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6086
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6087
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6088
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
6089
     230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6090
     0,   0,   0,   0,   0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0,
6092
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6093
     0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6094
     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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6098
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6099
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6100
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6101
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6102
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6103
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6104
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 230, 230, 230, 230,
6105
     220, 230, 230, 230, 222, 220, 230, 230, 230, 230, 230, 230, 220, 220, 220,
6106
     220, 220, 220, 230, 230, 220, 230, 230, 222, 228, 230, 10,  11,  12,  13,
6107
     14,  15,  16,  17,  18,  19,  19,  20,  21,  22,  0,   23,  0,   24,  25,
6108
     0,   230, 220, 0,   18,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6109
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6110
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6111
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6112
     0},
6113
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6114
     0,   230, 230, 230, 230, 230, 230, 230, 230, 30,  31,  32,  0,   0,   0,
6115
     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,   0,   0,   0,
6117
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6118
     27,  28,  29,  30,  31,  32,  33,  34,  230, 230, 220, 220, 230, 230, 230,
6119
     230, 230, 220, 230, 230, 220, 0,   0,   0,   0,   0,   0,   0,   0,   0,
6120
     0,   0,   0,   0,   0,   0,   0,   35,  0,   0,   0,   0,   0,   0,   0,
6121
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6122
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6123
     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,
6125
     0,   0,   0,   0,   0,   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,
6127
     0,   0,   0,   0,   230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230,
6128
     230, 230, 220, 230, 0,   0,   230, 230, 0,   220, 230, 230, 220, 0,   0,
6129
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6130
     0},
6131
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6132
     0,   0,   36,  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,
6134
     0,   0,   0,   230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220,
6135
     220, 230, 220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
6136
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6137
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6138
     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,
6140
     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,   0,   0,   0,
6142
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6143
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6144
     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,
6146
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230,
6147
     230, 230, 220, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   220, 0,
6148
     0},
6149
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6150
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 0,   230, 230, 230,
6151
     230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 0,   230, 230, 230, 230,
6152
     230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6153
     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,   220,
6155
     220, 220, 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,
6157
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6158
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6159
     0,   0,   230, 220, 220, 220, 230, 230, 230, 230, 0,   0,   0,   0,   0,
6160
     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,
6162
     0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230, 230, 220, 220, 220,
6163
     220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6164
     230, 0,   220, 230, 230, 220, 230, 230, 220, 230, 230, 230, 220, 220, 220,
6165
     27,  28,  29,  230, 230, 230, 220, 230, 230, 220, 220, 230, 230, 230, 230,
6166
     230},
6167
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6168
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6169
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   7,   0,   0,   0, 0, 0,
6170
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,   0, 0, 230, 220, 230, 230, 0, 0, 0,
6171
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6172
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6173
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6174
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6175
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6176
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6177
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0,   0,   0,   0,   0, 0, 0,
6178
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0},
6179
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6180
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6182
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6183
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6184
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6185
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6186
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
6187
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6188
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6189
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6190
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6191
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6192
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6193
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 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, 9, 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, 0, 0, 0,
6200
     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, 7, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
6204
     0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 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, 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, 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, 0, 0,
6208
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 7, 0, 0, 0,
6209
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,  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, 0, 0,
6211
     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, 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, 0, 0,
6214
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6215
     0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6217
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6218
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6219
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6220
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
6223
    {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,
6225
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6226
     0,   0,   103, 103, 9,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6227
     107, 107, 107, 107, 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,
6229
     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,
6231
     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,
6233
     0,   0,   0,   0,   118, 118, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6234
     0,   0,   122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6235
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6236
     0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6237
     0,   0,   0,   0},
6238
    {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,   220, 220, 0,   0,   0, 0,
6240
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6241
     0,   0, 0,   0,   0,   0,   0, 0, 220, 0,   220, 0,   216, 0, 0,
6242
     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,
6244
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6245
     0,   0, 0,   0,   0,   0,   0, 0, 129, 130, 0,   132, 0,   0, 0,
6246
     0,   0, 130, 130, 130, 130, 0, 0, 130, 0,   230, 230, 9,   0, 230,
6247
     230, 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,
6249
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6250
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6251
     0,   0, 0,   220, 0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
6252
     0,   0, 0,   0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0, 0,
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},
6256
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6257
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6258
     0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6259
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6260
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6261
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0,
6262
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6263
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6264
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6265
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,
6266
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6267
    {0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6268
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6269
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6270
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6271
     0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6272
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0,
6274
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6275
     0, 0, 0, 0, 0, 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, 0, 0, 0,
6277
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6278
     0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0},
6279
    {0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0,
6280
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6281
     0, 0, 0, 0, 9, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6282
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6283
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6286
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6287
     0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,
6288
     0, 0, 0, 0, 0, 230, 0, 0, 0, 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, 0},
6290
    {0, 0,   0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6292
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6293
     0, 0,   0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6296
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6297
     0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6298
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6299
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6300
     0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6301
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0, 0, 0, 0, 0, 0,
6302
     0, 0, 0, 0, 0, 0, 0, 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, 222, 230, 220, 0, 0, 0, 0, 0, 0,
6304
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6306
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6308
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6310
     0, 0, 0, 0, 0, 0, 0, 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,   0,   0, 0, 0, 0, 0, 0,
6312
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6313
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6314
     0,   0,   0,   0,   0,   0,   0,   0,   230, 220, 0,   0,   0,   0,   0,
6315
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6316
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6317
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6318
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6319
     0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6320
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230,
6321
     230, 230, 230, 230, 230, 0,   0,   220, 0,   0,   0,   0,   0,   0,   0,
6322
     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,
6324
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 230, 230,
6325
     230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 0,   220, 220, 230, 230,
6326
     220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 230, 230, 0,   0,   0,
6327
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6328
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6329
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6330
     0},
6331
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6332
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6333
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   7,   0,   0,   0,   0,
6334
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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,
6336
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 230, 230, 230,
6337
     230, 230, 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,
6339
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   9,
6340
     9,   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,
6342
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,
6343
     0,   0,   7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   9,   9,   0,   0,   0,
6344
     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,
6346
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6347
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6348
     0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   7,   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,   0,   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,   230, 230,
6359
     230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, 220, 230,
6360
     0,   1, 1, 1,   1,   1,   1,   1,   0,   0,   0,   0,   220, 0,   0,
6361
     0,   0, 0, 0,   230, 0,   0,   0,   230, 230, 0,   0,   0,   0,   0,
6362
     0},
6363
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6364
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6365
     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,
6367
     0,   0,   0,   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,
6369
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6370
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6371
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6372
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6373
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6374
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6375
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230, 230, 220,
6376
     230, 230, 230, 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230,
6377
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6378
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6379
     230, 230, 230, 230, 230, 230, 232, 228, 228, 220, 218, 230, 233, 220, 230,
6380
     220},
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,   0,
6385
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   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,   0,   0,
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
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,
6394
     230, 230, 1, 1, 230, 230, 230, 230, 1,   1,   1, 230, 230, 0,   0,   0,
6395
     0,   230, 0, 0, 0,   1,   1,   230, 220, 230, 1, 1,   220, 220, 220, 220,
6396
     230, 0,   0, 0, 0,   0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0},
6397
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6398
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6399
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6400
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6401
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6402
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6403
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6404
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6405
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6406
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,
6407
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230,
6408
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6409
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6410
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6411
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6412
     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,
6414
     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,
6416
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6417
     0,   0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,
6418
     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,
6420
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6421
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6422
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6423
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6424
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6425
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6426
     230},
6427
    {0, 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, 0,
6429
     0, 0, 218, 228, 232, 222, 224, 224, 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, 0,
6431
     0, 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, 0,
6433
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6434
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
6435
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6436
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6437
     0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6438
     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},
6440
    {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,
6442
     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,
6444
     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,
6446
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   230,
6447
     0,   0,   0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 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,   230, 230,
6450
     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,
6452
     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,
6454
     0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6455
     230, 230, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0},
6456
    {0,   0,   0,   0,   0,   0,   9,   0,   0,   0,   0,   0,   0,   0,   0,
6457
     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,   9,
6459
     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,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6463
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
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,   9,   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,   230,
6471
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
6472
     230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6473
     0},
6474
    {0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6475
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
6476
     220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6477
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
6478
     0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6479
     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,
6481
     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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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,
6484
     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},
6486
    {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,
6488
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6489
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 0,
6490
     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,
6492
     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,
6494
     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, 230, 0, 230, 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0,
6496
     230, 230, 0, 230, 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,
6498
     0,   0,   0, 0,   0, 0,   0, 0,   0,   0,   0, 0, 0,   0,   0, 0, 0, 0, 9,
6499
     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, 0, 0,
6501
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6502
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6503
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6504
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6505
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6507
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6508
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6509
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,
6510
     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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6512
     0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6513
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6514
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6515
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6516
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6517
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6518
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6519
     0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6520
     0, 0, 0, 0, 0, 0, 0,  0, 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},
6522
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6523
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6524
     0,   0,   230, 230, 230, 230, 230, 230, 230, 220, 220, 220, 220, 220, 220,
6525
     220, 230, 230, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6526
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6527
     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,
6529
     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,
6531
     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,
6533
     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,
6535
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6536
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6537
     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,
6539
     0},
6540
    {0, 0, 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, 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, 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, 0, 0,
6544
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6545
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0,
6548
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6549
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6550
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0},
6551
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6552
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6553
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6554
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6555
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6556
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6557
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6558
     0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0,
6560
     0, 0, 0, 0, 0, 0, 0, 0, 220, 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},
6562
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6563
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6564
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6565
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6566
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6567
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6568
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6569
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0,
6570
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   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, 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,
6573
     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, 220, 0, 230, 0,   0, 0,   0,
6575
     0, 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,   230, 1, 220, 0,
6577
     0, 0, 0, 9, 0, 0, 0, 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,
6579
     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, 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,
6582
     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,   0,   0, 0,   0,
6584
     0, 0, 0, 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, 230, 220, 0, 0, 0,   0, 0,   0,   0, 0,   0,
6586
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,   0, 0},
6587
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6588
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
6589
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6590
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   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,
6592
     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,
6594
     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,
6596
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6597
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0, 0, 0,
6598
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6599
    {0, 0, 0, 0, 0, 0, 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, 0, 0,   0,   0, 0, 0,
6601
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6602
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6603
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6604
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6605
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6606
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 230, 230, 0, 0, 0,
6607
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6608
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6609
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,  0, 0, 0, 0,   0,   0, 0, 0,
6610
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220},
6611
    {0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6612
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6613
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6614
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 220, 220,
6615
     230, 230, 230, 220, 230, 220, 220, 220, 220, 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,
6617
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6618
     0,   0,   0,   0,   230, 220, 230, 220, 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,
6620
     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,
6622
     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,
6624
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0,   0,
6625
     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, 9, 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, 9, 0, 0, 0, 0, 0, 0, 0,
6631
     0, 0, 0, 0, 0, 0, 0, 9, 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, 0,
6633
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 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, 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},
6637
    {230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6638
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6639
     0,   0,   0,   0, 0, 0, 0, 9, 9, 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,
6641
     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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6643
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6644
     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, 9, 0, 0, 0, 0, 0,
6646
     0,   0,   0,   0, 7, 0, 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,
6648
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6649
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6650
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6651
     0, 0, 0, 0, 0, 9, 7, 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, 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, 7, 9, 0, 0, 0, 0, 0,
6659
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6660
    {0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6661
     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,
6663
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   7,   7,   0, 0, 0,
6664
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   9, 0, 0,
6665
     0,   0,   0,   0,   0,   0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0,
6666
     0,   0,   0,   0,   0,   0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0,
6667
     230, 230, 230, 230, 230, 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,
6670
     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,   0, 0, 0,
6672
     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,
6674
     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},
6676
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6677
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6678
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 7,   0,
6679
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0,
6680
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6681
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6682
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6683
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6684
     0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6685
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,
6686
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 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, 0, 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, 9,
6695
     7, 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},
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, 9, 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, 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, 0, 0, 0, 0, 0, 0,
6705
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
6706
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6707
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6708
     0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 9, 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, 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, 0, 0, 0, 0, 0, 0, 0,
6716
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6717
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6718
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6719
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
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, 9, 7, 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, 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},
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, 9, 9, 0, 0, 0, 0, 7, 0, 0, 0, 0,
6734
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6735
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6736
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6737
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6738
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6739
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6740
     0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
6742
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6743
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6744
     0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
6745
     0, 0, 0, 0, 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, 0, 0, 0, 0,
6747
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6748
     0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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},
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, 9, 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
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6759
     0, 0, 0, 0, 0, 0, 0, 0, 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},
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6766
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0,
6770
     0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6771
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6772
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6773
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6774
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6775
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6776
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6777
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0,
6778
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6779
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6780
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6781
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6782
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6783
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6784
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6785
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6786
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6787
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
6789
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6790
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6791
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 0, 0,
6796
     1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6797
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6798
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6799
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0,
6800
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6801
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6802
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   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,   0, 0, 0, 0, 0,
6804
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6805
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6806
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6807
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6808
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6809
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6810
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6811
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6812
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6813
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6814
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6815
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6816
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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, 0, 0,
6820
     6, 6, 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, 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, 0, 0,
6823
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6824
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0,
6826
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6827
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 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, 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, 0, 0,
6831
     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,
6833
     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,
6835
     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,
6837
     0,   0,   0,   0, 0, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6838
     0,   0,   0,   0, 0, 216, 216, 1,   1,   1,   0,   0,   0,   226, 216, 216,
6839
     216, 216, 216, 0, 0, 0,   0,   0,   0,   0,   0,   220, 220, 220, 220, 220,
6840
     220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, 220, 0,   0,   0,   0,
6841
     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,   230, 230, 230, 230, 0,   0,
6843
     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,
6845
     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,
6847
     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, 0, 0,
6849
     0,   0,   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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6851
     230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6852
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6853
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6854
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6855
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6856
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6857
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6858
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6859
     0,   0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6860
    {230, 230, 230, 230, 230, 230, 230, 0,   230, 230, 230, 230, 230, 230, 230,
6861
     230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0,   0,   230, 230, 230,
6862
     230, 230, 230, 230, 0,   230, 230, 0,   230, 230, 230, 230, 230, 0,   0,
6863
     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,
6865
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6866
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6867
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6868
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6869
     0,   0,   0,   0,   0,   0,   0,   0,   230, 0,   0,   0,   0,   0,   0,
6870
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6871
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6872
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6873
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6874
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6875
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6876
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
6877
     0},
6878
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6879
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6880
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6881
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6882
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6883
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6884
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6885
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   230, 0,
6886
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6887
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,
6888
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0,   0,
6889
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6890
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6891
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6892
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6893
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6894
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6895
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6896
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6897
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6898
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6899
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0, 0,
6900
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, 220, 230, 0, 0,
6901
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
6902
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6903
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6904
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6905
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6906
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6907
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6908
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6909
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6910
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6911
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6912
     0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 0, 0, 0, 0, 0,
6913
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0,
6914
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0,   0},
6915
    {0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6916
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6917
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6918
     0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 7, 0, 0, 0, 0, 0,
6919
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6920
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6921
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6922
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6923
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6924
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6925
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6926
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
6927
     0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0,   0, 0}};
6928
6929
const uint8_t composition_index[4352] = {
6930
    0, 1, 2, 3, 4,  5,  6, 5, 5,  7,  5, 8,  9,  10, 5, 5, 11, 5,  5, 5, 5, 5,
6931
    5, 5, 5, 5, 5,  12, 5, 5, 13, 14, 5, 15, 16, 5,  5, 5, 5,  5,  5, 5, 5, 5,
6932
    5, 5, 5, 5, 17, 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, 18, 19, 5, 20, 21, 22, 5, 5, 5,  23, 5, 5, 5, 5,
6943
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6944
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6945
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6946
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6947
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6948
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6949
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6950
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6951
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6952
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6953
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6954
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6955
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6956
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6957
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6958
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6959
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6960
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6961
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6962
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6963
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6964
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6965
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6966
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6967
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6968
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6969
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6970
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6971
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6972
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6973
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6974
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6975
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6976
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6977
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6978
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6979
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6980
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6981
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6982
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6983
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6984
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6985
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6986
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6987
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6988
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6989
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6990
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6991
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6992
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6993
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6994
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6995
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6996
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6997
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6998
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
6999
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7000
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7001
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7002
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7003
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7004
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7005
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7006
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7007
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7008
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7009
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7010
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7011
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7012
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7013
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7014
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7015
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7016
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7017
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7018
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7019
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7020
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7021
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7022
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7023
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7024
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7025
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7026
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7027
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7028
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7029
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7030
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7031
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7032
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7033
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7034
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7035
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7036
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7037
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7038
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7039
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7040
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7041
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7042
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7043
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7044
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7045
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7046
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7047
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7048
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7049
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7050
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7051
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7052
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7053
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7054
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7055
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7056
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7057
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7058
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7059
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7060
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7061
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7062
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7063
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7064
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7065
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7066
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7067
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7068
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7069
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7070
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7071
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7072
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7073
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7074
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7075
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7076
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7077
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7078
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7079
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7080
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7081
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7082
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7083
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7084
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7085
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7086
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7087
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7088
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7089
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7090
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7091
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7092
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7093
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7094
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7095
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7096
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7097
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7098
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7099
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7100
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7101
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7102
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7103
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7104
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7105
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7106
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7107
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7108
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7109
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7110
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7111
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7112
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7113
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7114
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7115
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7116
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7117
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7118
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7119
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7120
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7121
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7122
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7123
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7124
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7125
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7126
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5,  5, 5, 5, 5,
7127
    5, 5, 5, 5, 5,  5,  5, 5, 5,  5,  5, 5,  5,  5,  5, 5, 5,  5};
7128
const uint16_t composition_block[67][257] = {
7129
    {1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7130
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7131
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7132
     1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,
7133
     1,   3,   5,   7,   7,   7,   39,  45,  55,  67,  101, 103, 117, 131, 161,
7134
     163, 173, 185, 191, 209, 241, 245, 245, 261, 275, 289, 327, 331, 343, 347,
7135
     365, 377, 377, 377, 377, 377, 377, 377, 409, 415, 425, 437, 471, 473, 487,
7136
     503, 531, 535, 545, 557, 563, 581, 613, 617, 617, 633, 647, 663, 701, 705,
7137
     719, 723, 743, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7138
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7139
     755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755, 755,
7140
     755, 755, 755, 755, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7141
     761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761, 761,
7142
     769, 769, 771, 773, 777, 779, 779, 779, 787, 787, 787, 787, 787, 789, 789,
7143
     789, 789, 789, 797, 803, 805, 805, 807, 807, 807, 807, 815, 815, 815, 815,
7144
     815, 815, 823, 823, 825, 827, 831, 833, 833, 833, 841, 841, 841, 841, 841,
7145
     843, 843, 843, 843, 843, 851, 857, 859, 859, 861, 861, 861, 861, 869, 869,
7146
     869, 869},
7147
    {869, 869, 869, 877, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885, 885,
7148
     885, 885, 885, 885, 889, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7149
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7150
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7151
     893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893, 893,
7152
     893, 893, 897, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901,
7153
     901, 903, 905, 905, 905, 905, 905, 907, 909, 909, 909, 909, 909, 909, 909,
7154
     911, 913, 915, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917, 917,
7155
     917, 917, 917, 917, 917, 917, 917, 917, 919, 919, 919, 919, 919, 919, 919,
7156
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919,
7157
     919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 919, 929, 939, 939, 939,
7158
     939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 939, 949, 959, 959, 959,
7159
     959, 959, 959, 959, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7160
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7161
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 961,
7162
     961, 961, 961, 961, 961, 961, 961, 961, 961, 961, 963, 965, 965, 965, 965,
7163
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7164
     965, 965},
7165
    {965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7166
     965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965, 965,
7167
     965, 965, 965, 965, 965, 965, 965, 965, 965, 967, 969, 971, 973, 973, 973,
7168
     973, 973, 975, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7169
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7170
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7171
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7172
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7173
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
7174
     977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 979, 979, 979,
7175
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7176
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7177
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7178
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7179
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7180
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7181
     979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979, 979,
7182
     979, 979},
7183
    {979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7184
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7185
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7186
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7187
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7188
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7189
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7190
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7191
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7192
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7193
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7194
     979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,  979,
7195
     979,  979,  993,  993,  993,  993,  1001, 1001, 1011, 1011, 1025, 1025,
7196
     1025, 1025, 1025, 1025, 1033, 1033, 1035, 1035, 1035, 1035, 1047, 1047,
7197
     1047, 1047, 1057, 1057, 1057, 1059, 1059, 1061, 1061, 1061, 1077, 1077,
7198
     1077, 1077, 1085, 1085, 1097, 1097, 1113, 1113, 1113, 1113, 1113, 1113,
7199
     1121, 1121, 1125, 1125, 1125, 1125, 1141, 1141, 1141, 1141, 1153, 1159,
7200
     1165, 1165, 1165, 1167, 1167, 1167, 1167, 1171, 1171, 1171, 1171, 1171,
7201
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7202
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7203
     1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
7204
     1171, 1171, 1171, 1171, 1171},
7205
    {1171, 1171, 1171, 1171, 1171, 1171, 1171, 1173, 1173, 1173, 1173, 1173,
7206
     1173, 1173, 1173, 1173, 1173, 1177, 1177, 1177, 1179, 1179, 1185, 1189,
7207
     1191, 1199, 1199, 1201, 1201, 1201, 1201, 1203, 1203, 1203, 1203, 1203,
7208
     1211, 1211, 1211, 1211, 1213, 1213, 1213, 1213, 1215, 1215, 1217, 1217,
7209
     1217, 1221, 1221, 1221, 1223, 1223, 1229, 1233, 1235, 1243, 1243, 1245,
7210
     1245, 1245, 1245, 1247, 1247, 1247, 1247, 1247, 1255, 1255, 1255, 1255,
7211
     1257, 1257, 1257, 1257, 1259, 1259, 1261, 1261, 1261, 1261, 1261, 1261,
7212
     1261, 1261, 1261, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7213
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263,
7214
     1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1267, 1267,
7215
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7216
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7217
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7218
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7219
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7220
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7221
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7222
     1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267, 1267,
7223
     1267, 1269, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271, 1271,
7224
     1271, 1271, 1271, 1271, 1271, 1273, 1275, 1275, 1275, 1275, 1275, 1275,
7225
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7226
     1275, 1275, 1275, 1275, 1275},
7227
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7228
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7229
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7230
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7231
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7232
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7233
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7234
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7235
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7236
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7237
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
7238
    {1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7239
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7240
     1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275, 1275,
7241
     1275, 1275, 1275, 1275, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7242
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7243
     1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281, 1281,
7244
     1281, 1283, 1283, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7245
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7246
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7247
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7248
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7249
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7250
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7251
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7252
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7253
     1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285, 1285,
7254
     1285, 1285, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
7255
     1287, 1287, 1287, 1287, 1287, 1287, 1287, 1289, 1289, 1289, 1291, 1291,
7256
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7257
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7258
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7259
     1291, 1291, 1291, 1291, 1291},
7260
    {1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7261
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7262
     1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291, 1291,
7263
     1291, 1291, 1291, 1291, 1291, 1293, 1293, 1293, 1293, 1293, 1293, 1293,
7264
     1293, 1295, 1295, 1295, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7265
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7266
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7267
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7268
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7269
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7270
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7271
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7272
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7273
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7274
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7275
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297,
7276
     1297, 1297, 1297, 1297, 1297, 1297, 1297, 1297, 1301, 1301, 1301, 1301,
7277
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7278
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7279
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7280
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7281
     1301, 1301, 1301, 1301, 1301},
7282
    {1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7283
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7284
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7285
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7286
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7287
     1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301, 1301,
7288
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7289
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7290
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7291
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7292
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7293
     1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307, 1307,
7294
     1307, 1307, 1307, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7295
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7296
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7297
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
7298
     1309, 1309, 1309, 1309, 1309, 1309, 1309, 1313, 1315, 1315, 1315, 1315,
7299
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7300
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7301
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7302
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7303
     1315, 1315, 1315, 1315, 1315},
7304
    {1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7305
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7306
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7307
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7308
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315,
7309
     1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1315, 1317,
7310
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7311
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7312
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7313
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7314
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7315
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7316
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7317
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7318
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7319
     1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317, 1317,
7320
     1319, 1319, 1319, 1319, 1319, 1319, 1319, 1325, 1325, 1325, 1325, 1327,
7321
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7322
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7323
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7324
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7325
     1327, 1327, 1327, 1327, 1327},
7326
    {1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7327
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7328
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7329
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7330
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327,
7331
     1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1331,
7332
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7333
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7334
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7335
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7336
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7337
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7338
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7339
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7340
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7341
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7342
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7343
     1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333, 1333,
7344
     1333, 1333, 1339, 1339, 1339, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7345
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7346
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7347
     1341, 1341, 1341, 1341, 1341},
7348
    {1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7349
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7350
     1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341, 1341,
7351
     1341, 1341, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7352
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7353
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7354
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7355
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7356
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7357
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7358
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7359
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7360
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7361
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7362
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7363
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7364
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7365
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7366
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7367
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7368
     1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343, 1343,
7369
     1343, 1343, 1343, 1343, 1343},
7370
    {1343, 1343, 1343, 1343, 1343, 1343, 1345, 1345, 1347, 1347, 1349, 1349,
7371
     1351, 1351, 1353, 1353, 1353, 1353, 1355, 1355, 1355, 1355, 1355, 1355,
7372
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7373
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355,
7374
     1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1355, 1357,
7375
     1357, 1359, 1359, 1361, 1363, 1363, 1363, 1365, 1365, 1365, 1365, 1365,
7376
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7377
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7378
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7379
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7380
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7381
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7382
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7383
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7384
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7385
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7386
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7387
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7388
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7389
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7390
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7391
     1365, 1365, 1365, 1365, 1365},
7392
    {1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7393
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7394
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7395
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1365,
7396
     1365, 1365, 1365, 1365, 1365, 1365, 1365, 1367, 1369, 1369, 1369, 1369,
7397
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7398
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369, 1369,
7399
     1369, 1369, 1369, 1369, 1369, 1369, 1369, 1371, 1373, 1373, 1373, 1373,
7400
     1373, 1373, 1373, 1375, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7401
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7402
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7403
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7404
     1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377,
7405
     1377, 1377, 1377, 1377, 1377, 1381, 1385, 1385, 1385, 1385, 1385, 1385,
7406
     1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385, 1385,
7407
     1385, 1385, 1385, 1385, 1385, 1387, 1389, 1389, 1389, 1389, 1389, 1389,
7408
     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
7409
     1389, 1391, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7410
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7411
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7412
     1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393, 1393,
7413
     1393, 1393, 1393, 1393, 1393},
7414
    {1393, 1401, 1409, 1411, 1413, 1415, 1417, 1419, 1421, 1429, 1437, 1439,
7415
     1441, 1443, 1445, 1447, 1449, 1453, 1457, 1457, 1457, 1457, 1457, 1457,
7416
     1457, 1461, 1465, 1465, 1465, 1465, 1465, 1465, 1465, 1473, 1481, 1483,
7417
     1485, 1487, 1489, 1491, 1493, 1501, 1509, 1511, 1513, 1515, 1517, 1519,
7418
     1521, 1527, 1533, 1533, 1533, 1533, 1533, 1533, 1533, 1539, 1545, 1545,
7419
     1545, 1545, 1545, 1545, 1545, 1549, 1553, 1553, 1553, 1553, 1553, 1553,
7420
     1553, 1557, 1561, 1561, 1561, 1561, 1561, 1561, 1561, 1567, 1573, 1573,
7421
     1573, 1573, 1573, 1573, 1573, 1573, 1579, 1579, 1579, 1579, 1579, 1579,
7422
     1579, 1587, 1595, 1597, 1599, 1601, 1603, 1605, 1607, 1615, 1623, 1625,
7423
     1627, 1629, 1631, 1633, 1635, 1637, 1637, 1637, 1637, 1639, 1639, 1639,
7424
     1639, 1639, 1639, 1639, 1639, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7425
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7426
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7427
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7428
     1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641, 1641,
7429
     1641, 1641, 1641, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643, 1643,
7430
     1649, 1649, 1649, 1649, 1649, 1649, 1649, 1651, 1651, 1651, 1651, 1651,
7431
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7432
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7433
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651, 1651,
7434
     1651, 1651, 1651, 1651, 1651, 1651, 1651, 1653, 1653, 1653, 1653, 1653,
7435
     1653, 1653, 1653, 1659, 1659},
7436
    {1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7437
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7438
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7439
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7440
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7441
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7442
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7443
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7444
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7445
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7446
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7447
     1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659, 1659,
7448
     1659, 1661, 1661, 1663, 1663, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7449
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7450
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7451
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7452
     1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665, 1665,
7453
     1665, 1665, 1665, 1665, 1665, 1667, 1667, 1669, 1669, 1671, 1671, 1671,
7454
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7455
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7456
     1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671, 1671,
7457
     1671, 1671, 1671, 1671, 1671},
7458
    {1671, 1671, 1671, 1671, 1673, 1673, 1673, 1673, 1673, 1675, 1675, 1675,
7459
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7460
     1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677, 1677,
7461
     1679, 1679, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7462
     1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681, 1681,
7463
     1681, 1683, 1683, 1683, 1683, 1683, 1683, 1683, 1685, 1685, 1687, 1687,
7464
     1687, 1689, 1689, 1689, 1689, 1689, 1691, 1691, 1691, 1691, 1691, 1691,
7465
     1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691, 1691,
7466
     1691, 1691, 1693, 1693, 1693, 1695, 1697, 1697, 1697, 1697, 1697, 1697,
7467
     1697, 1697, 1697, 1697, 1697, 1697, 1697, 1699, 1701, 1701, 1701, 1703,
7468
     1705, 1705, 1705, 1707, 1709, 1711, 1713, 1713, 1713, 1713, 1713, 1715,
7469
     1717, 1717, 1717, 1719, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721,
7470
     1721, 1721, 1723, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725, 1725,
7471
     1725, 1725, 1725, 1725, 1725, 1725, 1725, 1727, 1727, 1727, 1727, 1727,
7472
     1727, 1729, 1731, 1731, 1733, 1733, 1733, 1733, 1733, 1733, 1733, 1735,
7473
     1737, 1739, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7474
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7475
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7476
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7477
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7478
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7479
     1741, 1741, 1741, 1741, 1741},
7480
    {1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7481
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7482
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7483
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7484
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741,
7485
     1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1741, 1743,
7486
     1743, 1743, 1743, 1743, 1745, 1745, 1747, 1747, 1749, 1749, 1751, 1751,
7487
     1753, 1753, 1755, 1755, 1757, 1757, 1759, 1759, 1761, 1761, 1763, 1763,
7488
     1765, 1765, 1767, 1767, 1767, 1769, 1769, 1771, 1771, 1773, 1773, 1773,
7489
     1773, 1773, 1773, 1773, 1777, 1777, 1777, 1781, 1781, 1781, 1785, 1785,
7490
     1785, 1789, 1789, 1789, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7491
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7492
     1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793, 1793,
7493
     1793, 1793, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1795, 1797,
7494
     1797, 1797, 1797, 1797, 1799, 1799, 1801, 1801, 1803, 1803, 1805, 1805,
7495
     1807, 1807, 1809, 1809, 1811, 1811, 1813, 1813, 1815, 1815, 1817, 1817,
7496
     1819, 1819, 1821, 1821, 1821, 1823, 1823, 1825, 1825, 1827, 1827, 1827,
7497
     1827, 1827, 1827, 1827, 1831, 1831, 1831, 1835, 1835, 1835, 1839, 1839,
7498
     1839, 1843, 1843, 1843, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7499
     1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847, 1847,
7500
     1849, 1851, 1853, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855, 1855,
7501
     1855, 1855, 1857, 1857, 1857},
7502
    {1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7503
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7504
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7505
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7506
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7507
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7508
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7509
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7510
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7511
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7512
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7513
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857,
7514
     1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1857, 1859, 1859,
7515
     1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1861, 1863, 1863,
7516
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7517
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7518
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7519
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7520
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7521
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7522
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7523
     1863, 1863, 1863, 1863, 1863},
7524
    {1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7525
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7526
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7527
     1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863, 1863,
7528
     1863, 1863, 1865, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7529
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7530
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7531
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7532
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7533
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7534
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7535
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7536
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7537
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7538
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7539
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7540
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7541
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7542
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7543
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7544
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7545
     1867, 1867, 1867, 1867, 1867},
7546
    {1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7547
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7548
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7549
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7550
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7551
     1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867, 1867,
7552
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7553
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7554
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7555
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7556
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7557
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7558
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7559
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7560
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7561
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7562
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7563
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7564
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7565
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7566
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7567
     1871, 1871, 1871, 1871, 1871},
7568
    {1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7569
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7570
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7571
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7572
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7573
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7574
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7575
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7576
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7577
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7578
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7579
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7580
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7581
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7582
     1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871, 1871,
7583
     1871, 1871, 1871, 1871, 1871, 1871, 1877, 1877, 1877, 1877, 1877, 1877,
7584
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7585
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7586
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7587
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7588
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7589
     1877, 1877, 1877, 1877, 1877},
7590
    {1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7591
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7592
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7593
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7594
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7595
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7596
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7597
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7598
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7599
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7600
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7601
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7602
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7603
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7604
     1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
7605
     1877, 1877, 1877, 1877, 1877, 1879, 1881, 1881, 1881, 1881, 1881, 1881,
7606
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7607
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7608
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7609
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7610
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7611
     1881, 1881, 1881, 1881, 1881},
7612
    {1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7613
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7614
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7615
     1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881, 1881,
7616
     1881, 1881, 1881, 1881, 1881, 1881, 1883, 1883, 1883, 1883, 1883, 1883,
7617
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7618
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7619
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7620
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7621
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7622
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7623
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7624
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7625
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7626
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7627
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7628
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7629
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7630
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7631
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7632
     1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883, 1883,
7633
     1883, 1883, 1883, 1883, 1883}};
7634
const char32_t composition_data[1883] = {
7635
    0,     824,   8814,  824,   8800,  824,   8815,  768,   192,   769,   193,
7636
    770,   194,   771,   195,   772,   256,   774,   258,   775,   550,   776,
7637
    196,   777,   7842,  778,   197,   780,   461,   783,   512,   785,   514,
7638
    803,   7840,  805,   7680,  808,   260,   775,   7682,  803,   7684,  817,
7639
    7686,  769,   262,   770,   264,   775,   266,   780,   268,   807,   199,
7640
    775,   7690,  780,   270,   803,   7692,  807,   7696,  813,   7698,  817,
7641
    7694,  768,   200,   769,   201,   770,   202,   771,   7868,  772,   274,
7642
    774,   276,   775,   278,   776,   203,   777,   7866,  780,   282,   783,
7643
    516,   785,   518,   803,   7864,  807,   552,   808,   280,   813,   7704,
7644
    816,   7706,  775,   7710,  769,   500,   770,   284,   772,   7712,  774,
7645
    286,   775,   288,   780,   486,   807,   290,   770,   292,   775,   7714,
7646
    776,   7718,  780,   542,   803,   7716,  807,   7720,  814,   7722,  768,
7647
    204,   769,   205,   770,   206,   771,   296,   772,   298,   774,   300,
7648
    775,   304,   776,   207,   777,   7880,  780,   463,   783,   520,   785,
7649
    522,   803,   7882,  808,   302,   816,   7724,  770,   308,   769,   7728,
7650
    780,   488,   803,   7730,  807,   310,   817,   7732,  769,   313,   780,
7651
    317,   803,   7734,  807,   315,   813,   7740,  817,   7738,  769,   7742,
7652
    775,   7744,  803,   7746,  768,   504,   769,   323,   771,   209,   775,
7653
    7748,  780,   327,   803,   7750,  807,   325,   813,   7754,  817,   7752,
7654
    768,   210,   769,   211,   770,   212,   771,   213,   772,   332,   774,
7655
    334,   775,   558,   776,   214,   777,   7886,  779,   336,   780,   465,
7656
    783,   524,   785,   526,   795,   416,   803,   7884,  808,   490,   769,
7657
    7764,  775,   7766,  769,   340,   775,   7768,  780,   344,   783,   528,
7658
    785,   530,   803,   7770,  807,   342,   817,   7774,  769,   346,   770,
7659
    348,   775,   7776,  780,   352,   803,   7778,  806,   536,   807,   350,
7660
    775,   7786,  780,   356,   803,   7788,  806,   538,   807,   354,   813,
7661
    7792,  817,   7790,  768,   217,   769,   218,   770,   219,   771,   360,
7662
    772,   362,   774,   364,   776,   220,   777,   7910,  778,   366,   779,
7663
    368,   780,   467,   783,   532,   785,   534,   795,   431,   803,   7908,
7664
    804,   7794,  808,   370,   813,   7798,  816,   7796,  771,   7804,  803,
7665
    7806,  768,   7808,  769,   7810,  770,   372,   775,   7814,  776,   7812,
7666
    803,   7816,  775,   7818,  776,   7820,  768,   7922,  769,   221,   770,
7667
    374,   771,   7928,  772,   562,   775,   7822,  776,   376,   777,   7926,
7668
    803,   7924,  769,   377,   770,   7824,  775,   379,   780,   381,   803,
7669
    7826,  817,   7828,  768,   224,   769,   225,   770,   226,   771,   227,
7670
    772,   257,   774,   259,   775,   551,   776,   228,   777,   7843,  778,
7671
    229,   780,   462,   783,   513,   785,   515,   803,   7841,  805,   7681,
7672
    808,   261,   775,   7683,  803,   7685,  817,   7687,  769,   263,   770,
7673
    265,   775,   267,   780,   269,   807,   231,   775,   7691,  780,   271,
7674
    803,   7693,  807,   7697,  813,   7699,  817,   7695,  768,   232,   769,
7675
    233,   770,   234,   771,   7869,  772,   275,   774,   277,   775,   279,
7676
    776,   235,   777,   7867,  780,   283,   783,   517,   785,   519,   803,
7677
    7865,  807,   553,   808,   281,   813,   7705,  816,   7707,  775,   7711,
7678
    769,   501,   770,   285,   772,   7713,  774,   287,   775,   289,   780,
7679
    487,   807,   291,   770,   293,   775,   7715,  776,   7719,  780,   543,
7680
    803,   7717,  807,   7721,  814,   7723,  817,   7830,  768,   236,   769,
7681
    237,   770,   238,   771,   297,   772,   299,   774,   301,   776,   239,
7682
    777,   7881,  780,   464,   783,   521,   785,   523,   803,   7883,  808,
7683
    303,   816,   7725,  770,   309,   780,   496,   769,   7729,  780,   489,
7684
    803,   7731,  807,   311,   817,   7733,  769,   314,   780,   318,   803,
7685
    7735,  807,   316,   813,   7741,  817,   7739,  769,   7743,  775,   7745,
7686
    803,   7747,  768,   505,   769,   324,   771,   241,   775,   7749,  780,
7687
    328,   803,   7751,  807,   326,   813,   7755,  817,   7753,  768,   242,
7688
    769,   243,   770,   244,   771,   245,   772,   333,   774,   335,   775,
7689
    559,   776,   246,   777,   7887,  779,   337,   780,   466,   783,   525,
7690
    785,   527,   795,   417,   803,   7885,  808,   491,   769,   7765,  775,
7691
    7767,  769,   341,   775,   7769,  780,   345,   783,   529,   785,   531,
7692
    803,   7771,  807,   343,   817,   7775,  769,   347,   770,   349,   775,
7693
    7777,  780,   353,   803,   7779,  806,   537,   807,   351,   775,   7787,
7694
    776,   7831,  780,   357,   803,   7789,  806,   539,   807,   355,   813,
7695
    7793,  817,   7791,  768,   249,   769,   250,   770,   251,   771,   361,
7696
    772,   363,   774,   365,   776,   252,   777,   7911,  778,   367,   779,
7697
    369,   780,   468,   783,   533,   785,   535,   795,   432,   803,   7909,
7698
    804,   7795,  808,   371,   813,   7799,  816,   7797,  771,   7805,  803,
7699
    7807,  768,   7809,  769,   7811,  770,   373,   775,   7815,  776,   7813,
7700
    778,   7832,  803,   7817,  775,   7819,  776,   7821,  768,   7923,  769,
7701
    253,   770,   375,   771,   7929,  772,   563,   775,   7823,  776,   255,
7702
    777,   7927,  778,   7833,  803,   7925,  769,   378,   770,   7825,  775,
7703
    380,   780,   382,   803,   7827,  817,   7829,  768,   8173,  769,   901,
7704
    834,   8129,  768,   7846,  769,   7844,  771,   7850,  777,   7848,  772,
7705
    478,   769,   506,   769,   508,   772,   482,   769,   7688,  768,   7872,
7706
    769,   7870,  771,   7876,  777,   7874,  769,   7726,  768,   7890,  769,
7707
    7888,  771,   7894,  777,   7892,  769,   7756,  772,   556,   776,   7758,
7708
    772,   554,   769,   510,   768,   475,   769,   471,   772,   469,   780,
7709
    473,   768,   7847,  769,   7845,  771,   7851,  777,   7849,  772,   479,
7710
    769,   507,   769,   509,   772,   483,   769,   7689,  768,   7873,  769,
7711
    7871,  771,   7877,  777,   7875,  769,   7727,  768,   7891,  769,   7889,
7712
    771,   7895,  777,   7893,  769,   7757,  772,   557,   776,   7759,  772,
7713
    555,   769,   511,   768,   476,   769,   472,   772,   470,   780,   474,
7714
    768,   7856,  769,   7854,  771,   7860,  777,   7858,  768,   7857,  769,
7715
    7855,  771,   7861,  777,   7859,  768,   7700,  769,   7702,  768,   7701,
7716
    769,   7703,  768,   7760,  769,   7762,  768,   7761,  769,   7763,  775,
7717
    7780,  775,   7781,  775,   7782,  775,   7783,  769,   7800,  769,   7801,
7718
    776,   7802,  776,   7803,  775,   7835,  768,   7900,  769,   7898,  771,
7719
    7904,  777,   7902,  803,   7906,  768,   7901,  769,   7899,  771,   7905,
7720
    777,   7903,  803,   7907,  768,   7914,  769,   7912,  771,   7918,  777,
7721
    7916,  803,   7920,  768,   7915,  769,   7913,  771,   7919,  777,   7917,
7722
    803,   7921,  780,   494,   772,   492,   772,   493,   772,   480,   772,
7723
    481,   774,   7708,  774,   7709,  772,   560,   772,   561,   780,   495,
7724
    768,   8122,  769,   902,   772,   8121,  774,   8120,  787,   7944,  788,
7725
    7945,  837,   8124,  768,   8136,  769,   904,   787,   7960,  788,   7961,
7726
    768,   8138,  769,   905,   787,   7976,  788,   7977,  837,   8140,  768,
7727
    8154,  769,   906,   772,   8153,  774,   8152,  776,   938,   787,   7992,
7728
    788,   7993,  768,   8184,  769,   908,   787,   8008,  788,   8009,  788,
7729
    8172,  768,   8170,  769,   910,   772,   8169,  774,   8168,  776,   939,
7730
    788,   8025,  768,   8186,  769,   911,   787,   8040,  788,   8041,  837,
7731
    8188,  837,   8116,  837,   8132,  768,   8048,  769,   940,   772,   8113,
7732
    774,   8112,  787,   7936,  788,   7937,  834,   8118,  837,   8115,  768,
7733
    8050,  769,   941,   787,   7952,  788,   7953,  768,   8052,  769,   942,
7734
    787,   7968,  788,   7969,  834,   8134,  837,   8131,  768,   8054,  769,
7735
    943,   772,   8145,  774,   8144,  776,   970,   787,   7984,  788,   7985,
7736
    834,   8150,  768,   8056,  769,   972,   787,   8000,  788,   8001,  787,
7737
    8164,  788,   8165,  768,   8058,  769,   973,   772,   8161,  774,   8160,
7738
    776,   971,   787,   8016,  788,   8017,  834,   8166,  768,   8060,  769,
7739
    974,   787,   8032,  788,   8033,  834,   8182,  837,   8179,  768,   8146,
7740
    769,   912,   834,   8151,  768,   8162,  769,   944,   834,   8167,  837,
7741
    8180,  769,   979,   776,   980,   776,   1031,  774,   1232,  776,   1234,
7742
    769,   1027,  768,   1024,  774,   1238,  776,   1025,  774,   1217,  776,
7743
    1244,  776,   1246,  768,   1037,  772,   1250,  774,   1049,  776,   1252,
7744
    769,   1036,  776,   1254,  772,   1262,  774,   1038,  776,   1264,  779,
7745
    1266,  776,   1268,  776,   1272,  776,   1260,  774,   1233,  776,   1235,
7746
    769,   1107,  768,   1104,  774,   1239,  776,   1105,  774,   1218,  776,
7747
    1245,  776,   1247,  768,   1117,  772,   1251,  774,   1081,  776,   1253,
7748
    769,   1116,  776,   1255,  772,   1263,  774,   1118,  776,   1265,  779,
7749
    1267,  776,   1269,  776,   1273,  776,   1261,  776,   1111,  783,   1142,
7750
    783,   1143,  776,   1242,  776,   1243,  776,   1258,  776,   1259,  1619,
7751
    1570,  1620,  1571,  1621,  1573,  1620,  1572,  1620,  1574,  1620,  1730,
7752
    1620,  1747,  1620,  1728,  2364,  2345,  2364,  2353,  2364,  2356,  2494,
7753
    2507,  2519,  2508,  2878,  2891,  2902,  2888,  2903,  2892,  3031,  2964,
7754
    3006,  3018,  3031,  3020,  3006,  3019,  3158,  3144,  3285,  3264,  3266,
7755
    3274,  3285,  3271,  3286,  3272,  3285,  3275,  3390,  3402,  3415,  3404,
7756
    3390,  3403,  3530,  3546,  3535,  3548,  3551,  3550,  3530,  3549,  4142,
7757
    4134,  6965,  6918,  6965,  6920,  6965,  6922,  6965,  6924,  6965,  6926,
7758
    6965,  6930,  6965,  6971,  6965,  6973,  6965,  6976,  6965,  6977,  6965,
7759
    6979,  772,   7736,  772,   7737,  772,   7772,  772,   7773,  775,   7784,
7760
    775,   7785,  770,   7852,  774,   7862,  770,   7853,  774,   7863,  770,
7761
    7878,  770,   7879,  770,   7896,  770,   7897,  768,   7938,  769,   7940,
7762
    834,   7942,  837,   8064,  768,   7939,  769,   7941,  834,   7943,  837,
7763
    8065,  837,   8066,  837,   8067,  837,   8068,  837,   8069,  837,   8070,
7764
    837,   8071,  768,   7946,  769,   7948,  834,   7950,  837,   8072,  768,
7765
    7947,  769,   7949,  834,   7951,  837,   8073,  837,   8074,  837,   8075,
7766
    837,   8076,  837,   8077,  837,   8078,  837,   8079,  768,   7954,  769,
7767
    7956,  768,   7955,  769,   7957,  768,   7962,  769,   7964,  768,   7963,
7768
    769,   7965,  768,   7970,  769,   7972,  834,   7974,  837,   8080,  768,
7769
    7971,  769,   7973,  834,   7975,  837,   8081,  837,   8082,  837,   8083,
7770
    837,   8084,  837,   8085,  837,   8086,  837,   8087,  768,   7978,  769,
7771
    7980,  834,   7982,  837,   8088,  768,   7979,  769,   7981,  834,   7983,
7772
    837,   8089,  837,   8090,  837,   8091,  837,   8092,  837,   8093,  837,
7773
    8094,  837,   8095,  768,   7986,  769,   7988,  834,   7990,  768,   7987,
7774
    769,   7989,  834,   7991,  768,   7994,  769,   7996,  834,   7998,  768,
7775
    7995,  769,   7997,  834,   7999,  768,   8002,  769,   8004,  768,   8003,
7776
    769,   8005,  768,   8010,  769,   8012,  768,   8011,  769,   8013,  768,
7777
    8018,  769,   8020,  834,   8022,  768,   8019,  769,   8021,  834,   8023,
7778
    768,   8027,  769,   8029,  834,   8031,  768,   8034,  769,   8036,  834,
7779
    8038,  837,   8096,  768,   8035,  769,   8037,  834,   8039,  837,   8097,
7780
    837,   8098,  837,   8099,  837,   8100,  837,   8101,  837,   8102,  837,
7781
    8103,  768,   8042,  769,   8044,  834,   8046,  837,   8104,  768,   8043,
7782
    769,   8045,  834,   8047,  837,   8105,  837,   8106,  837,   8107,  837,
7783
    8108,  837,   8109,  837,   8110,  837,   8111,  837,   8114,  837,   8130,
7784
    837,   8178,  837,   8119,  768,   8141,  769,   8142,  834,   8143,  837,
7785
    8135,  837,   8183,  768,   8157,  769,   8158,  834,   8159,  824,   8602,
7786
    824,   8603,  824,   8622,  824,   8653,  824,   8655,  824,   8654,  824,
7787
    8708,  824,   8713,  824,   8716,  824,   8740,  824,   8742,  824,   8769,
7788
    824,   8772,  824,   8775,  824,   8777,  824,   8813,  824,   8802,  824,
7789
    8816,  824,   8817,  824,   8820,  824,   8821,  824,   8824,  824,   8825,
7790
    824,   8832,  824,   8833,  824,   8928,  824,   8929,  824,   8836,  824,
7791
    8837,  824,   8840,  824,   8841,  824,   8930,  824,   8931,  824,   8876,
7792
    824,   8877,  824,   8878,  824,   8879,  824,   8938,  824,   8939,  824,
7793
    8940,  824,   8941,  12441, 12436, 12441, 12364, 12441, 12366, 12441, 12368,
7794
    12441, 12370, 12441, 12372, 12441, 12374, 12441, 12376, 12441, 12378, 12441,
7795
    12380, 12441, 12382, 12441, 12384, 12441, 12386, 12441, 12389, 12441, 12391,
7796
    12441, 12393, 12441, 12400, 12442, 12401, 12441, 12403, 12442, 12404, 12441,
7797
    12406, 12442, 12407, 12441, 12409, 12442, 12410, 12441, 12412, 12442, 12413,
7798
    12441, 12446, 12441, 12532, 12441, 12460, 12441, 12462, 12441, 12464, 12441,
7799
    12466, 12441, 12468, 12441, 12470, 12441, 12472, 12441, 12474, 12441, 12476,
7800
    12441, 12478, 12441, 12480, 12441, 12482, 12441, 12485, 12441, 12487, 12441,
7801
    12489, 12441, 12496, 12442, 12497, 12441, 12499, 12442, 12500, 12441, 12502,
7802
    12442, 12503, 12441, 12505, 12442, 12506, 12441, 12508, 12442, 12509, 12441,
7803
    12535, 12441, 12536, 12441, 12537, 12441, 12538, 12441, 12542, 69818, 69786,
7804
    69818, 69788, 69818, 69803, 69927, 69934, 69927, 69935, 70462, 70475, 70487,
7805
    70476, 70832, 70844, 70842, 70843, 70845, 70846, 71087, 71098, 71087, 71099,
7806
    71984, 71992};
7807
7808
}  // namespace ada::idna
7809
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
7810
/* end file src/normalization_tables.cpp */
7811
7812
namespace ada::idna {
7813
7814
// See
7815
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
7816
constexpr char32_t hangul_sbase = 0xAC00;
7817
constexpr char32_t hangul_tbase = 0x11A7;
7818
constexpr char32_t hangul_vbase = 0x1161;
7819
constexpr char32_t hangul_lbase = 0x1100;
7820
constexpr char32_t hangul_lcount = 19;
7821
constexpr char32_t hangul_vcount = 21;
7822
constexpr char32_t hangul_tcount = 28;
7823
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
7824
constexpr char32_t hangul_scount =
7825
    hangul_lcount * hangul_vcount * hangul_tcount;
7826
7827
std::pair<bool, size_t> compute_decomposition_length(
7828
117k
    const std::u32string_view input) noexcept {
7829
117k
  bool decomposition_needed{false};
7830
117k
  size_t additional_elements{0};
7831
1.71M
  for (char32_t current_character : input) {
7832
1.71M
    size_t decomposition_length{0};
7833
7834
1.71M
    if (current_character >= hangul_sbase &&
7835
82.4k
        current_character < hangul_sbase + hangul_scount) {
7836
43.8k
      decomposition_length = 2;
7837
43.8k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7838
26.7k
        decomposition_length = 3;
7839
26.7k
      }
7840
1.66M
    } else if (current_character < 0x110000) {
7841
1.66M
      const uint8_t di = decomposition_index[current_character >> 8];
7842
1.66M
      const uint16_t* const decomposition =
7843
1.66M
          decomposition_block[di] + (current_character % 256);
7844
1.66M
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7845
1.66M
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7846
11.3k
        decomposition_length = 0;
7847
11.3k
      }
7848
1.66M
    }
7849
1.71M
    if (decomposition_length != 0) {
7850
85.1k
      decomposition_needed = true;
7851
85.1k
      additional_elements += decomposition_length - 1;
7852
85.1k
    }
7853
1.71M
  }
7854
117k
  return {decomposition_needed, additional_elements};
7855
117k
}
7856
7857
25.5k
void decompose(std::u32string& input, size_t additional_elements) {
7858
25.5k
  input.resize(input.size() + additional_elements);
7859
25.5k
  for (size_t descending_idx = input.size(),
7860
25.5k
              input_count = descending_idx - additional_elements;
7861
480k
       input_count--;) {
7862
454k
    if (input[input_count] >= hangul_sbase &&
7863
51.4k
        input[input_count] < hangul_sbase + hangul_scount) {
7864
      // Hangul decomposition.
7865
43.8k
      char32_t s_index = input[input_count] - hangul_sbase;
7866
43.8k
      if (s_index % hangul_tcount != 0) {
7867
26.7k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7868
26.7k
      }
7869
43.8k
      input[--descending_idx] =
7870
43.8k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7871
43.8k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7872
410k
    } else if (input[input_count] < 0x110000) {
7873
      // Check decomposition_data.
7874
410k
      const uint16_t* decomposition =
7875
410k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7876
410k
          (input[input_count] % 256);
7877
410k
      uint16_t decomposition_length =
7878
410k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7879
410k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7880
2.09k
        decomposition_length = 0;
7881
2.09k
      }
7882
410k
      if (decomposition_length > 0) {
7883
        // Non-recursive decomposition.
7884
145k
        while (decomposition_length-- > 0) {
7885
103k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7886
103k
                                                       decomposition_length];
7887
103k
        }
7888
369k
      } else {
7889
        // No decomposition.
7890
369k
        input[--descending_idx] = input[input_count];
7891
369k
      }
7892
410k
    } else {
7893
      // Non-Unicode character.
7894
0
      input[--descending_idx] = input[input_count];
7895
0
    }
7896
454k
  }
7897
25.5k
}
7898
7899
3.45M
uint8_t get_ccc(char32_t c) noexcept {
7900
3.45M
  return c < 0x110000 ? canonical_combining_class_block
7901
3.45M
                            [canonical_combining_class_index[c >> 8]][c % 256]
7902
3.45M
                      : 0;
7903
3.45M
}
7904
7905
117k
void sort_marks(std::u32string& input) {
7906
1.84M
  for (size_t idx = 1; idx < input.size(); idx++) {
7907
1.72M
    uint8_t ccc = get_ccc(input[idx]);
7908
1.72M
    if (ccc == 0) {
7909
1.62M
      continue;
7910
1.62M
    }  // Skip non-combining characters.
7911
99.4k
    auto current_character = input[idx];
7912
99.4k
    size_t back_idx = idx;
7913
129k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7914
30.4k
      input[back_idx] = input[back_idx - 1];
7915
30.4k
      back_idx--;
7916
30.4k
    }
7917
99.4k
    input[back_idx] = current_character;
7918
99.4k
  }
7919
117k
}
7920
7921
117k
void decompose_nfc(std::u32string& input) {
7922
  /**
7923
   * Decompose the domain_name string to Unicode Normalization Form C.
7924
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
7925
   */
7926
117k
  auto [decomposition_needed, additional_elements] =
7927
117k
      compute_decomposition_length(input);
7928
117k
  if (decomposition_needed) {
7929
25.5k
    decompose(input, additional_elements);
7930
25.5k
  }
7931
117k
  sort_marks(input);
7932
117k
}
7933
7934
117k
void compose(std::u32string& input) {
7935
  /**
7936
   * Compose the domain_name string to Unicode Normalization Form C.
7937
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
7938
   */
7939
117k
  size_t input_count{0};
7940
117k
  size_t composition_count{0};
7941
1.78M
  for (; input_count < input.size(); input_count++, composition_count++) {
7942
1.67M
    input[composition_count] = input[input_count];
7943
1.67M
    if (input[input_count] >= hangul_lbase &&
7944
550k
        input[input_count] < hangul_lbase + hangul_lcount) {
7945
58.4k
      if (input_count + 1 < input.size() &&
7946
55.8k
          input[input_count + 1] >= hangul_vbase &&
7947
47.2k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7948
44.2k
        input[composition_count] =
7949
44.2k
            hangul_sbase +
7950
44.2k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7951
44.2k
             input[input_count + 1] - hangul_vbase) *
7952
44.2k
                hangul_tcount;
7953
44.2k
        input_count++;
7954
44.2k
        if (input_count + 1 < input.size() &&
7955
42.9k
            input[input_count + 1] > hangul_tbase &&
7956
28.4k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7957
26.7k
          input[composition_count] += input[++input_count] - hangul_tbase;
7958
26.7k
        }
7959
44.2k
      }
7960
1.61M
    } else if (input[input_count] >= hangul_sbase &&
7961
35.7k
               input[input_count] < hangul_sbase + hangul_scount) {
7962
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount &&
7963
0
          input_count + 1 < input.size() &&
7964
0
          input[input_count + 1] > hangul_tbase &&
7965
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
7966
0
        input[composition_count] += input[++input_count] - hangul_tbase;
7967
0
      }
7968
1.61M
    } else if (input[input_count] < 0x110000) {
7969
1.61M
      const uint16_t* composition =
7970
1.61M
          &composition_block[composition_index[input[input_count] >> 8]]
7971
1.61M
                            [input[input_count] % 256];
7972
1.61M
      size_t initial_composition_count = composition_count;
7973
1.71M
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7974
1.61M
           input_count++) {
7975
1.60M
        uint8_t ccc = get_ccc(input[input_count + 1]);
7976
7977
1.60M
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7978
          // Try finding a composition.
7979
385k
          int left = composition[0];
7980
385k
          int right = composition[1];
7981
1.02M
          while (left + 2 < right) {
7982
            // mean without overflow
7983
641k
            int middle = left + (((right - left) >> 1) & ~1);
7984
641k
            if (composition_data[middle] <= input[input_count + 1]) {
7985
120k
              left = middle;
7986
120k
            }
7987
641k
            if (composition_data[middle] >= input[input_count + 1]) {
7988
563k
              right = middle;
7989
563k
            }
7990
641k
          }
7991
385k
          if (composition_data[left] == input[input_count + 1]) {
7992
63.7k
            input[initial_composition_count] = composition_data[left + 1];
7993
63.7k
            composition =
7994
63.7k
                &composition_block
7995
63.7k
                    [composition_index[composition_data[left + 1] >> 8]]
7996
63.7k
                    [composition_data[left + 1] % 256];
7997
63.7k
            continue;
7998
63.7k
          }
7999
385k
        }
8000
8001
1.54M
        if (ccc == 0) {
8002
1.50M
          break;
8003
1.50M
        }  // Not a combining character.
8004
36.2k
        previous_ccc = ccc;
8005
36.2k
        input[++composition_count] = input[input_count + 1];
8006
36.2k
      }
8007
1.61M
    }
8008
1.67M
  }
8009
8010
117k
  if (composition_count < input_count) {
8011
28.0k
    input.resize(composition_count);
8012
28.0k
  }
8013
117k
}
8014
8015
117k
void normalize(std::u32string& input) {
8016
  /**
8017
   * Normalize the domain_name string to Unicode Normalization Form C.
8018
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
8019
   */
8020
117k
  decompose_nfc(input);
8021
117k
  compose(input);
8022
117k
}
8023
8024
}  // namespace ada::idna
8025
/* end file src/normalization.cpp */
8026
/* begin file src/punycode.cpp */
8027
8028
#include <cstdint>
8029
8030
namespace ada::idna {
8031
8032
constexpr int32_t base = 36;
8033
constexpr int32_t tmin = 1;
8034
constexpr int32_t tmax = 26;
8035
constexpr int32_t skew = 38;
8036
constexpr int32_t damp = 700;
8037
constexpr int32_t initial_bias = 72;
8038
constexpr uint32_t initial_n = 128;
8039
8040
908k
static constexpr int32_t char_to_digit_value(char value) {
8041
908k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
238k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
8.92k
  return -1;
8044
238k
}
idna.cc:ada::idna::char_to_digit_value(char)
Line
Count
Source
8040
256k
static constexpr int32_t char_to_digit_value(char value) {
8041
256k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
45.9k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
6.39k
  return -1;
8044
45.9k
}
ada.cpp:ada::idna::char_to_digit_value(char)
Line
Count
Source
8040
117k
static constexpr int32_t char_to_digit_value(char value) {
8041
117k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
25.6k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
491
  return -1;
8044
25.6k
}
serializers.cc:ada::idna::char_to_digit_value(char)
Line
Count
Source
8040
5.94k
static constexpr int32_t char_to_digit_value(char value) {
8041
5.94k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
970
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
8
  return -1;
8044
970
}
Unexecuted instantiation: can_parse.cc:ada::idna::char_to_digit_value(char)
Unexecuted instantiation: unicode.cc:ada::idna::char_to_digit_value(char)
parse.cc:ada::idna::char_to_digit_value(char)
Line
Count
Source
8040
110k
static constexpr int32_t char_to_digit_value(char value) {
8041
110k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
28.1k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
182
  return -1;
8044
28.1k
}
url_pattern.cc:ada::idna::char_to_digit_value(char)
Line
Count
Source
8040
418k
static constexpr int32_t char_to_digit_value(char value) {
8041
418k
  if (value >= 'a' && value <= 'z') return value - 'a';
8042
137k
  if (value >= '0' && value <= '9') return value - '0' + 26;
8043
1.85k
  return -1;
8044
137k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::char_to_digit_value(char)
8045
8046
1.40M
static constexpr char digit_to_char(int32_t digit) {
8047
1.40M
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
1.40M
}
idna.cc:ada::idna::digit_to_char(int)
Line
Count
Source
8046
85.3k
static constexpr char digit_to_char(int32_t digit) {
8047
85.3k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
85.3k
}
ada.cpp:ada::idna::digit_to_char(int)
Line
Count
Source
8046
437k
static constexpr char digit_to_char(int32_t digit) {
8047
437k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
437k
}
serializers.cc:ada::idna::digit_to_char(int)
Line
Count
Source
8046
3.26k
static constexpr char digit_to_char(int32_t digit) {
8047
3.26k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
3.26k
}
Unexecuted instantiation: can_parse.cc:ada::idna::digit_to_char(int)
Unexecuted instantiation: unicode.cc:ada::idna::digit_to_char(int)
parse.cc:ada::idna::digit_to_char(int)
Line
Count
Source
8046
767k
static constexpr char digit_to_char(int32_t digit) {
8047
767k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
767k
}
url_pattern.cc:ada::idna::digit_to_char(int)
Line
Count
Source
8046
114k
static constexpr char digit_to_char(int32_t digit) {
8047
114k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
114k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::digit_to_char(int)
8049
8050
1.02M
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
1.02M
  if (firsttime) {
8052
188k
    d = d / damp;
8053
840k
  } else {
8054
840k
    d = d / 2;
8055
840k
  }
8056
1.02M
  d += d / n;
8057
1.02M
  int32_t k = 0;
8058
1.40M
  while (d > ((base - tmin) * tmax) / 2) {
8059
378k
    d /= base - tmin;
8060
378k
    k += base;
8061
378k
  }
8062
1.02M
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
1.02M
}
idna.cc:ada::idna::adapt(int, int, bool)
Line
Count
Source
8050
238k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
238k
  if (firsttime) {
8052
19.6k
    d = d / damp;
8053
218k
  } else {
8054
218k
    d = d / 2;
8055
218k
  }
8056
238k
  d += d / n;
8057
238k
  int32_t k = 0;
8058
263k
  while (d > ((base - tmin) * tmax) / 2) {
8059
24.5k
    d /= base - tmin;
8060
24.5k
    k += base;
8061
24.5k
  }
8062
238k
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
238k
}
ada.cpp:ada::idna::adapt(int, int, bool)
Line
Count
Source
8050
248k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
248k
  if (firsttime) {
8052
37.5k
    d = d / damp;
8053
210k
  } else {
8054
210k
    d = d / 2;
8055
210k
  }
8056
248k
  d += d / n;
8057
248k
  int32_t k = 0;
8058
344k
  while (d > ((base - tmin) * tmax) / 2) {
8059
95.9k
    d /= base - tmin;
8060
95.9k
    k += base;
8061
95.9k
  }
8062
248k
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
248k
}
serializers.cc:ada::idna::adapt(int, int, bool)
Line
Count
Source
8050
4.54k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
4.54k
  if (firsttime) {
8052
957
    d = d / damp;
8053
3.59k
  } else {
8054
3.59k
    d = d / 2;
8055
3.59k
  }
8056
4.54k
  d += d / n;
8057
4.54k
  int32_t k = 0;
8058
5.50k
  while (d > ((base - tmin) * tmax) / 2) {
8059
955
    d /= base - tmin;
8060
955
    k += base;
8061
955
  }
8062
4.54k
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
4.54k
}
Unexecuted instantiation: can_parse.cc:ada::idna::adapt(int, int, bool)
Unexecuted instantiation: unicode.cc:ada::idna::adapt(int, int, bool)
parse.cc:ada::idna::adapt(int, int, bool)
Line
Count
Source
8050
329k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
329k
  if (firsttime) {
8052
51.4k
    d = d / damp;
8053
278k
  } else {
8054
278k
    d = d / 2;
8055
278k
  }
8056
329k
  d += d / n;
8057
329k
  int32_t k = 0;
8058
509k
  while (d > ((base - tmin) * tmax) / 2) {
8059
180k
    d /= base - tmin;
8060
180k
    k += base;
8061
180k
  }
8062
329k
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
329k
}
url_pattern.cc:ada::idna::adapt(int, int, bool)
Line
Count
Source
8050
207k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
8051
207k
  if (firsttime) {
8052
78.8k
    d = d / damp;
8053
129k
  } else {
8054
129k
    d = d / 2;
8055
129k
  }
8056
207k
  d += d / n;
8057
207k
  int32_t k = 0;
8058
283k
  while (d > ((base - tmin) * tmax) / 2) {
8059
76.0k
    d /= base - tmin;
8060
76.0k
    k += base;
8061
76.0k
  }
8062
207k
  return k + (((base - tmin + 1) * d) / (d + skew));
8063
207k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::adapt(int, int, bool)
8064
8065
108k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8066
108k
  int32_t written_out{0};
8067
108k
  out.reserve(out.size() + input.size());
8068
108k
  uint32_t n = initial_n;
8069
108k
  int32_t i = 0;
8070
108k
  int32_t bias = initial_bias;
8071
  // grab ascii content
8072
108k
  size_t end_of_ascii = input.find_last_of('-');
8073
108k
  if (end_of_ascii != std::string_view::npos) {
8074
139k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8075
139k
      if (c >= 0x80) {
8076
353
        return false;
8077
353
      }
8078
139k
      out.push_back(c);
8079
139k
      written_out++;
8080
139k
    }
8081
20.8k
    input.remove_prefix(end_of_ascii + 1);
8082
20.8k
  }
8083
557k
  while (!input.empty()) {
8084
461k
    int32_t oldi = i;
8085
461k
    int32_t w = 1;
8086
897k
    for (int32_t k = base;; k += base) {
8087
897k
      if (input.empty()) {
8088
3.74k
        return false;
8089
3.74k
      }
8090
893k
      uint8_t code_point = input.front();
8091
893k
      input.remove_prefix(1);
8092
893k
      int32_t digit = char_to_digit_value(code_point);
8093
893k
      if (digit < 0) {
8094
6.40k
        return false;
8095
6.40k
      }
8096
887k
      if (digit > (0x7fffffff - i) / w) {
8097
457
        return false;
8098
457
      }
8099
886k
      i = i + digit * w;
8100
886k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8101
886k
      if (digit < t) {
8102
450k
        break;
8103
450k
      }
8104
435k
      if (w > 0x7fffffff / (base - t)) {
8105
0
        return false;
8106
0
      }
8107
435k
      w = w * (base - t);
8108
435k
    }
8109
450k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8110
450k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8111
1.82k
      return false;
8112
1.82k
    }
8113
449k
    n = n + i / (written_out + 1);
8114
449k
    i = i % (written_out + 1);
8115
449k
    if (n < 0x80) {
8116
0
      return false;
8117
0
    }
8118
449k
    out.insert(out.begin() + i, n);
8119
449k
    written_out++;
8120
449k
    ++i;
8121
449k
  }
8122
  // See https://github.com/whatwg/url/issues/803
8123
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
8124
96.0k
  if (out.size() >= 4 && out[0] == U'x' && out[1] == U'n' && out[2] == U'-' &&
8125
1.81k
      out[3] == U'-') {
8126
262
    return false;
8127
262
  }
8128
95.8k
  return true;
8129
96.0k
}
8130
8131
3.69k
bool verify_punycode(std::string_view input) {
8132
  // Track only the first 4 decoded code points to check for the "xn--" prefix.
8133
  // This avoids heap allocation while still detecting double-encoded ACE
8134
  // labels.
8135
3.69k
  uint32_t first4[4]{};
8136
3.69k
  size_t written_out{0};
8137
3.69k
  uint32_t n = initial_n;
8138
3.69k
  int32_t i = 0;
8139
3.69k
  int32_t bias = initial_bias;
8140
  // grab ascii content
8141
3.69k
  size_t end_of_ascii = input.find_last_of('-');
8142
3.69k
  if (end_of_ascii != std::string_view::npos) {
8143
30.0k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8144
30.0k
      if (c >= 0x80) {
8145
343
        return false;
8146
343
      }
8147
29.6k
      if (written_out < 4) {
8148
5.39k
        first4[written_out] = c;
8149
5.39k
      }
8150
29.6k
      written_out++;
8151
29.6k
    }
8152
1.47k
    input.remove_prefix(end_of_ascii + 1);
8153
1.47k
  }
8154
10.0k
  while (!input.empty()) {
8155
9.34k
    int32_t oldi = i;
8156
9.34k
    int32_t w = 1;
8157
14.9k
    for (int32_t k = base;; k += base) {
8158
14.9k
      if (input.empty()) {
8159
69
        return false;
8160
69
      }
8161
14.8k
      uint8_t code_point = input.front();
8162
14.8k
      input.remove_prefix(1);
8163
14.8k
      int32_t digit = char_to_digit_value(code_point);
8164
14.8k
      if (digit < 0) {
8165
2.52k
        return false;
8166
2.52k
      }
8167
12.3k
      if (digit > (0x7fffffff - i) / w) {
8168
25
        return false;
8169
25
      }
8170
12.3k
      i = i + digit * w;
8171
12.3k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8172
12.3k
      if (digit < t) {
8173
6.73k
        break;
8174
6.73k
      }
8175
5.59k
      if (w > 0x7fffffff / (base - t)) {
8176
0
        return false;
8177
0
      }
8178
5.59k
      w = w * (base - t);
8179
5.59k
    }
8180
6.73k
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8181
6.73k
    if (i / (written_out + 1) > 0x7fffffff - n) {
8182
0
      return false;
8183
0
    }
8184
6.73k
    n = n + i / int32_t(written_out + 1);
8185
6.73k
    i = i % int32_t(written_out + 1);
8186
6.73k
    if (n < 0x80) {
8187
0
      return false;
8188
0
    }
8189
    // Simulate insert at position i, maintaining only the first 4 slots.
8190
6.73k
    size_t insert_pos = size_t(i);
8191
6.73k
    if (insert_pos < 4) {
8192
4.40k
      for (size_t j = 3; j > insert_pos; j--) {
8193
2.67k
        first4[j] = first4[j - 1];
8194
2.67k
      }
8195
1.72k
      first4[insert_pos] = n;
8196
1.72k
    }
8197
6.73k
    written_out++;
8198
6.73k
    ++i;
8199
6.73k
  }
8200
  // See https://github.com/whatwg/url/issues/803
8201
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
8202
731
  if (written_out >= 4 && first4[0] == U'x' && first4[1] == U'n' &&
8203
311
      first4[2] == U'-' && first4[3] == U'-') {
8204
153
    return false;
8205
153
  }
8206
578
  return true;
8207
731
}
8208
8209
99.1k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8210
99.1k
  out.reserve(input.size() + out.size());
8211
99.1k
  uint32_t n = initial_n;
8212
99.1k
  int32_t d = 0;
8213
99.1k
  int32_t bias = initial_bias;
8214
99.1k
  size_t h = 0;
8215
  // first push the ascii content
8216
716k
  for (uint32_t c : input) {
8217
716k
    if (c < 0x80) {
8218
145k
      ++h;
8219
145k
      out.push_back(char(c));
8220
145k
    }
8221
716k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8222
139
      return false;
8223
139
    }
8224
716k
  }
8225
98.9k
  size_t b = h;
8226
98.9k
  if (b > 0) {
8227
28.1k
    out.push_back('-');
8228
28.1k
  }
8229
470k
  while (h < input.size()) {
8230
371k
    uint32_t m = 0x10FFFF;
8231
5.48M
    for (auto code_point : input) {
8232
5.48M
      if (code_point >= n && code_point < m) m = code_point;
8233
5.48M
    }
8234
8235
371k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8236
0
      return false;
8237
0
    }
8238
371k
    d = d + int32_t((m - n) * (h + 1));
8239
371k
    n = m;
8240
5.48M
    for (auto c : input) {
8241
5.48M
      if (c < n) {
8242
3.01M
        if (d == 0x7fffffff) {
8243
0
          return false;
8244
0
        }
8245
3.01M
        ++d;
8246
3.01M
      }
8247
5.48M
      if (c == n) {
8248
570k
        int32_t q = d;
8249
1.40M
        for (int32_t k = base;; k += base) {
8250
1.40M
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8251
8252
1.40M
          if (q < t) {
8253
570k
            break;
8254
570k
          }
8255
837k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8256
837k
          q = (q - t) / (base - t);
8257
837k
        }
8258
570k
        out.push_back(digit_to_char(q));
8259
570k
        bias = adapt(d, int32_t(h + 1), h == b);
8260
570k
        d = 0;
8261
570k
        ++h;
8262
570k
      }
8263
5.48M
    }
8264
371k
    ++d;
8265
371k
    ++n;
8266
371k
  }
8267
98.9k
  return true;
8268
98.9k
}
8269
8270
}  // namespace ada::idna
8271
/* end file src/punycode.cpp */
8272
/* begin file src/validity.cpp */
8273
#include <algorithm>
8274
#include <string_view>
8275
8276
namespace ada::idna {
8277
8278
enum direction : uint8_t {
8279
  NONE,
8280
  BN,
8281
  CS,
8282
  ES,
8283
  ON,
8284
  EN,
8285
  L,
8286
  R,
8287
  NSM,
8288
  AL,
8289
  AN,
8290
  ET,
8291
  WS,
8292
  RLO,
8293
  LRO,
8294
  PDF,
8295
  RLE,
8296
  RLI,
8297
  FSI,
8298
  PDI,
8299
  LRI,
8300
  B,
8301
  S,
8302
  LRE
8303
};
8304
8305
struct directions {
8306
  uint32_t start_code;
8307
  uint32_t final_code;
8308
  direction direct;
8309
};
8310
8311
static directions dir_table[] = {
8312
    {0x0, 0x8, direction::BN},          {0x9, 0x9, direction::S},
8313
    {0xa, 0xa, direction::B},           {0xb, 0xb, direction::S},
8314
    {0xc, 0xc, direction::WS},          {0xd, 0xd, direction::B},
8315
    {0xe, 0x1b, direction::BN},         {0x1c, 0x1e, direction::B},
8316
    {0x1f, 0x1f, direction::S},         {0x20, 0x20, direction::WS},
8317
    {0x21, 0x22, direction::ON},        {0x23, 0x25, direction::ET},
8318
    {0x26, 0x2a, direction::ON},        {0x2b, 0x2b, direction::ES},
8319
    {0x2c, 0x2c, direction::CS},        {0x2d, 0x2d, direction::ES},
8320
    {0x2e, 0x2f, direction::CS},        {0x30, 0x39, direction::EN},
8321
    {0x3a, 0x3a, direction::CS},        {0x3b, 0x40, direction::ON},
8322
    {0x41, 0x5a, direction::L},         {0x5b, 0x60, direction::ON},
8323
    {0x61, 0x7a, direction::L},         {0x7b, 0x7e, direction::ON},
8324
    {0x7f, 0x84, direction::BN},        {0x85, 0x85, direction::B},
8325
    {0x86, 0x9f, direction::BN},        {0xa0, 0xa0, direction::CS},
8326
    {0xa1, 0xa1, direction::ON},        {0xa2, 0xa5, direction::ET},
8327
    {0xa6, 0xa9, direction::ON},        {0xaa, 0xaa, direction::L},
8328
    {0xab, 0xac, direction::ON},        {0xad, 0xad, direction::BN},
8329
    {0xae, 0xaf, direction::ON},        {0xb0, 0xb1, direction::ET},
8330
    {0xb2, 0xb3, direction::EN},        {0xb4, 0xb4, direction::ON},
8331
    {0xb5, 0xb5, direction::L},         {0xb6, 0xb8, direction::ON},
8332
    {0xb9, 0xb9, direction::EN},        {0xba, 0xba, direction::L},
8333
    {0xbb, 0xbf, direction::ON},        {0xc0, 0xd6, direction::L},
8334
    {0xd7, 0xd7, direction::ON},        {0xd8, 0xf6, direction::L},
8335
    {0xf7, 0xf7, direction::ON},        {0xf8, 0x2b8, direction::L},
8336
    {0x2b9, 0x2ba, direction::ON},      {0x2bb, 0x2c1, direction::L},
8337
    {0x2c2, 0x2cf, direction::ON},      {0x2d0, 0x2d1, direction::L},
8338
    {0x2d2, 0x2df, direction::ON},      {0x2e0, 0x2e4, direction::L},
8339
    {0x2e5, 0x2ed, direction::ON},      {0x2ee, 0x2ee, direction::L},
8340
    {0x2ef, 0x2ff, direction::ON},      {0x300, 0x36f, direction::NSM},
8341
    {0x370, 0x373, direction::L},       {0x374, 0x375, direction::ON},
8342
    {0x376, 0x377, direction::L},       {0x37a, 0x37d, direction::L},
8343
    {0x37e, 0x37e, direction::ON},      {0x37f, 0x37f, direction::L},
8344
    {0x384, 0x385, direction::ON},      {0x386, 0x386, direction::L},
8345
    {0x387, 0x387, direction::ON},      {0x388, 0x38a, direction::L},
8346
    {0x38c, 0x38c, direction::L},       {0x38e, 0x3a1, direction::L},
8347
    {0x3a3, 0x3f5, direction::L},       {0x3f6, 0x3f6, direction::ON},
8348
    {0x3f7, 0x482, direction::L},       {0x483, 0x489, direction::NSM},
8349
    {0x48a, 0x52f, direction::L},       {0x531, 0x556, direction::L},
8350
    {0x559, 0x589, direction::L},       {0x58a, 0x58a, direction::ON},
8351
    {0x58d, 0x58e, direction::ON},      {0x58f, 0x58f, direction::ET},
8352
    {0x591, 0x5bd, direction::NSM},     {0x5be, 0x5be, direction::R},
8353
    {0x5bf, 0x5bf, direction::NSM},     {0x5c0, 0x5c0, direction::R},
8354
    {0x5c1, 0x5c2, direction::NSM},     {0x5c3, 0x5c3, direction::R},
8355
    {0x5c4, 0x5c5, direction::NSM},     {0x5c6, 0x5c6, direction::R},
8356
    {0x5c7, 0x5c7, direction::NSM},     {0x5d0, 0x5ea, direction::R},
8357
    {0x5ef, 0x5f4, direction::R},       {0x600, 0x605, direction::AN},
8358
    {0x606, 0x607, direction::ON},      {0x608, 0x608, direction::AL},
8359
    {0x609, 0x60a, direction::ET},      {0x60b, 0x60b, direction::AL},
8360
    {0x60c, 0x60c, direction::CS},      {0x60d, 0x60d, direction::AL},
8361
    {0x60e, 0x60f, direction::ON},      {0x610, 0x61a, direction::NSM},
8362
    {0x61b, 0x61c, direction::AL},      {0x61e, 0x64a, direction::AL},
8363
    {0x64b, 0x65f, direction::NSM},     {0x660, 0x669, direction::AN},
8364
    {0x66a, 0x66a, direction::ET},      {0x66b, 0x66c, direction::AN},
8365
    {0x66d, 0x66f, direction::AL},      {0x670, 0x670, direction::NSM},
8366
    {0x671, 0x6d5, direction::AL},      {0x6d6, 0x6dc, direction::NSM},
8367
    {0x6dd, 0x6dd, direction::AN},      {0x6de, 0x6de, direction::ON},
8368
    {0x6df, 0x6e4, direction::NSM},     {0x6e5, 0x6e6, direction::AL},
8369
    {0x6e7, 0x6e8, direction::NSM},     {0x6e9, 0x6e9, direction::ON},
8370
    {0x6ea, 0x6ed, direction::NSM},     {0x6ee, 0x6ef, direction::AL},
8371
    {0x6f0, 0x6f9, direction::EN},      {0x6fa, 0x70d, direction::AL},
8372
    {0x70f, 0x710, direction::AL},      {0x711, 0x711, direction::NSM},
8373
    {0x712, 0x72f, direction::AL},      {0x730, 0x74a, direction::NSM},
8374
    {0x74d, 0x7a5, direction::AL},      {0x7a6, 0x7b0, direction::NSM},
8375
    {0x7b1, 0x7b1, direction::AL},      {0x7c0, 0x7ea, direction::R},
8376
    {0x7eb, 0x7f3, direction::NSM},     {0x7f4, 0x7f5, direction::R},
8377
    {0x7f6, 0x7f9, direction::ON},      {0x7fa, 0x7fa, direction::R},
8378
    {0x7fd, 0x7fd, direction::NSM},     {0x7fe, 0x815, direction::R},
8379
    {0x816, 0x819, direction::NSM},     {0x81a, 0x81a, direction::R},
8380
    {0x81b, 0x823, direction::NSM},     {0x824, 0x824, direction::R},
8381
    {0x825, 0x827, direction::NSM},     {0x828, 0x828, direction::R},
8382
    {0x829, 0x82d, direction::NSM},     {0x830, 0x83e, direction::R},
8383
    {0x840, 0x858, direction::R},       {0x859, 0x85b, direction::NSM},
8384
    {0x85e, 0x85e, direction::R},       {0x860, 0x86a, direction::AL},
8385
    {0x8a0, 0x8b4, direction::AL},      {0x8b6, 0x8c7, direction::AL},
8386
    {0x8d3, 0x8e1, direction::NSM},     {0x8e2, 0x8e2, direction::AN},
8387
    {0x8e3, 0x902, direction::NSM},     {0x903, 0x939, direction::L},
8388
    {0x93a, 0x93a, direction::NSM},     {0x93b, 0x93b, direction::L},
8389
    {0x93c, 0x93c, direction::NSM},     {0x93d, 0x940, direction::L},
8390
    {0x941, 0x948, direction::NSM},     {0x949, 0x94c, direction::L},
8391
    {0x94d, 0x94d, direction::NSM},     {0x94e, 0x950, direction::L},
8392
    {0x951, 0x957, direction::NSM},     {0x958, 0x961, direction::L},
8393
    {0x962, 0x963, direction::NSM},     {0x964, 0x980, direction::L},
8394
    {0x981, 0x981, direction::NSM},     {0x982, 0x983, direction::L},
8395
    {0x985, 0x98c, direction::L},       {0x98f, 0x990, direction::L},
8396
    {0x993, 0x9a8, direction::L},       {0x9aa, 0x9b0, direction::L},
8397
    {0x9b2, 0x9b2, direction::L},       {0x9b6, 0x9b9, direction::L},
8398
    {0x9bc, 0x9bc, direction::NSM},     {0x9bd, 0x9c0, direction::L},
8399
    {0x9c1, 0x9c4, direction::NSM},     {0x9c7, 0x9c8, direction::L},
8400
    {0x9cb, 0x9cc, direction::L},       {0x9cd, 0x9cd, direction::NSM},
8401
    {0x9ce, 0x9ce, direction::L},       {0x9d7, 0x9d7, direction::L},
8402
    {0x9dc, 0x9dd, direction::L},       {0x9df, 0x9e1, direction::L},
8403
    {0x9e2, 0x9e3, direction::NSM},     {0x9e6, 0x9f1, direction::L},
8404
    {0x9f2, 0x9f3, direction::ET},      {0x9f4, 0x9fa, direction::L},
8405
    {0x9fb, 0x9fb, direction::ET},      {0x9fc, 0x9fd, direction::L},
8406
    {0x9fe, 0x9fe, direction::NSM},     {0xa01, 0xa02, direction::NSM},
8407
    {0xa03, 0xa03, direction::L},       {0xa05, 0xa0a, direction::L},
8408
    {0xa0f, 0xa10, direction::L},       {0xa13, 0xa28, direction::L},
8409
    {0xa2a, 0xa30, direction::L},       {0xa32, 0xa33, direction::L},
8410
    {0xa35, 0xa36, direction::L},       {0xa38, 0xa39, direction::L},
8411
    {0xa3c, 0xa3c, direction::NSM},     {0xa3e, 0xa40, direction::L},
8412
    {0xa41, 0xa42, direction::NSM},     {0xa47, 0xa48, direction::NSM},
8413
    {0xa4b, 0xa4d, direction::NSM},     {0xa51, 0xa51, direction::NSM},
8414
    {0xa59, 0xa5c, direction::L},       {0xa5e, 0xa5e, direction::L},
8415
    {0xa66, 0xa6f, direction::L},       {0xa70, 0xa71, direction::NSM},
8416
    {0xa72, 0xa74, direction::L},       {0xa75, 0xa75, direction::NSM},
8417
    {0xa76, 0xa76, direction::L},       {0xa81, 0xa82, direction::NSM},
8418
    {0xa83, 0xa83, direction::L},       {0xa85, 0xa8d, direction::L},
8419
    {0xa8f, 0xa91, direction::L},       {0xa93, 0xaa8, direction::L},
8420
    {0xaaa, 0xab0, direction::L},       {0xab2, 0xab3, direction::L},
8421
    {0xab5, 0xab9, direction::L},       {0xabc, 0xabc, direction::NSM},
8422
    {0xabd, 0xac0, direction::L},       {0xac1, 0xac5, direction::NSM},
8423
    {0xac7, 0xac8, direction::NSM},     {0xac9, 0xac9, direction::L},
8424
    {0xacb, 0xacc, direction::L},       {0xacd, 0xacd, direction::NSM},
8425
    {0xad0, 0xad0, direction::L},       {0xae0, 0xae1, direction::L},
8426
    {0xae2, 0xae3, direction::NSM},     {0xae6, 0xaf0, direction::L},
8427
    {0xaf1, 0xaf1, direction::ET},      {0xaf9, 0xaf9, direction::L},
8428
    {0xafa, 0xaff, direction::NSM},     {0xb01, 0xb01, direction::NSM},
8429
    {0xb02, 0xb03, direction::L},       {0xb05, 0xb0c, direction::L},
8430
    {0xb0f, 0xb10, direction::L},       {0xb13, 0xb28, direction::L},
8431
    {0xb2a, 0xb30, direction::L},       {0xb32, 0xb33, direction::L},
8432
    {0xb35, 0xb39, direction::L},       {0xb3c, 0xb3c, direction::NSM},
8433
    {0xb3d, 0xb3e, direction::L},       {0xb3f, 0xb3f, direction::NSM},
8434
    {0xb40, 0xb40, direction::L},       {0xb41, 0xb44, direction::NSM},
8435
    {0xb47, 0xb48, direction::L},       {0xb4b, 0xb4c, direction::L},
8436
    {0xb4d, 0xb4d, direction::NSM},     {0xb55, 0xb56, direction::NSM},
8437
    {0xb57, 0xb57, direction::L},       {0xb5c, 0xb5d, direction::L},
8438
    {0xb5f, 0xb61, direction::L},       {0xb62, 0xb63, direction::NSM},
8439
    {0xb66, 0xb77, direction::L},       {0xb82, 0xb82, direction::NSM},
8440
    {0xb83, 0xb83, direction::L},       {0xb85, 0xb8a, direction::L},
8441
    {0xb8e, 0xb90, direction::L},       {0xb92, 0xb95, direction::L},
8442
    {0xb99, 0xb9a, direction::L},       {0xb9c, 0xb9c, direction::L},
8443
    {0xb9e, 0xb9f, direction::L},       {0xba3, 0xba4, direction::L},
8444
    {0xba8, 0xbaa, direction::L},       {0xbae, 0xbb9, direction::L},
8445
    {0xbbe, 0xbbf, direction::L},       {0xbc0, 0xbc0, direction::NSM},
8446
    {0xbc1, 0xbc2, direction::L},       {0xbc6, 0xbc8, direction::L},
8447
    {0xbca, 0xbcc, direction::L},       {0xbcd, 0xbcd, direction::NSM},
8448
    {0xbd0, 0xbd0, direction::L},       {0xbd7, 0xbd7, direction::L},
8449
    {0xbe6, 0xbf2, direction::L},       {0xbf3, 0xbf8, direction::ON},
8450
    {0xbf9, 0xbf9, direction::ET},      {0xbfa, 0xbfa, direction::ON},
8451
    {0xc00, 0xc00, direction::NSM},     {0xc01, 0xc03, direction::L},
8452
    {0xc04, 0xc04, direction::NSM},     {0xc05, 0xc0c, direction::L},
8453
    {0xc0e, 0xc10, direction::L},       {0xc12, 0xc28, direction::L},
8454
    {0xc2a, 0xc39, direction::L},       {0xc3d, 0xc3d, direction::L},
8455
    {0xc3e, 0xc40, direction::NSM},     {0xc41, 0xc44, direction::L},
8456
    {0xc46, 0xc48, direction::NSM},     {0xc4a, 0xc4d, direction::NSM},
8457
    {0xc55, 0xc56, direction::NSM},     {0xc58, 0xc5a, direction::L},
8458
    {0xc60, 0xc61, direction::L},       {0xc62, 0xc63, direction::NSM},
8459
    {0xc66, 0xc6f, direction::L},       {0xc77, 0xc77, direction::L},
8460
    {0xc78, 0xc7e, direction::ON},      {0xc7f, 0xc80, direction::L},
8461
    {0xc81, 0xc81, direction::NSM},     {0xc82, 0xc8c, direction::L},
8462
    {0xc8e, 0xc90, direction::L},       {0xc92, 0xca8, direction::L},
8463
    {0xcaa, 0xcb3, direction::L},       {0xcb5, 0xcb9, direction::L},
8464
    {0xcbc, 0xcbc, direction::NSM},     {0xcbd, 0xcc4, direction::L},
8465
    {0xcc6, 0xcc8, direction::L},       {0xcca, 0xccb, direction::L},
8466
    {0xccc, 0xccd, direction::NSM},     {0xcd5, 0xcd6, direction::L},
8467
    {0xcde, 0xcde, direction::L},       {0xce0, 0xce1, direction::L},
8468
    {0xce2, 0xce3, direction::NSM},     {0xce6, 0xcef, direction::L},
8469
    {0xcf1, 0xcf2, direction::L},       {0xd00, 0xd01, direction::NSM},
8470
    {0xd02, 0xd0c, direction::L},       {0xd0e, 0xd10, direction::L},
8471
    {0xd12, 0xd3a, direction::L},       {0xd3b, 0xd3c, direction::NSM},
8472
    {0xd3d, 0xd40, direction::L},       {0xd41, 0xd44, direction::NSM},
8473
    {0xd46, 0xd48, direction::L},       {0xd4a, 0xd4c, direction::L},
8474
    {0xd4d, 0xd4d, direction::NSM},     {0xd4e, 0xd4f, direction::L},
8475
    {0xd54, 0xd61, direction::L},       {0xd62, 0xd63, direction::NSM},
8476
    {0xd66, 0xd7f, direction::L},       {0xd81, 0xd81, direction::NSM},
8477
    {0xd82, 0xd83, direction::L},       {0xd85, 0xd96, direction::L},
8478
    {0xd9a, 0xdb1, direction::L},       {0xdb3, 0xdbb, direction::L},
8479
    {0xdbd, 0xdbd, direction::L},       {0xdc0, 0xdc6, direction::L},
8480
    {0xdca, 0xdca, direction::NSM},     {0xdcf, 0xdd1, direction::L},
8481
    {0xdd2, 0xdd4, direction::NSM},     {0xdd6, 0xdd6, direction::NSM},
8482
    {0xdd8, 0xddf, direction::L},       {0xde6, 0xdef, direction::L},
8483
    {0xdf2, 0xdf4, direction::L},       {0xe01, 0xe30, direction::L},
8484
    {0xe31, 0xe31, direction::NSM},     {0xe32, 0xe33, direction::L},
8485
    {0xe34, 0xe3a, direction::NSM},     {0xe3f, 0xe3f, direction::ET},
8486
    {0xe40, 0xe46, direction::L},       {0xe47, 0xe4e, direction::NSM},
8487
    {0xe4f, 0xe5b, direction::L},       {0xe81, 0xe82, direction::L},
8488
    {0xe84, 0xe84, direction::L},       {0xe86, 0xe8a, direction::L},
8489
    {0xe8c, 0xea3, direction::L},       {0xea5, 0xea5, direction::L},
8490
    {0xea7, 0xeb0, direction::L},       {0xeb1, 0xeb1, direction::NSM},
8491
    {0xeb2, 0xeb3, direction::L},       {0xeb4, 0xebc, direction::NSM},
8492
    {0xebd, 0xebd, direction::L},       {0xec0, 0xec4, direction::L},
8493
    {0xec6, 0xec6, direction::L},       {0xec8, 0xecd, direction::NSM},
8494
    {0xed0, 0xed9, direction::L},       {0xedc, 0xedf, direction::L},
8495
    {0xf00, 0xf17, direction::L},       {0xf18, 0xf19, direction::NSM},
8496
    {0xf1a, 0xf34, direction::L},       {0xf35, 0xf35, direction::NSM},
8497
    {0xf36, 0xf36, direction::L},       {0xf37, 0xf37, direction::NSM},
8498
    {0xf38, 0xf38, direction::L},       {0xf39, 0xf39, direction::NSM},
8499
    {0xf3a, 0xf3d, direction::ON},      {0xf3e, 0xf47, direction::L},
8500
    {0xf49, 0xf6c, direction::L},       {0xf71, 0xf7e, direction::NSM},
8501
    {0xf7f, 0xf7f, direction::L},       {0xf80, 0xf84, direction::NSM},
8502
    {0xf85, 0xf85, direction::L},       {0xf86, 0xf87, direction::NSM},
8503
    {0xf88, 0xf8c, direction::L},       {0xf8d, 0xf97, direction::NSM},
8504
    {0xf99, 0xfbc, direction::NSM},     {0xfbe, 0xfc5, direction::L},
8505
    {0xfc6, 0xfc6, direction::NSM},     {0xfc7, 0xfcc, direction::L},
8506
    {0xfce, 0xfda, direction::L},       {0x1000, 0x102c, direction::L},
8507
    {0x102d, 0x1030, direction::NSM},   {0x1031, 0x1031, direction::L},
8508
    {0x1032, 0x1037, direction::NSM},   {0x1038, 0x1038, direction::L},
8509
    {0x1039, 0x103a, direction::NSM},   {0x103b, 0x103c, direction::L},
8510
    {0x103d, 0x103e, direction::NSM},   {0x103f, 0x1057, direction::L},
8511
    {0x1058, 0x1059, direction::NSM},   {0x105a, 0x105d, direction::L},
8512
    {0x105e, 0x1060, direction::NSM},   {0x1061, 0x1070, direction::L},
8513
    {0x1071, 0x1074, direction::NSM},   {0x1075, 0x1081, direction::L},
8514
    {0x1082, 0x1082, direction::NSM},   {0x1083, 0x1084, direction::L},
8515
    {0x1085, 0x1086, direction::NSM},   {0x1087, 0x108c, direction::L},
8516
    {0x108d, 0x108d, direction::NSM},   {0x108e, 0x109c, direction::L},
8517
    {0x109d, 0x109d, direction::NSM},   {0x109e, 0x10c5, direction::L},
8518
    {0x10c7, 0x10c7, direction::L},     {0x10cd, 0x10cd, direction::L},
8519
    {0x10d0, 0x1248, direction::L},     {0x124a, 0x124d, direction::L},
8520
    {0x1250, 0x1256, direction::L},     {0x1258, 0x1258, direction::L},
8521
    {0x125a, 0x125d, direction::L},     {0x1260, 0x1288, direction::L},
8522
    {0x128a, 0x128d, direction::L},     {0x1290, 0x12b0, direction::L},
8523
    {0x12b2, 0x12b5, direction::L},     {0x12b8, 0x12be, direction::L},
8524
    {0x12c0, 0x12c0, direction::L},     {0x12c2, 0x12c5, direction::L},
8525
    {0x12c8, 0x12d6, direction::L},     {0x12d8, 0x1310, direction::L},
8526
    {0x1312, 0x1315, direction::L},     {0x1318, 0x135a, direction::L},
8527
    {0x135d, 0x135f, direction::NSM},   {0x1360, 0x137c, direction::L},
8528
    {0x1380, 0x138f, direction::L},     {0x1390, 0x1399, direction::ON},
8529
    {0x13a0, 0x13f5, direction::L},     {0x13f8, 0x13fd, direction::L},
8530
    {0x1400, 0x1400, direction::ON},    {0x1401, 0x167f, direction::L},
8531
    {0x1680, 0x1680, direction::WS},    {0x1681, 0x169a, direction::L},
8532
    {0x169b, 0x169c, direction::ON},    {0x16a0, 0x16f8, direction::L},
8533
    {0x1700, 0x170c, direction::L},     {0x170e, 0x1711, direction::L},
8534
    {0x1712, 0x1714, direction::NSM},   {0x1720, 0x1731, direction::L},
8535
    {0x1732, 0x1734, direction::NSM},   {0x1735, 0x1736, direction::L},
8536
    {0x1740, 0x1751, direction::L},     {0x1752, 0x1753, direction::NSM},
8537
    {0x1760, 0x176c, direction::L},     {0x176e, 0x1770, direction::L},
8538
    {0x1772, 0x1773, direction::NSM},   {0x1780, 0x17b3, direction::L},
8539
    {0x17b4, 0x17b5, direction::NSM},   {0x17b6, 0x17b6, direction::L},
8540
    {0x17b7, 0x17bd, direction::NSM},   {0x17be, 0x17c5, direction::L},
8541
    {0x17c6, 0x17c6, direction::NSM},   {0x17c7, 0x17c8, direction::L},
8542
    {0x17c9, 0x17d3, direction::NSM},   {0x17d4, 0x17da, direction::L},
8543
    {0x17db, 0x17db, direction::ET},    {0x17dc, 0x17dc, direction::L},
8544
    {0x17dd, 0x17dd, direction::NSM},   {0x17e0, 0x17e9, direction::L},
8545
    {0x17f0, 0x17f9, direction::ON},    {0x1800, 0x180a, direction::ON},
8546
    {0x180b, 0x180d, direction::NSM},   {0x180e, 0x180e, direction::BN},
8547
    {0x1810, 0x1819, direction::L},     {0x1820, 0x1878, direction::L},
8548
    {0x1880, 0x1884, direction::L},     {0x1885, 0x1886, direction::NSM},
8549
    {0x1887, 0x18a8, direction::L},     {0x18a9, 0x18a9, direction::NSM},
8550
    {0x18aa, 0x18aa, direction::L},     {0x18b0, 0x18f5, direction::L},
8551
    {0x1900, 0x191e, direction::L},     {0x1920, 0x1922, direction::NSM},
8552
    {0x1923, 0x1926, direction::L},     {0x1927, 0x1928, direction::NSM},
8553
    {0x1929, 0x192b, direction::L},     {0x1930, 0x1931, direction::L},
8554
    {0x1932, 0x1932, direction::NSM},   {0x1933, 0x1938, direction::L},
8555
    {0x1939, 0x193b, direction::NSM},   {0x1940, 0x1940, direction::ON},
8556
    {0x1944, 0x1945, direction::ON},    {0x1946, 0x196d, direction::L},
8557
    {0x1970, 0x1974, direction::L},     {0x1980, 0x19ab, direction::L},
8558
    {0x19b0, 0x19c9, direction::L},     {0x19d0, 0x19da, direction::L},
8559
    {0x19de, 0x19ff, direction::ON},    {0x1a00, 0x1a16, direction::L},
8560
    {0x1a17, 0x1a18, direction::NSM},   {0x1a19, 0x1a1a, direction::L},
8561
    {0x1a1b, 0x1a1b, direction::NSM},   {0x1a1e, 0x1a55, direction::L},
8562
    {0x1a56, 0x1a56, direction::NSM},   {0x1a57, 0x1a57, direction::L},
8563
    {0x1a58, 0x1a5e, direction::NSM},   {0x1a60, 0x1a60, direction::NSM},
8564
    {0x1a61, 0x1a61, direction::L},     {0x1a62, 0x1a62, direction::NSM},
8565
    {0x1a63, 0x1a64, direction::L},     {0x1a65, 0x1a6c, direction::NSM},
8566
    {0x1a6d, 0x1a72, direction::L},     {0x1a73, 0x1a7c, direction::NSM},
8567
    {0x1a7f, 0x1a7f, direction::NSM},   {0x1a80, 0x1a89, direction::L},
8568
    {0x1a90, 0x1a99, direction::L},     {0x1aa0, 0x1aad, direction::L},
8569
    {0x1ab0, 0x1ac0, direction::NSM},   {0x1b00, 0x1b03, direction::NSM},
8570
    {0x1b04, 0x1b33, direction::L},     {0x1b34, 0x1b34, direction::NSM},
8571
    {0x1b35, 0x1b35, direction::L},     {0x1b36, 0x1b3a, direction::NSM},
8572
    {0x1b3b, 0x1b3b, direction::L},     {0x1b3c, 0x1b3c, direction::NSM},
8573
    {0x1b3d, 0x1b41, direction::L},     {0x1b42, 0x1b42, direction::NSM},
8574
    {0x1b43, 0x1b4b, direction::L},     {0x1b50, 0x1b6a, direction::L},
8575
    {0x1b6b, 0x1b73, direction::NSM},   {0x1b74, 0x1b7c, direction::L},
8576
    {0x1b80, 0x1b81, direction::NSM},   {0x1b82, 0x1ba1, direction::L},
8577
    {0x1ba2, 0x1ba5, direction::NSM},   {0x1ba6, 0x1ba7, direction::L},
8578
    {0x1ba8, 0x1ba9, direction::NSM},   {0x1baa, 0x1baa, direction::L},
8579
    {0x1bab, 0x1bad, direction::NSM},   {0x1bae, 0x1be5, direction::L},
8580
    {0x1be6, 0x1be6, direction::NSM},   {0x1be7, 0x1be7, direction::L},
8581
    {0x1be8, 0x1be9, direction::NSM},   {0x1bea, 0x1bec, direction::L},
8582
    {0x1bed, 0x1bed, direction::NSM},   {0x1bee, 0x1bee, direction::L},
8583
    {0x1bef, 0x1bf1, direction::NSM},   {0x1bf2, 0x1bf3, direction::L},
8584
    {0x1bfc, 0x1c2b, direction::L},     {0x1c2c, 0x1c33, direction::NSM},
8585
    {0x1c34, 0x1c35, direction::L},     {0x1c36, 0x1c37, direction::NSM},
8586
    {0x1c3b, 0x1c49, direction::L},     {0x1c4d, 0x1c88, direction::L},
8587
    {0x1c90, 0x1cba, direction::L},     {0x1cbd, 0x1cc7, direction::L},
8588
    {0x1cd0, 0x1cd2, direction::NSM},   {0x1cd3, 0x1cd3, direction::L},
8589
    {0x1cd4, 0x1ce0, direction::NSM},   {0x1ce1, 0x1ce1, direction::L},
8590
    {0x1ce2, 0x1ce8, direction::NSM},   {0x1ce9, 0x1cec, direction::L},
8591
    {0x1ced, 0x1ced, direction::NSM},   {0x1cee, 0x1cf3, direction::L},
8592
    {0x1cf4, 0x1cf4, direction::NSM},   {0x1cf5, 0x1cf7, direction::L},
8593
    {0x1cf8, 0x1cf9, direction::NSM},   {0x1cfa, 0x1cfa, direction::L},
8594
    {0x1d00, 0x1dbf, direction::L},     {0x1dc0, 0x1df9, direction::NSM},
8595
    {0x1dfb, 0x1dff, direction::NSM},   {0x1e00, 0x1f15, direction::L},
8596
    {0x1f18, 0x1f1d, direction::L},     {0x1f20, 0x1f45, direction::L},
8597
    {0x1f48, 0x1f4d, direction::L},     {0x1f50, 0x1f57, direction::L},
8598
    {0x1f59, 0x1f59, direction::L},     {0x1f5b, 0x1f5b, direction::L},
8599
    {0x1f5d, 0x1f5d, direction::L},     {0x1f5f, 0x1f7d, direction::L},
8600
    {0x1f80, 0x1fb4, direction::L},     {0x1fb6, 0x1fbc, direction::L},
8601
    {0x1fbd, 0x1fbd, direction::ON},    {0x1fbe, 0x1fbe, direction::L},
8602
    {0x1fbf, 0x1fc1, direction::ON},    {0x1fc2, 0x1fc4, direction::L},
8603
    {0x1fc6, 0x1fcc, direction::L},     {0x1fcd, 0x1fcf, direction::ON},
8604
    {0x1fd0, 0x1fd3, direction::L},     {0x1fd6, 0x1fdb, direction::L},
8605
    {0x1fdd, 0x1fdf, direction::ON},    {0x1fe0, 0x1fec, direction::L},
8606
    {0x1fed, 0x1fef, direction::ON},    {0x1ff2, 0x1ff4, direction::L},
8607
    {0x1ff6, 0x1ffc, direction::L},     {0x1ffd, 0x1ffe, direction::ON},
8608
    {0x2000, 0x200a, direction::WS},    {0x200b, 0x200d, direction::BN},
8609
    {0x200e, 0x200e, direction::L},     {0x200f, 0x200f, direction::R},
8610
    {0x2010, 0x2027, direction::ON},    {0x2028, 0x2028, direction::WS},
8611
    {0x2029, 0x2029, direction::B},     {0x202a, 0x202a, direction::LRE},
8612
    {0x202b, 0x202b, direction::RLE},   {0x202c, 0x202c, direction::PDF},
8613
    {0x202d, 0x202d, direction::LRO},   {0x202e, 0x202e, direction::RLO},
8614
    {0x202f, 0x202f, direction::CS},    {0x2030, 0x2034, direction::ET},
8615
    {0x2035, 0x2043, direction::ON},    {0x2044, 0x2044, direction::CS},
8616
    {0x2045, 0x205e, direction::ON},    {0x205f, 0x205f, direction::WS},
8617
    {0x2060, 0x2064, direction::BN},    {0x2066, 0x2066, direction::LRI},
8618
    {0x2067, 0x2067, direction::RLI},   {0x2068, 0x2068, direction::FSI},
8619
    {0x2069, 0x2069, direction::PDI},   {0x206a, 0x206f, direction::BN},
8620
    {0x2070, 0x2070, direction::EN},    {0x2071, 0x2071, direction::L},
8621
    {0x2074, 0x2079, direction::EN},    {0x207a, 0x207b, direction::ES},
8622
    {0x207c, 0x207e, direction::ON},    {0x207f, 0x207f, direction::L},
8623
    {0x2080, 0x2089, direction::EN},    {0x208a, 0x208b, direction::ES},
8624
    {0x208c, 0x208e, direction::ON},    {0x2090, 0x209c, direction::L},
8625
    {0x20a0, 0x20bf, direction::ET},    {0x20d0, 0x20f0, direction::NSM},
8626
    {0x2100, 0x2101, direction::ON},    {0x2102, 0x2102, direction::L},
8627
    {0x2103, 0x2106, direction::ON},    {0x2107, 0x2107, direction::L},
8628
    {0x2108, 0x2109, direction::ON},    {0x210a, 0x2113, direction::L},
8629
    {0x2114, 0x2114, direction::ON},    {0x2115, 0x2115, direction::L},
8630
    {0x2116, 0x2118, direction::ON},    {0x2119, 0x211d, direction::L},
8631
    {0x211e, 0x2123, direction::ON},    {0x2124, 0x2124, direction::L},
8632
    {0x2125, 0x2125, direction::ON},    {0x2126, 0x2126, direction::L},
8633
    {0x2127, 0x2127, direction::ON},    {0x2128, 0x2128, direction::L},
8634
    {0x2129, 0x2129, direction::ON},    {0x212a, 0x212d, direction::L},
8635
    {0x212e, 0x212e, direction::ET},    {0x212f, 0x2139, direction::L},
8636
    {0x213a, 0x213b, direction::ON},    {0x213c, 0x213f, direction::L},
8637
    {0x2140, 0x2144, direction::ON},    {0x2145, 0x2149, direction::L},
8638
    {0x214a, 0x214d, direction::ON},    {0x214e, 0x214f, direction::L},
8639
    {0x2150, 0x215f, direction::ON},    {0x2160, 0x2188, direction::L},
8640
    {0x2189, 0x218b, direction::ON},    {0x2190, 0x2211, direction::ON},
8641
    {0x2212, 0x2212, direction::ES},    {0x2213, 0x2213, direction::ET},
8642
    {0x2214, 0x2335, direction::ON},    {0x2336, 0x237a, direction::L},
8643
    {0x237b, 0x2394, direction::ON},    {0x2395, 0x2395, direction::L},
8644
    {0x2396, 0x2426, direction::ON},    {0x2440, 0x244a, direction::ON},
8645
    {0x2460, 0x2487, direction::ON},    {0x2488, 0x249b, direction::EN},
8646
    {0x249c, 0x24e9, direction::L},     {0x24ea, 0x26ab, direction::ON},
8647
    {0x26ac, 0x26ac, direction::L},     {0x26ad, 0x27ff, direction::ON},
8648
    {0x2800, 0x28ff, direction::L},     {0x2900, 0x2b73, direction::ON},
8649
    {0x2b76, 0x2b95, direction::ON},    {0x2b97, 0x2bff, direction::ON},
8650
    {0x2c00, 0x2c2e, direction::L},     {0x2c30, 0x2c5e, direction::L},
8651
    {0x2c60, 0x2ce4, direction::L},     {0x2ce5, 0x2cea, direction::ON},
8652
    {0x2ceb, 0x2cee, direction::L},     {0x2cef, 0x2cf1, direction::NSM},
8653
    {0x2cf2, 0x2cf3, direction::L},     {0x2cf9, 0x2cff, direction::ON},
8654
    {0x2d00, 0x2d25, direction::L},     {0x2d27, 0x2d27, direction::L},
8655
    {0x2d2d, 0x2d2d, direction::L},     {0x2d30, 0x2d67, direction::L},
8656
    {0x2d6f, 0x2d70, direction::L},     {0x2d7f, 0x2d7f, direction::NSM},
8657
    {0x2d80, 0x2d96, direction::L},     {0x2da0, 0x2da6, direction::L},
8658
    {0x2da8, 0x2dae, direction::L},     {0x2db0, 0x2db6, direction::L},
8659
    {0x2db8, 0x2dbe, direction::L},     {0x2dc0, 0x2dc6, direction::L},
8660
    {0x2dc8, 0x2dce, direction::L},     {0x2dd0, 0x2dd6, direction::L},
8661
    {0x2dd8, 0x2dde, direction::L},     {0x2de0, 0x2dff, direction::NSM},
8662
    {0x2e00, 0x2e52, direction::ON},    {0x2e80, 0x2e99, direction::ON},
8663
    {0x2e9b, 0x2ef3, direction::ON},    {0x2f00, 0x2fd5, direction::ON},
8664
    {0x2ff0, 0x2ffb, direction::ON},    {0x3000, 0x3000, direction::WS},
8665
    {0x3001, 0x3004, direction::ON},    {0x3005, 0x3007, direction::L},
8666
    {0x3008, 0x3020, direction::ON},    {0x3021, 0x3029, direction::L},
8667
    {0x302a, 0x302d, direction::NSM},   {0x302e, 0x302f, direction::L},
8668
    {0x3030, 0x3030, direction::ON},    {0x3031, 0x3035, direction::L},
8669
    {0x3036, 0x3037, direction::ON},    {0x3038, 0x303c, direction::L},
8670
    {0x303d, 0x303f, direction::ON},    {0x3041, 0x3096, direction::L},
8671
    {0x3099, 0x309a, direction::NSM},   {0x309b, 0x309c, direction::ON},
8672
    {0x309d, 0x309f, direction::L},     {0x30a0, 0x30a0, direction::ON},
8673
    {0x30a1, 0x30fa, direction::L},     {0x30fb, 0x30fb, direction::ON},
8674
    {0x30fc, 0x30ff, direction::L},     {0x3105, 0x312f, direction::L},
8675
    {0x3131, 0x318e, direction::L},     {0x3190, 0x31bf, direction::L},
8676
    {0x31c0, 0x31e3, direction::ON},    {0x31f0, 0x321c, direction::L},
8677
    {0x321d, 0x321e, direction::ON},    {0x3220, 0x324f, direction::L},
8678
    {0x3250, 0x325f, direction::ON},    {0x3260, 0x327b, direction::L},
8679
    {0x327c, 0x327e, direction::ON},    {0x327f, 0x32b0, direction::L},
8680
    {0x32b1, 0x32bf, direction::ON},    {0x32c0, 0x32cb, direction::L},
8681
    {0x32cc, 0x32cf, direction::ON},    {0x32d0, 0x3376, direction::L},
8682
    {0x3377, 0x337a, direction::ON},    {0x337b, 0x33dd, direction::L},
8683
    {0x33de, 0x33df, direction::ON},    {0x33e0, 0x33fe, direction::L},
8684
    {0x33ff, 0x33ff, direction::ON},    {0x3400, 0x4dbf, direction::L},
8685
    {0x4dc0, 0x4dff, direction::ON},    {0x4e00, 0x9ffc, direction::L},
8686
    {0xa000, 0xa48c, direction::L},     {0xa490, 0xa4c6, direction::ON},
8687
    {0xa4d0, 0xa60c, direction::L},     {0xa60d, 0xa60f, direction::ON},
8688
    {0xa610, 0xa62b, direction::L},     {0xa640, 0xa66e, direction::L},
8689
    {0xa66f, 0xa672, direction::NSM},   {0xa673, 0xa673, direction::ON},
8690
    {0xa674, 0xa67d, direction::NSM},   {0xa67e, 0xa67f, direction::ON},
8691
    {0xa680, 0xa69d, direction::L},     {0xa69e, 0xa69f, direction::NSM},
8692
    {0xa6a0, 0xa6ef, direction::L},     {0xa6f0, 0xa6f1, direction::NSM},
8693
    {0xa6f2, 0xa6f7, direction::L},     {0xa700, 0xa721, direction::ON},
8694
    {0xa722, 0xa787, direction::L},     {0xa788, 0xa788, direction::ON},
8695
    {0xa789, 0xa7bf, direction::L},     {0xa7c2, 0xa7ca, direction::L},
8696
    {0xa7f5, 0xa801, direction::L},     {0xa802, 0xa802, direction::NSM},
8697
    {0xa803, 0xa805, direction::L},     {0xa806, 0xa806, direction::NSM},
8698
    {0xa807, 0xa80a, direction::L},     {0xa80b, 0xa80b, direction::NSM},
8699
    {0xa80c, 0xa824, direction::L},     {0xa825, 0xa826, direction::NSM},
8700
    {0xa827, 0xa827, direction::L},     {0xa828, 0xa82b, direction::ON},
8701
    {0xa82c, 0xa82c, direction::NSM},   {0xa830, 0xa837, direction::L},
8702
    {0xa838, 0xa839, direction::ET},    {0xa840, 0xa873, direction::L},
8703
    {0xa874, 0xa877, direction::ON},    {0xa880, 0xa8c3, direction::L},
8704
    {0xa8c4, 0xa8c5, direction::NSM},   {0xa8ce, 0xa8d9, direction::L},
8705
    {0xa8e0, 0xa8f1, direction::NSM},   {0xa8f2, 0xa8fe, direction::L},
8706
    {0xa8ff, 0xa8ff, direction::NSM},   {0xa900, 0xa925, direction::L},
8707
    {0xa926, 0xa92d, direction::NSM},   {0xa92e, 0xa946, direction::L},
8708
    {0xa947, 0xa951, direction::NSM},   {0xa952, 0xa953, direction::L},
8709
    {0xa95f, 0xa97c, direction::L},     {0xa980, 0xa982, direction::NSM},
8710
    {0xa983, 0xa9b2, direction::L},     {0xa9b3, 0xa9b3, direction::NSM},
8711
    {0xa9b4, 0xa9b5, direction::L},     {0xa9b6, 0xa9b9, direction::NSM},
8712
    {0xa9ba, 0xa9bb, direction::L},     {0xa9bc, 0xa9bd, direction::NSM},
8713
    {0xa9be, 0xa9cd, direction::L},     {0xa9cf, 0xa9d9, direction::L},
8714
    {0xa9de, 0xa9e4, direction::L},     {0xa9e5, 0xa9e5, direction::NSM},
8715
    {0xa9e6, 0xa9fe, direction::L},     {0xaa00, 0xaa28, direction::L},
8716
    {0xaa29, 0xaa2e, direction::NSM},   {0xaa2f, 0xaa30, direction::L},
8717
    {0xaa31, 0xaa32, direction::NSM},   {0xaa33, 0xaa34, direction::L},
8718
    {0xaa35, 0xaa36, direction::NSM},   {0xaa40, 0xaa42, direction::L},
8719
    {0xaa43, 0xaa43, direction::NSM},   {0xaa44, 0xaa4b, direction::L},
8720
    {0xaa4c, 0xaa4c, direction::NSM},   {0xaa4d, 0xaa4d, direction::L},
8721
    {0xaa50, 0xaa59, direction::L},     {0xaa5c, 0xaa7b, direction::L},
8722
    {0xaa7c, 0xaa7c, direction::NSM},   {0xaa7d, 0xaaaf, direction::L},
8723
    {0xaab0, 0xaab0, direction::NSM},   {0xaab1, 0xaab1, direction::L},
8724
    {0xaab2, 0xaab4, direction::NSM},   {0xaab5, 0xaab6, direction::L},
8725
    {0xaab7, 0xaab8, direction::NSM},   {0xaab9, 0xaabd, direction::L},
8726
    {0xaabe, 0xaabf, direction::NSM},   {0xaac0, 0xaac0, direction::L},
8727
    {0xaac1, 0xaac1, direction::NSM},   {0xaac2, 0xaac2, direction::L},
8728
    {0xaadb, 0xaaeb, direction::L},     {0xaaec, 0xaaed, direction::NSM},
8729
    {0xaaee, 0xaaf5, direction::L},     {0xaaf6, 0xaaf6, direction::NSM},
8730
    {0xab01, 0xab06, direction::L},     {0xab09, 0xab0e, direction::L},
8731
    {0xab11, 0xab16, direction::L},     {0xab20, 0xab26, direction::L},
8732
    {0xab28, 0xab2e, direction::L},     {0xab30, 0xab69, direction::L},
8733
    {0xab6a, 0xab6b, direction::ON},    {0xab70, 0xabe4, direction::L},
8734
    {0xabe5, 0xabe5, direction::NSM},   {0xabe6, 0xabe7, direction::L},
8735
    {0xabe8, 0xabe8, direction::NSM},   {0xabe9, 0xabec, direction::L},
8736
    {0xabed, 0xabed, direction::NSM},   {0xabf0, 0xabf9, direction::L},
8737
    {0xac00, 0xd7a3, direction::L},     {0xd7b0, 0xd7c6, direction::L},
8738
    {0xd7cb, 0xd7fb, direction::L},     {0xd800, 0xfa6d, direction::L},
8739
    {0xfa70, 0xfad9, direction::L},     {0xfb00, 0xfb06, direction::L},
8740
    {0xfb13, 0xfb17, direction::L},     {0xfb1d, 0xfb1d, direction::R},
8741
    {0xfb1e, 0xfb1e, direction::NSM},   {0xfb1f, 0xfb28, direction::R},
8742
    {0xfb29, 0xfb29, direction::ES},    {0xfb2a, 0xfb36, direction::R},
8743
    {0xfb38, 0xfb3c, direction::R},     {0xfb3e, 0xfb3e, direction::R},
8744
    {0xfb40, 0xfb41, direction::R},     {0xfb43, 0xfb44, direction::R},
8745
    {0xfb46, 0xfb4f, direction::R},     {0xfb50, 0xfbc1, direction::AL},
8746
    {0xfbd3, 0xfd3d, direction::AL},    {0xfd3e, 0xfd3f, direction::ON},
8747
    {0xfd50, 0xfd8f, direction::AL},    {0xfd92, 0xfdc7, direction::AL},
8748
    {0xfdf0, 0xfdfc, direction::AL},    {0xfdfd, 0xfdfd, direction::ON},
8749
    {0xfe00, 0xfe0f, direction::NSM},   {0xfe10, 0xfe19, direction::ON},
8750
    {0xfe20, 0xfe2f, direction::NSM},   {0xfe30, 0xfe4f, direction::ON},
8751
    {0xfe50, 0xfe50, direction::CS},    {0xfe51, 0xfe51, direction::ON},
8752
    {0xfe52, 0xfe52, direction::CS},    {0xfe54, 0xfe54, direction::ON},
8753
    {0xfe55, 0xfe55, direction::CS},    {0xfe56, 0xfe5e, direction::ON},
8754
    {0xfe5f, 0xfe5f, direction::ET},    {0xfe60, 0xfe61, direction::ON},
8755
    {0xfe62, 0xfe63, direction::ES},    {0xfe64, 0xfe66, direction::ON},
8756
    {0xfe68, 0xfe68, direction::ON},    {0xfe69, 0xfe6a, direction::ET},
8757
    {0xfe6b, 0xfe6b, direction::ON},    {0xfe70, 0xfe74, direction::AL},
8758
    {0xfe76, 0xfefc, direction::AL},    {0xfeff, 0xfeff, direction::BN},
8759
    {0xff01, 0xff02, direction::ON},    {0xff03, 0xff05, direction::ET},
8760
    {0xff06, 0xff0a, direction::ON},    {0xff0b, 0xff0b, direction::ES},
8761
    {0xff0c, 0xff0c, direction::CS},    {0xff0d, 0xff0d, direction::ES},
8762
    {0xff0e, 0xff0f, direction::CS},    {0xff10, 0xff19, direction::EN},
8763
    {0xff1a, 0xff1a, direction::CS},    {0xff1b, 0xff20, direction::ON},
8764
    {0xff21, 0xff3a, direction::L},     {0xff3b, 0xff40, direction::ON},
8765
    {0xff41, 0xff5a, direction::L},     {0xff5b, 0xff65, direction::ON},
8766
    {0xff66, 0xffbe, direction::L},     {0xffc2, 0xffc7, direction::L},
8767
    {0xffca, 0xffcf, direction::L},     {0xffd2, 0xffd7, direction::L},
8768
    {0xffda, 0xffdc, direction::L},     {0xffe0, 0xffe1, direction::ET},
8769
    {0xffe2, 0xffe4, direction::ON},    {0xffe5, 0xffe6, direction::ET},
8770
    {0xffe8, 0xffee, direction::ON},    {0xfff9, 0xfffd, direction::ON},
8771
    {0x10000, 0x1000b, direction::L},   {0x1000d, 0x10026, direction::L},
8772
    {0x10028, 0x1003a, direction::L},   {0x1003c, 0x1003d, direction::L},
8773
    {0x1003f, 0x1004d, direction::L},   {0x10050, 0x1005d, direction::L},
8774
    {0x10080, 0x100fa, direction::L},   {0x10100, 0x10100, direction::L},
8775
    {0x10101, 0x10101, direction::ON},  {0x10102, 0x10102, direction::L},
8776
    {0x10107, 0x10133, direction::L},   {0x10137, 0x1013f, direction::L},
8777
    {0x10140, 0x1018c, direction::ON},  {0x1018d, 0x1018e, direction::L},
8778
    {0x10190, 0x1019c, direction::ON},  {0x101a0, 0x101a0, direction::ON},
8779
    {0x101d0, 0x101fc, direction::L},   {0x101fd, 0x101fd, direction::NSM},
8780
    {0x10280, 0x1029c, direction::L},   {0x102a0, 0x102d0, direction::L},
8781
    {0x102e0, 0x102e0, direction::NSM}, {0x102e1, 0x102fb, direction::EN},
8782
    {0x10300, 0x10323, direction::L},   {0x1032d, 0x1034a, direction::L},
8783
    {0x10350, 0x10375, direction::L},   {0x10376, 0x1037a, direction::NSM},
8784
    {0x10380, 0x1039d, direction::L},   {0x1039f, 0x103c3, direction::L},
8785
    {0x103c8, 0x103d5, direction::L},   {0x10400, 0x1049d, direction::L},
8786
    {0x104a0, 0x104a9, direction::L},   {0x104b0, 0x104d3, direction::L},
8787
    {0x104d8, 0x104fb, direction::L},   {0x10500, 0x10527, direction::L},
8788
    {0x10530, 0x10563, direction::L},   {0x1056f, 0x1056f, direction::L},
8789
    {0x10600, 0x10736, direction::L},   {0x10740, 0x10755, direction::L},
8790
    {0x10760, 0x10767, direction::L},   {0x10800, 0x10805, direction::R},
8791
    {0x10808, 0x10808, direction::R},   {0x1080a, 0x10835, direction::R},
8792
    {0x10837, 0x10838, direction::R},   {0x1083c, 0x1083c, direction::R},
8793
    {0x1083f, 0x10855, direction::R},   {0x10857, 0x1089e, direction::R},
8794
    {0x108a7, 0x108af, direction::R},   {0x108e0, 0x108f2, direction::R},
8795
    {0x108f4, 0x108f5, direction::R},   {0x108fb, 0x1091b, direction::R},
8796
    {0x1091f, 0x1091f, direction::ON},  {0x10920, 0x10939, direction::R},
8797
    {0x1093f, 0x1093f, direction::R},   {0x10980, 0x109b7, direction::R},
8798
    {0x109bc, 0x109cf, direction::R},   {0x109d2, 0x10a00, direction::R},
8799
    {0x10a01, 0x10a03, direction::NSM}, {0x10a05, 0x10a06, direction::NSM},
8800
    {0x10a0c, 0x10a0f, direction::NSM}, {0x10a10, 0x10a13, direction::R},
8801
    {0x10a15, 0x10a17, direction::R},   {0x10a19, 0x10a35, direction::R},
8802
    {0x10a38, 0x10a3a, direction::NSM}, {0x10a3f, 0x10a3f, direction::NSM},
8803
    {0x10a40, 0x10a48, direction::R},   {0x10a50, 0x10a58, direction::R},
8804
    {0x10a60, 0x10a9f, direction::R},   {0x10ac0, 0x10ae4, direction::R},
8805
    {0x10ae5, 0x10ae6, direction::NSM}, {0x10aeb, 0x10af6, direction::R},
8806
    {0x10b00, 0x10b35, direction::R},   {0x10b39, 0x10b3f, direction::ON},
8807
    {0x10b40, 0x10b55, direction::R},   {0x10b58, 0x10b72, direction::R},
8808
    {0x10b78, 0x10b91, direction::R},   {0x10b99, 0x10b9c, direction::R},
8809
    {0x10ba9, 0x10baf, direction::R},   {0x10c00, 0x10c48, direction::R},
8810
    {0x10c80, 0x10cb2, direction::R},   {0x10cc0, 0x10cf2, direction::R},
8811
    {0x10cfa, 0x10cff, direction::R},   {0x10d00, 0x10d23, direction::AL},
8812
    {0x10d24, 0x10d27, direction::NSM}, {0x10d30, 0x10d39, direction::AN},
8813
    {0x10e60, 0x10e7e, direction::AN},  {0x10e80, 0x10ea9, direction::R},
8814
    {0x10eab, 0x10eac, direction::NSM}, {0x10ead, 0x10ead, direction::R},
8815
    {0x10eb0, 0x10eb1, direction::R},   {0x10f00, 0x10f27, direction::R},
8816
    {0x10f30, 0x10f45, direction::AL},  {0x10f46, 0x10f50, direction::NSM},
8817
    {0x10f51, 0x10f59, direction::AL},  {0x10fb0, 0x10fcb, direction::R},
8818
    {0x10fe0, 0x10ff6, direction::R},   {0x11000, 0x11000, direction::L},
8819
    {0x11001, 0x11001, direction::NSM}, {0x11002, 0x11037, direction::L},
8820
    {0x11038, 0x11046, direction::NSM}, {0x11047, 0x1104d, direction::L},
8821
    {0x11052, 0x11065, direction::ON},  {0x11066, 0x1106f, direction::L},
8822
    {0x1107f, 0x11081, direction::NSM}, {0x11082, 0x110b2, direction::L},
8823
    {0x110b3, 0x110b6, direction::NSM}, {0x110b7, 0x110b8, direction::L},
8824
    {0x110b9, 0x110ba, direction::NSM}, {0x110bb, 0x110c1, direction::L},
8825
    {0x110cd, 0x110cd, direction::L},   {0x110d0, 0x110e8, direction::L},
8826
    {0x110f0, 0x110f9, direction::L},   {0x11100, 0x11102, direction::NSM},
8827
    {0x11103, 0x11126, direction::L},   {0x11127, 0x1112b, direction::NSM},
8828
    {0x1112c, 0x1112c, direction::L},   {0x1112d, 0x11134, direction::NSM},
8829
    {0x11136, 0x11147, direction::L},   {0x11150, 0x11172, direction::L},
8830
    {0x11173, 0x11173, direction::NSM}, {0x11174, 0x11176, direction::L},
8831
    {0x11180, 0x11181, direction::NSM}, {0x11182, 0x111b5, direction::L},
8832
    {0x111b6, 0x111be, direction::NSM}, {0x111bf, 0x111c8, direction::L},
8833
    {0x111c9, 0x111cc, direction::NSM}, {0x111cd, 0x111ce, direction::L},
8834
    {0x111cf, 0x111cf, direction::NSM}, {0x111d0, 0x111df, direction::L},
8835
    {0x111e1, 0x111f4, direction::L},   {0x11200, 0x11211, direction::L},
8836
    {0x11213, 0x1122e, direction::L},   {0x1122f, 0x11231, direction::NSM},
8837
    {0x11232, 0x11233, direction::L},   {0x11234, 0x11234, direction::NSM},
8838
    {0x11235, 0x11235, direction::L},   {0x11236, 0x11237, direction::NSM},
8839
    {0x11238, 0x1123d, direction::L},   {0x1123e, 0x1123e, direction::NSM},
8840
    {0x11280, 0x11286, direction::L},   {0x11288, 0x11288, direction::L},
8841
    {0x1128a, 0x1128d, direction::L},   {0x1128f, 0x1129d, direction::L},
8842
    {0x1129f, 0x112a9, direction::L},   {0x112b0, 0x112de, direction::L},
8843
    {0x112df, 0x112df, direction::NSM}, {0x112e0, 0x112e2, direction::L},
8844
    {0x112e3, 0x112ea, direction::NSM}, {0x112f0, 0x112f9, direction::L},
8845
    {0x11300, 0x11301, direction::NSM}, {0x11302, 0x11303, direction::L},
8846
    {0x11305, 0x1130c, direction::L},   {0x1130f, 0x11310, direction::L},
8847
    {0x11313, 0x11328, direction::L},   {0x1132a, 0x11330, direction::L},
8848
    {0x11332, 0x11333, direction::L},   {0x11335, 0x11339, direction::L},
8849
    {0x1133b, 0x1133c, direction::NSM}, {0x1133d, 0x1133f, direction::L},
8850
    {0x11340, 0x11340, direction::NSM}, {0x11341, 0x11344, direction::L},
8851
    {0x11347, 0x11348, direction::L},   {0x1134b, 0x1134d, direction::L},
8852
    {0x11350, 0x11350, direction::L},   {0x11357, 0x11357, direction::L},
8853
    {0x1135d, 0x11363, direction::L},   {0x11366, 0x1136c, direction::NSM},
8854
    {0x11370, 0x11374, direction::NSM}, {0x11400, 0x11437, direction::L},
8855
    {0x11438, 0x1143f, direction::NSM}, {0x11440, 0x11441, direction::L},
8856
    {0x11442, 0x11444, direction::NSM}, {0x11445, 0x11445, direction::L},
8857
    {0x11446, 0x11446, direction::NSM}, {0x11447, 0x1145b, direction::L},
8858
    {0x1145d, 0x1145d, direction::L},   {0x1145e, 0x1145e, direction::NSM},
8859
    {0x1145f, 0x11461, direction::L},   {0x11480, 0x114b2, direction::L},
8860
    {0x114b3, 0x114b8, direction::NSM}, {0x114b9, 0x114b9, direction::L},
8861
    {0x114ba, 0x114ba, direction::NSM}, {0x114bb, 0x114be, direction::L},
8862
    {0x114bf, 0x114c0, direction::NSM}, {0x114c1, 0x114c1, direction::L},
8863
    {0x114c2, 0x114c3, direction::NSM}, {0x114c4, 0x114c7, direction::L},
8864
    {0x114d0, 0x114d9, direction::L},   {0x11580, 0x115b1, direction::L},
8865
    {0x115b2, 0x115b5, direction::NSM}, {0x115b8, 0x115bb, direction::L},
8866
    {0x115bc, 0x115bd, direction::NSM}, {0x115be, 0x115be, direction::L},
8867
    {0x115bf, 0x115c0, direction::NSM}, {0x115c1, 0x115db, direction::L},
8868
    {0x115dc, 0x115dd, direction::NSM}, {0x11600, 0x11632, direction::L},
8869
    {0x11633, 0x1163a, direction::NSM}, {0x1163b, 0x1163c, direction::L},
8870
    {0x1163d, 0x1163d, direction::NSM}, {0x1163e, 0x1163e, direction::L},
8871
    {0x1163f, 0x11640, direction::NSM}, {0x11641, 0x11644, direction::L},
8872
    {0x11650, 0x11659, direction::L},   {0x11660, 0x1166c, direction::ON},
8873
    {0x11680, 0x116aa, direction::L},   {0x116ab, 0x116ab, direction::NSM},
8874
    {0x116ac, 0x116ac, direction::L},   {0x116ad, 0x116ad, direction::NSM},
8875
    {0x116ae, 0x116af, direction::L},   {0x116b0, 0x116b5, direction::NSM},
8876
    {0x116b6, 0x116b6, direction::L},   {0x116b7, 0x116b7, direction::NSM},
8877
    {0x116b8, 0x116b8, direction::L},   {0x116c0, 0x116c9, direction::L},
8878
    {0x11700, 0x1171a, direction::L},   {0x1171d, 0x1171f, direction::NSM},
8879
    {0x11720, 0x11721, direction::L},   {0x11722, 0x11725, direction::NSM},
8880
    {0x11726, 0x11726, direction::L},   {0x11727, 0x1172b, direction::NSM},
8881
    {0x11730, 0x1173f, direction::L},   {0x11800, 0x1182e, direction::L},
8882
    {0x1182f, 0x11837, direction::NSM}, {0x11838, 0x11838, direction::L},
8883
    {0x11839, 0x1183a, direction::NSM}, {0x1183b, 0x1183b, direction::L},
8884
    {0x118a0, 0x118f2, direction::L},   {0x118ff, 0x11906, direction::L},
8885
    {0x11909, 0x11909, direction::L},   {0x1190c, 0x11913, direction::L},
8886
    {0x11915, 0x11916, direction::L},   {0x11918, 0x11935, direction::L},
8887
    {0x11937, 0x11938, direction::L},   {0x1193b, 0x1193c, direction::NSM},
8888
    {0x1193d, 0x1193d, direction::L},   {0x1193e, 0x1193e, direction::NSM},
8889
    {0x1193f, 0x11942, direction::L},   {0x11943, 0x11943, direction::NSM},
8890
    {0x11944, 0x11946, direction::L},   {0x11950, 0x11959, direction::L},
8891
    {0x119a0, 0x119a7, direction::L},   {0x119aa, 0x119d3, direction::L},
8892
    {0x119d4, 0x119d7, direction::NSM}, {0x119da, 0x119db, direction::NSM},
8893
    {0x119dc, 0x119df, direction::L},   {0x119e0, 0x119e0, direction::NSM},
8894
    {0x119e1, 0x119e4, direction::L},   {0x11a00, 0x11a00, direction::L},
8895
    {0x11a01, 0x11a06, direction::NSM}, {0x11a07, 0x11a08, direction::L},
8896
    {0x11a09, 0x11a0a, direction::NSM}, {0x11a0b, 0x11a32, direction::L},
8897
    {0x11a33, 0x11a38, direction::NSM}, {0x11a39, 0x11a3a, direction::L},
8898
    {0x11a3b, 0x11a3e, direction::NSM}, {0x11a3f, 0x11a46, direction::L},
8899
    {0x11a47, 0x11a47, direction::NSM}, {0x11a50, 0x11a50, direction::L},
8900
    {0x11a51, 0x11a56, direction::NSM}, {0x11a57, 0x11a58, direction::L},
8901
    {0x11a59, 0x11a5b, direction::NSM}, {0x11a5c, 0x11a89, direction::L},
8902
    {0x11a8a, 0x11a96, direction::NSM}, {0x11a97, 0x11a97, direction::L},
8903
    {0x11a98, 0x11a99, direction::NSM}, {0x11a9a, 0x11aa2, direction::L},
8904
    {0x11ac0, 0x11af8, direction::L},   {0x11c00, 0x11c08, direction::L},
8905
    {0x11c0a, 0x11c2f, direction::L},   {0x11c30, 0x11c36, direction::NSM},
8906
    {0x11c38, 0x11c3d, direction::NSM}, {0x11c3e, 0x11c45, direction::L},
8907
    {0x11c50, 0x11c6c, direction::L},   {0x11c70, 0x11c8f, direction::L},
8908
    {0x11c92, 0x11ca7, direction::NSM}, {0x11ca9, 0x11ca9, direction::L},
8909
    {0x11caa, 0x11cb0, direction::NSM}, {0x11cb1, 0x11cb1, direction::L},
8910
    {0x11cb2, 0x11cb3, direction::NSM}, {0x11cb4, 0x11cb4, direction::L},
8911
    {0x11cb5, 0x11cb6, direction::NSM}, {0x11d00, 0x11d06, direction::L},
8912
    {0x11d08, 0x11d09, direction::L},   {0x11d0b, 0x11d30, direction::L},
8913
    {0x11d31, 0x11d36, direction::NSM}, {0x11d3a, 0x11d3a, direction::NSM},
8914
    {0x11d3c, 0x11d3d, direction::NSM}, {0x11d3f, 0x11d45, direction::NSM},
8915
    {0x11d46, 0x11d46, direction::L},   {0x11d47, 0x11d47, direction::NSM},
8916
    {0x11d50, 0x11d59, direction::L},   {0x11d60, 0x11d65, direction::L},
8917
    {0x11d67, 0x11d68, direction::L},   {0x11d6a, 0x11d8e, direction::L},
8918
    {0x11d90, 0x11d91, direction::NSM}, {0x11d93, 0x11d94, direction::L},
8919
    {0x11d95, 0x11d95, direction::NSM}, {0x11d96, 0x11d96, direction::L},
8920
    {0x11d97, 0x11d97, direction::NSM}, {0x11d98, 0x11d98, direction::L},
8921
    {0x11da0, 0x11da9, direction::L},   {0x11ee0, 0x11ef2, direction::L},
8922
    {0x11ef3, 0x11ef4, direction::NSM}, {0x11ef5, 0x11ef8, direction::L},
8923
    {0x11fb0, 0x11fb0, direction::L},   {0x11fc0, 0x11fd4, direction::L},
8924
    {0x11fd5, 0x11fdc, direction::ON},  {0x11fdd, 0x11fe0, direction::ET},
8925
    {0x11fe1, 0x11ff1, direction::ON},  {0x11fff, 0x12399, direction::L},
8926
    {0x12400, 0x1246e, direction::L},   {0x12470, 0x12474, direction::L},
8927
    {0x12480, 0x12543, direction::L},   {0x13000, 0x1342e, direction::L},
8928
    {0x13430, 0x13438, direction::L},   {0x14400, 0x14646, direction::L},
8929
    {0x16800, 0x16a38, direction::L},   {0x16a40, 0x16a5e, direction::L},
8930
    {0x16a60, 0x16a69, direction::L},   {0x16a6e, 0x16a6f, direction::L},
8931
    {0x16ad0, 0x16aed, direction::L},   {0x16af0, 0x16af4, direction::NSM},
8932
    {0x16af5, 0x16af5, direction::L},   {0x16b00, 0x16b2f, direction::L},
8933
    {0x16b30, 0x16b36, direction::NSM}, {0x16b37, 0x16b45, direction::L},
8934
    {0x16b50, 0x16b59, direction::L},   {0x16b5b, 0x16b61, direction::L},
8935
    {0x16b63, 0x16b77, direction::L},   {0x16b7d, 0x16b8f, direction::L},
8936
    {0x16e40, 0x16e9a, direction::L},   {0x16f00, 0x16f4a, direction::L},
8937
    {0x16f4f, 0x16f4f, direction::NSM}, {0x16f50, 0x16f87, direction::L},
8938
    {0x16f8f, 0x16f92, direction::NSM}, {0x16f93, 0x16f9f, direction::L},
8939
    {0x16fe0, 0x16fe1, direction::L},   {0x16fe2, 0x16fe2, direction::ON},
8940
    {0x16fe3, 0x16fe3, direction::L},   {0x16fe4, 0x16fe4, direction::NSM},
8941
    {0x16ff0, 0x16ff1, direction::L},   {0x17000, 0x187f7, direction::L},
8942
    {0x18800, 0x18cd5, direction::L},   {0x18d00, 0x18d08, direction::L},
8943
    {0x1b000, 0x1b11e, direction::L},   {0x1b150, 0x1b152, direction::L},
8944
    {0x1b164, 0x1b167, direction::L},   {0x1b170, 0x1b2fb, direction::L},
8945
    {0x1bc00, 0x1bc6a, direction::L},   {0x1bc70, 0x1bc7c, direction::L},
8946
    {0x1bc80, 0x1bc88, direction::L},   {0x1bc90, 0x1bc99, direction::L},
8947
    {0x1bc9c, 0x1bc9c, direction::L},   {0x1bc9d, 0x1bc9e, direction::NSM},
8948
    {0x1bc9f, 0x1bc9f, direction::L},   {0x1bca0, 0x1bca3, direction::BN},
8949
    {0x1d000, 0x1d0f5, direction::L},   {0x1d100, 0x1d126, direction::L},
8950
    {0x1d129, 0x1d166, direction::L},   {0x1d167, 0x1d169, direction::NSM},
8951
    {0x1d16a, 0x1d172, direction::L},   {0x1d173, 0x1d17a, direction::BN},
8952
    {0x1d17b, 0x1d182, direction::NSM}, {0x1d183, 0x1d184, direction::L},
8953
    {0x1d185, 0x1d18b, direction::NSM}, {0x1d18c, 0x1d1a9, direction::L},
8954
    {0x1d1aa, 0x1d1ad, direction::NSM}, {0x1d1ae, 0x1d1e8, direction::L},
8955
    {0x1d200, 0x1d241, direction::ON},  {0x1d242, 0x1d244, direction::NSM},
8956
    {0x1d245, 0x1d245, direction::ON},  {0x1d2e0, 0x1d2f3, direction::L},
8957
    {0x1d300, 0x1d356, direction::ON},  {0x1d360, 0x1d378, direction::L},
8958
    {0x1d400, 0x1d454, direction::L},   {0x1d456, 0x1d49c, direction::L},
8959
    {0x1d49e, 0x1d49f, direction::L},   {0x1d4a2, 0x1d4a2, direction::L},
8960
    {0x1d4a5, 0x1d4a6, direction::L},   {0x1d4a9, 0x1d4ac, direction::L},
8961
    {0x1d4ae, 0x1d4b9, direction::L},   {0x1d4bb, 0x1d4bb, direction::L},
8962
    {0x1d4bd, 0x1d4c3, direction::L},   {0x1d4c5, 0x1d505, direction::L},
8963
    {0x1d507, 0x1d50a, direction::L},   {0x1d50d, 0x1d514, direction::L},
8964
    {0x1d516, 0x1d51c, direction::L},   {0x1d51e, 0x1d539, direction::L},
8965
    {0x1d53b, 0x1d53e, direction::L},   {0x1d540, 0x1d544, direction::L},
8966
    {0x1d546, 0x1d546, direction::L},   {0x1d54a, 0x1d550, direction::L},
8967
    {0x1d552, 0x1d6a5, direction::L},   {0x1d6a8, 0x1d6da, direction::L},
8968
    {0x1d6db, 0x1d6db, direction::ON},  {0x1d6dc, 0x1d714, direction::L},
8969
    {0x1d715, 0x1d715, direction::ON},  {0x1d716, 0x1d74e, direction::L},
8970
    {0x1d74f, 0x1d74f, direction::ON},  {0x1d750, 0x1d788, direction::L},
8971
    {0x1d789, 0x1d789, direction::ON},  {0x1d78a, 0x1d7c2, direction::L},
8972
    {0x1d7c3, 0x1d7c3, direction::ON},  {0x1d7c4, 0x1d7cb, direction::L},
8973
    {0x1d7ce, 0x1d7ff, direction::EN},  {0x1d800, 0x1d9ff, direction::L},
8974
    {0x1da00, 0x1da36, direction::NSM}, {0x1da37, 0x1da3a, direction::L},
8975
    {0x1da3b, 0x1da6c, direction::NSM}, {0x1da6d, 0x1da74, direction::L},
8976
    {0x1da75, 0x1da75, direction::NSM}, {0x1da76, 0x1da83, direction::L},
8977
    {0x1da84, 0x1da84, direction::NSM}, {0x1da85, 0x1da8b, direction::L},
8978
    {0x1da9b, 0x1da9f, direction::NSM}, {0x1daa1, 0x1daaf, direction::NSM},
8979
    {0x1e000, 0x1e006, direction::NSM}, {0x1e008, 0x1e018, direction::NSM},
8980
    {0x1e01b, 0x1e021, direction::NSM}, {0x1e023, 0x1e024, direction::NSM},
8981
    {0x1e026, 0x1e02a, direction::NSM}, {0x1e100, 0x1e12c, direction::L},
8982
    {0x1e130, 0x1e136, direction::NSM}, {0x1e137, 0x1e13d, direction::L},
8983
    {0x1e140, 0x1e149, direction::L},   {0x1e14e, 0x1e14f, direction::L},
8984
    {0x1e2c0, 0x1e2eb, direction::L},   {0x1e2ec, 0x1e2ef, direction::NSM},
8985
    {0x1e2f0, 0x1e2f9, direction::L},   {0x1e2ff, 0x1e2ff, direction::ET},
8986
    {0x1e800, 0x1e8c4, direction::R},   {0x1e8c7, 0x1e8cf, direction::R},
8987
    {0x1e8d0, 0x1e8d6, direction::NSM}, {0x1e900, 0x1e943, direction::R},
8988
    {0x1e944, 0x1e94a, direction::NSM}, {0x1e94b, 0x1e94b, direction::R},
8989
    {0x1e950, 0x1e959, direction::R},   {0x1e95e, 0x1e95f, direction::R},
8990
    {0x1ec71, 0x1ecb4, direction::AL},  {0x1ed01, 0x1ed3d, direction::AL},
8991
    {0x1ee00, 0x1ee03, direction::AL},  {0x1ee05, 0x1ee1f, direction::AL},
8992
    {0x1ee21, 0x1ee22, direction::AL},  {0x1ee24, 0x1ee24, direction::AL},
8993
    {0x1ee27, 0x1ee27, direction::AL},  {0x1ee29, 0x1ee32, direction::AL},
8994
    {0x1ee34, 0x1ee37, direction::AL},  {0x1ee39, 0x1ee39, direction::AL},
8995
    {0x1ee3b, 0x1ee3b, direction::AL},  {0x1ee42, 0x1ee42, direction::AL},
8996
    {0x1ee47, 0x1ee47, direction::AL},  {0x1ee49, 0x1ee49, direction::AL},
8997
    {0x1ee4b, 0x1ee4b, direction::AL},  {0x1ee4d, 0x1ee4f, direction::AL},
8998
    {0x1ee51, 0x1ee52, direction::AL},  {0x1ee54, 0x1ee54, direction::AL},
8999
    {0x1ee57, 0x1ee57, direction::AL},  {0x1ee59, 0x1ee59, direction::AL},
9000
    {0x1ee5b, 0x1ee5b, direction::AL},  {0x1ee5d, 0x1ee5d, direction::AL},
9001
    {0x1ee5f, 0x1ee5f, direction::AL},  {0x1ee61, 0x1ee62, direction::AL},
9002
    {0x1ee64, 0x1ee64, direction::AL},  {0x1ee67, 0x1ee6a, direction::AL},
9003
    {0x1ee6c, 0x1ee72, direction::AL},  {0x1ee74, 0x1ee77, direction::AL},
9004
    {0x1ee79, 0x1ee7c, direction::AL},  {0x1ee7e, 0x1ee7e, direction::AL},
9005
    {0x1ee80, 0x1ee89, direction::AL},  {0x1ee8b, 0x1ee9b, direction::AL},
9006
    {0x1eea1, 0x1eea3, direction::AL},  {0x1eea5, 0x1eea9, direction::AL},
9007
    {0x1eeab, 0x1eebb, direction::AL},  {0x1eef0, 0x1eef1, direction::ON},
9008
    {0x1f000, 0x1f02b, direction::ON},  {0x1f030, 0x1f093, direction::ON},
9009
    {0x1f0a0, 0x1f0ae, direction::ON},  {0x1f0b1, 0x1f0bf, direction::ON},
9010
    {0x1f0c1, 0x1f0cf, direction::ON},  {0x1f0d1, 0x1f0f5, direction::ON},
9011
    {0x1f100, 0x1f10a, direction::EN},  {0x1f10b, 0x1f10f, direction::ON},
9012
    {0x1f110, 0x1f12e, direction::L},   {0x1f12f, 0x1f12f, direction::ON},
9013
    {0x1f130, 0x1f169, direction::L},   {0x1f16a, 0x1f16f, direction::ON},
9014
    {0x1f170, 0x1f1ac, direction::L},   {0x1f1ad, 0x1f1ad, direction::ON},
9015
    {0x1f1e6, 0x1f202, direction::L},   {0x1f210, 0x1f23b, direction::L},
9016
    {0x1f240, 0x1f248, direction::L},   {0x1f250, 0x1f251, direction::L},
9017
    {0x1f260, 0x1f265, direction::ON},  {0x1f300, 0x1f6d7, direction::ON},
9018
    {0x1f6e0, 0x1f6ec, direction::ON},  {0x1f6f0, 0x1f6fc, direction::ON},
9019
    {0x1f700, 0x1f773, direction::ON},  {0x1f780, 0x1f7d8, direction::ON},
9020
    {0x1f7e0, 0x1f7eb, direction::ON},  {0x1f800, 0x1f80b, direction::ON},
9021
    {0x1f810, 0x1f847, direction::ON},  {0x1f850, 0x1f859, direction::ON},
9022
    {0x1f860, 0x1f887, direction::ON},  {0x1f890, 0x1f8ad, direction::ON},
9023
    {0x1f8b0, 0x1f8b1, direction::ON},  {0x1f900, 0x1f978, direction::ON},
9024
    {0x1f97a, 0x1f9cb, direction::ON},  {0x1f9cd, 0x1fa53, direction::ON},
9025
    {0x1fa60, 0x1fa6d, direction::ON},  {0x1fa70, 0x1fa74, direction::ON},
9026
    {0x1fa78, 0x1fa7a, direction::ON},  {0x1fa80, 0x1fa86, direction::ON},
9027
    {0x1fa90, 0x1faa8, direction::ON},  {0x1fab0, 0x1fab6, direction::ON},
9028
    {0x1fac0, 0x1fac2, direction::ON},  {0x1fad0, 0x1fad6, direction::ON},
9029
    {0x1fb00, 0x1fb92, direction::ON},  {0x1fb94, 0x1fbca, direction::ON},
9030
    {0x1fbf0, 0x1fbf9, direction::EN},  {0x20000, 0x2a6dd, direction::L},
9031
    {0x2a700, 0x2b734, direction::L},   {0x2b740, 0x2b81d, direction::L},
9032
    {0x2b820, 0x2cea1, direction::L},   {0x2ceb0, 0x2ebe0, direction::L},
9033
    {0x2f800, 0x2fa1d, direction::L},   {0x30000, 0x3134a, direction::L},
9034
    {0xe0001, 0xe0001, direction::BN},  {0xe0020, 0xe007f, direction::BN},
9035
    {0xe0100, 0xe01ef, direction::NSM}, {0xf0000, 0xffffd, direction::L},
9036
    {0x100000, 0x10fffd, direction::L}};
9037
9038
// CheckJoiners and CheckBidi are true for URL specification.
9039
9040
1.17M
inline static direction find_direction(uint32_t code_point) noexcept {
9041
1.17M
  const auto it = std::ranges::lower_bound(
9042
1.17M
      dir_table, code_point, {},
9043
1.17M
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
1.17M
  if (it == std::ranges::end(dir_table)) {
9047
622
    return direction::NONE;
9048
622
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
1.17M
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
1.17M
}
idna.cc:ada::idna::find_direction(unsigned int)
Line
Count
Source
9040
132k
inline static direction find_direction(uint32_t code_point) noexcept {
9041
132k
  const auto it = std::ranges::lower_bound(
9042
132k
      dir_table, code_point, {},
9043
132k
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
132k
  if (it == std::ranges::end(dir_table)) {
9047
622
    return direction::NONE;
9048
622
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
131k
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
132k
}
ada.cpp:ada::idna::find_direction(unsigned int)
Line
Count
Source
9040
235k
inline static direction find_direction(uint32_t code_point) noexcept {
9041
235k
  const auto it = std::ranges::lower_bound(
9042
235k
      dir_table, code_point, {},
9043
235k
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
235k
  if (it == std::ranges::end(dir_table)) {
9047
0
    return direction::NONE;
9048
0
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
235k
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
235k
}
serializers.cc:ada::idna::find_direction(unsigned int)
Line
Count
Source
9040
16.5k
inline static direction find_direction(uint32_t code_point) noexcept {
9041
16.5k
  const auto it = std::ranges::lower_bound(
9042
16.5k
      dir_table, code_point, {},
9043
16.5k
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
16.5k
  if (it == std::ranges::end(dir_table)) {
9047
0
    return direction::NONE;
9048
0
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
16.5k
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
16.5k
}
Unexecuted instantiation: can_parse.cc:ada::idna::find_direction(unsigned int)
Unexecuted instantiation: unicode.cc:ada::idna::find_direction(unsigned int)
parse.cc:ada::idna::find_direction(unsigned int)
Line
Count
Source
9040
410k
inline static direction find_direction(uint32_t code_point) noexcept {
9041
410k
  const auto it = std::ranges::lower_bound(
9042
410k
      dir_table, code_point, {},
9043
410k
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
410k
  if (it == std::ranges::end(dir_table)) {
9047
0
    return direction::NONE;
9048
0
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
410k
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
410k
}
url_pattern.cc:ada::idna::find_direction(unsigned int)
Line
Count
Source
9040
382k
inline static direction find_direction(uint32_t code_point) noexcept {
9041
382k
  const auto it = std::ranges::lower_bound(
9042
382k
      dir_table, code_point, {},
9043
382k
      &directions::final_code);  // project to the upper bound of each range
9044
9045
  // Safety check - almost always false, but cheap.
9046
382k
  if (it == std::ranges::end(dir_table)) {
9047
0
    return direction::NONE;
9048
0
  }
9049
9050
  // Invariant: it->final_code >= code_point. Confirm it's also in range.
9051
382k
  return code_point >= it->start_code ? it->direct : direction::NONE;
9052
382k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::find_direction(unsigned int)
9053
9054
inline static size_t find_last_not_of_nsm(
9055
158k
    const std::u32string_view label) noexcept {
9056
168k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
168k
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
158k
}
idna.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9055
13.7k
    const std::u32string_view label) noexcept {
9056
16.8k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
16.8k
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
13.7k
}
ada.cpp:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9055
37.0k
    const std::u32string_view label) noexcept {
9056
37.5k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
37.5k
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
37.0k
}
serializers.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9055
926
    const std::u32string_view label) noexcept {
9056
970
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
970
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
926
}
Unexecuted instantiation: can_parse.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Unexecuted instantiation: unicode.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
parse.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9055
49.8k
    const std::u32string_view label) noexcept {
9056
50.8k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
50.8k
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
49.8k
}
url_pattern.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9055
56.9k
    const std::u32string_view label) noexcept {
9056
62.0k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
9057
62.0k
    if (find_direction(label[i]) != direction::NSM) return i;
9058
9059
0
  return std::u32string_view::npos;
9060
56.9k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::find_last_not_of_nsm(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
9061
9062
// An RTL label is a label that contains at least one character of type R, AL,
9063
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
9064
158k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
158k
  const size_t mask =
9066
158k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
158k
  size_t directions = 0;
9069
1.03M
  for (size_t i = 0; i < label.size(); i++) {
9070
881k
    directions |= 1u << find_direction(label[i]);
9071
881k
  }
9072
158k
  return (directions & mask) != 0;
9073
158k
}
idna.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9064
13.7k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
13.7k
  const size_t mask =
9066
13.7k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
13.7k
  size_t directions = 0;
9069
116k
  for (size_t i = 0; i < label.size(); i++) {
9070
102k
    directions |= 1u << find_direction(label[i]);
9071
102k
  }
9072
13.7k
  return (directions & mask) != 0;
9073
13.7k
}
ada.cpp:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9064
37.0k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
37.0k
  const size_t mask =
9066
37.0k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
37.0k
  size_t directions = 0;
9069
227k
  for (size_t i = 0; i < label.size(); i++) {
9070
190k
    directions |= 1u << find_direction(label[i]);
9071
190k
  }
9072
37.0k
  return (directions & mask) != 0;
9073
37.0k
}
serializers.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9064
926
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
926
  const size_t mask =
9066
926
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
926
  size_t directions = 0;
9069
13.2k
  for (size_t i = 0; i < label.size(); i++) {
9070
12.3k
    directions |= 1u << find_direction(label[i]);
9071
12.3k
  }
9072
926
  return (directions & mask) != 0;
9073
926
}
Unexecuted instantiation: can_parse.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Unexecuted instantiation: unicode.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
parse.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9064
49.8k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
49.8k
  const size_t mask =
9066
49.8k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
49.8k
  size_t directions = 0;
9069
391k
  for (size_t i = 0; i < label.size(); i++) {
9070
342k
    directions |= 1u << find_direction(label[i]);
9071
342k
  }
9072
49.8k
  return (directions & mask) != 0;
9073
49.8k
}
url_pattern.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
Line
Count
Source
9064
56.9k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
9065
56.9k
  const size_t mask =
9066
56.9k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
9067
9068
56.9k
  size_t directions = 0;
9069
290k
  for (size_t i = 0; i < label.size(); i++) {
9070
233k
    directions |= 1u << find_direction(label[i]);
9071
233k
  }
9072
56.9k
  return (directions & mask) != 0;
9073
56.9k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::is_rtl_label(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)
9074
9075
171k
bool is_label_valid(const std::u32string_view label) {
9076
171k
  if (label.empty()) {
9077
0
    return true;
9078
0
  }
9079
9080
  ///////////////
9081
  // We have a normalization step which ensures that we are in NFC.
9082
  // If we receive punycode, we normalize and check that the normalized
9083
  // version matches the original.
9084
  // --------------------------------------
9085
  // The label must be in Unicode Normalization Form NFC.
9086
9087
  // Current URL standard indicatest that CheckHyphens is set to false.
9088
  // ---------------------------------------
9089
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
9090
  // in both the third and fourth positions. If CheckHyphens, the label must
9091
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
9092
9093
  // This is not necessary because we segment the
9094
  // labels by '.'.
9095
  // ---------------------------------------
9096
  // The label must not contain a U+002E ( . ) FULL STOP.
9097
  // if (label.find('.') != std::string_view::npos) return false;
9098
9099
  // The label must not begin with a combining mark, that is:
9100
  // General_Category=Mark.
9101
171k
  constexpr static uint32_t combining[] = {
9102
171k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9103
171k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9104
171k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9105
171k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9106
171k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9107
171k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9108
171k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9109
171k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9110
171k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9111
171k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9112
171k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9113
171k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9114
171k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9115
171k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9116
171k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9117
171k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9118
171k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9119
171k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9120
171k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9121
171k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9122
171k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9123
171k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9124
171k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9125
171k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9126
171k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9127
171k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9128
171k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9129
171k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9130
171k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9131
171k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9132
171k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9133
171k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9134
171k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9135
171k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9136
171k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9137
171k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9138
171k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9139
171k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9140
171k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9141
171k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9142
171k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9143
171k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9144
171k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9145
171k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9146
171k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9147
171k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9148
171k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9149
171k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9150
171k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9151
171k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9152
171k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9153
171k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9154
171k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9155
171k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9156
171k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9157
171k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9158
171k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9159
171k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9160
171k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9161
171k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9162
171k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9163
171k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9164
171k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9165
171k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9166
171k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9167
171k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9168
171k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9169
171k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9170
171k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9171
171k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9172
171k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9173
171k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9174
171k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9175
171k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9176
171k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9177
171k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9178
171k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9179
171k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9180
171k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9181
171k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9182
171k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9183
171k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9184
171k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9185
171k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9186
171k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9187
171k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9188
171k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9189
171k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9190
171k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9191
171k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9192
171k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9193
171k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9194
171k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9195
171k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9196
171k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9197
171k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9198
171k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9199
171k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9200
171k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9201
171k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9202
171k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9203
171k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9204
171k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9205
171k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9206
171k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9207
171k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9208
171k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9209
171k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9210
171k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9211
171k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9212
171k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9213
171k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9214
171k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9215
171k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9216
171k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9217
171k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9218
171k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9219
171k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9220
171k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9221
171k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9222
171k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9223
171k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9224
171k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9225
171k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9226
171k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9227
171k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9228
171k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9229
171k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9230
171k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9231
171k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9232
171k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9233
171k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9234
171k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9235
171k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9236
171k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9237
171k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9238
171k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9239
171k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9240
171k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9241
171k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9242
171k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9243
171k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9244
171k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9245
171k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9246
171k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9247
171k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9248
171k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9249
171k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9250
171k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9251
171k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9252
171k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9253
171k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9254
171k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9255
171k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9256
171k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9257
171k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9258
171k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9259
171k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9260
171k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9261
171k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9262
171k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9263
171k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9264
171k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9265
171k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9266
171k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9267
171k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9268
171k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9269
171k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9270
171k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9271
171k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9272
171k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9273
171k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9274
171k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9275
171k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9276
171k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9277
171k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9278
171k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9279
171k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9280
171k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9281
171k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9282
171k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9283
171k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9284
171k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9285
171k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9286
171k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9287
171k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9288
171k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9289
171k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9290
171k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9291
171k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9292
171k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9293
171k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9294
171k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9295
171k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9296
171k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9297
171k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9298
171k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9299
171k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9300
171k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9301
171k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9302
171k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9303
171k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9304
171k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9305
171k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9306
171k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9307
171k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9308
171k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9309
171k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9310
171k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9311
171k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9312
171k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9313
171k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9314
171k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9315
171k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9316
171k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9317
171k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9318
171k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9319
171k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9320
171k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9321
171k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9322
171k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9323
171k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9324
171k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9325
171k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9326
171k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9327
171k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9328
171k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9329
171k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9330
171k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9331
171k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9332
171k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9333
171k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9334
171k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9335
171k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9336
171k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9337
171k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9338
171k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9339
171k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9340
171k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9341
171k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9342
171k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9343
171k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9344
171k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9345
171k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9346
171k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9347
171k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9348
171k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9349
171k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9350
171k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9351
171k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9352
171k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9353
171k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9354
171k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9355
171k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9356
171k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9357
171k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9358
171k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9359
171k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9360
171k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9361
171k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9362
171k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9363
171k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9364
171k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9365
171k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9366
171k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9367
171k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9368
171k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9369
171k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9370
171k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9371
171k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9372
171k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9373
171k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9374
171k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9375
171k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9376
171k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9377
171k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9378
171k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9379
171k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9380
171k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9381
171k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9382
171k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9383
171k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9384
171k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9385
171k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9386
171k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9387
171k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9388
171k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9389
171k
  if (std::ranges::binary_search(combining, label.front())) {
9390
1.23k
    return false;
9391
1.23k
  }
9392
  // We verify this next step as part of the mapping:
9393
  // ---------------------------------------------
9394
  // Each code point in the label must only have certain status values
9395
  // according to Section 5, IDNA Mapping Table:
9396
  // - For Transitional Processing, each value must be valid.
9397
  // - For Nontransitional Processing, each value must be either valid or
9398
  // deviation.
9399
9400
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
9401
  // A, in The Unicode Code Points and Internationalized Domain Names for
9402
  // Applications (IDNA) [IDNA2008].
9403
170k
  constexpr static uint32_t virama[] = {
9404
170k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9405
170k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9406
170k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9407
170k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9408
170k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9409
170k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9410
170k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9411
170k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9412
170k
  constexpr static uint32_t R[] = {
9413
170k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9414
170k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9415
170k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9416
170k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9417
170k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9418
170k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9419
170k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9420
170k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9421
170k
  constexpr static uint32_t L[] = {0xa872};
9422
170k
  constexpr static uint32_t D[] = {
9423
170k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9424
170k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9425
170k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9426
170k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9427
170k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9428
170k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9429
170k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9430
170k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9431
170k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9432
170k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9433
170k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9434
170k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9435
170k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9436
170k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9437
170k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9438
170k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9439
170k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9440
170k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9441
170k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9442
170k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9443
170k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9444
170k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9445
170k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9446
170k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9447
170k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9448
170k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9449
170k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9450
170k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9451
170k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9452
170k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9453
170k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9454
170k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9455
170k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9456
170k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9457
170k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9458
170k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9459
170k
      0xa870, 0xa871};
9460
9461
1.17M
  for (size_t i = 0; i < label.size(); i++) {
9462
1.01M
    uint32_t c = label[i];
9463
1.01M
    if (c == 0x200c) {
9464
9.35k
      if (i > 0) {
9465
9.23k
        if (std::ranges::binary_search(virama, label[i - 1])) {
9466
562
          return true;
9467
562
        }
9468
9.23k
      }
9469
8.79k
      if ((i == 0) || (i + 1 >= label.size())) {
9470
594
        return false;
9471
594
      }
9472
      // we go backward looking for L or D
9473
23.0k
      auto is_l_or_d = [](uint32_t code) {
9474
23.0k
        return std::ranges::binary_search(L, code) ||
9475
22.6k
               std::ranges::binary_search(D, code);
9476
23.0k
      };
idna.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Line
Count
Source
9473
2.67k
      auto is_l_or_d = [](uint32_t code) {
9474
2.67k
        return std::ranges::binary_search(L, code) ||
9475
2.63k
               std::ranges::binary_search(D, code);
9476
2.67k
      };
ada.cpp:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Line
Count
Source
9473
1.63k
      auto is_l_or_d = [](uint32_t code) {
9474
1.63k
        return std::ranges::binary_search(L, code) ||
9475
1.50k
               std::ranges::binary_search(D, code);
9476
1.63k
      };
serializers.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Line
Count
Source
9473
913
      auto is_l_or_d = [](uint32_t code) {
9474
913
        return std::ranges::binary_search(L, code) ||
9475
913
               std::ranges::binary_search(D, code);
9476
913
      };
Unexecuted instantiation: can_parse.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Unexecuted instantiation: unicode.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
parse.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Line
Count
Source
9473
2.78k
      auto is_l_or_d = [](uint32_t code) {
9474
2.78k
        return std::ranges::binary_search(L, code) ||
9475
2.70k
               std::ranges::binary_search(D, code);
9476
2.78k
      };
url_pattern.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
Line
Count
Source
9473
15.0k
      auto is_l_or_d = [](uint32_t code) {
9474
15.0k
        return std::ranges::binary_search(L, code) ||
9475
14.8k
               std::ranges::binary_search(D, code);
9476
15.0k
      };
Unexecuted instantiation: url_search_params.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_0::operator()(unsigned int) const
9477
18.9k
      auto is_r_or_d = [](uint32_t code) {
9478
18.9k
        return std::ranges::binary_search(R, code) ||
9479
18.1k
               std::ranges::binary_search(D, code);
9480
18.9k
      };
idna.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Line
Count
Source
9477
2.58k
      auto is_r_or_d = [](uint32_t code) {
9478
2.58k
        return std::ranges::binary_search(R, code) ||
9479
2.18k
               std::ranges::binary_search(D, code);
9480
2.58k
      };
ada.cpp:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Line
Count
Source
9477
731
      auto is_r_or_d = [](uint32_t code) {
9478
731
        return std::ranges::binary_search(R, code) ||
9479
505
               std::ranges::binary_search(D, code);
9480
731
      };
serializers.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Line
Count
Source
9477
705
      auto is_r_or_d = [](uint32_t code) {
9478
705
        return std::ranges::binary_search(R, code) ||
9479
704
               std::ranges::binary_search(D, code);
9480
705
      };
Unexecuted instantiation: can_parse.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Unexecuted instantiation: unicode.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
parse.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Line
Count
Source
9477
2.59k
      auto is_r_or_d = [](uint32_t code) {
9478
2.59k
        return std::ranges::binary_search(R, code) ||
9479
2.33k
               std::ranges::binary_search(D, code);
9480
2.59k
      };
url_pattern.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
Line
Count
Source
9477
12.3k
      auto is_r_or_d = [](uint32_t code) {
9478
12.3k
        return std::ranges::binary_search(R, code) ||
9479
12.3k
               std::ranges::binary_search(D, code);
9480
12.3k
      };
Unexecuted instantiation: url_search_params.cc:ada::idna::is_label_valid(std::__1::basic_string_view<char32_t, std::__1::char_traits<char32_t> >)::$_1::operator()(unsigned int) const
9481
8.20k
      std::u32string_view before = label.substr(0, i);
9482
8.20k
      std::u32string_view after = label.substr(i + 1);
9483
8.20k
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9484
8.20k
              before.end()) &&
9485
5.08k
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9486
5.08k
              after.end());
9487
1.00M
    } else if (c == 0x200d) {
9488
2.74k
      if (i > 0) {
9489
2.62k
        if (std::ranges::binary_search(virama, label[i - 1])) {
9490
1.12k
          return true;
9491
1.12k
        }
9492
2.62k
      }
9493
1.62k
      return false;
9494
2.74k
    }
9495
1.01M
  }
9496
9497
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
9498
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
9499
  // Section 2.
9500
9501
  // The following rule, consisting of six conditions, applies to labels
9502
  // in Bidi domain names.  The requirements that this rule satisfies are
9503
  // described in Section 3.  All of the conditions must be satisfied for
9504
  // the rule to be satisfied.
9505
  //
9506
  //  1.  The first character must be a character with Bidi property L, R,
9507
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
9508
  //     has the L property, it is an LTR label.
9509
  //
9510
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
9511
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
9512
  //
9513
  //   3.  In an RTL label, the end of the label must be a character with
9514
  //       Bidi property R, AL, EN, or AN, followed by zero or more
9515
  //       characters with Bidi property NSM.
9516
  //
9517
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
9518
  //       vice versa.
9519
  //
9520
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
9521
  //       ES, CS, ET, ON, BN, or NSM are allowed.
9522
  //
9523
  //   6.  In an LTR label, the end of the label must be a character with
9524
  //       Bidi property L or EN, followed by zero or more characters with
9525
  //       Bidi property NSM.
9526
9527
158k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9528
158k
  if (last_non_nsm_char == std::u32string_view::npos) {
9529
0
    return false;
9530
0
  }
9531
9532
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
9533
  // The following rule, consisting of six conditions, applies to labels in Bidi
9534
  // domain names.
9535
158k
  if (is_rtl_label(label)) {
9536
    // The first character must be a character with Bidi property L, R,
9537
    // or AL. If it has the R or AL property, it is an RTL label; if it
9538
    // has the L property, it is an LTR label.
9539
9540
23.4k
    if (find_direction(label[0]) == direction::L) {
9541
      // Eval as LTR
9542
9543
      // In an LTR label, only characters with the Bidi properties L, EN,
9544
      // ES, CS, ET, ON, BN, or NSM are allowed.
9545
33.3k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9546
33.3k
        const direction d = find_direction(label[i]);
9547
33.3k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9548
16.8k
              d == direction::CS || d == direction::ET || d == direction::ON ||
9549
10.5k
              d == direction::BN || d == direction::NSM)) {
9550
5.86k
          return false;
9551
5.86k
        }
9552
33.3k
      }
9553
9554
0
      const direction last_dir = find_direction(label[last_non_nsm_char]);
9555
0
      if (!(last_dir == direction::L || last_dir == direction::EN)) {
9556
0
        return false;
9557
0
      }
9558
9559
0
      return true;
9560
9561
17.5k
    } else {
9562
      // Eval as RTL
9563
9564
      // The first character must be R or AL; a leading AN (or any other
9565
      // direction) does not start a valid RTL label.
9566
17.5k
      const direction first_dir = find_direction(label[0]);
9567
17.5k
      if (first_dir != direction::R && first_dir != direction::AL) {
9568
2.06k
        return false;
9569
2.06k
      }
9570
9571
15.5k
      bool has_an = false;
9572
15.5k
      bool has_en = false;
9573
64.9k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9574
53.7k
        const direction d = find_direction(label[i]);
9575
9576
        // In an RTL label, if an EN is present, no AN may be present, and vice
9577
        // versa.
9578
53.7k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9579
53.6k
            (d == direction::AN && ((has_an = true) && has_en))) {
9580
212
          return false;
9581
212
        }
9582
9583
53.5k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9584
21.8k
              d == direction::EN || d == direction::ES || d == direction::CS ||
9585
13.1k
              d == direction::ET || d == direction::ON || d == direction::BN ||
9586
4.59k
              d == direction::NSM)) {
9587
2.35k
          return false;
9588
2.35k
        }
9589
9590
51.2k
        if (i == last_non_nsm_char &&
9591
12.9k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9592
3.29k
              d == direction::EN)) {
9593
1.72k
          return false;
9594
1.72k
        }
9595
51.2k
      }
9596
9597
11.2k
      return true;
9598
15.5k
    }
9599
23.4k
  }
9600
9601
134k
  return true;
9602
158k
}
9603
9604
}  // namespace ada::idna
9605
/* end file src/validity.cpp */
9606
/* begin file src/to_ascii.cpp */
9607
9608
#include <algorithm>
9609
#include <cstdint>
9610
#include <ranges>
9611
9612
9613
#ifdef ADA_USE_SIMDUTF
9614
#include "simdutf.h"
9615
#endif
9616
9617
namespace ada::idna {
9618
9619
209k
bool constexpr is_ascii(std::u32string_view view) {
9620
362k
  for (uint32_t c : view) {
9621
362k
    if (c >= 0x80) {
9622
191k
      return false;
9623
191k
    }
9624
362k
  }
9625
18.1k
  return true;
9626
209k
}
9627
9628
208k
bool constexpr is_ascii(std::string_view view) {
9629
2.20M
  for (uint8_t c : view) {
9630
2.20M
    if (c >= 0x80) {
9631
67.3k
      return false;
9632
67.3k
    }
9633
2.20M
  }
9634
141k
  return true;
9635
208k
}
9636
9637
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
9638
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9639
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
9640
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
9641
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
9642
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9643
    0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9644
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9645
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9646
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9647
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
9648
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
9649
9650
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
9651
9652
44.2k
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9653
44.2k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9654
44.2k
}
9655
9656
3.69k
bool contains_forbidden_domain_code_point(std::string_view view) {
9657
3.69k
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9658
3.69k
}
9659
9660
// We return "" on error.
9661
129k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
129k
  static const std::string error = "";
9663
129k
  std::string out;
9664
129k
  out.reserve(ut8_string.size());
9665
129k
  std::u32string tmp_buffer;
9666
129k
  std::u32string post_map;
9667
129k
  size_t label_start = 0;
9668
9669
285k
  while (label_start != ut8_string.size()) {
9670
189k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
189k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
189k
    size_t label_size =
9673
189k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
189k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
189k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
189k
    label_start += label_size_with_dot;
9677
189k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
168k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
168k
      size_t label_out_start = out.size();
9683
168k
      out.append(label_view);
9684
168k
      ascii_map(out.data() + label_out_start, label_size);
9685
168k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
168k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
76.3k
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
76.3k
                                            label_size - 4);
9690
76.3k
        tmp_buffer.clear();
9691
76.3k
        bool is_ok =
9692
76.3k
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
76.3k
        if (!is_ok) {
9694
7.01k
          return error;
9695
7.01k
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
69.3k
        if (is_ascii(tmp_buffer)) {
9700
2.79k
          return error;
9701
2.79k
        }
9702
66.5k
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
8.10k
          return error;
9704
8.10k
        }
9705
58.4k
        if (tmp_buffer != post_map) {
9706
4.07k
          return error;
9707
4.07k
        }
9708
54.3k
        normalize(post_map);
9709
54.3k
        if (post_map != tmp_buffer) {
9710
2.46k
          return error;
9711
2.46k
        }
9712
51.8k
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
51.8k
        if (!is_label_valid(post_map)) {
9716
9.83k
          return error;
9717
9.83k
        }
9718
51.8k
      }
9719
168k
    }
9720
155k
    if (!is_last_label) {
9721
66.7k
      out.push_back('.');
9722
66.7k
    }
9723
155k
  }
9724
95.6k
  return out;
9725
129k
}
idna.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
9661
6.49k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
6.49k
  static const std::string error = "";
9663
6.49k
  std::string out;
9664
6.49k
  out.reserve(ut8_string.size());
9665
6.49k
  std::u32string tmp_buffer;
9666
6.49k
  std::u32string post_map;
9667
6.49k
  size_t label_start = 0;
9668
9669
18.8k
  while (label_start != ut8_string.size()) {
9670
13.1k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
13.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
13.1k
    size_t label_size =
9673
13.1k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
13.1k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
13.1k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
13.1k
    label_start += label_size_with_dot;
9677
13.1k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
8.39k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
8.39k
      size_t label_out_start = out.size();
9683
8.39k
      out.append(label_view);
9684
8.39k
      ascii_map(out.data() + label_out_start, label_size);
9685
8.39k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
8.39k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
6.01k
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
6.01k
                                            label_size - 4);
9690
6.01k
        tmp_buffer.clear();
9691
6.01k
        bool is_ok =
9692
6.01k
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
6.01k
        if (!is_ok) {
9694
186
          return error;
9695
186
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
5.83k
        if (is_ascii(tmp_buffer)) {
9700
108
          return error;
9701
108
        }
9702
5.72k
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
318
          return error;
9704
318
        }
9705
5.40k
        if (tmp_buffer != post_map) {
9706
88
          return error;
9707
88
        }
9708
5.31k
        normalize(post_map);
9709
5.31k
        if (post_map != tmp_buffer) {
9710
58
          return error;
9711
58
        }
9712
5.26k
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
5.26k
        if (!is_label_valid(post_map)) {
9716
19
          return error;
9717
19
        }
9718
5.26k
      }
9719
8.39k
    }
9720
12.3k
    if (!is_last_label) {
9721
10.4k
      out.push_back('.');
9722
10.4k
    }
9723
12.3k
  }
9724
5.72k
  return out;
9725
6.49k
}
ada.cpp:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
9661
9.98k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
9.98k
  static const std::string error = "";
9663
9.98k
  std::string out;
9664
9.98k
  out.reserve(ut8_string.size());
9665
9.98k
  std::u32string tmp_buffer;
9666
9.98k
  std::u32string post_map;
9667
9.98k
  size_t label_start = 0;
9668
9669
36.1k
  while (label_start != ut8_string.size()) {
9670
26.6k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
26.6k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
26.6k
    size_t label_size =
9673
26.6k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
26.6k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
26.6k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
26.6k
    label_start += label_size_with_dot;
9677
26.6k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
20.7k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
20.7k
      size_t label_out_start = out.size();
9683
20.7k
      out.append(label_view);
9684
20.7k
      ascii_map(out.data() + label_out_start, label_size);
9685
20.7k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
20.7k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
8.88k
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
8.88k
                                            label_size - 4);
9690
8.88k
        tmp_buffer.clear();
9691
8.88k
        bool is_ok =
9692
8.88k
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
8.88k
        if (!is_ok) {
9694
281
          return error;
9695
281
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
8.60k
        if (is_ascii(tmp_buffer)) {
9700
142
          return error;
9701
142
        }
9702
8.46k
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
24
          return error;
9704
24
        }
9705
8.43k
        if (tmp_buffer != post_map) {
9706
71
          return error;
9707
71
        }
9708
8.36k
        normalize(post_map);
9709
8.36k
        if (post_map != tmp_buffer) {
9710
19
          return error;
9711
19
        }
9712
8.34k
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
8.34k
        if (!is_label_valid(post_map)) {
9716
14
          return error;
9717
14
        }
9718
8.34k
      }
9719
20.7k
    }
9720
26.1k
    if (!is_last_label) {
9721
17.1k
      out.push_back('.');
9722
17.1k
    }
9723
26.1k
  }
9724
9.43k
  return out;
9725
9.98k
}
serializers.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
9661
633
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
633
  static const std::string error = "";
9663
633
  std::string out;
9664
633
  out.reserve(ut8_string.size());
9665
633
  std::u32string tmp_buffer;
9666
633
  std::u32string post_map;
9667
633
  size_t label_start = 0;
9668
9669
1.82k
  while (label_start != ut8_string.size()) {
9670
1.33k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
1.33k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
1.33k
    size_t label_size =
9673
1.33k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
1.33k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
1.33k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
1.33k
    label_start += label_size_with_dot;
9677
1.33k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
1.20k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
1.20k
      size_t label_out_start = out.size();
9683
1.20k
      out.append(label_view);
9684
1.20k
      ascii_map(out.data() + label_out_start, label_size);
9685
1.20k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
1.20k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
237
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
237
                                            label_size - 4);
9690
237
        tmp_buffer.clear();
9691
237
        bool is_ok =
9692
237
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
237
        if (!is_ok) {
9694
20
          return error;
9695
20
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
217
        if (is_ascii(tmp_buffer)) {
9700
4
          return error;
9701
4
        }
9702
213
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
48
          return error;
9704
48
        }
9705
165
        if (tmp_buffer != post_map) {
9706
21
          return error;
9707
21
        }
9708
144
        normalize(post_map);
9709
144
        if (post_map != tmp_buffer) {
9710
22
          return error;
9711
22
        }
9712
122
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
122
        if (!is_label_valid(post_map)) {
9716
21
          return error;
9717
21
        }
9718
122
      }
9719
1.20k
    }
9720
1.19k
    if (!is_last_label) {
9721
740
      out.push_back('.');
9722
740
    }
9723
1.19k
  }
9724
497
  return out;
9725
633
}
Unexecuted instantiation: can_parse.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: unicode.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
parse.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
9661
14.6k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
14.6k
  static const std::string error = "";
9663
14.6k
  std::string out;
9664
14.6k
  out.reserve(ut8_string.size());
9665
14.6k
  std::u32string tmp_buffer;
9666
14.6k
  std::u32string post_map;
9667
14.6k
  size_t label_start = 0;
9668
9669
40.7k
  while (label_start != ut8_string.size()) {
9670
27.3k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
27.3k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
27.3k
    size_t label_size =
9673
27.3k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
27.3k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
27.3k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
27.3k
    label_start += label_size_with_dot;
9677
27.3k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
25.0k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
25.0k
      size_t label_out_start = out.size();
9683
25.0k
      out.append(label_view);
9684
25.0k
      ascii_map(out.data() + label_out_start, label_size);
9685
25.0k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
25.0k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
8.52k
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
8.52k
                                            label_size - 4);
9690
8.52k
        tmp_buffer.clear();
9691
8.52k
        bool is_ok =
9692
8.52k
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
8.52k
        if (!is_ok) {
9694
404
          return error;
9695
404
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
8.12k
        if (is_ascii(tmp_buffer)) {
9700
194
          return error;
9701
194
        }
9702
7.92k
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
322
          return error;
9704
322
        }
9705
7.60k
        if (tmp_buffer != post_map) {
9706
155
          return error;
9707
155
        }
9708
7.45k
        normalize(post_map);
9709
7.45k
        if (post_map != tmp_buffer) {
9710
79
          return error;
9711
79
        }
9712
7.37k
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
7.37k
        if (!is_label_valid(post_map)) {
9716
88
          return error;
9717
88
        }
9718
7.37k
      }
9719
25.0k
    }
9720
26.0k
    if (!is_last_label) {
9721
13.8k
      out.push_back('.');
9722
13.8k
    }
9723
26.0k
  }
9724
13.4k
  return out;
9725
14.6k
}
url_pattern.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
9661
98.1k
static std::string from_ascii_to_ascii(std::string_view ut8_string) {
9662
98.1k
  static const std::string error = "";
9663
98.1k
  std::string out;
9664
98.1k
  out.reserve(ut8_string.size());
9665
98.1k
  std::u32string tmp_buffer;
9666
98.1k
  std::u32string post_map;
9667
98.1k
  size_t label_start = 0;
9668
9669
187k
  while (label_start != ut8_string.size()) {
9670
121k
    size_t loc_dot = ut8_string.find('.', label_start);
9671
121k
    bool is_last_label = (loc_dot == std::string_view::npos);
9672
121k
    size_t label_size =
9673
121k
        is_last_label ? ut8_string.size() - label_start : loc_dot - label_start;
9674
121k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9675
121k
    std::string_view label_view(ut8_string.data() + label_start, label_size);
9676
121k
    label_start += label_size_with_dot;
9677
121k
    if (label_size == 0) {
9678
      // empty label? Nothing to do.
9679
113k
    } else {
9680
      // Append the label to out and lowercase it in-place, avoiding a separate
9681
      // copy of the entire input string.
9682
113k
      size_t label_out_start = out.size();
9683
113k
      out.append(label_view);
9684
113k
      ascii_map(out.data() + label_out_start, label_size);
9685
113k
      std::string_view mapped_label(out.data() + label_out_start, label_size);
9686
113k
      if (mapped_label.starts_with("xn--")) {
9687
        // The xn-- part is the expensive game.
9688
52.6k
        std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9689
52.6k
                                            label_size - 4);
9690
52.6k
        tmp_buffer.clear();
9691
52.6k
        bool is_ok =
9692
52.6k
            ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9693
52.6k
        if (!is_ok) {
9694
6.11k
          return error;
9695
6.11k
        }
9696
        // If the input is just ASCII, it should not have been encoded
9697
        // as punycode.
9698
        // https://github.com/whatwg/url/issues/760
9699
46.5k
        if (is_ascii(tmp_buffer)) {
9700
2.34k
          return error;
9701
2.34k
        }
9702
44.1k
        if (!ada::idna::map(tmp_buffer, post_map)) {
9703
7.39k
          return error;
9704
7.39k
        }
9705
36.7k
        if (tmp_buffer != post_map) {
9706
3.73k
          return error;
9707
3.73k
        }
9708
33.0k
        normalize(post_map);
9709
33.0k
        if (post_map != tmp_buffer) {
9710
2.29k
          return error;
9711
2.29k
        }
9712
30.7k
        if (post_map.empty()) {
9713
0
          return error;
9714
0
        }
9715
30.7k
        if (!is_label_valid(post_map)) {
9716
9.69k
          return error;
9717
9.69k
        }
9718
30.7k
      }
9719
113k
    }
9720
89.5k
    if (!is_last_label) {
9721
24.5k
      out.push_back('.');
9722
24.5k
    }
9723
89.5k
  }
9724
66.5k
  return out;
9725
98.1k
}
Unexecuted instantiation: url_search_params.cc:ada::idna::from_ascii_to_ascii(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
9726
9727
// We return "" on error.
9728
193k
std::string to_ascii(std::string_view ut8_string) {
9729
193k
  if (is_ascii(ut8_string)) {
9730
129k
    return from_ascii_to_ascii(ut8_string);
9731
129k
  }
9732
63.3k
  static const std::string error = "";
9733
  // We convert to UTF-32
9734
9735
#ifdef ADA_USE_SIMDUTF
9736
  size_t utf32_length =
9737
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9738
  std::u32string utf32(utf32_length, '\0');
9739
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
9740
      ut8_string.data(), ut8_string.size(), utf32.data());
9741
#else
9742
63.3k
  size_t utf32_length =
9743
63.3k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9744
63.3k
  std::u32string utf32(utf32_length, '\0');
9745
63.3k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9746
63.3k
      ut8_string.data(), ut8_string.size(), utf32.data());
9747
63.3k
#endif
9748
63.3k
  if (actual_utf32_length == 0) {
9749
15.5k
    return error;
9750
15.5k
  }
9751
  // mapping: use the two-argument overload to avoid an extra heap allocation
9752
  // that the single-argument overload (which returns by value) would incur.
9753
47.7k
  std::u32string tmp_buffer;
9754
47.7k
  std::u32string post_map;
9755
47.7k
  if (!ada::idna::map(utf32, tmp_buffer)) {
9756
948
    return error;
9757
948
  }
9758
46.8k
  utf32 = std::move(tmp_buffer);
9759
46.8k
  normalize(utf32);
9760
46.8k
  std::string out;
9761
46.8k
  out.reserve(ut8_string.size());
9762
46.8k
  size_t label_start = 0;
9763
9764
177k
  while (label_start != utf32.size()) {
9765
147k
    size_t loc_dot = utf32.find('.', label_start);
9766
147k
    bool is_last_label = (loc_dot == std::string_view::npos);
9767
147k
    size_t label_size =
9768
147k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9769
147k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9770
147k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9771
147k
    label_start += label_size_with_dot;
9772
147k
    if (label_size == 0) {
9773
      // empty label? Nothing to do.
9774
133k
    } else if (label_view.starts_with(U"xn--")) {
9775
      // we do not need to check, e.g., Xn-- because mapping goes to lower case
9776
      // Validate first, then bulk-copy with a single resize to avoid per-char
9777
      // capacity checks in operator+=.
9778
147k
      for (char32_t c : label_view) {
9779
147k
        if (c >= 0x80) {
9780
704
          return error;
9781
704
        }
9782
147k
      }
9783
11.1k
      size_t label_out_start = out.size();
9784
11.1k
      out.resize(label_out_start + label_size);
9785
11.1k
      char* dest = out.data() + label_out_start;
9786
142k
      for (char32_t c : label_view) {
9787
142k
        *dest++ = static_cast<char>(c);
9788
142k
      }
9789
11.1k
      std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9790
11.1k
                                          label_size - 4);
9791
11.1k
      tmp_buffer.clear();
9792
11.1k
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9793
11.1k
      if (!is_ok) {
9794
661
        return error;
9795
661
      }
9796
      // If the input is just ASCII, it should not have been encoded
9797
      // as punycode.
9798
      // https://github.com/whatwg/url/issues/760
9799
10.5k
      if (is_ascii(tmp_buffer)) {
9800
1.14k
        return error;
9801
1.14k
      }
9802
9.38k
      if (!ada::idna::map(tmp_buffer, post_map)) {
9803
1.41k
        return error;
9804
1.41k
      }
9805
7.97k
      if (tmp_buffer != post_map) {
9806
1.52k
        return error;
9807
1.52k
      }
9808
6.44k
      normalize(post_map);
9809
6.44k
      if (post_map != tmp_buffer) {
9810
871
        return error;
9811
871
      }
9812
5.57k
      if (post_map.empty()) {
9813
0
        return error;
9814
0
      }
9815
5.57k
      if (!is_label_valid(post_map)) {
9816
276
        return error;
9817
276
      }
9818
121k
    } else {
9819
      // The fast path here is an ascii label.
9820
121k
      if (is_ascii(label_view)) {
9821
        // no validation needed; bulk-copy with single resize.
9822
13.2k
        size_t old_size = out.size();
9823
13.2k
        out.resize(old_size + label_size);
9824
13.2k
        char* dest = out.data() + old_size;
9825
66.4k
        for (char32_t c : label_view) {
9826
66.4k
          *dest++ = static_cast<char>(c);
9827
66.4k
        }
9828
108k
      } else {
9829
        // slow path.
9830
        // first check validity.
9831
108k
        if (!is_label_valid(label_view)) {
9832
9.76k
          return error;
9833
9.76k
        }
9834
        // It is valid! So now we must encode it as punycode...
9835
98.5k
        out.append("xn--");
9836
98.5k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9837
98.5k
        if (!is_ok) {
9838
0
          return error;
9839
0
        }
9840
98.5k
      }
9841
121k
    }
9842
131k
    if (!is_last_label) {
9843
103k
      out.push_back('.');
9844
103k
    }
9845
131k
  }
9846
30.4k
  return out;
9847
46.8k
}
9848
}  // namespace ada::idna
9849
/* end file src/to_ascii.cpp */
9850
/* begin file src/to_unicode.cpp */
9851
9852
#include <algorithm>
9853
#include <string>
9854
9855
9856
#ifdef ADA_USE_SIMDUTF
9857
#include "simdutf.h"
9858
#endif
9859
9860
namespace ada::idna {
9861
17.4k
std::string to_unicode(std::string_view input) {
9862
17.4k
  std::string output;
9863
17.4k
  output.reserve(input.size());
9864
9865
17.4k
  size_t label_start = 0;
9866
17.4k
  std::u32string tmp_buffer;
9867
17.4k
  std::u32string post_map;
9868
80.6k
  while (label_start < input.size()) {
9869
63.1k
    size_t loc_dot = input.find('.', label_start);
9870
63.1k
    bool is_last_label = (loc_dot == std::string_view::npos);
9871
63.1k
    size_t label_size =
9872
63.1k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9873
63.1k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9874
9875
63.1k
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9876
10.2k
      label_view.remove_prefix(4);
9877
10.2k
      tmp_buffer.clear();
9878
10.2k
      if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
9879
        // Per UTS #46, the decoded label must be re-validated. Reject decodings
9880
        // that are pure ASCII (xn-- encoding of an ASCII-only label), or whose
9881
        // mapping/normalization is not stable, or that fail label validity.
9882
8.11k
        bool accept_decoded = true;
9883
8.11k
        if (ada::idna::is_ascii(tmp_buffer)) {
9884
955
          accept_decoded = false;
9885
7.15k
        } else {
9886
7.15k
          post_map.clear();
9887
7.15k
          if (!ada::idna::map(tmp_buffer, post_map) || post_map != tmp_buffer) {
9888
1.12k
            accept_decoded = false;
9889
6.03k
          } else {
9890
6.03k
            ada::idna::normalize(post_map);
9891
6.03k
            if (post_map != tmp_buffer || post_map.empty() ||
9892
5.96k
                !ada::idna::is_label_valid(post_map)) {
9893
118
              accept_decoded = false;
9894
118
            }
9895
6.03k
          }
9896
7.15k
        }
9897
9898
8.11k
        if (accept_decoded) {
9899
#ifdef ADA_USE_SIMDUTF
9900
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
9901
                                                           tmp_buffer.size());
9902
          size_t old_size = output.size();
9903
          output.resize(old_size + utf8_size);
9904
          size_t written = simdutf::convert_utf32_to_utf8(
9905
              tmp_buffer.data(), tmp_buffer.size(), output.data() + old_size);
9906
          if (written != utf8_size) {
9907
            // This cannot happen because punycode_to_utf32 only produces valid
9908
            // Unicode code points, but if it does (it would indicate a bug in
9909
            // punycode_to_utf32 or simdutf), we can fall back to the original
9910
            // input. This is pendantic. We have no report of such an issue and
9911
            // no reason to expect it, but we want to be robust against any such
9912
            // bug.
9913
            output.resize(old_size);
9914
            output.append(
9915
                std::string_view(input.data() + label_start, label_size));
9916
          }
9917
#else
9918
5.91k
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9919
5.91k
                                                             tmp_buffer.size());
9920
5.91k
          size_t old_size = output.size();
9921
5.91k
          output.resize(old_size + utf8_size);
9922
5.91k
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9923
5.91k
                                   output.data() + old_size);
9924
5.91k
#endif
9925
5.91k
        } else {
9926
          // ToUnicode never fails. If any step fails, return the original
9927
          // input sequence for the label.
9928
2.20k
          output.append(
9929
2.20k
              std::string_view(input.data() + label_start, label_size));
9930
2.20k
        }
9931
8.11k
      } else {
9932
        // ToUnicode never fails.  If any step fails, then the original input
9933
        // sequence is returned immediately in that step.
9934
2.17k
        output.append(std::string_view(input.data() + label_start, label_size));
9935
2.17k
      }
9936
52.9k
    } else {
9937
52.9k
      output.append(label_view);
9938
52.9k
    }
9939
9940
63.1k
    if (!is_last_label) {
9941
46.5k
      output.push_back('.');
9942
46.5k
    }
9943
9944
63.1k
    label_start += label_size + 1;
9945
63.1k
  }
9946
9947
17.4k
  return output;
9948
17.4k
}
9949
}  // namespace ada::idna
9950
/* end file src/to_unicode.cpp */
9951
/* begin file src/identifier.cpp */
9952
9953
#include <algorithm>
9954
#include <array>
9955
#include <span>
9956
#include <string>
9957
9958
/* begin file src/id_tables.cpp */
9959
// IDNA  17.0.0
9960
9961
// clang-format off
9962
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
9963
#define ADA_IDNA_IDENTIFIER_TABLES_H
9964
#include <cstdint>
9965
9966
namespace ada::idna {
9967
9968
const uint32_t id_continue[1418][2] =
9969
{
9970
  {48, 57}, {65, 90}, {95, 95}, {97, 122},
9971
  {170, 170}, {181, 181}, {183, 183}, {186, 186},
9972
  {192, 214}, {216, 246}, {248, 442}, {443, 443},
9973
  {444, 447}, {448, 451}, {452, 659}, {660, 661},
9974
  {662, 687}, {688, 705}, {710, 721}, {736, 740},
9975
  {748, 748}, {750, 750}, {768, 879}, {880, 883},
9976
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
9977
  {895, 895}, {902, 902}, {903, 903}, {904, 906},
9978
  {908, 908}, {910, 929}, {931, 1013}, {1015, 1153},
9979
  {1155, 1159}, {1162, 1327}, {1329, 1366}, {1369, 1369},
9980
  {1376, 1416}, {1425, 1469}, {1471, 1471}, {1473, 1474},
9981
  {1476, 1477}, {1479, 1479}, {1488, 1514}, {1519, 1522},
9982
  {1552, 1562}, {1568, 1599}, {1600, 1600}, {1601, 1610},
9983
  {1611, 1631}, {1632, 1641}, {1646, 1647}, {1648, 1648},
9984
  {1649, 1747}, {1749, 1749}, {1750, 1756}, {1759, 1764},
9985
  {1765, 1766}, {1767, 1768}, {1770, 1773}, {1774, 1775},
9986
  {1776, 1785}, {1786, 1788}, {1791, 1791}, {1808, 1808},
9987
  {1809, 1809}, {1810, 1839}, {1840, 1866}, {1869, 1957},
9988
  {1958, 1968}, {1969, 1969}, {1984, 1993}, {1994, 2026},
9989
  {2027, 2035}, {2036, 2037}, {2042, 2042}, {2045, 2045},
9990
  {2048, 2069}, {2070, 2073}, {2074, 2074}, {2075, 2083},
9991
  {2084, 2084}, {2085, 2087}, {2088, 2088}, {2089, 2093},
9992
  {2112, 2136}, {2137, 2139}, {2144, 2154}, {2160, 2183},
9993
  {2185, 2191}, {2199, 2207}, {2208, 2248}, {2249, 2249},
9994
  {2250, 2273}, {2275, 2306}, {2307, 2307}, {2308, 2361},
9995
  {2362, 2362}, {2363, 2363}, {2364, 2364}, {2365, 2365},
9996
  {2366, 2368}, {2369, 2376}, {2377, 2380}, {2381, 2381},
9997
  {2382, 2383}, {2384, 2384}, {2385, 2391}, {2392, 2401},
9998
  {2402, 2403}, {2406, 2415}, {2417, 2417}, {2418, 2432},
9999
  {2433, 2433}, {2434, 2435}, {2437, 2444}, {2447, 2448},
10000
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10001
  {2492, 2492}, {2493, 2493}, {2494, 2496}, {2497, 2500},
10002
  {2503, 2504}, {2507, 2508}, {2509, 2509}, {2510, 2510},
10003
  {2519, 2519}, {2524, 2525}, {2527, 2529}, {2530, 2531},
10004
  {2534, 2543}, {2544, 2545}, {2556, 2556}, {2558, 2558},
10005
  {2561, 2562}, {2563, 2563}, {2565, 2570}, {2575, 2576},
10006
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10007
  {2616, 2617}, {2620, 2620}, {2622, 2624}, {2625, 2626},
10008
  {2631, 2632}, {2635, 2637}, {2641, 2641}, {2649, 2652},
10009
  {2654, 2654}, {2662, 2671}, {2672, 2673}, {2674, 2676},
10010
  {2677, 2677}, {2689, 2690}, {2691, 2691}, {2693, 2701},
10011
  {2703, 2705}, {2707, 2728}, {2730, 2736}, {2738, 2739},
10012
  {2741, 2745}, {2748, 2748}, {2749, 2749}, {2750, 2752},
10013
  {2753, 2757}, {2759, 2760}, {2761, 2761}, {2763, 2764},
10014
  {2765, 2765}, {2768, 2768}, {2784, 2785}, {2786, 2787},
10015
  {2790, 2799}, {2809, 2809}, {2810, 2815}, {2817, 2817},
10016
  {2818, 2819}, {2821, 2828}, {2831, 2832}, {2835, 2856},
10017
  {2858, 2864}, {2866, 2867}, {2869, 2873}, {2876, 2876},
10018
  {2877, 2877}, {2878, 2878}, {2879, 2879}, {2880, 2880},
10019
  {2881, 2884}, {2887, 2888}, {2891, 2892}, {2893, 2893},
10020
  {2901, 2902}, {2903, 2903}, {2908, 2909}, {2911, 2913},
10021
  {2914, 2915}, {2918, 2927}, {2929, 2929}, {2946, 2946},
10022
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10023
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10024
  {2984, 2986}, {2990, 3001}, {3006, 3007}, {3008, 3008},
10025
  {3009, 3010}, {3014, 3016}, {3018, 3020}, {3021, 3021},
10026
  {3024, 3024}, {3031, 3031}, {3046, 3055}, {3072, 3072},
10027
  {3073, 3075}, {3076, 3076}, {3077, 3084}, {3086, 3088},
10028
  {3090, 3112}, {3114, 3129}, {3132, 3132}, {3133, 3133},
10029
  {3134, 3136}, {3137, 3140}, {3142, 3144}, {3146, 3149},
10030
  {3157, 3158}, {3160, 3162}, {3164, 3165}, {3168, 3169},
10031
  {3170, 3171}, {3174, 3183}, {3200, 3200}, {3201, 3201},
10032
  {3202, 3203}, {3205, 3212}, {3214, 3216}, {3218, 3240},
10033
  {3242, 3251}, {3253, 3257}, {3260, 3260}, {3261, 3261},
10034
  {3262, 3262}, {3263, 3263}, {3264, 3268}, {3270, 3270},
10035
  {3271, 3272}, {3274, 3275}, {3276, 3277}, {3285, 3286},
10036
  {3292, 3294}, {3296, 3297}, {3298, 3299}, {3302, 3311},
10037
  {3313, 3314}, {3315, 3315}, {3328, 3329}, {3330, 3331},
10038
  {3332, 3340}, {3342, 3344}, {3346, 3386}, {3387, 3388},
10039
  {3389, 3389}, {3390, 3392}, {3393, 3396}, {3398, 3400},
10040
  {3402, 3404}, {3405, 3405}, {3406, 3406}, {3412, 3414},
10041
  {3415, 3415}, {3423, 3425}, {3426, 3427}, {3430, 3439},
10042
  {3450, 3455}, {3457, 3457}, {3458, 3459}, {3461, 3478},
10043
  {3482, 3505}, {3507, 3515}, {3517, 3517}, {3520, 3526},
10044
  {3530, 3530}, {3535, 3537}, {3538, 3540}, {3542, 3542},
10045
  {3544, 3551}, {3558, 3567}, {3570, 3571}, {3585, 3632},
10046
  {3633, 3633}, {3634, 3635}, {3636, 3642}, {3648, 3653},
10047
  {3654, 3654}, {3655, 3662}, {3664, 3673}, {3713, 3714},
10048
  {3716, 3716}, {3718, 3722}, {3724, 3747}, {3749, 3749},
10049
  {3751, 3760}, {3761, 3761}, {3762, 3763}, {3764, 3772},
10050
  {3773, 3773}, {3776, 3780}, {3782, 3782}, {3784, 3790},
10051
  {3792, 3801}, {3804, 3807}, {3840, 3840}, {3864, 3865},
10052
  {3872, 3881}, {3893, 3893}, {3895, 3895}, {3897, 3897},
10053
  {3902, 3903}, {3904, 3911}, {3913, 3948}, {3953, 3966},
10054
  {3967, 3967}, {3968, 3972}, {3974, 3975}, {3976, 3980},
10055
  {3981, 3991}, {3993, 4028}, {4038, 4038}, {4096, 4138},
10056
  {4139, 4140}, {4141, 4144}, {4145, 4145}, {4146, 4151},
10057
  {4152, 4152}, {4153, 4154}, {4155, 4156}, {4157, 4158},
10058
  {4159, 4159}, {4160, 4169}, {4176, 4181}, {4182, 4183},
10059
  {4184, 4185}, {4186, 4189}, {4190, 4192}, {4193, 4193},
10060
  {4194, 4196}, {4197, 4198}, {4199, 4205}, {4206, 4208},
10061
  {4209, 4212}, {4213, 4225}, {4226, 4226}, {4227, 4228},
10062
  {4229, 4230}, {4231, 4236}, {4237, 4237}, {4238, 4238},
10063
  {4239, 4239}, {4240, 4249}, {4250, 4252}, {4253, 4253},
10064
  {4256, 4293}, {4295, 4295}, {4301, 4301}, {4304, 4346},
10065
  {4348, 4348}, {4349, 4351}, {4352, 4680}, {4682, 4685},
10066
  {4688, 4694}, {4696, 4696}, {4698, 4701}, {4704, 4744},
10067
  {4746, 4749}, {4752, 4784}, {4786, 4789}, {4792, 4798},
10068
  {4800, 4800}, {4802, 4805}, {4808, 4822}, {4824, 4880},
10069
  {4882, 4885}, {4888, 4954}, {4957, 4959}, {4969, 4977},
10070
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10071
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10072
  {5873, 5880}, {5888, 5905}, {5906, 5908}, {5909, 5909},
10073
  {5919, 5937}, {5938, 5939}, {5940, 5940}, {5952, 5969},
10074
  {5970, 5971}, {5984, 5996}, {5998, 6000}, {6002, 6003},
10075
  {6016, 6067}, {6068, 6069}, {6070, 6070}, {6071, 6077},
10076
  {6078, 6085}, {6086, 6086}, {6087, 6088}, {6089, 6099},
10077
  {6103, 6103}, {6108, 6108}, {6109, 6109}, {6112, 6121},
10078
  {6155, 6157}, {6159, 6159}, {6160, 6169}, {6176, 6210},
10079
  {6211, 6211}, {6212, 6264}, {6272, 6276}, {6277, 6278},
10080
  {6279, 6312}, {6313, 6313}, {6314, 6314}, {6320, 6389},
10081
  {6400, 6430}, {6432, 6434}, {6435, 6438}, {6439, 6440},
10082
  {6441, 6443}, {6448, 6449}, {6450, 6450}, {6451, 6456},
10083
  {6457, 6459}, {6470, 6479}, {6480, 6509}, {6512, 6516},
10084
  {6528, 6571}, {6576, 6601}, {6608, 6617}, {6618, 6618},
10085
  {6656, 6678}, {6679, 6680}, {6681, 6682}, {6683, 6683},
10086
  {6688, 6740}, {6741, 6741}, {6742, 6742}, {6743, 6743},
10087
  {6744, 6750}, {6752, 6752}, {6753, 6753}, {6754, 6754},
10088
  {6755, 6756}, {6757, 6764}, {6765, 6770}, {6771, 6780},
10089
  {6783, 6783}, {6784, 6793}, {6800, 6809}, {6823, 6823},
10090
  {6832, 6845}, {6847, 6877}, {6880, 6891}, {6912, 6915},
10091
  {6916, 6916}, {6917, 6963}, {6964, 6964}, {6965, 6965},
10092
  {6966, 6970}, {6971, 6971}, {6972, 6972}, {6973, 6977},
10093
  {6978, 6978}, {6979, 6980}, {6981, 6988}, {6992, 7001},
10094
  {7019, 7027}, {7040, 7041}, {7042, 7042}, {7043, 7072},
10095
  {7073, 7073}, {7074, 7077}, {7078, 7079}, {7080, 7081},
10096
  {7082, 7082}, {7083, 7085}, {7086, 7087}, {7088, 7097},
10097
  {7098, 7141}, {7142, 7142}, {7143, 7143}, {7144, 7145},
10098
  {7146, 7148}, {7149, 7149}, {7150, 7150}, {7151, 7153},
10099
  {7154, 7155}, {7168, 7203}, {7204, 7211}, {7212, 7219},
10100
  {7220, 7221}, {7222, 7223}, {7232, 7241}, {7245, 7247},
10101
  {7248, 7257}, {7258, 7287}, {7288, 7293}, {7296, 7306},
10102
  {7312, 7354}, {7357, 7359}, {7376, 7378}, {7380, 7392},
10103
  {7393, 7393}, {7394, 7400}, {7401, 7404}, {7405, 7405},
10104
  {7406, 7411}, {7412, 7412}, {7413, 7414}, {7415, 7415},
10105
  {7416, 7417}, {7418, 7418}, {7424, 7467}, {7468, 7530},
10106
  {7531, 7543}, {7544, 7544}, {7545, 7578}, {7579, 7615},
10107
  {7616, 7679}, {7680, 7957}, {7960, 7965}, {7968, 8005},
10108
  {8008, 8013}, {8016, 8023}, {8025, 8025}, {8027, 8027},
10109
  {8029, 8029}, {8031, 8061}, {8064, 8116}, {8118, 8124},
10110
  {8126, 8126}, {8130, 8132}, {8134, 8140}, {8144, 8147},
10111
  {8150, 8155}, {8160, 8172}, {8178, 8180}, {8182, 8188},
10112
  {8204, 8205}, {8255, 8256}, {8276, 8276}, {8305, 8305},
10113
  {8319, 8319}, {8336, 8348}, {8400, 8412}, {8417, 8417},
10114
  {8421, 8432}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10115
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10116
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10117
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10118
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10119
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10120
  {11499, 11502}, {11503, 11505}, {11506, 11507}, {11520, 11557},
10121
  {11559, 11559}, {11565, 11565}, {11568, 11623}, {11631, 11631},
10122
  {11647, 11647}, {11648, 11670}, {11680, 11686}, {11688, 11694},
10123
  {11696, 11702}, {11704, 11710}, {11712, 11718}, {11720, 11726},
10124
  {11728, 11734}, {11736, 11742}, {11744, 11775}, {12293, 12293},
10125
  {12294, 12294}, {12295, 12295}, {12321, 12329}, {12330, 12333},
10126
  {12334, 12335}, {12337, 12341}, {12344, 12346}, {12347, 12347},
10127
  {12348, 12348}, {12353, 12438}, {12441, 12442}, {12443, 12444},
10128
  {12445, 12446}, {12447, 12447}, {12449, 12538}, {12539, 12539},
10129
  {12540, 12542}, {12543, 12543}, {12549, 12591}, {12593, 12686},
10130
  {12704, 12735}, {12784, 12799}, {13312, 19903}, {19968, 40980},
10131
  {40981, 40981}, {40982, 42124}, {42192, 42231}, {42232, 42237},
10132
  {42240, 42507}, {42508, 42508}, {42512, 42527}, {42528, 42537},
10133
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42607, 42607},
10134
  {42612, 42621}, {42623, 42623}, {42624, 42651}, {42652, 42653},
10135
  {42654, 42655}, {42656, 42725}, {42726, 42735}, {42736, 42737},
10136
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10137
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10138
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10139
  {43002, 43002}, {43003, 43009}, {43010, 43010}, {43011, 43013},
10140
  {43014, 43014}, {43015, 43018}, {43019, 43019}, {43020, 43042},
10141
  {43043, 43044}, {43045, 43046}, {43047, 43047}, {43052, 43052},
10142
  {43072, 43123}, {43136, 43137}, {43138, 43187}, {43188, 43203},
10143
  {43204, 43205}, {43216, 43225}, {43232, 43249}, {43250, 43255},
10144
  {43259, 43259}, {43261, 43262}, {43263, 43263}, {43264, 43273},
10145
  {43274, 43301}, {43302, 43309}, {43312, 43334}, {43335, 43345},
10146
  {43346, 43347}, {43360, 43388}, {43392, 43394}, {43395, 43395},
10147
  {43396, 43442}, {43443, 43443}, {43444, 43445}, {43446, 43449},
10148
  {43450, 43451}, {43452, 43453}, {43454, 43456}, {43471, 43471},
10149
  {43472, 43481}, {43488, 43492}, {43493, 43493}, {43494, 43494},
10150
  {43495, 43503}, {43504, 43513}, {43514, 43518}, {43520, 43560},
10151
  {43561, 43566}, {43567, 43568}, {43569, 43570}, {43571, 43572},
10152
  {43573, 43574}, {43584, 43586}, {43587, 43587}, {43588, 43595},
10153
  {43596, 43596}, {43597, 43597}, {43600, 43609}, {43616, 43631},
10154
  {43632, 43632}, {43633, 43638}, {43642, 43642}, {43643, 43643},
10155
  {43644, 43644}, {43645, 43645}, {43646, 43695}, {43696, 43696},
10156
  {43697, 43697}, {43698, 43700}, {43701, 43702}, {43703, 43704},
10157
  {43705, 43709}, {43710, 43711}, {43712, 43712}, {43713, 43713},
10158
  {43714, 43714}, {43739, 43740}, {43741, 43741}, {43744, 43754},
10159
  {43755, 43755}, {43756, 43757}, {43758, 43759}, {43762, 43762},
10160
  {43763, 43764}, {43765, 43765}, {43766, 43766}, {43777, 43782},
10161
  {43785, 43790}, {43793, 43798}, {43808, 43814}, {43816, 43822},
10162
  {43824, 43866}, {43868, 43871}, {43872, 43880}, {43881, 43881},
10163
  {43888, 43967}, {43968, 44002}, {44003, 44004}, {44005, 44005},
10164
  {44006, 44007}, {44008, 44008}, {44009, 44010}, {44012, 44012},
10165
  {44013, 44013}, {44016, 44025}, {44032, 55203}, {55216, 55238},
10166
  {55243, 55291}, {63744, 64109}, {64112, 64217}, {64256, 64262},
10167
  {64275, 64279}, {64285, 64285}, {64286, 64286}, {64287, 64296},
10168
  {64298, 64310}, {64312, 64316}, {64318, 64318}, {64320, 64321},
10169
  {64323, 64324}, {64326, 64433}, {64467, 64829}, {64848, 64911},
10170
  {64914, 64967}, {65008, 65019}, {65024, 65039}, {65056, 65071},
10171
  {65075, 65076}, {65101, 65103}, {65136, 65140}, {65142, 65276},
10172
  {65296, 65305}, {65313, 65338}, {65343, 65343}, {65345, 65370},
10173
  {65381, 65381}, {65382, 65391}, {65392, 65392}, {65393, 65437},
10174
  {65438, 65439}, {65440, 65470}, {65474, 65479}, {65482, 65487},
10175
  {65490, 65495}, {65498, 65500}, {65536, 65547}, {65549, 65574},
10176
  {65576, 65594}, {65596, 65597}, {65599, 65613}, {65616, 65629},
10177
  {65664, 65786}, {65856, 65908}, {66045, 66045}, {66176, 66204},
10178
  {66208, 66256}, {66272, 66272}, {66304, 66335}, {66349, 66368},
10179
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10180
  {66422, 66426}, {66432, 66461}, {66464, 66499}, {66504, 66511},
10181
  {66513, 66517}, {66560, 66639}, {66640, 66717}, {66720, 66729},
10182
  {66736, 66771}, {66776, 66811}, {66816, 66855}, {66864, 66915},
10183
  {66928, 66938}, {66940, 66954}, {66956, 66962}, {66964, 66965},
10184
  {66967, 66977}, {66979, 66993}, {66995, 67001}, {67003, 67004},
10185
  {67008, 67059}, {67072, 67382}, {67392, 67413}, {67424, 67431},
10186
  {67456, 67461}, {67463, 67504}, {67506, 67514}, {67584, 67589},
10187
  {67592, 67592}, {67594, 67637}, {67639, 67640}, {67644, 67644},
10188
  {67647, 67669}, {67680, 67702}, {67712, 67742}, {67808, 67826},
10189
  {67828, 67829}, {67840, 67861}, {67872, 67897}, {67904, 67929},
10190
  {67968, 68023}, {68030, 68031}, {68096, 68096}, {68097, 68099},
10191
  {68101, 68102}, {68108, 68111}, {68112, 68115}, {68117, 68119},
10192
  {68121, 68149}, {68152, 68154}, {68159, 68159}, {68192, 68220},
10193
  {68224, 68252}, {68288, 68295}, {68297, 68324}, {68325, 68326},
10194
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10195
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10196
  {68900, 68903}, {68912, 68921}, {68928, 68937}, {68938, 68941},
10197
  {68942, 68942}, {68943, 68943}, {68944, 68965}, {68969, 68973},
10198
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69291, 69292},
10199
  {69296, 69297}, {69314, 69316}, {69317, 69317}, {69318, 69319},
10200
  {69370, 69375}, {69376, 69404}, {69415, 69415}, {69424, 69445},
10201
  {69446, 69456}, {69488, 69505}, {69506, 69509}, {69552, 69572},
10202
  {69600, 69622}, {69632, 69632}, {69633, 69633}, {69634, 69634},
10203
  {69635, 69687}, {69688, 69702}, {69734, 69743}, {69744, 69744},
10204
  {69745, 69746}, {69747, 69748}, {69749, 69749}, {69759, 69761},
10205
  {69762, 69762}, {69763, 69807}, {69808, 69810}, {69811, 69814},
10206
  {69815, 69816}, {69817, 69818}, {69826, 69826}, {69840, 69864},
10207
  {69872, 69881}, {69888, 69890}, {69891, 69926}, {69927, 69931},
10208
  {69932, 69932}, {69933, 69940}, {69942, 69951}, {69956, 69956},
10209
  {69957, 69958}, {69959, 69959}, {69968, 70002}, {70003, 70003},
10210
  {70006, 70006}, {70016, 70017}, {70018, 70018}, {70019, 70066},
10211
  {70067, 70069}, {70070, 70078}, {70079, 70080}, {70081, 70084},
10212
  {70089, 70092}, {70094, 70094}, {70095, 70095}, {70096, 70105},
10213
  {70106, 70106}, {70108, 70108}, {70144, 70161}, {70163, 70187},
10214
  {70188, 70190}, {70191, 70193}, {70194, 70195}, {70196, 70196},
10215
  {70197, 70197}, {70198, 70199}, {70206, 70206}, {70207, 70208},
10216
  {70209, 70209}, {70272, 70278}, {70280, 70280}, {70282, 70285},
10217
  {70287, 70301}, {70303, 70312}, {70320, 70366}, {70367, 70367},
10218
  {70368, 70370}, {70371, 70378}, {70384, 70393}, {70400, 70401},
10219
  {70402, 70403}, {70405, 70412}, {70415, 70416}, {70419, 70440},
10220
  {70442, 70448}, {70450, 70451}, {70453, 70457}, {70459, 70460},
10221
  {70461, 70461}, {70462, 70463}, {70464, 70464}, {70465, 70468},
10222
  {70471, 70472}, {70475, 70477}, {70480, 70480}, {70487, 70487},
10223
  {70493, 70497}, {70498, 70499}, {70502, 70508}, {70512, 70516},
10224
  {70528, 70537}, {70539, 70539}, {70542, 70542}, {70544, 70581},
10225
  {70583, 70583}, {70584, 70586}, {70587, 70592}, {70594, 70594},
10226
  {70597, 70597}, {70599, 70602}, {70604, 70605}, {70606, 70606},
10227
  {70607, 70607}, {70608, 70608}, {70609, 70609}, {70610, 70610},
10228
  {70611, 70611}, {70625, 70626}, {70656, 70708}, {70709, 70711},
10229
  {70712, 70719}, {70720, 70721}, {70722, 70724}, {70725, 70725},
10230
  {70726, 70726}, {70727, 70730}, {70736, 70745}, {70750, 70750},
10231
  {70751, 70753}, {70784, 70831}, {70832, 70834}, {70835, 70840},
10232
  {70841, 70841}, {70842, 70842}, {70843, 70846}, {70847, 70848},
10233
  {70849, 70849}, {70850, 70851}, {70852, 70853}, {70855, 70855},
10234
  {70864, 70873}, {71040, 71086}, {71087, 71089}, {71090, 71093},
10235
  {71096, 71099}, {71100, 71101}, {71102, 71102}, {71103, 71104},
10236
  {71128, 71131}, {71132, 71133}, {71168, 71215}, {71216, 71218},
10237
  {71219, 71226}, {71227, 71228}, {71229, 71229}, {71230, 71230},
10238
  {71231, 71232}, {71236, 71236}, {71248, 71257}, {71296, 71338},
10239
  {71339, 71339}, {71340, 71340}, {71341, 71341}, {71342, 71343},
10240
  {71344, 71349}, {71350, 71350}, {71351, 71351}, {71352, 71352},
10241
  {71360, 71369}, {71376, 71395}, {71424, 71450}, {71453, 71453},
10242
  {71454, 71454}, {71455, 71455}, {71456, 71457}, {71458, 71461},
10243
  {71462, 71462}, {71463, 71467}, {71472, 71481}, {71488, 71494},
10244
  {71680, 71723}, {71724, 71726}, {71727, 71735}, {71736, 71736},
10245
  {71737, 71738}, {71840, 71903}, {71904, 71913}, {71935, 71942},
10246
  {71945, 71945}, {71948, 71955}, {71957, 71958}, {71960, 71983},
10247
  {71984, 71989}, {71991, 71992}, {71995, 71996}, {71997, 71997},
10248
  {71998, 71998}, {71999, 71999}, {72000, 72000}, {72001, 72001},
10249
  {72002, 72002}, {72003, 72003}, {72016, 72025}, {72096, 72103},
10250
  {72106, 72144}, {72145, 72147}, {72148, 72151}, {72154, 72155},
10251
  {72156, 72159}, {72160, 72160}, {72161, 72161}, {72163, 72163},
10252
  {72164, 72164}, {72192, 72192}, {72193, 72202}, {72203, 72242},
10253
  {72243, 72248}, {72249, 72249}, {72250, 72250}, {72251, 72254},
10254
  {72263, 72263}, {72272, 72272}, {72273, 72278}, {72279, 72280},
10255
  {72281, 72283}, {72284, 72329}, {72330, 72342}, {72343, 72343},
10256
  {72344, 72345}, {72349, 72349}, {72368, 72440}, {72544, 72544},
10257
  {72545, 72545}, {72546, 72548}, {72549, 72549}, {72550, 72550},
10258
  {72551, 72551}, {72640, 72672}, {72688, 72697}, {72704, 72712},
10259
  {72714, 72750}, {72751, 72751}, {72752, 72758}, {72760, 72765},
10260
  {72766, 72766}, {72767, 72767}, {72768, 72768}, {72784, 72793},
10261
  {72818, 72847}, {72850, 72871}, {72873, 72873}, {72874, 72880},
10262
  {72881, 72881}, {72882, 72883}, {72884, 72884}, {72885, 72886},
10263
  {72960, 72966}, {72968, 72969}, {72971, 73008}, {73009, 73014},
10264
  {73018, 73018}, {73020, 73021}, {73023, 73029}, {73030, 73030},
10265
  {73031, 73031}, {73040, 73049}, {73056, 73061}, {73063, 73064},
10266
  {73066, 73097}, {73098, 73102}, {73104, 73105}, {73107, 73108},
10267
  {73109, 73109}, {73110, 73110}, {73111, 73111}, {73112, 73112},
10268
  {73120, 73129}, {73136, 73176}, {73177, 73177}, {73178, 73179},
10269
  {73184, 73193}, {73440, 73458}, {73459, 73460}, {73461, 73462},
10270
  {73472, 73473}, {73474, 73474}, {73475, 73475}, {73476, 73488},
10271
  {73490, 73523}, {73524, 73525}, {73526, 73530}, {73534, 73535},
10272
  {73536, 73536}, {73537, 73537}, {73538, 73538}, {73552, 73561},
10273
  {73562, 73562}, {73648, 73648}, {73728, 74649}, {74752, 74862},
10274
  {74880, 75075}, {77712, 77808}, {77824, 78895}, {78912, 78912},
10275
  {78913, 78918}, {78919, 78933}, {78944, 82938}, {82944, 83526},
10276
  {90368, 90397}, {90398, 90409}, {90410, 90412}, {90413, 90415},
10277
  {90416, 90425}, {92160, 92728}, {92736, 92766}, {92768, 92777},
10278
  {92784, 92862}, {92864, 92873}, {92880, 92909}, {92912, 92916},
10279
  {92928, 92975}, {92976, 92982}, {92992, 92995}, {93008, 93017},
10280
  {93027, 93047}, {93053, 93071}, {93504, 93506}, {93507, 93546},
10281
  {93547, 93548}, {93552, 93561}, {93760, 93823}, {93856, 93880},
10282
  {93883, 93907}, {93952, 94026}, {94031, 94031}, {94032, 94032},
10283
  {94033, 94087}, {94095, 94098}, {94099, 94111}, {94176, 94177},
10284
  {94179, 94179}, {94180, 94180}, {94192, 94193}, {94194, 94195},
10285
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10286
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10287
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10288
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10289
  {113808, 113817}, {113821, 113822}, {118000, 118009}, {118528, 118573},
10290
  {118576, 118598}, {119141, 119142}, {119143, 119145}, {119149, 119154},
10291
  {119163, 119170}, {119173, 119179}, {119210, 119213}, {119362, 119364},
10292
  {119808, 119892}, {119894, 119964}, {119966, 119967}, {119970, 119970},
10293
  {119973, 119974}, {119977, 119980}, {119982, 119993}, {119995, 119995},
10294
  {119997, 120003}, {120005, 120069}, {120071, 120074}, {120077, 120084},
10295
  {120086, 120092}, {120094, 120121}, {120123, 120126}, {120128, 120132},
10296
  {120134, 120134}, {120138, 120144}, {120146, 120485}, {120488, 120512},
10297
  {120514, 120538}, {120540, 120570}, {120572, 120596}, {120598, 120628},
10298
  {120630, 120654}, {120656, 120686}, {120688, 120712}, {120714, 120744},
10299
  {120746, 120770}, {120772, 120779}, {120782, 120831}, {121344, 121398},
10300
  {121403, 121452}, {121461, 121461}, {121476, 121476}, {121499, 121503},
10301
  {121505, 121519}, {122624, 122633}, {122634, 122634}, {122635, 122654},
10302
  {122661, 122666}, {122880, 122886}, {122888, 122904}, {122907, 122913},
10303
  {122915, 122916}, {122918, 122922}, {122928, 122989}, {123023, 123023},
10304
  {123136, 123180}, {123184, 123190}, {123191, 123197}, {123200, 123209},
10305
  {123214, 123214}, {123536, 123565}, {123566, 123566}, {123584, 123627},
10306
  {123628, 123631}, {123632, 123641}, {124112, 124138}, {124139, 124139},
10307
  {124140, 124143}, {124144, 124153}, {124368, 124397}, {124398, 124399},
10308
  {124400, 124400}, {124401, 124410}, {124608, 124638}, {124640, 124642},
10309
  {124643, 124643}, {124644, 124645}, {124646, 124646}, {124647, 124653},
10310
  {124654, 124655}, {124656, 124660}, {124661, 124661}, {124670, 124670},
10311
  {124671, 124671}, {124896, 124902}, {124904, 124907}, {124909, 124910},
10312
  {124912, 124926}, {124928, 125124}, {125136, 125142}, {125184, 125251},
10313
  {125252, 125258}, {125259, 125259}, {125264, 125273}, {126464, 126467},
10314
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10315
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10316
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10317
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10318
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10319
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10320
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10321
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10322
  {130032, 130041}, {131072, 173791}, {173824, 178205}, {178208, 183981},
10323
  {183984, 191456}, {191472, 192093}, {194560, 195101}, {196608, 201546},
10324
  {201552, 210041}, {917760, 917999}
10325
};
10326
const uint32_t id_start[776][2] =
10327
{
10328
  {65, 90}, {97, 122}, {170, 170}, {181, 181},
10329
  {186, 186}, {192, 214}, {216, 246}, {248, 442},
10330
  {443, 443}, {444, 447}, {448, 451}, {452, 659},
10331
  {660, 661}, {662, 687}, {688, 705}, {710, 721},
10332
  {736, 740}, {748, 748}, {750, 750}, {880, 883},
10333
  {884, 884}, {886, 887}, {890, 890}, {891, 893},
10334
  {895, 895}, {902, 902}, {904, 906}, {908, 908},
10335
  {910, 929}, {931, 1013}, {1015, 1153}, {1162, 1327},
10336
  {1329, 1366}, {1369, 1369}, {1376, 1416}, {1488, 1514},
10337
  {1519, 1522}, {1568, 1599}, {1600, 1600}, {1601, 1610},
10338
  {1646, 1647}, {1649, 1747}, {1749, 1749}, {1765, 1766},
10339
  {1774, 1775}, {1786, 1788}, {1791, 1791}, {1808, 1808},
10340
  {1810, 1839}, {1869, 1957}, {1969, 1969}, {1994, 2026},
10341
  {2036, 2037}, {2042, 2042}, {2048, 2069}, {2074, 2074},
10342
  {2084, 2084}, {2088, 2088}, {2112, 2136}, {2144, 2154},
10343
  {2160, 2183}, {2185, 2191}, {2208, 2248}, {2249, 2249},
10344
  {2308, 2361}, {2365, 2365}, {2384, 2384}, {2392, 2401},
10345
  {2417, 2417}, {2418, 2432}, {2437, 2444}, {2447, 2448},
10346
  {2451, 2472}, {2474, 2480}, {2482, 2482}, {2486, 2489},
10347
  {2493, 2493}, {2510, 2510}, {2524, 2525}, {2527, 2529},
10348
  {2544, 2545}, {2556, 2556}, {2565, 2570}, {2575, 2576},
10349
  {2579, 2600}, {2602, 2608}, {2610, 2611}, {2613, 2614},
10350
  {2616, 2617}, {2649, 2652}, {2654, 2654}, {2674, 2676},
10351
  {2693, 2701}, {2703, 2705}, {2707, 2728}, {2730, 2736},
10352
  {2738, 2739}, {2741, 2745}, {2749, 2749}, {2768, 2768},
10353
  {2784, 2785}, {2809, 2809}, {2821, 2828}, {2831, 2832},
10354
  {2835, 2856}, {2858, 2864}, {2866, 2867}, {2869, 2873},
10355
  {2877, 2877}, {2908, 2909}, {2911, 2913}, {2929, 2929},
10356
  {2947, 2947}, {2949, 2954}, {2958, 2960}, {2962, 2965},
10357
  {2969, 2970}, {2972, 2972}, {2974, 2975}, {2979, 2980},
10358
  {2984, 2986}, {2990, 3001}, {3024, 3024}, {3077, 3084},
10359
  {3086, 3088}, {3090, 3112}, {3114, 3129}, {3133, 3133},
10360
  {3160, 3162}, {3164, 3165}, {3168, 3169}, {3200, 3200},
10361
  {3205, 3212}, {3214, 3216}, {3218, 3240}, {3242, 3251},
10362
  {3253, 3257}, {3261, 3261}, {3292, 3294}, {3296, 3297},
10363
  {3313, 3314}, {3332, 3340}, {3342, 3344}, {3346, 3386},
10364
  {3389, 3389}, {3406, 3406}, {3412, 3414}, {3423, 3425},
10365
  {3450, 3455}, {3461, 3478}, {3482, 3505}, {3507, 3515},
10366
  {3517, 3517}, {3520, 3526}, {3585, 3632}, {3634, 3635},
10367
  {3648, 3653}, {3654, 3654}, {3713, 3714}, {3716, 3716},
10368
  {3718, 3722}, {3724, 3747}, {3749, 3749}, {3751, 3760},
10369
  {3762, 3763}, {3773, 3773}, {3776, 3780}, {3782, 3782},
10370
  {3804, 3807}, {3840, 3840}, {3904, 3911}, {3913, 3948},
10371
  {3976, 3980}, {4096, 4138}, {4159, 4159}, {4176, 4181},
10372
  {4186, 4189}, {4193, 4193}, {4197, 4198}, {4206, 4208},
10373
  {4213, 4225}, {4238, 4238}, {4256, 4293}, {4295, 4295},
10374
  {4301, 4301}, {4304, 4346}, {4348, 4348}, {4349, 4351},
10375
  {4352, 4680}, {4682, 4685}, {4688, 4694}, {4696, 4696},
10376
  {4698, 4701}, {4704, 4744}, {4746, 4749}, {4752, 4784},
10377
  {4786, 4789}, {4792, 4798}, {4800, 4800}, {4802, 4805},
10378
  {4808, 4822}, {4824, 4880}, {4882, 4885}, {4888, 4954},
10379
  {4992, 5007}, {5024, 5109}, {5112, 5117}, {5121, 5740},
10380
  {5743, 5759}, {5761, 5786}, {5792, 5866}, {5870, 5872},
10381
  {5873, 5880}, {5888, 5905}, {5919, 5937}, {5952, 5969},
10382
  {5984, 5996}, {5998, 6000}, {6016, 6067}, {6103, 6103},
10383
  {6108, 6108}, {6176, 6210}, {6211, 6211}, {6212, 6264},
10384
  {6272, 6276}, {6277, 6278}, {6279, 6312}, {6314, 6314},
10385
  {6320, 6389}, {6400, 6430}, {6480, 6509}, {6512, 6516},
10386
  {6528, 6571}, {6576, 6601}, {6656, 6678}, {6688, 6740},
10387
  {6823, 6823}, {6917, 6963}, {6981, 6988}, {7043, 7072},
10388
  {7086, 7087}, {7098, 7141}, {7168, 7203}, {7245, 7247},
10389
  {7258, 7287}, {7288, 7293}, {7296, 7306}, {7312, 7354},
10390
  {7357, 7359}, {7401, 7404}, {7406, 7411}, {7413, 7414},
10391
  {7418, 7418}, {7424, 7467}, {7468, 7530}, {7531, 7543},
10392
  {7544, 7544}, {7545, 7578}, {7579, 7615}, {7680, 7957},
10393
  {7960, 7965}, {7968, 8005}, {8008, 8013}, {8016, 8023},
10394
  {8025, 8025}, {8027, 8027}, {8029, 8029}, {8031, 8061},
10395
  {8064, 8116}, {8118, 8124}, {8126, 8126}, {8130, 8132},
10396
  {8134, 8140}, {8144, 8147}, {8150, 8155}, {8160, 8172},
10397
  {8178, 8180}, {8182, 8188}, {8305, 8305}, {8319, 8319},
10398
  {8336, 8348}, {8450, 8450}, {8455, 8455}, {8458, 8467},
10399
  {8469, 8469}, {8472, 8472}, {8473, 8477}, {8484, 8484},
10400
  {8486, 8486}, {8488, 8488}, {8490, 8493}, {8494, 8494},
10401
  {8495, 8500}, {8501, 8504}, {8505, 8505}, {8508, 8511},
10402
  {8517, 8521}, {8526, 8526}, {8544, 8578}, {8579, 8580},
10403
  {8581, 8584}, {11264, 11387}, {11388, 11389}, {11390, 11492},
10404
  {11499, 11502}, {11506, 11507}, {11520, 11557}, {11559, 11559},
10405
  {11565, 11565}, {11568, 11623}, {11631, 11631}, {11648, 11670},
10406
  {11680, 11686}, {11688, 11694}, {11696, 11702}, {11704, 11710},
10407
  {11712, 11718}, {11720, 11726}, {11728, 11734}, {11736, 11742},
10408
  {12293, 12293}, {12294, 12294}, {12295, 12295}, {12321, 12329},
10409
  {12337, 12341}, {12344, 12346}, {12347, 12347}, {12348, 12348},
10410
  {12353, 12438}, {12443, 12444}, {12445, 12446}, {12447, 12447},
10411
  {12449, 12538}, {12540, 12542}, {12543, 12543}, {12549, 12591},
10412
  {12593, 12686}, {12704, 12735}, {12784, 12799}, {13312, 19903},
10413
  {19968, 40980}, {40981, 40981}, {40982, 42124}, {42192, 42231},
10414
  {42232, 42237}, {42240, 42507}, {42508, 42508}, {42512, 42527},
10415
  {42538, 42539}, {42560, 42605}, {42606, 42606}, {42623, 42623},
10416
  {42624, 42651}, {42652, 42653}, {42656, 42725}, {42726, 42735},
10417
  {42775, 42783}, {42786, 42863}, {42864, 42864}, {42865, 42887},
10418
  {42888, 42888}, {42891, 42894}, {42895, 42895}, {42896, 42972},
10419
  {42993, 42996}, {42997, 42998}, {42999, 42999}, {43000, 43001},
10420
  {43002, 43002}, {43003, 43009}, {43011, 43013}, {43015, 43018},
10421
  {43020, 43042}, {43072, 43123}, {43138, 43187}, {43250, 43255},
10422
  {43259, 43259}, {43261, 43262}, {43274, 43301}, {43312, 43334},
10423
  {43360, 43388}, {43396, 43442}, {43471, 43471}, {43488, 43492},
10424
  {43494, 43494}, {43495, 43503}, {43514, 43518}, {43520, 43560},
10425
  {43584, 43586}, {43588, 43595}, {43616, 43631}, {43632, 43632},
10426
  {43633, 43638}, {43642, 43642}, {43646, 43695}, {43697, 43697},
10427
  {43701, 43702}, {43705, 43709}, {43712, 43712}, {43714, 43714},
10428
  {43739, 43740}, {43741, 43741}, {43744, 43754}, {43762, 43762},
10429
  {43763, 43764}, {43777, 43782}, {43785, 43790}, {43793, 43798},
10430
  {43808, 43814}, {43816, 43822}, {43824, 43866}, {43868, 43871},
10431
  {43872, 43880}, {43881, 43881}, {43888, 43967}, {43968, 44002},
10432
  {44032, 55203}, {55216, 55238}, {55243, 55291}, {63744, 64109},
10433
  {64112, 64217}, {64256, 64262}, {64275, 64279}, {64285, 64285},
10434
  {64287, 64296}, {64298, 64310}, {64312, 64316}, {64318, 64318},
10435
  {64320, 64321}, {64323, 64324}, {64326, 64433}, {64467, 64829},
10436
  {64848, 64911}, {64914, 64967}, {65008, 65019}, {65136, 65140},
10437
  {65142, 65276}, {65313, 65338}, {65345, 65370}, {65382, 65391},
10438
  {65392, 65392}, {65393, 65437}, {65438, 65439}, {65440, 65470},
10439
  {65474, 65479}, {65482, 65487}, {65490, 65495}, {65498, 65500},
10440
  {65536, 65547}, {65549, 65574}, {65576, 65594}, {65596, 65597},
10441
  {65599, 65613}, {65616, 65629}, {65664, 65786}, {65856, 65908},
10442
  {66176, 66204}, {66208, 66256}, {66304, 66335}, {66349, 66368},
10443
  {66369, 66369}, {66370, 66377}, {66378, 66378}, {66384, 66421},
10444
  {66432, 66461}, {66464, 66499}, {66504, 66511}, {66513, 66517},
10445
  {66560, 66639}, {66640, 66717}, {66736, 66771}, {66776, 66811},
10446
  {66816, 66855}, {66864, 66915}, {66928, 66938}, {66940, 66954},
10447
  {66956, 66962}, {66964, 66965}, {66967, 66977}, {66979, 66993},
10448
  {66995, 67001}, {67003, 67004}, {67008, 67059}, {67072, 67382},
10449
  {67392, 67413}, {67424, 67431}, {67456, 67461}, {67463, 67504},
10450
  {67506, 67514}, {67584, 67589}, {67592, 67592}, {67594, 67637},
10451
  {67639, 67640}, {67644, 67644}, {67647, 67669}, {67680, 67702},
10452
  {67712, 67742}, {67808, 67826}, {67828, 67829}, {67840, 67861},
10453
  {67872, 67897}, {67904, 67929}, {67968, 68023}, {68030, 68031},
10454
  {68096, 68096}, {68112, 68115}, {68117, 68119}, {68121, 68149},
10455
  {68192, 68220}, {68224, 68252}, {68288, 68295}, {68297, 68324},
10456
  {68352, 68405}, {68416, 68437}, {68448, 68466}, {68480, 68497},
10457
  {68608, 68680}, {68736, 68786}, {68800, 68850}, {68864, 68899},
10458
  {68938, 68941}, {68942, 68942}, {68943, 68943}, {68944, 68965},
10459
  {68975, 68975}, {68976, 68997}, {69248, 69289}, {69296, 69297},
10460
  {69314, 69316}, {69317, 69317}, {69318, 69319}, {69376, 69404},
10461
  {69415, 69415}, {69424, 69445}, {69488, 69505}, {69552, 69572},
10462
  {69600, 69622}, {69635, 69687}, {69745, 69746}, {69749, 69749},
10463
  {69763, 69807}, {69840, 69864}, {69891, 69926}, {69956, 69956},
10464
  {69959, 69959}, {69968, 70002}, {70006, 70006}, {70019, 70066},
10465
  {70081, 70084}, {70106, 70106}, {70108, 70108}, {70144, 70161},
10466
  {70163, 70187}, {70207, 70208}, {70272, 70278}, {70280, 70280},
10467
  {70282, 70285}, {70287, 70301}, {70303, 70312}, {70320, 70366},
10468
  {70405, 70412}, {70415, 70416}, {70419, 70440}, {70442, 70448},
10469
  {70450, 70451}, {70453, 70457}, {70461, 70461}, {70480, 70480},
10470
  {70493, 70497}, {70528, 70537}, {70539, 70539}, {70542, 70542},
10471
  {70544, 70581}, {70583, 70583}, {70609, 70609}, {70611, 70611},
10472
  {70656, 70708}, {70727, 70730}, {70751, 70753}, {70784, 70831},
10473
  {70852, 70853}, {70855, 70855}, {71040, 71086}, {71128, 71131},
10474
  {71168, 71215}, {71236, 71236}, {71296, 71338}, {71352, 71352},
10475
  {71424, 71450}, {71488, 71494}, {71680, 71723}, {71840, 71903},
10476
  {71935, 71942}, {71945, 71945}, {71948, 71955}, {71957, 71958},
10477
  {71960, 71983}, {71999, 71999}, {72001, 72001}, {72096, 72103},
10478
  {72106, 72144}, {72161, 72161}, {72163, 72163}, {72192, 72192},
10479
  {72203, 72242}, {72250, 72250}, {72272, 72272}, {72284, 72329},
10480
  {72349, 72349}, {72368, 72440}, {72640, 72672}, {72704, 72712},
10481
  {72714, 72750}, {72768, 72768}, {72818, 72847}, {72960, 72966},
10482
  {72968, 72969}, {72971, 73008}, {73030, 73030}, {73056, 73061},
10483
  {73063, 73064}, {73066, 73097}, {73112, 73112}, {73136, 73176},
10484
  {73177, 73177}, {73178, 73179}, {73440, 73458}, {73474, 73474},
10485
  {73476, 73488}, {73490, 73523}, {73648, 73648}, {73728, 74649},
10486
  {74752, 74862}, {74880, 75075}, {77712, 77808}, {77824, 78895},
10487
  {78913, 78918}, {78944, 82938}, {82944, 83526}, {90368, 90397},
10488
  {92160, 92728}, {92736, 92766}, {92784, 92862}, {92880, 92909},
10489
  {92928, 92975}, {92992, 92995}, {93027, 93047}, {93053, 93071},
10490
  {93504, 93506}, {93507, 93546}, {93547, 93548}, {93760, 93823},
10491
  {93856, 93880}, {93883, 93907}, {93952, 94026}, {94032, 94032},
10492
  {94099, 94111}, {94176, 94177}, {94179, 94179}, {94194, 94195},
10493
  {94196, 94198}, {94208, 101589}, {101631, 101662}, {101760, 101874},
10494
  {110576, 110579}, {110581, 110587}, {110589, 110590}, {110592, 110882},
10495
  {110898, 110898}, {110928, 110930}, {110933, 110933}, {110948, 110951},
10496
  {110960, 111355}, {113664, 113770}, {113776, 113788}, {113792, 113800},
10497
  {113808, 113817}, {119808, 119892}, {119894, 119964}, {119966, 119967},
10498
  {119970, 119970}, {119973, 119974}, {119977, 119980}, {119982, 119993},
10499
  {119995, 119995}, {119997, 120003}, {120005, 120069}, {120071, 120074},
10500
  {120077, 120084}, {120086, 120092}, {120094, 120121}, {120123, 120126},
10501
  {120128, 120132}, {120134, 120134}, {120138, 120144}, {120146, 120485},
10502
  {120488, 120512}, {120514, 120538}, {120540, 120570}, {120572, 120596},
10503
  {120598, 120628}, {120630, 120654}, {120656, 120686}, {120688, 120712},
10504
  {120714, 120744}, {120746, 120770}, {120772, 120779}, {122624, 122633},
10505
  {122634, 122634}, {122635, 122654}, {122661, 122666}, {122928, 122989},
10506
  {123136, 123180}, {123191, 123197}, {123214, 123214}, {123536, 123565},
10507
  {123584, 123627}, {124112, 124138}, {124139, 124139}, {124368, 124397},
10508
  {124400, 124400}, {124608, 124638}, {124640, 124642}, {124644, 124645},
10509
  {124647, 124653}, {124656, 124660}, {124670, 124670}, {124671, 124671},
10510
  {124896, 124902}, {124904, 124907}, {124909, 124910}, {124912, 124926},
10511
  {124928, 125124}, {125184, 125251}, {125259, 125259}, {126464, 126467},
10512
  {126469, 126495}, {126497, 126498}, {126500, 126500}, {126503, 126503},
10513
  {126505, 126514}, {126516, 126519}, {126521, 126521}, {126523, 126523},
10514
  {126530, 126530}, {126535, 126535}, {126537, 126537}, {126539, 126539},
10515
  {126541, 126543}, {126545, 126546}, {126548, 126548}, {126551, 126551},
10516
  {126553, 126553}, {126555, 126555}, {126557, 126557}, {126559, 126559},
10517
  {126561, 126562}, {126564, 126564}, {126567, 126570}, {126572, 126578},
10518
  {126580, 126583}, {126585, 126588}, {126590, 126590}, {126592, 126601},
10519
  {126603, 126619}, {126625, 126627}, {126629, 126633}, {126635, 126651},
10520
  {131072, 173791}, {173824, 178205}, {178208, 183981}, {183984, 191456},
10521
  {191472, 192093}, {194560, 195101}, {196608, 201546}, {201552, 210041}
10522
};
10523
10524
10525
} // namespace ada::idna
10526
#endif // ADA_IDNA_IDENTIFIER_TABLES_H
10527
/* end file src/id_tables.cpp */
10528
10529
namespace ada::idna {
10530
43.4k
constexpr bool is_ascii_letter(char32_t c) noexcept {
10531
43.4k
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10532
43.4k
}
10533
10534
7.81k
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10535
7.81k
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10536
5.67k
         (c >= '0' && c <= '9');
10537
7.81k
}
10538
10539
52.6k
bool valid_name_code_point(char32_t code_point, bool first) {
10540
  // https://tc39.es/ecma262/#prod-IdentifierStart
10541
10542
  // Fast paths
10543
52.6k
  if (first && (code_point == U'$' || code_point == U'_' ||
10544
43.4k
                is_ascii_letter(code_point))) {
10545
4.34k
    return true;
10546
4.34k
  }
10547
48.2k
  if (!first && (code_point == U'$' || is_ascii_letter_or_digit(code_point))) {
10548
3.34k
    return true;
10549
3.34k
  }
10550
10551
  // Minimal error handling for invalid code point
10552
44.9k
  if (code_point > 0x10FFFF) {
10553
0
    return false;
10554
0
  }
10555
44.9k
  if (code_point >= 0xD800 && code_point <= 0xDFFF) {
10556
0
    return false;
10557
0
  }
10558
10559
  // Slow path: binary search through the appropriate Unicode range table.
10560
  // Each entry is a [low, high] inclusive range.
10561
44.9k
  const std::span<const uint32_t[2]> ranges =
10562
44.9k
      first ? std::span<const uint32_t[2]>{ada::idna::id_start}
10563
44.9k
            : std::span<const uint32_t[2]>{ada::idna::id_continue};
10564
10565
44.9k
  const auto iter = std::ranges::lower_bound(
10566
44.9k
      ranges, code_point, {},
10567
452k
      [](const auto& range) { return range[1]; });  // project to range-high
Unexecuted instantiation: idna.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Unexecuted instantiation: ada.cpp:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Unexecuted instantiation: serializers.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Unexecuted instantiation: can_parse.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Unexecuted instantiation: unicode.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Unexecuted instantiation: parse.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
url_pattern.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
Line
Count
Source
10567
452k
      [](const auto& range) { return range[1]; });  // project to range-high
Unexecuted instantiation: url_search_params.cc:auto ada::idna::valid_name_code_point(char32_t, bool)::$_0::operator()<unsigned int [2]>(unsigned int const (&) [2]) const
10568
10569
44.9k
  return iter != ranges.end() && code_point >= (*iter)[0];
10570
44.9k
}
10571
}  // namespace ada::idna
10572
/* end file src/identifier.cpp */
10573
/* end file src/idna.cpp */
10574
/* end file src/ada_idna.cpp */
10575
ADA_POP_DISABLE_WARNINGS
10576
10577
#include <algorithm>
10578
#if ADA_SSSE3
10579
#include <tmmintrin.h>
10580
#elif ADA_NEON
10581
#include <arm_neon.h>
10582
#elif ADA_SSE2
10583
#include <emmintrin.h>
10584
#elif ADA_LSX
10585
#include <lsxintrin.h>
10586
#elif ADA_RVV
10587
#include <riscv_vector.h>
10588
#endif
10589
10590
#include <ranges>
10591
10592
namespace ada::unicode {
10593
10594
5.94M
constexpr bool is_tabs_or_newline(char c) noexcept {
10595
5.94M
  return c == '\r' || c == '\n' || c == '\t';
10596
5.94M
}
10597
10598
1.04M
constexpr uint64_t broadcast(uint8_t v) noexcept {
10599
1.04M
  return 0x101010101010101ull * v;
10600
1.04M
}
10601
10602
349k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10603
349k
  uint64_t broadcast_80 = broadcast(0x80);
10604
349k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10605
349k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10606
349k
  uint64_t non_ascii = 0;
10607
349k
  size_t i = 0;
10608
10609
438k
  for (; i + 7 < length; i += 8) {
10610
89.4k
    uint64_t word{};
10611
89.4k
    memcpy(&word, input + i, sizeof(word));
10612
89.4k
    non_ascii |= (word & broadcast_80);
10613
89.4k
    word ^=
10614
89.4k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10615
89.4k
    memcpy(input + i, &word, sizeof(word));
10616
89.4k
  }
10617
349k
  if (i < length) {
10618
345k
    uint64_t word{};
10619
345k
    memcpy(&word, input + i, length - i);
10620
345k
    non_ascii |= (word & broadcast_80);
10621
345k
    word ^=
10622
345k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10623
345k
    memcpy(input + i, &word, length - i);
10624
345k
  }
10625
349k
  return non_ascii == 0;
10626
349k
}
10627
#if ADA_SSSE3
10628
ada_really_inline bool has_tabs_or_newline(
10629
    std::string_view user_input) noexcept {
10630
  // first check for short strings in which case we do it naively.
10631
  if (user_input.size() < 16) {  // slow path
10632
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10633
  }
10634
  // fast path for long strings (expected to be common)
10635
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
10636
  size_t i = 0;
10637
  // Lookup table where positions 9, 10, 13 contain their own values
10638
  // Everything else is set to 1 so it won't match
10639
  const __m128i rnt =
10640
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
10641
  __m128i running = _mm_setzero_si128();
10642
  for (; i + 15 < user_input.size(); i += 16) {
10643
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10644
    // Shuffle the lookup table using input bytes as indices
10645
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10646
    // Compare: if shuffled value matches input, we found \t, \n, or \r
10647
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10648
    running = _mm_or_si128(running, matches);
10649
  }
10650
  if (i < user_input.size()) {
10651
    __m128i word = _mm_loadu_si128(
10652
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10653
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
10654
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
10655
    running = _mm_or_si128(running, matches);
10656
  }
10657
  return _mm_movemask_epi8(running) != 0;
10658
}
10659
#elif ADA_NEON
10660
ada_really_inline bool has_tabs_or_newline(
10661
    std::string_view user_input) noexcept {
10662
  // first check for short strings in which case we do it naively.
10663
  if (user_input.size() < 16) {  // slow path
10664
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10665
  }
10666
  // fast path for long strings (expected to be common)
10667
  size_t i = 0;
10668
  /**
10669
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
10670
   * on table lookup instruction. We notice that these are all unique numbers
10671
   * between 0..15. Let's prepare a special register, where we put '\t' in the
10672
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
10673
   * input register. If the input had `\t` in position X then this shuffled
10674
   * register will also have '\t' in that position. Comparing input with this
10675
   * shuffled register will mark us all interesting characters in the input.
10676
   *
10677
   * credit for algorithmic idea: @aqrit, credit for description:
10678
   * @DenisYaroshevskiy
10679
   */
10680
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
10681
                                  0, 9, 10, 0, 0, 13, 0, 0};
10682
  const uint8x16_t rnt = vld1q_u8(rnt_array);
10683
  // m['0xd', '0xa', '0x9']
10684
  uint8x16_t running{0};
10685
  for (; i + 15 < user_input.size(); i += 16) {
10686
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
10687
10688
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10689
  }
10690
  if (i < user_input.size()) {
10691
    uint8x16_t word =
10692
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
10693
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
10694
  }
10695
  return vmaxvq_u32(vreinterpretq_u32_u8(running)) != 0;
10696
}
10697
#elif ADA_SSE2
10698
ada_really_inline bool has_tabs_or_newline(
10699
1.49M
    std::string_view user_input) noexcept {
10700
  // first check for short strings in which case we do it naively.
10701
1.49M
  if (user_input.size() < 16) {  // slow path
10702
710k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10703
710k
  }
10704
  // fast path for long strings (expected to be common)
10705
786k
  size_t i = 0;
10706
786k
  const __m128i mask1 = _mm_set1_epi8('\r');
10707
786k
  const __m128i mask2 = _mm_set1_epi8('\n');
10708
786k
  const __m128i mask3 = _mm_set1_epi8('\t');
10709
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10710
786k
  __m128i running{0};
10711
2.05M
  for (; i + 15 < user_input.size(); i += 16) {
10712
1.26M
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10713
1.26M
    running = _mm_or_si128(
10714
1.26M
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10715
1.26M
                                           _mm_cmpeq_epi8(word, mask2))),
10716
1.26M
        _mm_cmpeq_epi8(word, mask3));
10717
1.26M
  }
10718
786k
  if (i < user_input.size()) {
10719
752k
    __m128i word = _mm_loadu_si128(
10720
752k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10721
752k
    running = _mm_or_si128(
10722
752k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10723
752k
                                           _mm_cmpeq_epi8(word, mask2))),
10724
752k
        _mm_cmpeq_epi8(word, mask3));
10725
752k
  }
10726
786k
  return _mm_movemask_epi8(running) != 0;
10727
1.49M
}
10728
#elif ADA_LSX
10729
ada_really_inline bool has_tabs_or_newline(
10730
    std::string_view user_input) noexcept {
10731
  // first check for short strings in which case we do it naively.
10732
  if (user_input.size() < 16) {  // slow path
10733
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10734
  }
10735
  // fast path for long strings (expected to be common)
10736
  size_t i = 0;
10737
  const __m128i mask1 = __lsx_vrepli_b('\r');
10738
  const __m128i mask2 = __lsx_vrepli_b('\n');
10739
  const __m128i mask3 = __lsx_vrepli_b('\t');
10740
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10741
  __m128i running{0};
10742
  for (; i + 15 < user_input.size(); i += 16) {
10743
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
10744
    running = __lsx_vor_v(
10745
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10746
                                         __lsx_vseq_b(word, mask2))),
10747
        __lsx_vseq_b(word, mask3));
10748
  }
10749
  if (i < user_input.size()) {
10750
    __m128i word = __lsx_vld(
10751
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
10752
    running = __lsx_vor_v(
10753
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
10754
                                         __lsx_vseq_b(word, mask2))),
10755
        __lsx_vseq_b(word, mask3));
10756
  }
10757
  if (__lsx_bz_v(running)) return false;
10758
  return true;
10759
}
10760
#elif ADA_RVV
10761
ada_really_inline bool has_tabs_or_newline(
10762
    std::string_view user_input) noexcept {
10763
  uint8_t* src = (uint8_t*)user_input.data();
10764
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
10765
    vl = __riscv_vsetvl_e8m1(n);
10766
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
10767
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
10768
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
10769
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
10770
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
10771
    long idx = __riscv_vfirst(m, vl);
10772
    if (idx >= 0) return true;
10773
  }
10774
  return false;
10775
}
10776
#else
10777
ada_really_inline bool has_tabs_or_newline(
10778
    std::string_view user_input) noexcept {
10779
  auto has_zero_byte = [](uint64_t v) {
10780
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
10781
  };
10782
  size_t i = 0;
10783
  uint64_t mask1 = broadcast('\r');
10784
  uint64_t mask2 = broadcast('\n');
10785
  uint64_t mask3 = broadcast('\t');
10786
  uint64_t running{0};
10787
  for (; i + 7 < user_input.size(); i += 8) {
10788
    uint64_t word{};
10789
    memcpy(&word, user_input.data() + i, sizeof(word));
10790
    uint64_t xor1 = word ^ mask1;
10791
    uint64_t xor2 = word ^ mask2;
10792
    uint64_t xor3 = word ^ mask3;
10793
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10794
  }
10795
  if (i < user_input.size()) {
10796
    uint64_t word{};
10797
    memcpy(&word, user_input.data() + i, user_input.size() - i);
10798
    uint64_t xor1 = word ^ mask1;
10799
    uint64_t xor2 = word ^ mask2;
10800
    uint64_t xor3 = word ^ mask3;
10801
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
10802
  }
10803
  return running;
10804
}
10805
#endif
10806
10807
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
10808
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
10809
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
10810
// U+007C (|).
10811
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
10812
    []() consteval {
10813
      std::array<uint8_t, 256> result{};
10814
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10815
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
10816
        result[c] = true;
10817
      }
10818
      return result;
10819
    }();
10820
10821
ada_really_inline constexpr bool is_forbidden_host_code_point(
10822
1.92M
    const char c) noexcept {
10823
1.92M
  return is_forbidden_host_code_point_table[uint8_t(c)];
10824
1.92M
}
10825
10826
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
10827
    []() consteval {
10828
      std::array<uint8_t, 256> result{};
10829
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10830
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10831
        result[c] = true;
10832
      }
10833
      for (uint8_t c = 0; c <= 32; c++) {
10834
        result[c] = true;
10835
      }
10836
      for (size_t c = 127; c < 256; c++) {
10837
        result[c] = true;
10838
      }
10839
      return result;
10840
    }();
10841
10842
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
10843
10844
ada_really_inline constexpr bool is_forbidden_domain_code_point(
10845
2.17M
    const char c) noexcept {
10846
2.17M
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10847
2.17M
}
10848
10849
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10850
170k
    const char* input, size_t length) noexcept {
10851
170k
  size_t i = 0;
10852
170k
  uint8_t accumulator{};
10853
997k
  for (; i + 4 <= length; i += 4) {
10854
826k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10855
826k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10856
826k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10857
826k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10858
826k
  }
10859
463k
  for (; i < length; i++) {
10860
292k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10861
292k
  }
10862
170k
  return accumulator;
10863
170k
}
10864
10865
constexpr static std::array<uint8_t, 256>
10866
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
10867
      std::array<uint8_t, 256> result{};
10868
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
10869
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
10870
        result[c] = 1;
10871
      }
10872
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
10873
        result[c] = 2;
10874
      }
10875
      for (uint8_t c = 0; c <= 32; c++) {
10876
        result[c] = 1;
10877
      }
10878
      for (size_t c = 127; c < 256; c++) {
10879
        result[c] = 1;
10880
      }
10881
      return result;
10882
    }();
10883
10884
ada_really_inline constexpr uint8_t
10885
contains_forbidden_domain_code_point_or_upper(const char* input,
10886
646k
                                              size_t length) noexcept {
10887
646k
  size_t i = 0;
10888
646k
  uint8_t accumulator{};
10889
1.98M
  for (; i + 4 <= length; i += 4) {
10890
1.33M
    accumulator |=
10891
1.33M
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10892
1.33M
    accumulator |=
10893
1.33M
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10894
1.33M
    accumulator |=
10895
1.33M
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10896
1.33M
    accumulator |=
10897
1.33M
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10898
1.33M
  }
10899
2.07M
  for (; i < length; i++) {
10900
1.42M
    accumulator |=
10901
1.42M
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10902
1.42M
  }
10903
646k
  return accumulator;
10904
646k
}
10905
10906
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
10907
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
10908
  std::array<bool, 256> result{};
10909
  for (size_t c = 0; c < 256; c++) {
10910
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
10911
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
10912
  }
10913
  return result;
10914
}();
10915
10916
6.60M
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10917
6.60M
  return is_alnum_plus_table[uint8_t(c)];
10918
  // A table is almost surely much faster than the
10919
  // following under most compilers: return
10920
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
10921
6.60M
}
10922
10923
1.77M
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10924
1.77M
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10925
128k
         (c >= 'a' && c <= 'f');
10926
1.77M
}
10927
10928
557k
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
10929
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
10930
  // inclusive.
10931
557k
  return (c >= '0' && c <= '9');
10932
557k
}
10933
10934
24.8k
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
10935
  // If code point is between U+0000 and U+007F inclusive, then return true.
10936
24.8k
  return c <= 0x7F;
10937
24.8k
}
10938
10939
2.95M
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10940
2.95M
  return (unsigned char)c <= ' ';
10941
2.95M
}
10942
10943
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10944
7.48M
    const char c) noexcept {
10945
7.48M
  return c == '\t' || c == '\n' || c == '\r';
10946
7.48M
}
10947
10948
constexpr std::string_view table_is_double_dot_path_segment[] = {
10949
    "..", "%2e.", ".%2e", "%2e%2e"};
10950
10951
ada_really_inline constexpr bool is_double_dot_path_segment(
10952
370k
    std::string_view input) noexcept {
10953
  // This will catch most cases:
10954
  // The length must be 2,4 or 6.
10955
  // We divide by two and require
10956
  // that the result be between 1 and 3 inclusively.
10957
370k
  uint64_t half_length = uint64_t(input.size()) / 2;
10958
370k
  if (half_length - 1 > 2) {
10959
231k
    return false;
10960
231k
  }
10961
  // We have a string of length 2, 4 or 6.
10962
  // We now check the first character:
10963
139k
  if ((input[0] != '.') && (input[0] != '%')) {
10964
58.4k
    return false;
10965
58.4k
  }
10966
  // We are unlikely the get beyond this point.
10967
80.9k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10968
80.9k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10969
80.9k
  if (target.size() != input.size()) {
10970
26.5k
    return false;
10971
26.5k
  }
10972
  // We almost never get here.
10973
  // Optimizing the rest is relatively unimportant.
10974
54.3k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10975
54.3k
    uint16_t A, B;
10976
54.3k
    memcpy(&A, a.data(), sizeof(A));
10977
54.3k
    memcpy(&B, b.data(), sizeof(B));
10978
54.3k
    return A == B;
10979
54.3k
  };
10980
54.3k
  if (!prefix_equal_unsafe(input, target)) {
10981
8.00k
    return false;
10982
8.00k
  }
10983
57.1k
  for (size_t i = 2; i < input.size(); i++) {
10984
16.5k
    char c = input[i];
10985
16.5k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10986
5.81k
      return false;
10987
5.81k
    }
10988
16.5k
  }
10989
40.5k
  return true;
10990
  // The above code might be a bit better than the code below. Compilers
10991
  // are not stupid and may use the fact that these strings have length 2,4 and
10992
  // 6 and other tricks.
10993
  // return input == ".." ||
10994
  //  input == ".%2e" || input == ".%2E" ||
10995
  //  input == "%2e." || input == "%2E." ||
10996
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
10997
  //  "%2e%2E";
10998
46.3k
}
10999
11000
ada_really_inline constexpr bool is_single_dot_path_segment(
11001
657k
    std::string_view input) noexcept {
11002
657k
  return input == "." || input == "%2e" || input == "%2E";
11003
657k
}
11004
11005
112k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
11006
112k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
11007
112k
}
11008
11009
constexpr static char hex_to_binary_table[] = {
11010
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
11011
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
11012
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
11013
1.73M
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
11014
1.73M
  return hex_to_binary_table[c - '0'];
11015
1.73M
}
11016
11017
193k
std::string percent_decode(const std::string_view input, size_t first_percent) {
11018
  // next line is for safety only, we expect users to avoid calling
11019
  // percent_decode when first_percent is outside the range.
11020
193k
  if (first_percent == std::string_view::npos) {
11021
90.6k
    return std::string(input);
11022
90.6k
  }
11023
103k
  std::string dest;
11024
103k
  dest.reserve(input.length());
11025
103k
  dest.append(input.substr(0, first_percent));
11026
103k
  const char* pointer = input.data() + first_percent;
11027
103k
  const char* end = input.data() + input.size();
11028
  // Optimization opportunity: if the following code gets
11029
  // called often, it can be optimized quite a bit.
11030
1.49M
  while (pointer < end) {
11031
1.38M
    const char ch = pointer[0];
11032
1.38M
    size_t remaining = end - pointer - 1;
11033
1.38M
    if (ch != '%' || remaining < 2 ||
11034
867k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
11035
867k
            (!is_ascii_hex_digit(pointer[1]) ||
11036
855k
             !is_ascii_hex_digit(pointer[2])))) {
11037
538k
      dest += ch;
11038
538k
      pointer++;
11039
848k
    } else {
11040
848k
      unsigned a = convert_hex_to_binary(pointer[1]);
11041
848k
      unsigned b = convert_hex_to_binary(pointer[2]);
11042
848k
      char c = static_cast<char>(a * 16 + b);
11043
848k
      dest += c;
11044
848k
      pointer += 3;
11045
848k
    }
11046
1.38M
  }
11047
103k
  return dest;
11048
193k
}
11049
11050
std::string percent_encode(const std::string_view input,
11051
531k
                           const uint8_t character_set[]) {
11052
2.19M
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
2.19M
    return character_sets::bit_at(character_set, c);
11054
2.19M
  });
Unexecuted instantiation: idna.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
ada.cpp:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Line
Count
Source
11052
808k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
808k
    return character_sets::bit_at(character_set, c);
11054
808k
  });
serializers.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Line
Count
Source
11052
84.6k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
84.6k
    return character_sets::bit_at(character_set, c);
11054
84.6k
  });
Unexecuted instantiation: can_parse.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Unexecuted instantiation: unicode.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
parse.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Line
Count
Source
11052
1.17M
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
1.17M
    return character_sets::bit_at(character_set, c);
11054
1.17M
  });
url_pattern.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Line
Count
Source
11052
57.6k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
57.6k
    return character_sets::bit_at(character_set, c);
11054
57.6k
  });
url_search_params.cc:ada::unicode::percent_encode(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*)::$_0::operator()(char) const
Line
Count
Source
11052
71.6k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11053
71.6k
    return character_sets::bit_at(character_set, c);
11054
71.6k
  });
11055
  // Optimization: Don't iterate if percent encode is not required
11056
531k
  if (pointer == input.end()) {
11057
351k
    return std::string(input);
11058
351k
  }
11059
11060
179k
  std::string result;
11061
179k
  result.reserve(input.length());  // in the worst case, percent encoding might
11062
                                   // produce 3 characters.
11063
179k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
11064
11065
3.88M
  for (; pointer != input.end(); pointer++) {
11066
3.70M
    if (character_sets::bit_at(character_set, *pointer)) {
11067
2.85M
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11068
2.85M
    } else {
11069
844k
      result += *pointer;
11070
844k
    }
11071
3.70M
  }
11072
11073
179k
  return result;
11074
531k
}
11075
11076
template <bool append>
11077
bool percent_encode(const std::string_view input, const uint8_t character_set[],
11078
416k
                    std::string& out) {
11079
416k
  ada_log("percent_encode ", input, " to output string while ",
11080
416k
          append ? "appending" : "overwriting");
11081
2.99M
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
2.99M
    return character_sets::bit_at(character_set, c);
11083
2.99M
  });
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
11081
548k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
548k
    return character_sets::bit_at(character_set, c);
11083
548k
  });
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
11081
2.45M
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
2.45M
    return character_sets::bit_at(character_set, c);
11083
2.45M
  });
11084
416k
  ada_log("percent_encode done checking, moved to ",
11085
416k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
416k
  if (pointer == input.end()) {
11089
284k
    ada_log("percent_encode encoding not needed.");
11090
284k
    return false;
11091
284k
  }
11092
131k
  if constexpr (!append) {
11093
89.7k
    out.clear();
11094
89.7k
  }
11095
131k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
131k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
131k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
131k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
131k
          " bytes");
11101
2.69M
  for (; pointer != input.end(); pointer++) {
11102
2.56M
    if (character_sets::bit_at(character_set, *pointer)) {
11103
2.01M
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
2.01M
    } else {
11105
548k
      out += *pointer;
11106
548k
    }
11107
2.56M
  }
11108
131k
  return true;
11109
416k
}
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
11078
241k
                    std::string& out) {
11079
241k
  ada_log("percent_encode ", input, " to output string while ",
11080
241k
          append ? "appending" : "overwriting");
11081
241k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
241k
    return character_sets::bit_at(character_set, c);
11083
241k
  });
11084
241k
  ada_log("percent_encode done checking, moved to ",
11085
241k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
241k
  if (pointer == input.end()) {
11089
151k
    ada_log("percent_encode encoding not needed.");
11090
151k
    return false;
11091
151k
  }
11092
89.7k
  if constexpr (!append) {
11093
89.7k
    out.clear();
11094
89.7k
  }
11095
89.7k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
89.7k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
89.7k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
89.7k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
89.7k
          " bytes");
11101
1.42M
  for (; pointer != input.end(); pointer++) {
11102
1.33M
    if (character_sets::bit_at(character_set, *pointer)) {
11103
1.06M
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
1.06M
    } else {
11105
276k
      out += *pointer;
11106
276k
    }
11107
1.33M
  }
11108
89.7k
  return true;
11109
241k
}
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
11078
174k
                    std::string& out) {
11079
174k
  ada_log("percent_encode ", input, " to output string while ",
11080
174k
          append ? "appending" : "overwriting");
11081
174k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
174k
    return character_sets::bit_at(character_set, c);
11083
174k
  });
11084
174k
  ada_log("percent_encode done checking, moved to ",
11085
174k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
174k
  if (pointer == input.end()) {
11089
132k
    ada_log("percent_encode encoding not needed.");
11090
132k
    return false;
11091
132k
  }
11092
  if constexpr (!append) {
11093
    out.clear();
11094
  }
11095
42.1k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
42.1k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
42.1k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
42.1k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
42.1k
          " bytes");
11101
1.26M
  for (; pointer != input.end(); pointer++) {
11102
1.22M
    if (character_sets::bit_at(character_set, *pointer)) {
11103
952k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
952k
    } else {
11105
272k
      out += *pointer;
11106
272k
    }
11107
1.22M
  }
11108
42.1k
  return true;
11109
174k
}
11110
11111
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11112
175k
              size_t first_percent) {
11113
175k
  std::string percent_decoded_buffer;
11114
175k
  std::string_view input = plain;
11115
175k
  if (first_percent != std::string_view::npos) {
11116
49.2k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11117
49.2k
    input = percent_decoded_buffer;
11118
49.2k
  }
11119
  // input is a non-empty UTF-8 string, must be percent decoded
11120
175k
  std::string idna_ascii = ada::idna::to_ascii(input);
11121
175k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11122
112k
                                idna_ascii.data(), idna_ascii.size())) {
11123
97.0k
    return false;
11124
97.0k
  }
11125
78.7k
  out = std::move(idna_ascii);
11126
78.7k
  return true;
11127
175k
}
11128
11129
std::string percent_encode(const std::string_view input,
11130
47.2k
                           const uint8_t character_set[], size_t index) {
11131
47.2k
  std::string out;
11132
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11133
47.2k
  out.append(input.data(), index);
11134
47.2k
  auto pointer = input.begin() + index;
11135
981k
  for (; pointer != input.end(); pointer++) {
11136
933k
    if (character_sets::bit_at(character_set, *pointer)) {
11137
635k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11138
635k
    } else {
11139
298k
      out += *pointer;
11140
298k
    }
11141
933k
  }
11142
47.2k
  return out;
11143
47.2k
}
11144
11145
}  // namespace ada::unicode
11146
/* end file src/unicode.cpp */
11147
/* begin file src/serializers.cpp */
11148
#include <array>
11149
#include <charconv>
11150
#include <string>
11151
11152
namespace ada::serializers {
11153
11154
void find_longest_sequence_of_ipv6_pieces(
11155
    const std::array<uint16_t, 8>& address, size_t& compress,
11156
10.7k
    size_t& compress_length) noexcept {
11157
67.7k
  for (size_t i = 0; i < 8; i++) {
11158
59.0k
    if (address[i] == 0) {
11159
7.03k
      size_t next = i + 1;
11160
31.0k
      while (next != 8 && address[next] == 0) ++next;
11161
7.03k
      const size_t count = next - i;
11162
7.03k
      if (compress_length < count) {
11163
5.60k
        compress_length = count;
11164
5.60k
        compress = i;
11165
5.60k
        if (next == 8) break;
11166
3.53k
        i = next;
11167
3.53k
      }
11168
7.03k
    }
11169
59.0k
  }
11170
10.7k
}
11171
11172
7.54k
std::string ipv6(const std::array<uint16_t, 8>& address) {
11173
7.54k
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11174
7.54k
  size_t compress = 0;         // The start of a long sequence of zeros.
11175
7.54k
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11176
11177
7.54k
  if (compress_length <= 1) {
11178
    // Optimization opportunity: Find a faster way then snprintf for imploding
11179
    // and return here.
11180
3.22k
    compress = compress_length = 8;
11181
3.22k
  }
11182
11183
7.54k
  std::string output(4 * 8 + 7 + 2, '\0');
11184
7.54k
  size_t piece_index = 0;
11185
7.54k
  char* point = output.data();
11186
7.54k
  char* point_end = output.data() + output.size();
11187
7.54k
  *point++ = '[';
11188
36.1k
  while (true) {
11189
36.1k
    if (piece_index == compress) {
11190
4.32k
      *point++ = ':';
11191
      // If we skip a value initially, we need to write '::', otherwise
11192
      // a single ':' will do since it follows a previous ':'.
11193
4.32k
      if (piece_index == 0) {
11194
2.40k
        *point++ = ':';
11195
2.40k
      }
11196
4.32k
      piece_index += compress_length;
11197
4.32k
      if (piece_index == 8) {
11198
1.81k
        break;
11199
1.81k
      }
11200
4.32k
    }
11201
34.2k
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11202
34.2k
    piece_index++;
11203
34.2k
    if (piece_index == 8) {
11204
5.73k
      break;
11205
5.73k
    }
11206
28.5k
    *point++ = ':';
11207
28.5k
  }
11208
7.54k
  *point++ = ']';
11209
7.54k
  output.resize(point - output.data());
11210
7.54k
  return output;
11211
7.54k
}
11212
11213
48.1k
std::string ipv4(const uint64_t address) {
11214
48.1k
  std::string output(15, '\0');
11215
48.1k
  char* point = output.data();
11216
48.1k
  char* point_end = output.data() + output.size();
11217
48.1k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11218
192k
  for (int i = 2; i >= 0; i--) {
11219
144k
    *point++ = '.';
11220
144k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11221
144k
  }
11222
48.1k
  output.resize(point - output.data());
11223
48.1k
  return output;
11224
48.1k
}
11225
11226
}  // namespace ada::serializers
11227
/* end file src/serializers.cpp */
11228
/* begin file src/implementation.cpp */
11229
11230
#include <atomic>
11231
#include <limits>
11232
#include <optional>
11233
#include <string_view>
11234
11235
11236
namespace ada {
11237
11238
static std::atomic<uint32_t> max_input_length_{
11239
    std::numeric_limits<uint32_t>::max()};
11240
11241
0
void set_max_input_length(uint32_t length) {
11242
0
  max_input_length_.store(length, std::memory_order_relaxed);
11243
0
}
11244
11245
1.69M
uint32_t get_max_input_length() {
11246
1.69M
  return max_input_length_.load(std::memory_order_relaxed);
11247
1.69M
}
11248
11249
namespace {
11250
11251
// @private
11252
// Fast-path validator for can_parse.
11253
//
11254
// Validates absolute special (non-file) URLs without constructing any
11255
// url_aggregator object and without running the state machine.
11256
// Performs a single forward scan over the input bytes.
11257
//
11258
// Returns:
11259
//   true      -- URL is structurally valid
11260
//   false     -- URL is definitely invalid
11261
//   nullopt   -- edge case; fall through to the full parser
11262
//               (credentials, IDNA, IPv4/6, tabs/newlines, relative URLs, ...)
11263
std::optional<bool> try_can_parse_absolute_fast(
11264
8.50k
    std::string_view input) noexcept {
11265
8.50k
  const uint8_t* b = reinterpret_cast<const uint8_t*>(input.data());
11266
8.50k
  size_t len = input.size();
11267
11268
  // -- Inline C0 whitespace trim (no allocation) --------------------------
11269
  // Note: \t (0x09), \n (0x0a), \r (0x0d) are all <= 0x20, so any
11270
  // leading/trailing tabs or newlines are correctly stripped here, matching
11271
  // the WHATWG spec's "remove leading/trailing C0 control and space" step.
11272
17.6k
  while (len > 0 && b[0] <= 0x20) {
11273
9.17k
    b++;
11274
9.17k
    len--;
11275
9.17k
  }
11276
20.2k
  while (len > 0 && b[len - 1] <= 0x20) {
11277
11.7k
    len--;
11278
11.7k
  }
11279
8.50k
  if (len == 0) return false;
11280
11281
  // -- Scheme detection -----------------------------------------------------
11282
  // Fast path for HTTP and HTTPS (covers ~90%+ of real-world URLs).
11283
  // Avoids the general scheme loop, buffer copy, and perfect hash lookup.
11284
  // We know HTTP and HTTPS are special non-file schemes, so no further
11285
  // scheme_type checks are needed on the fast path -- only `pos` matters.
11286
8.28k
  size_t pos;
11287
11288
8.28k
  if (len >= 7 && (b[0] | 0x20) == 'h' && (b[1] | 0x20) == 't' &&
11289
21
      (b[2] | 0x20) == 't' && (b[3] | 0x20) == 'p') {
11290
16
    if (b[4] == ':' && b[5] == '/' && b[6] == '/') {
11291
0
      pos = 7;
11292
0
      goto skip_extra_slashes;
11293
0
    }
11294
16
    if (len >= 8 && (b[4] | 0x20) == 's' && b[5] == ':' && b[6] == '/' &&
11295
1
        b[7] == '/') {
11296
1
      pos = 8;
11297
1
      goto skip_extra_slashes;
11298
1
    }
11299
    // Fall through: could be "httpe://", tabs in scheme, etc.
11300
16
  }
11301
11302
8.28k
  {
11303
    // General scheme detection for ws, wss, ftp, and edge cases.
11304
8.28k
    if (!checkers::is_alpha(static_cast<char>(b[0]))) return false;
11305
11306
    // Scan for ':' within the first 7 bytes. All special schemes are <= 5
11307
    // chars ("https"), so any URL whose first ':' is beyond byte 6 is either
11308
    // non-special or relative -- both require the full parser.
11309
8.27k
    size_t colon_pos = 0;
11310
19.9k
    for (size_t i = 1;; ++i) {
11311
19.9k
      if (i >= 7 || i >= len) return std::nullopt;
11312
18.9k
      const char c = static_cast<char>(b[i]);
11313
18.9k
      if (c == ':') {
11314
7.27k
        colon_pos = i;
11315
7.27k
        break;
11316
7.27k
      }
11317
      // Tabs/newlines in the scheme require the full parser to strip them.
11318
11.7k
      if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
11319
11.7k
      if (!unicode::is_alnum_plus(c)) return false;
11320
11.7k
    }
11321
11322
    // Lowercase scheme bytes inline and classify via the existing perfect
11323
    // hash.
11324
7.27k
    char scheme_buf[6];
11325
7.27k
    scheme_buf[0] = static_cast<char>(b[0] | 0x20);
11326
17.1k
    for (size_t i = 1; i < colon_pos; ++i)
11327
9.82k
      scheme_buf[i] = static_cast<char>(b[i] | 0x20);
11328
11329
7.27k
    const ada::scheme::type scheme_type =
11330
7.27k
        ada::scheme::get_scheme_type({scheme_buf, colon_pos});
11331
11332
    // Only handle special, non-file schemes.
11333
7.27k
    if (scheme_type == ada::scheme::NOT_SPECIAL) return std::nullopt;
11334
5.25k
    if (scheme_type == ada::scheme::FILE) return std::nullopt;
11335
11336
    // Per WHATWG, special URLs don't require "//": "http:example.com" is valid
11337
    // (SPECIAL_AUTHORITY_IGNORE_SLASHES just skips leading slashes and
11338
    // proceeds to AUTHORITY).  Defer to the inline fallback for any input
11339
    // without "://".
11340
4.33k
    pos = colon_pos + 1;
11341
4.33k
    if (pos + 2 > len || b[pos] != '/' || b[pos + 1] != '/') {
11342
4.32k
      return std::nullopt;
11343
4.32k
    }
11344
10
    pos += 2;
11345
10
  }
11346
11347
11
skip_extra_slashes:
11348
  // SPECIAL_AUTHORITY_IGNORE_SLASHES: the full parser skips any additional
11349
  // leading '/' or '\' after the initial "//".  Mirror that here so we don't
11350
  // mis-identify the host as empty when there are extra slashes.
11351
38
  while (pos < len && (b[pos] == '/' || b[pos] == '\\')) {
11352
27
    ++pos;
11353
27
  }
11354
11355
  // Early IPv6 bail-out: if the authority starts with '[', it's an IPv6
11356
  // literal which requires the full parser.  Checking here avoids scanning
11357
  // the entire bracketed address only to bail out afterward.
11358
11
  if (pos < len && b[pos] == '[') return std::nullopt;
11359
11360
  // -- Merged authority + host scan ------------------------------------------
11361
  // A single forward pass over the authority bytes that simultaneously:
11362
  //   - finds the authority end and port colon
11363
  //   - validates host characters (forbidden domain code points)
11364
  //   - tracks IPv4 indicators (all-decimal-dots, last non-dot char)
11365
  //   - detects xn-- prefixes (IDNA punycode)
11366
  //   - detects tabs/newlines (which require the full parser to strip)
11367
  // This replaces 4 separate scans over the host bytes.
11368
11
  const size_t auth_start = pos;
11369
11
  size_t auth_end = pos;
11370
11
  size_t port_colon = SIZE_MAX;
11371
11
  bool all_dec_dots = true;
11372
11
  uint8_t last_non_dot = 0;
11373
11374
210
  for (; auth_end < len; ++auth_end) {
11375
208
    const uint8_t c = b[auth_end];
11376
11377
    // Non-ASCII -> needs IDNA processing -> full parser.
11378
208
    if (c >= 0x80) return std::nullopt;
11379
11380
    // Authority delimiters.
11381
207
    if (c == '/' || c == '?' || c == '#' || c == '\\') break;
11382
11383
    // Port separator.
11384
201
    if (c == ':') {
11385
4
      if (port_colon == SIZE_MAX) port_colon = auth_end;
11386
4
      continue;
11387
4
    }
11388
11389
    // Credentials or percent-encoding -> full parser.
11390
197
    if (c == '@' || c == '%') return std::nullopt;
11391
11392
    // Tabs/newlines anywhere in the authority require the full parser to
11393
    // strip them before validation.  Without this, a tab in the port (e.g.
11394
    // "http://host:8\t0/") would be mis-rejected by port validation.
11395
195
    if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
11396
11397
    // Skip remaining host-specific checks for port bytes.  Port digits are
11398
    // validated separately below, and no forbidden-domain-code-point check
11399
    // is needed on port characters.
11400
195
    if (port_colon != SIZE_MAX) continue;
11401
11402
    // -- Host byte validation (inlined) ------------------------------------
11403
    // Forbidden domain code points that are not already caught above:
11404
    //   C0 controls and space (0x00-0x20), DEL (0x7F), <, >, [, ], ^, |.
11405
    // At this stage, the input may still be userinfo or be normalized later
11406
    // (e.g., percent-encoded), so we do not reject here and defer to the
11407
    // parser. Characters already caught: >= 0x80 (non-ASCII), '/' '?' '#' '\\'
11408
    // (delimiters), ':' (port), '@' '%' (bail), '\t' '\n' '\r' (bail).
11409
45
    if (c <= 0x20 || c == 0x7F || c == '<' || c == '>' || c == '[' ||
11410
45
        c == ']' || c == '^' || c == '|') {
11411
0
      return std::nullopt;
11412
0
    }
11413
11414
    // Track whether host is all decimal digits and dots (potential IPv4).
11415
45
    if (c != '.' && (c < '0' || c > '9')) all_dec_dots = false;
11416
11417
    // Track last non-dot character for the IPv4 hex/octal heuristic.
11418
45
    if (c != '.') last_non_dot = c;
11419
11420
    // Detect xn-- prefix inline (IDNA punycode -> needs full parser).
11421
    // Checking at every position mirrors the original behavior: any
11422
    // occurrence of "xn--" in the host (not just at label boundaries)
11423
    // triggers a bail-out to the full IDNA validator.
11424
45
    if ((c | 0x20) == 'x' && auth_end + 4 <= len &&
11425
0
        (b[auth_end + 1] | 0x20) == 'n' && b[auth_end + 2] == '-' &&
11426
0
        b[auth_end + 3] == '-') {
11427
0
      return std::nullopt;
11428
0
    }
11429
45
  }
11430
11431
8
  const size_t host_end = (port_colon != SIZE_MAX) ? port_colon : auth_end;
11432
11433
  // Empty host is invalid for special URLs.
11434
8
  if (auth_start == host_end) return false;
11435
11436
  // -- IPv4 handling ---------------------------------------------------------
11437
7
  const char* host_ptr = reinterpret_cast<const char*>(b + auth_start);
11438
7
  const size_t host_len = host_end - auth_start;
11439
11440
7
  if (all_dec_dots) {
11441
    // Host is all decimal digits and dots -> try the fast IPv4 parser.
11442
1
    if (checkers::try_parse_ipv4_fast({host_ptr, host_len}) !=
11443
1
        checkers::ipv4_fast_fail) {
11444
      // Valid decimal IPv4 host.  Do NOT return true yet: the port still
11445
      // needs to be validated below before we can declare the URL valid.
11446
0
      goto validate_port;
11447
0
    }
11448
    // Fast IPv4 parsing failed (e.g. host is ".", "..", "1.2.3.500").
11449
    // Such hosts may still be valid domain names; defer to the full parser.
11450
1
    return std::nullopt;
11451
1
  }
11452
11453
  // Last-significant-character heuristic for non-decimal IPv4 (hex/octal):
11454
  // if the last non-dot char is a digit, 'a'-'f', or 'x' the host might be
11455
  // an IPv4 address that the fast path can't validate -- fall through.
11456
  // last_non_dot was tracked during the authority scan above.
11457
6
  {
11458
6
    const uint8_t lc = last_non_dot | 0x20;
11459
6
    if ((last_non_dot >= '0' && last_non_dot <= '9') ||
11460
6
        (lc >= 'a' && lc <= 'f') || lc == 'x') {
11461
2
      return std::nullopt;
11462
2
    }
11463
6
  }
11464
11465
  // -- Port validation -------------------------------------------------------
11466
4
validate_port:
11467
4
  if (port_colon != SIZE_MAX) {
11468
3
    const uint8_t* pp = b + port_colon + 1;
11469
3
    size_t pl = auth_end - port_colon - 1;
11470
3
    if (pl > 0) {
11471
      // Strip leading zeros: "0000001" == 1, "0000000000000" == 0, both valid.
11472
      // Only the significant digits count toward the 5-digit maximum.
11473
0
      while (pl > 0 && *pp == '0') {
11474
0
        ++pp;
11475
0
        --pl;
11476
0
      }
11477
0
      if (pl > 5) return false;  // significant digits > 99999
11478
0
      uint32_t pv = 0;
11479
0
      for (size_t i = 0; i < pl; ++i) {
11480
0
        if (pp[i] < '0' || pp[i] > '9') return false;
11481
0
        pv = pv * 10 + (pp[i] - '0');
11482
0
      }
11483
0
      if (pv > 65535) return false;
11484
0
    }
11485
3
  }
11486
11487
  // Path, query, and fragment are structurally always valid for can_parse --
11488
  // the parser would encode whatever is there.
11489
4
  return true;
11490
4
}
Unexecuted instantiation: idna.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
ada.cpp:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
11264
8.50k
    std::string_view input) noexcept {
11265
8.50k
  const uint8_t* b = reinterpret_cast<const uint8_t*>(input.data());
11266
8.50k
  size_t len = input.size();
11267
11268
  // -- Inline C0 whitespace trim (no allocation) --------------------------
11269
  // Note: \t (0x09), \n (0x0a), \r (0x0d) are all <= 0x20, so any
11270
  // leading/trailing tabs or newlines are correctly stripped here, matching
11271
  // the WHATWG spec's "remove leading/trailing C0 control and space" step.
11272
17.6k
  while (len > 0 && b[0] <= 0x20) {
11273
9.17k
    b++;
11274
9.17k
    len--;
11275
9.17k
  }
11276
20.2k
  while (len > 0 && b[len - 1] <= 0x20) {
11277
11.7k
    len--;
11278
11.7k
  }
11279
8.50k
  if (len == 0) return false;
11280
11281
  // -- Scheme detection -----------------------------------------------------
11282
  // Fast path for HTTP and HTTPS (covers ~90%+ of real-world URLs).
11283
  // Avoids the general scheme loop, buffer copy, and perfect hash lookup.
11284
  // We know HTTP and HTTPS are special non-file schemes, so no further
11285
  // scheme_type checks are needed on the fast path -- only `pos` matters.
11286
8.28k
  size_t pos;
11287
11288
8.28k
  if (len >= 7 && (b[0] | 0x20) == 'h' && (b[1] | 0x20) == 't' &&
11289
21
      (b[2] | 0x20) == 't' && (b[3] | 0x20) == 'p') {
11290
16
    if (b[4] == ':' && b[5] == '/' && b[6] == '/') {
11291
0
      pos = 7;
11292
0
      goto skip_extra_slashes;
11293
0
    }
11294
16
    if (len >= 8 && (b[4] | 0x20) == 's' && b[5] == ':' && b[6] == '/' &&
11295
1
        b[7] == '/') {
11296
1
      pos = 8;
11297
1
      goto skip_extra_slashes;
11298
1
    }
11299
    // Fall through: could be "httpe://", tabs in scheme, etc.
11300
16
  }
11301
11302
8.28k
  {
11303
    // General scheme detection for ws, wss, ftp, and edge cases.
11304
8.28k
    if (!checkers::is_alpha(static_cast<char>(b[0]))) return false;
11305
11306
    // Scan for ':' within the first 7 bytes. All special schemes are <= 5
11307
    // chars ("https"), so any URL whose first ':' is beyond byte 6 is either
11308
    // non-special or relative -- both require the full parser.
11309
8.27k
    size_t colon_pos = 0;
11310
19.9k
    for (size_t i = 1;; ++i) {
11311
19.9k
      if (i >= 7 || i >= len) return std::nullopt;
11312
18.9k
      const char c = static_cast<char>(b[i]);
11313
18.9k
      if (c == ':') {
11314
7.27k
        colon_pos = i;
11315
7.27k
        break;
11316
7.27k
      }
11317
      // Tabs/newlines in the scheme require the full parser to strip them.
11318
11.7k
      if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
11319
11.7k
      if (!unicode::is_alnum_plus(c)) return false;
11320
11.7k
    }
11321
11322
    // Lowercase scheme bytes inline and classify via the existing perfect
11323
    // hash.
11324
7.27k
    char scheme_buf[6];
11325
7.27k
    scheme_buf[0] = static_cast<char>(b[0] | 0x20);
11326
17.1k
    for (size_t i = 1; i < colon_pos; ++i)
11327
9.82k
      scheme_buf[i] = static_cast<char>(b[i] | 0x20);
11328
11329
7.27k
    const ada::scheme::type scheme_type =
11330
7.27k
        ada::scheme::get_scheme_type({scheme_buf, colon_pos});
11331
11332
    // Only handle special, non-file schemes.
11333
7.27k
    if (scheme_type == ada::scheme::NOT_SPECIAL) return std::nullopt;
11334
5.25k
    if (scheme_type == ada::scheme::FILE) return std::nullopt;
11335
11336
    // Per WHATWG, special URLs don't require "//": "http:example.com" is valid
11337
    // (SPECIAL_AUTHORITY_IGNORE_SLASHES just skips leading slashes and
11338
    // proceeds to AUTHORITY).  Defer to the inline fallback for any input
11339
    // without "://".
11340
4.33k
    pos = colon_pos + 1;
11341
4.33k
    if (pos + 2 > len || b[pos] != '/' || b[pos + 1] != '/') {
11342
4.32k
      return std::nullopt;
11343
4.32k
    }
11344
10
    pos += 2;
11345
10
  }
11346
11347
11
skip_extra_slashes:
11348
  // SPECIAL_AUTHORITY_IGNORE_SLASHES: the full parser skips any additional
11349
  // leading '/' or '\' after the initial "//".  Mirror that here so we don't
11350
  // mis-identify the host as empty when there are extra slashes.
11351
38
  while (pos < len && (b[pos] == '/' || b[pos] == '\\')) {
11352
27
    ++pos;
11353
27
  }
11354
11355
  // Early IPv6 bail-out: if the authority starts with '[', it's an IPv6
11356
  // literal which requires the full parser.  Checking here avoids scanning
11357
  // the entire bracketed address only to bail out afterward.
11358
11
  if (pos < len && b[pos] == '[') return std::nullopt;
11359
11360
  // -- Merged authority + host scan ------------------------------------------
11361
  // A single forward pass over the authority bytes that simultaneously:
11362
  //   - finds the authority end and port colon
11363
  //   - validates host characters (forbidden domain code points)
11364
  //   - tracks IPv4 indicators (all-decimal-dots, last non-dot char)
11365
  //   - detects xn-- prefixes (IDNA punycode)
11366
  //   - detects tabs/newlines (which require the full parser to strip)
11367
  // This replaces 4 separate scans over the host bytes.
11368
11
  const size_t auth_start = pos;
11369
11
  size_t auth_end = pos;
11370
11
  size_t port_colon = SIZE_MAX;
11371
11
  bool all_dec_dots = true;
11372
11
  uint8_t last_non_dot = 0;
11373
11374
210
  for (; auth_end < len; ++auth_end) {
11375
208
    const uint8_t c = b[auth_end];
11376
11377
    // Non-ASCII -> needs IDNA processing -> full parser.
11378
208
    if (c >= 0x80) return std::nullopt;
11379
11380
    // Authority delimiters.
11381
207
    if (c == '/' || c == '?' || c == '#' || c == '\\') break;
11382
11383
    // Port separator.
11384
201
    if (c == ':') {
11385
4
      if (port_colon == SIZE_MAX) port_colon = auth_end;
11386
4
      continue;
11387
4
    }
11388
11389
    // Credentials or percent-encoding -> full parser.
11390
197
    if (c == '@' || c == '%') return std::nullopt;
11391
11392
    // Tabs/newlines anywhere in the authority require the full parser to
11393
    // strip them before validation.  Without this, a tab in the port (e.g.
11394
    // "http://host:8\t0/") would be mis-rejected by port validation.
11395
195
    if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
11396
11397
    // Skip remaining host-specific checks for port bytes.  Port digits are
11398
    // validated separately below, and no forbidden-domain-code-point check
11399
    // is needed on port characters.
11400
195
    if (port_colon != SIZE_MAX) continue;
11401
11402
    // -- Host byte validation (inlined) ------------------------------------
11403
    // Forbidden domain code points that are not already caught above:
11404
    //   C0 controls and space (0x00-0x20), DEL (0x7F), <, >, [, ], ^, |.
11405
    // At this stage, the input may still be userinfo or be normalized later
11406
    // (e.g., percent-encoded), so we do not reject here and defer to the
11407
    // parser. Characters already caught: >= 0x80 (non-ASCII), '/' '?' '#' '\\'
11408
    // (delimiters), ':' (port), '@' '%' (bail), '\t' '\n' '\r' (bail).
11409
45
    if (c <= 0x20 || c == 0x7F || c == '<' || c == '>' || c == '[' ||
11410
45
        c == ']' || c == '^' || c == '|') {
11411
0
      return std::nullopt;
11412
0
    }
11413
11414
    // Track whether host is all decimal digits and dots (potential IPv4).
11415
45
    if (c != '.' && (c < '0' || c > '9')) all_dec_dots = false;
11416
11417
    // Track last non-dot character for the IPv4 hex/octal heuristic.
11418
45
    if (c != '.') last_non_dot = c;
11419
11420
    // Detect xn-- prefix inline (IDNA punycode -> needs full parser).
11421
    // Checking at every position mirrors the original behavior: any
11422
    // occurrence of "xn--" in the host (not just at label boundaries)
11423
    // triggers a bail-out to the full IDNA validator.
11424
45
    if ((c | 0x20) == 'x' && auth_end + 4 <= len &&
11425
0
        (b[auth_end + 1] | 0x20) == 'n' && b[auth_end + 2] == '-' &&
11426
0
        b[auth_end + 3] == '-') {
11427
0
      return std::nullopt;
11428
0
    }
11429
45
  }
11430
11431
8
  const size_t host_end = (port_colon != SIZE_MAX) ? port_colon : auth_end;
11432
11433
  // Empty host is invalid for special URLs.
11434
8
  if (auth_start == host_end) return false;
11435
11436
  // -- IPv4 handling ---------------------------------------------------------
11437
7
  const char* host_ptr = reinterpret_cast<const char*>(b + auth_start);
11438
7
  const size_t host_len = host_end - auth_start;
11439
11440
7
  if (all_dec_dots) {
11441
    // Host is all decimal digits and dots -> try the fast IPv4 parser.
11442
1
    if (checkers::try_parse_ipv4_fast({host_ptr, host_len}) !=
11443
1
        checkers::ipv4_fast_fail) {
11444
      // Valid decimal IPv4 host.  Do NOT return true yet: the port still
11445
      // needs to be validated below before we can declare the URL valid.
11446
0
      goto validate_port;
11447
0
    }
11448
    // Fast IPv4 parsing failed (e.g. host is ".", "..", "1.2.3.500").
11449
    // Such hosts may still be valid domain names; defer to the full parser.
11450
1
    return std::nullopt;
11451
1
  }
11452
11453
  // Last-significant-character heuristic for non-decimal IPv4 (hex/octal):
11454
  // if the last non-dot char is a digit, 'a'-'f', or 'x' the host might be
11455
  // an IPv4 address that the fast path can't validate -- fall through.
11456
  // last_non_dot was tracked during the authority scan above.
11457
6
  {
11458
6
    const uint8_t lc = last_non_dot | 0x20;
11459
6
    if ((last_non_dot >= '0' && last_non_dot <= '9') ||
11460
6
        (lc >= 'a' && lc <= 'f') || lc == 'x') {
11461
2
      return std::nullopt;
11462
2
    }
11463
6
  }
11464
11465
  // -- Port validation -------------------------------------------------------
11466
4
validate_port:
11467
4
  if (port_colon != SIZE_MAX) {
11468
3
    const uint8_t* pp = b + port_colon + 1;
11469
3
    size_t pl = auth_end - port_colon - 1;
11470
3
    if (pl > 0) {
11471
      // Strip leading zeros: "0000001" == 1, "0000000000000" == 0, both valid.
11472
      // Only the significant digits count toward the 5-digit maximum.
11473
0
      while (pl > 0 && *pp == '0') {
11474
0
        ++pp;
11475
0
        --pl;
11476
0
      }
11477
0
      if (pl > 5) return false;  // significant digits > 99999
11478
0
      uint32_t pv = 0;
11479
0
      for (size_t i = 0; i < pl; ++i) {
11480
0
        if (pp[i] < '0' || pp[i] > '9') return false;
11481
0
        pv = pv * 10 + (pp[i] - '0');
11482
0
      }
11483
0
      if (pv > 65535) return false;
11484
0
    }
11485
3
  }
11486
11487
  // Path, query, and fragment are structurally always valid for can_parse --
11488
  // the parser would encode whatever is there.
11489
4
  return true;
11490
4
}
Unexecuted instantiation: serializers.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: can_parse.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: unicode.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: parse.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: url_pattern.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: url_search_params.cc:ada::(anonymous namespace)::try_can_parse_absolute_fast(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
11491
11492
}  // namespace
11493
11494
template <class result_type>
11495
ada_warn_unused tl::expected<result_type, errors> parse(
11496
1.42M
    std::string_view input, const result_type* base_url) {
11497
1.42M
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
11498
1.42M
  if (!u.is_valid) {
11499
587k
    return tl::unexpected(errors::type_error);
11500
587k
  }
11501
840k
  return u;
11502
1.42M
}
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
11496
65.7k
    std::string_view input, const result_type* base_url) {
11497
65.7k
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
11498
65.7k
  if (!u.is_valid) {
11499
21.8k
    return tl::unexpected(errors::type_error);
11500
21.8k
  }
11501
43.8k
  return u;
11502
65.7k
}
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
11496
1.36M
    std::string_view input, const result_type* base_url) {
11497
1.36M
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
11498
1.36M
  if (!u.is_valid) {
11499
565k
    return tl::unexpected(errors::type_error);
11500
565k
  }
11501
796k
  return u;
11502
1.36M
}
11503
11504
template ada::result<url> parse<url>(std::string_view input,
11505
                                     const url* base_url = nullptr);
11506
template ada::result<url_aggregator> parse<url_aggregator>(
11507
    std::string_view input, const url_aggregator* base_url = nullptr);
11508
11509
13.6k
std::string href_from_file(std::string_view input) {
11510
  // This is going to be much faster than constructing a URL.
11511
13.6k
  std::string tmp_buffer;
11512
13.6k
  std::string_view internal_input;
11513
13.6k
  if (unicode::has_tabs_or_newline(input)) {
11514
347
    tmp_buffer = input;
11515
347
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11516
347
    internal_input = tmp_buffer;
11517
13.3k
  } else {
11518
13.3k
    internal_input = input;
11519
13.3k
  }
11520
13.6k
  std::string path;
11521
13.6k
  if (internal_input.empty()) {
11522
1.46k
    path = "/";
11523
12.1k
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11524
1.44k
    helpers::parse_prepared_path(internal_input.substr(1),
11525
1.44k
                                 ada::scheme::type::FILE, path);
11526
10.7k
  } else {
11527
10.7k
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11528
10.7k
  }
11529
13.6k
  return "file://" + path;
11530
13.6k
}
11531
11532
17.0k
bool can_parse(std::string_view input, const std::string_view* base_input) {
11533
  // Fast path: handles the overwhelming majority of inputs -- absolute special
11534
  // URLs with an ASCII domain, no credentials, and no base -- with a single
11535
  // forward scan and zero allocations.
11536
17.0k
  if (base_input == nullptr) {
11537
8.50k
    if (const auto r = try_can_parse_absolute_fast(input)) {
11538
236
      return *r;
11539
236
    }
11540
8.50k
  }
11541
11542
  // Reject inputs that exceed the configurable maximum length.
11543
  // This check is placed after the fast path so the common case (default 4 GB
11544
  // limit, absolute URLs) pays no overhead.
11545
  // Note: can_parse() does not perform normalization (percent-encoding, IDNA),
11546
  // so it cannot detect cases where a short input normalizes into a long URL.
11547
  // In such edge cases can_parse() may return true while parse() fails.
11548
16.7k
  const uint32_t max_length = ada::get_max_input_length();
11549
16.7k
  if (input.size() > max_length) {
11550
0
    return false;
11551
0
  }
11552
16.7k
  if (base_input != nullptr && base_input->size() > max_length) {
11553
0
    return false;
11554
0
  }
11555
11556
  // Fallback: run the parser in validation-only mode (store_values=false),
11557
  // which skips all the expensive work that isn't needed to determine validity:
11558
  // buffer reservation, credential encoding, path normalisation, query and
11559
  // fragment percent-encoding.  The host is still fully validated (IDNA, IPv4,
11560
  // IPv6) because parse_host() must run for correctness.
11561
16.7k
  ada::url_aggregator base_agg;
11562
16.7k
  ada::url_aggregator* base_ptr = nullptr;
11563
16.7k
  if (base_input != nullptr) {
11564
8.50k
    base_agg = ada::parser::parse_url_impl<ada::url_aggregator, false>(
11565
8.50k
        *base_input, nullptr);
11566
8.50k
    if (!base_agg.is_valid) return false;
11567
799
    base_ptr = &base_agg;
11568
799
  }
11569
9.06k
  return ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
11570
9.06k
                                                                 base_ptr)
11571
9.06k
      .is_valid;
11572
16.7k
}
11573
11574
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
11575
0
  switch (type) {
11576
0
    case ada::encoding_type::UTF8:
11577
0
      return "UTF-8";
11578
0
    case ada::encoding_type::UTF_16LE:
11579
0
      return "UTF-16LE";
11580
0
    case ada::encoding_type::UTF_16BE:
11581
0
      return "UTF-16BE";
11582
0
    default:
11583
0
      unreachable();
11584
0
  }
11585
0
}
11586
11587
}  // namespace ada
11588
/* end file src/implementation.cpp */
11589
/* begin file src/helpers.cpp */
11590
#include <cstdint>
11591
#include <cstring>
11592
#include <sstream>
11593
11594
11595
#if ADA_SSSE3
11596
#include <tmmintrin.h>
11597
#endif
11598
11599
namespace ada::helpers {
11600
11601
template <typename out_iter>
11602
251k
void encode_json(std::string_view view, out_iter out) {
11603
  // trivial implementation. could be faster.
11604
251k
  const char* hexvalues =
11605
251k
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11606
10.5M
  for (uint8_t c : view) {
11607
10.5M
    if (c == '\\') {
11608
4.78k
      *out++ = '\\';
11609
4.78k
      *out++ = '\\';
11610
10.5M
    } else if (c == '"') {
11611
4.15k
      *out++ = '\\';
11612
4.15k
      *out++ = '"';
11613
10.5M
    } else if (c <= 0x1f) {
11614
0
      *out++ = '\\';
11615
0
      *out++ = 'u';
11616
0
      *out++ = '0';
11617
0
      *out++ = '0';
11618
0
      *out++ = hexvalues[2 * c];
11619
0
      *out++ = hexvalues[2 * c + 1];
11620
10.5M
    } else {
11621
10.5M
      *out++ = c;
11622
10.5M
    }
11623
10.5M
  }
11624
251k
}
11625
11626
0
ada_unused std::string get_state(ada::state s) {
11627
0
  switch (s) {
11628
0
    case ada::state::AUTHORITY:
11629
0
      return "Authority";
11630
0
    case ada::state::SCHEME_START:
11631
0
      return "Scheme Start";
11632
0
    case ada::state::SCHEME:
11633
0
      return "Scheme";
11634
0
    case ada::state::HOST:
11635
0
      return "Host";
11636
0
    case ada::state::NO_SCHEME:
11637
0
      return "No Scheme";
11638
0
    case ada::state::FRAGMENT:
11639
0
      return "Fragment";
11640
0
    case ada::state::RELATIVE_SCHEME:
11641
0
      return "Relative Scheme";
11642
0
    case ada::state::RELATIVE_SLASH:
11643
0
      return "Relative Slash";
11644
0
    case ada::state::FILE:
11645
0
      return "File";
11646
0
    case ada::state::FILE_HOST:
11647
0
      return "File Host";
11648
0
    case ada::state::FILE_SLASH:
11649
0
      return "File Slash";
11650
0
    case ada::state::PATH_OR_AUTHORITY:
11651
0
      return "Path or Authority";
11652
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
11653
0
      return "Special Authority Ignore Slashes";
11654
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
11655
0
      return "Special Authority Slashes";
11656
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
11657
0
      return "Special Relative or Authority";
11658
0
    case ada::state::QUERY:
11659
0
      return "Query";
11660
0
    case ada::state::PATH:
11661
0
      return "Path";
11662
0
    case ada::state::PATH_START:
11663
0
      return "Path Start";
11664
0
    case ada::state::OPAQUE_PATH:
11665
0
      return "Opaque Path";
11666
0
    case ada::state::PORT:
11667
0
      return "Port";
11668
0
    default:
11669
0
      return "unknown state";
11670
0
  }
11671
0
}
11672
11673
ada_really_inline std::optional<std::string_view> prune_hash(
11674
1.44M
    std::string_view& input) noexcept {
11675
  // compiles down to 20--30 instructions including a class to memchr (C
11676
  // function). this function should be quite fast.
11677
1.44M
  size_t location_of_first = input.find('#');
11678
1.44M
  if (location_of_first == std::string_view::npos) {
11679
1.38M
    return std::nullopt;
11680
1.38M
  }
11681
63.0k
  std::string_view hash = input;
11682
63.0k
  hash.remove_prefix(location_of_first + 1);
11683
63.0k
  input.remove_suffix(input.size() - location_of_first);
11684
63.0k
  return hash;
11685
1.44M
}
11686
11687
41.2k
ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) {
11688
  // Let path be url's path.
11689
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11690
  // Windows drive letter, then return.
11691
41.2k
  if (type == ada::scheme::type::FILE &&
11692
22.3k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11693
13.6k
    if (checkers::is_normalized_windows_drive_letter(
11694
13.6k
            helpers::substring(path, 1))) {
11695
3.37k
      return false;
11696
3.37k
    }
11697
13.6k
  }
11698
11699
  // Remove path's last item, if any.
11700
37.8k
  size_t last_delimiter = path.rfind('/');
11701
37.8k
  if (last_delimiter != std::string::npos) {
11702
25.5k
    path.erase(last_delimiter);
11703
25.5k
    return true;
11704
25.5k
  }
11705
11706
12.3k
  return false;
11707
37.8k
}
11708
11709
ada_really_inline bool shorten_path(std::string_view& path,
11710
6.78k
                                    ada::scheme::type type) {
11711
  // Let path be url's path.
11712
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
11713
  // Windows drive letter, then return.
11714
6.78k
  if (type == ada::scheme::type::FILE &&
11715
337
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11716
234
    if (checkers::is_normalized_windows_drive_letter(
11717
234
            helpers::substring(path, 1))) {
11718
13
      return false;
11719
13
    }
11720
234
  }
11721
11722
  // Remove path's last item, if any.
11723
6.77k
  if (!path.empty()) {
11724
6.58k
    size_t slash_loc = path.rfind('/');
11725
6.58k
    if (slash_loc != std::string_view::npos) {
11726
6.43k
      path.remove_suffix(path.size() - slash_loc);
11727
6.43k
      return true;
11728
6.43k
    }
11729
6.58k
  }
11730
11731
334
  return false;
11732
6.77k
}
11733
11734
271k
ada_really_inline void remove_ascii_tab_or_newline(std::string& input) {
11735
  // if this ever becomes a performance issue, we could use an approach similar
11736
  // to has_tabs_or_newline
11737
271k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11738
271k
}
11739
11740
ada_really_inline constexpr std::string_view substring(std::string_view input,
11741
52.9k
                                                       size_t pos) {
11742
52.9k
  ADA_ASSERT_TRUE(pos <= input.size());
11743
  // The following is safer but unneeded if we have the above line:
11744
  // return pos > input.size() ? std::string_view() : input.substr(pos);
11745
52.9k
  return input.substr(pos);
11746
52.9k
}
11747
11748
90
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11749
90
  ADA_ASSERT_TRUE(pos <= input.size());
11750
90
  input.remove_suffix(input.size() - pos);
11751
90
}
11752
11753
// computes the number of trailing zeroes
11754
// this is a private inline function only defined in this source file.
11755
353k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
11756
#ifdef ADA_REGULAR_VISUAL_STUDIO
11757
  unsigned long ret;
11758
  // Search the mask data from least significant bit (LSB)
11759
  // to the most significant bit (MSB) for a set bit (1).
11760
  _BitScanForward(&ret, input_num);
11761
  return (int)ret;
11762
#else   // ADA_REGULAR_VISUAL_STUDIO
11763
353k
  return __builtin_ctzl(input_num);
11764
353k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11765
353k
}
11766
11767
// starting at index location, this finds the next location of a character
11768
// :, /, \\, ? or [. If none is found, view.size() is returned.
11769
// For use within get_host_delimiter_location.
11770
#if ADA_SSSE3
11771
ada_really_inline size_t find_next_host_delimiter_special(
11772
    std::string_view view, size_t location) noexcept {
11773
  // first check for short strings in which case we do it naively.
11774
  if (view.size() - location < 16) {  // slow path
11775
    for (size_t i = location; i < view.size(); i++) {
11776
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11777
          view[i] == '?' || view[i] == '[') {
11778
        return i;
11779
      }
11780
    }
11781
    return size_t(view.size());
11782
  }
11783
  // fast path for long strings (expected to be common)
11784
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
11785
  size_t i = location;
11786
  const __m128i low_mask =
11787
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11788
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11789
  const __m128i high_mask =
11790
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
11791
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11792
  const __m128i fmask = _mm_set1_epi8(0xf);
11793
  const __m128i zero = _mm_setzero_si128();
11794
  for (; i + 15 < view.size(); i += 16) {
11795
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11796
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11797
    __m128i highpart = _mm_shuffle_epi8(
11798
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11799
    __m128i classify = _mm_and_si128(lowpart, highpart);
11800
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11801
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11802
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11803
    // avoid false positives.
11804
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11805
    if (mask != 0) {
11806
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
11807
    }
11808
  }
11809
  if (i < view.size()) {
11810
    __m128i word =
11811
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11812
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
11813
    __m128i highpart = _mm_shuffle_epi8(
11814
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
11815
    __m128i classify = _mm_and_si128(lowpart, highpart);
11816
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
11817
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
11818
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
11819
    // avoid false positives.
11820
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
11821
    if (mask != 0) {
11822
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
11823
    }
11824
  }
11825
  return size_t(view.size());
11826
}
11827
#elif ADA_NEON
11828
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
11829
// support direct initialization of uint8x16_t. See
11830
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
11831
#ifndef ada_make_uint8x16_t
11832
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
11833
                            x13, x14, x15, x16)                                \
11834
  ([=]() {                                                                     \
11835
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
11836
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
11837
    return vld1q_u8(array);                                                    \
11838
  }())
11839
#endif
11840
11841
ada_really_inline size_t find_next_host_delimiter_special(
11842
    std::string_view view, size_t location) noexcept {
11843
  // first check for short strings in which case we do it naively.
11844
  if (view.size() - location < 16) {  // slow path
11845
    for (size_t i = location; i < view.size(); i++) {
11846
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11847
          view[i] == '?' || view[i] == '[') {
11848
        return i;
11849
      }
11850
    }
11851
    return size_t(view.size());
11852
  }
11853
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
11854
    uint8x16_t bit_mask =
11855
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
11856
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
11857
    uint8x16_t minput = vandq_u8(input, bit_mask);
11858
    uint8x16_t tmp = vpaddq_u8(minput, minput);
11859
    tmp = vpaddq_u8(tmp, tmp);
11860
    tmp = vpaddq_u8(tmp, tmp);
11861
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
11862
  };
11863
11864
  // fast path for long strings (expected to be common)
11865
  size_t i = location;
11866
  uint8x16_t low_mask =
11867
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11868
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
11869
  uint8x16_t high_mask =
11870
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
11871
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
11872
  uint8x16_t fmask = vmovq_n_u8(0xf);
11873
  uint8x16_t zero{0};
11874
  for (; i + 15 < view.size(); i += 16) {
11875
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
11876
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11877
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11878
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11879
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11880
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11881
      uint16_t is_non_zero = static_cast<uint16_t>(~to_bitmask(is_zero));
11882
      return i + trailing_zeroes(is_non_zero);
11883
    }
11884
  }
11885
11886
  if (i < view.size()) {
11887
    uint8x16_t word =
11888
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
11889
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
11890
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
11891
    uint8x16_t classify = vandq_u8(lowpart, highpart);
11892
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
11893
      uint8x16_t is_zero = vceqq_u8(classify, zero);
11894
      uint16_t is_non_zero = static_cast<uint16_t>(~to_bitmask(is_zero));
11895
      return view.length() - 16 + trailing_zeroes(is_non_zero);
11896
    }
11897
  }
11898
  return size_t(view.size());
11899
}
11900
#elif ADA_SSE2
11901
ada_really_inline size_t find_next_host_delimiter_special(
11902
1.15M
    std::string_view view, size_t location) noexcept {
11903
  // first check for short strings in which case we do it naively.
11904
1.15M
  if (view.size() - location < 16) {  // slow path
11905
5.60M
    for (size_t i = location; i < view.size(); i++) {
11906
4.84M
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11907
4.61M
          view[i] == '?' || view[i] == '[') {
11908
252k
        return i;
11909
252k
      }
11910
4.84M
    }
11911
760k
    return size_t(view.size());
11912
1.01M
  }
11913
  // fast path for long strings (expected to be common)
11914
142k
  size_t i = location;
11915
142k
  const __m128i mask1 = _mm_set1_epi8(':');
11916
142k
  const __m128i mask2 = _mm_set1_epi8('/');
11917
142k
  const __m128i mask3 = _mm_set1_epi8('\\');
11918
142k
  const __m128i mask4 = _mm_set1_epi8('?');
11919
142k
  const __m128i mask5 = _mm_set1_epi8('[');
11920
11921
236k
  for (; i + 15 < view.size(); i += 16) {
11922
195k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11923
195k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11924
195k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11925
195k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11926
195k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11927
195k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11928
195k
    __m128i m = _mm_or_si128(
11929
195k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11930
195k
    int mask = _mm_movemask_epi8(m);
11931
195k
    if (mask != 0) {
11932
101k
      return i + trailing_zeroes(mask);
11933
101k
    }
11934
195k
  }
11935
40.9k
  if (i < view.size()) {
11936
39.0k
    __m128i word =
11937
39.0k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11938
39.0k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11939
39.0k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11940
39.0k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11941
39.0k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11942
39.0k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11943
39.0k
    __m128i m = _mm_or_si128(
11944
39.0k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11945
39.0k
    int mask = _mm_movemask_epi8(m);
11946
39.0k
    if (mask != 0) {
11947
31.5k
      return view.length() - 16 + trailing_zeroes(mask);
11948
31.5k
    }
11949
39.0k
  }
11950
9.38k
  return size_t(view.length());
11951
40.9k
}
11952
#elif ADA_LSX
11953
ada_really_inline size_t find_next_host_delimiter_special(
11954
    std::string_view view, size_t location) noexcept {
11955
  // first check for short strings in which case we do it naively.
11956
  if (view.size() - location < 16) {  // slow path
11957
    for (size_t i = location; i < view.size(); i++) {
11958
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11959
          view[i] == '?' || view[i] == '[') {
11960
        return i;
11961
      }
11962
    }
11963
    return size_t(view.size());
11964
  }
11965
  // fast path for long strings (expected to be common)
11966
  size_t i = location;
11967
  const __m128i mask1 = __lsx_vrepli_b(':');
11968
  const __m128i mask2 = __lsx_vrepli_b('/');
11969
  const __m128i mask3 = __lsx_vrepli_b('\\');
11970
  const __m128i mask4 = __lsx_vrepli_b('?');
11971
  const __m128i mask5 = __lsx_vrepli_b('[');
11972
11973
  for (; i + 15 < view.size(); i += 16) {
11974
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
11975
    __m128i m1 = __lsx_vseq_b(word, mask1);
11976
    __m128i m2 = __lsx_vseq_b(word, mask2);
11977
    __m128i m3 = __lsx_vseq_b(word, mask3);
11978
    __m128i m4 = __lsx_vseq_b(word, mask4);
11979
    __m128i m5 = __lsx_vseq_b(word, mask5);
11980
    __m128i m =
11981
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11982
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11983
    if (mask != 0) {
11984
      return i + trailing_zeroes(mask);
11985
    }
11986
  }
11987
  if (i < view.size()) {
11988
    __m128i word =
11989
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
11990
    __m128i m1 = __lsx_vseq_b(word, mask1);
11991
    __m128i m2 = __lsx_vseq_b(word, mask2);
11992
    __m128i m3 = __lsx_vseq_b(word, mask3);
11993
    __m128i m4 = __lsx_vseq_b(word, mask4);
11994
    __m128i m5 = __lsx_vseq_b(word, mask5);
11995
    __m128i m =
11996
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
11997
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
11998
    if (mask != 0) {
11999
      return view.length() - 16 + trailing_zeroes(mask);
12000
    }
12001
  }
12002
  return size_t(view.length());
12003
}
12004
#elif ADA_RVV
12005
ada_really_inline size_t find_next_host_delimiter_special(
12006
    std::string_view view, size_t location) noexcept {
12007
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
12008
  // being faster on future hardware.
12009
#if 0
12010
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
12011
  static const uint8_t tbl[16] = {
12012
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
12013
  };
12014
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
12015
#endif
12016
  uint8_t* src = (uint8_t*)view.data() + location;
12017
  for (size_t vl, n = view.size() - location; n > 0;
12018
       n -= vl, src += vl, location += vl) {
12019
    vl = __riscv_vsetvl_e8m1(n);
12020
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
12021
#if 0
12022
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
12023
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
12024
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
12025
#else
12026
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
12027
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
12028
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
12029
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
12030
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
12031
    vbool8_t m = __riscv_vmor(
12032
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
12033
        m5, vl);
12034
#endif
12035
    long idx = __riscv_vfirst(m, vl);
12036
    if (idx >= 0) return location + idx;
12037
  }
12038
  return size_t(view.size());
12039
}
12040
#else
12041
// : / [ \\ ?
12042
static constexpr std::array<uint8_t, 256> special_host_delimiters =
12043
    []() consteval {
12044
      std::array<uint8_t, 256> result{};
12045
      for (int i : {':', '/', '[', '\\', '?'}) {
12046
        result[i] = 1;
12047
      }
12048
      return result;
12049
    }();
12050
// credit: @the-moisrex recommended a table-based approach
12051
ada_really_inline size_t find_next_host_delimiter_special(
12052
    std::string_view view, size_t location) noexcept {
12053
  auto const str = view.substr(location);
12054
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
12055
    if (special_host_delimiters[(uint8_t)*pos]) {
12056
      return pos - str.begin() + location;
12057
    }
12058
  }
12059
  return size_t(view.size());
12060
}
12061
#endif
12062
12063
// starting at index location, this finds the next location of a character
12064
// :, /, ? or [. If none is found, view.size() is returned.
12065
// For use within get_host_delimiter_location.
12066
#if ADA_SSSE3
12067
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12068
                                                  size_t location) noexcept {
12069
  // first check for short strings in which case we do it naively.
12070
  if (view.size() - location < 16) {  // slow path
12071
    for (size_t i = location; i < view.size(); i++) {
12072
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
12073
          view[i] == '[') {
12074
        return i;
12075
      }
12076
    }
12077
    return size_t(view.size());
12078
  }
12079
  // fast path for long strings (expected to be common)
12080
  size_t i = location;
12081
  // Lookup tables for bit classification:
12082
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
12083
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
12084
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
12085
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
12086
  const __m128i low_mask =
12087
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12088
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
12089
  const __m128i high_mask =
12090
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
12091
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
12092
  const __m128i fmask = _mm_set1_epi8(0xf);
12093
  const __m128i zero = _mm_setzero_si128();
12094
12095
  for (; i + 15 < view.size(); i += 16) {
12096
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
12097
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
12098
    __m128i highpart = _mm_shuffle_epi8(
12099
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
12100
    __m128i classify = _mm_and_si128(lowpart, highpart);
12101
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
12102
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
12103
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
12104
    // avoid false positives.
12105
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
12106
    if (mask != 0) {
12107
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
12108
    }
12109
  }
12110
12111
  if (i < view.size()) {
12112
    __m128i word =
12113
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
12114
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
12115
    __m128i highpart = _mm_shuffle_epi8(
12116
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
12117
    __m128i classify = _mm_and_si128(lowpart, highpart);
12118
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
12119
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
12120
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
12121
    // avoid false positives.
12122
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
12123
    if (mask != 0) {
12124
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
12125
    }
12126
  }
12127
  return size_t(view.size());
12128
}
12129
#elif ADA_NEON
12130
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12131
                                                  size_t location) noexcept {
12132
  // first check for short strings in which case we do it naively.
12133
  if (view.size() - location < 16) {  // slow path
12134
    for (size_t i = location; i < view.size(); i++) {
12135
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
12136
          view[i] == '[') {
12137
        return i;
12138
      }
12139
    }
12140
    return size_t(view.size());
12141
  }
12142
  auto to_bitmask = [](uint8x16_t input) -> uint16_t {
12143
    uint8x16_t bit_mask =
12144
        ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
12145
                            0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
12146
    uint8x16_t minput = vandq_u8(input, bit_mask);
12147
    uint8x16_t tmp = vpaddq_u8(minput, minput);
12148
    tmp = vpaddq_u8(tmp, tmp);
12149
    tmp = vpaddq_u8(tmp, tmp);
12150
    return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
12151
  };
12152
12153
  // fast path for long strings (expected to be common)
12154
  size_t i = location;
12155
  uint8x16_t low_mask =
12156
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12157
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
12158
  uint8x16_t high_mask =
12159
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
12160
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
12161
  uint8x16_t fmask = vmovq_n_u8(0xf);
12162
  uint8x16_t zero{0};
12163
  for (; i + 15 < view.size(); i += 16) {
12164
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
12165
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
12166
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
12167
    uint8x16_t classify = vandq_u8(lowpart, highpart);
12168
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
12169
      uint8x16_t is_zero = vceqq_u8(classify, zero);
12170
      uint16_t is_non_zero = static_cast<uint16_t>(~to_bitmask(is_zero));
12171
      return i + trailing_zeroes(is_non_zero);
12172
    }
12173
  }
12174
12175
  if (i < view.size()) {
12176
    uint8x16_t word =
12177
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
12178
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
12179
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
12180
    uint8x16_t classify = vandq_u8(lowpart, highpart);
12181
    if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
12182
      uint8x16_t is_zero = vceqq_u8(classify, zero);
12183
      uint16_t is_non_zero = static_cast<uint16_t>(~to_bitmask(is_zero));
12184
      return view.length() - 16 + trailing_zeroes(is_non_zero);
12185
    }
12186
  }
12187
  return size_t(view.size());
12188
}
12189
#elif ADA_SSE2
12190
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12191
228k
                                                  size_t location) noexcept {
12192
  // first check for short strings in which case we do it naively.
12193
228k
  if (view.size() - location < 16) {  // slow path
12194
25.0k
    for (size_t i = location; i < view.size(); i++) {
12195
22.9k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
12196
19.5k
          view[i] == '[') {
12197
4.59k
        return i;
12198
4.59k
      }
12199
22.9k
    }
12200
2.10k
    return size_t(view.size());
12201
6.70k
  }
12202
  // fast path for long strings (expected to be common)
12203
221k
  size_t i = location;
12204
221k
  const __m128i mask1 = _mm_set1_epi8(':');
12205
221k
  const __m128i mask2 = _mm_set1_epi8('/');
12206
221k
  const __m128i mask4 = _mm_set1_epi8('?');
12207
221k
  const __m128i mask5 = _mm_set1_epi8('[');
12208
12209
233k
  for (; i + 15 < view.size(); i += 16) {
12210
231k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
12211
231k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
12212
231k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
12213
231k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
12214
231k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
12215
231k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
12216
231k
    int mask = _mm_movemask_epi8(m);
12217
231k
    if (mask != 0) {
12218
220k
      return i + trailing_zeroes(mask);
12219
220k
    }
12220
231k
  }
12221
1.13k
  if (i < view.size()) {
12222
947
    __m128i word =
12223
947
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
12224
947
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
12225
947
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
12226
947
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
12227
947
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
12228
947
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
12229
947
    int mask = _mm_movemask_epi8(m);
12230
947
    if (mask != 0) {
12231
205
      return view.length() - 16 + trailing_zeroes(mask);
12232
205
    }
12233
947
  }
12234
930
  return size_t(view.length());
12235
1.13k
}
12236
#elif ADA_LSX
12237
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12238
                                                  size_t location) noexcept {
12239
  // first check for short strings in which case we do it naively.
12240
  if (view.size() - location < 16) {  // slow path
12241
    for (size_t i = location; i < view.size(); i++) {
12242
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
12243
          view[i] == '[') {
12244
        return i;
12245
      }
12246
    }
12247
    return size_t(view.size());
12248
  }
12249
  // fast path for long strings (expected to be common)
12250
  size_t i = location;
12251
  const __m128i mask1 = __lsx_vrepli_b(':');
12252
  const __m128i mask2 = __lsx_vrepli_b('/');
12253
  const __m128i mask4 = __lsx_vrepli_b('?');
12254
  const __m128i mask5 = __lsx_vrepli_b('[');
12255
12256
  for (; i + 15 < view.size(); i += 16) {
12257
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
12258
    __m128i m1 = __lsx_vseq_b(word, mask1);
12259
    __m128i m2 = __lsx_vseq_b(word, mask2);
12260
    __m128i m4 = __lsx_vseq_b(word, mask4);
12261
    __m128i m5 = __lsx_vseq_b(word, mask5);
12262
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
12263
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
12264
    if (mask != 0) {
12265
      return i + trailing_zeroes(mask);
12266
    }
12267
  }
12268
  if (i < view.size()) {
12269
    __m128i word =
12270
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
12271
    __m128i m1 = __lsx_vseq_b(word, mask1);
12272
    __m128i m2 = __lsx_vseq_b(word, mask2);
12273
    __m128i m4 = __lsx_vseq_b(word, mask4);
12274
    __m128i m5 = __lsx_vseq_b(word, mask5);
12275
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
12276
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
12277
    if (mask != 0) {
12278
      return view.length() - 16 + trailing_zeroes(mask);
12279
    }
12280
  }
12281
  return size_t(view.length());
12282
}
12283
#elif ADA_RVV
12284
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12285
                                                  size_t location) noexcept {
12286
  uint8_t* src = (uint8_t*)view.data() + location;
12287
  for (size_t vl, n = view.size() - location; n > 0;
12288
       n -= vl, src += vl, location += vl) {
12289
    vl = __riscv_vsetvl_e8m1(n);
12290
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
12291
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
12292
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
12293
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
12294
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
12295
    vbool8_t m =
12296
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
12297
    long idx = __riscv_vfirst(m, vl);
12298
    if (idx >= 0) return location + idx;
12299
  }
12300
  return size_t(view.size());
12301
}
12302
#else
12303
// : / [ ?
12304
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
12305
  std::array<uint8_t, 256> result{};
12306
  for (int i : {':', '/', '?', '['}) {
12307
    result[i] = 1;
12308
  }
12309
  return result;
12310
}();
12311
// credit: @the-moisrex recommended a table-based approach
12312
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
12313
                                                  size_t location) noexcept {
12314
  auto const str = view.substr(location);
12315
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
12316
    if (host_delimiters[(uint8_t)*pos]) {
12317
      return pos - str.begin() + location;
12318
    }
12319
  }
12320
  return size_t(view.size());
12321
}
12322
#endif
12323
12324
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
12325
1.35M
    const bool is_special, std::string_view& view) noexcept {
12326
  /**
12327
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
12328
   * compute a variable called insideBrackets but this variable is only used
12329
   * once, to check whether a ':' character was found outside brackets. Exact
12330
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
12331
   * It is conceptually simpler and arguably more efficient to just return a
12332
   * Boolean indicating whether ':' was found outside brackets.
12333
   */
12334
1.35M
  const size_t view_size = view.size();
12335
1.35M
  size_t location = 0;
12336
1.35M
  bool found_colon = false;
12337
  /**
12338
   * Performance analysis:
12339
   *
12340
   * We are basically seeking the end of the hostname which can be indicated
12341
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
12342
   * (where '\\' is only applicable for special URLs). However, these must
12343
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
12344
   * '?' does not count.
12345
   *
12346
   * So we can skip ahead to the next delimiter, as long as we include '[' in
12347
   * the set of delimiters, and that we handle it first.
12348
   *
12349
   * So the trick is to have a fast function that locates the next delimiter.
12350
   * Unless we find '[', then it only needs to be called once! Ideally, such a
12351
   * function would be provided by the C++ standard library, but it seems that
12352
   * find_first_of is not very fast, so we are forced to roll our own.
12353
   *
12354
   * We do not break into two loops for speed, but for clarity.
12355
   */
12356
1.35M
  if (is_special) {
12357
    // We move to the next delimiter.
12358
1.12M
    location = find_next_host_delimiter_special(view, location);
12359
    // Unless we find '[' then we are going only going to have to call
12360
    // find_next_host_delimiter_special once.
12361
1.15M
    for (; location < view_size;
12362
1.12M
         location = find_next_host_delimiter_special(view, location)) {
12363
385k
      if (view[location] == '[') {
12364
37.7k
        location = view.find(']', location);
12365
37.7k
        if (location == std::string_view::npos) {
12366
          // performance: view.find might get translated to a memchr, which
12367
          // has no notion of std::string_view::npos, so the code does not
12368
          // reflect the assembly.
12369
12.3k
          location = view_size;
12370
12.3k
          break;
12371
12.3k
        }
12372
347k
      } else {
12373
347k
        found_colon = view[location] == ':';
12374
347k
        break;
12375
347k
      }
12376
385k
    }
12377
1.12M
  } else {
12378
    // We move to the next delimiter.
12379
225k
    location = find_next_host_delimiter(view, location);
12380
    // Unless we find '[' then we are going only going to have to call
12381
    // find_next_host_delimiter_special once.
12382
228k
    for (; location < view_size;
12383
225k
         location = find_next_host_delimiter(view, location)) {
12384
225k
      if (view[location] == '[') {
12385
2.96k
        location = view.find(']', location);
12386
2.96k
        if (location == std::string_view::npos) {
12387
          // performance: view.find might get translated to a memchr, which
12388
          // has no notion of std::string_view::npos, so the code does not
12389
          // reflect the assembly.
12390
220
          location = view_size;
12391
220
          break;
12392
220
        }
12393
222k
      } else {
12394
222k
        found_colon = view[location] == ':';
12395
222k
        break;
12396
222k
      }
12397
225k
    }
12398
225k
  }
12399
  // performance: remove_suffix may translate into a single instruction.
12400
1.35M
  view.remove_suffix(view_size - location);
12401
1.35M
  return {location, found_colon};
12402
1.35M
}
12403
12404
1.44M
void trim_c0_whitespace(std::string_view& input) noexcept {
12405
1.51M
  while (!input.empty() &&
12406
1.48M
         ada::unicode::is_c0_control_or_space(input.front())) {
12407
68.4k
    input.remove_prefix(1);
12408
68.4k
  }
12409
1.49M
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12410
48.6k
    input.remove_suffix(1);
12411
48.6k
  }
12412
1.44M
}
12413
12414
ada_really_inline void parse_prepared_path(std::string_view input,
12415
                                           ada::scheme::type type,
12416
44.8k
                                           std::string& path) {
12417
44.8k
  ada_log("parse_prepared_path ", input);
12418
44.8k
  uint8_t accumulator = checkers::path_signature(input);
12419
  // Let us first detect a trivial case.
12420
  // If it is special, we check that we have no dot, no %,  no \ and no
12421
  // character needing percent encoding. Otherwise, we check that we have no %,
12422
  // no dot, and no character needing percent encoding.
12423
44.8k
  constexpr uint8_t need_encoding = 1;
12424
44.8k
  constexpr uint8_t backslash_char = 2;
12425
44.8k
  constexpr uint8_t dot_char = 4;
12426
44.8k
  constexpr uint8_t percent_char = 8;
12427
44.8k
  bool special = type != ada::scheme::NOT_SPECIAL;
12428
44.8k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12429
15.1k
                                      checkers::is_windows_drive_letter(input));
12430
44.8k
  bool trivial_path =
12431
44.8k
      (special ? (accumulator == 0)
12432
44.8k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12433
1.64k
                  0)) &&
12434
22.5k
      (!may_need_slow_file_handling);
12435
44.8k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
12436
    // '4' means that we have at least one dot, but nothing that requires
12437
    // percent encoding or decoding. The only part that is not trivial is
12438
    // that we may have single dots and double dots path segments.
12439
    // If we have such segments, then we either have a path that begins
12440
    // with '.' (easy to check), or we have the sequence './'.
12441
    // Note: input cannot be empty, it must at least contain one character ('.')
12442
    // Note: we know that '\' is not present.
12443
5.53k
    if (input[0] != '.') {
12444
3.91k
      size_t slashdot = 0;
12445
3.91k
      bool dot_is_file = true;
12446
14.9k
      for (;;) {
12447
14.9k
        slashdot = input.find("/.", slashdot);
12448
14.9k
        if (slashdot == std::string_view::npos) {  // common case
12449
3.91k
          break;
12450
10.9k
        } else {  // uncommon
12451
          // only three cases matter: /./, /.. or a final /
12452
10.9k
          slashdot += 2;
12453
10.9k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12454
2.42k
                           input[slashdot] == '/');
12455
10.9k
        }
12456
14.9k
      }
12457
3.91k
      trivial_path = dot_is_file;
12458
3.91k
    }
12459
5.53k
  }
12460
44.8k
  if (trivial_path) {
12461
24.1k
    ada_log("parse_path trivial");
12462
24.1k
    path += '/';
12463
24.1k
    path += input;
12464
24.1k
    return;
12465
24.1k
  }
12466
  // We are going to need to look a bit at the path, but let us see if we can
12467
  // ignore percent encoding *and* backslashes *and* percent characters.
12468
  // Except for the trivial case, this is likely to capture 99% of paths out
12469
  // there.
12470
20.7k
  bool fast_path =
12471
20.7k
      (special &&
12472
19.5k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12473
3.73k
      (type != ada::scheme::type::FILE);
12474
20.7k
  if (fast_path) {
12475
2.02k
    ada_log("parse_prepared_path fast");
12476
    // Here we don't need to worry about \ or percent encoding.
12477
    // We also do not have a file protocol. We might have dots, however,
12478
    // but dots must as appear as '.', and they cannot be encoded because
12479
    // the symbol '%' is not present.
12480
2.02k
    size_t previous_location = 0;  // We start at 0.
12481
20.2k
    do {
12482
20.2k
      size_t new_location = input.find('/', previous_location);
12483
      // std::string_view path_view = input;
12484
      //  We process the last segment separately:
12485
20.2k
      if (new_location == std::string_view::npos) {
12486
2.02k
        std::string_view path_view = input.substr(previous_location);
12487
2.02k
        if (path_view == "..") {  // The path ends with ..
12488
          // e.g., if you receive ".." with an empty path, you go to "/".
12489
424
          if (path.empty()) {
12490
146
            path = '/';
12491
146
            return;
12492
146
          }
12493
          // Fast case where we have nothing to do:
12494
278
          if (path.back() == '/') {
12495
113
            return;
12496
113
          }
12497
          // If you have the path "/joe/myfriend",
12498
          // then you delete 'myfriend'.
12499
165
          path.resize(path.rfind('/') + 1);
12500
165
          return;
12501
278
        }
12502
1.59k
        path += '/';
12503
1.59k
        if (path_view != ".") {
12504
1.17k
          path.append(path_view);
12505
1.17k
        }
12506
1.59k
        return;
12507
18.2k
      } else {
12508
        // This is a non-final segment.
12509
18.2k
        std::string_view path_view =
12510
18.2k
            input.substr(previous_location, new_location - previous_location);
12511
18.2k
        previous_location = new_location + 1;
12512
18.2k
        if (path_view == "..") {
12513
4.69k
          size_t last_delimiter = path.rfind('/');
12514
4.69k
          if (last_delimiter != std::string::npos) {
12515
3.19k
            path.erase(last_delimiter);
12516
3.19k
          }
12517
13.5k
        } else if (path_view != ".") {
12518
11.4k
          path += '/';
12519
11.4k
          path.append(path_view);
12520
11.4k
        }
12521
18.2k
      }
12522
20.2k
    } while (true);
12523
18.6k
  } else {
12524
18.6k
    ada_log("parse_path slow");
12525
    // we have reached the general case
12526
18.6k
    bool needs_percent_encoding = (accumulator & 1);
12527
18.6k
    std::string path_buffer_tmp;
12528
82.9k
    do {
12529
82.9k
      size_t location = (special && (accumulator & 2))
12530
82.9k
                            ? input.find_first_of("/\\")
12531
82.9k
                            : input.find('/');
12532
82.9k
      std::string_view path_view = input;
12533
82.9k
      if (location != std::string_view::npos) {
12534
64.2k
        path_view.remove_suffix(path_view.size() - location);
12535
64.2k
        input.remove_prefix(location + 1);
12536
64.2k
      }
12537
      // path_buffer is either path_view or it might point at a percent encoded
12538
      // temporary file.
12539
82.9k
      std::string_view path_buffer =
12540
82.9k
          (needs_percent_encoding &&
12541
53.1k
           ada::unicode::percent_encode<false>(
12542
53.1k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12543
82.9k
              ? path_buffer_tmp
12544
82.9k
              : path_view;
12545
82.9k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12546
16.5k
        helpers::shorten_path(path, type);
12547
16.5k
        if (location == std::string_view::npos) {
12548
1.20k
          path += '/';
12549
1.20k
        }
12550
66.3k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12551
5.54k
                 (location == std::string_view::npos)) {
12552
618
        path += '/';
12553
618
      }
12554
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12555
65.7k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
12556
        // If url's scheme is "file", url's path is empty, and path_buffer is a
12557
        // Windows drive letter, then replace the second code point in
12558
        // path_buffer with U+003A (:).
12559
60.8k
        if (type == ada::scheme::type::FILE && path.empty() &&
12560
14.7k
            checkers::is_windows_drive_letter(path_buffer)) {
12561
1.05k
          path += '/';
12562
1.05k
          path += path_buffer[0];
12563
1.05k
          path += ':';
12564
1.05k
          path_buffer.remove_prefix(2);
12565
1.05k
          path.append(path_buffer);
12566
59.7k
        } else {
12567
          // Append path_buffer to url's path.
12568
59.7k
          path += '/';
12569
59.7k
          path.append(path_buffer);
12570
59.7k
        }
12571
60.8k
      }
12572
82.9k
      if (location == std::string_view::npos) {
12573
18.6k
        return;
12574
18.6k
      }
12575
82.9k
    } while (true);
12576
18.6k
  }
12577
20.7k
}
12578
12579
0
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
12580
0
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
12581
0
          input1.size(), " bytes] is part of string '", input2, "' [",
12582
0
          input2.size(), " bytes]");
12583
0
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
12584
0
         input1.data() < input2.data() + input2.size();
12585
0
}
12586
12587
template <class url_type>
12588
7.54k
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12589
7.54k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12590
7.54k
  if (!url.has_opaque_path) return;
12591
0
  if (url.has_hash()) return;
12592
0
  if (url.has_search()) return;
12593
12594
0
  auto path = std::string(url.get_pathname());
12595
0
  while (!path.empty() && path.back() == ' ') {
12596
0
    path.resize(path.size() - 1);
12597
0
  }
12598
0
  url.update_base_pathname(path);
12599
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Line
Count
Source
12588
3.15k
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12589
3.15k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12590
3.15k
  if (!url.has_opaque_path) return;
12591
0
  if (url.has_hash()) return;
12592
0
  if (url.has_search()) return;
12593
12594
0
  auto path = std::string(url.get_pathname());
12595
0
  while (!path.empty() && path.back() == ' ') {
12596
0
    path.resize(path.size() - 1);
12597
0
  }
12598
0
  url.update_base_pathname(path);
12599
0
}
void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
Line
Count
Source
12588
4.38k
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12589
4.38k
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12590
4.38k
  if (!url.has_opaque_path) return;
12591
0
  if (url.has_hash()) return;
12592
0
  if (url.has_search()) return;
12593
12594
0
  auto path = std::string(url.get_pathname());
12595
0
  while (!path.empty() && path.back() == ' ') {
12596
0
    path.resize(path.size() - 1);
12597
0
  }
12598
0
  url.update_base_pathname(path);
12599
0
}
12600
12601
// @ / \\ ?
12602
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
12603
    []() consteval {
12604
      std::array<uint8_t, 256> result{};
12605
      for (uint8_t i : {'@', '/', '\\', '?'}) {
12606
        result[i] = 1;
12607
      }
12608
      return result;
12609
    }();
12610
// credit: @the-moisrex recommended a table-based approach
12611
ada_really_inline size_t
12612
187k
find_authority_delimiter_special(std::string_view view) noexcept {
12613
  // performance note: we might be able to gain further performance
12614
  // with SIMD intrinsics.
12615
1.66M
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12616
1.65M
    if (authority_delimiter_special[(uint8_t)*pos]) {
12617
181k
      return pos - view.begin();
12618
181k
    }
12619
1.65M
  }
12620
6.01k
  return size_t(view.size());
12621
187k
}
12622
12623
// @ / ?
12624
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
12625
  std::array<uint8_t, 256> result{};
12626
  for (uint8_t i : {'@', '/', '?'}) {
12627
    result[i] = 1;
12628
  }
12629
  return result;
12630
}();
12631
// credit: @the-moisrex recommended a table-based approach
12632
ada_really_inline size_t
12633
16.7k
find_authority_delimiter(std::string_view view) noexcept {
12634
  // performance note: we might be able to gain further performance
12635
  // with SIMD instrinsics.
12636
462k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12637
462k
    if (authority_delimiter[(uint8_t)*pos]) {
12638
16.0k
      return pos - view.begin();
12639
16.0k
    }
12640
462k
  }
12641
696
  return size_t(view.size());
12642
16.7k
}
12643
12644
}  // namespace ada::helpers
12645
12646
namespace ada {
12647
0
ada_warn_unused std::string to_string(ada::state state) {
12648
0
  return ada::helpers::get_state(state);
12649
0
}
12650
#undef ada_make_uint8x16_t
12651
}  // namespace ada
12652
/* end file src/helpers.cpp */
12653
/* begin file src/url.cpp */
12654
12655
#include <algorithm>
12656
#include <iterator>
12657
#include <numeric>
12658
#include <ranges>
12659
#include <string>
12660
#include <string_view>
12661
12662
namespace ada {
12663
12664
701
bool url::parse_opaque_host(std::string_view input) {
12665
701
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12666
701
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12667
56
    return is_valid = false;
12668
56
  }
12669
12670
  // Return the result of running UTF-8 percent-encode on input using the C0
12671
  // control percent-encode set.
12672
645
  host = ada::unicode::percent_encode(
12673
645
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12674
645
  return true;
12675
701
}
12676
12677
5.17k
bool url::parse_ipv4(std::string_view input) {
12678
5.17k
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12679
5.17k
  if (input.back() == '.') {
12680
456
    input.remove_suffix(1);
12681
456
  }
12682
5.17k
  size_t digit_count{0};
12683
5.17k
  int pure_decimal_count = 0;  // entries that are decimal
12684
5.17k
  std::string_view original_input =
12685
5.17k
      input;  // we might use this if pure_decimal_count == 4.
12686
5.17k
  uint64_t ipv4{0};
12687
  // we could unroll for better performance?
12688
6.68k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12689
6.60k
    uint32_t
12690
6.60k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12691
6.60k
    bool is_hex = checkers::has_hex_prefix(input);
12692
6.60k
    if (is_hex && ((input.length() == 2) ||
12693
1.40k
                   ((input.length() > 2) && (input[2] == '.')))) {
12694
      // special case
12695
245
      segment_result = 0;
12696
245
      input.remove_prefix(2);
12697
6.36k
    } else {
12698
6.36k
      std::from_chars_result r{};
12699
6.36k
      if (is_hex) {
12700
1.36k
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12701
1.36k
                            segment_result, 16);
12702
4.99k
      } else if ((input.length() >= 2) && input[0] == '0' &&
12703
1.46k
                 checkers::is_digit(input[1])) {
12704
1.11k
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12705
1.11k
                            segment_result, 8);
12706
3.88k
      } else {
12707
3.88k
        pure_decimal_count++;
12708
3.88k
        r = std::from_chars(input.data(), input.data() + input.size(),
12709
3.88k
                            segment_result, 10);
12710
3.88k
      }
12711
6.36k
      if (r.ec != std::errc()) {
12712
1.15k
        return is_valid = false;
12713
1.15k
      }
12714
5.20k
      input.remove_prefix(r.ptr - input.data());
12715
5.20k
    }
12716
5.45k
    if (input.empty()) {
12717
      // We have the last value.
12718
      // At this stage, ipv4 contains digit_count*8 bits.
12719
      // So we have 32-digit_count*8 bits left.
12720
3.64k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12721
74
        return is_valid = false;
12722
74
      }
12723
3.56k
      ipv4 <<= (32 - digit_count * 8);
12724
3.56k
      ipv4 |= segment_result;
12725
3.56k
      goto final;
12726
3.64k
    } else {
12727
      // There is more, so that the value must no be larger than 255
12728
      // and we must have a '.'.
12729
1.80k
      if ((segment_result > 255) || (input[0] != '.')) {
12730
302
        return is_valid = false;
12731
302
      }
12732
1.50k
      ipv4 <<= 8;
12733
1.50k
      ipv4 |= segment_result;
12734
1.50k
      input.remove_prefix(1);  // remove '.'
12735
1.50k
    }
12736
5.45k
  }
12737
80
  if ((digit_count != 4) || (!input.empty())) {
12738
80
    return is_valid = false;
12739
80
  }
12740
3.56k
final:
12741
  // We could also check r.ptr to see where the parsing ended.
12742
3.56k
  if (pure_decimal_count == 4) {
12743
24
    host = original_input;  // The original input was already all decimal and we
12744
                            // validated it.
12745
3.54k
  } else {
12746
3.54k
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12747
3.54k
  }
12748
3.56k
  host_type = IPV4;
12749
3.56k
  return true;
12750
80
}
12751
12752
1.09k
bool url::parse_ipv6(std::string_view input) {
12753
1.09k
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12754
12755
1.09k
  if (input.empty()) {
12756
90
    return is_valid = false;
12757
90
  }
12758
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12759
1.00k
  std::array<uint16_t, 8> address{};
12760
12761
  // Let pieceIndex be 0.
12762
1.00k
  int piece_index = 0;
12763
12764
  // Let compress be null.
12765
1.00k
  std::optional<int> compress{};
12766
12767
  // Let pointer be a pointer for input.
12768
1.00k
  std::string_view::iterator pointer = input.begin();
12769
12770
  // If c is U+003A (:), then:
12771
1.00k
  if (input[0] == ':') {
12772
    // If remaining does not start with U+003A (:), validation error, return
12773
    // failure.
12774
385
    if (input.size() == 1 || input[1] != ':') {
12775
51
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12776
51
      return is_valid = false;
12777
51
    }
12778
12779
    // Increase pointer by 2.
12780
334
    pointer += 2;
12781
12782
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12783
334
    compress = ++piece_index;
12784
334
  }
12785
12786
  // While c is not the EOF code point:
12787
2.74k
  while (pointer != input.end()) {
12788
    // If pieceIndex is 8, validation error, return failure.
12789
2.21k
    if (piece_index == 8) {
12790
12
      ada_log("parse_ipv6 piece_index == 8");
12791
12
      return is_valid = false;
12792
12
    }
12793
12794
    // If c is U+003A (:), then:
12795
2.20k
    if (*pointer == ':') {
12796
      // If compress is non-null, validation error, return failure.
12797
230
      if (compress.has_value()) {
12798
23
        ada_log("parse_ipv6 compress is non-null");
12799
23
        return is_valid = false;
12800
23
      }
12801
12802
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12803
      // then continue.
12804
207
      pointer++;
12805
207
      compress = ++piece_index;
12806
207
      continue;
12807
230
    }
12808
12809
    // Let value and length be 0.
12810
1.97k
    uint16_t value = 0, length = 0;
12811
12812
    // While length is less than 4 and c is an ASCII hex digit,
12813
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
12814
    // increase pointer and length by 1.
12815
4.97k
    while (length < 4 && pointer != input.end() &&
12816
4.46k
           unicode::is_ascii_hex_digit(*pointer)) {
12817
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12818
3.00k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12819
3.00k
      pointer++;
12820
3.00k
      length++;
12821
3.00k
    }
12822
12823
    // If c is U+002E (.), then:
12824
1.97k
    if (pointer != input.end() && *pointer == '.') {
12825
      // If length is 0, validation error, return failure.
12826
227
      if (length == 0) {
12827
12
        ada_log("parse_ipv6 length is 0");
12828
12
        return is_valid = false;
12829
12
      }
12830
12831
      // Decrease pointer by length.
12832
215
      pointer -= length;
12833
12834
      // If pieceIndex is greater than 6, validation error, return failure.
12835
215
      if (piece_index > 6) {
12836
9
        ada_log("parse_ipv6 piece_index > 6");
12837
9
        return is_valid = false;
12838
9
      }
12839
12840
      // Let numbersSeen be 0.
12841
206
      int numbers_seen = 0;
12842
12843
      // While c is not the EOF code point:
12844
637
      while (pointer != input.end()) {
12845
        // Let ipv4Piece be null.
12846
571
        std::optional<uint16_t> ipv4_piece{};
12847
12848
        // If numbersSeen is greater than 0, then:
12849
571
        if (numbers_seen > 0) {
12850
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12851
          // pointer by 1.
12852
365
          if (*pointer == '.' && numbers_seen < 4) {
12853
320
            pointer++;
12854
320
          }
12855
          // Otherwise, validation error, return failure.
12856
45
          else {
12857
45
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12858
45
            return is_valid = false;
12859
45
          }
12860
365
        }
12861
12862
        // If c is not an ASCII digit, validation error, return failure.
12863
526
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12864
42
          ada_log(
12865
42
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12866
42
              "failure");
12867
42
          return is_valid = false;
12868
42
        }
12869
12870
        // While c is an ASCII digit:
12871
1.16k
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12872
          // Let number be c interpreted as decimal number.
12873
735
          int number = *pointer - '0';
12874
12875
          // If ipv4Piece is null, then set ipv4Piece to number.
12876
735
          if (!ipv4_piece.has_value()) {
12877
484
            ipv4_piece = number;
12878
484
          }
12879
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12880
251
          else if (ipv4_piece == 0) {
12881
27
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12882
27
            return is_valid = false;
12883
27
          }
12884
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12885
224
          else {
12886
224
            ipv4_piece = *ipv4_piece * 10 + number;
12887
224
          }
12888
12889
          // If ipv4Piece is greater than 255, validation error, return failure.
12890
708
          if (ipv4_piece > 255) {
12891
26
            ada_log("parse_ipv6 ipv4_piece > 255");
12892
26
            return is_valid = false;
12893
26
          }
12894
12895
          // Increase pointer by 1.
12896
682
          pointer++;
12897
682
        }
12898
12899
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
12900
        // ipv4Piece.
12901
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12902
431
        address[piece_index] =
12903
431
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12904
12905
        // Increase numbersSeen by 1.
12906
431
        numbers_seen++;
12907
12908
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12909
431
        if (numbers_seen == 2 || numbers_seen == 4) {
12910
192
          piece_index++;
12911
192
        }
12912
431
      }
12913
12914
      // If numbersSeen is not 4, validation error, return failure.
12915
66
      if (numbers_seen != 4) {
12916
24
        return is_valid = false;
12917
24
      }
12918
12919
      // Break.
12920
42
      break;
12921
66
    }
12922
    // Otherwise, if c is U+003A (:):
12923
1.74k
    else if ((pointer != input.end()) && (*pointer == ':')) {
12924
      // Increase pointer by 1.
12925
1.26k
      pointer++;
12926
12927
      // If c is the EOF code point, validation error, return failure.
12928
1.26k
      if (pointer == input.end()) {
12929
21
        ada_log(
12930
21
            "parse_ipv6 If c is the EOF code point, validation error, return "
12931
21
            "failure");
12932
21
        return is_valid = false;
12933
21
      }
12934
1.26k
    }
12935
    // Otherwise, if c is not the EOF code point, validation error, return
12936
    // failure.
12937
481
    else if (pointer != input.end()) {
12938
136
      ada_log(
12939
136
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12940
136
          "error, return failure");
12941
136
      return is_valid = false;
12942
136
    }
12943
12944
    // Set address[pieceIndex] to value.
12945
1.59k
    address[piece_index] = value;
12946
12947
    // Increase pieceIndex by 1.
12948
1.59k
    piece_index++;
12949
1.59k
  }
12950
12951
  // If compress is non-null, then:
12952
573
  if (compress.has_value()) {
12953
    // Let swaps be pieceIndex - compress.
12954
474
    int swaps = piece_index - *compress;
12955
12956
    // Set pieceIndex to 7.
12957
474
    piece_index = 7;
12958
12959
    // While pieceIndex is not 0 and swaps is greater than 0,
12960
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
12961
    // decrease both pieceIndex and swaps by 1.
12962
1.25k
    while (piece_index != 0 && swaps > 0) {
12963
783
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12964
783
      piece_index--;
12965
783
      swaps--;
12966
783
    }
12967
474
  }
12968
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12969
  // return failure.
12970
99
  else if (piece_index != 8) {
12971
70
    ada_log(
12972
70
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12973
70
        "error, return failure");
12974
70
    return is_valid = false;
12975
70
  }
12976
503
  host = ada::serializers::ipv6(address);
12977
503
  ada_log("parse_ipv6 ", *host);
12978
503
  host_type = IPV6;
12979
503
  return true;
12980
573
}
12981
12982
template <bool has_state_override>
12983
52.0k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12984
52.0k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12985
52.0k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12986
  /**
12987
   * In the common case, we will immediately recognize a special scheme (e.g.,
12988
   *http, https), in which case, we can go really fast.
12989
   **/
12990
52.0k
  if (is_input_special) {  // fast path!!!
12991
38.6k
    if constexpr (has_state_override) {
12992
      // If url's scheme is not a special scheme and buffer is a special scheme,
12993
      // then return.
12994
3.38k
      if (is_special() != is_input_special) {
12995
0
        return false;
12996
0
      }
12997
12998
      // If url includes credentials or has a non-null port, and buffer is
12999
      // "file", then return.
13000
3.38k
      if ((has_credentials() || port.has_value()) &&
13001
140
          parsed_type == ada::scheme::type::FILE) {
13002
41
        return false;
13003
41
      }
13004
13005
      // If url's scheme is "file" and its host is an empty host, then return.
13006
      // An empty host is the empty string.
13007
3.34k
      if (type == ada::scheme::type::FILE && host.has_value() &&
13008
22
          host->empty()) {
13009
6
        return false;
13010
6
      }
13011
3.34k
    }
13012
13013
3.33k
    type = parsed_type;
13014
13015
38.6k
    if constexpr (has_state_override) {
13016
      // This is uncommon.
13017
3.38k
      uint16_t urls_scheme_port = get_special_port();
13018
13019
3.38k
      if (urls_scheme_port) {
13020
        // If url's port is url's scheme's default port, then set url's port to
13021
        // null.
13022
1.96k
        if (port.has_value() && *port == urls_scheme_port) {
13023
10
          port = std::nullopt;
13024
10
        }
13025
1.96k
      }
13026
3.38k
    }
13027
38.6k
  } else {  // slow path
13028
13.3k
    std::string _buffer(input);
13029
    // Next function is only valid if the input is ASCII and returns false
13030
    // otherwise, but it seems that we always have ascii content so we do not
13031
    // need to check the return value.
13032
    // bool is_ascii =
13033
13.3k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13034
13035
13.3k
    if constexpr (has_state_override) {
13036
      // The state-override validation errors below ("return" in the WHATWG URL
13037
      // parser) leave the URL unchanged. The setter contract is
13038
      // "true on success, false if the scheme is invalid" -- the fast path
13039
      // above already returns false here, so the slow path must agree.
13040
13041
      // If url's scheme is a special scheme and buffer is not a special scheme,
13042
      // then return. If url's scheme is not a special scheme and buffer is a
13043
      // special scheme, then return.
13044
3.69k
      if (is_special() != ada::scheme::is_special(_buffer)) {
13045
2.54k
        return false;
13046
2.54k
      }
13047
13048
      // If url includes credentials or has a non-null port, and buffer is
13049
      // "file", then return.
13050
1.15k
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
13051
17
        return false;
13052
17
      }
13053
13054
      // If url's scheme is "file" and its host is an empty host, then return.
13055
      // An empty host is the empty string.
13056
1.13k
      if (type == ada::scheme::type::FILE && host.has_value() &&
13057
23
          host->empty()) {
13058
6
        return false;
13059
6
      }
13060
1.13k
    }
13061
13062
1.12k
    set_scheme(std::move(_buffer));
13063
13064
13.3k
    if constexpr (has_state_override) {
13065
      // This is uncommon.
13066
3.69k
      uint16_t urls_scheme_port = get_special_port();
13067
13068
3.69k
      if (urls_scheme_port) {
13069
        // If url's port is url's scheme's default port, then set url's port to
13070
        // null.
13071
924
        if (port.has_value() && *port == urls_scheme_port) {
13072
10
          port = std::nullopt;
13073
10
        }
13074
924
      }
13075
3.69k
    }
13076
13.3k
  }
13077
13078
0
  return true;
13079
52.0k
}
bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12983
7.08k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12984
7.08k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12985
7.08k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12986
  /**
12987
   * In the common case, we will immediately recognize a special scheme (e.g.,
12988
   *http, https), in which case, we can go really fast.
12989
   **/
12990
7.08k
  if (is_input_special) {  // fast path!!!
12991
3.38k
    if constexpr (has_state_override) {
12992
      // If url's scheme is not a special scheme and buffer is a special scheme,
12993
      // then return.
12994
3.38k
      if (is_special() != is_input_special) {
12995
0
        return false;
12996
0
      }
12997
12998
      // If url includes credentials or has a non-null port, and buffer is
12999
      // "file", then return.
13000
3.38k
      if ((has_credentials() || port.has_value()) &&
13001
140
          parsed_type == ada::scheme::type::FILE) {
13002
41
        return false;
13003
41
      }
13004
13005
      // If url's scheme is "file" and its host is an empty host, then return.
13006
      // An empty host is the empty string.
13007
3.34k
      if (type == ada::scheme::type::FILE && host.has_value() &&
13008
22
          host->empty()) {
13009
6
        return false;
13010
6
      }
13011
3.34k
    }
13012
13013
3.33k
    type = parsed_type;
13014
13015
3.38k
    if constexpr (has_state_override) {
13016
      // This is uncommon.
13017
3.38k
      uint16_t urls_scheme_port = get_special_port();
13018
13019
3.38k
      if (urls_scheme_port) {
13020
        // If url's port is url's scheme's default port, then set url's port to
13021
        // null.
13022
1.96k
        if (port.has_value() && *port == urls_scheme_port) {
13023
10
          port = std::nullopt;
13024
10
        }
13025
1.96k
      }
13026
3.38k
    }
13027
3.69k
  } else {  // slow path
13028
3.69k
    std::string _buffer(input);
13029
    // Next function is only valid if the input is ASCII and returns false
13030
    // otherwise, but it seems that we always have ascii content so we do not
13031
    // need to check the return value.
13032
    // bool is_ascii =
13033
3.69k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13034
13035
3.69k
    if constexpr (has_state_override) {
13036
      // The state-override validation errors below ("return" in the WHATWG URL
13037
      // parser) leave the URL unchanged. The setter contract is
13038
      // "true on success, false if the scheme is invalid" -- the fast path
13039
      // above already returns false here, so the slow path must agree.
13040
13041
      // If url's scheme is a special scheme and buffer is not a special scheme,
13042
      // then return. If url's scheme is not a special scheme and buffer is a
13043
      // special scheme, then return.
13044
3.69k
      if (is_special() != ada::scheme::is_special(_buffer)) {
13045
2.54k
        return false;
13046
2.54k
      }
13047
13048
      // If url includes credentials or has a non-null port, and buffer is
13049
      // "file", then return.
13050
1.15k
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
13051
17
        return false;
13052
17
      }
13053
13054
      // If url's scheme is "file" and its host is an empty host, then return.
13055
      // An empty host is the empty string.
13056
1.13k
      if (type == ada::scheme::type::FILE && host.has_value() &&
13057
23
          host->empty()) {
13058
6
        return false;
13059
6
      }
13060
1.13k
    }
13061
13062
1.12k
    set_scheme(std::move(_buffer));
13063
13064
3.69k
    if constexpr (has_state_override) {
13065
      // This is uncommon.
13066
3.69k
      uint16_t urls_scheme_port = get_special_port();
13067
13068
3.69k
      if (urls_scheme_port) {
13069
        // If url's port is url's scheme's default port, then set url's port to
13070
        // null.
13071
924
        if (port.has_value() && *port == urls_scheme_port) {
13072
10
          port = std::nullopt;
13073
10
        }
13074
924
      }
13075
3.69k
    }
13076
3.69k
  }
13077
13078
0
  return true;
13079
7.08k
}
bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
12983
44.9k
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12984
44.9k
  auto parsed_type = ada::scheme::get_scheme_type(input);
12985
44.9k
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
12986
  /**
12987
   * In the common case, we will immediately recognize a special scheme (e.g.,
12988
   *http, https), in which case, we can go really fast.
12989
   **/
12990
44.9k
  if (is_input_special) {  // fast path!!!
12991
    if constexpr (has_state_override) {
12992
      // If url's scheme is not a special scheme and buffer is a special scheme,
12993
      // then return.
12994
      if (is_special() != is_input_special) {
12995
        return false;
12996
      }
12997
12998
      // If url includes credentials or has a non-null port, and buffer is
12999
      // "file", then return.
13000
      if ((has_credentials() || port.has_value()) &&
13001
          parsed_type == ada::scheme::type::FILE) {
13002
        return false;
13003
      }
13004
13005
      // If url's scheme is "file" and its host is an empty host, then return.
13006
      // An empty host is the empty string.
13007
      if (type == ada::scheme::type::FILE && host.has_value() &&
13008
          host->empty()) {
13009
        return false;
13010
      }
13011
    }
13012
13013
35.2k
    type = parsed_type;
13014
13015
    if constexpr (has_state_override) {
13016
      // This is uncommon.
13017
      uint16_t urls_scheme_port = get_special_port();
13018
13019
      if (urls_scheme_port) {
13020
        // If url's port is url's scheme's default port, then set url's port to
13021
        // null.
13022
        if (port.has_value() && *port == urls_scheme_port) {
13023
          port = std::nullopt;
13024
        }
13025
      }
13026
    }
13027
35.2k
  } else {  // slow path
13028
9.68k
    std::string _buffer(input);
13029
    // Next function is only valid if the input is ASCII and returns false
13030
    // otherwise, but it seems that we always have ascii content so we do not
13031
    // need to check the return value.
13032
    // bool is_ascii =
13033
9.68k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13034
13035
    if constexpr (has_state_override) {
13036
      // The state-override validation errors below ("return" in the WHATWG URL
13037
      // parser) leave the URL unchanged. The setter contract is
13038
      // "true on success, false if the scheme is invalid" -- the fast path
13039
      // above already returns false here, so the slow path must agree.
13040
13041
      // If url's scheme is a special scheme and buffer is not a special scheme,
13042
      // then return. If url's scheme is not a special scheme and buffer is a
13043
      // special scheme, then return.
13044
      if (is_special() != ada::scheme::is_special(_buffer)) {
13045
        return false;
13046
      }
13047
13048
      // If url includes credentials or has a non-null port, and buffer is
13049
      // "file", then return.
13050
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
13051
        return false;
13052
      }
13053
13054
      // If url's scheme is "file" and its host is an empty host, then return.
13055
      // An empty host is the empty string.
13056
      if (type == ada::scheme::type::FILE && host.has_value() &&
13057
          host->empty()) {
13058
        return false;
13059
      }
13060
    }
13061
13062
9.68k
    set_scheme(std::move(_buffer));
13063
13064
    if constexpr (has_state_override) {
13065
      // This is uncommon.
13066
      uint16_t urls_scheme_port = get_special_port();
13067
13068
      if (urls_scheme_port) {
13069
        // If url's port is url's scheme's default port, then set url's port to
13070
        // null.
13071
        if (port.has_value() && *port == urls_scheme_port) {
13072
          port = std::nullopt;
13073
        }
13074
      }
13075
    }
13076
9.68k
  }
13077
13078
44.9k
  return true;
13079
44.9k
}
13080
13081
57.7k
ada_really_inline bool url::parse_host(std::string_view input) {
13082
57.7k
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
13083
57.7k
  if (input.empty()) {
13084
31
    return is_valid = false;
13085
31
  }  // technically unnecessary.
13086
  // If input starts with U+005B ([), then:
13087
57.6k
  if (input[0] == '[') {
13088
    // If input does not end with U+005D (]), validation error, return failure.
13089
1.75k
    if (input.back() != ']') {
13090
662
      return is_valid = false;
13091
662
    }
13092
1.09k
    ada_log("parse_host ipv6");
13093
13094
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
13095
    // trailing U+005D (]) removed.
13096
1.09k
    input.remove_prefix(1);
13097
1.09k
    input.remove_suffix(1);
13098
1.09k
    return parse_ipv6(input);
13099
1.75k
  }
13100
13101
  // If isNotSpecial is true, then return the result of opaque-host parsing
13102
  // input.
13103
55.9k
  if (!is_special()) {
13104
701
    return parse_opaque_host(input);
13105
701
  }
13106
13107
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
13108
55.2k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
13109
55.2k
  if (fast_result < checkers::ipv4_fast_fail) {
13110
    // Fast path succeeded - input is pure decimal IPv4
13111
277
    if (!input.empty() && input.back() == '.') {
13112
115
      host = input.substr(0, input.size() - 1);
13113
162
    } else {
13114
162
      host = input;
13115
162
    }
13116
277
    host_type = IPV4;
13117
277
    is_valid = true;
13118
277
    ada_log("parse_host fast path decimal ipv4");
13119
277
    return true;
13120
277
  }
13121
  // Let domain be the result of running UTF-8 decode without BOM on the
13122
  // percent-decoding of input. Let asciiDomain be the result of running domain
13123
  // to ASCII with domain and false. The most common case is an ASCII input, in
13124
  // which case we do not need to call the expensive 'to_ascii' if a few
13125
  // conditions are met: no '%' and no 'xn-' subsequence.
13126
54.9k
  std::string buffer = std::string(input);
13127
  // This next function checks that the result is ascii, but we are going to
13128
  // to check anyhow with is_forbidden.
13129
  // bool is_ascii =
13130
54.9k
  unicode::to_lower_ascii(buffer.data(), buffer.size());
13131
54.9k
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
13132
54.9k
      buffer.data(), buffer.size());
13133
54.9k
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
13134
    // fast path
13135
42.5k
    host = std::move(buffer);
13136
13137
    // Check for other IPv4 formats (hex, octal, etc.)
13138
42.5k
    if (checkers::is_ipv4(host.value())) {
13139
4.45k
      ada_log("parse_host fast path ipv4");
13140
4.45k
      return parse_ipv4(host.value());
13141
4.45k
    }
13142
38.1k
    ada_log("parse_host fast path ", *host);
13143
38.1k
    is_valid = true;
13144
38.1k
    return true;
13145
42.5k
  }
13146
12.3k
  ada_log("parse_host calling to_ascii");
13147
12.3k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13148
12.3k
  if (!is_valid || !host.has_value()) {
13149
7.29k
    ada_log("parse_host to_ascii returns false");
13150
7.29k
    return is_valid = false;
13151
7.29k
  }
13152
5.07k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
13153
5.07k
          " bytes]");
13154
13155
5.07k
  if (std::any_of(host->begin(), host->end(),
13156
5.07k
                  ada::unicode::is_forbidden_domain_code_point)) {
13157
0
    host = std::nullopt;
13158
0
    return is_valid = false;
13159
0
  }
13160
13161
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
13162
  // asciiDomain.
13163
5.07k
  if (checkers::is_ipv4(*host)) {
13164
729
    ada_log("parse_host got ipv4 ", *host);
13165
729
    return parse_ipv4(*host);
13166
729
  }
13167
13168
4.34k
  return true;
13169
5.07k
}
13170
13171
15.2k
ada_really_inline void url::parse_path(std::string_view input) {
13172
15.2k
  ada_log("parse_path ", input);
13173
15.2k
  std::string tmp_buffer;
13174
15.2k
  std::string_view internal_input;
13175
15.2k
  if (unicode::has_tabs_or_newline(input)) {
13176
412
    tmp_buffer = input;
13177
    // Optimization opportunity: Instead of copying and then pruning, we could
13178
    // just directly build the string from user_input.
13179
412
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13180
412
    internal_input = tmp_buffer;
13181
14.8k
  } else {
13182
14.8k
    internal_input = input;
13183
14.8k
  }
13184
13185
  // If url is special, then:
13186
15.2k
  if (is_special()) {
13187
15.2k
    if (internal_input.empty()) {
13188
1.64k
      path = "/";
13189
13.6k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13190
2.08k
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
13191
11.5k
    } else {
13192
11.5k
      helpers::parse_prepared_path(internal_input, type, path);
13193
11.5k
    }
13194
15.2k
  } else if (!internal_input.empty()) {
13195
0
    if (internal_input[0] == '/') {
13196
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
13197
0
    } else {
13198
0
      helpers::parse_prepared_path(internal_input, type, path);
13199
0
    }
13200
0
  } else {
13201
0
    if (!host.has_value()) {
13202
0
      path = "/";
13203
0
    }
13204
0
  }
13205
15.2k
}
13206
13207
20.5k
[[nodiscard]] std::string url::to_string() const {
13208
20.5k
  if (!is_valid) {
13209
3.05k
    return "null";
13210
3.05k
  }
13211
17.4k
  std::string answer;
13212
17.4k
  auto back = std::back_insert_iterator(answer);
13213
17.4k
  answer.append("{\n");
13214
17.4k
  answer.append("\t\"protocol\":\"");
13215
17.4k
  helpers::encode_json(get_protocol(), back);
13216
17.4k
  answer.append("\",\n");
13217
17.4k
  if (has_credentials()) {
13218
9.83k
    answer.append("\t\"username\":\"");
13219
9.83k
    helpers::encode_json(username, back);
13220
9.83k
    answer.append("\",\n");
13221
9.83k
    answer.append("\t\"password\":\"");
13222
9.83k
    helpers::encode_json(password, back);
13223
9.83k
    answer.append("\",\n");
13224
9.83k
  }
13225
17.4k
  if (host.has_value()) {
13226
15.3k
    answer.append("\t\"host\":\"");
13227
15.3k
    helpers::encode_json(host.value(), back);
13228
15.3k
    answer.append("\",\n");
13229
15.3k
  }
13230
17.4k
  if (port.has_value()) {
13231
1.82k
    answer.append("\t\"port\":\"");
13232
1.82k
    answer.append(std::to_string(port.value()));
13233
1.82k
    answer.append("\",\n");
13234
1.82k
  }
13235
17.4k
  answer.append("\t\"path\":\"");
13236
17.4k
  helpers::encode_json(path, back);
13237
17.4k
  answer.append("\",\n");
13238
17.4k
  answer.append("\t\"opaque path\":");
13239
17.4k
  answer.append((has_opaque_path ? "true" : "false"));
13240
17.4k
  if (has_search()) {
13241
9.83k
    answer.append(",\n");
13242
9.83k
    answer.append("\t\"query\":\"");
13243
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
13244
9.83k
    helpers::encode_json(query.value(), back);
13245
9.83k
    answer.append("\"");
13246
9.83k
  }
13247
17.4k
  if (hash.has_value()) {
13248
9.79k
    answer.append(",\n");
13249
9.79k
    answer.append("\t\"hash\":\"");
13250
9.79k
    helpers::encode_json(hash.value(), back);
13251
9.79k
    answer.append("\"");
13252
9.79k
  }
13253
17.4k
  answer.append("\n}");
13254
17.4k
  return answer;
13255
20.5k
}
13256
13257
20.5k
[[nodiscard]] bool url::has_valid_domain() const noexcept {
13258
20.5k
  if (!host.has_value()) {
13259
2.12k
    return false;
13260
2.12k
  }
13261
18.4k
  return checkers::verify_dns_length(*host);
13262
20.5k
}
13263
13264
27.4k
[[nodiscard]] std::string url::get_origin() const {
13265
27.4k
  if (is_special()) {
13266
    // Return a new opaque origin.
13267
22.3k
    if (type == scheme::FILE) {
13268
3.65k
      return "null";
13269
3.65k
    }
13270
18.6k
    return ada::helpers::concat(get_protocol(), "//", get_host());
13271
22.3k
  }
13272
13273
5.07k
  if (non_special_scheme == "blob") {
13274
1.43k
    if (!path.empty()) {
13275
1.40k
      auto result = ada::parse<ada::url>(path);
13276
1.40k
      if (result &&
13277
384
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
13278
        // If pathURL's scheme is not "http" and not "https", then return a
13279
        // new opaque origin.
13280
48
        return ada::helpers::concat(result->get_protocol(), "//",
13281
48
                                    result->get_host());
13282
48
      }
13283
1.40k
    }
13284
1.43k
  }
13285
13286
  // Return a new opaque origin.
13287
5.02k
  return "null";
13288
5.07k
}
13289
13290
160k
[[nodiscard]] std::string url::get_protocol() const {
13291
160k
  if (is_special()) {
13292
133k
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
13293
133k
  }
13294
  // We only move the 'scheme' if it is non-special.
13295
27.1k
  return helpers::concat(non_special_scheme, ":");
13296
160k
}
13297
13298
43.3k
[[nodiscard]] std::string url::get_host() const {
13299
  // If url's host is null, then return the empty string.
13300
  // If url's port is null, return url's host, serialized.
13301
  // Return url's host, serialized, followed by U+003A (:) and url's port,
13302
  // serialized.
13303
43.3k
  if (!host.has_value()) {
13304
3.44k
    return "";
13305
3.44k
  }
13306
39.9k
  if (port.has_value()) {
13307
4.07k
    return host.value() + ":" + get_port();
13308
4.07k
  }
13309
35.8k
  return host.value();
13310
39.9k
}
13311
13312
24.6k
[[nodiscard]] std::string url::get_hostname() const {
13313
24.6k
  return host.value_or("");
13314
24.6k
}
13315
13316
50.4k
[[nodiscard]] std::string url::get_search() const {
13317
  // If this's URL's query is either null or the empty string, then return the
13318
  // empty string. Return U+003F (?), followed by this's URL's query.
13319
50.4k
  return (!query.has_value() || (query->empty())) ? "" : "?" + query.value();
13320
50.4k
}
13321
13322
24.6k
[[nodiscard]] const std::string& url::get_username() const noexcept {
13323
24.6k
  return username;
13324
24.6k
}
13325
13326
50.2k
[[nodiscard]] const std::string& url::get_password() const noexcept {
13327
50.2k
  return password;
13328
50.2k
}
13329
13330
56.7k
[[nodiscard]] std::string url::get_port() const {
13331
56.7k
  return port.has_value() ? std::to_string(port.value()) : "";
13332
56.7k
}
13333
13334
24.6k
[[nodiscard]] std::string url::get_hash() const {
13335
  // If this's URL's fragment is either null or the empty string, then return
13336
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
13337
24.6k
  return (!hash.has_value() || (hash->empty())) ? "" : "#" + hash.value();
13338
24.6k
}
13339
13340
template <bool override_hostname>
13341
32.4k
bool url::set_host_or_hostname(const std::string_view input) {
13342
32.4k
  if (has_opaque_path) {
13343
0
    return false;
13344
0
  }
13345
13346
32.4k
  url saved_url(*this);
13347
13348
32.4k
  std::optional<std::string> previous_host = host;
13349
32.4k
  std::optional<uint16_t> previous_port = port;
13350
13351
32.4k
  size_t host_end_pos = input.find('#');
13352
32.4k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13353
32.4k
                                      ? host_end_pos
13354
32.4k
                                      : input.size());
13355
32.4k
  helpers::remove_ascii_tab_or_newline(_host);
13356
32.4k
  std::string_view new_host(_host);
13357
13358
32.4k
  auto check_url_size = [&]() -> bool {
13359
12.4k
    if (get_href_size() > ada::get_max_input_length()) {
13360
0
      *this = std::move(saved_url);
13361
0
      return false;
13362
0
    }
13363
12.4k
    return true;
13364
12.4k
  };
ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Line
Count
Source
13358
8.74k
  auto check_url_size = [&]() -> bool {
13359
8.74k
    if (get_href_size() > ada::get_max_input_length()) {
13360
0
      *this = std::move(saved_url);
13361
0
      return false;
13362
0
    }
13363
8.74k
    return true;
13364
8.74k
  };
ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Line
Count
Source
13358
3.74k
  auto check_url_size = [&]() -> bool {
13359
3.74k
    if (get_href_size() > ada::get_max_input_length()) {
13360
0
      *this = std::move(saved_url);
13361
0
      return false;
13362
0
    }
13363
3.74k
    return true;
13364
3.74k
  };
13365
13366
  // If url's scheme is "file", then set state to file host state, instead of
13367
  // host state.
13368
32.4k
  if (type != ada::scheme::type::FILE) {
13369
29.5k
    std::string_view host_view(_host.data(), _host.length());
13370
29.5k
    auto [location, found_colon] =
13371
29.5k
        helpers::get_host_delimiter_location(is_special(), host_view);
13372
13373
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13374
    // Note: the 'found_colon' value is true if and only if a colon was
13375
    // encountered while not inside brackets.
13376
29.5k
    if (found_colon) {
13377
      // If buffer is the empty string, host-missing validation error, return
13378
      // failure.
13379
11.2k
      std::string_view buffer = host_view.substr(0, location);
13380
11.2k
      if (buffer.empty()) {
13381
216
        return false;
13382
216
      }
13383
13384
      // If state override is given and state override is hostname state, then
13385
      // return failure.
13386
11.0k
      if constexpr (override_hostname) {
13387
5.11k
        return false;
13388
5.11k
      }
13389
13390
      // Let host be the result of host parsing buffer with url is not special.
13391
0
      bool succeeded = parse_host(buffer);
13392
11.0k
      if (!succeeded) {
13393
704
        host = std::move(previous_host);
13394
704
        update_base_port(previous_port);
13395
704
        return false;
13396
704
      }
13397
13398
      // Set url's host to host, buffer to the empty string, and state to port
13399
      // state.
13400
10.3k
      std::string_view port_buffer = new_host.substr(location + 1);
13401
10.3k
      if (!port_buffer.empty()) {
13402
4.59k
        set_port(port_buffer);
13403
4.59k
      }
13404
10.3k
      return check_url_size();
13405
11.0k
    }
13406
    // Otherwise, if one of the following is true:
13407
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13408
    // - url is special and c is U+005C (\)
13409
18.2k
    else {
13410
      // If url is special and host_view is the empty string, host-missing
13411
      // validation error, return failure.
13412
18.2k
      if (host_view.empty() && is_special()) {
13413
6.61k
        return false;
13414
6.61k
      }
13415
13416
      // Otherwise, if state override is given, host_view is the empty string,
13417
      // and either url includes credentials or url's port is non-null, then
13418
      // return failure.
13419
11.6k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
13420
0
        return false;
13421
0
      }
13422
13423
      // Let host be the result of host parsing host_view with url is not
13424
      // special.
13425
11.6k
      if (host_view.empty() && !is_special()) {
13426
0
        host = "";
13427
0
        return check_url_size();
13428
0
      }
13429
13430
11.6k
      bool succeeded = parse_host(host_view);
13431
11.6k
      if (!succeeded) {
13432
5.30k
        host = std::move(previous_host);
13433
5.30k
        update_base_port(previous_port);
13434
5.30k
        return false;
13435
5.30k
      }
13436
6.32k
      return check_url_size();
13437
11.6k
    }
13438
29.5k
  }
13439
13440
2.95k
  size_t location = new_host.find_first_of("/\\?");
13441
2.95k
  if (location != std::string_view::npos) {
13442
1.73k
    new_host.remove_suffix(new_host.length() - location);
13443
1.73k
  }
13444
13445
2.95k
  if (new_host.empty()) {
13446
    // Set url's host to the empty string.
13447
92
    host = "";
13448
2.85k
  } else {
13449
    // Let host be the result of host parsing buffer with url is not special.
13450
2.85k
    if (!parse_host(new_host)) {
13451
2.03k
      host = std::move(previous_host);
13452
2.03k
      update_base_port(previous_port);
13453
2.03k
      return false;
13454
2.03k
    }
13455
13456
    // If host is "localhost", then set host to the empty string.
13457
821
    if (host == "localhost") {
13458
24
      host = "";
13459
24
    }
13460
821
  }
13461
913
  return check_url_size();
13462
2.95k
}
bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13341
16.4k
bool url::set_host_or_hostname(const std::string_view input) {
13342
16.4k
  if (has_opaque_path) {
13343
0
    return false;
13344
0
  }
13345
13346
16.4k
  url saved_url(*this);
13347
13348
16.4k
  std::optional<std::string> previous_host = host;
13349
16.4k
  std::optional<uint16_t> previous_port = port;
13350
13351
16.4k
  size_t host_end_pos = input.find('#');
13352
16.4k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13353
16.4k
                                      ? host_end_pos
13354
16.4k
                                      : input.size());
13355
16.4k
  helpers::remove_ascii_tab_or_newline(_host);
13356
16.4k
  std::string_view new_host(_host);
13357
13358
16.4k
  auto check_url_size = [&]() -> bool {
13359
16.4k
    if (get_href_size() > ada::get_max_input_length()) {
13360
16.4k
      *this = std::move(saved_url);
13361
16.4k
      return false;
13362
16.4k
    }
13363
16.4k
    return true;
13364
16.4k
  };
13365
13366
  // If url's scheme is "file", then set state to file host state, instead of
13367
  // host state.
13368
16.4k
  if (type != ada::scheme::type::FILE) {
13369
15.0k
    std::string_view host_view(_host.data(), _host.length());
13370
15.0k
    auto [location, found_colon] =
13371
15.0k
        helpers::get_host_delimiter_location(is_special(), host_view);
13372
13373
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13374
    // Note: the 'found_colon' value is true if and only if a colon was
13375
    // encountered while not inside brackets.
13376
15.0k
    if (found_colon) {
13377
      // If buffer is the empty string, host-missing validation error, return
13378
      // failure.
13379
6.07k
      std::string_view buffer = host_view.substr(0, location);
13380
6.07k
      if (buffer.empty()) {
13381
109
        return false;
13382
109
      }
13383
13384
      // If state override is given and state override is hostname state, then
13385
      // return failure.
13386
      if constexpr (override_hostname) {
13387
        return false;
13388
      }
13389
13390
      // Let host be the result of host parsing buffer with url is not special.
13391
5.96k
      bool succeeded = parse_host(buffer);
13392
5.96k
      if (!succeeded) {
13393
704
        host = std::move(previous_host);
13394
704
        update_base_port(previous_port);
13395
704
        return false;
13396
704
      }
13397
13398
      // Set url's host to host, buffer to the empty string, and state to port
13399
      // state.
13400
5.25k
      std::string_view port_buffer = new_host.substr(location + 1);
13401
5.25k
      if (!port_buffer.empty()) {
13402
4.59k
        set_port(port_buffer);
13403
4.59k
      }
13404
5.25k
      return check_url_size();
13405
5.96k
    }
13406
    // Otherwise, if one of the following is true:
13407
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13408
    // - url is special and c is U+005C (\)
13409
8.94k
    else {
13410
      // If url is special and host_view is the empty string, host-missing
13411
      // validation error, return failure.
13412
8.94k
      if (host_view.empty() && is_special()) {
13413
3.28k
        return false;
13414
3.28k
      }
13415
13416
      // Otherwise, if state override is given, host_view is the empty string,
13417
      // and either url includes credentials or url's port is non-null, then
13418
      // return failure.
13419
5.65k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
13420
0
        return false;
13421
0
      }
13422
13423
      // Let host be the result of host parsing host_view with url is not
13424
      // special.
13425
5.65k
      if (host_view.empty() && !is_special()) {
13426
0
        host = "";
13427
0
        return check_url_size();
13428
0
      }
13429
13430
5.65k
      bool succeeded = parse_host(host_view);
13431
5.65k
      if (!succeeded) {
13432
2.59k
        host = std::move(previous_host);
13433
2.59k
        update_base_port(previous_port);
13434
2.59k
        return false;
13435
2.59k
      }
13436
3.06k
      return check_url_size();
13437
5.65k
    }
13438
15.0k
  }
13439
13440
1.45k
  size_t location = new_host.find_first_of("/\\?");
13441
1.45k
  if (location != std::string_view::npos) {
13442
851
    new_host.remove_suffix(new_host.length() - location);
13443
851
  }
13444
13445
1.45k
  if (new_host.empty()) {
13446
    // Set url's host to the empty string.
13447
37
    host = "";
13448
1.41k
  } else {
13449
    // Let host be the result of host parsing buffer with url is not special.
13450
1.41k
    if (!parse_host(new_host)) {
13451
1.02k
      host = std::move(previous_host);
13452
1.02k
      update_base_port(previous_port);
13453
1.02k
      return false;
13454
1.02k
    }
13455
13456
    // If host is "localhost", then set host to the empty string.
13457
390
    if (host == "localhost") {
13458
13
      host = "";
13459
13
    }
13460
390
  }
13461
427
  return check_url_size();
13462
1.45k
}
bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13341
16.0k
bool url::set_host_or_hostname(const std::string_view input) {
13342
16.0k
  if (has_opaque_path) {
13343
0
    return false;
13344
0
  }
13345
13346
16.0k
  url saved_url(*this);
13347
13348
16.0k
  std::optional<std::string> previous_host = host;
13349
16.0k
  std::optional<uint16_t> previous_port = port;
13350
13351
16.0k
  size_t host_end_pos = input.find('#');
13352
16.0k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13353
16.0k
                                      ? host_end_pos
13354
16.0k
                                      : input.size());
13355
16.0k
  helpers::remove_ascii_tab_or_newline(_host);
13356
16.0k
  std::string_view new_host(_host);
13357
13358
16.0k
  auto check_url_size = [&]() -> bool {
13359
16.0k
    if (get_href_size() > ada::get_max_input_length()) {
13360
16.0k
      *this = std::move(saved_url);
13361
16.0k
      return false;
13362
16.0k
    }
13363
16.0k
    return true;
13364
16.0k
  };
13365
13366
  // If url's scheme is "file", then set state to file host state, instead of
13367
  // host state.
13368
16.0k
  if (type != ada::scheme::type::FILE) {
13369
14.5k
    std::string_view host_view(_host.data(), _host.length());
13370
14.5k
    auto [location, found_colon] =
13371
14.5k
        helpers::get_host_delimiter_location(is_special(), host_view);
13372
13373
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13374
    // Note: the 'found_colon' value is true if and only if a colon was
13375
    // encountered while not inside brackets.
13376
14.5k
    if (found_colon) {
13377
      // If buffer is the empty string, host-missing validation error, return
13378
      // failure.
13379
5.21k
      std::string_view buffer = host_view.substr(0, location);
13380
5.21k
      if (buffer.empty()) {
13381
107
        return false;
13382
107
      }
13383
13384
      // If state override is given and state override is hostname state, then
13385
      // return failure.
13386
5.11k
      if constexpr (override_hostname) {
13387
5.11k
        return false;
13388
5.11k
      }
13389
13390
      // Let host be the result of host parsing buffer with url is not special.
13391
0
      bool succeeded = parse_host(buffer);
13392
5.11k
      if (!succeeded) {
13393
0
        host = std::move(previous_host);
13394
0
        update_base_port(previous_port);
13395
0
        return false;
13396
0
      }
13397
13398
      // Set url's host to host, buffer to the empty string, and state to port
13399
      // state.
13400
5.11k
      std::string_view port_buffer = new_host.substr(location + 1);
13401
5.11k
      if (!port_buffer.empty()) {
13402
0
        set_port(port_buffer);
13403
0
      }
13404
5.11k
      return check_url_size();
13405
5.11k
    }
13406
    // Otherwise, if one of the following is true:
13407
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13408
    // - url is special and c is U+005C (\)
13409
9.29k
    else {
13410
      // If url is special and host_view is the empty string, host-missing
13411
      // validation error, return failure.
13412
9.29k
      if (host_view.empty() && is_special()) {
13413
3.32k
        return false;
13414
3.32k
      }
13415
13416
      // Otherwise, if state override is given, host_view is the empty string,
13417
      // and either url includes credentials or url's port is non-null, then
13418
      // return failure.
13419
5.96k
      if (host_view.empty() && (has_credentials() || port.has_value())) {
13420
0
        return false;
13421
0
      }
13422
13423
      // Let host be the result of host parsing host_view with url is not
13424
      // special.
13425
5.96k
      if (host_view.empty() && !is_special()) {
13426
0
        host = "";
13427
0
        return check_url_size();
13428
0
      }
13429
13430
5.96k
      bool succeeded = parse_host(host_view);
13431
5.96k
      if (!succeeded) {
13432
2.70k
        host = std::move(previous_host);
13433
2.70k
        update_base_port(previous_port);
13434
2.70k
        return false;
13435
2.70k
      }
13436
3.26k
      return check_url_size();
13437
5.96k
    }
13438
14.5k
  }
13439
13440
1.49k
  size_t location = new_host.find_first_of("/\\?");
13441
1.49k
  if (location != std::string_view::npos) {
13442
883
    new_host.remove_suffix(new_host.length() - location);
13443
883
  }
13444
13445
1.49k
  if (new_host.empty()) {
13446
    // Set url's host to the empty string.
13447
55
    host = "";
13448
1.44k
  } else {
13449
    // Let host be the result of host parsing buffer with url is not special.
13450
1.44k
    if (!parse_host(new_host)) {
13451
1.01k
      host = std::move(previous_host);
13452
1.01k
      update_base_port(previous_port);
13453
1.01k
      return false;
13454
1.01k
    }
13455
13456
    // If host is "localhost", then set host to the empty string.
13457
431
    if (host == "localhost") {
13458
11
      host = "";
13459
11
    }
13460
431
  }
13461
486
  return check_url_size();
13462
1.49k
}
13463
13464
16.4k
bool url::set_host(const std::string_view input) {
13465
16.4k
  return set_host_or_hostname<false>(input);
13466
16.4k
}
13467
13468
16.0k
bool url::set_hostname(const std::string_view input) {
13469
16.0k
  return set_host_or_hostname<true>(input);
13470
16.0k
}
13471
13472
14.9k
bool url::set_username(const std::string_view input) {
13473
14.9k
  if (cannot_have_credentials_or_port()) {
13474
855
    return false;
13475
855
  }
13476
14.0k
  auto previous_username = std::move(username);
13477
14.0k
  username = ada::unicode::percent_encode(
13478
14.0k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13479
14.0k
  if (get_href_size() > ada::get_max_input_length()) {
13480
0
    username = std::move(previous_username);
13481
0
    return false;
13482
0
  }
13483
14.0k
  return true;
13484
14.0k
}
13485
13486
15.0k
bool url::set_password(const std::string_view input) {
13487
15.0k
  if (cannot_have_credentials_or_port()) {
13488
859
    return false;
13489
859
  }
13490
14.2k
  auto previous_password = std::move(password);
13491
14.2k
  password = ada::unicode::percent_encode(
13492
14.2k
      input, character_sets::USERINFO_PERCENT_ENCODE);
13493
14.2k
  if (get_href_size() > ada::get_max_input_length()) {
13494
0
    password = std::move(previous_password);
13495
0
    return false;
13496
0
  }
13497
14.2k
  return true;
13498
14.2k
}
13499
13500
19.3k
bool url::set_port(const std::string_view input) {
13501
19.3k
  if (cannot_have_credentials_or_port()) {
13502
853
    return false;
13503
853
  }
13504
13505
18.5k
  if (input.empty()) {
13506
2.24k
    port = std::nullopt;
13507
2.24k
    return true;
13508
2.24k
  }
13509
13510
16.2k
  std::string trimmed(input);
13511
16.2k
  helpers::remove_ascii_tab_or_newline(trimmed);
13512
13513
16.2k
  if (trimmed.empty()) {
13514
100
    return true;
13515
100
  }
13516
13517
  // Input should not start with a non-digit character.
13518
16.1k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13519
13.6k
    return false;
13520
13.6k
  }
13521
13522
  // Find the first non-digit character to determine the length of digits
13523
2.48k
  auto first_non_digit =
13524
2.48k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13525
2.48k
  std::string_view digits_to_parse =
13526
2.48k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13527
13528
  // Revert changes if parse_port fails.
13529
2.48k
  std::optional<uint16_t> previous_port = port;
13530
2.48k
  parse_port(digits_to_parse);
13531
2.48k
  if (is_valid) {
13532
1.95k
    if (get_href_size() > ada::get_max_input_length()) {
13533
0
      port = std::move(previous_port);
13534
0
      return false;
13535
0
    }
13536
1.95k
    return true;
13537
1.95k
  }
13538
530
  port = std::move(previous_port);
13539
530
  is_valid = true;
13540
530
  return false;
13541
2.48k
}
13542
13543
14.0k
void url::set_hash(const std::string_view input) {
13544
14.0k
  if (input.empty()) {
13545
1.53k
    hash = std::nullopt;
13546
1.53k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13547
1.53k
    return;
13548
1.53k
  }
13549
13550
12.5k
  std::string new_value;
13551
12.5k
  new_value = input[0] == '#' ? input.substr(1) : input;
13552
12.5k
  helpers::remove_ascii_tab_or_newline(new_value);
13553
12.5k
  auto previous_hash = std::move(hash);
13554
12.5k
  hash = unicode::percent_encode(new_value,
13555
12.5k
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13556
12.5k
  if (get_href_size() > ada::get_max_input_length()) {
13557
0
    hash = std::move(previous_hash);
13558
0
  }
13559
12.5k
}
13560
13561
14.2k
void url::set_search(const std::string_view input) {
13562
14.2k
  if (input.empty()) {
13563
1.62k
    query = std::nullopt;
13564
1.62k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13565
1.62k
    return;
13566
1.62k
  }
13567
13568
12.6k
  std::string new_value;
13569
12.6k
  new_value = input[0] == '?' ? input.substr(1) : input;
13570
12.6k
  helpers::remove_ascii_tab_or_newline(new_value);
13571
13572
12.6k
  auto query_percent_encode_set =
13573
12.6k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13574
12.6k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13575
13576
12.6k
  auto previous_query = std::move(query);
13577
12.6k
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13578
12.6k
  if (get_href_size() > ada::get_max_input_length()) {
13579
0
    query = std::move(previous_query);
13580
0
  }
13581
12.6k
}
13582
13583
15.2k
bool url::set_pathname(const std::string_view input) {
13584
15.2k
  if (has_opaque_path) {
13585
0
    return false;
13586
0
  }
13587
15.2k
  auto previous_path = std::move(path);
13588
15.2k
  path.clear();
13589
15.2k
  parse_path(input);
13590
15.2k
  if (get_href_size() > ada::get_max_input_length()) {
13591
0
    path = std::move(previous_path);
13592
0
    return false;
13593
0
  }
13594
15.2k
  return true;
13595
15.2k
}
13596
13597
32.7k
bool url::set_protocol(const std::string_view input) {
13598
32.7k
  std::string view(input);
13599
32.7k
  helpers::remove_ascii_tab_or_newline(view);
13600
32.7k
  if (view.empty()) {
13601
18.5k
    return true;
13602
18.5k
  }
13603
13604
  // Schemes should start with alpha values.
13605
14.2k
  if (!checkers::is_alpha(view[0])) {
13606
6.31k
    return false;
13607
6.31k
  }
13608
13609
7.88k
  view.append(":");
13610
13611
7.88k
  std::string::iterator pointer =
13612
7.88k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13613
13614
7.88k
  if (pointer != view.end() && *pointer == ':') {
13615
7.08k
    url saved_url(*this);
13616
7.08k
    bool result = parse_scheme<true>(
13617
7.08k
        std::string_view(view.data(), pointer - view.begin()));
13618
7.08k
    if (result && get_href_size() > ada::get_max_input_length()) {
13619
0
      *this = std::move(saved_url);
13620
0
      return false;
13621
0
    }
13622
7.08k
    return result;
13623
7.08k
  }
13624
804
  return false;
13625
7.88k
}
13626
13627
4.12k
bool url::set_href(const std::string_view input) {
13628
4.12k
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13629
13630
4.12k
  if (out) {
13631
    // The parser enforces get_max_input_length() on both the input and the
13632
    // normalized result. This is a defense-in-depth check.
13633
4.12k
    if (out->get_href_size() > ada::get_max_input_length()) {
13634
0
      return false;
13635
0
    }
13636
4.12k
    *this = *out;
13637
4.12k
  }
13638
13639
4.12k
  return out.has_value();
13640
4.12k
}
13641
13642
}  // namespace ada
13643
/* end file src/url.cpp */
13644
/* begin file src/parser.cpp */
13645
13646
#include <limits>
13647
#include <ranges>
13648
13649
13650
namespace ada::parser {
13651
13652
template <class result_type, bool store_values>
13653
result_type parse_url_impl(std::string_view user_input,
13654
1.44M
                           const result_type* base_url) {
13655
  // We can specialize the implementation per type.
13656
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13657
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13658
  // something else } is free (at runtime). This means that ada::url_aggregator
13659
  // and ada::url **do not have to support the exact same API**.
13660
1.44M
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
1.44M
  constexpr bool result_type_is_ada_url_aggregator =
13662
1.44M
      std::is_same_v<url_aggregator, result_type>;
13663
1.44M
  static_assert(result_type_is_ada_url ||
13664
1.44M
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
1.44M
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
1.44M
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
1.44M
          ")");
13670
13671
1.44M
  state state = state::SCHEME_START;
13672
1.44M
  result_type url{};
13673
13674
1.44M
  const uint32_t max_input_length = ada::get_max_input_length();
13675
13676
  // We refuse to parse URL strings that exceed the maximum input length.
13677
  // By default, this is 4GB but can be configured via
13678
  // ada::set_max_input_length().
13679
1.44M
  if (user_input.size() > max_input_length) [[unlikely]] {
13680
0
    url.is_valid = false;
13681
0
  }
13682
  // Going forward, user_input.size() is in [0,
13683
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13684
  // base, or the optional_url was invalid, we must return.
13685
1.44M
  if (base_url != nullptr) {
13686
574k
    url.is_valid &= base_url->is_valid;
13687
574k
  }
13688
1.44M
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
1.44M
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13692
    // Most of the time, we just need user_input.size().
13693
    // In some instances, we may need a bit more.
13694
    ///////////////////////////
13695
    // This is *very* important. This line should *not* be removed
13696
    // hastily. There are principled reasons why reserve is important
13697
    // for performance. If you have a benchmark with small inputs,
13698
    // it may not matter, but in other instances, it could.
13699
    ////
13700
    // This rounds up to the next power of two.
13701
    // We know that user_input.size() is in [0,
13702
    // std::numeric_limits<uint32_t>::max).
13703
1.36M
    uint32_t reserve_capacity =
13704
1.36M
        (0xFFFFFFFF >>
13705
1.36M
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
1.36M
        1;
13707
1.36M
    url.reserve(reserve_capacity);
13708
1.36M
  }
13709
1.44M
  std::string tmp_buffer;
13710
1.44M
  std::string_view url_data;
13711
1.44M
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
11.0k
    tmp_buffer = user_input;
13713
    // Optimization opportunity: Instead of copying and then pruning, we could
13714
    // just directly build the string from user_input.
13715
11.0k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
11.0k
    url_data = tmp_buffer;
13717
1.43M
  } else [[likely]] {
13718
1.43M
    url_data = user_input;
13719
1.43M
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
1.44M
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
1.44M
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13727
  // We add it last so that an implementation like ada::url_aggregator
13728
  // can append it last to its internal buffer, thus improving performance.
13729
13730
  // Here url_data no longer has its fragment.
13731
  // We are going to access the data from url_data (it is immutable).
13732
  // At any given time, we are pointing at byte 'input_position' in url_data.
13733
  // The input_position variable should range from 0 to input_size.
13734
  // It is illegal to access url_data at input_size.
13735
1.44M
  size_t input_position = 0;
13736
1.44M
  const size_t input_size = url_data.size();
13737
  // Keep running the following state machine by switching on state.
13738
  // If after a run pointer points to the EOF code point, go to the next step.
13739
  // Otherwise, increase pointer by 1 and continue with the state machine.
13740
  // We never decrement input_position.
13741
8.83M
  while (input_position <= input_size) {
13742
8.42M
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
8.42M
            " in state ", ada::to_string(state));
13744
8.42M
    switch (state) {
13745
1.44M
      case state::SCHEME_START: {
13746
1.44M
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13747
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13748
        // state to scheme state.
13749
1.44M
        if ((input_position != input_size) &&
13750
1.41M
            checkers::is_alpha(url_data[input_position])) {
13751
1.35M
          state = state::SCHEME;
13752
1.35M
          input_position++;
13753
1.35M
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
86.0k
          state = state::NO_SCHEME;
13757
86.0k
        }
13758
1.44M
        break;
13759
0
      }
13760
1.35M
      case state::SCHEME: {
13761
1.35M
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13762
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13763
        // append c, lowercased, to buffer.
13764
6.49M
        while ((input_position != input_size) &&
13765
6.49M
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
5.13M
          input_position++;
13767
5.13M
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
1.35M
        if ((input_position != input_size) &&
13770
1.35M
            (url_data[input_position] == ':')) {
13771
1.34M
          ada_log("SCHEME the scheme should be ",
13772
1.34M
                  url_data.substr(0, input_position));
13773
1.34M
          if constexpr (result_type_is_ada_url) {
13774
44.9k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13775
0
              return url;
13776
0
            }
13777
1.30M
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
1.30M
            if (!url.parse_scheme_with_colon(
13780
1.30M
                    url_data.substr(0, input_position + 1))) {
13781
0
              return url;
13782
0
            }
13783
1.30M
          }
13784
1.34M
          ada_log("SCHEME the scheme is ", url.get_protocol());
13785
13786
          // If url's scheme is "file", then:
13787
          // NOLINTNEXTLINE(bugprone-branch-clone)
13788
1.34M
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
11.0k
            state = state::FILE;
13791
11.0k
          }
13792
          // Otherwise, if url is special, base is non-null, and base's scheme
13793
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13794
          // != nullptr is false.
13795
1.33M
          else if (url.is_special() && base_url != nullptr &&
13796
550k
                   base_url->type == url.type) {
13797
            // Set state to special relative or authority state.
13798
217k
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13799
217k
          }
13800
          // Otherwise, if url is special, set state to special authority
13801
          // slashes state.
13802
1.12M
          else if (url.is_special()) {
13803
853k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
853k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
267k
          else if (input_position + 1 < input_size &&
13808
260k
                   url_data[input_position + 1] == '/') {
13809
249k
            state = state::PATH_OR_AUTHORITY;
13810
249k
            input_position++;
13811
249k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
18.5k
          else {
13815
18.5k
            state = state::OPAQUE_PATH;
13816
18.5k
          }
13817
1.34M
        }
13818
        // Otherwise, if state override is not given, set buffer to the empty
13819
        // string, state to no scheme state, and start over (from the first code
13820
        // point in input).
13821
10.4k
        else {
13822
10.4k
          state = state::NO_SCHEME;
13823
10.4k
          input_position = 0;
13824
10.4k
          break;
13825
10.4k
        }
13826
1.34M
        input_position++;
13827
1.34M
        break;
13828
1.35M
      }
13829
96.5k
      case state::NO_SCHEME: {
13830
96.5k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13831
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13832
        // validation error, return failure.
13833
96.5k
        if (base_url == nullptr ||
13834
81.3k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
81.3k
          ada_log("NO_SCHEME validation error");
13836
81.3k
          url.is_valid = false;
13837
81.3k
          return url;
13838
81.3k
        }
13839
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13840
        // set url's scheme to base's scheme, url's path to base's path, url's
13841
        // query to base's query, and set state to fragment state.
13842
15.2k
        else if (base_url->has_opaque_path && fragment.has_value() &&
13843
794
                 input_position == input_size) {
13844
361
          ada_log("NO_SCHEME opaque base with fragment");
13845
361
          url.copy_scheme(*base_url);
13846
361
          url.has_opaque_path = base_url->has_opaque_path;
13847
13848
361
          if constexpr (result_type_is_ada_url) {
13849
129
            url.path = base_url->path;
13850
129
            url.query = base_url->query;
13851
232
          } else {
13852
232
            url.update_base_pathname(base_url->get_pathname());
13853
232
            if (base_url->has_search()) {
13854
              // get_search() returns "" for an empty query string (URL ends
13855
              // with '?'). update_base_search("") would incorrectly clear the
13856
              // query, so pass "?" to preserve the empty query distinction.
13857
86
              auto s = base_url->get_search();
13858
86
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13859
86
            }
13860
232
          }
13861
361
          url.update_unencoded_base_hash(*fragment);
13862
361
          return url;
13863
361
        }
13864
        // Otherwise, if base's scheme is not "file", set state to relative
13865
        // state and decrease pointer by 1.
13866
        // NOLINTNEXTLINE(bugprone-branch-clone)
13867
14.8k
        else if (base_url->type != scheme::type::FILE) {
13868
12.6k
          ada_log("NO_SCHEME non-file relative path");
13869
12.6k
          state = state::RELATIVE_SCHEME;
13870
12.6k
        }
13871
        // Otherwise, set state to file state and decrease pointer by 1.
13872
2.20k
        else {
13873
2.20k
          ada_log("NO_SCHEME file base type");
13874
2.20k
          state = state::FILE;
13875
2.20k
        }
13876
14.8k
        break;
13877
96.5k
      }
13878
1.29M
      case state::AUTHORITY: {
13879
1.29M
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13880
        // most URLs have no @. Having no @ tells us that we don't have to worry
13881
        // about AUTHORITY. Of course, we could have @ and still not have to
13882
        // worry about AUTHORITY.
13883
        // TODO: Instead of just collecting a bool, collect the location of the
13884
        // '@' and do something useful with it.
13885
        // TODO: We could do various processing early on, using a single pass
13886
        // over the string to collect information about it, e.g., telling us
13887
        // whether there is a @ and if so, where (or how many).
13888
13889
        // Check if url data contains an @.
13890
1.29M
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
1.21M
          state = state::HOST;
13892
1.21M
          break;
13893
1.21M
        }
13894
76.4k
        bool at_sign_seen{false};
13895
76.4k
        bool password_token_seen{false};
13896
        /**
13897
         * We expect something of the sort...
13898
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13899
         * --------^
13900
         */
13901
204k
        do {
13902
204k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
204k
          size_t location =
13905
204k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
204k
                               : helpers::find_authority_delimiter(view);
13907
204k
          std::string_view authority_view = view.substr(0, location);
13908
204k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
204k
          if ((end_of_authority != input_size) &&
13911
197k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
128k
            if (at_sign_seen) {
13914
64.7k
              if (password_token_seen) {
13915
25.7k
                if constexpr (result_type_is_ada_url) {
13916
4.04k
                  url.password += "%40";
13917
21.7k
                } else {
13918
21.7k
                  url.append_base_password("%40");
13919
21.7k
                }
13920
39.0k
              } else {
13921
39.0k
                if constexpr (result_type_is_ada_url) {
13922
5.81k
                  url.username += "%40";
13923
33.1k
                } else {
13924
33.1k
                  url.append_base_username("%40");
13925
33.1k
                }
13926
39.0k
              }
13927
64.7k
            }
13928
13929
128k
            at_sign_seen = true;
13930
13931
128k
            if (!password_token_seen) {
13932
102k
              size_t password_token_location = authority_view.find(':');
13933
102k
              password_token_seen =
13934
102k
                  password_token_location != std::string_view::npos;
13935
13936
102k
              if constexpr (store_values) {
13937
100k
                if (!password_token_seen) {
13938
59.6k
                  if constexpr (result_type_is_ada_url) {
13939
6.66k
                    url.username += unicode::percent_encode(
13940
6.66k
                        authority_view,
13941
6.66k
                        character_sets::USERINFO_PERCENT_ENCODE);
13942
52.9k
                  } else {
13943
52.9k
                    url.append_base_username(unicode::percent_encode(
13944
52.9k
                        authority_view,
13945
52.9k
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
52.9k
                  }
13947
59.6k
                } else {
13948
41.0k
                  if constexpr (result_type_is_ada_url) {
13949
14.3k
                    url.username += unicode::percent_encode(
13950
14.3k
                        authority_view.substr(0, password_token_location),
13951
14.3k
                        character_sets::USERINFO_PERCENT_ENCODE);
13952
14.3k
                    url.password += unicode::percent_encode(
13953
14.3k
                        authority_view.substr(password_token_location + 1),
13954
14.3k
                        character_sets::USERINFO_PERCENT_ENCODE);
13955
26.7k
                  } else {
13956
26.7k
                    url.append_base_username(unicode::percent_encode(
13957
26.7k
                        authority_view.substr(0, password_token_location),
13958
26.7k
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
26.7k
                    url.append_base_password(unicode::percent_encode(
13960
26.7k
                        authority_view.substr(password_token_location + 1),
13961
26.7k
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
26.7k
                  }
13963
41.0k
                }
13964
100k
              }
13965
102k
            } else if constexpr (store_values) {
13966
24.8k
              if constexpr (result_type_is_ada_url) {
13967
4.04k
                url.password += unicode::percent_encode(
13968
4.04k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13969
20.8k
              } else {
13970
20.8k
                url.append_base_password(unicode::percent_encode(
13971
20.8k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
20.8k
              }
13973
24.8k
            }
13974
128k
          }
13975
          // Otherwise, if one of the following is true:
13976
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13977
          // - url is special and c is U+005C (\)
13978
76.4k
          else if (end_of_authority == input_size ||
13979
69.7k
                   url_data[end_of_authority] == '/' ||
13980
1.50k
                   url_data[end_of_authority] == '?' ||
13981
76.4k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13982
            // If atSignSeen is true and authority_view is the empty string,
13983
            // validation error, return failure.
13984
76.4k
            if (at_sign_seen && authority_view.empty()) {
13985
7.17k
              url.is_valid = false;
13986
7.17k
              return url;
13987
7.17k
            }
13988
69.2k
            state = state::HOST;
13989
69.2k
            break;
13990
76.4k
          }
13991
128k
          if (end_of_authority == input_size) {
13992
0
            if constexpr (store_values) {
13993
0
              if (fragment.has_value()) {
13994
0
                url.update_unencoded_base_hash(*fragment);
13995
0
              }
13996
0
            }
13997
0
            return url;
13998
0
          }
13999
128k
          input_position = end_of_authority + 1;
14000
128k
        } while (true);
14001
14002
69.2k
        break;
14003
76.4k
      }
14004
217k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
14005
217k
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
14006
217k
                helpers::substring(url_data, input_position));
14007
14008
        // If c is U+002F (/) and remaining starts with U+002F (/),
14009
        // then set state to special authority ignore slashes state and increase
14010
        // pointer by 1.
14011
217k
        if (url_data.substr(input_position, 2) == "//") {
14012
216k
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14013
216k
          input_position += 2;
14014
216k
        } else {
14015
          // Otherwise, validation error, set state to relative state and
14016
          // decrease pointer by 1.
14017
333
          state = state::RELATIVE_SCHEME;
14018
333
        }
14019
14020
217k
        break;
14021
76.4k
      }
14022
249k
      case state::PATH_OR_AUTHORITY: {
14023
249k
        ada_log("PATH_OR_AUTHORITY ",
14024
249k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
249k
        if ((input_position != input_size) &&
14028
228k
            (url_data[input_position] == '/')) {
14029
223k
          state = state::AUTHORITY;
14030
223k
          input_position++;
14031
223k
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
25.2k
          state = state::PATH;
14034
25.2k
        }
14035
14036
249k
        break;
14037
76.4k
      }
14038
12.9k
      case state::RELATIVE_SCHEME: {
14039
12.9k
        ada_log("RELATIVE_SCHEME ",
14040
12.9k
                helpers::substring(url_data, input_position));
14041
14042
        // Set url's scheme to base's scheme.
14043
12.9k
        url.copy_scheme(*base_url);
14044
14045
        // If c is U+002F (/), then set state to relative slash state.
14046
12.9k
        if ((input_position != input_size) &&
14047
            // NOLINTNEXTLINE(bugprone-branch-clone)
14048
8.97k
            (url_data[input_position] == '/')) {
14049
1.80k
          ada_log(
14050
1.80k
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
14051
1.80k
              "slash state");
14052
1.80k
          state = state::RELATIVE_SLASH;
14053
11.1k
        } else if (url.is_special() && (input_position != input_size) &&
14054
6.13k
                   (url_data[input_position] == '\\')) {
14055
          // Otherwise, if url is special and c is U+005C (\), validation error,
14056
          // set state to relative slash state.
14057
63
          ada_log(
14058
63
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
14059
63
              "error, set state to relative slash state");
14060
63
          state = state::RELATIVE_SLASH;
14061
11.1k
        } else {
14062
11.1k
          ada_log("RELATIVE_SCHEME otherwise");
14063
          // Set url's username to base's username, url's password to base's
14064
          // password, url's host to base's host, url's port to base's port,
14065
          // url's path to a clone of base's path, and url's query to base's
14066
          // query.
14067
11.1k
          if constexpr (result_type_is_ada_url) {
14068
825
            url.username = base_url->username;
14069
825
            url.password = base_url->password;
14070
825
            url.host = base_url->host;
14071
825
            url.port = base_url->port;
14072
            // cloning the base path includes cloning the has_opaque_path flag
14073
825
            url.has_opaque_path = base_url->has_opaque_path;
14074
825
            url.path = base_url->path;
14075
825
            url.query = base_url->query;
14076
10.3k
          } else {
14077
10.3k
            url.update_base_authority(base_url->get_href(),
14078
10.3k
                                      base_url->get_components());
14079
10.3k
            url.update_host_to_base_host(base_url->get_hostname());
14080
10.3k
            url.update_base_port(base_url->retrieve_base_port());
14081
            // cloning the base path includes cloning the has_opaque_path flag
14082
10.3k
            url.has_opaque_path = base_url->has_opaque_path;
14083
10.3k
            url.update_base_pathname(base_url->get_pathname());
14084
10.3k
            if (base_url->has_search()) {
14085
              // get_search() returns "" for an empty query string (URL ends
14086
              // with '?'). update_base_search("") would incorrectly clear the
14087
              // query, so pass "?" to preserve the empty query distinction.
14088
7.41k
              auto s = base_url->get_search();
14089
7.41k
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
7.41k
            }
14091
10.3k
          }
14092
14093
11.1k
          url.has_opaque_path = base_url->has_opaque_path;
14094
14095
          // If c is U+003F (?), then set url's query to the empty string, and
14096
          // state to query state.
14097
11.1k
          if ((input_position != input_size) &&
14098
7.10k
              (url_data[input_position] == '?')) {
14099
183
            state = state::QUERY;
14100
183
          }
14101
          // Otherwise, if c is not the EOF code point:
14102
10.9k
          else if (input_position != input_size) {
14103
            // Set url's query to null.
14104
6.92k
            url.clear_search();
14105
6.92k
            if constexpr (result_type_is_ada_url) {
14106
              // Shorten url's path.
14107
478
              helpers::shorten_path(url.path, url.type);
14108
6.44k
            } else {
14109
6.44k
              std::string_view path = url.get_pathname();
14110
6.44k
              if (helpers::shorten_path(path, url.type)) {
14111
6.11k
                url.update_base_pathname(std::move(std::string(path)));
14112
6.11k
              }
14113
6.44k
            }
14114
            // Set state to path state and decrease pointer by 1.
14115
6.92k
            state = state::PATH;
14116
6.92k
            break;
14117
6.92k
          }
14118
11.1k
        }
14119
6.07k
        input_position++;
14120
6.07k
        break;
14121
12.9k
      }
14122
1.86k
      case state::RELATIVE_SLASH: {
14123
1.86k
        ada_log("RELATIVE_SLASH ",
14124
1.86k
                helpers::substring(url_data, input_position));
14125
14126
        // If url is special and c is U+002F (/) or U+005C (\), then:
14127
        // NOLINTNEXTLINE(bugprone-branch-clone)
14128
1.86k
        if (url.is_special() && (input_position != input_size) &&
14129
1.44k
            (url_data[input_position] == '/' ||
14130
744
             url_data[input_position] == '\\')) {
14131
          // Set state to special authority ignore slashes state.
14132
744
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14133
744
        }
14134
        // Otherwise, if c is U+002F (/), then set state to authority state.
14135
1.12k
        else if ((input_position != input_size) &&
14136
872
                 (url_data[input_position] == '/')) {
14137
143
          state = state::AUTHORITY;
14138
143
        }
14139
        // Otherwise, set
14140
        // - url's username to base's username,
14141
        // - url's password to base's password,
14142
        // - url's host to base's host,
14143
        // - url's port to base's port,
14144
        // - state to path state, and then, decrease pointer by 1.
14145
980
        else {
14146
980
          if constexpr (result_type_is_ada_url) {
14147
70
            url.username = base_url->username;
14148
70
            url.password = base_url->password;
14149
70
            url.host = base_url->host;
14150
70
            url.port = base_url->port;
14151
910
          } else {
14152
910
            url.update_base_authority(base_url->get_href(),
14153
910
                                      base_url->get_components());
14154
910
            url.update_host_to_base_host(base_url->get_hostname());
14155
910
            url.update_base_port(base_url->retrieve_base_port());
14156
910
          }
14157
980
          state = state::PATH;
14158
980
          break;
14159
980
        }
14160
14161
887
        input_position++;
14162
887
        break;
14163
1.86k
      }
14164
853k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
853k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
853k
                helpers::substring(url_data, input_position));
14167
14168
        // If c is U+002F (/) and remaining starts with U+002F (/),
14169
        // then set state to special authority ignore slashes state and increase
14170
        // pointer by 1.
14171
853k
        if (url_data.substr(input_position, 2) == "//") {
14172
822k
          input_position += 2;
14173
822k
        }
14174
14175
853k
        [[fallthrough]];
14176
853k
      }
14177
1.07M
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
1.07M
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
1.07M
                helpers::substring(url_data, input_position));
14180
14181
        // If c is neither U+002F (/) nor U+005C (\), then set state to
14182
        // authority state and decrease pointer by 1.
14183
1.48M
        while ((input_position != input_size) &&
14184
1.08M
               ((url_data[input_position] == '/') ||
14185
685k
                (url_data[input_position] == '\\'))) {
14186
411k
          input_position++;
14187
411k
        }
14188
1.07M
        state = state::AUTHORITY;
14189
14190
1.07M
        break;
14191
853k
      }
14192
78.3k
      case state::QUERY: {
14193
78.3k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
78.3k
        if constexpr (store_values) {
14195
          // Let queryPercentEncodeSet be the special-query percent-encode set
14196
          // if url is special; otherwise the query percent-encode set.
14197
78.3k
          const uint8_t* query_percent_encode_set =
14198
78.3k
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
78.3k
                               : character_sets::QUERY_PERCENT_ENCODE;
14200
14201
          // Percent-encode after encoding, with encoding, buffer, and
14202
          // queryPercentEncodeSet, and append the result to url's query.
14203
78.3k
          url.update_base_search(url_data.substr(input_position),
14204
78.3k
                                 query_percent_encode_set);
14205
78.3k
          ada_log("QUERY update_base_search completed ");
14206
78.3k
          if (fragment.has_value()) {
14207
45.4k
            url.update_unencoded_base_hash(*fragment);
14208
45.4k
          }
14209
78.3k
        }
14210
78.3k
        return url;
14211
853k
      }
14212
1.28M
      case state::HOST: {
14213
1.28M
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
1.28M
        std::string_view host_view = url_data.substr(input_position);
14216
1.28M
        auto [location, found_colon] =
14217
1.28M
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
1.28M
        input_position = (location != std::string_view::npos)
14219
1.28M
                             ? input_position + location
14220
1.28M
                             : input_size;
14221
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14222
        // Note: the 'found_colon' value is true if and only if a colon was
14223
        // encountered while not inside brackets.
14224
1.28M
        if (found_colon) {
14225
          // If buffer is the empty string, validation error, return failure.
14226
          // Let host be the result of host parsing buffer with url is not
14227
          // special.
14228
58.0k
          ada_log("HOST parsing ", host_view);
14229
58.0k
          if (!url.parse_host(host_view)) {
14230
5.35k
            return url;
14231
5.35k
          }
14232
52.6k
          ada_log("HOST parsing results in ", url.get_hostname());
14233
          // Set url's host to host, buffer to the empty string, and state to
14234
          // port state.
14235
52.6k
          state = state::PORT;
14236
52.6k
          input_position++;
14237
52.6k
        }
14238
        // Otherwise, if one of the following is true:
14239
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14240
        // - url is special and c is U+005C (\)
14241
        // The get_host_delimiter_location function either brings us to
14242
        // the colon outside of the bracket, or to one of those characters.
14243
1.22M
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
1.22M
          if (host_view.empty() && url.is_special()) {
14247
396k
            url.is_valid = false;
14248
396k
            return url;
14249
396k
          }
14250
832k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
14251
          // Let host be the result of host parsing host_view with url is not
14252
          // special.
14253
832k
          if (host_view.empty()) {
14254
663
            url.update_base_hostname("");
14255
832k
          } else if (!url.parse_host(host_view)) {
14256
103k
            return url;
14257
103k
          }
14258
729k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
729k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
729k
          state = state::PATH_START;
14263
729k
        }
14264
14265
781k
        break;
14266
1.28M
      }
14267
781k
      case state::OPAQUE_PATH: {
14268
18.5k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
14269
        // Opaque path, query, and fragment are structurally always valid:
14270
        // the parser would just percent-encode whatever is there. When we
14271
        // are not storing values (can_parse), we can return immediately.
14272
        // We must set has_opaque_path = true before returning so that when
14273
        // this URL is used as an internal base inside can_parse, NO_SCHEME
14274
        // correctly rejects relative inputs against an opaque-path base
14275
        // (e.g. can_parse("", &"W:") must return false).
14276
18.5k
        if constexpr (!store_values) {
14277
1.84k
          url.has_opaque_path = true;
14278
1.84k
          return url;
14279
1.84k
        }
14280
0
        std::string_view view = url_data.substr(input_position);
14281
        // If c is U+003F (?), then set url's query to the empty string and
14282
        // state to query state.
14283
18.5k
        size_t location = view.find('?');
14284
18.5k
        if (location != std::string_view::npos) {
14285
1.07k
          view.remove_suffix(view.size() - location);
14286
1.07k
          state = state::QUERY;
14287
1.07k
          input_position += location + 1;
14288
17.4k
        } else {
14289
17.4k
          input_position = input_size + 1;
14290
17.4k
        }
14291
18.5k
        url.has_opaque_path = true;
14292
14293
        // This is a really unlikely scenario in real world. We should not seek
14294
        // to optimize it.
14295
18.5k
        if (view.ends_with(' ')) {
14296
392
          std::string modified_view =
14297
392
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
392
          url.update_base_pathname(unicode::percent_encode(
14299
392
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
18.1k
        } else {
14301
18.1k
          url.update_base_pathname(unicode::percent_encode(
14302
18.1k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
18.1k
        }
14304
18.5k
        break;
14305
1.28M
      }
14306
52.6k
      case state::PORT: {
14307
52.6k
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
52.6k
        std::string_view port_view = url_data.substr(input_position);
14309
52.6k
        input_position += url.parse_port(port_view, true);
14310
52.6k
        if (!url.is_valid) {
14311
4.30k
          return url;
14312
4.30k
        }
14313
48.3k
        state = state::PATH_START;
14314
48.3k
        [[fallthrough]];
14315
48.3k
      }
14316
782k
      case state::PATH_START: {
14317
782k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
14318
        // Path, query, and fragment are structurally always valid: the
14319
        // parser would just percent-encode whatever is there. When we are
14320
        // not storing values (can_parse), we can return immediately since
14321
        // no subsequent state can invalidate the URL.
14322
782k
        if constexpr (!store_values) {
14323
2.61k
          return url;
14324
2.61k
        }
14325
14326
        // If url is special, then:
14327
782k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
557k
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
557k
          if (input_position == input_size) {
14334
342k
            if constexpr (store_values) {
14335
342k
              url.update_base_pathname("/");
14336
342k
              if (fragment.has_value()) {
14337
6.19k
                url.update_unencoded_base_hash(*fragment);
14338
6.19k
              }
14339
342k
            }
14340
342k
            return url;
14341
342k
          }
14342
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
14343
          // by 1. We know that (input_position == input_size) is impossible
14344
          // here, because of the previous if-check.
14345
215k
          if ((url_data[input_position] != '/') &&
14346
13.0k
              (url_data[input_position] != '\\')) {
14347
10.2k
            break;
14348
10.2k
          }
14349
215k
        }
14350
        // Otherwise, if state override is not given and c is U+003F (?),
14351
        // set url's query to the empty string and state to query state.
14352
224k
        else if ((input_position != input_size) &&
14353
219k
                 (url_data[input_position] == '?')) {
14354
197
          state = state::QUERY;
14355
197
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
224k
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
219k
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
219k
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
219k
        }
14366
14367
430k
        input_position++;
14368
430k
        break;
14369
782k
      }
14370
474k
      case state::PATH: {
14371
474k
        ada_log("PATH ", helpers::substring(url_data, input_position));
14372
        // Path, query, and fragment are structurally always valid: the
14373
        // parser would just percent-encode whatever is there. When we are
14374
        // not storing values (can_parse), we can return immediately since
14375
        // no subsequent state can invalidate the URL.
14376
474k
        if constexpr (!store_values) {
14377
1.42k
          return url;
14378
1.42k
        }
14379
0
        std::string_view view = url_data.substr(input_position);
14380
14381
        // Most time, we do not need percent encoding.
14382
        // Furthermore, we can immediately locate the '?'.
14383
474k
        size_t locofquestionmark = view.find('?');
14384
474k
        if (locofquestionmark != std::string_view::npos) {
14385
76.8k
          state = state::QUERY;
14386
76.8k
          view.remove_suffix(view.size() - locofquestionmark);
14387
76.8k
          input_position += locofquestionmark + 1;
14388
397k
        } else {
14389
397k
          input_position = input_size + 1;
14390
397k
        }
14391
474k
        if constexpr (store_values) {
14392
473k
          if constexpr (result_type_is_ada_url) {
14393
19.0k
            helpers::parse_prepared_path(view, url.type, url.path);
14394
454k
          } else {
14395
454k
            url.consume_prepared_path(view);
14396
454k
            ADA_ASSERT_TRUE(url.validate());
14397
454k
          }
14398
473k
        }
14399
474k
        break;
14400
782k
      }
14401
7.22k
      case state::FILE_SLASH: {
14402
7.22k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
7.22k
        if ((input_position != input_size) &&
14406
6.81k
            (url_data[input_position] == '/' ||
14407
5.92k
             url_data[input_position] == '\\')) {
14408
5.92k
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
5.92k
          state = state::FILE_HOST;
14411
5.92k
          input_position++;
14412
5.92k
        } else {
14413
1.30k
          ada_log("FILE_SLASH otherwise");
14414
          // If base is non-null and base's scheme is "file", then:
14415
          // Note: it is unsafe to do base_url->scheme unless you know that
14416
          // base_url_has_value() is true.
14417
1.30k
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14418
            // Set url's host to base's host.
14419
488
            if constexpr (result_type_is_ada_url) {
14420
167
              url.host = base_url->host;
14421
321
            } else {
14422
321
              url.update_host_to_base_host(base_url->get_host());
14423
321
            }
14424
            // If the code point substring from pointer to the end of input does
14425
            // not start with a Windows drive letter and base's path[0] is a
14426
            // normalized Windows drive letter, then append base's path[0] to
14427
            // url's path.
14428
488
            if (!base_url->get_pathname().empty()) {
14429
488
              if (!checkers::is_windows_drive_letter(
14430
488
                      url_data.substr(input_position))) {
14431
407
                std::string_view first_base_url_path =
14432
407
                    base_url->get_pathname().substr(1);
14433
407
                size_t loc = first_base_url_path.find('/');
14434
407
                if (loc != std::string_view::npos) {
14435
90
                  helpers::resize(first_base_url_path, loc);
14436
90
                }
14437
407
                if (checkers::is_normalized_windows_drive_letter(
14438
407
                        first_base_url_path)) {
14439
82
                  if constexpr (result_type_is_ada_url) {
14440
28
                    url.path += '/';
14441
28
                    url.path += first_base_url_path;
14442
54
                  } else {
14443
54
                    url.append_base_pathname(
14444
54
                        helpers::concat("/", first_base_url_path));
14445
54
                  }
14446
82
                }
14447
407
              }
14448
488
            }
14449
488
          }
14450
14451
          // Set state to path state, and decrease pointer by 1.
14452
1.30k
          state = state::PATH;
14453
1.30k
        }
14454
14455
7.22k
        break;
14456
782k
      }
14457
5.92k
      case state::FILE_HOST: {
14458
5.92k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
5.92k
        std::string_view view = url_data.substr(input_position);
14460
14461
5.92k
        size_t location = view.find_first_of("/\\?");
14462
5.92k
        std::string_view file_host_buffer = view.substr(
14463
5.92k
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
5.92k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
64
          state = state::PATH;
14467
5.85k
        } else if (file_host_buffer.empty()) {
14468
          // Set url's host to the empty string.
14469
1.36k
          if constexpr (result_type_is_ada_url) {
14470
85
            url.host = "";
14471
1.27k
          } else {
14472
1.27k
            url.update_base_hostname("");
14473
1.27k
          }
14474
          // Set state to path start state.
14475
1.36k
          state = state::PATH_START;
14476
4.49k
        } else {
14477
4.49k
          size_t consumed_bytes = file_host_buffer.size();
14478
4.49k
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
4.49k
          if (!url.parse_host(file_host_buffer)) {
14482
867
            return url;
14483
867
          }
14484
14485
3.62k
          if constexpr (result_type_is_ada_url) {
14486
            // If host is "localhost", then set host to the empty string.
14487
1.09k
            if (url.host.has_value() && url.host.value() == "localhost") {
14488
16
              url.host = "";
14489
16
            }
14490
2.53k
          } else {
14491
2.53k
            if (url.get_hostname() == "localhost") {
14492
24
              url.update_base_hostname("");
14493
24
            }
14494
2.53k
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
3.62k
          state = state::PATH_START;
14498
3.62k
        }
14499
14500
5.05k
        break;
14501
5.92k
      }
14502
13.2k
      case state::FILE: {
14503
13.2k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
13.2k
        std::string_view file_view = url_data.substr(input_position);
14505
14506
13.2k
        url.set_protocol_as_file();
14507
13.2k
        if constexpr (result_type_is_ada_url) {
14508
          // Set url's host to the empty string.
14509
3.33k
          url.host = "";
14510
9.94k
        } else {
14511
9.94k
          url.update_base_hostname("");
14512
9.94k
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
13.2k
        if (input_position != input_size &&
14515
11.4k
            (url_data[input_position] == '/' ||
14516
7.22k
             url_data[input_position] == '\\')) {
14517
7.22k
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
7.22k
          state = state::FILE_SLASH;
14520
7.22k
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
6.05k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14523
          // Set url's host to base's host, url's path to a clone of base's
14524
          // path, and url's query to base's query.
14525
1.65k
          ada_log("FILE base non-null");
14526
1.65k
          if constexpr (result_type_is_ada_url) {
14527
407
            url.host = base_url->host;
14528
407
            url.path = base_url->path;
14529
407
            url.query = base_url->query;
14530
1.25k
          } else {
14531
1.25k
            url.update_host_to_base_host(base_url->get_hostname());
14532
1.25k
            url.update_base_pathname(base_url->get_pathname());
14533
1.25k
            if (base_url->has_search()) {
14534
              // get_search() returns "" for an empty query string (URL ends
14535
              // with '?'). update_base_search("") would incorrectly clear the
14536
              // query, so pass "?" to preserve the empty query distinction.
14537
151
              auto s = base_url->get_search();
14538
151
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
151
            }
14540
1.25k
          }
14541
1.65k
          url.has_opaque_path = base_url->has_opaque_path;
14542
14543
          // If c is U+003F (?), then set url's query to the empty string and
14544
          // state to query state.
14545
1.65k
          if (input_position != input_size && url_data[input_position] == '?') {
14546
49
            state = state::QUERY;
14547
49
          }
14548
          // Otherwise, if c is not the EOF code point:
14549
1.60k
          else if (input_position != input_size) {
14550
            // Set url's query to null.
14551
604
            url.clear_search();
14552
            // If the code point substring from pointer to the end of input does
14553
            // not start with a Windows drive letter, then shorten url's path.
14554
604
            if (!checkers::is_windows_drive_letter(file_view)) {
14555
501
              if constexpr (result_type_is_ada_url) {
14556
164
                helpers::shorten_path(url.path, url.type);
14557
337
              } else {
14558
337
                std::string_view path = url.get_pathname();
14559
337
                if (helpers::shorten_path(path, url.type)) {
14560
319
                  url.update_base_pathname(std::move(std::string(path)));
14561
319
                }
14562
337
              }
14563
501
            }
14564
            // Otherwise:
14565
103
            else {
14566
              // Set url's path to an empty list.
14567
103
              url.clear_pathname();
14568
103
              url.has_opaque_path = true;
14569
103
            }
14570
14571
            // Set state to path state and decrease pointer by 1.
14572
604
            state = state::PATH;
14573
604
            break;
14574
604
          }
14575
1.65k
        }
14576
        // Otherwise, set state to path state, and decrease pointer by 1.
14577
4.40k
        else {
14578
4.40k
          ada_log("FILE go to path");
14579
4.40k
          state = state::PATH;
14580
4.40k
          break;
14581
4.40k
        }
14582
14583
8.28k
        input_position++;
14584
8.28k
        break;
14585
13.2k
      }
14586
0
      default:
14587
0
        unreachable();
14588
8.42M
    }
14589
8.42M
  }
14590
419k
  if constexpr (store_values) {
14591
419k
    if (fragment.has_value()) {
14592
6.57k
      url.update_unencoded_base_hash(*fragment);
14593
6.57k
    }
14594
419k
  }
14595
  // Check the resulting (normalized) URL size against the maximum input length.
14596
  // Normalization (percent-encoding, IDNA, etc.) can expand the URL beyond the
14597
  // original input size.
14598
419k
  if constexpr (store_values) {
14599
419k
    if (url.is_valid) {
14600
419k
      if constexpr (result_type_is_ada_url_aggregator) {
14601
409k
        if (url.buffer.size() > max_input_length) {
14602
0
          url.is_valid = false;
14603
0
        }
14604
409k
      } else {
14605
10.1k
        if (url.get_href_size() > max_input_length) {
14606
0
          url.is_valid = false;
14607
0
        }
14608
10.1k
      }
14609
419k
    }
14610
419k
  }
14611
419k
  return url;
14612
1.44M
}
ada::url ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Line
Count
Source
13654
65.7k
                           const result_type* base_url) {
13655
  // We can specialize the implementation per type.
13656
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13657
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13658
  // something else } is free (at runtime). This means that ada::url_aggregator
13659
  // and ada::url **do not have to support the exact same API**.
13660
65.7k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
65.7k
  constexpr bool result_type_is_ada_url_aggregator =
13662
65.7k
      std::is_same_v<url_aggregator, result_type>;
13663
65.7k
  static_assert(result_type_is_ada_url ||
13664
65.7k
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
65.7k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
65.7k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
65.7k
          ")");
13670
13671
65.7k
  state state = state::SCHEME_START;
13672
65.7k
  result_type url{};
13673
13674
65.7k
  const uint32_t max_input_length = ada::get_max_input_length();
13675
13676
  // We refuse to parse URL strings that exceed the maximum input length.
13677
  // By default, this is 4GB but can be configured via
13678
  // ada::set_max_input_length().
13679
65.7k
  if (user_input.size() > max_input_length) [[unlikely]] {
13680
0
    url.is_valid = false;
13681
0
  }
13682
  // Going forward, user_input.size() is in [0,
13683
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13684
  // base, or the optional_url was invalid, we must return.
13685
65.7k
  if (base_url != nullptr) {
13686
5.58k
    url.is_valid &= base_url->is_valid;
13687
5.58k
  }
13688
65.7k
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13692
    // Most of the time, we just need user_input.size().
13693
    // In some instances, we may need a bit more.
13694
    ///////////////////////////
13695
    // This is *very* important. This line should *not* be removed
13696
    // hastily. There are principled reasons why reserve is important
13697
    // for performance. If you have a benchmark with small inputs,
13698
    // it may not matter, but in other instances, it could.
13699
    ////
13700
    // This rounds up to the next power of two.
13701
    // We know that user_input.size() is in [0,
13702
    // std::numeric_limits<uint32_t>::max).
13703
    uint32_t reserve_capacity =
13704
        (0xFFFFFFFF >>
13705
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
        1;
13707
    url.reserve(reserve_capacity);
13708
  }
13709
65.7k
  std::string tmp_buffer;
13710
65.7k
  std::string_view url_data;
13711
65.7k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
630
    tmp_buffer = user_input;
13713
    // Optimization opportunity: Instead of copying and then pruning, we could
13714
    // just directly build the string from user_input.
13715
630
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
630
    url_data = tmp_buffer;
13717
65.1k
  } else [[likely]] {
13718
65.1k
    url_data = user_input;
13719
65.1k
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
65.7k
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
65.7k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13727
  // We add it last so that an implementation like ada::url_aggregator
13728
  // can append it last to its internal buffer, thus improving performance.
13729
13730
  // Here url_data no longer has its fragment.
13731
  // We are going to access the data from url_data (it is immutable).
13732
  // At any given time, we are pointing at byte 'input_position' in url_data.
13733
  // The input_position variable should range from 0 to input_size.
13734
  // It is illegal to access url_data at input_size.
13735
65.7k
  size_t input_position = 0;
13736
65.7k
  const size_t input_size = url_data.size();
13737
  // Keep running the following state machine by switching on state.
13738
  // If after a run pointer points to the EOF code point, go to the next step.
13739
  // Otherwise, increase pointer by 1 and continue with the state machine.
13740
  // We never decrement input_position.
13741
335k
  while (input_position <= input_size) {
13742
325k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
325k
            " in state ", ada::to_string(state));
13744
325k
    switch (state) {
13745
65.7k
      case state::SCHEME_START: {
13746
65.7k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13747
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13748
        // state to scheme state.
13749
65.7k
        if ((input_position != input_size) &&
13750
53.7k
            checkers::is_alpha(url_data[input_position])) {
13751
46.9k
          state = state::SCHEME;
13752
46.9k
          input_position++;
13753
46.9k
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
18.8k
          state = state::NO_SCHEME;
13757
18.8k
        }
13758
65.7k
        break;
13759
0
      }
13760
46.9k
      case state::SCHEME: {
13761
46.9k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13762
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13763
        // append c, lowercased, to buffer.
13764
205k
        while ((input_position != input_size) &&
13765
204k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
158k
          input_position++;
13767
158k
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
46.9k
        if ((input_position != input_size) &&
13770
45.9k
            (url_data[input_position] == ':')) {
13771
44.9k
          ada_log("SCHEME the scheme should be ",
13772
44.9k
                  url_data.substr(0, input_position));
13773
44.9k
          if constexpr (result_type_is_ada_url) {
13774
44.9k
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13775
0
              return url;
13776
0
            }
13777
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
            if (!url.parse_scheme_with_colon(
13780
                    url_data.substr(0, input_position + 1))) {
13781
              return url;
13782
            }
13783
          }
13784
44.9k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13785
13786
          // If url's scheme is "file", then:
13787
          // NOLINTNEXTLINE(bugprone-branch-clone)
13788
44.9k
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
2.74k
            state = state::FILE;
13791
2.74k
          }
13792
          // Otherwise, if url is special, base is non-null, and base's scheme
13793
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13794
          // != nullptr is false.
13795
42.2k
          else if (url.is_special() && base_url != nullptr &&
13796
2.28k
                   base_url->type == url.type) {
13797
            // Set state to special relative or authority state.
13798
108
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13799
108
          }
13800
          // Otherwise, if url is special, set state to special authority
13801
          // slashes state.
13802
42.1k
          else if (url.is_special()) {
13803
35.0k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
35.0k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
7.02k
          else if (input_position + 1 < input_size &&
13808
4.81k
                   url_data[input_position + 1] == '/') {
13809
2.35k
            state = state::PATH_OR_AUTHORITY;
13810
2.35k
            input_position++;
13811
2.35k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
4.67k
          else {
13815
4.67k
            state = state::OPAQUE_PATH;
13816
4.67k
          }
13817
44.9k
        }
13818
        // Otherwise, if state override is not given, set buffer to the empty
13819
        // string, state to no scheme state, and start over (from the first code
13820
        // point in input).
13821
1.97k
        else {
13822
1.97k
          state = state::NO_SCHEME;
13823
1.97k
          input_position = 0;
13824
1.97k
          break;
13825
1.97k
        }
13826
44.9k
        input_position++;
13827
44.9k
        break;
13828
46.9k
      }
13829
20.7k
      case state::NO_SCHEME: {
13830
20.7k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13831
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13832
        // validation error, return failure.
13833
20.7k
        if (base_url == nullptr ||
13834
19.1k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
19.1k
          ada_log("NO_SCHEME validation error");
13836
19.1k
          url.is_valid = false;
13837
19.1k
          return url;
13838
19.1k
        }
13839
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13840
        // set url's scheme to base's scheme, url's path to base's path, url's
13841
        // query to base's query, and set state to fragment state.
13842
1.57k
        else if (base_url->has_opaque_path && fragment.has_value() &&
13843
282
                 input_position == input_size) {
13844
129
          ada_log("NO_SCHEME opaque base with fragment");
13845
129
          url.copy_scheme(*base_url);
13846
129
          url.has_opaque_path = base_url->has_opaque_path;
13847
13848
129
          if constexpr (result_type_is_ada_url) {
13849
129
            url.path = base_url->path;
13850
129
            url.query = base_url->query;
13851
          } else {
13852
            url.update_base_pathname(base_url->get_pathname());
13853
            if (base_url->has_search()) {
13854
              // get_search() returns "" for an empty query string (URL ends
13855
              // with '?'). update_base_search("") would incorrectly clear the
13856
              // query, so pass "?" to preserve the empty query distinction.
13857
              auto s = base_url->get_search();
13858
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13859
            }
13860
          }
13861
129
          url.update_unencoded_base_hash(*fragment);
13862
129
          return url;
13863
129
        }
13864
        // Otherwise, if base's scheme is not "file", set state to relative
13865
        // state and decrease pointer by 1.
13866
        // NOLINTNEXTLINE(bugprone-branch-clone)
13867
1.44k
        else if (base_url->type != scheme::type::FILE) {
13868
854
          ada_log("NO_SCHEME non-file relative path");
13869
854
          state = state::RELATIVE_SCHEME;
13870
854
        }
13871
        // Otherwise, set state to file state and decrease pointer by 1.
13872
595
        else {
13873
595
          ada_log("NO_SCHEME file base type");
13874
595
          state = state::FILE;
13875
595
        }
13876
1.44k
        break;
13877
20.7k
      }
13878
36.3k
      case state::AUTHORITY: {
13879
36.3k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13880
        // most URLs have no @. Having no @ tells us that we don't have to worry
13881
        // about AUTHORITY. Of course, we could have @ and still not have to
13882
        // worry about AUTHORITY.
13883
        // TODO: Instead of just collecting a bool, collect the location of the
13884
        // '@' and do something useful with it.
13885
        // TODO: We could do various processing early on, using a single pass
13886
        // over the string to collect information about it, e.g., telling us
13887
        // whether there is a @ and if so, where (or how many).
13888
13889
        // Check if url data contains an @.
13890
36.3k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
21.1k
          state = state::HOST;
13892
21.1k
          break;
13893
21.1k
        }
13894
15.2k
        bool at_sign_seen{false};
13895
15.2k
        bool password_token_seen{false};
13896
        /**
13897
         * We expect something of the sort...
13898
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13899
         * --------^
13900
         */
13901
40.2k
        do {
13902
40.2k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
40.2k
          size_t location =
13905
40.2k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
40.2k
                               : helpers::find_authority_delimiter(view);
13907
40.2k
          std::string_view authority_view = view.substr(0, location);
13908
40.2k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
40.2k
          if ((end_of_authority != input_size) &&
13911
39.0k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
25.0k
            if (at_sign_seen) {
13914
9.86k
              if (password_token_seen) {
13915
4.04k
                if constexpr (result_type_is_ada_url) {
13916
4.04k
                  url.password += "%40";
13917
                } else {
13918
                  url.append_base_password("%40");
13919
                }
13920
5.81k
              } else {
13921
5.81k
                if constexpr (result_type_is_ada_url) {
13922
5.81k
                  url.username += "%40";
13923
                } else {
13924
                  url.append_base_username("%40");
13925
                }
13926
5.81k
              }
13927
9.86k
            }
13928
13929
25.0k
            at_sign_seen = true;
13930
13931
25.0k
            if (!password_token_seen) {
13932
20.9k
              size_t password_token_location = authority_view.find(':');
13933
20.9k
              password_token_seen =
13934
20.9k
                  password_token_location != std::string_view::npos;
13935
13936
20.9k
              if constexpr (store_values) {
13937
20.9k
                if (!password_token_seen) {
13938
6.66k
                  if constexpr (result_type_is_ada_url) {
13939
6.66k
                    url.username += unicode::percent_encode(
13940
6.66k
                        authority_view,
13941
6.66k
                        character_sets::USERINFO_PERCENT_ENCODE);
13942
                  } else {
13943
                    url.append_base_username(unicode::percent_encode(
13944
                        authority_view,
13945
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
                  }
13947
14.3k
                } else {
13948
14.3k
                  if constexpr (result_type_is_ada_url) {
13949
14.3k
                    url.username += unicode::percent_encode(
13950
14.3k
                        authority_view.substr(0, password_token_location),
13951
14.3k
                        character_sets::USERINFO_PERCENT_ENCODE);
13952
14.3k
                    url.password += unicode::percent_encode(
13953
14.3k
                        authority_view.substr(password_token_location + 1),
13954
14.3k
                        character_sets::USERINFO_PERCENT_ENCODE);
13955
                  } else {
13956
                    url.append_base_username(unicode::percent_encode(
13957
                        authority_view.substr(0, password_token_location),
13958
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
                    url.append_base_password(unicode::percent_encode(
13960
                        authority_view.substr(password_token_location + 1),
13961
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
                  }
13963
14.3k
                }
13964
20.9k
              }
13965
20.9k
            } else if constexpr (store_values) {
13966
4.04k
              if constexpr (result_type_is_ada_url) {
13967
4.04k
                url.password += unicode::percent_encode(
13968
4.04k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13969
              } else {
13970
                url.append_base_password(unicode::percent_encode(
13971
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
              }
13973
4.04k
            }
13974
25.0k
          }
13975
          // Otherwise, if one of the following is true:
13976
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13977
          // - url is special and c is U+005C (\)
13978
15.2k
          else if (end_of_authority == input_size ||
13979
14.0k
                   url_data[end_of_authority] == '/' ||
13980
168
                   url_data[end_of_authority] == '?' ||
13981
15.2k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13982
            // If atSignSeen is true and authority_view is the empty string,
13983
            // validation error, return failure.
13984
15.2k
            if (at_sign_seen && authority_view.empty()) {
13985
172
              url.is_valid = false;
13986
172
              return url;
13987
172
            }
13988
15.0k
            state = state::HOST;
13989
15.0k
            break;
13990
15.2k
          }
13991
25.0k
          if (end_of_authority == input_size) {
13992
0
            if constexpr (store_values) {
13993
0
              if (fragment.has_value()) {
13994
0
                url.update_unencoded_base_hash(*fragment);
13995
0
              }
13996
0
            }
13997
0
            return url;
13998
0
          }
13999
25.0k
          input_position = end_of_authority + 1;
14000
25.0k
        } while (true);
14001
14002
15.0k
        break;
14003
15.2k
      }
14004
15.0k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
14005
108
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
14006
108
                helpers::substring(url_data, input_position));
14007
14008
        // If c is U+002F (/) and remaining starts with U+002F (/),
14009
        // then set state to special authority ignore slashes state and increase
14010
        // pointer by 1.
14011
108
        if (url_data.substr(input_position, 2) == "//") {
14012
9
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14013
9
          input_position += 2;
14014
99
        } else {
14015
          // Otherwise, validation error, set state to relative state and
14016
          // decrease pointer by 1.
14017
99
          state = state::RELATIVE_SCHEME;
14018
99
        }
14019
14020
108
        break;
14021
15.2k
      }
14022
2.35k
      case state::PATH_OR_AUTHORITY: {
14023
2.35k
        ada_log("PATH_OR_AUTHORITY ",
14024
2.35k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
2.35k
        if ((input_position != input_size) &&
14028
2.21k
            (url_data[input_position] == '/')) {
14029
1.19k
          state = state::AUTHORITY;
14030
1.19k
          input_position++;
14031
1.19k
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
1.15k
          state = state::PATH;
14034
1.15k
        }
14035
14036
2.35k
        break;
14037
15.2k
      }
14038
953
      case state::RELATIVE_SCHEME: {
14039
953
        ada_log("RELATIVE_SCHEME ",
14040
953
                helpers::substring(url_data, input_position));
14041
14042
        // Set url's scheme to base's scheme.
14043
953
        url.copy_scheme(*base_url);
14044
14045
        // If c is U+002F (/), then set state to relative slash state.
14046
953
        if ((input_position != input_size) &&
14047
            // NOLINTNEXTLINE(bugprone-branch-clone)
14048
644
            (url_data[input_position] == '/')) {
14049
120
          ada_log(
14050
120
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
14051
120
              "slash state");
14052
120
          state = state::RELATIVE_SLASH;
14053
833
        } else if (url.is_special() && (input_position != input_size) &&
14054
218
                   (url_data[input_position] == '\\')) {
14055
          // Otherwise, if url is special and c is U+005C (\), validation error,
14056
          // set state to relative slash state.
14057
8
          ada_log(
14058
8
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
14059
8
              "error, set state to relative slash state");
14060
8
          state = state::RELATIVE_SLASH;
14061
825
        } else {
14062
825
          ada_log("RELATIVE_SCHEME otherwise");
14063
          // Set url's username to base's username, url's password to base's
14064
          // password, url's host to base's host, url's port to base's port,
14065
          // url's path to a clone of base's path, and url's query to base's
14066
          // query.
14067
825
          if constexpr (result_type_is_ada_url) {
14068
825
            url.username = base_url->username;
14069
825
            url.password = base_url->password;
14070
825
            url.host = base_url->host;
14071
825
            url.port = base_url->port;
14072
            // cloning the base path includes cloning the has_opaque_path flag
14073
825
            url.has_opaque_path = base_url->has_opaque_path;
14074
825
            url.path = base_url->path;
14075
825
            url.query = base_url->query;
14076
          } else {
14077
            url.update_base_authority(base_url->get_href(),
14078
                                      base_url->get_components());
14079
            url.update_host_to_base_host(base_url->get_hostname());
14080
            url.update_base_port(base_url->retrieve_base_port());
14081
            // cloning the base path includes cloning the has_opaque_path flag
14082
            url.has_opaque_path = base_url->has_opaque_path;
14083
            url.update_base_pathname(base_url->get_pathname());
14084
            if (base_url->has_search()) {
14085
              // get_search() returns "" for an empty query string (URL ends
14086
              // with '?'). update_base_search("") would incorrectly clear the
14087
              // query, so pass "?" to preserve the empty query distinction.
14088
              auto s = base_url->get_search();
14089
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
            }
14091
          }
14092
14093
825
          url.has_opaque_path = base_url->has_opaque_path;
14094
14095
          // If c is U+003F (?), then set url's query to the empty string, and
14096
          // state to query state.
14097
825
          if ((input_position != input_size) &&
14098
516
              (url_data[input_position] == '?')) {
14099
38
            state = state::QUERY;
14100
38
          }
14101
          // Otherwise, if c is not the EOF code point:
14102
787
          else if (input_position != input_size) {
14103
            // Set url's query to null.
14104
478
            url.clear_search();
14105
478
            if constexpr (result_type_is_ada_url) {
14106
              // Shorten url's path.
14107
478
              helpers::shorten_path(url.path, url.type);
14108
            } else {
14109
              std::string_view path = url.get_pathname();
14110
              if (helpers::shorten_path(path, url.type)) {
14111
                url.update_base_pathname(std::move(std::string(path)));
14112
              }
14113
            }
14114
            // Set state to path state and decrease pointer by 1.
14115
478
            state = state::PATH;
14116
478
            break;
14117
478
          }
14118
825
        }
14119
475
        input_position++;
14120
475
        break;
14121
953
      }
14122
128
      case state::RELATIVE_SLASH: {
14123
128
        ada_log("RELATIVE_SLASH ",
14124
128
                helpers::substring(url_data, input_position));
14125
14126
        // If url is special and c is U+002F (/) or U+005C (\), then:
14127
        // NOLINTNEXTLINE(bugprone-branch-clone)
14128
128
        if (url.is_special() && (input_position != input_size) &&
14129
27
            (url_data[input_position] == '/' ||
14130
23
             url_data[input_position] == '\\')) {
14131
          // Set state to special authority ignore slashes state.
14132
7
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14133
7
        }
14134
        // Otherwise, if c is U+002F (/), then set state to authority state.
14135
121
        else if ((input_position != input_size) &&
14136
80
                 (url_data[input_position] == '/')) {
14137
51
          state = state::AUTHORITY;
14138
51
        }
14139
        // Otherwise, set
14140
        // - url's username to base's username,
14141
        // - url's password to base's password,
14142
        // - url's host to base's host,
14143
        // - url's port to base's port,
14144
        // - state to path state, and then, decrease pointer by 1.
14145
70
        else {
14146
70
          if constexpr (result_type_is_ada_url) {
14147
70
            url.username = base_url->username;
14148
70
            url.password = base_url->password;
14149
70
            url.host = base_url->host;
14150
70
            url.port = base_url->port;
14151
          } else {
14152
            url.update_base_authority(base_url->get_href(),
14153
                                      base_url->get_components());
14154
            url.update_host_to_base_host(base_url->get_hostname());
14155
            url.update_base_port(base_url->retrieve_base_port());
14156
          }
14157
70
          state = state::PATH;
14158
70
          break;
14159
70
        }
14160
14161
58
        input_position++;
14162
58
        break;
14163
128
      }
14164
35.0k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
35.0k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
35.0k
                helpers::substring(url_data, input_position));
14167
14168
        // If c is U+002F (/) and remaining starts with U+002F (/),
14169
        // then set state to special authority ignore slashes state and increase
14170
        // pointer by 1.
14171
35.0k
        if (url_data.substr(input_position, 2) == "//") {
14172
27.4k
          input_position += 2;
14173
27.4k
        }
14174
14175
35.0k
        [[fallthrough]];
14176
35.0k
      }
14177
35.1k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
35.1k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
35.1k
                helpers::substring(url_data, input_position));
14180
14181
        // If c is neither U+002F (/) nor U+005C (\), then set state to
14182
        // authority state and decrease pointer by 1.
14183
36.5k
        while ((input_position != input_size) &&
14184
36.4k
               ((url_data[input_position] == '/') ||
14185
35.9k
                (url_data[input_position] == '\\'))) {
14186
1.40k
          input_position++;
14187
1.40k
        }
14188
35.1k
        state = state::AUTHORITY;
14189
14190
35.1k
        break;
14191
35.0k
      }
14192
14.8k
      case state::QUERY: {
14193
14.8k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
14.8k
        if constexpr (store_values) {
14195
          // Let queryPercentEncodeSet be the special-query percent-encode set
14196
          // if url is special; otherwise the query percent-encode set.
14197
14.8k
          const uint8_t* query_percent_encode_set =
14198
14.8k
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
14.8k
                               : character_sets::QUERY_PERCENT_ENCODE;
14200
14201
          // Percent-encode after encoding, with encoding, buffer, and
14202
          // queryPercentEncodeSet, and append the result to url's query.
14203
14.8k
          url.update_base_search(url_data.substr(input_position),
14204
14.8k
                                 query_percent_encode_set);
14205
14.8k
          ada_log("QUERY update_base_search completed ");
14206
14.8k
          if (fragment.has_value()) {
14207
13.9k
            url.update_unencoded_base_hash(*fragment);
14208
13.9k
          }
14209
14.8k
        }
14210
14.8k
        return url;
14211
35.0k
      }
14212
36.1k
      case state::HOST: {
14213
36.1k
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
36.1k
        std::string_view host_view = url_data.substr(input_position);
14216
36.1k
        auto [location, found_colon] =
14217
36.1k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
36.1k
        input_position = (location != std::string_view::npos)
14219
36.1k
                             ? input_position + location
14220
36.1k
                             : input_size;
14221
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14222
        // Note: the 'found_colon' value is true if and only if a colon was
14223
        // encountered while not inside brackets.
14224
36.1k
        if (found_colon) {
14225
          // If buffer is the empty string, validation error, return failure.
14226
          // Let host be the result of host parsing buffer with url is not
14227
          // special.
14228
15.5k
          ada_log("HOST parsing ", host_view);
14229
15.5k
          if (!url.parse_host(host_view)) {
14230
308
            return url;
14231
308
          }
14232
15.2k
          ada_log("HOST parsing results in ", url.get_hostname());
14233
          // Set url's host to host, buffer to the empty string, and state to
14234
          // port state.
14235
15.2k
          state = state::PORT;
14236
15.2k
          input_position++;
14237
15.2k
        }
14238
        // Otherwise, if one of the following is true:
14239
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14240
        // - url is special and c is U+005C (\)
14241
        // The get_host_delimiter_location function either brings us to
14242
        // the colon outside of the bracket, or to one of those characters.
14243
20.6k
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
20.6k
          if (host_view.empty() && url.is_special()) {
14247
102
            url.is_valid = false;
14248
102
            return url;
14249
102
          }
14250
20.5k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
14251
          // Let host be the result of host parsing host_view with url is not
14252
          // special.
14253
20.5k
          if (host_view.empty()) {
14254
139
            url.update_base_hostname("");
14255
20.4k
          } else if (!url.parse_host(host_view)) {
14256
1.66k
            return url;
14257
1.66k
          }
14258
18.8k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
18.8k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
18.8k
          state = state::PATH_START;
14263
18.8k
        }
14264
14265
34.1k
        break;
14266
36.1k
      }
14267
34.1k
      case state::OPAQUE_PATH: {
14268
4.67k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
14269
        // Opaque path, query, and fragment are structurally always valid:
14270
        // the parser would just percent-encode whatever is there. When we
14271
        // are not storing values (can_parse), we can return immediately.
14272
        // We must set has_opaque_path = true before returning so that when
14273
        // this URL is used as an internal base inside can_parse, NO_SCHEME
14274
        // correctly rejects relative inputs against an opaque-path base
14275
        // (e.g. can_parse("", &"W:") must return false).
14276
        if constexpr (!store_values) {
14277
          url.has_opaque_path = true;
14278
          return url;
14279
        }
14280
4.67k
        std::string_view view = url_data.substr(input_position);
14281
        // If c is U+003F (?), then set url's query to the empty string and
14282
        // state to query state.
14283
4.67k
        size_t location = view.find('?');
14284
4.67k
        if (location != std::string_view::npos) {
14285
355
          view.remove_suffix(view.size() - location);
14286
355
          state = state::QUERY;
14287
355
          input_position += location + 1;
14288
4.31k
        } else {
14289
4.31k
          input_position = input_size + 1;
14290
4.31k
        }
14291
4.67k
        url.has_opaque_path = true;
14292
14293
        // This is a really unlikely scenario in real world. We should not seek
14294
        // to optimize it.
14295
4.67k
        if (view.ends_with(' ')) {
14296
137
          std::string modified_view =
14297
137
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
137
          url.update_base_pathname(unicode::percent_encode(
14299
137
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
4.53k
        } else {
14301
4.53k
          url.update_base_pathname(unicode::percent_encode(
14302
4.53k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
4.53k
        }
14304
4.67k
        break;
14305
36.1k
      }
14306
15.2k
      case state::PORT: {
14307
15.2k
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
15.2k
        std::string_view port_view = url_data.substr(input_position);
14309
15.2k
        input_position += url.parse_port(port_view, true);
14310
15.2k
        if (!url.is_valid) {
14311
214
          return url;
14312
214
        }
14313
15.0k
        state = state::PATH_START;
14314
15.0k
        [[fallthrough]];
14315
15.0k
      }
14316
35.0k
      case state::PATH_START: {
14317
35.0k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
14318
        // Path, query, and fragment are structurally always valid: the
14319
        // parser would just percent-encode whatever is there. When we are
14320
        // not storing values (can_parse), we can return immediately since
14321
        // no subsequent state can invalidate the URL.
14322
        if constexpr (!store_values) {
14323
          return url;
14324
        }
14325
14326
        // If url is special, then:
14327
35.0k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
34.2k
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
34.2k
          if (input_position == input_size) {
14334
18.7k
            if constexpr (store_values) {
14335
18.7k
              url.update_base_pathname("/");
14336
18.7k
              if (fragment.has_value()) {
14337
156
                url.update_unencoded_base_hash(*fragment);
14338
156
              }
14339
18.7k
            }
14340
18.7k
            return url;
14341
18.7k
          }
14342
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
14343
          // by 1. We know that (input_position == input_size) is impossible
14344
          // here, because of the previous if-check.
14345
15.4k
          if ((url_data[input_position] != '/') &&
14346
482
              (url_data[input_position] != '\\')) {
14347
405
            break;
14348
405
          }
14349
15.4k
        }
14350
        // Otherwise, if state override is not given and c is U+003F (?),
14351
        // set url's query to the empty string and state to query state.
14352
879
        else if ((input_position != input_size) &&
14353
243
                 (url_data[input_position] == '?')) {
14354
55
          state = state::QUERY;
14355
55
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
824
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
188
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
188
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
188
        }
14366
14367
15.9k
        input_position++;
14368
15.9k
        break;
14369
35.0k
      }
14370
19.0k
      case state::PATH: {
14371
19.0k
        ada_log("PATH ", helpers::substring(url_data, input_position));
14372
        // Path, query, and fragment are structurally always valid: the
14373
        // parser would just percent-encode whatever is there. When we are
14374
        // not storing values (can_parse), we can return immediately since
14375
        // no subsequent state can invalidate the URL.
14376
        if constexpr (!store_values) {
14377
          return url;
14378
        }
14379
19.0k
        std::string_view view = url_data.substr(input_position);
14380
14381
        // Most time, we do not need percent encoding.
14382
        // Furthermore, we can immediately locate the '?'.
14383
19.0k
        size_t locofquestionmark = view.find('?');
14384
19.0k
        if (locofquestionmark != std::string_view::npos) {
14385
14.3k
          state = state::QUERY;
14386
14.3k
          view.remove_suffix(view.size() - locofquestionmark);
14387
14.3k
          input_position += locofquestionmark + 1;
14388
14.3k
        } else {
14389
4.72k
          input_position = input_size + 1;
14390
4.72k
        }
14391
19.0k
        if constexpr (store_values) {
14392
19.0k
          if constexpr (result_type_is_ada_url) {
14393
19.0k
            helpers::parse_prepared_path(view, url.type, url.path);
14394
          } else {
14395
            url.consume_prepared_path(view);
14396
            ADA_ASSERT_TRUE(url.validate());
14397
          }
14398
19.0k
        }
14399
19.0k
        break;
14400
35.0k
      }
14401
1.86k
      case state::FILE_SLASH: {
14402
1.86k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
1.86k
        if ((input_position != input_size) &&
14406
1.75k
            (url_data[input_position] == '/' ||
14407
1.43k
             url_data[input_position] == '\\')) {
14408
1.43k
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
1.43k
          state = state::FILE_HOST;
14411
1.43k
          input_position++;
14412
1.43k
        } else {
14413
426
          ada_log("FILE_SLASH otherwise");
14414
          // If base is non-null and base's scheme is "file", then:
14415
          // Note: it is unsafe to do base_url->scheme unless you know that
14416
          // base_url_has_value() is true.
14417
426
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14418
            // Set url's host to base's host.
14419
167
            if constexpr (result_type_is_ada_url) {
14420
167
              url.host = base_url->host;
14421
            } else {
14422
              url.update_host_to_base_host(base_url->get_host());
14423
            }
14424
            // If the code point substring from pointer to the end of input does
14425
            // not start with a Windows drive letter and base's path[0] is a
14426
            // normalized Windows drive letter, then append base's path[0] to
14427
            // url's path.
14428
167
            if (!base_url->get_pathname().empty()) {
14429
167
              if (!checkers::is_windows_drive_letter(
14430
167
                      url_data.substr(input_position))) {
14431
140
                std::string_view first_base_url_path =
14432
140
                    base_url->get_pathname().substr(1);
14433
140
                size_t loc = first_base_url_path.find('/');
14434
140
                if (loc != std::string_view::npos) {
14435
27
                  helpers::resize(first_base_url_path, loc);
14436
27
                }
14437
140
                if (checkers::is_normalized_windows_drive_letter(
14438
140
                        first_base_url_path)) {
14439
28
                  if constexpr (result_type_is_ada_url) {
14440
28
                    url.path += '/';
14441
28
                    url.path += first_base_url_path;
14442
                  } else {
14443
                    url.append_base_pathname(
14444
                        helpers::concat("/", first_base_url_path));
14445
                  }
14446
28
                }
14447
140
              }
14448
167
            }
14449
167
          }
14450
14451
          // Set state to path state, and decrease pointer by 1.
14452
426
          state = state::PATH;
14453
426
        }
14454
14455
1.86k
        break;
14456
35.0k
      }
14457
1.43k
      case state::FILE_HOST: {
14458
1.43k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
1.43k
        std::string_view view = url_data.substr(input_position);
14460
14461
1.43k
        size_t location = view.find_first_of("/\\?");
14462
1.43k
        std::string_view file_host_buffer = view.substr(
14463
1.43k
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
1.43k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
26
          state = state::PATH;
14467
1.41k
        } else if (file_host_buffer.empty()) {
14468
          // Set url's host to the empty string.
14469
85
          if constexpr (result_type_is_ada_url) {
14470
85
            url.host = "";
14471
          } else {
14472
            url.update_base_hostname("");
14473
          }
14474
          // Set state to path start state.
14475
85
          state = state::PATH_START;
14476
1.32k
        } else {
14477
1.32k
          size_t consumed_bytes = file_host_buffer.size();
14478
1.32k
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
1.32k
          if (!url.parse_host(file_host_buffer)) {
14482
234
            return url;
14483
234
          }
14484
14485
1.09k
          if constexpr (result_type_is_ada_url) {
14486
            // If host is "localhost", then set host to the empty string.
14487
1.09k
            if (url.host.has_value() && url.host.value() == "localhost") {
14488
16
              url.host = "";
14489
16
            }
14490
          } else {
14491
            if (url.get_hostname() == "localhost") {
14492
              url.update_base_hostname("");
14493
            }
14494
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
1.09k
          state = state::PATH_START;
14498
1.09k
        }
14499
14500
1.20k
        break;
14501
1.43k
      }
14502
3.33k
      case state::FILE: {
14503
3.33k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
3.33k
        std::string_view file_view = url_data.substr(input_position);
14505
14506
3.33k
        url.set_protocol_as_file();
14507
3.33k
        if constexpr (result_type_is_ada_url) {
14508
          // Set url's host to the empty string.
14509
3.33k
          url.host = "";
14510
        } else {
14511
          url.update_base_hostname("");
14512
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
3.33k
        if (input_position != input_size &&
14515
2.97k
            (url_data[input_position] == '/' ||
14516
1.86k
             url_data[input_position] == '\\')) {
14517
1.86k
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
1.86k
          state = state::FILE_SLASH;
14520
1.86k
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
1.47k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14523
          // Set url's host to base's host, url's path to a clone of base's
14524
          // path, and url's query to base's query.
14525
407
          ada_log("FILE base non-null");
14526
407
          if constexpr (result_type_is_ada_url) {
14527
407
            url.host = base_url->host;
14528
407
            url.path = base_url->path;
14529
407
            url.query = base_url->query;
14530
          } else {
14531
            url.update_host_to_base_host(base_url->get_hostname());
14532
            url.update_base_pathname(base_url->get_pathname());
14533
            if (base_url->has_search()) {
14534
              // get_search() returns "" for an empty query string (URL ends
14535
              // with '?'). update_base_search("") would incorrectly clear the
14536
              // query, so pass "?" to preserve the empty query distinction.
14537
              auto s = base_url->get_search();
14538
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
            }
14540
          }
14541
407
          url.has_opaque_path = base_url->has_opaque_path;
14542
14543
          // If c is U+003F (?), then set url's query to the empty string and
14544
          // state to query state.
14545
407
          if (input_position != input_size && url_data[input_position] == '?') {
14546
17
            state = state::QUERY;
14547
17
          }
14548
          // Otherwise, if c is not the EOF code point:
14549
390
          else if (input_position != input_size) {
14550
            // Set url's query to null.
14551
199
            url.clear_search();
14552
            // If the code point substring from pointer to the end of input does
14553
            // not start with a Windows drive letter, then shorten url's path.
14554
199
            if (!checkers::is_windows_drive_letter(file_view)) {
14555
164
              if constexpr (result_type_is_ada_url) {
14556
164
                helpers::shorten_path(url.path, url.type);
14557
              } else {
14558
                std::string_view path = url.get_pathname();
14559
                if (helpers::shorten_path(path, url.type)) {
14560
                  url.update_base_pathname(std::move(std::string(path)));
14561
                }
14562
              }
14563
164
            }
14564
            // Otherwise:
14565
35
            else {
14566
              // Set url's path to an empty list.
14567
35
              url.clear_pathname();
14568
35
              url.has_opaque_path = true;
14569
35
            }
14570
14571
            // Set state to path state and decrease pointer by 1.
14572
199
            state = state::PATH;
14573
199
            break;
14574
199
          }
14575
407
        }
14576
        // Otherwise, set state to path state, and decrease pointer by 1.
14577
1.06k
        else {
14578
1.06k
          ada_log("FILE go to path");
14579
1.06k
          state = state::PATH;
14580
1.06k
          break;
14581
1.06k
        }
14582
14583
2.07k
        input_position++;
14584
2.07k
        break;
14585
3.33k
      }
14586
0
      default:
14587
0
        unreachable();
14588
325k
    }
14589
325k
  }
14590
10.1k
  if constexpr (store_values) {
14591
10.1k
    if (fragment.has_value()) {
14592
545
      url.update_unencoded_base_hash(*fragment);
14593
545
    }
14594
10.1k
  }
14595
  // Check the resulting (normalized) URL size against the maximum input length.
14596
  // Normalization (percent-encoding, IDNA, etc.) can expand the URL beyond the
14597
  // original input size.
14598
10.1k
  if constexpr (store_values) {
14599
10.1k
    if (url.is_valid) {
14600
      if constexpr (result_type_is_ada_url_aggregator) {
14601
        if (url.buffer.size() > max_input_length) {
14602
          url.is_valid = false;
14603
        }
14604
10.1k
      } else {
14605
10.1k
        if (url.get_href_size() > max_input_length) {
14606
0
          url.is_valid = false;
14607
0
        }
14608
10.1k
      }
14609
10.1k
    }
14610
10.1k
  }
14611
10.1k
  return url;
14612
65.7k
}
ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
Line
Count
Source
13654
1.36M
                           const result_type* base_url) {
13655
  // We can specialize the implementation per type.
13656
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13657
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13658
  // something else } is free (at runtime). This means that ada::url_aggregator
13659
  // and ada::url **do not have to support the exact same API**.
13660
1.36M
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
1.36M
  constexpr bool result_type_is_ada_url_aggregator =
13662
1.36M
      std::is_same_v<url_aggregator, result_type>;
13663
1.36M
  static_assert(result_type_is_ada_url ||
13664
1.36M
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
1.36M
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
1.36M
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
1.36M
          ")");
13670
13671
1.36M
  state state = state::SCHEME_START;
13672
1.36M
  result_type url{};
13673
13674
1.36M
  const uint32_t max_input_length = ada::get_max_input_length();
13675
13676
  // We refuse to parse URL strings that exceed the maximum input length.
13677
  // By default, this is 4GB but can be configured via
13678
  // ada::set_max_input_length().
13679
1.36M
  if (user_input.size() > max_input_length) [[unlikely]] {
13680
0
    url.is_valid = false;
13681
0
  }
13682
  // Going forward, user_input.size() is in [0,
13683
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13684
  // base, or the optional_url was invalid, we must return.
13685
1.36M
  if (base_url != nullptr) {
13686
567k
    url.is_valid &= base_url->is_valid;
13687
567k
  }
13688
1.36M
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
1.36M
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13692
    // Most of the time, we just need user_input.size().
13693
    // In some instances, we may need a bit more.
13694
    ///////////////////////////
13695
    // This is *very* important. This line should *not* be removed
13696
    // hastily. There are principled reasons why reserve is important
13697
    // for performance. If you have a benchmark with small inputs,
13698
    // it may not matter, but in other instances, it could.
13699
    ////
13700
    // This rounds up to the next power of two.
13701
    // We know that user_input.size() is in [0,
13702
    // std::numeric_limits<uint32_t>::max).
13703
1.36M
    uint32_t reserve_capacity =
13704
1.36M
        (0xFFFFFFFF >>
13705
1.36M
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
1.36M
        1;
13707
1.36M
    url.reserve(reserve_capacity);
13708
1.36M
  }
13709
1.36M
  std::string tmp_buffer;
13710
1.36M
  std::string_view url_data;
13711
1.36M
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
10.0k
    tmp_buffer = user_input;
13713
    // Optimization opportunity: Instead of copying and then pruning, we could
13714
    // just directly build the string from user_input.
13715
10.0k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
10.0k
    url_data = tmp_buffer;
13717
1.35M
  } else [[likely]] {
13718
1.35M
    url_data = user_input;
13719
1.35M
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
1.36M
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
1.36M
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13727
  // We add it last so that an implementation like ada::url_aggregator
13728
  // can append it last to its internal buffer, thus improving performance.
13729
13730
  // Here url_data no longer has its fragment.
13731
  // We are going to access the data from url_data (it is immutable).
13732
  // At any given time, we are pointing at byte 'input_position' in url_data.
13733
  // The input_position variable should range from 0 to input_size.
13734
  // It is illegal to access url_data at input_size.
13735
1.36M
  size_t input_position = 0;
13736
1.36M
  const size_t input_size = url_data.size();
13737
  // Keep running the following state machine by switching on state.
13738
  // If after a run pointer points to the EOF code point, go to the next step.
13739
  // Otherwise, increase pointer by 1 and continue with the state machine.
13740
  // We never decrement input_position.
13741
8.44M
  while (input_position <= input_size) {
13742
8.03M
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
8.03M
            " in state ", ada::to_string(state));
13744
8.03M
    switch (state) {
13745
1.36M
      case state::SCHEME_START: {
13746
1.36M
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13747
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13748
        // state to scheme state.
13749
1.36M
        if ((input_position != input_size) &&
13750
1.34M
            checkers::is_alpha(url_data[input_position])) {
13751
1.30M
          state = state::SCHEME;
13752
1.30M
          input_position++;
13753
1.30M
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
60.5k
          state = state::NO_SCHEME;
13757
60.5k
        }
13758
1.36M
        break;
13759
0
      }
13760
1.30M
      case state::SCHEME: {
13761
1.30M
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13762
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13763
        // append c, lowercased, to buffer.
13764
6.21M
        while ((input_position != input_size) &&
13765
6.21M
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
4.91M
          input_position++;
13767
4.91M
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
1.30M
        if ((input_position != input_size) &&
13770
1.29M
            (url_data[input_position] == ':')) {
13771
1.29M
          ada_log("SCHEME the scheme should be ",
13772
1.29M
                  url_data.substr(0, input_position));
13773
          if constexpr (result_type_is_ada_url) {
13774
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13775
              return url;
13776
            }
13777
1.29M
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
1.29M
            if (!url.parse_scheme_with_colon(
13780
1.29M
                    url_data.substr(0, input_position + 1))) {
13781
0
              return url;
13782
0
            }
13783
1.29M
          }
13784
1.29M
          ada_log("SCHEME the scheme is ", url.get_protocol());
13785
13786
          // If url's scheme is "file", then:
13787
          // NOLINTNEXTLINE(bugprone-branch-clone)
13788
1.29M
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
7.35k
            state = state::FILE;
13791
7.35k
          }
13792
          // Otherwise, if url is special, base is non-null, and base's scheme
13793
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13794
          // != nullptr is false.
13795
1.28M
          else if (url.is_special() && base_url != nullptr &&
13796
547k
                   base_url->type == url.type) {
13797
            // Set state to special relative or authority state.
13798
216k
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13799
216k
          }
13800
          // Otherwise, if url is special, set state to special authority
13801
          // slashes state.
13802
1.07M
          else if (url.is_special()) {
13803
813k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
813k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
257k
          else if (input_position + 1 < input_size &&
13808
253k
                   url_data[input_position + 1] == '/') {
13809
245k
            state = state::PATH_OR_AUTHORITY;
13810
245k
            input_position++;
13811
245k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
12.0k
          else {
13815
12.0k
            state = state::OPAQUE_PATH;
13816
12.0k
          }
13817
1.29M
        }
13818
        // Otherwise, if state override is not given, set buffer to the empty
13819
        // string, state to no scheme state, and start over (from the first code
13820
        // point in input).
13821
6.25k
        else {
13822
6.25k
          state = state::NO_SCHEME;
13823
6.25k
          input_position = 0;
13824
6.25k
          break;
13825
6.25k
        }
13826
1.29M
        input_position++;
13827
1.29M
        break;
13828
1.30M
      }
13829
66.7k
      case state::NO_SCHEME: {
13830
66.7k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13831
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13832
        // validation error, return failure.
13833
66.7k
        if (base_url == nullptr ||
13834
53.2k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
53.2k
          ada_log("NO_SCHEME validation error");
13836
53.2k
          url.is_valid = false;
13837
53.2k
          return url;
13838
53.2k
        }
13839
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13840
        // set url's scheme to base's scheme, url's path to base's path, url's
13841
        // query to base's query, and set state to fragment state.
13842
13.4k
        else if (base_url->has_opaque_path && fragment.has_value() &&
13843
512
                 input_position == input_size) {
13844
232
          ada_log("NO_SCHEME opaque base with fragment");
13845
232
          url.copy_scheme(*base_url);
13846
232
          url.has_opaque_path = base_url->has_opaque_path;
13847
13848
          if constexpr (result_type_is_ada_url) {
13849
            url.path = base_url->path;
13850
            url.query = base_url->query;
13851
232
          } else {
13852
232
            url.update_base_pathname(base_url->get_pathname());
13853
232
            if (base_url->has_search()) {
13854
              // get_search() returns "" for an empty query string (URL ends
13855
              // with '?'). update_base_search("") would incorrectly clear the
13856
              // query, so pass "?" to preserve the empty query distinction.
13857
86
              auto s = base_url->get_search();
13858
86
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13859
86
            }
13860
232
          }
13861
232
          url.update_unencoded_base_hash(*fragment);
13862
232
          return url;
13863
232
        }
13864
        // Otherwise, if base's scheme is not "file", set state to relative
13865
        // state and decrease pointer by 1.
13866
        // NOLINTNEXTLINE(bugprone-branch-clone)
13867
13.2k
        else if (base_url->type != scheme::type::FILE) {
13868
11.6k
          ada_log("NO_SCHEME non-file relative path");
13869
11.6k
          state = state::RELATIVE_SCHEME;
13870
11.6k
        }
13871
        // Otherwise, set state to file state and decrease pointer by 1.
13872
1.61k
        else {
13873
1.61k
          ada_log("NO_SCHEME file base type");
13874
1.61k
          state = state::FILE;
13875
1.61k
        }
13876
13.2k
        break;
13877
66.7k
      }
13878
1.25M
      case state::AUTHORITY: {
13879
1.25M
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13880
        // most URLs have no @. Having no @ tells us that we don't have to worry
13881
        // about AUTHORITY. Of course, we could have @ and still not have to
13882
        // worry about AUTHORITY.
13883
        // TODO: Instead of just collecting a bool, collect the location of the
13884
        // '@' and do something useful with it.
13885
        // TODO: We could do various processing early on, using a single pass
13886
        // over the string to collect information about it, e.g., telling us
13887
        // whether there is a @ and if so, where (or how many).
13888
13889
        // Check if url data contains an @.
13890
1.25M
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
1.19M
          state = state::HOST;
13892
1.19M
          break;
13893
1.19M
        }
13894
60.8k
        bool at_sign_seen{false};
13895
60.8k
        bool password_token_seen{false};
13896
        /**
13897
         * We expect something of the sort...
13898
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13899
         * --------^
13900
         */
13901
161k
        do {
13902
161k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
161k
          size_t location =
13905
161k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
161k
                               : helpers::find_authority_delimiter(view);
13907
161k
          std::string_view authority_view = view.substr(0, location);
13908
161k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
161k
          if ((end_of_authority != input_size) &&
13911
156k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
100k
            if (at_sign_seen) {
13914
52.4k
              if (password_token_seen) {
13915
                if constexpr (result_type_is_ada_url) {
13916
                  url.password += "%40";
13917
20.8k
                } else {
13918
20.8k
                  url.append_base_password("%40");
13919
20.8k
                }
13920
31.6k
              } else {
13921
                if constexpr (result_type_is_ada_url) {
13922
                  url.username += "%40";
13923
31.6k
                } else {
13924
31.6k
                  url.append_base_username("%40");
13925
31.6k
                }
13926
31.6k
              }
13927
52.4k
            }
13928
13929
100k
            at_sign_seen = true;
13930
13931
100k
            if (!password_token_seen) {
13932
79.7k
              size_t password_token_location = authority_view.find(':');
13933
79.7k
              password_token_seen =
13934
79.7k
                  password_token_location != std::string_view::npos;
13935
13936
79.7k
              if constexpr (store_values) {
13937
79.7k
                if (!password_token_seen) {
13938
                  if constexpr (result_type_is_ada_url) {
13939
                    url.username += unicode::percent_encode(
13940
                        authority_view,
13941
                        character_sets::USERINFO_PERCENT_ENCODE);
13942
52.9k
                  } else {
13943
52.9k
                    url.append_base_username(unicode::percent_encode(
13944
52.9k
                        authority_view,
13945
52.9k
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
52.9k
                  }
13947
52.9k
                } else {
13948
                  if constexpr (result_type_is_ada_url) {
13949
                    url.username += unicode::percent_encode(
13950
                        authority_view.substr(0, password_token_location),
13951
                        character_sets::USERINFO_PERCENT_ENCODE);
13952
                    url.password += unicode::percent_encode(
13953
                        authority_view.substr(password_token_location + 1),
13954
                        character_sets::USERINFO_PERCENT_ENCODE);
13955
26.7k
                  } else {
13956
26.7k
                    url.append_base_username(unicode::percent_encode(
13957
26.7k
                        authority_view.substr(0, password_token_location),
13958
26.7k
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
26.7k
                    url.append_base_password(unicode::percent_encode(
13960
26.7k
                        authority_view.substr(password_token_location + 1),
13961
26.7k
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
26.7k
                  }
13963
26.7k
                }
13964
79.7k
              }
13965
79.7k
            } else if constexpr (store_values) {
13966
              if constexpr (result_type_is_ada_url) {
13967
                url.password += unicode::percent_encode(
13968
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13969
20.8k
              } else {
13970
20.8k
                url.append_base_password(unicode::percent_encode(
13971
20.8k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
20.8k
              }
13973
20.8k
            }
13974
100k
          }
13975
          // Otherwise, if one of the following is true:
13976
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13977
          // - url is special and c is U+005C (\)
13978
60.8k
          else if (end_of_authority == input_size ||
13979
55.6k
                   url_data[end_of_authority] == '/' ||
13980
1.32k
                   url_data[end_of_authority] == '?' ||
13981
60.8k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13982
            // If atSignSeen is true and authority_view is the empty string,
13983
            // validation error, return failure.
13984
60.8k
            if (at_sign_seen && authority_view.empty()) {
13985
6.88k
              url.is_valid = false;
13986
6.88k
              return url;
13987
6.88k
            }
13988
54.0k
            state = state::HOST;
13989
54.0k
            break;
13990
60.8k
          }
13991
100k
          if (end_of_authority == input_size) {
13992
0
            if constexpr (store_values) {
13993
0
              if (fragment.has_value()) {
13994
0
                url.update_unencoded_base_hash(*fragment);
13995
0
              }
13996
0
            }
13997
0
            return url;
13998
0
          }
13999
100k
          input_position = end_of_authority + 1;
14000
100k
        } while (true);
14001
14002
54.0k
        break;
14003
60.8k
      }
14004
216k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
14005
216k
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
14006
216k
                helpers::substring(url_data, input_position));
14007
14008
        // If c is U+002F (/) and remaining starts with U+002F (/),
14009
        // then set state to special authority ignore slashes state and increase
14010
        // pointer by 1.
14011
216k
        if (url_data.substr(input_position, 2) == "//") {
14012
216k
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14013
216k
          input_position += 2;
14014
216k
        } else {
14015
          // Otherwise, validation error, set state to relative state and
14016
          // decrease pointer by 1.
14017
232
          state = state::RELATIVE_SCHEME;
14018
232
        }
14019
14020
216k
        break;
14021
60.8k
      }
14022
245k
      case state::PATH_OR_AUTHORITY: {
14023
245k
        ada_log("PATH_OR_AUTHORITY ",
14024
245k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
245k
        if ((input_position != input_size) &&
14028
225k
            (url_data[input_position] == '/')) {
14029
222k
          state = state::AUTHORITY;
14030
222k
          input_position++;
14031
222k
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
23.4k
          state = state::PATH;
14034
23.4k
        }
14035
14036
245k
        break;
14037
60.8k
      }
14038
11.8k
      case state::RELATIVE_SCHEME: {
14039
11.8k
        ada_log("RELATIVE_SCHEME ",
14040
11.8k
                helpers::substring(url_data, input_position));
14041
14042
        // Set url's scheme to base's scheme.
14043
11.8k
        url.copy_scheme(*base_url);
14044
14045
        // If c is U+002F (/), then set state to relative slash state.
14046
11.8k
        if ((input_position != input_size) &&
14047
            // NOLINTNEXTLINE(bugprone-branch-clone)
14048
8.26k
            (url_data[input_position] == '/')) {
14049
1.68k
          ada_log(
14050
1.68k
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
14051
1.68k
              "slash state");
14052
1.68k
          state = state::RELATIVE_SLASH;
14053
10.1k
        } else if (url.is_special() && (input_position != input_size) &&
14054
5.91k
                   (url_data[input_position] == '\\')) {
14055
          // Otherwise, if url is special and c is U+005C (\), validation error,
14056
          // set state to relative slash state.
14057
55
          ada_log(
14058
55
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
14059
55
              "error, set state to relative slash state");
14060
55
          state = state::RELATIVE_SLASH;
14061
10.1k
        } else {
14062
10.1k
          ada_log("RELATIVE_SCHEME otherwise");
14063
          // Set url's username to base's username, url's password to base's
14064
          // password, url's host to base's host, url's port to base's port,
14065
          // url's path to a clone of base's path, and url's query to base's
14066
          // query.
14067
          if constexpr (result_type_is_ada_url) {
14068
            url.username = base_url->username;
14069
            url.password = base_url->password;
14070
            url.host = base_url->host;
14071
            url.port = base_url->port;
14072
            // cloning the base path includes cloning the has_opaque_path flag
14073
            url.has_opaque_path = base_url->has_opaque_path;
14074
            url.path = base_url->path;
14075
            url.query = base_url->query;
14076
10.1k
          } else {
14077
10.1k
            url.update_base_authority(base_url->get_href(),
14078
10.1k
                                      base_url->get_components());
14079
10.1k
            url.update_host_to_base_host(base_url->get_hostname());
14080
10.1k
            url.update_base_port(base_url->retrieve_base_port());
14081
            // cloning the base path includes cloning the has_opaque_path flag
14082
10.1k
            url.has_opaque_path = base_url->has_opaque_path;
14083
10.1k
            url.update_base_pathname(base_url->get_pathname());
14084
10.1k
            if (base_url->has_search()) {
14085
              // get_search() returns "" for an empty query string (URL ends
14086
              // with '?'). update_base_search("") would incorrectly clear the
14087
              // query, so pass "?" to preserve the empty query distinction.
14088
7.41k
              auto s = base_url->get_search();
14089
7.41k
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
7.41k
            }
14091
10.1k
          }
14092
14093
10.1k
          url.has_opaque_path = base_url->has_opaque_path;
14094
14095
          // If c is U+003F (?), then set url's query to the empty string, and
14096
          // state to query state.
14097
10.1k
          if ((input_position != input_size) &&
14098
6.52k
              (url_data[input_position] == '?')) {
14099
145
            state = state::QUERY;
14100
145
          }
14101
          // Otherwise, if c is not the EOF code point:
14102
9.98k
          else if (input_position != input_size) {
14103
            // Set url's query to null.
14104
6.37k
            url.clear_search();
14105
            if constexpr (result_type_is_ada_url) {
14106
              // Shorten url's path.
14107
              helpers::shorten_path(url.path, url.type);
14108
6.37k
            } else {
14109
6.37k
              std::string_view path = url.get_pathname();
14110
6.37k
              if (helpers::shorten_path(path, url.type)) {
14111
6.11k
                url.update_base_pathname(std::move(std::string(path)));
14112
6.11k
              }
14113
6.37k
            }
14114
            // Set state to path state and decrease pointer by 1.
14115
6.37k
            state = state::PATH;
14116
6.37k
            break;
14117
6.37k
          }
14118
10.1k
        }
14119
5.49k
        input_position++;
14120
5.49k
        break;
14121
11.8k
      }
14122
1.73k
      case state::RELATIVE_SLASH: {
14123
1.73k
        ada_log("RELATIVE_SLASH ",
14124
1.73k
                helpers::substring(url_data, input_position));
14125
14126
        // If url is special and c is U+002F (/) or U+005C (\), then:
14127
        // NOLINTNEXTLINE(bugprone-branch-clone)
14128
1.73k
        if (url.is_special() && (input_position != input_size) &&
14129
1.41k
            (url_data[input_position] == '/' ||
14130
737
             url_data[input_position] == '\\')) {
14131
          // Set state to special authority ignore slashes state.
14132
737
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14133
737
        }
14134
        // Otherwise, if c is U+002F (/), then set state to authority state.
14135
1.00k
        else if ((input_position != input_size) &&
14136
792
                 (url_data[input_position] == '/')) {
14137
92
          state = state::AUTHORITY;
14138
92
        }
14139
        // Otherwise, set
14140
        // - url's username to base's username,
14141
        // - url's password to base's password,
14142
        // - url's host to base's host,
14143
        // - url's port to base's port,
14144
        // - state to path state, and then, decrease pointer by 1.
14145
910
        else {
14146
          if constexpr (result_type_is_ada_url) {
14147
            url.username = base_url->username;
14148
            url.password = base_url->password;
14149
            url.host = base_url->host;
14150
            url.port = base_url->port;
14151
910
          } else {
14152
910
            url.update_base_authority(base_url->get_href(),
14153
910
                                      base_url->get_components());
14154
910
            url.update_host_to_base_host(base_url->get_hostname());
14155
910
            url.update_base_port(base_url->retrieve_base_port());
14156
910
          }
14157
910
          state = state::PATH;
14158
910
          break;
14159
910
        }
14160
14161
829
        input_position++;
14162
829
        break;
14163
1.73k
      }
14164
813k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
813k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
813k
                helpers::substring(url_data, input_position));
14167
14168
        // If c is U+002F (/) and remaining starts with U+002F (/),
14169
        // then set state to special authority ignore slashes state and increase
14170
        // pointer by 1.
14171
813k
        if (url_data.substr(input_position, 2) == "//") {
14172
795k
          input_position += 2;
14173
795k
        }
14174
14175
813k
        [[fallthrough]];
14176
813k
      }
14177
1.03M
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
1.03M
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
1.03M
                helpers::substring(url_data, input_position));
14180
14181
        // If c is neither U+002F (/) nor U+005C (\), then set state to
14182
        // authority state and decrease pointer by 1.
14183
1.44M
        while ((input_position != input_size) &&
14184
1.04M
               ((url_data[input_position] == '/') ||
14185
645k
                (url_data[input_position] == '\\'))) {
14186
409k
          input_position++;
14187
409k
        }
14188
1.03M
        state = state::AUTHORITY;
14189
14190
1.03M
        break;
14191
813k
      }
14192
63.5k
      case state::QUERY: {
14193
63.5k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
63.5k
        if constexpr (store_values) {
14195
          // Let queryPercentEncodeSet be the special-query percent-encode set
14196
          // if url is special; otherwise the query percent-encode set.
14197
63.5k
          const uint8_t* query_percent_encode_set =
14198
63.5k
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
63.5k
                               : character_sets::QUERY_PERCENT_ENCODE;
14200
14201
          // Percent-encode after encoding, with encoding, buffer, and
14202
          // queryPercentEncodeSet, and append the result to url's query.
14203
63.5k
          url.update_base_search(url_data.substr(input_position),
14204
63.5k
                                 query_percent_encode_set);
14205
63.5k
          ada_log("QUERY update_base_search completed ");
14206
63.5k
          if (fragment.has_value()) {
14207
31.5k
            url.update_unencoded_base_hash(*fragment);
14208
31.5k
          }
14209
63.5k
        }
14210
63.5k
        return url;
14211
813k
      }
14212
1.24M
      case state::HOST: {
14213
1.24M
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
1.24M
        std::string_view host_view = url_data.substr(input_position);
14216
1.24M
        auto [location, found_colon] =
14217
1.24M
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
1.24M
        input_position = (location != std::string_view::npos)
14219
1.24M
                             ? input_position + location
14220
1.24M
                             : input_size;
14221
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14222
        // Note: the 'found_colon' value is true if and only if a colon was
14223
        // encountered while not inside brackets.
14224
1.24M
        if (found_colon) {
14225
          // If buffer is the empty string, validation error, return failure.
14226
          // Let host be the result of host parsing buffer with url is not
14227
          // special.
14228
42.3k
          ada_log("HOST parsing ", host_view);
14229
42.3k
          if (!url.parse_host(host_view)) {
14230
4.99k
            return url;
14231
4.99k
          }
14232
37.3k
          ada_log("HOST parsing results in ", url.get_hostname());
14233
          // Set url's host to host, buffer to the empty string, and state to
14234
          // port state.
14235
37.3k
          state = state::PORT;
14236
37.3k
          input_position++;
14237
37.3k
        }
14238
        // Otherwise, if one of the following is true:
14239
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14240
        // - url is special and c is U+005C (\)
14241
        // The get_host_delimiter_location function either brings us to
14242
        // the colon outside of the bracket, or to one of those characters.
14243
1.20M
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
1.20M
          if (host_view.empty() && url.is_special()) {
14247
395k
            url.is_valid = false;
14248
395k
            return url;
14249
395k
          }
14250
808k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
14251
          // Let host be the result of host parsing host_view with url is not
14252
          // special.
14253
808k
          if (host_view.empty()) {
14254
442
            url.update_base_hostname("");
14255
808k
          } else if (!url.parse_host(host_view)) {
14256
100k
            return url;
14257
100k
          }
14258
708k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
708k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
708k
          state = state::PATH_START;
14263
708k
        }
14264
14265
745k
        break;
14266
1.24M
      }
14267
745k
      case state::OPAQUE_PATH: {
14268
12.0k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
14269
        // Opaque path, query, and fragment are structurally always valid:
14270
        // the parser would just percent-encode whatever is there. When we
14271
        // are not storing values (can_parse), we can return immediately.
14272
        // We must set has_opaque_path = true before returning so that when
14273
        // this URL is used as an internal base inside can_parse, NO_SCHEME
14274
        // correctly rejects relative inputs against an opaque-path base
14275
        // (e.g. can_parse("", &"W:") must return false).
14276
        if constexpr (!store_values) {
14277
          url.has_opaque_path = true;
14278
          return url;
14279
        }
14280
12.0k
        std::string_view view = url_data.substr(input_position);
14281
        // If c is U+003F (?), then set url's query to the empty string and
14282
        // state to query state.
14283
12.0k
        size_t location = view.find('?');
14284
12.0k
        if (location != std::string_view::npos) {
14285
723
          view.remove_suffix(view.size() - location);
14286
723
          state = state::QUERY;
14287
723
          input_position += location + 1;
14288
11.3k
        } else {
14289
11.3k
          input_position = input_size + 1;
14290
11.3k
        }
14291
12.0k
        url.has_opaque_path = true;
14292
14293
        // This is a really unlikely scenario in real world. We should not seek
14294
        // to optimize it.
14295
12.0k
        if (view.ends_with(' ')) {
14296
255
          std::string modified_view =
14297
255
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
255
          url.update_base_pathname(unicode::percent_encode(
14299
255
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
11.7k
        } else {
14301
11.7k
          url.update_base_pathname(unicode::percent_encode(
14302
11.7k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
11.7k
        }
14304
12.0k
        break;
14305
1.24M
      }
14306
37.3k
      case state::PORT: {
14307
37.3k
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
37.3k
        std::string_view port_view = url_data.substr(input_position);
14309
37.3k
        input_position += url.parse_port(port_view, true);
14310
37.3k
        if (!url.is_valid) {
14311
4.07k
          return url;
14312
4.07k
        }
14313
33.2k
        state = state::PATH_START;
14314
33.2k
        [[fallthrough]];
14315
33.2k
      }
14316
744k
      case state::PATH_START: {
14317
744k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
14318
        // Path, query, and fragment are structurally always valid: the
14319
        // parser would just percent-encode whatever is there. When we are
14320
        // not storing values (can_parse), we can return immediately since
14321
        // no subsequent state can invalidate the URL.
14322
        if constexpr (!store_values) {
14323
          return url;
14324
        }
14325
14326
        // If url is special, then:
14327
744k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
523k
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
523k
          if (input_position == input_size) {
14334
323k
            if constexpr (store_values) {
14335
323k
              url.update_base_pathname("/");
14336
323k
              if (fragment.has_value()) {
14337
6.03k
                url.update_unencoded_base_hash(*fragment);
14338
6.03k
              }
14339
323k
            }
14340
323k
            return url;
14341
323k
          }
14342
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
14343
          // by 1. We know that (input_position == input_size) is impossible
14344
          // here, because of the previous if-check.
14345
200k
          if ((url_data[input_position] != '/') &&
14346
12.5k
              (url_data[input_position] != '\\')) {
14347
9.86k
            break;
14348
9.86k
          }
14349
200k
        }
14350
        // Otherwise, if state override is not given and c is U+003F (?),
14351
        // set url's query to the empty string and state to query state.
14352
221k
        else if ((input_position != input_size) &&
14353
219k
                 (url_data[input_position] == '?')) {
14354
142
          state = state::QUERY;
14355
142
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
221k
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
219k
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
219k
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
219k
        }
14366
14367
411k
        input_position++;
14368
411k
        break;
14369
744k
      }
14370
454k
      case state::PATH: {
14371
454k
        ada_log("PATH ", helpers::substring(url_data, input_position));
14372
        // Path, query, and fragment are structurally always valid: the
14373
        // parser would just percent-encode whatever is there. When we are
14374
        // not storing values (can_parse), we can return immediately since
14375
        // no subsequent state can invalidate the URL.
14376
        if constexpr (!store_values) {
14377
          return url;
14378
        }
14379
454k
        std::string_view view = url_data.substr(input_position);
14380
14381
        // Most time, we do not need percent encoding.
14382
        // Furthermore, we can immediately locate the '?'.
14383
454k
        size_t locofquestionmark = view.find('?');
14384
454k
        if (locofquestionmark != std::string_view::npos) {
14385
62.5k
          state = state::QUERY;
14386
62.5k
          view.remove_suffix(view.size() - locofquestionmark);
14387
62.5k
          input_position += locofquestionmark + 1;
14388
391k
        } else {
14389
391k
          input_position = input_size + 1;
14390
391k
        }
14391
454k
        if constexpr (store_values) {
14392
          if constexpr (result_type_is_ada_url) {
14393
            helpers::parse_prepared_path(view, url.type, url.path);
14394
454k
          } else {
14395
454k
            url.consume_prepared_path(view);
14396
454k
            ADA_ASSERT_TRUE(url.validate());
14397
454k
          }
14398
454k
        }
14399
454k
        break;
14400
744k
      }
14401
5.02k
      case state::FILE_SLASH: {
14402
5.02k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
5.02k
        if ((input_position != input_size) &&
14406
4.76k
            (url_data[input_position] == '/' ||
14407
4.20k
             url_data[input_position] == '\\')) {
14408
4.20k
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
4.20k
          state = state::FILE_HOST;
14411
4.20k
          input_position++;
14412
4.20k
        } else {
14413
821
          ada_log("FILE_SLASH otherwise");
14414
          // If base is non-null and base's scheme is "file", then:
14415
          // Note: it is unsafe to do base_url->scheme unless you know that
14416
          // base_url_has_value() is true.
14417
821
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14418
            // Set url's host to base's host.
14419
            if constexpr (result_type_is_ada_url) {
14420
              url.host = base_url->host;
14421
321
            } else {
14422
321
              url.update_host_to_base_host(base_url->get_host());
14423
321
            }
14424
            // If the code point substring from pointer to the end of input does
14425
            // not start with a Windows drive letter and base's path[0] is a
14426
            // normalized Windows drive letter, then append base's path[0] to
14427
            // url's path.
14428
321
            if (!base_url->get_pathname().empty()) {
14429
321
              if (!checkers::is_windows_drive_letter(
14430
321
                      url_data.substr(input_position))) {
14431
267
                std::string_view first_base_url_path =
14432
267
                    base_url->get_pathname().substr(1);
14433
267
                size_t loc = first_base_url_path.find('/');
14434
267
                if (loc != std::string_view::npos) {
14435
63
                  helpers::resize(first_base_url_path, loc);
14436
63
                }
14437
267
                if (checkers::is_normalized_windows_drive_letter(
14438
267
                        first_base_url_path)) {
14439
                  if constexpr (result_type_is_ada_url) {
14440
                    url.path += '/';
14441
                    url.path += first_base_url_path;
14442
54
                  } else {
14443
54
                    url.append_base_pathname(
14444
54
                        helpers::concat("/", first_base_url_path));
14445
54
                  }
14446
54
                }
14447
267
              }
14448
321
            }
14449
321
          }
14450
14451
          // Set state to path state, and decrease pointer by 1.
14452
821
          state = state::PATH;
14453
821
        }
14454
14455
5.02k
        break;
14456
744k
      }
14457
4.20k
      case state::FILE_HOST: {
14458
4.20k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
4.20k
        std::string_view view = url_data.substr(input_position);
14460
14461
4.20k
        size_t location = view.find_first_of("/\\?");
14462
4.20k
        std::string_view file_host_buffer = view.substr(
14463
4.20k
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
4.20k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
38
          state = state::PATH;
14467
4.16k
        } else if (file_host_buffer.empty()) {
14468
          // Set url's host to the empty string.
14469
          if constexpr (result_type_is_ada_url) {
14470
            url.host = "";
14471
1.25k
          } else {
14472
1.25k
            url.update_base_hostname("");
14473
1.25k
          }
14474
          // Set state to path start state.
14475
1.25k
          state = state::PATH_START;
14476
2.91k
        } else {
14477
2.91k
          size_t consumed_bytes = file_host_buffer.size();
14478
2.91k
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
2.91k
          if (!url.parse_host(file_host_buffer)) {
14482
522
            return url;
14483
522
          }
14484
14485
          if constexpr (result_type_is_ada_url) {
14486
            // If host is "localhost", then set host to the empty string.
14487
            if (url.host.has_value() && url.host.value() == "localhost") {
14488
              url.host = "";
14489
            }
14490
2.39k
          } else {
14491
2.39k
            if (url.get_hostname() == "localhost") {
14492
24
              url.update_base_hostname("");
14493
24
            }
14494
2.39k
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
2.39k
          state = state::PATH_START;
14498
2.39k
        }
14499
14500
3.68k
        break;
14501
4.20k
      }
14502
8.97k
      case state::FILE: {
14503
8.97k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
8.97k
        std::string_view file_view = url_data.substr(input_position);
14505
14506
8.97k
        url.set_protocol_as_file();
14507
        if constexpr (result_type_is_ada_url) {
14508
          // Set url's host to the empty string.
14509
          url.host = "";
14510
8.97k
        } else {
14511
8.97k
          url.update_base_hostname("");
14512
8.97k
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
8.97k
        if (input_position != input_size &&
14515
7.65k
            (url_data[input_position] == '/' ||
14516
5.02k
             url_data[input_position] == '\\')) {
14517
5.02k
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
5.02k
          state = state::FILE_SLASH;
14520
5.02k
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
3.94k
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14523
          // Set url's host to base's host, url's path to a clone of base's
14524
          // path, and url's query to base's query.
14525
1.24k
          ada_log("FILE base non-null");
14526
          if constexpr (result_type_is_ada_url) {
14527
            url.host = base_url->host;
14528
            url.path = base_url->path;
14529
            url.query = base_url->query;
14530
1.24k
          } else {
14531
1.24k
            url.update_host_to_base_host(base_url->get_hostname());
14532
1.24k
            url.update_base_pathname(base_url->get_pathname());
14533
1.24k
            if (base_url->has_search()) {
14534
              // get_search() returns "" for an empty query string (URL ends
14535
              // with '?'). update_base_search("") would incorrectly clear the
14536
              // query, so pass "?" to preserve the empty query distinction.
14537
151
              auto s = base_url->get_search();
14538
151
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
151
            }
14540
1.24k
          }
14541
1.24k
          url.has_opaque_path = base_url->has_opaque_path;
14542
14543
          // If c is U+003F (?), then set url's query to the empty string and
14544
          // state to query state.
14545
1.24k
          if (input_position != input_size && url_data[input_position] == '?') {
14546
32
            state = state::QUERY;
14547
32
          }
14548
          // Otherwise, if c is not the EOF code point:
14549
1.21k
          else if (input_position != input_size) {
14550
            // Set url's query to null.
14551
400
            url.clear_search();
14552
            // If the code point substring from pointer to the end of input does
14553
            // not start with a Windows drive letter, then shorten url's path.
14554
400
            if (!checkers::is_windows_drive_letter(file_view)) {
14555
              if constexpr (result_type_is_ada_url) {
14556
                helpers::shorten_path(url.path, url.type);
14557
332
              } else {
14558
332
                std::string_view path = url.get_pathname();
14559
332
                if (helpers::shorten_path(path, url.type)) {
14560
319
                  url.update_base_pathname(std::move(std::string(path)));
14561
319
                }
14562
332
              }
14563
332
            }
14564
            // Otherwise:
14565
68
            else {
14566
              // Set url's path to an empty list.
14567
68
              url.clear_pathname();
14568
68
              url.has_opaque_path = true;
14569
68
            }
14570
14571
            // Set state to path state and decrease pointer by 1.
14572
400
            state = state::PATH;
14573
400
            break;
14574
400
          }
14575
1.24k
        }
14576
        // Otherwise, set state to path state, and decrease pointer by 1.
14577
2.69k
        else {
14578
2.69k
          ada_log("FILE go to path");
14579
2.69k
          state = state::PATH;
14580
2.69k
          break;
14581
2.69k
        }
14582
14583
5.87k
        input_position++;
14584
5.87k
        break;
14585
8.97k
      }
14586
0
      default:
14587
0
        unreachable();
14588
8.03M
    }
14589
8.03M
  }
14590
409k
  if constexpr (store_values) {
14591
409k
    if (fragment.has_value()) {
14592
6.02k
      url.update_unencoded_base_hash(*fragment);
14593
6.02k
    }
14594
409k
  }
14595
  // Check the resulting (normalized) URL size against the maximum input length.
14596
  // Normalization (percent-encoding, IDNA, etc.) can expand the URL beyond the
14597
  // original input size.
14598
409k
  if constexpr (store_values) {
14599
409k
    if (url.is_valid) {
14600
409k
      if constexpr (result_type_is_ada_url_aggregator) {
14601
409k
        if (url.buffer.size() > max_input_length) {
14602
0
          url.is_valid = false;
14603
0
        }
14604
      } else {
14605
        if (url.get_href_size() > max_input_length) {
14606
          url.is_valid = false;
14607
        }
14608
      }
14609
409k
    }
14610
409k
  }
14611
409k
  return url;
14612
1.36M
}
ada::url_aggregator ada::parser::parse_url_impl<ada::url_aggregator, false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
Line
Count
Source
13654
17.5k
                           const result_type* base_url) {
13655
  // We can specialize the implementation per type.
13656
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
13657
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
13658
  // something else } is free (at runtime). This means that ada::url_aggregator
13659
  // and ada::url **do not have to support the exact same API**.
13660
17.5k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
17.5k
  constexpr bool result_type_is_ada_url_aggregator =
13662
17.5k
      std::is_same_v<url_aggregator, result_type>;
13663
17.5k
  static_assert(result_type_is_ada_url ||
13664
17.5k
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
17.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
17.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
17.5k
          ")");
13670
13671
17.5k
  state state = state::SCHEME_START;
13672
17.5k
  result_type url{};
13673
13674
17.5k
  const uint32_t max_input_length = ada::get_max_input_length();
13675
13676
  // We refuse to parse URL strings that exceed the maximum input length.
13677
  // By default, this is 4GB but can be configured via
13678
  // ada::set_max_input_length().
13679
17.5k
  if (user_input.size() > max_input_length) [[unlikely]] {
13680
0
    url.is_valid = false;
13681
0
  }
13682
  // Going forward, user_input.size() is in [0,
13683
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
13684
  // base, or the optional_url was invalid, we must return.
13685
17.5k
  if (base_url != nullptr) {
13686
799
    url.is_valid &= base_url->is_valid;
13687
799
  }
13688
17.5k
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
13692
    // Most of the time, we just need user_input.size().
13693
    // In some instances, we may need a bit more.
13694
    ///////////////////////////
13695
    // This is *very* important. This line should *not* be removed
13696
    // hastily. There are principled reasons why reserve is important
13697
    // for performance. If you have a benchmark with small inputs,
13698
    // it may not matter, but in other instances, it could.
13699
    ////
13700
    // This rounds up to the next power of two.
13701
    // We know that user_input.size() is in [0,
13702
    // std::numeric_limits<uint32_t>::max).
13703
    uint32_t reserve_capacity =
13704
        (0xFFFFFFFF >>
13705
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
        1;
13707
    url.reserve(reserve_capacity);
13708
  }
13709
17.5k
  std::string tmp_buffer;
13710
17.5k
  std::string_view url_data;
13711
17.5k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
418
    tmp_buffer = user_input;
13713
    // Optimization opportunity: Instead of copying and then pruning, we could
13714
    // just directly build the string from user_input.
13715
418
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
418
    url_data = tmp_buffer;
13717
17.1k
  } else [[likely]] {
13718
17.1k
    url_data = user_input;
13719
17.1k
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
17.5k
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
17.5k
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
13727
  // We add it last so that an implementation like ada::url_aggregator
13728
  // can append it last to its internal buffer, thus improving performance.
13729
13730
  // Here url_data no longer has its fragment.
13731
  // We are going to access the data from url_data (it is immutable).
13732
  // At any given time, we are pointing at byte 'input_position' in url_data.
13733
  // The input_position variable should range from 0 to input_size.
13734
  // It is illegal to access url_data at input_size.
13735
17.5k
  size_t input_position = 0;
13736
17.5k
  const size_t input_size = url_data.size();
13737
  // Keep running the following state machine by switching on state.
13738
  // If after a run pointer points to the EOF code point, go to the next step.
13739
  // Otherwise, increase pointer by 1 and continue with the state machine.
13740
  // We never decrement input_position.
13741
61.0k
  while (input_position <= input_size) {
13742
60.8k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
60.8k
            " in state ", ada::to_string(state));
13744
60.8k
    switch (state) {
13745
17.5k
      case state::SCHEME_START: {
13746
17.5k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13747
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13748
        // state to scheme state.
13749
17.5k
        if ((input_position != input_size) &&
13750
17.2k
            checkers::is_alpha(url_data[input_position])) {
13751
10.8k
          state = state::SCHEME;
13752
10.8k
          input_position++;
13753
10.8k
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
6.75k
          state = state::NO_SCHEME;
13757
6.75k
        }
13758
17.5k
        break;
13759
0
      }
13760
10.8k
      case state::SCHEME: {
13761
10.8k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13762
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13763
        // append c, lowercased, to buffer.
13764
76.2k
        while ((input_position != input_size) &&
13765
74.5k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
65.4k
          input_position++;
13767
65.4k
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
10.8k
        if ((input_position != input_size) &&
13770
9.05k
            (url_data[input_position] == ':')) {
13771
8.57k
          ada_log("SCHEME the scheme should be ",
13772
8.57k
                  url_data.substr(0, input_position));
13773
          if constexpr (result_type_is_ada_url) {
13774
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13775
              return url;
13776
            }
13777
8.57k
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
8.57k
            if (!url.parse_scheme_with_colon(
13780
8.57k
                    url_data.substr(0, input_position + 1))) {
13781
0
              return url;
13782
0
            }
13783
8.57k
          }
13784
8.57k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13785
13786
          // If url's scheme is "file", then:
13787
          // NOLINTNEXTLINE(bugprone-branch-clone)
13788
8.57k
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
975
            state = state::FILE;
13791
975
          }
13792
          // Otherwise, if url is special, base is non-null, and base's scheme
13793
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13794
          // != nullptr is false.
13795
7.60k
          else if (url.is_special() && base_url != nullptr &&
13796
157
                   base_url->type == url.type) {
13797
            // Set state to special relative or authority state.
13798
2
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13799
2
          }
13800
          // Otherwise, if url is special, set state to special authority
13801
          // slashes state.
13802
7.60k
          else if (url.is_special()) {
13803
4.65k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
4.65k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
2.95k
          else if (input_position + 1 < input_size &&
13808
2.33k
                   url_data[input_position + 1] == '/') {
13809
1.10k
            state = state::PATH_OR_AUTHORITY;
13810
1.10k
            input_position++;
13811
1.10k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
1.84k
          else {
13815
1.84k
            state = state::OPAQUE_PATH;
13816
1.84k
          }
13817
8.57k
        }
13818
        // Otherwise, if state override is not given, set buffer to the empty
13819
        // string, state to no scheme state, and start over (from the first code
13820
        // point in input).
13821
2.23k
        else {
13822
2.23k
          state = state::NO_SCHEME;
13823
2.23k
          input_position = 0;
13824
2.23k
          break;
13825
2.23k
        }
13826
8.57k
        input_position++;
13827
8.57k
        break;
13828
10.8k
      }
13829
8.99k
      case state::NO_SCHEME: {
13830
8.99k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13831
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13832
        // validation error, return failure.
13833
8.99k
        if (base_url == nullptr ||
13834
8.81k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
8.81k
          ada_log("NO_SCHEME validation error");
13836
8.81k
          url.is_valid = false;
13837
8.81k
          return url;
13838
8.81k
        }
13839
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13840
        // set url's scheme to base's scheme, url's path to base's path, url's
13841
        // query to base's query, and set state to fragment state.
13842
177
        else if (base_url->has_opaque_path && fragment.has_value() &&
13843
0
                 input_position == input_size) {
13844
0
          ada_log("NO_SCHEME opaque base with fragment");
13845
0
          url.copy_scheme(*base_url);
13846
0
          url.has_opaque_path = base_url->has_opaque_path;
13847
13848
          if constexpr (result_type_is_ada_url) {
13849
            url.path = base_url->path;
13850
            url.query = base_url->query;
13851
0
          } else {
13852
0
            url.update_base_pathname(base_url->get_pathname());
13853
0
            if (base_url->has_search()) {
13854
              // get_search() returns "" for an empty query string (URL ends
13855
              // with '?'). update_base_search("") would incorrectly clear the
13856
              // query, so pass "?" to preserve the empty query distinction.
13857
0
              auto s = base_url->get_search();
13858
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13859
0
            }
13860
0
          }
13861
0
          url.update_unencoded_base_hash(*fragment);
13862
0
          return url;
13863
0
        }
13864
        // Otherwise, if base's scheme is not "file", set state to relative
13865
        // state and decrease pointer by 1.
13866
        // NOLINTNEXTLINE(bugprone-branch-clone)
13867
177
        else if (base_url->type != scheme::type::FILE) {
13868
174
          ada_log("NO_SCHEME non-file relative path");
13869
174
          state = state::RELATIVE_SCHEME;
13870
174
        }
13871
        // Otherwise, set state to file state and decrease pointer by 1.
13872
3
        else {
13873
3
          ada_log("NO_SCHEME file base type");
13874
3
          state = state::FILE;
13875
3
        }
13876
177
        break;
13877
8.99k
      }
13878
5.10k
      case state::AUTHORITY: {
13879
5.10k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13880
        // most URLs have no @. Having no @ tells us that we don't have to worry
13881
        // about AUTHORITY. Of course, we could have @ and still not have to
13882
        // worry about AUTHORITY.
13883
        // TODO: Instead of just collecting a bool, collect the location of the
13884
        // '@' and do something useful with it.
13885
        // TODO: We could do various processing early on, using a single pass
13886
        // over the string to collect information about it, e.g., telling us
13887
        // whether there is a @ and if so, where (or how many).
13888
13889
        // Check if url data contains an @.
13890
5.10k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
4.83k
          state = state::HOST;
13892
4.83k
          break;
13893
4.83k
        }
13894
272
        bool at_sign_seen{false};
13895
272
        bool password_token_seen{false};
13896
        /**
13897
         * We expect something of the sort...
13898
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13899
         * --------^
13900
         */
13901
2.97k
        do {
13902
2.97k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
2.97k
          size_t location =
13905
2.97k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
2.97k
                               : helpers::find_authority_delimiter(view);
13907
2.97k
          std::string_view authority_view = view.substr(0, location);
13908
2.97k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
2.97k
          if ((end_of_authority != input_size) &&
13911
2.72k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
2.69k
            if (at_sign_seen) {
13914
2.43k
              if (password_token_seen) {
13915
                if constexpr (result_type_is_ada_url) {
13916
                  url.password += "%40";
13917
897
                } else {
13918
897
                  url.append_base_password("%40");
13919
897
                }
13920
1.54k
              } else {
13921
                if constexpr (result_type_is_ada_url) {
13922
                  url.username += "%40";
13923
1.54k
                } else {
13924
1.54k
                  url.append_base_username("%40");
13925
1.54k
                }
13926
1.54k
              }
13927
2.43k
            }
13928
13929
2.69k
            at_sign_seen = true;
13930
13931
2.69k
            if (!password_token_seen) {
13932
1.80k
              size_t password_token_location = authority_view.find(':');
13933
1.80k
              password_token_seen =
13934
1.80k
                  password_token_location != std::string_view::npos;
13935
13936
              if constexpr (store_values) {
13937
                if (!password_token_seen) {
13938
                  if constexpr (result_type_is_ada_url) {
13939
                    url.username += unicode::percent_encode(
13940
                        authority_view,
13941
                        character_sets::USERINFO_PERCENT_ENCODE);
13942
                  } else {
13943
                    url.append_base_username(unicode::percent_encode(
13944
                        authority_view,
13945
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
                  }
13947
                } else {
13948
                  if constexpr (result_type_is_ada_url) {
13949
                    url.username += unicode::percent_encode(
13950
                        authority_view.substr(0, password_token_location),
13951
                        character_sets::USERINFO_PERCENT_ENCODE);
13952
                    url.password += unicode::percent_encode(
13953
                        authority_view.substr(password_token_location + 1),
13954
                        character_sets::USERINFO_PERCENT_ENCODE);
13955
                  } else {
13956
                    url.append_base_username(unicode::percent_encode(
13957
                        authority_view.substr(0, password_token_location),
13958
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
                    url.append_base_password(unicode::percent_encode(
13960
                        authority_view.substr(password_token_location + 1),
13961
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
                  }
13963
                }
13964
              }
13965
1.80k
            } else if constexpr (store_values) {
13966
897
              if constexpr (result_type_is_ada_url) {
13967
897
                url.password += unicode::percent_encode(
13968
897
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13969
897
              } else {
13970
897
                url.append_base_password(unicode::percent_encode(
13971
897
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
897
              }
13973
897
            }
13974
2.69k
          }
13975
          // Otherwise, if one of the following is true:
13976
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13977
          // - url is special and c is U+005C (\)
13978
272
          else if (end_of_authority == input_size ||
13979
24
                   url_data[end_of_authority] == '/' ||
13980
5
                   url_data[end_of_authority] == '?' ||
13981
272
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13982
            // If atSignSeen is true and authority_view is the empty string,
13983
            // validation error, return failure.
13984
272
            if (at_sign_seen && authority_view.empty()) {
13985
122
              url.is_valid = false;
13986
122
              return url;
13987
122
            }
13988
150
            state = state::HOST;
13989
150
            break;
13990
272
          }
13991
2.69k
          if (end_of_authority == input_size) {
13992
            if constexpr (store_values) {
13993
              if (fragment.has_value()) {
13994
                url.update_unencoded_base_hash(*fragment);
13995
              }
13996
            }
13997
0
            return url;
13998
0
          }
13999
2.69k
          input_position = end_of_authority + 1;
14000
2.69k
        } while (true);
14001
14002
150
        break;
14003
272
      }
14004
150
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
14005
2
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
14006
2
                helpers::substring(url_data, input_position));
14007
14008
        // If c is U+002F (/) and remaining starts with U+002F (/),
14009
        // then set state to special authority ignore slashes state and increase
14010
        // pointer by 1.
14011
2
        if (url_data.substr(input_position, 2) == "//") {
14012
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14013
0
          input_position += 2;
14014
2
        } else {
14015
          // Otherwise, validation error, set state to relative state and
14016
          // decrease pointer by 1.
14017
2
          state = state::RELATIVE_SCHEME;
14018
2
        }
14019
14020
2
        break;
14021
272
      }
14022
1.10k
      case state::PATH_OR_AUTHORITY: {
14023
1.10k
        ada_log("PATH_OR_AUTHORITY ",
14024
1.10k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
1.10k
        if ((input_position != input_size) &&
14028
874
            (url_data[input_position] == '/')) {
14029
454
          state = state::AUTHORITY;
14030
454
          input_position++;
14031
650
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
650
          state = state::PATH;
14034
650
        }
14035
14036
1.10k
        break;
14037
272
      }
14038
176
      case state::RELATIVE_SCHEME: {
14039
176
        ada_log("RELATIVE_SCHEME ",
14040
176
                helpers::substring(url_data, input_position));
14041
14042
        // Set url's scheme to base's scheme.
14043
176
        url.copy_scheme(*base_url);
14044
14045
        // If c is U+002F (/), then set state to relative slash state.
14046
176
        if ((input_position != input_size) &&
14047
            // NOLINTNEXTLINE(bugprone-branch-clone)
14048
70
            (url_data[input_position] == '/')) {
14049
0
          ada_log(
14050
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
14051
0
              "slash state");
14052
0
          state = state::RELATIVE_SLASH;
14053
176
        } else if (url.is_special() && (input_position != input_size) &&
14054
2
                   (url_data[input_position] == '\\')) {
14055
          // Otherwise, if url is special and c is U+005C (\), validation error,
14056
          // set state to relative slash state.
14057
0
          ada_log(
14058
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
14059
0
              "error, set state to relative slash state");
14060
0
          state = state::RELATIVE_SLASH;
14061
176
        } else {
14062
176
          ada_log("RELATIVE_SCHEME otherwise");
14063
          // Set url's username to base's username, url's password to base's
14064
          // password, url's host to base's host, url's port to base's port,
14065
          // url's path to a clone of base's path, and url's query to base's
14066
          // query.
14067
          if constexpr (result_type_is_ada_url) {
14068
            url.username = base_url->username;
14069
            url.password = base_url->password;
14070
            url.host = base_url->host;
14071
            url.port = base_url->port;
14072
            // cloning the base path includes cloning the has_opaque_path flag
14073
            url.has_opaque_path = base_url->has_opaque_path;
14074
            url.path = base_url->path;
14075
            url.query = base_url->query;
14076
176
          } else {
14077
176
            url.update_base_authority(base_url->get_href(),
14078
176
                                      base_url->get_components());
14079
176
            url.update_host_to_base_host(base_url->get_hostname());
14080
176
            url.update_base_port(base_url->retrieve_base_port());
14081
            // cloning the base path includes cloning the has_opaque_path flag
14082
176
            url.has_opaque_path = base_url->has_opaque_path;
14083
176
            url.update_base_pathname(base_url->get_pathname());
14084
176
            if (base_url->has_search()) {
14085
              // get_search() returns "" for an empty query string (URL ends
14086
              // with '?'). update_base_search("") would incorrectly clear the
14087
              // query, so pass "?" to preserve the empty query distinction.
14088
0
              auto s = base_url->get_search();
14089
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
0
            }
14091
176
          }
14092
14093
176
          url.has_opaque_path = base_url->has_opaque_path;
14094
14095
          // If c is U+003F (?), then set url's query to the empty string, and
14096
          // state to query state.
14097
176
          if ((input_position != input_size) &&
14098
70
              (url_data[input_position] == '?')) {
14099
0
            state = state::QUERY;
14100
0
          }
14101
          // Otherwise, if c is not the EOF code point:
14102
176
          else if (input_position != input_size) {
14103
            // Set url's query to null.
14104
70
            url.clear_search();
14105
            if constexpr (result_type_is_ada_url) {
14106
              // Shorten url's path.
14107
              helpers::shorten_path(url.path, url.type);
14108
70
            } else {
14109
70
              std::string_view path = url.get_pathname();
14110
70
              if (helpers::shorten_path(path, url.type)) {
14111
0
                url.update_base_pathname(std::move(std::string(path)));
14112
0
              }
14113
70
            }
14114
            // Set state to path state and decrease pointer by 1.
14115
70
            state = state::PATH;
14116
70
            break;
14117
70
          }
14118
176
        }
14119
106
        input_position++;
14120
106
        break;
14121
176
      }
14122
0
      case state::RELATIVE_SLASH: {
14123
0
        ada_log("RELATIVE_SLASH ",
14124
0
                helpers::substring(url_data, input_position));
14125
14126
        // If url is special and c is U+002F (/) or U+005C (\), then:
14127
        // NOLINTNEXTLINE(bugprone-branch-clone)
14128
0
        if (url.is_special() && (input_position != input_size) &&
14129
0
            (url_data[input_position] == '/' ||
14130
0
             url_data[input_position] == '\\')) {
14131
          // Set state to special authority ignore slashes state.
14132
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14133
0
        }
14134
        // Otherwise, if c is U+002F (/), then set state to authority state.
14135
0
        else if ((input_position != input_size) &&
14136
0
                 (url_data[input_position] == '/')) {
14137
0
          state = state::AUTHORITY;
14138
0
        }
14139
        // Otherwise, set
14140
        // - url's username to base's username,
14141
        // - url's password to base's password,
14142
        // - url's host to base's host,
14143
        // - url's port to base's port,
14144
        // - state to path state, and then, decrease pointer by 1.
14145
0
        else {
14146
          if constexpr (result_type_is_ada_url) {
14147
            url.username = base_url->username;
14148
            url.password = base_url->password;
14149
            url.host = base_url->host;
14150
            url.port = base_url->port;
14151
0
          } else {
14152
0
            url.update_base_authority(base_url->get_href(),
14153
0
                                      base_url->get_components());
14154
0
            url.update_host_to_base_host(base_url->get_hostname());
14155
0
            url.update_base_port(base_url->retrieve_base_port());
14156
0
          }
14157
0
          state = state::PATH;
14158
0
          break;
14159
0
        }
14160
14161
0
        input_position++;
14162
0
        break;
14163
0
      }
14164
4.65k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
4.65k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
4.65k
                helpers::substring(url_data, input_position));
14167
14168
        // If c is U+002F (/) and remaining starts with U+002F (/),
14169
        // then set state to special authority ignore slashes state and increase
14170
        // pointer by 1.
14171
4.65k
        if (url_data.substr(input_position, 2) == "//") {
14172
9
          input_position += 2;
14173
9
        }
14174
14175
4.65k
        [[fallthrough]];
14176
4.65k
      }
14177
4.65k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
4.65k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
4.65k
                helpers::substring(url_data, input_position));
14180
14181
        // If c is neither U+002F (/) nor U+005C (\), then set state to
14182
        // authority state and decrease pointer by 1.
14183
5.08k
        while ((input_position != input_size) &&
14184
4.03k
               ((url_data[input_position] == '/') ||
14185
3.80k
                (url_data[input_position] == '\\'))) {
14186
428
          input_position++;
14187
428
        }
14188
4.65k
        state = state::AUTHORITY;
14189
14190
4.65k
        break;
14191
4.65k
      }
14192
0
      case state::QUERY: {
14193
0
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
        if constexpr (store_values) {
14195
          // Let queryPercentEncodeSet be the special-query percent-encode set
14196
          // if url is special; otherwise the query percent-encode set.
14197
          const uint8_t* query_percent_encode_set =
14198
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
                               : character_sets::QUERY_PERCENT_ENCODE;
14200
14201
          // Percent-encode after encoding, with encoding, buffer, and
14202
          // queryPercentEncodeSet, and append the result to url's query.
14203
          url.update_base_search(url_data.substr(input_position),
14204
                                 query_percent_encode_set);
14205
          ada_log("QUERY update_base_search completed ");
14206
          if (fragment.has_value()) {
14207
            url.update_unencoded_base_hash(*fragment);
14208
          }
14209
        }
14210
0
        return url;
14211
4.65k
      }
14212
4.98k
      case state::HOST: {
14213
4.98k
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
4.98k
        std::string_view host_view = url_data.substr(input_position);
14216
4.98k
        auto [location, found_colon] =
14217
4.98k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
4.98k
        input_position = (location != std::string_view::npos)
14219
4.98k
                             ? input_position + location
14220
4.98k
                             : input_size;
14221
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14222
        // Note: the 'found_colon' value is true if and only if a colon was
14223
        // encountered while not inside brackets.
14224
4.98k
        if (found_colon) {
14225
          // If buffer is the empty string, validation error, return failure.
14226
          // Let host be the result of host parsing buffer with url is not
14227
          // special.
14228
196
          ada_log("HOST parsing ", host_view);
14229
196
          if (!url.parse_host(host_view)) {
14230
53
            return url;
14231
53
          }
14232
143
          ada_log("HOST parsing results in ", url.get_hostname());
14233
          // Set url's host to host, buffer to the empty string, and state to
14234
          // port state.
14235
143
          state = state::PORT;
14236
143
          input_position++;
14237
143
        }
14238
        // Otherwise, if one of the following is true:
14239
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14240
        // - url is special and c is U+005C (\)
14241
        // The get_host_delimiter_location function either brings us to
14242
        // the colon outside of the bracket, or to one of those characters.
14243
4.78k
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
4.78k
          if (host_view.empty() && url.is_special()) {
14247
1.04k
            url.is_valid = false;
14248
1.04k
            return url;
14249
1.04k
          }
14250
3.74k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
14251
          // Let host be the result of host parsing host_view with url is not
14252
          // special.
14253
3.74k
          if (host_view.empty()) {
14254
82
            url.update_base_hostname("");
14255
3.66k
          } else if (!url.parse_host(host_view)) {
14256
1.41k
            return url;
14257
1.41k
          }
14258
2.32k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
2.32k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
2.32k
          state = state::PATH_START;
14263
2.32k
        }
14264
14265
2.47k
        break;
14266
4.98k
      }
14267
2.47k
      case state::OPAQUE_PATH: {
14268
1.84k
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
14269
        // Opaque path, query, and fragment are structurally always valid:
14270
        // the parser would just percent-encode whatever is there. When we
14271
        // are not storing values (can_parse), we can return immediately.
14272
        // We must set has_opaque_path = true before returning so that when
14273
        // this URL is used as an internal base inside can_parse, NO_SCHEME
14274
        // correctly rejects relative inputs against an opaque-path base
14275
        // (e.g. can_parse("", &"W:") must return false).
14276
1.84k
        if constexpr (!store_values) {
14277
1.84k
          url.has_opaque_path = true;
14278
1.84k
          return url;
14279
1.84k
        }
14280
0
        std::string_view view = url_data.substr(input_position);
14281
        // If c is U+003F (?), then set url's query to the empty string and
14282
        // state to query state.
14283
1.84k
        size_t location = view.find('?');
14284
1.84k
        if (location != std::string_view::npos) {
14285
0
          view.remove_suffix(view.size() - location);
14286
0
          state = state::QUERY;
14287
0
          input_position += location + 1;
14288
1.84k
        } else {
14289
1.84k
          input_position = input_size + 1;
14290
1.84k
        }
14291
1.84k
        url.has_opaque_path = true;
14292
14293
        // This is a really unlikely scenario in real world. We should not seek
14294
        // to optimize it.
14295
1.84k
        if (view.ends_with(' ')) {
14296
0
          std::string modified_view =
14297
0
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
0
          url.update_base_pathname(unicode::percent_encode(
14299
0
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
1.84k
        } else {
14301
1.84k
          url.update_base_pathname(unicode::percent_encode(
14302
1.84k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
1.84k
        }
14304
1.84k
        break;
14305
4.98k
      }
14306
143
      case state::PORT: {
14307
143
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
143
        std::string_view port_view = url_data.substr(input_position);
14309
143
        input_position += url.parse_port(port_view, true);
14310
143
        if (!url.is_valid) {
14311
21
          return url;
14312
21
        }
14313
122
        state = state::PATH_START;
14314
122
        [[fallthrough]];
14315
122
      }
14316
2.61k
      case state::PATH_START: {
14317
2.61k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
14318
        // Path, query, and fragment are structurally always valid: the
14319
        // parser would just percent-encode whatever is there. When we are
14320
        // not storing values (can_parse), we can return immediately since
14321
        // no subsequent state can invalidate the URL.
14322
2.61k
        if constexpr (!store_values) {
14323
2.61k
          return url;
14324
2.61k
        }
14325
14326
        // If url is special, then:
14327
2.61k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
0
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
0
          if (input_position == input_size) {
14334
            if constexpr (store_values) {
14335
              url.update_base_pathname("/");
14336
              if (fragment.has_value()) {
14337
                url.update_unencoded_base_hash(*fragment);
14338
              }
14339
            }
14340
0
            return url;
14341
0
          }
14342
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
14343
          // by 1. We know that (input_position == input_size) is impossible
14344
          // here, because of the previous if-check.
14345
0
          if ((url_data[input_position] != '/') &&
14346
0
              (url_data[input_position] != '\\')) {
14347
0
            break;
14348
0
          }
14349
0
        }
14350
        // Otherwise, if state override is not given and c is U+003F (?),
14351
        // set url's query to the empty string and state to query state.
14352
2.61k
        else if ((input_position != input_size) &&
14353
0
                 (url_data[input_position] == '?')) {
14354
0
          state = state::QUERY;
14355
0
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
2.61k
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
0
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
0
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
0
        }
14366
14367
2.61k
        input_position++;
14368
2.61k
        break;
14369
2.61k
      }
14370
1.42k
      case state::PATH: {
14371
1.42k
        ada_log("PATH ", helpers::substring(url_data, input_position));
14372
        // Path, query, and fragment are structurally always valid: the
14373
        // parser would just percent-encode whatever is there. When we are
14374
        // not storing values (can_parse), we can return immediately since
14375
        // no subsequent state can invalidate the URL.
14376
1.42k
        if constexpr (!store_values) {
14377
1.42k
          return url;
14378
1.42k
        }
14379
0
        std::string_view view = url_data.substr(input_position);
14380
14381
        // Most time, we do not need percent encoding.
14382
        // Furthermore, we can immediately locate the '?'.
14383
1.42k
        size_t locofquestionmark = view.find('?');
14384
1.42k
        if (locofquestionmark != std::string_view::npos) {
14385
0
          state = state::QUERY;
14386
0
          view.remove_suffix(view.size() - locofquestionmark);
14387
0
          input_position += locofquestionmark + 1;
14388
1.42k
        } else {
14389
1.42k
          input_position = input_size + 1;
14390
1.42k
        }
14391
        if constexpr (store_values) {
14392
          if constexpr (result_type_is_ada_url) {
14393
            helpers::parse_prepared_path(view, url.type, url.path);
14394
          } else {
14395
            url.consume_prepared_path(view);
14396
            ADA_ASSERT_TRUE(url.validate());
14397
          }
14398
        }
14399
1.42k
        break;
14400
2.61k
      }
14401
335
      case state::FILE_SLASH: {
14402
335
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
335
        if ((input_position != input_size) &&
14406
297
            (url_data[input_position] == '/' ||
14407
276
             url_data[input_position] == '\\')) {
14408
276
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
276
          state = state::FILE_HOST;
14411
276
          input_position++;
14412
276
        } else {
14413
59
          ada_log("FILE_SLASH otherwise");
14414
          // If base is non-null and base's scheme is "file", then:
14415
          // Note: it is unsafe to do base_url->scheme unless you know that
14416
          // base_url_has_value() is true.
14417
59
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14418
            // Set url's host to base's host.
14419
            if constexpr (result_type_is_ada_url) {
14420
              url.host = base_url->host;
14421
0
            } else {
14422
0
              url.update_host_to_base_host(base_url->get_host());
14423
0
            }
14424
            // If the code point substring from pointer to the end of input does
14425
            // not start with a Windows drive letter and base's path[0] is a
14426
            // normalized Windows drive letter, then append base's path[0] to
14427
            // url's path.
14428
0
            if (!base_url->get_pathname().empty()) {
14429
0
              if (!checkers::is_windows_drive_letter(
14430
0
                      url_data.substr(input_position))) {
14431
0
                std::string_view first_base_url_path =
14432
0
                    base_url->get_pathname().substr(1);
14433
0
                size_t loc = first_base_url_path.find('/');
14434
0
                if (loc != std::string_view::npos) {
14435
0
                  helpers::resize(first_base_url_path, loc);
14436
0
                }
14437
0
                if (checkers::is_normalized_windows_drive_letter(
14438
0
                        first_base_url_path)) {
14439
                  if constexpr (result_type_is_ada_url) {
14440
                    url.path += '/';
14441
                    url.path += first_base_url_path;
14442
0
                  } else {
14443
0
                    url.append_base_pathname(
14444
0
                        helpers::concat("/", first_base_url_path));
14445
0
                  }
14446
0
                }
14447
0
              }
14448
0
            }
14449
0
          }
14450
14451
          // Set state to path state, and decrease pointer by 1.
14452
59
          state = state::PATH;
14453
59
        }
14454
14455
335
        break;
14456
2.61k
      }
14457
276
      case state::FILE_HOST: {
14458
276
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
276
        std::string_view view = url_data.substr(input_position);
14460
14461
276
        size_t location = view.find_first_of("/\\?");
14462
276
        std::string_view file_host_buffer = view.substr(
14463
276
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
276
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
0
          state = state::PATH;
14467
276
        } else if (file_host_buffer.empty()) {
14468
          // Set url's host to the empty string.
14469
          if constexpr (result_type_is_ada_url) {
14470
            url.host = "";
14471
22
          } else {
14472
22
            url.update_base_hostname("");
14473
22
          }
14474
          // Set state to path start state.
14475
22
          state = state::PATH_START;
14476
254
        } else {
14477
254
          size_t consumed_bytes = file_host_buffer.size();
14478
254
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
254
          if (!url.parse_host(file_host_buffer)) {
14482
111
            return url;
14483
111
          }
14484
14485
          if constexpr (result_type_is_ada_url) {
14486
            // If host is "localhost", then set host to the empty string.
14487
            if (url.host.has_value() && url.host.value() == "localhost") {
14488
              url.host = "";
14489
            }
14490
143
          } else {
14491
143
            if (url.get_hostname() == "localhost") {
14492
0
              url.update_base_hostname("");
14493
0
            }
14494
143
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
143
          state = state::PATH_START;
14498
143
        }
14499
14500
165
        break;
14501
276
      }
14502
978
      case state::FILE: {
14503
978
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
978
        std::string_view file_view = url_data.substr(input_position);
14505
14506
978
        url.set_protocol_as_file();
14507
        if constexpr (result_type_is_ada_url) {
14508
          // Set url's host to the empty string.
14509
          url.host = "";
14510
978
        } else {
14511
978
          url.update_base_hostname("");
14512
978
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
978
        if (input_position != input_size &&
14515
816
            (url_data[input_position] == '/' ||
14516
495
             url_data[input_position] == '\\')) {
14517
335
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
335
          state = state::FILE_SLASH;
14520
335
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
643
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14523
          // Set url's host to base's host, url's path to a clone of base's
14524
          // path, and url's query to base's query.
14525
7
          ada_log("FILE base non-null");
14526
          if constexpr (result_type_is_ada_url) {
14527
            url.host = base_url->host;
14528
            url.path = base_url->path;
14529
            url.query = base_url->query;
14530
7
          } else {
14531
7
            url.update_host_to_base_host(base_url->get_hostname());
14532
7
            url.update_base_pathname(base_url->get_pathname());
14533
7
            if (base_url->has_search()) {
14534
              // get_search() returns "" for an empty query string (URL ends
14535
              // with '?'). update_base_search("") would incorrectly clear the
14536
              // query, so pass "?" to preserve the empty query distinction.
14537
0
              auto s = base_url->get_search();
14538
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
0
            }
14540
7
          }
14541
7
          url.has_opaque_path = base_url->has_opaque_path;
14542
14543
          // If c is U+003F (?), then set url's query to the empty string and
14544
          // state to query state.
14545
7
          if (input_position != input_size && url_data[input_position] == '?') {
14546
0
            state = state::QUERY;
14547
0
          }
14548
          // Otherwise, if c is not the EOF code point:
14549
7
          else if (input_position != input_size) {
14550
            // Set url's query to null.
14551
5
            url.clear_search();
14552
            // If the code point substring from pointer to the end of input does
14553
            // not start with a Windows drive letter, then shorten url's path.
14554
5
            if (!checkers::is_windows_drive_letter(file_view)) {
14555
              if constexpr (result_type_is_ada_url) {
14556
                helpers::shorten_path(url.path, url.type);
14557
5
              } else {
14558
5
                std::string_view path = url.get_pathname();
14559
5
                if (helpers::shorten_path(path, url.type)) {
14560
0
                  url.update_base_pathname(std::move(std::string(path)));
14561
0
                }
14562
5
              }
14563
5
            }
14564
            // Otherwise:
14565
0
            else {
14566
              // Set url's path to an empty list.
14567
0
              url.clear_pathname();
14568
0
              url.has_opaque_path = true;
14569
0
            }
14570
14571
            // Set state to path state and decrease pointer by 1.
14572
5
            state = state::PATH;
14573
5
            break;
14574
5
          }
14575
7
        }
14576
        // Otherwise, set state to path state, and decrease pointer by 1.
14577
636
        else {
14578
636
          ada_log("FILE go to path");
14579
636
          state = state::PATH;
14580
636
          break;
14581
636
        }
14582
14583
337
        input_position++;
14584
337
        break;
14585
978
      }
14586
0
      default:
14587
0
        unreachable();
14588
60.8k
    }
14589
60.8k
  }
14590
  if constexpr (store_values) {
14591
    if (fragment.has_value()) {
14592
      url.update_unencoded_base_hash(*fragment);
14593
    }
14594
  }
14595
  // Check the resulting (normalized) URL size against the maximum input length.
14596
  // Normalization (percent-encoding, IDNA, etc.) can expand the URL beyond the
14597
  // original input size.
14598
  if constexpr (store_values) {
14599
    if (url.is_valid) {
14600
      if constexpr (result_type_is_ada_url_aggregator) {
14601
        if (url.buffer.size() > max_input_length) {
14602
          url.is_valid = false;
14603
        }
14604
      } else {
14605
        if (url.get_href_size() > max_input_length) {
14606
          url.is_valid = false;
14607
        }
14608
      }
14609
    }
14610
  }
14611
108
  return url;
14612
17.5k
}
14613
14614
template url parse_url_impl<url, true>(std::string_view user_input,
14615
                                       const url* base_url = nullptr);
14616
template url_aggregator parse_url_impl<url_aggregator, true>(
14617
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14618
template url_aggregator parse_url_impl<url_aggregator, false>(
14619
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14620
14621
template <class result_type>
14622
result_type parse_url(std::string_view user_input,
14623
0
                      const result_type* base_url) {
14624
0
  return parse_url_impl<result_type, true>(user_input, base_url);
14625
0
}
Unexecuted instantiation: ada::url ada::parser::parse_url<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
Unexecuted instantiation: ada::url_aggregator ada::parser::parse_url<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)
14626
14627
template url parse_url<url>(std::string_view user_input,
14628
                            const url* base_url = nullptr);
14629
template url_aggregator parse_url<url_aggregator>(
14630
    std::string_view user_input, const url_aggregator* base_url = nullptr);
14631
}  // namespace ada::parser
14632
/* end file src/parser.cpp */
14633
/* begin file src/url_components.cpp */
14634
14635
#include <iterator>
14636
#include <string>
14637
14638
namespace ada {
14639
14640
0
[[nodiscard]] std::string url_components::to_string() const {
14641
0
  std::string answer;
14642
0
  auto back = std::back_insert_iterator(answer);
14643
0
  answer.append("{\n");
14644
14645
0
  answer.append("\t\"protocol_end\":\"");
14646
0
  helpers::encode_json(std::to_string(protocol_end), back);
14647
0
  answer.append("\",\n");
14648
14649
0
  answer.append("\t\"username_end\":\"");
14650
0
  helpers::encode_json(std::to_string(username_end), back);
14651
0
  answer.append("\",\n");
14652
14653
0
  answer.append("\t\"host_start\":\"");
14654
0
  helpers::encode_json(std::to_string(host_start), back);
14655
0
  answer.append("\",\n");
14656
14657
0
  answer.append("\t\"host_end\":\"");
14658
0
  helpers::encode_json(std::to_string(host_end), back);
14659
0
  answer.append("\",\n");
14660
14661
0
  answer.append("\t\"port\":\"");
14662
0
  helpers::encode_json(std::to_string(port), back);
14663
0
  answer.append("\",\n");
14664
14665
0
  answer.append("\t\"pathname_start\":\"");
14666
0
  helpers::encode_json(std::to_string(pathname_start), back);
14667
0
  answer.append("\",\n");
14668
14669
0
  answer.append("\t\"search_start\":\"");
14670
0
  helpers::encode_json(std::to_string(search_start), back);
14671
0
  answer.append("\",\n");
14672
14673
0
  answer.append("\t\"hash_start\":\"");
14674
0
  helpers::encode_json(std::to_string(hash_start), back);
14675
0
  answer.append("\",\n");
14676
14677
0
  answer.append("\n}");
14678
0
  return answer;
14679
0
}
14680
14681
}  // namespace ada
14682
/* end file src/url_components.cpp */
14683
/* begin file src/url_aggregator.cpp */
14684
14685
#include <iterator>
14686
#include <ranges>
14687
#include <string>
14688
#include <string_view>
14689
14690
namespace {
14691
14692
ada_really_inline void apply_shifted_non_scheme_offsets(
14693
1.32M
    ada::url_components& components, uint32_t new_difference) {
14694
1.32M
  components.username_end += new_difference;
14695
1.32M
  components.host_start += new_difference;
14696
1.32M
  components.host_end += new_difference;
14697
1.32M
  components.pathname_start += new_difference;
14698
1.32M
  if (components.search_start != ada::url_components::omitted) {
14699
1.09k
    components.search_start += new_difference;
14700
1.09k
  }
14701
1.32M
  if (components.hash_start != ada::url_components::omitted) {
14702
1.00k
    components.hash_start += new_difference;
14703
1.00k
  }
14704
1.32M
}
Unexecuted instantiation: idna.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
ada.cpp:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Line
Count
Source
14693
31.0k
    ada::url_components& components, uint32_t new_difference) {
14694
31.0k
  components.username_end += new_difference;
14695
31.0k
  components.host_start += new_difference;
14696
31.0k
  components.host_end += new_difference;
14697
31.0k
  components.pathname_start += new_difference;
14698
31.0k
  if (components.search_start != ada::url_components::omitted) {
14699
131
    components.search_start += new_difference;
14700
131
  }
14701
31.0k
  if (components.hash_start != ada::url_components::omitted) {
14702
34
    components.hash_start += new_difference;
14703
34
  }
14704
31.0k
}
serializers.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Line
Count
Source
14693
5.68k
    ada::url_components& components, uint32_t new_difference) {
14694
5.68k
  components.username_end += new_difference;
14695
5.68k
  components.host_start += new_difference;
14696
5.68k
  components.host_end += new_difference;
14697
5.68k
  components.pathname_start += new_difference;
14698
5.68k
  if (components.search_start != ada::url_components::omitted) {
14699
0
    components.search_start += new_difference;
14700
0
  }
14701
5.68k
  if (components.hash_start != ada::url_components::omitted) {
14702
0
    components.hash_start += new_difference;
14703
0
  }
14704
5.68k
}
Unexecuted instantiation: can_parse.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Unexecuted instantiation: unicode.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
parse.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Line
Count
Source
14693
100k
    ada::url_components& components, uint32_t new_difference) {
14694
100k
  components.username_end += new_difference;
14695
100k
  components.host_start += new_difference;
14696
100k
  components.host_end += new_difference;
14697
100k
  components.pathname_start += new_difference;
14698
100k
  if (components.search_start != ada::url_components::omitted) {
14699
963
    components.search_start += new_difference;
14700
963
  }
14701
100k
  if (components.hash_start != ada::url_components::omitted) {
14702
967
    components.hash_start += new_difference;
14703
967
  }
14704
100k
}
url_pattern.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Line
Count
Source
14693
1.18M
    ada::url_components& components, uint32_t new_difference) {
14694
1.18M
  components.username_end += new_difference;
14695
1.18M
  components.host_start += new_difference;
14696
1.18M
  components.host_end += new_difference;
14697
1.18M
  components.pathname_start += new_difference;
14698
1.18M
  if (components.search_start != ada::url_components::omitted) {
14699
0
    components.search_start += new_difference;
14700
0
  }
14701
1.18M
  if (components.hash_start != ada::url_components::omitted) {
14702
0
    components.hash_start += new_difference;
14703
0
  }
14704
1.18M
}
url_search_params.cc:(anonymous namespace)::apply_shifted_non_scheme_offsets(ada::url_components&, unsigned int)
Line
Count
Source
14693
2.60k
    ada::url_components& components, uint32_t new_difference) {
14694
2.60k
  components.username_end += new_difference;
14695
2.60k
  components.host_start += new_difference;
14696
2.60k
  components.host_end += new_difference;
14697
2.60k
  components.pathname_start += new_difference;
14698
2.60k
  if (components.search_start != ada::url_components::omitted) {
14699
0
    components.search_start += new_difference;
14700
0
  }
14701
2.60k
  if (components.hash_start != ada::url_components::omitted) {
14702
0
    components.hash_start += new_difference;
14703
0
  }
14704
2.60k
}
14705
14706
}  // namespace
14707
14708
namespace ada {
14709
template <bool has_state_override>
14710
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
14711
1.31M
    const std::string_view input_with_colon) {
14712
1.31M
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
1.31M
  ADA_ASSERT_TRUE(validate());
14714
1.31M
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
1.31M
  std::string_view input{input_with_colon};
14716
1.31M
  input.remove_suffix(1);
14717
1.31M
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
1.31M
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14719
  /**
14720
   * In the common case, we will immediately recognize a special scheme (e.g.,
14721
   *http, https), in which case, we can go really fast.
14722
   **/
14723
1.31M
  if (is_input_special) {  // fast path!!!
14724
1.03M
    if constexpr (has_state_override) {
14725
      // If url's scheme is not a special scheme and buffer is a special scheme,
14726
      // then return.
14727
5.04k
      if (is_special() != is_input_special) {
14728
0
        return false;
14729
0
      }
14730
14731
      // If url includes credentials or has a non-null port, and buffer is
14732
      // "file", then return.
14733
5.04k
      if ((has_credentials() || components.port != url_components::omitted) &&
14734
555
          parsed_type == ada::scheme::type::FILE) {
14735
41
        return false;
14736
41
      }
14737
14738
      // If url's scheme is "file" and its host is an empty host, then return.
14739
      // An empty host is the empty string.
14740
5.00k
      if (type == ada::scheme::type::FILE &&
14741
505
          components.host_start == components.host_end) {
14742
402
        return false;
14743
402
      }
14744
5.00k
    }
14745
14746
4.59k
    type = parsed_type;
14747
1.03M
    set_scheme_from_view_with_colon(input_with_colon);
14748
14749
1.03M
    if constexpr (has_state_override) {
14750
      // This is uncommon.
14751
5.04k
      uint16_t urls_scheme_port = get_special_port();
14752
14753
      // If url's port is url's scheme's default port, then set url's port to
14754
      // null.
14755
5.04k
      if (components.port == urls_scheme_port) {
14756
10
        clear_port();
14757
10
      }
14758
5.04k
    }
14759
1.03M
  } else {  // slow path
14760
276k
    std::string _buffer(input);
14761
    // Next function is only valid if the input is ASCII and returns false
14762
    // otherwise, but it seems that we always have ascii content so we do not
14763
    // need to check the return value.
14764
276k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14765
14766
276k
    if constexpr (has_state_override) {
14767
      // The state-override validation errors below ("return" in the WHATWG URL
14768
      // parser) leave the URL unchanged. The setter contract is
14769
      // "true on success, false if the scheme is invalid" -- the fast path
14770
      // above already returns false here, so the slow path must agree.
14771
14772
      // If url's scheme is a special scheme and buffer is not a special scheme,
14773
      // then return. If url's scheme is not a special scheme and buffer is a
14774
      // special scheme, then return.
14775
6.46k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14776
2.54k
        return false;
14777
2.54k
      }
14778
14779
      // If url includes credentials or has a non-null port, and buffer is
14780
      // "file", then return.
14781
3.91k
      if ((has_credentials() || components.port != url_components::omitted) &&
14782
539
          _buffer == "file") {
14783
17
        return false;
14784
17
      }
14785
14786
      // If url's scheme is "file" and its host is an empty host, then return.
14787
      // An empty host is the empty string.
14788
3.89k
      if (type == ada::scheme::type::FILE &&
14789
335
          components.host_start == components.host_end) {
14790
268
        return false;
14791
268
      }
14792
3.89k
    }
14793
14794
3.63k
    set_scheme(_buffer);
14795
14796
276k
    if constexpr (has_state_override) {
14797
      // This is uncommon.
14798
6.46k
      uint16_t urls_scheme_port = get_special_port();
14799
14800
      // If url's port is url's scheme's default port, then set url's port to
14801
      // null.
14802
6.46k
      if (components.port == urls_scheme_port) {
14803
28
        clear_port();
14804
28
      }
14805
6.46k
    }
14806
276k
  }
14807
0
  ADA_ASSERT_TRUE(validate());
14808
1.31M
  return true;
14809
1.31M
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14711
1.30M
    const std::string_view input_with_colon) {
14712
1.30M
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
1.30M
  ADA_ASSERT_TRUE(validate());
14714
1.30M
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
1.30M
  std::string_view input{input_with_colon};
14716
1.30M
  input.remove_suffix(1);
14717
1.30M
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
1.30M
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14719
  /**
14720
   * In the common case, we will immediately recognize a special scheme (e.g.,
14721
   *http, https), in which case, we can go really fast.
14722
   **/
14723
1.30M
  if (is_input_special) {  // fast path!!!
14724
    if constexpr (has_state_override) {
14725
      // If url's scheme is not a special scheme and buffer is a special scheme,
14726
      // then return.
14727
      if (is_special() != is_input_special) {
14728
        return false;
14729
      }
14730
14731
      // If url includes credentials or has a non-null port, and buffer is
14732
      // "file", then return.
14733
      if ((has_credentials() || components.port != url_components::omitted) &&
14734
          parsed_type == ada::scheme::type::FILE) {
14735
        return false;
14736
      }
14737
14738
      // If url's scheme is "file" and its host is an empty host, then return.
14739
      // An empty host is the empty string.
14740
      if (type == ada::scheme::type::FILE &&
14741
          components.host_start == components.host_end) {
14742
        return false;
14743
      }
14744
    }
14745
14746
1.03M
    type = parsed_type;
14747
1.03M
    set_scheme_from_view_with_colon(input_with_colon);
14748
14749
    if constexpr (has_state_override) {
14750
      // This is uncommon.
14751
      uint16_t urls_scheme_port = get_special_port();
14752
14753
      // If url's port is url's scheme's default port, then set url's port to
14754
      // null.
14755
      if (components.port == urls_scheme_port) {
14756
        clear_port();
14757
      }
14758
    }
14759
1.03M
  } else {  // slow path
14760
270k
    std::string _buffer(input);
14761
    // Next function is only valid if the input is ASCII and returns false
14762
    // otherwise, but it seems that we always have ascii content so we do not
14763
    // need to check the return value.
14764
270k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14765
14766
    if constexpr (has_state_override) {
14767
      // The state-override validation errors below ("return" in the WHATWG URL
14768
      // parser) leave the URL unchanged. The setter contract is
14769
      // "true on success, false if the scheme is invalid" -- the fast path
14770
      // above already returns false here, so the slow path must agree.
14771
14772
      // If url's scheme is a special scheme and buffer is not a special scheme,
14773
      // then return. If url's scheme is not a special scheme and buffer is a
14774
      // special scheme, then return.
14775
      if (is_special() != ada::scheme::is_special(_buffer)) {
14776
        return false;
14777
      }
14778
14779
      // If url includes credentials or has a non-null port, and buffer is
14780
      // "file", then return.
14781
      if ((has_credentials() || components.port != url_components::omitted) &&
14782
          _buffer == "file") {
14783
        return false;
14784
      }
14785
14786
      // If url's scheme is "file" and its host is an empty host, then return.
14787
      // An empty host is the empty string.
14788
      if (type == ada::scheme::type::FILE &&
14789
          components.host_start == components.host_end) {
14790
        return false;
14791
      }
14792
    }
14793
14794
270k
    set_scheme(_buffer);
14795
14796
    if constexpr (has_state_override) {
14797
      // This is uncommon.
14798
      uint16_t urls_scheme_port = get_special_port();
14799
14800
      // If url's port is url's scheme's default port, then set url's port to
14801
      // null.
14802
      if (components.port == urls_scheme_port) {
14803
        clear_port();
14804
      }
14805
    }
14806
270k
  }
14807
1.30M
  ADA_ASSERT_TRUE(validate());
14808
1.30M
  return true;
14809
1.30M
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14711
11.5k
    const std::string_view input_with_colon) {
14712
11.5k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
11.5k
  ADA_ASSERT_TRUE(validate());
14714
11.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
11.5k
  std::string_view input{input_with_colon};
14716
11.5k
  input.remove_suffix(1);
14717
11.5k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
11.5k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
14719
  /**
14720
   * In the common case, we will immediately recognize a special scheme (e.g.,
14721
   *http, https), in which case, we can go really fast.
14722
   **/
14723
11.5k
  if (is_input_special) {  // fast path!!!
14724
5.04k
    if constexpr (has_state_override) {
14725
      // If url's scheme is not a special scheme and buffer is a special scheme,
14726
      // then return.
14727
5.04k
      if (is_special() != is_input_special) {
14728
0
        return false;
14729
0
      }
14730
14731
      // If url includes credentials or has a non-null port, and buffer is
14732
      // "file", then return.
14733
5.04k
      if ((has_credentials() || components.port != url_components::omitted) &&
14734
555
          parsed_type == ada::scheme::type::FILE) {
14735
41
        return false;
14736
41
      }
14737
14738
      // If url's scheme is "file" and its host is an empty host, then return.
14739
      // An empty host is the empty string.
14740
5.00k
      if (type == ada::scheme::type::FILE &&
14741
505
          components.host_start == components.host_end) {
14742
402
        return false;
14743
402
      }
14744
5.00k
    }
14745
14746
4.59k
    type = parsed_type;
14747
5.04k
    set_scheme_from_view_with_colon(input_with_colon);
14748
14749
5.04k
    if constexpr (has_state_override) {
14750
      // This is uncommon.
14751
5.04k
      uint16_t urls_scheme_port = get_special_port();
14752
14753
      // If url's port is url's scheme's default port, then set url's port to
14754
      // null.
14755
5.04k
      if (components.port == urls_scheme_port) {
14756
10
        clear_port();
14757
10
      }
14758
5.04k
    }
14759
6.46k
  } else {  // slow path
14760
6.46k
    std::string _buffer(input);
14761
    // Next function is only valid if the input is ASCII and returns false
14762
    // otherwise, but it seems that we always have ascii content so we do not
14763
    // need to check the return value.
14764
6.46k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14765
14766
6.46k
    if constexpr (has_state_override) {
14767
      // The state-override validation errors below ("return" in the WHATWG URL
14768
      // parser) leave the URL unchanged. The setter contract is
14769
      // "true on success, false if the scheme is invalid" -- the fast path
14770
      // above already returns false here, so the slow path must agree.
14771
14772
      // If url's scheme is a special scheme and buffer is not a special scheme,
14773
      // then return. If url's scheme is not a special scheme and buffer is a
14774
      // special scheme, then return.
14775
6.46k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14776
2.54k
        return false;
14777
2.54k
      }
14778
14779
      // If url includes credentials or has a non-null port, and buffer is
14780
      // "file", then return.
14781
3.91k
      if ((has_credentials() || components.port != url_components::omitted) &&
14782
539
          _buffer == "file") {
14783
17
        return false;
14784
17
      }
14785
14786
      // If url's scheme is "file" and its host is an empty host, then return.
14787
      // An empty host is the empty string.
14788
3.89k
      if (type == ada::scheme::type::FILE &&
14789
335
          components.host_start == components.host_end) {
14790
268
        return false;
14791
268
      }
14792
3.89k
    }
14793
14794
3.63k
    set_scheme(_buffer);
14795
14796
6.46k
    if constexpr (has_state_override) {
14797
      // This is uncommon.
14798
6.46k
      uint16_t urls_scheme_port = get_special_port();
14799
14800
      // If url's port is url's scheme's default port, then set url's port to
14801
      // null.
14802
6.46k
      if (components.port == urls_scheme_port) {
14803
28
        clear_port();
14804
28
      }
14805
6.46k
    }
14806
6.46k
  }
14807
0
  ADA_ASSERT_TRUE(validate());
14808
11.5k
  return true;
14809
11.5k
}
14810
14811
12.2k
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14812
12.2k
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14813
12.2k
  ADA_ASSERT_TRUE(validate());
14814
  // next line could overflow but unsigned arithmetic has well-defined
14815
  // overflows.
14816
12.2k
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14817
14818
12.2k
  type = u.type;
14819
12.2k
  buffer.erase(0, components.protocol_end);
14820
12.2k
  buffer.insert(0, u.get_protocol());
14821
12.2k
  components.protocol_end = u.components.protocol_end;
14822
14823
  // No need to update the components
14824
12.2k
  if (new_difference == 0) {
14825
234
    return;
14826
234
  }
14827
14828
12.0k
  apply_shifted_non_scheme_offsets(components, new_difference);
14829
12.0k
  ADA_ASSERT_TRUE(validate());
14830
12.0k
}
14831
14832
inline void url_aggregator::set_scheme_from_view_with_colon(
14833
1.03M
    std::string_view new_scheme_with_colon) {
14834
1.03M
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14835
1.03M
          new_scheme_with_colon);
14836
1.03M
  ADA_ASSERT_TRUE(validate());
14837
1.03M
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14838
1.03M
                  new_scheme_with_colon.back() == ':');
14839
  // next line could overflow but unsigned arithmetic has well-defined
14840
  // overflows.
14841
1.03M
  uint32_t new_difference =
14842
1.03M
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14843
14844
1.03M
  if (buffer.empty()) {
14845
1.03M
    buffer.append(new_scheme_with_colon);
14846
1.03M
  } else {
14847
4.59k
    buffer.erase(0, components.protocol_end);
14848
4.59k
    buffer.insert(0, new_scheme_with_colon);
14849
4.59k
  }
14850
1.03M
  components.protocol_end += new_difference;
14851
14852
1.03M
  apply_shifted_non_scheme_offsets(components, new_difference);
14853
1.03M
  ADA_ASSERT_TRUE(validate());
14854
1.03M
}
14855
14856
273k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14857
273k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14858
273k
  ADA_ASSERT_TRUE(validate());
14859
273k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14860
  // next line could overflow but unsigned arithmetic has well-defined
14861
  // overflows.
14862
273k
  uint32_t new_difference =
14863
273k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14864
14865
273k
  type = ada::scheme::get_scheme_type(new_scheme);
14866
273k
  if (buffer.empty()) {
14867
270k
    buffer.append(helpers::concat(new_scheme, ":"));
14868
270k
  } else {
14869
3.63k
    buffer.erase(0, components.protocol_end);
14870
3.63k
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14871
3.63k
  }
14872
273k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14873
14874
273k
  apply_shifted_non_scheme_offsets(components, new_difference);
14875
273k
  ADA_ASSERT_TRUE(validate());
14876
273k
}
14877
14878
37.3k
bool url_aggregator::set_protocol(const std::string_view input) {
14879
37.3k
  ada_log("url_aggregator::set_protocol ", input);
14880
37.3k
  ADA_ASSERT_TRUE(validate());
14881
37.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14882
37.3k
  std::string view(input);
14883
37.3k
  helpers::remove_ascii_tab_or_newline(view);
14884
37.3k
  if (view.empty()) {
14885
18.5k
    return true;
14886
18.5k
  }
14887
14888
  // Schemes should start with alpha values.
14889
18.8k
  if (!checkers::is_alpha(view[0])) {
14890
6.56k
    return false;
14891
6.56k
  }
14892
14893
12.3k
  view.append(":");
14894
14895
12.3k
  std::string::iterator pointer =
14896
12.3k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14897
14898
12.3k
  if (pointer != view.end() && *pointer == ':') {
14899
11.5k
    url_aggregator saved_url(*this);
14900
11.5k
    bool result = parse_scheme_with_colon<true>(
14901
11.5k
        view.substr(0, pointer - view.begin() + 1));
14902
11.5k
    if (result && buffer.size() > ada::get_max_input_length()) {
14903
0
      *this = std::move(saved_url);
14904
0
      return false;
14905
0
    }
14906
11.5k
    return result;
14907
11.5k
  }
14908
804
  return false;
14909
12.3k
}
14910
14911
19.6k
bool url_aggregator::set_username(const std::string_view input) {
14912
19.6k
  ada_log("url_aggregator::set_username '", input, "' ");
14913
19.6k
  ADA_ASSERT_TRUE(validate());
14914
19.6k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14915
19.6k
  if (cannot_have_credentials_or_port()) {
14916
2.81k
    return false;
14917
2.81k
  }
14918
16.8k
  url_aggregator saved_url(*this);
14919
16.8k
  size_t idx = ada::unicode::percent_encode_index(
14920
16.8k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14921
16.8k
  if (idx == input.size()) {
14922
3.98k
    update_base_username(input);
14923
12.8k
  } else {
14924
    // We only create a temporary string if we have to!
14925
12.8k
    update_base_username(ada::unicode::percent_encode(
14926
12.8k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14927
12.8k
  }
14928
16.8k
  if (buffer.size() > ada::get_max_input_length()) {
14929
0
    *this = std::move(saved_url);
14930
0
    return false;
14931
0
  }
14932
16.8k
  ADA_ASSERT_TRUE(validate());
14933
16.8k
  return true;
14934
16.8k
}
14935
14936
19.7k
bool url_aggregator::set_password(const std::string_view input) {
14937
19.7k
  ada_log("url_aggregator::set_password '", input, "'");
14938
19.7k
  ADA_ASSERT_TRUE(validate());
14939
19.7k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14940
19.7k
  if (cannot_have_credentials_or_port()) {
14941
2.81k
    return false;
14942
2.81k
  }
14943
16.9k
  url_aggregator saved_url(*this);
14944
16.9k
  size_t idx = ada::unicode::percent_encode_index(
14945
16.9k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14946
16.9k
  if (idx == input.size()) {
14947
4.09k
    update_base_password(input);
14948
12.8k
  } else {
14949
    // We only create a temporary string if we have to!
14950
12.8k
    update_base_password(ada::unicode::percent_encode(
14951
12.8k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14952
12.8k
  }
14953
16.9k
  if (buffer.size() > ada::get_max_input_length()) {
14954
0
    *this = std::move(saved_url);
14955
0
    return false;
14956
0
  }
14957
16.9k
  ADA_ASSERT_TRUE(validate());
14958
16.9k
  return true;
14959
16.9k
}
14960
14961
26.5k
bool url_aggregator::set_port(const std::string_view input) {
14962
26.5k
  ada_log("url_aggregator::set_port ", input);
14963
26.5k
  ADA_ASSERT_TRUE(validate());
14964
26.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14965
26.5k
  if (cannot_have_credentials_or_port()) {
14966
2.81k
    return false;
14967
2.81k
  }
14968
14969
23.7k
  if (input.empty()) {
14970
2.24k
    clear_port();
14971
2.24k
    return true;
14972
2.24k
  }
14973
14974
21.5k
  std::string trimmed(input);
14975
21.5k
  helpers::remove_ascii_tab_or_newline(trimmed);
14976
14977
21.5k
  if (trimmed.empty()) {
14978
100
    return true;
14979
100
  }
14980
14981
  // Input should not start with a non-digit character.
14982
21.4k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14983
18.1k
    return false;
14984
18.1k
  }
14985
14986
  // Find the first non-digit character to determine the length of digits
14987
3.27k
  auto first_non_digit =
14988
3.27k
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14989
3.27k
  std::string_view digits_to_parse =
14990
3.27k
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14991
14992
  // Revert changes if parse_port fails.
14993
3.27k
  url_aggregator saved_url(*this);
14994
3.27k
  parse_port(digits_to_parse);
14995
3.27k
  if (is_valid) {
14996
2.72k
    if (buffer.size() > ada::get_max_input_length()) {
14997
0
      *this = std::move(saved_url);
14998
0
      return false;
14999
0
    }
15000
2.72k
    return true;
15001
2.72k
  }
15002
550
  *this = std::move(saved_url);
15003
550
  is_valid = true;
15004
550
  ADA_ASSERT_TRUE(validate());
15005
550
  return false;
15006
3.27k
}
15007
15008
19.9k
bool url_aggregator::set_pathname(const std::string_view input) {
15009
19.9k
  ada_log("url_aggregator::set_pathname ", input);
15010
19.9k
  ADA_ASSERT_TRUE(validate());
15011
19.9k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15012
19.9k
  if (has_opaque_path) {
15013
1.13k
    return false;
15014
1.13k
  }
15015
18.8k
  url_aggregator saved_url(*this);
15016
18.8k
  clear_pathname();
15017
18.8k
  parse_path(input);
15018
18.8k
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
15019
0
    buffer.insert(components.pathname_start, "/.");
15020
0
    components.pathname_start += 2;
15021
0
    if (components.search_start != url_components::omitted) {
15022
0
      components.search_start += 2;
15023
0
    }
15024
0
    if (components.hash_start != url_components::omitted) {
15025
0
      components.hash_start += 2;
15026
0
    }
15027
0
  }
15028
18.8k
  if (buffer.size() > ada::get_max_input_length()) {
15029
0
    *this = std::move(saved_url);
15030
0
    return false;
15031
0
  }
15032
18.8k
  ADA_ASSERT_TRUE(validate());
15033
18.8k
  return true;
15034
18.8k
}
15035
15036
18.8k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
15037
18.8k
  ada_log("url_aggregator::parse_path ", input);
15038
18.8k
  ADA_ASSERT_TRUE(validate());
15039
18.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15040
18.8k
  std::string tmp_buffer;
15041
18.8k
  std::string_view internal_input;
15042
18.8k
  if (unicode::has_tabs_or_newline(input)) {
15043
522
    tmp_buffer = input;
15044
    // Optimization opportunity: Instead of copying and then pruning, we could
15045
    // just directly build the string from user_input.
15046
522
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
15047
522
    internal_input = tmp_buffer;
15048
18.2k
  } else {
15049
18.2k
    internal_input = input;
15050
18.2k
  }
15051
15052
  // If url is special, then:
15053
18.8k
  if (is_special()) {
15054
18.0k
    if (internal_input.empty()) {
15055
1.64k
      update_base_pathname("/");
15056
16.3k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
15057
2.08k
      consume_prepared_path(internal_input.substr(1));
15058
14.2k
    } else {
15059
14.2k
      consume_prepared_path(internal_input);
15060
14.2k
    }
15061
18.0k
  } else if (!internal_input.empty()) {
15062
798
    if (internal_input[0] == '/') {
15063
0
      consume_prepared_path(internal_input.substr(1));
15064
798
    } else {
15065
798
      consume_prepared_path(internal_input);
15066
798
    }
15067
798
  } else {
15068
    // Non-special URLs with an empty host can have their paths erased
15069
    // Path-only URLs cannot have their paths erased
15070
0
    if (components.host_start == components.host_end && !has_authority()) {
15071
0
      update_base_pathname("/");
15072
0
    }
15073
0
  }
15074
18.8k
  ADA_ASSERT_TRUE(validate());
15075
18.8k
}
15076
15077
35.1k
void url_aggregator::set_search(const std::string_view input) {
15078
35.1k
  ada_log("url_aggregator::set_search ", input);
15079
35.1k
  ADA_ASSERT_TRUE(validate());
15080
35.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15081
35.1k
  if (input.empty()) {
15082
2.85k
    clear_search();
15083
2.85k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
15084
2.85k
    return;
15085
2.85k
  }
15086
15087
32.3k
  std::string new_value;
15088
32.3k
  new_value = input[0] == '?' ? input.substr(1) : input;
15089
32.3k
  helpers::remove_ascii_tab_or_newline(new_value);
15090
15091
32.3k
  auto query_percent_encode_set =
15092
32.3k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
15093
32.3k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
15094
15095
32.3k
  url_aggregator saved_url(*this);
15096
32.3k
  update_base_search(new_value, query_percent_encode_set);
15097
32.3k
  if (buffer.size() > ada::get_max_input_length()) {
15098
0
    *this = std::move(saved_url);
15099
0
    return;
15100
0
  }
15101
32.3k
  ADA_ASSERT_TRUE(validate());
15102
32.3k
}
15103
15104
18.7k
void url_aggregator::set_hash(const std::string_view input) {
15105
18.7k
  ada_log("url_aggregator::set_hash ", input);
15106
18.7k
  ADA_ASSERT_TRUE(validate());
15107
18.7k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15108
18.7k
  if (input.empty()) {
15109
1.53k
    if (components.hash_start != url_components::omitted) {
15110
122
      buffer.resize(components.hash_start);
15111
122
      components.hash_start = url_components::omitted;
15112
122
    }
15113
1.53k
    helpers::strip_trailing_spaces_from_opaque_path(*this);
15114
1.53k
    return;
15115
1.53k
  }
15116
15117
17.1k
  std::string new_value;
15118
17.1k
  new_value = input[0] == '#' ? input.substr(1) : input;
15119
17.1k
  helpers::remove_ascii_tab_or_newline(new_value);
15120
17.1k
  url_aggregator saved_url(*this);
15121
17.1k
  update_unencoded_base_hash(new_value);
15122
17.1k
  if (buffer.size() > ada::get_max_input_length()) {
15123
0
    *this = std::move(saved_url);
15124
0
    return;
15125
0
  }
15126
17.1k
  ADA_ASSERT_TRUE(validate());
15127
17.1k
}
15128
15129
8.79k
bool url_aggregator::set_href(const std::string_view input) {
15130
8.79k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15131
8.79k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
15132
8.79k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
15133
8.79k
  ada_log("url_aggregator::set_href, success :", out.has_value());
15134
15135
8.79k
  if (out) {
15136
    // The parser enforces get_max_input_length() on both the input and the
15137
    // normalized result. This is a defense-in-depth check.
15138
8.79k
    if (out->buffer.size() > ada::get_max_input_length()) {
15139
0
      return false;
15140
0
    }
15141
8.79k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
15142
    // TODO: Figure out why the following line puts test to never finish.
15143
8.79k
    *this = *out;
15144
8.79k
  }
15145
15146
8.79k
  return out.has_value();
15147
8.79k
}
15148
15149
885k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
15150
885k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
15151
885k
          " bytes]");
15152
885k
  ADA_ASSERT_TRUE(validate());
15153
885k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15154
885k
  if (input.empty()) {
15155
624
    return is_valid = false;
15156
624
  }  // technically unnecessary.
15157
  // If input starts with U+005B ([), then:
15158
884k
  if (input[0] == '[') {
15159
    // If input does not end with U+005D (]), validation error, return failure.
15160
17.8k
    if (input.back() != ']') {
15161
4.35k
      return is_valid = false;
15162
4.35k
    }
15163
13.5k
    ada_log("parse_host ipv6");
15164
15165
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
15166
    // trailing U+005D (]) removed.
15167
13.5k
    input.remove_prefix(1);
15168
13.5k
    input.remove_suffix(1);
15169
13.5k
    return parse_ipv6(input);
15170
17.8k
  }
15171
15172
  // If isNotSpecial is true, then return the result of opaque-host parsing
15173
  // input.
15174
866k
  if (!is_special()) {
15175
221k
    return parse_opaque_host(input);
15176
221k
  }
15177
  // Let domain be the result of running UTF-8 decode without BOM on the
15178
  // percent-decoding of input. Let asciiDomain be the result of running domain
15179
  // to ASCII with domain and false. The most common case is an ASCII input, in
15180
  // which case we do not need to call the expensive 'to_ascii' if a few
15181
  // conditions are met: no '%' and no 'xn-' subsequence.
15182
15183
  // Often, the input does not contain any forbidden code points, and no upper
15184
  // case ASCII letter, then we can just copy it to the buffer. We want to
15185
  // optimize for such a common case.
15186
15187
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
15188
644k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
15189
644k
  if (fast_result < checkers::ipv4_fast_fail) {
15190
    // Fast path succeeded - input is pure decimal IPv4
15191
1.55k
    if (!input.empty() && input.back() == '.') {
15192
336
      update_base_hostname(input.substr(0, input.size() - 1));
15193
1.22k
    } else {
15194
1.22k
      update_base_hostname(input);
15195
1.22k
    }
15196
1.55k
    host_type = IPV4;
15197
1.55k
    is_valid = true;
15198
1.55k
    ada_log("parse_host fast path decimal ipv4");
15199
1.55k
    ADA_ASSERT_TRUE(validate());
15200
1.55k
    return true;
15201
1.55k
  }
15202
643k
  uint8_t is_forbidden_or_upper =
15203
643k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
15204
643k
                                                             input.size());
15205
  // Minor optimization opportunity:
15206
  // contains_forbidden_domain_code_point_or_upper could be extend to check for
15207
  // the presence of characters that cannot appear in the ipv4 address and we
15208
  // could also check whether x and n and - are present, and so we could skip
15209
  // some of the checks below. However, the gains are likely to be small, and
15210
  // the code would be more complex.
15211
643k
  if (is_forbidden_or_upper == 0 &&
15212
495k
      input.find("xn-") == std::string_view::npos) {
15213
    // fast path
15214
479k
    update_base_hostname(input);
15215
15216
    // Check for other IPv4 formats (hex, octal, etc.)
15217
479k
    if (checkers::is_ipv4(get_hostname())) {
15218
46.8k
      ada_log("parse_host fast path ipv4");
15219
46.8k
      return parse_ipv4(get_hostname(), true);
15220
46.8k
    }
15221
433k
    ada_log("parse_host fast path ", get_hostname());
15222
433k
    is_valid = true;
15223
433k
    return true;
15224
479k
  }
15225
  // We have encountered at least one forbidden code point or the input contains
15226
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
15227
  // conversion.
15228
15229
163k
  ada_log("parse_host calling to_ascii");
15230
163k
  std::optional<std::string> host = std::string(get_hostname());
15231
163k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
15232
163k
  if (!is_valid) {
15233
89.7k
    ada_log("parse_host to_ascii returns false");
15234
89.7k
    return is_valid = false;
15235
89.7k
  }
15236
73.6k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
15237
73.6k
          " bytes]");
15238
15239
73.6k
  if (std::ranges::any_of(host.value(),
15240
73.6k
                          ada::unicode::is_forbidden_domain_code_point)) {
15241
0
    return is_valid = false;
15242
0
  }
15243
15244
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
15245
  // asciiDomain.
15246
73.6k
  if (checkers::is_ipv4(host.value())) {
15247
8.46k
    ada_log("parse_host got ipv4 ", *host);
15248
8.46k
    return parse_ipv4(host.value(), false);
15249
8.46k
  }
15250
15251
65.2k
  update_base_hostname(host.value());
15252
65.2k
  ADA_ASSERT_TRUE(validate());
15253
65.2k
  return true;
15254
73.6k
}
15255
15256
template <bool override_hostname>
15257
44.9k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
44.9k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
44.9k
  ADA_ASSERT_TRUE(validate());
15260
44.9k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
44.9k
  if (has_opaque_path) {
15262
2.26k
    return false;
15263
2.26k
  }
15264
15265
42.6k
  url_aggregator saved_url(*this);
15266
15267
42.6k
  std::string previous_host(get_hostname());
15268
42.6k
  uint32_t previous_port = components.port;
15269
15270
42.6k
  size_t host_end_pos = input.find('#');
15271
42.6k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
42.6k
                                      ? host_end_pos
15273
42.6k
                                      : input.size());
15274
42.6k
  helpers::remove_ascii_tab_or_newline(_host);
15275
42.6k
  std::string_view new_host(_host);
15276
15277
42.6k
  auto check_url_size = [&]() -> bool {
15278
16.9k
    if (buffer.size() > ada::get_max_input_length()) {
15279
0
      *this = std::move(saved_url);
15280
0
      return false;
15281
0
    }
15282
16.9k
    return true;
15283
16.9k
  };
ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Line
Count
Source
15277
11.2k
  auto check_url_size = [&]() -> bool {
15278
11.2k
    if (buffer.size() > ada::get_max_input_length()) {
15279
0
      *this = std::move(saved_url);
15280
0
      return false;
15281
0
    }
15282
11.2k
    return true;
15283
11.2k
  };
ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Line
Count
Source
15277
5.70k
  auto check_url_size = [&]() -> bool {
15278
5.70k
    if (buffer.size() > ada::get_max_input_length()) {
15279
0
      *this = std::move(saved_url);
15280
0
      return false;
15281
0
    }
15282
5.70k
    return true;
15283
5.70k
  };
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
42.6k
  if (type != ada::scheme::type::FILE) {
15288
38.0k
    std::string_view host_view(_host.data(), _host.length());
15289
38.0k
    auto [location, found_colon] =
15290
38.0k
        helpers::get_host_delimiter_location(is_special(), host_view);
15291
15292
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
15293
    // Note: the 'found_colon' value is true if and only if a colon was
15294
    // encountered while not inside brackets.
15295
38.0k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
16.7k
      std::string_view host_buffer = host_view.substr(0, location);
15299
16.7k
      if (host_buffer.empty()) {
15300
226
        return false;
15301
226
      }
15302
15303
      // If state override is given and state override is hostname state, then
15304
      // return failure.
15305
16.5k
      if constexpr (override_hostname) {
15306
7.83k
        return false;
15307
7.83k
      }
15308
15309
      // Let host be the result of host parsing buffer with url is not special.
15310
0
      bool succeeded = parse_host(host_buffer);
15311
16.5k
      if (!succeeded) {
15312
897
        update_base_hostname(previous_host);
15313
897
        update_base_port(previous_port);
15314
897
        return false;
15315
897
      }
15316
15317
      // Set url's host to host, buffer to the empty string, and state to port
15318
      // state.
15319
15.6k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
15.6k
      if (!port_buffer.empty()) {
15321
7.12k
        set_port(port_buffer);
15322
7.12k
      }
15323
15.6k
      return check_url_size();
15324
16.5k
    }
15325
    // Otherwise, if one of the following is true:
15326
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
15327
    // - url is special and c is U+005C (\)
15328
21.3k
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
21.3k
      if (host_view.empty() && is_special()) {
15332
6.68k
        return false;
15333
6.68k
      }
15334
15335
      // Otherwise, if state override is given, host_view is the empty string,
15336
      // and either url includes credentials or url's port is non-null, then
15337
      // return failure.
15338
14.6k
      if (host_view.empty() && (has_credentials() || has_port())) {
15339
0
        return false;
15340
0
      }
15341
15342
      // Let host be the result of host parsing host_view with url is not
15343
      // special.
15344
14.6k
      if (host_view.empty() && !is_special()) {
15345
0
        if (has_hostname()) {
15346
0
          clear_hostname();  // easy!
15347
0
        } else if (has_dash_dot()) {
15348
0
          add_authority_slashes_if_needed();
15349
0
          delete_dash_dot();
15350
0
        }
15351
0
        return check_url_size();
15352
0
      }
15353
15354
14.6k
      bool succeeded = parse_host(host_view);
15355
14.6k
      if (!succeeded) {
15356
6.37k
        update_base_hostname(previous_host);
15357
6.37k
        update_base_port(previous_port);
15358
6.37k
        return false;
15359
8.28k
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
8.28k
      return check_url_size();
15364
14.6k
    }
15365
38.0k
  }
15366
15367
4.58k
  size_t location = new_host.find_first_of("/\\?");
15368
4.58k
  if (location != std::string_view::npos) {
15369
2.29k
    new_host.remove_suffix(new_host.length() - location);
15370
2.29k
  }
15371
15372
4.58k
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
92
    clear_hostname();
15375
4.49k
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
4.49k
    if (!parse_host(new_host)) {
15378
3.67k
      update_base_hostname(previous_host);
15379
3.67k
      update_base_port(previous_port);
15380
3.67k
      return false;
15381
3.67k
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
821
    if (helpers::substring(buffer, components.host_start,
15385
821
                           components.host_end) == "localhost") {
15386
24
      clear_hostname();
15387
24
    }
15388
821
  }
15389
913
  ADA_ASSERT_TRUE(validate());
15390
913
  return check_url_size();
15391
4.58k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
15257
21.1k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
21.1k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
21.1k
  ADA_ASSERT_TRUE(validate());
15260
21.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
21.1k
  if (has_opaque_path) {
15262
1.13k
    return false;
15263
1.13k
  }
15264
15265
20.0k
  url_aggregator saved_url(*this);
15266
15267
20.0k
  std::string previous_host(get_hostname());
15268
20.0k
  uint32_t previous_port = components.port;
15269
15270
20.0k
  size_t host_end_pos = input.find('#');
15271
20.0k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
20.0k
                                      ? host_end_pos
15273
20.0k
                                      : input.size());
15274
20.0k
  helpers::remove_ascii_tab_or_newline(_host);
15275
20.0k
  std::string_view new_host(_host);
15276
15277
20.0k
  auto check_url_size = [&]() -> bool {
15278
20.0k
    if (buffer.size() > ada::get_max_input_length()) {
15279
20.0k
      *this = std::move(saved_url);
15280
20.0k
      return false;
15281
20.0k
    }
15282
20.0k
    return true;
15283
20.0k
  };
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
20.0k
  if (type != ada::scheme::type::FILE) {
15288
17.7k
    std::string_view host_view(_host.data(), _host.length());
15289
17.7k
    auto [location, found_colon] =
15290
17.7k
        helpers::get_host_delimiter_location(is_special(), host_view);
15291
15292
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
15293
    // Note: the 'found_colon' value is true if and only if a colon was
15294
    // encountered while not inside brackets.
15295
17.7k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
8.79k
      std::string_view host_buffer = host_view.substr(0, location);
15299
8.79k
      if (host_buffer.empty()) {
15300
109
        return false;
15301
109
      }
15302
15303
      // If state override is given and state override is hostname state, then
15304
      // return failure.
15305
      if constexpr (override_hostname) {
15306
        return false;
15307
      }
15308
15309
      // Let host be the result of host parsing buffer with url is not special.
15310
8.68k
      bool succeeded = parse_host(host_buffer);
15311
8.68k
      if (!succeeded) {
15312
897
        update_base_hostname(previous_host);
15313
897
        update_base_port(previous_port);
15314
897
        return false;
15315
897
      }
15316
15317
      // Set url's host to host, buffer to the empty string, and state to port
15318
      // state.
15319
7.78k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
7.78k
      if (!port_buffer.empty()) {
15321
7.12k
        set_port(port_buffer);
15322
7.12k
      }
15323
7.78k
      return check_url_size();
15324
8.68k
    }
15325
    // Otherwise, if one of the following is true:
15326
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
15327
    // - url is special and c is U+005C (\)
15328
8.94k
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
8.94k
      if (host_view.empty() && is_special()) {
15332
3.28k
        return false;
15333
3.28k
      }
15334
15335
      // Otherwise, if state override is given, host_view is the empty string,
15336
      // and either url includes credentials or url's port is non-null, then
15337
      // return failure.
15338
5.65k
      if (host_view.empty() && (has_credentials() || has_port())) {
15339
0
        return false;
15340
0
      }
15341
15342
      // Let host be the result of host parsing host_view with url is not
15343
      // special.
15344
5.65k
      if (host_view.empty() && !is_special()) {
15345
0
        if (has_hostname()) {
15346
0
          clear_hostname();  // easy!
15347
0
        } else if (has_dash_dot()) {
15348
0
          add_authority_slashes_if_needed();
15349
0
          delete_dash_dot();
15350
0
        }
15351
0
        return check_url_size();
15352
0
      }
15353
15354
5.65k
      bool succeeded = parse_host(host_view);
15355
5.65k
      if (!succeeded) {
15356
2.59k
        update_base_hostname(previous_host);
15357
2.59k
        update_base_port(previous_port);
15358
2.59k
        return false;
15359
3.06k
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
3.06k
      return check_url_size();
15364
5.65k
    }
15365
17.7k
  }
15366
15367
2.27k
  size_t location = new_host.find_first_of("/\\?");
15368
2.27k
  if (location != std::string_view::npos) {
15369
1.13k
    new_host.remove_suffix(new_host.length() - location);
15370
1.13k
  }
15371
15372
2.27k
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
37
    clear_hostname();
15375
2.23k
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
2.23k
    if (!parse_host(new_host)) {
15378
1.84k
      update_base_hostname(previous_host);
15379
1.84k
      update_base_port(previous_port);
15380
1.84k
      return false;
15381
1.84k
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
390
    if (helpers::substring(buffer, components.host_start,
15385
390
                           components.host_end) == "localhost") {
15386
13
      clear_hostname();
15387
13
    }
15388
390
  }
15389
427
  ADA_ASSERT_TRUE(validate());
15390
427
  return check_url_size();
15391
2.27k
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
15257
23.8k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
23.8k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
23.8k
  ADA_ASSERT_TRUE(validate());
15260
23.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
23.8k
  if (has_opaque_path) {
15262
1.13k
    return false;
15263
1.13k
  }
15264
15265
22.6k
  url_aggregator saved_url(*this);
15266
15267
22.6k
  std::string previous_host(get_hostname());
15268
22.6k
  uint32_t previous_port = components.port;
15269
15270
22.6k
  size_t host_end_pos = input.find('#');
15271
22.6k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
22.6k
                                      ? host_end_pos
15273
22.6k
                                      : input.size());
15274
22.6k
  helpers::remove_ascii_tab_or_newline(_host);
15275
22.6k
  std::string_view new_host(_host);
15276
15277
22.6k
  auto check_url_size = [&]() -> bool {
15278
22.6k
    if (buffer.size() > ada::get_max_input_length()) {
15279
22.6k
      *this = std::move(saved_url);
15280
22.6k
      return false;
15281
22.6k
    }
15282
22.6k
    return true;
15283
22.6k
  };
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
22.6k
  if (type != ada::scheme::type::FILE) {
15288
20.3k
    std::string_view host_view(_host.data(), _host.length());
15289
20.3k
    auto [location, found_colon] =
15290
20.3k
        helpers::get_host_delimiter_location(is_special(), host_view);
15291
15292
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
15293
    // Note: the 'found_colon' value is true if and only if a colon was
15294
    // encountered while not inside brackets.
15295
20.3k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
7.95k
      std::string_view host_buffer = host_view.substr(0, location);
15299
7.95k
      if (host_buffer.empty()) {
15300
117
        return false;
15301
117
      }
15302
15303
      // If state override is given and state override is hostname state, then
15304
      // return failure.
15305
7.83k
      if constexpr (override_hostname) {
15306
7.83k
        return false;
15307
7.83k
      }
15308
15309
      // Let host be the result of host parsing buffer with url is not special.
15310
0
      bool succeeded = parse_host(host_buffer);
15311
7.83k
      if (!succeeded) {
15312
0
        update_base_hostname(previous_host);
15313
0
        update_base_port(previous_port);
15314
0
        return false;
15315
0
      }
15316
15317
      // Set url's host to host, buffer to the empty string, and state to port
15318
      // state.
15319
7.83k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
7.83k
      if (!port_buffer.empty()) {
15321
0
        set_port(port_buffer);
15322
0
      }
15323
7.83k
      return check_url_size();
15324
7.83k
    }
15325
    // Otherwise, if one of the following is true:
15326
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
15327
    // - url is special and c is U+005C (\)
15328
12.4k
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
12.4k
      if (host_view.empty() && is_special()) {
15332
3.40k
        return false;
15333
3.40k
      }
15334
15335
      // Otherwise, if state override is given, host_view is the empty string,
15336
      // and either url includes credentials or url's port is non-null, then
15337
      // return failure.
15338
9.00k
      if (host_view.empty() && (has_credentials() || has_port())) {
15339
0
        return false;
15340
0
      }
15341
15342
      // Let host be the result of host parsing host_view with url is not
15343
      // special.
15344
9.00k
      if (host_view.empty() && !is_special()) {
15345
0
        if (has_hostname()) {
15346
0
          clear_hostname();  // easy!
15347
0
        } else if (has_dash_dot()) {
15348
0
          add_authority_slashes_if_needed();
15349
0
          delete_dash_dot();
15350
0
        }
15351
0
        return check_url_size();
15352
0
      }
15353
15354
9.00k
      bool succeeded = parse_host(host_view);
15355
9.00k
      if (!succeeded) {
15356
3.78k
        update_base_hostname(previous_host);
15357
3.78k
        update_base_port(previous_port);
15358
3.78k
        return false;
15359
5.22k
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
5.22k
      return check_url_size();
15364
9.00k
    }
15365
20.3k
  }
15366
15367
2.31k
  size_t location = new_host.find_first_of("/\\?");
15368
2.31k
  if (location != std::string_view::npos) {
15369
1.16k
    new_host.remove_suffix(new_host.length() - location);
15370
1.16k
  }
15371
15372
2.31k
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
55
    clear_hostname();
15375
2.26k
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
2.26k
    if (!parse_host(new_host)) {
15378
1.83k
      update_base_hostname(previous_host);
15379
1.83k
      update_base_port(previous_port);
15380
1.83k
      return false;
15381
1.83k
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
431
    if (helpers::substring(buffer, components.host_start,
15385
431
                           components.host_end) == "localhost") {
15386
11
      clear_hostname();
15387
11
    }
15388
431
  }
15389
486
  ADA_ASSERT_TRUE(validate());
15390
486
  return check_url_size();
15391
2.31k
}
15392
15393
21.1k
bool url_aggregator::set_host(const std::string_view input) {
15394
21.1k
  ada_log("url_aggregator::set_host '", input, "'");
15395
21.1k
  ADA_ASSERT_TRUE(validate());
15396
21.1k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15397
21.1k
  return set_host_or_hostname<false>(input);
15398
21.1k
}
15399
15400
23.8k
bool url_aggregator::set_hostname(const std::string_view input) {
15401
23.8k
  ada_log("url_aggregator::set_hostname '", input, "'");
15402
23.8k
  ADA_ASSERT_TRUE(validate());
15403
23.8k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15404
23.8k
  return set_host_or_hostname<true>(input);
15405
23.8k
}
15406
15407
44.9k
[[nodiscard]] std::string url_aggregator::get_origin() const {
15408
44.9k
  ada_log("url_aggregator::get_origin");
15409
44.9k
  if (is_special()) {
15410
    // Return a new opaque origin.
15411
36.0k
    if (type == scheme::FILE) {
15412
5.25k
      return "null";
15413
5.25k
    }
15414
15415
30.7k
    return helpers::concat(get_protocol(), "//", get_host());
15416
36.0k
  }
15417
15418
8.90k
  if (get_protocol() == "blob:") {
15419
2.90k
    std::string_view path = get_pathname();
15420
2.90k
    if (!path.empty()) {
15421
2.68k
      auto out = ada::parse<ada::url_aggregator>(path);
15422
2.68k
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
15423
        // If pathURL's scheme is not "http" and not "https", then return a
15424
        // new opaque origin.
15425
75
        return helpers::concat(out->get_protocol(), "//", out->get_host());
15426
75
      }
15427
2.68k
    }
15428
2.90k
  }
15429
15430
  // Return a new opaque origin.
15431
8.83k
  return "null";
15432
8.90k
}
15433
15434
[[nodiscard]] std::string_view url_aggregator::get_username() const
15435
226k
    ada_lifetime_bound {
15436
226k
  ada_log("url_aggregator::get_username");
15437
226k
  if (has_non_empty_username()) {
15438
40.5k
    return helpers::substring(buffer, components.protocol_end + 2,
15439
40.5k
                              components.username_end);
15440
40.5k
  }
15441
186k
  return "";
15442
226k
}
15443
15444
[[nodiscard]] std::string_view url_aggregator::get_password() const
15445
226k
    ada_lifetime_bound {
15446
226k
  ada_log("url_aggregator::get_password");
15447
226k
  if (has_non_empty_password()) {
15448
31.3k
    return helpers::substring(buffer, components.username_end + 1,
15449
31.3k
                              components.host_start);
15450
31.3k
  }
15451
195k
  return "";
15452
226k
}
15453
15454
[[nodiscard]] std::string_view url_aggregator::get_port() const
15455
256k
    ada_lifetime_bound {
15456
256k
  ada_log("url_aggregator::get_port");
15457
256k
  if (components.port == url_components::omitted) {
15458
245k
    return "";
15459
245k
  }
15460
10.6k
  return helpers::substring(buffer, components.host_end + 1,
15461
10.6k
                            components.pathname_start);
15462
256k
}
15463
15464
[[nodiscard]] std::string_view url_aggregator::get_hash() const
15465
162k
    ada_lifetime_bound {
15466
162k
  ada_log("url_aggregator::get_hash");
15467
  // If this's URL's fragment is either null or the empty string, then return
15468
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
15469
162k
  if (components.hash_start == url_components::omitted) {
15470
120k
    return "";
15471
120k
  }
15472
41.8k
  if (buffer.size() - components.hash_start <= 1) {
15473
2.74k
    return "";
15474
2.74k
  }
15475
39.0k
  return helpers::substring(buffer, components.hash_start);
15476
41.8k
}
15477
15478
[[nodiscard]] std::string_view url_aggregator::get_host() const
15479
102k
    ada_lifetime_bound {
15480
102k
  ada_log("url_aggregator::get_host");
15481
  // Technically, we should check if there is a hostname, but
15482
  // the code below works even if there isn't.
15483
  // if(!has_hostname()) { return ""; }
15484
102k
  size_t start = components.host_start;
15485
102k
  if (components.host_end > components.host_start &&
15486
89.2k
      buffer[components.host_start] == '@') {
15487
40.5k
    start++;
15488
40.5k
  }
15489
  // if we have an empty host, then the space between components.host_end and
15490
  // components.pathname_start may be occupied by /.
15491
102k
  if (start == components.host_end) {
15492
13.4k
    return {};
15493
13.4k
  }
15494
89.2k
  return helpers::substring(buffer, start, components.pathname_start);
15495
102k
}
15496
15497
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
15498
992k
    ada_lifetime_bound {
15499
992k
  ada_log("url_aggregator::get_hostname");
15500
  // Technically, we should check if there is a hostname, but
15501
  // the code below works even if there isn't.
15502
  // if(!has_hostname()) { return ""; }
15503
992k
  size_t start = components.host_start;
15504
  // So host_start is not where the host begins.
15505
992k
  if (components.host_end > components.host_start &&
15506
834k
      buffer[components.host_start] == '@') {
15507
124k
    start++;
15508
124k
  }
15509
992k
  return helpers::substring(buffer, start, components.host_end);
15510
992k
}
15511
15512
[[nodiscard]] std::string_view url_aggregator::get_search() const
15513
190k
    ada_lifetime_bound {
15514
190k
  ada_log("url_aggregator::get_search");
15515
  // If this's URL's query is either null or the empty string, then return the
15516
  // empty string. Return U+003F (?), followed by this's URL's query.
15517
190k
  if (components.search_start == url_components::omitted) {
15518
117k
    return "";
15519
117k
  }
15520
73.4k
  auto ending_index = uint32_t(buffer.size());
15521
73.4k
  if (components.hash_start != url_components::omitted) {
15522
38.1k
    ending_index = components.hash_start;
15523
38.1k
  }
15524
73.4k
  if (ending_index - components.search_start <= 1) {
15525
5.19k
    return "";
15526
5.19k
  }
15527
68.2k
  return helpers::substring(buffer, components.search_start, ending_index);
15528
73.4k
}
15529
15530
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
15531
411k
    ada_lifetime_bound {
15532
411k
  ada_log("url_aggregator::get_protocol");
15533
411k
  return helpers::substring(buffer, 0, components.protocol_end);
15534
411k
}
15535
15536
32.8k
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
15537
32.8k
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
15538
32.8k
          " bytes]");
15539
32.8k
  if (!is_valid) {
15540
3.05k
    return "null";
15541
3.05k
  }
15542
15543
29.8k
  std::string answer;
15544
29.8k
  auto back = std::back_insert_iterator(answer);
15545
29.8k
  answer.append("{\n");
15546
15547
29.8k
  answer.append("\t\"buffer\":\"");
15548
29.8k
  helpers::encode_json(buffer, back);
15549
29.8k
  answer.append("\",\n");
15550
15551
29.8k
  answer.append("\t\"protocol\":\"");
15552
29.8k
  helpers::encode_json(get_protocol(), back);
15553
29.8k
  answer.append("\",\n");
15554
15555
29.8k
  if (has_credentials()) {
15556
10.2k
    answer.append("\t\"username\":\"");
15557
10.2k
    helpers::encode_json(get_username(), back);
15558
10.2k
    answer.append("\",\n");
15559
10.2k
    answer.append("\t\"password\":\"");
15560
10.2k
    helpers::encode_json(get_password(), back);
15561
10.2k
    answer.append("\",\n");
15562
10.2k
  }
15563
15564
29.8k
  answer.append("\t\"host\":\"");
15565
29.8k
  helpers::encode_json(get_host(), back);
15566
29.8k
  answer.append("\",\n");
15567
15568
29.8k
  answer.append("\t\"path\":\"");
15569
29.8k
  helpers::encode_json(get_pathname(), back);
15570
29.8k
  answer.append("\",\n");
15571
29.8k
  answer.append("\t\"opaque path\":");
15572
29.8k
  answer.append((has_opaque_path ? "true" : "false"));
15573
29.8k
  answer.append(",\n");
15574
15575
29.8k
  if (components.search_start != url_components::omitted) {
15576
12.0k
    answer.append("\t\"query\":\"");
15577
12.0k
    helpers::encode_json(get_search(), back);
15578
12.0k
    answer.append("\",\n");
15579
12.0k
  }
15580
29.8k
  if (components.hash_start != url_components::omitted) {
15581
10.4k
    answer.append("\t\"fragment\":\"");
15582
10.4k
    helpers::encode_json(get_hash(), back);
15583
10.4k
    answer.append("\",\n");
15584
10.4k
  }
15585
15586
238k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15587
238k
    if (offset == url_components::omitted) {
15588
64.9k
      return "null";
15589
173k
    } else {
15590
173k
      return std::to_string(offset);
15591
173k
    }
15592
238k
  };
Unexecuted instantiation: idna.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Unexecuted instantiation: ada.cpp:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Unexecuted instantiation: serializers.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Unexecuted instantiation: can_parse.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Unexecuted instantiation: unicode.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
parse.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Line
Count
Source
15586
238k
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15587
238k
    if (offset == url_components::omitted) {
15588
64.9k
      return "null";
15589
173k
    } else {
15590
173k
      return std::to_string(offset);
15591
173k
    }
15592
238k
  };
Unexecuted instantiation: url_pattern.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
Unexecuted instantiation: url_search_params.cc:ada::url_aggregator::to_string() const::$_0::operator()(unsigned int) const
15593
15594
29.8k
  answer.append("\t\"protocol_end\":");
15595
29.8k
  answer.append(convert_offset_to_string(components.protocol_end));
15596
29.8k
  answer.append(",\n");
15597
15598
29.8k
  answer.append("\t\"username_end\":");
15599
29.8k
  answer.append(convert_offset_to_string(components.username_end));
15600
29.8k
  answer.append(",\n");
15601
15602
29.8k
  answer.append("\t\"host_start\":");
15603
29.8k
  answer.append(convert_offset_to_string(components.host_start));
15604
29.8k
  answer.append(",\n");
15605
15606
29.8k
  answer.append("\t\"host_end\":");
15607
29.8k
  answer.append(convert_offset_to_string(components.host_end));
15608
29.8k
  answer.append(",\n");
15609
15610
29.8k
  answer.append("\t\"port\":");
15611
29.8k
  answer.append(convert_offset_to_string(components.port));
15612
29.8k
  answer.append(",\n");
15613
15614
29.8k
  answer.append("\t\"pathname_start\":");
15615
29.8k
  answer.append(convert_offset_to_string(components.pathname_start));
15616
29.8k
  answer.append(",\n");
15617
15618
29.8k
  answer.append("\t\"search_start\":");
15619
29.8k
  answer.append(convert_offset_to_string(components.search_start));
15620
29.8k
  answer.append(",\n");
15621
15622
29.8k
  answer.append("\t\"hash_start\":");
15623
29.8k
  answer.append(convert_offset_to_string(components.hash_start));
15624
29.8k
  answer.append("\n}");
15625
15626
29.8k
  return answer;
15627
32.8k
}
15628
15629
32.8k
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15630
32.8k
  if (components.host_start == components.host_end) {
15631
4.80k
    return false;
15632
4.80k
  }
15633
  // Avoid allocation: construct a string_view directly into the buffer.
15634
28.0k
  size_t start = components.host_start;
15635
28.0k
  if (components.host_end > components.host_start &&
15636
28.0k
      buffer[components.host_start] == '@') {
15637
12.4k
    start++;
15638
12.4k
  }
15639
28.0k
  return checkers::verify_dns_length(
15640
28.0k
      std::string_view(buffer.data() + start, components.host_end - start));
15641
32.8k
}
15642
15643
55.2k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15644
55.2k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15645
55.2k
          " bytes], overlaps with buffer: ",
15646
55.2k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15647
55.2k
  ADA_ASSERT_TRUE(validate());
15648
55.2k
  const bool trailing_dot = (input.back() == '.');
15649
55.2k
  if (trailing_dot) {
15650
1.68k
    input.remove_suffix(1);
15651
1.68k
  }
15652
55.2k
  size_t digit_count{0};
15653
55.2k
  int pure_decimal_count = 0;  // entries that are decimal
15654
55.2k
  uint64_t ipv4{0};
15655
  // we could unroll for better performance?
15656
66.2k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15657
66.0k
    uint32_t
15658
66.0k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15659
66.0k
    bool is_hex = checkers::has_hex_prefix(input);
15660
66.0k
    if (is_hex && ((input.length() == 2) ||
15661
14.6k
                   ((input.length() > 2) && (input[2] == '.')))) {
15662
      // special case
15663
1.15k
      segment_result = 0;
15664
1.15k
      input.remove_prefix(2);
15665
64.8k
    } else {
15666
64.8k
      std::from_chars_result r{};
15667
64.8k
      if (is_hex) {
15668
14.2k
        ada_log("parse_ipv4 trying to parse hex number");
15669
14.2k
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15670
14.2k
                            segment_result, 16);
15671
50.5k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15672
13.0k
                 checkers::is_digit(input[1])) {
15673
9.74k
        ada_log("parse_ipv4 trying to parse octal number");
15674
9.74k
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15675
9.74k
                            segment_result, 8);
15676
40.8k
      } else {
15677
40.8k
        ada_log("parse_ipv4 trying to parse decimal number");
15678
40.8k
        pure_decimal_count++;
15679
40.8k
        r = std::from_chars(input.data(), input.data() + input.size(),
15680
40.8k
                            segment_result, 10);
15681
40.8k
      }
15682
64.8k
      if (r.ec != std::errc()) {
15683
8.97k
        ada_log("parse_ipv4 parsing failed");
15684
8.97k
        return is_valid = false;
15685
8.97k
      }
15686
55.8k
      ada_log("parse_ipv4 parsed ", segment_result);
15687
55.8k
      input.remove_prefix(r.ptr - input.data());
15688
55.8k
    }
15689
57.0k
    if (input.empty()) {
15690
      // We have the last value.
15691
      // At this stage, ipv4 contains digit_count*8 bits.
15692
      // So we have 32-digit_count*8 bits left.
15693
42.7k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15694
1.34k
        return is_valid = false;
15695
1.34k
      }
15696
41.3k
      ipv4 <<= (32 - digit_count * 8);
15697
41.3k
      ipv4 |= segment_result;
15698
41.3k
      goto final;
15699
42.7k
    } else {
15700
      // There is more, so that the value must no be larger than 255
15701
      // and we must have a '.'.
15702
14.3k
      if ((segment_result > 255) || (input[0] != '.')) {
15703
3.33k
        return is_valid = false;
15704
3.33k
      }
15705
11.0k
      ipv4 <<= 8;
15706
11.0k
      ipv4 |= segment_result;
15707
11.0k
      input.remove_prefix(1);  // remove '.'
15708
11.0k
    }
15709
57.0k
  }
15710
278
  if ((digit_count != 4) || (!input.empty())) {
15711
278
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15712
278
    return is_valid = false;
15713
278
  }
15714
41.3k
final:
15715
41.3k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15716
41.3k
          " host: ", get_host());
15717
15718
  // We could also check r.ptr to see where the parsing ended.
15719
41.3k
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15720
0
    ada_log(
15721
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15722
0
        "buffer");
15723
    // The original input was already all decimal and we validated it. So we
15724
    // don't need to do anything.
15725
41.3k
  } else {
15726
41.3k
    ada_log("url_aggregator::parse_ipv4 completed and we need to update it");
15727
    // Optimization opportunity: Get rid of unnecessary string return in ipv4
15728
    // serializer.
15729
    // TODO: This is likely a bug because it goes back update_base_hostname, not
15730
    // what we want to do.
15731
41.3k
    update_base_hostname(
15732
41.3k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15733
41.3k
  }
15734
41.3k
  host_type = IPV4;
15735
41.3k
  ADA_ASSERT_TRUE(validate());
15736
41.3k
  return true;
15737
278
}
15738
15739
13.5k
bool url_aggregator::parse_ipv6(std::string_view input) {
15740
  // TODO: Implement in_place optimization: we know that input points
15741
  // in the buffer, so we can just check whether the buffer is already
15742
  // well formatted.
15743
  // TODO: Find a way to merge parse_ipv6 with url.cpp implementation.
15744
13.5k
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15745
13.5k
  ADA_ASSERT_TRUE(validate());
15746
13.5k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15747
13.5k
  if (input.empty()) {
15748
382
    return is_valid = false;
15749
382
  }
15750
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15751
13.1k
  std::array<uint16_t, 8> address{};
15752
15753
  // Let pieceIndex be 0.
15754
13.1k
  int piece_index = 0;
15755
15756
  // Let compress be null.
15757
13.1k
  std::optional<int> compress{};
15758
15759
  // Let pointer be a pointer for input.
15760
13.1k
  std::string_view::iterator pointer = input.begin();
15761
15762
  // If c is U+003A (:), then:
15763
13.1k
  if (input[0] == ':') {
15764
    // If remaining does not start with U+003A (:), validation error, return
15765
    // failure.
15766
2.63k
    if (input.size() == 1 || input[1] != ':') {
15767
244
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15768
244
      return is_valid = false;
15769
244
    }
15770
15771
    // Increase pointer by 2.
15772
2.38k
    pointer += 2;
15773
15774
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15775
2.38k
    compress = ++piece_index;
15776
2.38k
  }
15777
15778
  // While c is not the EOF code point:
15779
29.0k
  while (pointer != input.end()) {
15780
    // If pieceIndex is 8, validation error, return failure.
15781
24.1k
    if (piece_index == 8) {
15782
103
      ada_log("parse_ipv6 piece_index == 8");
15783
103
      return is_valid = false;
15784
103
    }
15785
15786
    // If c is U+003A (:), then:
15787
24.0k
    if (*pointer == ':') {
15788
      // If compress is non-null, validation error, return failure.
15789
2.07k
      if (compress.has_value()) {
15790
175
        ada_log("parse_ipv6 compress is non-null");
15791
175
        return is_valid = false;
15792
175
      }
15793
15794
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15795
      // then continue.
15796
1.90k
      pointer++;
15797
1.90k
      compress = ++piece_index;
15798
1.90k
      continue;
15799
2.07k
    }
15800
15801
    // Let value and length be 0.
15802
21.9k
    uint16_t value = 0, length = 0;
15803
15804
    // While length is less than 4 and c is an ASCII hex digit,
15805
    // set value to value times 0x10 + c interpreted as hexadecimal number, and
15806
    // increase pointer and length by 1.
15807
52.2k
    while (length < 4 && pointer != input.end() &&
15808
47.0k
           unicode::is_ascii_hex_digit(*pointer)) {
15809
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15810
30.3k
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15811
30.3k
      pointer++;
15812
30.3k
      length++;
15813
30.3k
    }
15814
15815
    // If c is U+002E (.), then:
15816
21.9k
    if (pointer != input.end() && *pointer == '.') {
15817
      // If length is 0, validation error, return failure.
15818
2.45k
      if (length == 0) {
15819
180
        ada_log("parse_ipv6 length is 0");
15820
180
        return is_valid = false;
15821
180
      }
15822
15823
      // Decrease pointer by length.
15824
2.27k
      pointer -= length;
15825
15826
      // If pieceIndex is greater than 6, validation error, return failure.
15827
2.27k
      if (piece_index > 6) {
15828
99
        ada_log("parse_ipv6 piece_index > 6");
15829
99
        return is_valid = false;
15830
99
      }
15831
15832
      // Let numbersSeen be 0.
15833
2.17k
      int numbers_seen = 0;
15834
15835
      // While c is not the EOF code point:
15836
5.94k
      while (pointer != input.end()) {
15837
        // Let ipv4Piece be null.
15838
5.32k
        std::optional<uint16_t> ipv4_piece{};
15839
15840
        // If numbersSeen is greater than 0, then:
15841
5.32k
        if (numbers_seen > 0) {
15842
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15843
          // pointer by 1.
15844
3.14k
          if (*pointer == '.' && numbers_seen < 4) {
15845
2.58k
            pointer++;
15846
2.58k
          } else {
15847
            // Otherwise, validation error, return failure.
15848
559
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15849
559
            return is_valid = false;
15850
559
          }
15851
3.14k
        }
15852
15853
        // If c is not an ASCII digit, validation error, return failure.
15854
4.76k
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15855
467
          ada_log(
15856
467
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15857
467
              "failure");
15858
467
          return is_valid = false;
15859
467
        }
15860
15861
        // While c is an ASCII digit:
15862
10.6k
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15863
          // Let number be c interpreted as decimal number.
15864
6.83k
          int number = *pointer - '0';
15865
15866
          // If ipv4Piece is null, then set ipv4Piece to number.
15867
6.83k
          if (!ipv4_piece.has_value()) {
15868
4.29k
            ipv4_piece = number;
15869
4.29k
          }
15870
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15871
2.54k
          else if (ipv4_piece == 0) {
15872
126
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15873
126
            return is_valid = false;
15874
126
          }
15875
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15876
2.41k
          else {
15877
2.41k
            ipv4_piece = *ipv4_piece * 10 + number;
15878
2.41k
          }
15879
15880
          // If ipv4Piece is greater than 255, validation error, return failure.
15881
6.71k
          if (ipv4_piece > 255) {
15882
397
            ada_log("parse_ipv6 ipv4_piece > 255");
15883
397
            return is_valid = false;
15884
397
          }
15885
15886
          // Increase pointer by 1.
15887
6.31k
          pointer++;
15888
6.31k
        }
15889
15890
        // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
15891
        // ipv4Piece.
15892
        // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15893
3.77k
        if (!ipv4_piece.has_value()) {
15894
0
          return is_valid = false;
15895
0
        }
15896
3.77k
        address[piece_index] =
15897
3.77k
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15898
15899
        // Increase numbersSeen by 1.
15900
3.77k
        numbers_seen++;
15901
15902
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15903
3.77k
        if (numbers_seen == 2 || numbers_seen == 4) {
15904
1.48k
          piece_index++;
15905
1.48k
        }
15906
3.77k
      }
15907
15908
      // If numbersSeen is not 4, validation error, return failure.
15909
627
      if (numbers_seen != 4) {
15910
419
        return is_valid = false;
15911
419
      }
15912
15913
      // Break.
15914
208
      break;
15915
627
    }
15916
    // Otherwise, if c is U+003A (:):
15917
19.5k
    else if ((pointer != input.end()) && (*pointer == ':')) {
15918
      // Increase pointer by 1.
15919
10.7k
      pointer++;
15920
15921
      // If c is the EOF code point, validation error, return failure.
15922
10.7k
      if (pointer == input.end()) {
15923
173
        ada_log(
15924
173
            "parse_ipv6 If c is the EOF code point, validation error, return "
15925
173
            "failure");
15926
173
        return is_valid = false;
15927
173
      }
15928
10.7k
    }
15929
    // Otherwise, if c is not the EOF code point, validation error, return
15930
    // failure.
15931
8.75k
    else if (pointer != input.end()) {
15932
5.04k
      ada_log(
15933
5.04k
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15934
5.04k
          "error, return failure");
15935
5.04k
      return is_valid = false;
15936
5.04k
    }
15937
15938
    // Set address[pieceIndex] to value.
15939
14.2k
    address[piece_index] = value;
15940
15941
    // Increase pieceIndex by 1.
15942
14.2k
    piece_index++;
15943
14.2k
  }
15944
15945
  // If compress is non-null, then:
15946
5.14k
  if (compress.has_value()) {
15947
    // Let swaps be pieceIndex - compress.
15948
3.71k
    int swaps = piece_index - *compress;
15949
15950
    // Set pieceIndex to 7.
15951
3.71k
    piece_index = 7;
15952
15953
    // While pieceIndex is not 0 and swaps is greater than 0,
15954
    // swap address[pieceIndex] with address[compress + swaps - 1], and then
15955
    // decrease both pieceIndex and swaps by 1.
15956
9.38k
    while (piece_index != 0 && swaps > 0) {
15957
5.67k
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15958
5.67k
      piece_index--;
15959
5.67k
      swaps--;
15960
5.67k
    }
15961
3.71k
  }
15962
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15963
  // return failure.
15964
1.42k
  else if (piece_index != 8) {
15965
1.28k
    ada_log(
15966
1.28k
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15967
1.28k
        "error, return failure");
15968
1.28k
    return is_valid = false;
15969
1.28k
  }
15970
  // TODO: Optimization opportunity: Get rid of unnecessary string creation.
15971
  // TODO: This is likely a bug because it goes back update_base_hostname, not
15972
  // what we want to do.
15973
3.85k
  update_base_hostname(ada::serializers::ipv6(address));
15974
3.85k
  ada_log("parse_ipv6 ", get_hostname());
15975
3.85k
  ADA_ASSERT_TRUE(validate());
15976
3.85k
  host_type = IPV6;
15977
3.85k
  return true;
15978
5.14k
}
15979
15980
221k
bool url_aggregator::parse_opaque_host(std::string_view input) {
15981
221k
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15982
221k
  ADA_ASSERT_TRUE(validate());
15983
221k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15984
221k
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15985
287
    return is_valid = false;
15986
287
  }
15987
15988
  // Return the result of running UTF-8 percent-encode on input using the C0
15989
  // control percent-encode set.
15990
221k
  size_t idx = ada::unicode::percent_encode_index(
15991
221k
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15992
221k
  if (idx == input.size()) {
15993
220k
    update_base_hostname(input);
15994
220k
  } else {
15995
    // We only create a temporary string if we need to.
15996
1.08k
    update_base_hostname(ada::unicode::percent_encode(
15997
1.08k
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15998
1.08k
  }
15999
221k
  ADA_ASSERT_TRUE(validate());
16000
221k
  return true;
16001
221k
}
16002
16003
32.8k
[[nodiscard]] std::string url_aggregator::to_diagram() const {
16004
32.8k
  if (!is_valid) {
16005
3.05k
    return "invalid";
16006
3.05k
  }
16007
29.8k
  std::string answer;
16008
29.8k
  answer.append(buffer);
16009
29.8k
  answer.append(" [");
16010
29.8k
  answer.append(std::to_string(buffer.size()));
16011
29.8k
  answer.append(" bytes]");
16012
29.8k
  answer.append("\n");
16013
  // first line
16014
29.8k
  std::string line1;
16015
29.8k
  line1.resize(buffer.size(), ' ');
16016
29.8k
  if (components.hash_start != url_components::omitted) {
16017
10.4k
    line1[components.hash_start] = '|';
16018
10.4k
  }
16019
29.8k
  if (components.search_start != url_components::omitted) {
16020
12.0k
    line1[components.search_start] = '|';
16021
12.0k
  }
16022
29.8k
  if (components.pathname_start != buffer.size()) {
16023
28.9k
    line1[components.pathname_start] = '|';
16024
28.9k
  }
16025
29.8k
  if (components.host_end != buffer.size()) {
16026
29.0k
    line1[components.host_end] = '|';
16027
29.0k
  }
16028
29.8k
  if (components.host_start != buffer.size()) {
16029
29.3k
    line1[components.host_start] = '|';
16030
29.3k
  }
16031
29.8k
  if (components.username_end != buffer.size()) {
16032
29.3k
    line1[components.username_end] = '|';
16033
29.3k
  }
16034
29.8k
  if (components.protocol_end != buffer.size()) {
16035
29.3k
    line1[components.protocol_end] = '|';
16036
29.3k
  }
16037
29.8k
  answer.append(line1);
16038
29.8k
  answer.append("\n");
16039
16040
29.8k
  std::string line2 = line1;
16041
29.8k
  if (components.hash_start != url_components::omitted) {
16042
10.4k
    line2[components.hash_start] = '`';
16043
10.4k
    line1[components.hash_start] = ' ';
16044
16045
469k
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
16046
459k
      line2[i] = '-';
16047
459k
    }
16048
10.4k
    line2.append(" hash_start");
16049
10.4k
    answer.append(line2);
16050
10.4k
    answer.append("\n");
16051
10.4k
  }
16052
16053
29.8k
  std::string line3 = line1;
16054
29.8k
  if (components.search_start != url_components::omitted) {
16055
12.0k
    line3[components.search_start] = '`';
16056
12.0k
    line1[components.search_start] = ' ';
16057
16058
943k
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
16059
931k
      line3[i] = '-';
16060
931k
    }
16061
12.0k
    line3.append(" search_start ");
16062
12.0k
    line3.append(std::to_string(components.search_start));
16063
12.0k
    answer.append(line3);
16064
12.0k
    answer.append("\n");
16065
12.0k
  }
16066
16067
29.8k
  std::string line4 = line1;
16068
29.8k
  if (components.pathname_start != buffer.size()) {
16069
28.9k
    line4[components.pathname_start] = '`';
16070
28.9k
    line1[components.pathname_start] = ' ';
16071
1.94M
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
16072
1.91M
      line4[i] = '-';
16073
1.91M
    }
16074
28.9k
    line4.append(" pathname_start ");
16075
28.9k
    line4.append(std::to_string(components.pathname_start));
16076
28.9k
    answer.append(line4);
16077
28.9k
    answer.append("\n");
16078
28.9k
  }
16079
16080
29.8k
  std::string line5 = line1;
16081
29.8k
  if (components.host_end != buffer.size()) {
16082
29.0k
    line5[components.host_end] = '`';
16083
29.0k
    line1[components.host_end] = ' ';
16084
16085
1.94M
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
16086
1.91M
      line5[i] = '-';
16087
1.91M
    }
16088
29.0k
    line5.append(" host_end ");
16089
29.0k
    line5.append(std::to_string(components.host_end));
16090
29.0k
    answer.append(line5);
16091
29.0k
    answer.append("\n");
16092
29.0k
  }
16093
16094
29.8k
  std::string line6 = line1;
16095
29.8k
  if (components.host_start != buffer.size()) {
16096
29.3k
    line6[components.host_start] = '`';
16097
29.3k
    line1[components.host_start] = ' ';
16098
16099
2.48M
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
16100
2.45M
      line6[i] = '-';
16101
2.45M
    }
16102
29.3k
    line6.append(" host_start ");
16103
29.3k
    line6.append(std::to_string(components.host_start));
16104
29.3k
    answer.append(line6);
16105
29.3k
    answer.append("\n");
16106
29.3k
  }
16107
16108
29.8k
  std::string line7 = line1;
16109
29.8k
  if (components.username_end != buffer.size()) {
16110
29.3k
    line7[components.username_end] = '`';
16111
29.3k
    line1[components.username_end] = ' ';
16112
16113
3.04M
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
16114
3.01M
      line7[i] = '-';
16115
3.01M
    }
16116
29.3k
    line7.append(" username_end ");
16117
29.3k
    line7.append(std::to_string(components.username_end));
16118
29.3k
    answer.append(line7);
16119
29.3k
    answer.append("\n");
16120
29.3k
  }
16121
16122
29.8k
  std::string line8 = line1;
16123
29.8k
  if (components.protocol_end != buffer.size()) {
16124
29.3k
    line8[components.protocol_end] = '`';
16125
29.3k
    line1[components.protocol_end] = ' ';
16126
16127
3.66M
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
16128
3.63M
      line8[i] = '-';
16129
3.63M
    }
16130
29.3k
    line8.append(" protocol_end ");
16131
29.3k
    line8.append(std::to_string(components.protocol_end));
16132
29.3k
    answer.append(line8);
16133
29.3k
    answer.append("\n");
16134
29.3k
  }
16135
16136
29.8k
  if (components.hash_start == url_components::omitted) {
16137
19.3k
    answer.append("note: hash omitted\n");
16138
19.3k
  }
16139
29.8k
  if (components.search_start == url_components::omitted) {
16140
17.7k
    answer.append("note: search omitted\n");
16141
17.7k
  }
16142
29.8k
  if (components.protocol_end > buffer.size()) {
16143
0
    answer.append("warning: protocol_end overflows\n");
16144
0
  }
16145
29.8k
  if (components.username_end > buffer.size()) {
16146
0
    answer.append("warning: username_end overflows\n");
16147
0
  }
16148
29.8k
  if (components.host_start > buffer.size()) {
16149
0
    answer.append("warning: host_start overflows\n");
16150
0
  }
16151
29.8k
  if (components.host_end > buffer.size()) {
16152
0
    answer.append("warning: host_end overflows\n");
16153
0
  }
16154
29.8k
  if (components.pathname_start > buffer.size()) {
16155
0
    answer.append("warning: pathname_start overflows\n");
16156
0
  }
16157
29.8k
  return answer;
16158
32.8k
}
16159
16160
35
void url_aggregator::delete_dash_dot() {
16161
35
  ada_log("url_aggregator::delete_dash_dot");
16162
35
  ADA_ASSERT_TRUE(validate());
16163
35
  ADA_ASSERT_TRUE(has_dash_dot());
16164
35
  buffer.erase(components.host_end, 2);
16165
35
  components.pathname_start -= 2;
16166
35
  if (components.search_start != url_components::omitted) {
16167
0
    components.search_start -= 2;
16168
0
  }
16169
35
  if (components.hash_start != url_components::omitted) {
16170
0
    components.hash_start -= 2;
16171
0
  }
16172
35
  ADA_ASSERT_TRUE(validate());
16173
35
  ADA_ASSERT_TRUE(!has_dash_dot());
16174
35
}
16175
16176
471k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
16177
471k
  ada_log("url_aggregator::consume_prepared_path ", input);
16178
  /***
16179
   * This is largely duplicated code from helpers::parse_prepared_path, which is
16180
   * unfortunate. This particular function is nearly identical, except that it
16181
   * is a method on url_aggregator. The idea is that the trivial path (which is
16182
   * very common) merely appends to the buffer. This is the same trivial path as
16183
   * with helpers::parse_prepared_path, except that we have the additional check
16184
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
16185
   * modify it, and then insert it back into the buffer.
16186
   */
16187
471k
  uint8_t accumulator = checkers::path_signature(input);
16188
  // Let us first detect a trivial case.
16189
  // If it is special, we check that we have no dot, no %,  no \ and no
16190
  // character needing percent encoding. Otherwise, we check that we have no %,
16191
  // no dot, and no character needing percent encoding.
16192
471k
  constexpr uint8_t need_encoding = 1;
16193
471k
  constexpr uint8_t backslash_char = 2;
16194
471k
  constexpr uint8_t dot_char = 4;
16195
471k
  constexpr uint8_t percent_char = 8;
16196
471k
  bool special = type != ada::scheme::NOT_SPECIAL;
16197
471k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
16198
7.72k
                                      checkers::is_windows_drive_letter(input));
16199
471k
  bool trivial_path =
16200
471k
      (special ? (accumulator == 0)
16201
471k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
16202
244k
                  0)) &&
16203
374k
      (!may_need_slow_file_handling);
16204
471k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
16205
    // '4' means that we have at least one dot, but nothing that requires
16206
    // percent encoding or decoding. The only part that is not trivial is
16207
    // that we may have single dots and double dots path segments.
16208
    // If we have such segments, then we either have a path that begins
16209
    // with '.' (easy to check), or we have the sequence './'.
16210
    // Note: input cannot be empty, it must at least contain one character ('.')
16211
    // Note: we know that '\' is not present.
16212
34.0k
    if (input[0] != '.') {
16213
21.9k
      size_t slashdot = 0;
16214
21.9k
      bool dot_is_file = true;
16215
49.3k
      for (;;) {
16216
49.3k
        slashdot = input.find("/.", slashdot);
16217
49.3k
        if (slashdot == std::string_view::npos) {  // common case
16218
21.9k
          break;
16219
27.4k
        } else {  // uncommon
16220
          // only three cases matter: /./, /.. or a final /
16221
27.4k
          slashdot += 2;
16222
27.4k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
16223
10.1k
                           input[slashdot] == '/');
16224
27.4k
        }
16225
49.3k
      }
16226
21.9k
      trivial_path = dot_is_file;
16227
21.9k
    }
16228
34.0k
  }
16229
471k
  if (trivial_path && is_at_path()) {
16230
383k
    ada_log("parse_path trivial");
16231
383k
    buffer += '/';
16232
383k
    buffer += input;
16233
383k
    return;
16234
383k
  }
16235
87.9k
  std::string path = std::string(get_pathname());
16236
  // We are going to need to look a bit at the path, but let us see if we can
16237
  // ignore percent encoding *and* backslashes *and* percent characters.
16238
  // Except for the trivial case, this is likely to capture 99% of paths out
16239
  // there.
16240
87.9k
  bool fast_path =
16241
87.9k
      (special &&
16242
48.2k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
16243
20.3k
      (type != ada::scheme::type::FILE);
16244
87.9k
  if (fast_path) {
16245
19.2k
    ada_log("parse_prepared_path fast");
16246
    // Here we don't need to worry about \ or percent encoding.
16247
    // We also do not have a file protocol. We might have dots, however,
16248
    // but dots must as appear as '.', and they cannot be encoded because
16249
    // the symbol '%' is not present.
16250
19.2k
    size_t previous_location = 0;  // We start at 0.
16251
102k
    do {
16252
102k
      size_t new_location = input.find('/', previous_location);
16253
      // std::string_view path_view = input;
16254
      //  We process the last segment separately:
16255
102k
      if (new_location == std::string_view::npos) {
16256
19.2k
        std::string_view path_view = input.substr(previous_location);
16257
19.2k
        if (path_view == "..") {  // The path ends with ..
16258
          // e.g., if you receive ".." with an empty path, you go to "/".
16259
1.93k
          if (path.empty()) {
16260
658
            path = '/';
16261
658
            update_base_pathname(path);
16262
658
            return;
16263
658
          }
16264
          // Fast case where we have nothing to do:
16265
1.27k
          if (path.back() == '/') {
16266
399
            update_base_pathname(path);
16267
399
            return;
16268
399
          }
16269
          // If you have the path "/joe/myfriend",
16270
          // then you delete 'myfriend'.
16271
880
          path.resize(path.rfind('/') + 1);
16272
880
          update_base_pathname(path);
16273
880
          return;
16274
1.27k
        }
16275
17.3k
        path += '/';
16276
17.3k
        if (path_view != ".") {
16277
16.1k
          path.append(path_view);
16278
16.1k
        }
16279
17.3k
        update_base_pathname(path);
16280
17.3k
        return;
16281
83.3k
      } else {
16282
        // This is a non-final segment.
16283
83.3k
        std::string_view path_view =
16284
83.3k
            input.substr(previous_location, new_location - previous_location);
16285
83.3k
        previous_location = new_location + 1;
16286
83.3k
        if (path_view == "..") {
16287
14.6k
          size_t last_delimiter = path.rfind('/');
16288
14.6k
          if (last_delimiter != std::string::npos) {
16289
7.55k
            path.erase(last_delimiter);
16290
7.55k
          }
16291
68.7k
        } else if (path_view != ".") {
16292
59.8k
          path += '/';
16293
59.8k
          path.append(path_view);
16294
59.8k
        }
16295
83.3k
      }
16296
102k
    } while (true);
16297
68.7k
  } else {
16298
68.7k
    ada_log("parse_path slow");
16299
    // we have reached the general case
16300
68.7k
    bool needs_percent_encoding = (accumulator & 1);
16301
68.7k
    std::string path_buffer_tmp;
16302
287k
    do {
16303
287k
      size_t location = (special && (accumulator & 2))
16304
287k
                            ? input.find_first_of("/\\")
16305
287k
                            : input.find('/');
16306
287k
      std::string_view path_view = input;
16307
287k
      if (location != std::string_view::npos) {
16308
218k
        path_view.remove_suffix(path_view.size() - location);
16309
218k
        input.remove_prefix(location + 1);
16310
218k
      }
16311
      // path_buffer is either path_view or it might point at a percent encoded
16312
      // temporary string.
16313
287k
      std::string_view path_buffer =
16314
287k
          (needs_percent_encoding &&
16315
169k
           ada::unicode::percent_encode<false>(
16316
169k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
16317
287k
              ? path_buffer_tmp
16318
287k
              : path_view;
16319
287k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
16320
24.0k
        helpers::shorten_path(path, type);
16321
24.0k
        if (location == std::string_view::npos) {
16322
2.20k
          path += '/';
16323
2.20k
        }
16324
263k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
16325
11.7k
                 (location == std::string_view::npos)) {
16326
1.73k
        path += '/';
16327
1.73k
      }
16328
      // Otherwise, if path_buffer is not a single-dot path segment, then:
16329
261k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
16330
        // If url's scheme is "file", url's path is empty, and path_buffer is a
16331
        // Windows drive letter, then replace the second code point in
16332
        // path_buffer with U+003A (:).
16333
251k
        if (type == ada::scheme::type::FILE && path.empty() &&
16334
9.32k
            checkers::is_windows_drive_letter(path_buffer)) {
16335
685
          path += '/';
16336
685
          path += path_buffer[0];
16337
685
          path += ':';
16338
685
          path_buffer.remove_prefix(2);
16339
685
          path.append(path_buffer);
16340
250k
        } else {
16341
          // Append path_buffer to url's path.
16342
250k
          path += '/';
16343
250k
          path.append(path_buffer);
16344
250k
        }
16345
251k
      }
16346
287k
      if (location == std::string_view::npos) {
16347
68.7k
        update_base_pathname(path);
16348
68.7k
        return;
16349
68.7k
      }
16350
287k
    } while (true);
16351
68.7k
  }
16352
87.9k
}
16353
}  // namespace ada
16354
/* end file src/url_aggregator.cpp */
16355
16356
#if ADA_INCLUDE_URL_PATTERN
16357
/* begin file src/url_pattern.cpp */
16358
#if ADA_INCLUDE_URL_PATTERN
16359
16360
16361
#include <algorithm>
16362
#include <optional>
16363
#include <string>
16364
16365
namespace ada {
16366
16367
tl::expected<url_pattern_init, errors> url_pattern_init::process(
16368
    const url_pattern_init& init, url_pattern_init::process_type type,
16369
    std::optional<std::string_view> protocol,
16370
    std::optional<std::string_view> username,
16371
    std::optional<std::string_view> password,
16372
    std::optional<std::string_view> hostname,
16373
    std::optional<std::string_view> port,
16374
    std::optional<std::string_view> pathname,
16375
    std::optional<std::string_view> search,
16376
378k
    std::optional<std::string_view> hash) {
16377
  // Let result be the result of creating a new URLPatternInit.
16378
378k
  auto result = url_pattern_init{};
16379
16380
  // If protocol is not null, set result["protocol"] to protocol.
16381
378k
  if (protocol.has_value()) result.protocol = *protocol;
16382
16383
  // If username is not null, set result["username"] to username.
16384
378k
  if (username.has_value()) result.username = *username;
16385
16386
  // If password is not null, set result["password"] to password.
16387
378k
  if (password.has_value()) result.password = *password;
16388
16389
  // If hostname is not null, set result["hostname"] to hostname.
16390
378k
  if (hostname.has_value()) result.hostname = *hostname;
16391
16392
  // If port is not null, set result["port"] to port.
16393
378k
  if (port.has_value()) result.port = *port;
16394
16395
  // If pathname is not null, set result["pathname"] to pathname.
16396
378k
  if (pathname.has_value()) result.pathname = *pathname;
16397
16398
  // If search is not null, set result["search"] to search.
16399
378k
  if (search.has_value()) result.search = *search;
16400
16401
  // If hash is not null, set result["hash"] to hash.
16402
378k
  if (hash.has_value()) result.hash = *hash;
16403
16404
  // Let baseURL be null.
16405
378k
  std::optional<url_aggregator> base_url{};
16406
16407
  // If init["baseURL"] exists:
16408
378k
  if (init.base_url.has_value()) {
16409
    // Set baseURL to the result of parsing init["baseURL"].
16410
99.2k
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
16411
    // If baseURL is failure, then throw a TypeError.
16412
99.2k
    if (!parsing_result) {
16413
48.2k
      return tl::unexpected(errors::type_error);
16414
48.2k
    }
16415
50.9k
    base_url = std::move(*parsing_result);
16416
16417
    // If init["protocol"] does not exist, then set result["protocol"] to the
16418
    // result of processing a base URL string given baseURL's scheme and type.
16419
50.9k
    if (!init.protocol.has_value()) {
16420
25.9k
      ADA_ASSERT_TRUE(base_url.has_value());
16421
25.9k
      std::string_view base_url_protocol = base_url->get_protocol();
16422
25.9k
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
16423
25.9k
      result.protocol =
16424
25.9k
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
16425
25.9k
    }
16426
16427
    // If type is not "pattern" and init contains none of "protocol",
16428
    // "hostname", "port" and "username", then set result["username"] to the
16429
    // result of processing a base URL string given baseURL's username and type.
16430
50.9k
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
16431
0
        !init.port && !init.username) {
16432
0
      result.username = url_pattern_helpers::process_base_url_string(
16433
0
          base_url->get_username(), type);
16434
0
    }
16435
16436
    // TODO: Optimization opportunity: Merge this with the previous check.
16437
    // If type is not "pattern" and init contains none of "protocol",
16438
    // "hostname", "port", "username" and "password", then set
16439
    // result["password"] to the result of processing a base URL string given
16440
    // baseURL's password and type.
16441
50.9k
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
16442
0
        !init.port && !init.username && !init.password) {
16443
0
      result.password = url_pattern_helpers::process_base_url_string(
16444
0
          base_url->get_password(), type);
16445
0
    }
16446
16447
    // If init contains neither "protocol" nor "hostname", then:
16448
50.9k
    if (!init.protocol && !init.hostname) {
16449
      // Let baseHost be baseURL's host.
16450
      // If baseHost is null, then set baseHost to the empty string.
16451
25.9k
      auto base_host = base_url->get_hostname();
16452
      // Set result["hostname"] to the result of processing a base URL string
16453
      // given baseHost and type.
16454
25.9k
      result.hostname =
16455
25.9k
          url_pattern_helpers::process_base_url_string(base_host, type);
16456
25.9k
    }
16457
16458
    // If init contains none of "protocol", "hostname", and "port", then:
16459
50.9k
    if (!init.protocol && !init.hostname && !init.port) {
16460
      // If baseURL's port is null, then set result["port"] to the empty string.
16461
      // Otherwise, set result["port"] to baseURL's port, serialized.
16462
25.9k
      result.port = base_url->get_port();
16463
25.9k
    }
16464
16465
    // If init contains none of "protocol", "hostname", "port", and "pathname",
16466
    // then set result["pathname"] to the result of processing a base URL string
16467
    // given the result of URL path serializing baseURL and type.
16468
50.9k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
16469
0
      result.pathname = url_pattern_helpers::process_base_url_string(
16470
0
          base_url->get_pathname(), type);
16471
0
    }
16472
16473
    // If init contains none of "protocol", "hostname", "port", "pathname", and
16474
    // "search", then:
16475
50.9k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
16476
0
        !init.search) {
16477
      // Let baseQuery be baseURL's query.
16478
      // Set result["search"] to the result of processing a base URL string
16479
      // given baseQuery and type.
16480
0
      result.search = url_pattern_helpers::process_base_url_string(
16481
0
          base_url->get_search(), type);
16482
0
    }
16483
16484
    // If init contains none of "protocol", "hostname", "port", "pathname",
16485
    // "search", and "hash", then:
16486
50.9k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
16487
0
        !init.search && !init.hash) {
16488
      // Let baseFragment be baseURL's fragment.
16489
      // Set result["hash"] to the result of processing a base URL string given
16490
      // baseFragment and type.
16491
0
      result.hash = url_pattern_helpers::process_base_url_string(
16492
0
          base_url->get_hash(), type);
16493
0
    }
16494
50.9k
  }
16495
16496
  // If init["protocol"] exists, then set result["protocol"] to the result of
16497
  // process protocol for init given init["protocol"] and type.
16498
330k
  if (init.protocol) {
16499
63.2k
    auto process_result = process_protocol(*init.protocol, type);
16500
63.2k
    if (!process_result) {
16501
0
      return tl::unexpected(process_result.error());
16502
0
    }
16503
63.2k
    result.protocol = std::move(*process_result);
16504
63.2k
  }
16505
16506
  // If init["username"] exists, then set result["username"] to the result of
16507
  // process username for init given init["username"] and type.
16508
330k
  if (init.username.has_value()) {
16509
25.9k
    auto process_result = process_username(*init.username, type);
16510
25.9k
    if (!process_result) {
16511
0
      return tl::unexpected(process_result.error());
16512
0
    }
16513
25.9k
    result.username = std::move(*process_result);
16514
25.9k
  }
16515
16516
  // If init["password"] exists, then set result["password"] to the result of
16517
  // process password for init given init["password"] and type.
16518
330k
  if (init.password.has_value()) {
16519
25.4k
    auto process_result = process_password(*init.password, type);
16520
25.4k
    if (!process_result) {
16521
0
      return tl::unexpected(process_result.error());
16522
0
    }
16523
25.4k
    result.password = std::move(*process_result);
16524
25.4k
  }
16525
16526
  // If init["hostname"] exists, then set result["hostname"] to the result of
16527
  // process hostname for init given init["hostname"] and type.
16528
330k
  if (init.hostname.has_value()) {
16529
63.3k
    auto process_result = process_hostname(*init.hostname, type);
16530
63.3k
    if (!process_result) {
16531
0
      return tl::unexpected(process_result.error());
16532
0
    }
16533
63.3k
    result.hostname = std::move(*process_result);
16534
63.3k
  }
16535
16536
  // If init["port"] exists, then set result["port"] to the result of process
16537
  // port for init given init["port"], result["protocol"], and type.
16538
330k
  if (init.port) {
16539
63.3k
    auto process_result =
16540
63.3k
        process_port(*init.port, result.protocol.value_or("fake"), type);
16541
63.3k
    if (!process_result) {
16542
0
      return tl::unexpected(process_result.error());
16543
0
    }
16544
63.3k
    result.port = std::move(*process_result);
16545
63.3k
  }
16546
16547
  // If init["pathname"] exists:
16548
330k
  if (init.pathname.has_value()) {
16549
    // Set result["pathname"] to init["pathname"].
16550
306k
    result.pathname = init.pathname;
16551
16552
    // If the following are all true:
16553
    // - baseURL is not null;
16554
    // - baseURL has an opaque path; and
16555
    // - the result of running is an absolute pathname given result["pathname"]
16556
    // and type is false,
16557
306k
    if (base_url && !base_url->has_opaque_path &&
16558
50.9k
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
16559
      // Let baseURLPath be the result of running process a base URL string
16560
      // given the result of URL path serializing baseURL and type.
16561
      // TODO: Optimization opportunity: Avoid returning a string if no slash
16562
      // exist.
16563
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
16564
0
          base_url->get_pathname(), type);
16565
16566
      // Let slash index be the index of the last U+002F (/) code point found in
16567
      // baseURLPath, interpreted as a sequence of code points, or null if there
16568
      // are no instances of the code point.
16569
0
      auto slash_index = base_url_path.find_last_of('/');
16570
16571
      // If slash index is not null:
16572
0
      if (slash_index != std::string::npos) {
16573
        // Let new pathname be the code point substring from 0 to slash index +
16574
        // 1 within baseURLPath.
16575
0
        base_url_path.resize(slash_index + 1);
16576
        // Append result["pathname"] to the end of new pathname.
16577
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
16578
0
        base_url_path.append(std::move(*result.pathname));
16579
        // Set result["pathname"] to new pathname.
16580
0
        result.pathname = std::move(base_url_path);
16581
0
      }
16582
0
    }
16583
16584
    // Set result["pathname"] to the result of process pathname for init given
16585
    // result["pathname"], result["protocol"], and type.
16586
306k
    auto pathname_processing_result =
16587
306k
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
16588
306k
    if (!pathname_processing_result) {
16589
568
      return tl::unexpected(pathname_processing_result.error());
16590
568
    }
16591
305k
    result.pathname = std::move(*pathname_processing_result);
16592
305k
  }
16593
16594
  // If init["search"] exists then set result["search"] to the result of process
16595
  // search for init given init["search"] and type.
16596
329k
  if (init.search) {
16597
25.7k
    auto process_result = process_search(*init.search, type);
16598
25.7k
    if (!process_result) {
16599
0
      return tl::unexpected(process_result.error());
16600
0
    }
16601
25.7k
    result.search = std::move(*process_result);
16602
25.7k
  }
16603
16604
  // If init["hash"] exists then set result["hash"] to the result of process
16605
  // hash for init given init["hash"] and type.
16606
329k
  if (init.hash) {
16607
25.9k
    auto process_result = process_hash(*init.hash, type);
16608
25.9k
    if (!process_result) {
16609
0
      return tl::unexpected(process_result.error());
16610
0
    }
16611
25.9k
    result.hash = std::move(*process_result);
16612
25.9k
  }
16613
  // Return result.
16614
329k
  return result;
16615
329k
}
16616
16617
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16618
63.2k
    std::string_view value, process_type type) {
16619
63.2k
  ada_log("process_protocol=", value, " [", type, "]");
16620
  // Let strippedValue be the given value with a single trailing U+003A (:)
16621
  // removed, if any.
16622
63.2k
  if (value.ends_with(":")) {
16623
45
    value.remove_suffix(1);
16624
45
  }
16625
  // If type is "pattern" then return strippedValue.
16626
63.2k
  if (type == process_type::pattern) {
16627
63.2k
    return std::string(value);
16628
63.2k
  }
16629
  // Return the result of running canonicalize a protocol given strippedValue.
16630
0
  return url_pattern_helpers::canonicalize_protocol(value);
16631
63.2k
}
16632
16633
tl::expected<std::string, errors> url_pattern_init::process_username(
16634
25.9k
    std::string_view value, process_type type) {
16635
  // If type is "pattern" then return value.
16636
25.9k
  if (type == process_type::pattern) {
16637
25.9k
    return std::string(value);
16638
25.9k
  }
16639
  // Return the result of running canonicalize a username given value.
16640
0
  return url_pattern_helpers::canonicalize_username(value);
16641
25.9k
}
16642
16643
tl::expected<std::string, errors> url_pattern_init::process_password(
16644
25.4k
    std::string_view value, process_type type) {
16645
  // If type is "pattern" then return value.
16646
25.4k
  if (type == process_type::pattern) {
16647
25.4k
    return std::string(value);
16648
25.4k
  }
16649
  // Return the result of running canonicalize a password given value.
16650
0
  return url_pattern_helpers::canonicalize_password(value);
16651
25.4k
}
16652
16653
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16654
63.3k
    std::string_view value, process_type type) {
16655
63.3k
  ada_log("process_hostname value=", value, " type=", type);
16656
  // If type is "pattern" then return value.
16657
63.3k
  if (type == process_type::pattern) {
16658
63.3k
    return std::string(value);
16659
63.3k
  }
16660
  // Return the result of running canonicalize a hostname given value.
16661
0
  return url_pattern_helpers::canonicalize_hostname(value);
16662
63.3k
}
16663
16664
tl::expected<std::string, errors> url_pattern_init::process_port(
16665
63.3k
    std::string_view port, std::string_view protocol, process_type type) {
16666
  // If type is "pattern" then return portValue.
16667
63.3k
  if (type == process_type::pattern) {
16668
63.3k
    return std::string(port);
16669
63.3k
  }
16670
  // Return the result of running canonicalize a port given portValue and
16671
  // protocolValue.
16672
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
16673
63.3k
}
16674
16675
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16676
306k
    std::string_view value, std::string_view protocol, process_type type) {
16677
  // If type is "pattern" then return pathnameValue.
16678
306k
  if (type == process_type::pattern) {
16679
89.4k
    return std::string(value);
16680
89.4k
  }
16681
16682
  // If protocolValue is a special scheme or the empty string, then return the
16683
  // result of running canonicalize a pathname given pathnameValue.
16684
216k
  if (protocol.empty() || scheme::is_special(protocol)) {
16685
216k
    return url_pattern_helpers::canonicalize_pathname(value);
16686
216k
  }
16687
16688
  // Return the result of running canonicalize an opaque pathname given
16689
  // pathnameValue.
16690
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
16691
216k
}
16692
16693
tl::expected<std::string, errors> url_pattern_init::process_search(
16694
25.7k
    std::string_view value, process_type type) {
16695
  // Let strippedValue be the given value with a single leading U+003F (?)
16696
  // removed, if any.
16697
25.7k
  if (value.starts_with("?")) {
16698
12
    value.remove_prefix(1);
16699
12
  }
16700
  // We cannot assert that the value is no longer starting with a single
16701
  // question mark because technically it can start. The question is whether or
16702
  // not we should remove the first question mark. Ref:
16703
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
16704
16705
  // If type is "pattern" then return strippedValue.
16706
25.7k
  if (type == process_type::pattern) {
16707
25.7k
    return std::string(value);
16708
25.7k
  }
16709
  // Return the result of running canonicalize a search given strippedValue.
16710
0
  return url_pattern_helpers::canonicalize_search(value);
16711
25.7k
}
16712
16713
tl::expected<std::string, errors> url_pattern_init::process_hash(
16714
25.9k
    std::string_view value, process_type type) {
16715
  // Let strippedValue be the given value with a single leading U+0023 (#)
16716
  // removed, if any.
16717
25.9k
  if (value.starts_with("#")) {
16718
23
    value.remove_prefix(1);
16719
23
  }
16720
25.9k
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16721
  // If type is "pattern" then return strippedValue.
16722
25.9k
  if (type == process_type::pattern) {
16723
25.9k
    return std::string(value);
16724
25.9k
  }
16725
  // Return the result of running canonicalize a hash given strippedValue.
16726
0
  return url_pattern_helpers::canonicalize_hash(value);
16727
25.9k
}
16728
16729
}  // namespace ada
16730
16731
#endif  // ADA_INCLUDE_URL_PATTERN
16732
/* end file src/url_pattern.cpp */
16733
/* begin file src/url_pattern_helpers.cpp */
16734
#if ADA_INCLUDE_URL_PATTERN
16735
16736
#include <algorithm>
16737
#include <array>
16738
#include <charconv>
16739
#include <optional>
16740
#include <ranges>
16741
#include <string>
16742
16743
16744
namespace ada::url_pattern_helpers {
16745
16746
std::tuple<std::string, std::vector<std::string>>
16747
generate_regular_expression_and_name_list(
16748
    const std::vector<url_pattern_part>& part_list,
16749
44.0k
    url_pattern_compile_component_options options) {
16750
  // Let result be "^"
16751
44.0k
  std::string result = "^";
16752
  // Reserve capacity to reduce reallocations
16753
44.0k
  result.reserve(part_list.size() * 16);
16754
16755
  // Let name list be a new list
16756
44.0k
  std::vector<std::string> name_list{};
16757
44.0k
  name_list.reserve(part_list.size());
16758
16759
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16760
44.0k
  std::string segment_wildcard_regexp;
16761
16762
  // For each part of part list:
16763
56.1k
  for (const url_pattern_part& part : part_list) {
16764
    // If part's type is "fixed-text":
16765
56.1k
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16766
      // If part's modifier is "none"
16767
6.20k
      if (part.modifier == url_pattern_part_modifier::none) {
16768
5.85k
        result.append(escape_regexp_string(part.value));
16769
5.85k
      } else {
16770
        // (?:<fixed text>)<modifier>
16771
345
        result.append("(?:");
16772
345
        result.append(escape_regexp_string(part.value));
16773
345
        result.push_back(')');
16774
345
        result.append(convert_modifier_to_string(part.modifier));
16775
345
      }
16776
6.20k
      continue;
16777
6.20k
    }
16778
16779
    // Assert: part's name is not the empty string
16780
49.9k
    ADA_ASSERT_TRUE(!part.name.empty());
16781
49.9k
    name_list.push_back(part.name);
16782
16783
    // Use string_view to avoid copies where possible
16784
49.9k
    std::string_view regexp_value = part.value;
16785
16786
49.9k
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16787
      // Lazy generate segment wildcard regexp
16788
1.80k
      if (segment_wildcard_regexp.empty()) {
16789
1.36k
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16790
1.36k
      }
16791
1.80k
      regexp_value = segment_wildcard_regexp;
16792
48.1k
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16793
45.8k
      regexp_value = ".*";
16794
45.8k
    }
16795
16796
    // If part's prefix is the empty string and part's suffix is the empty
16797
    // string
16798
49.9k
    if (part.prefix.empty() && part.suffix.empty()) {
16799
      // If part's modifier is "none" or "optional"
16800
9.72k
      if (part.modifier == url_pattern_part_modifier::none ||
16801
7.80k
          part.modifier == url_pattern_part_modifier::optional) {
16802
        // (<regexp value>)<modifier>
16803
7.80k
        result.push_back('(');
16804
7.80k
        result.append(regexp_value);
16805
7.80k
        result.push_back(')');
16806
7.80k
        result.append(convert_modifier_to_string(part.modifier));
16807
7.80k
      } else {
16808
        // ((?:<regexp value>)<modifier>)
16809
1.92k
        result.append("((?:");
16810
1.92k
        result.append(regexp_value);
16811
1.92k
        result.push_back(')');
16812
1.92k
        result.append(convert_modifier_to_string(part.modifier));
16813
1.92k
        result.push_back(')');
16814
1.92k
      }
16815
9.72k
      continue;
16816
9.72k
    }
16817
16818
    // If part's modifier is "none" or "optional"
16819
40.2k
    if (part.modifier == url_pattern_part_modifier::none ||
16820
38.6k
        part.modifier == url_pattern_part_modifier::optional) {
16821
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16822
38.6k
      result.append("(?:");
16823
38.6k
      result.append(escape_regexp_string(part.prefix));
16824
38.6k
      result.push_back('(');
16825
38.6k
      result.append(regexp_value);
16826
38.6k
      result.push_back(')');
16827
38.6k
      result.append(escape_regexp_string(part.suffix));
16828
38.6k
      result.push_back(')');
16829
38.6k
      result.append(convert_modifier_to_string(part.modifier));
16830
38.6k
      continue;
16831
38.6k
    }
16832
16833
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16834
1.53k
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16835
1.53k
                    part.modifier == url_pattern_part_modifier::one_or_more);
16836
16837
    // Assert: part's prefix is not the empty string or part's suffix is not the
16838
    // empty string
16839
1.53k
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16840
16841
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16842
    // value>))*)<suffix>)?
16843
    // Append "(?:" to the end of result.
16844
1.53k
    result.append("(?:");
16845
    // Append the result of running escape a regexp string given part's prefix
16846
    // to the end of result.
16847
1.53k
    result.append(escape_regexp_string(part.prefix));
16848
    // Append "((?:" to the end of result.
16849
1.53k
    result.append("((?:");
16850
    // Append regexp value to the end of result.
16851
1.53k
    result.append(regexp_value);
16852
    // Append ")(?:" to the end of result.
16853
1.53k
    result.append(")(?:");
16854
    // Append the result of running escape a regexp string given part's suffix
16855
    // to the end of result.
16856
1.53k
    result.append(escape_regexp_string(part.suffix));
16857
    // Append the result of running escape a regexp string given part's prefix
16858
    // to the end of result.
16859
1.53k
    result.append(escape_regexp_string(part.prefix));
16860
    // Append "(?:" to the end of result.
16861
1.53k
    result.append("(?:");
16862
    // Append regexp value to the end of result.
16863
1.53k
    result.append(regexp_value);
16864
    // Append "))*)" to the end of result.
16865
1.53k
    result.append("))*)");
16866
    // Append the result of running escape a regexp string given part's suffix
16867
    // to the end of result.
16868
1.53k
    result.append(escape_regexp_string(part.suffix));
16869
    // Append ")" to the end of result.
16870
1.53k
    result.append(")");
16871
16872
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16873
1.53k
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16874
1.10k
      result += "?";
16875
1.10k
    }
16876
1.53k
  }
16877
16878
  // Append "$" to the end of result
16879
44.0k
  result += "$";
16880
16881
  // Return (result, name list)
16882
44.0k
  return {std::move(result), std::move(name_list)};
16883
44.0k
}
16884
16885
111k
bool is_ipv6_address(std::string_view input) noexcept {
16886
  // If input's code point length is less than 2, then return false.
16887
111k
  if (input.size() < 2) return false;
16888
16889
  // Let input code points be input interpreted as a list of code points.
16890
  // If input code points[0] is U+005B ([), then return true.
16891
65.7k
  if (input.front() == '[') return true;
16892
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16893
  // ([), then return true.
16894
65.6k
  if (input.starts_with("{[")) return true;
16895
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16896
  // ([), then return true.
16897
65.6k
  return input.starts_with("\\[");
16898
65.6k
}
16899
16900
std::string_view convert_modifier_to_string(
16901
544k
    url_pattern_part_modifier modifier) {
16902
544k
  switch (modifier) {
16903
      // If modifier is "zero-or-more", then return "*".
16904
5.03k
    case url_pattern_part_modifier::zero_or_more:
16905
5.03k
      return "*";
16906
    // If modifier is "optional", then return "?".
16907
746
    case url_pattern_part_modifier::optional:
16908
746
      return "?";
16909
    // If modifier is "one-or-more", then return "+".
16910
868
    case url_pattern_part_modifier::one_or_more:
16911
868
      return "+";
16912
    // Return the empty string.
16913
537k
    default:
16914
537k
      return "";
16915
544k
  }
16916
544k
}
16917
16918
std::string generate_segment_wildcard_regexp(
16919
927k
    url_pattern_compile_component_options options) {
16920
  // Let result be "[^".
16921
927k
  std::string result = "[^";
16922
  // Append the result of running escape a regexp string given options's
16923
  // delimiter code point to the end of result.
16924
927k
  result.append(escape_regexp_string(options.get_delimiter()));
16925
  // Append "]+?" to the end of result.
16926
927k
  result.append("]+?");
16927
  // Return result.
16928
927k
  ada_log("generate_segment_wildcard_regexp result: ", result);
16929
927k
  return result;
16930
927k
}
16931
16932
namespace {
16933
// Unified lookup table for URL pattern character classification
16934
// Bit flags for different character types
16935
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16936
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16937
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16938
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16939
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16940
16941
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16942
  std::array<uint8_t, 256> table{};
16943
  for (int c = 'a'; c <= 'z'; c++)
16944
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16945
  for (int c = 'A'; c <= 'Z'; c++)
16946
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16947
  for (int c = '0'; c <= '9'; c++)
16948
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16949
  table['+'] = CHAR_SCHEME;
16950
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16951
  table['.'] =
16952
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16953
  table['/'] = CHAR_SIMPLE_PATHNAME;
16954
  table['_'] = CHAR_SIMPLE_PATHNAME;
16955
  table['~'] = CHAR_SIMPLE_PATHNAME;
16956
  return table;
16957
}();
16958
}  // namespace
16959
16960
tl::expected<std::string, errors> canonicalize_protocol(
16961
160k
    std::string_view input) {
16962
160k
  ada_log("canonicalize_protocol called with input=", input);
16963
160k
  if (input.empty()) [[unlikely]] {
16964
56.3k
    return "";
16965
56.3k
  }
16966
16967
103k
  if (input.ends_with(":")) {
16968
19
    input.remove_suffix(1);
16969
19
  }
16970
16971
  // Fast path: special schemes are already canonical
16972
103k
  if (scheme::is_special(input)) {
16973
101k
    return std::string(input);
16974
101k
  }
16975
16976
  // Fast path: validate scheme chars and check for uppercase
16977
  // First char must be alpha (not +, -, ., or digit)
16978
2.82k
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16979
2.82k
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16980
1.90k
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16981
1.90k
    return tl::unexpected(errors::type_error);
16982
1.90k
  }
16983
16984
923
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16985
1.45k
  for (size_t i = 1; i < input.size(); i++) {
16986
563
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16987
563
    if (!(flags & CHAR_SCHEME)) {
16988
28
      return tl::unexpected(errors::type_error);
16989
28
    }
16990
535
    needs_lowercase |= flags & CHAR_UPPER;
16991
535
  }
16992
16993
895
  if (needs_lowercase == 0) {
16994
477
    return std::string(input);
16995
477
  }
16996
16997
418
  std::string result(input);
16998
418
  unicode::to_lower_ascii(result.data(), result.size());
16999
418
  return result;
17000
895
}
17001
17002
tl::expected<std::string, errors> canonicalize_username(
17003
178k
    std::string_view input) {
17004
  // If value is the empty string, return value.
17005
178k
  if (input.empty()) [[unlikely]] {
17006
177k
    return "";
17007
177k
  }
17008
  // Percent-encode the input using the userinfo percent-encode set.
17009
1.18k
  size_t idx = ada::unicode::percent_encode_index(
17010
1.18k
      input, character_sets::USERINFO_PERCENT_ENCODE);
17011
1.18k
  if (idx == input.size()) {
17012
    // No encoding needed, return input as-is
17013
635
    return std::string(input);
17014
635
  }
17015
  // Percent-encode from the first character that needs encoding
17016
550
  return ada::unicode::percent_encode(
17017
550
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
17018
1.18k
}
17019
17020
tl::expected<std::string, errors> canonicalize_password(
17021
177k
    std::string_view input) {
17022
  // If value is the empty string, return value.
17023
177k
  if (input.empty()) [[unlikely]] {
17024
177k
    return "";
17025
177k
  }
17026
  // Percent-encode the input using the userinfo percent-encode set.
17027
798
  size_t idx = ada::unicode::percent_encode_index(
17028
798
      input, character_sets::USERINFO_PERCENT_ENCODE);
17029
798
  if (idx == input.size()) {
17030
    // No encoding needed, return input as-is
17031
437
    return std::string(input);
17032
437
  }
17033
  // Percent-encode from the first character that needs encoding
17034
361
  return ada::unicode::percent_encode(
17035
361
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
17036
798
}
17037
17038
tl::expected<std::string, errors> canonicalize_hostname(
17039
120k
    std::string_view input) {
17040
120k
  ada_log("canonicalize_hostname input=", input);
17041
120k
  if (input.empty()) [[unlikely]] {
17042
53.4k
    return "";
17043
53.4k
  }
17044
17045
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
17046
66.6k
  bool needs_processing = false;
17047
710k
  for (char c : input) {
17048
710k
    needs_processing |=
17049
710k
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
17050
710k
  }
17051
66.6k
  if (!needs_processing) {
17052
63.5k
    return std::string(input);
17053
63.5k
  }
17054
17055
  // Let dummyURL be a new URL record.
17056
  // Let parseResult be the result of running the basic URL parser given value
17057
  // with dummyURL as url and hostname state as state override.
17058
17059
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
17060
  // hostname will not be converted using IDNA.
17061
3.12k
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
17062
3.12k
  ADA_ASSERT_TRUE(url);
17063
  // if (!isValidHostnameInput(hostname)) return kj::none;
17064
3.12k
  if (!url->set_hostname(input)) {
17065
    // If parseResult is failure, then throw a TypeError.
17066
1.16k
    return tl::unexpected(errors::type_error);
17067
1.16k
  }
17068
  // Return dummyURL's host, serialized, or empty string if it is null.
17069
1.96k
  return std::string(url->get_hostname());
17070
3.12k
}
17071
17072
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
17073
374
    std::string_view input) {
17074
374
  ada_log("canonicalize_ipv6_hostname input=", input);
17075
  // TODO: Optimization opportunity: Use lookup table to speed up checking
17076
998
  if (std::ranges::any_of(input, [](char c) {
17077
998
        return c != '[' && c != ']' && c != ':' &&
17078
437
               !unicode::is_ascii_hex_digit(c);
17079
998
      })) {
Unexecuted instantiation: idna.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Unexecuted instantiation: ada.cpp:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Unexecuted instantiation: serializers.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Unexecuted instantiation: can_parse.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Unexecuted instantiation: unicode.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Unexecuted instantiation: parse.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
url_pattern.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
Line
Count
Source
17076
998
  if (std::ranges::any_of(input, [](char c) {
17077
998
        return c != '[' && c != ']' && c != ':' &&
17078
437
               !unicode::is_ascii_hex_digit(c);
17079
998
      })) {
Unexecuted instantiation: url_search_params.cc:ada::url_pattern_helpers::canonicalize_ipv6_hostname(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::$_0::operator()(char) const
17080
23
    return tl::unexpected(errors::type_error);
17081
23
  }
17082
  // Append the result of running ASCII lowercase given code point to the end of
17083
  // result.
17084
351
  auto hostname = std::string(input);
17085
351
  unicode::to_lower_ascii(hostname.data(), hostname.size());
17086
351
  return hostname;
17087
374
}
17088
17089
tl::expected<std::string, errors> canonicalize_port(
17090
49.1k
    std::string_view port_value) {
17091
  // If portValue is the empty string, return portValue.
17092
49.1k
  if (port_value.empty()) [[unlikely]] {
17093
48.4k
    return "";
17094
48.4k
  }
17095
17096
  // Remove ASCII tab or newline characters
17097
648
  std::string trimmed(port_value);
17098
648
  helpers::remove_ascii_tab_or_newline(trimmed);
17099
17100
648
  if (trimmed.empty()) {
17101
127
    return "";
17102
127
  }
17103
17104
  // Input should start with a digit character
17105
521
  if (!unicode::is_ascii_digit(trimmed.front())) {
17106
262
    return tl::unexpected(errors::type_error);
17107
262
  }
17108
17109
  // Find the first non-digit character
17110
259
  auto first_non_digit =
17111
259
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
17112
259
  std::string_view digits_to_parse =
17113
259
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
17114
17115
  // Here we have that a range of ASCII digit characters identified
17116
  // by digits_to_parse. It is none empty.
17117
  // We want to determine whether it is a valid port number (0-65535).
17118
  // Clearly, if the length is greater than 5, it is invalid.
17119
  // If the length is 5, we need to compare lexicographically to "65535".
17120
  // Otherwise it is valid.
17121
259
  if (digits_to_parse.size() == 5) {
17122
34
    if (digits_to_parse > "65535") {
17123
7
      return tl::unexpected(errors::type_error);
17124
7
    }
17125
225
  } else if (digits_to_parse.size() > 5) {
17126
0
    return tl::unexpected(errors::type_error);
17127
0
  }
17128
252
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
17129
    // Leading zeros are not allowed for multi-digit ports
17130
12
    return tl::unexpected(errors::type_error);
17131
12
  }
17132
  // It is valid! Most times, we do not need to parse it into an integer.
17133
240
  return std::string(digits_to_parse);
17134
252
}
17135
17136
tl::expected<std::string, errors> canonicalize_port_with_protocol(
17137
0
    std::string_view port_value, std::string_view protocol) {
17138
  // If portValue is the empty string, return portValue.
17139
0
  if (port_value.empty()) [[unlikely]] {
17140
0
    return "";
17141
0
  }
17142
17143
  // Handle empty or trailing colon in protocol
17144
0
  if (protocol.empty()) {
17145
0
    protocol = "fake";
17146
0
  } else if (protocol.ends_with(":")) {
17147
0
    protocol.remove_suffix(1);
17148
0
  }
17149
17150
  // Remove ASCII tab or newline characters
17151
0
  std::string trimmed(port_value);
17152
0
  helpers::remove_ascii_tab_or_newline(trimmed);
17153
17154
0
  if (trimmed.empty()) {
17155
0
    return "";
17156
0
  }
17157
17158
  // Input should start with a digit character
17159
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
17160
0
    return tl::unexpected(errors::type_error);
17161
0
  }
17162
17163
  // Find the first non-digit character
17164
0
  auto first_non_digit =
17165
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
17166
0
  std::string_view digits_to_parse =
17167
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
17168
17169
  // Parse the port number
17170
0
  uint16_t parsed_port{};
17171
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
17172
0
  auto result = std::from_chars(digits_to_parse.data(),
17173
0
                                digits_to_parse.data() + digits_to_parse.size(),
17174
0
                                parsed_port);
17175
17176
0
  if (result.ec == std::errc::result_out_of_range) {
17177
0
    return tl::unexpected(errors::type_error);
17178
0
  }
17179
17180
0
  if (result.ec == std::errc()) {
17181
    // Check if this is the default port for the scheme
17182
0
    uint16_t default_port = scheme::get_special_port(protocol);
17183
17184
    // If it's the default port for a special scheme, return empty string
17185
0
    if (default_port != 0 && default_port == parsed_port) {
17186
0
      return "";
17187
0
    }
17188
17189
    // Successfully parsed, return as string
17190
0
    return std::to_string(parsed_port);
17191
0
  }
17192
17193
0
  return tl::unexpected(errors::type_error);
17194
0
}
17195
17196
tl::expected<std::string, errors> canonicalize_pathname(
17197
372k
    std::string_view input) {
17198
372k
  if (input.empty()) [[unlikely]] {
17199
88.7k
    return "";
17200
88.7k
  }
17201
17202
  // Fast path: simple pathnames (no . which needs normalization) can be
17203
  // returned as-is
17204
283k
  bool needs_processing = false;
17205
2.90M
  for (char c : input) {
17206
2.90M
    needs_processing |=
17207
2.90M
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
17208
2.90M
  }
17209
283k
  if (!needs_processing) {
17210
65.6k
    return std::string(input);
17211
65.6k
  }
17212
17213
  // Let leading slash be true if the first code point in value is U+002F (/)
17214
  // and otherwise false.
17215
218k
  const bool leading_slash = input.starts_with("/");
17216
  // Let modified value be "/-" if leading slash is false and otherwise the
17217
  // empty string.
17218
218k
  const auto modified_value = leading_slash ? "" : "/-";
17219
218k
  const auto full_url =
17220
218k
      std::string("fake://fake-url") + modified_value + std::string(input);
17221
218k
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
17222
218k
    const auto pathname = url->get_pathname();
17223
    // If leading slash is false, then set result to the code point substring
17224
    // from 2 to the end of the string within result.
17225
218k
    if (!leading_slash) {
17226
      // pathname should start with "/-" but path traversal (e.g. "../../")
17227
      // can reduce it to just "/" which is shorter than 2 characters.
17228
217k
      if (pathname.size() < 2) {
17229
583
        return tl::unexpected(errors::type_error);
17230
583
      }
17231
216k
      return std::string(pathname.substr(2));
17232
217k
    }
17233
507
    return std::string(pathname);
17234
218k
  }
17235
  // If parseResult is failure, then throw a TypeError.
17236
0
  return tl::unexpected(errors::type_error);
17237
218k
}
17238
17239
tl::expected<std::string, errors> canonicalize_opaque_pathname(
17240
24.0k
    std::string_view input) {
17241
  // If value is the empty string, return value.
17242
24.0k
  if (input.empty()) [[unlikely]] {
17243
2.41k
    return "";
17244
2.41k
  }
17245
  // Let dummyURL be a new URL record.
17246
  // Set dummyURL's path to the empty string.
17247
  // Let parseResult be the result of running URL parsing given value with
17248
  // dummyURL as url and opaque path state as state override.
17249
21.6k
  if (auto url =
17250
21.6k
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
17251
    // Return the result of URL path serializing dummyURL.
17252
21.3k
    return std::string(url->get_pathname());
17253
21.3k
  }
17254
  // If parseResult is failure, then throw a TypeError.
17255
238
  return tl::unexpected(errors::type_error);
17256
21.6k
}
17257
17258
174k
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
17259
  // If value is the empty string, return value.
17260
174k
  if (input.empty()) [[unlikely]] {
17261
173k
    return "";
17262
173k
  }
17263
  // Remove leading '?' if present
17264
687
  std::string new_value;
17265
687
  new_value = input[0] == '?' ? input.substr(1) : input;
17266
  // Remove ASCII tab or newline characters
17267
687
  helpers::remove_ascii_tab_or_newline(new_value);
17268
17269
687
  if (new_value.empty()) {
17270
126
    return "";
17271
126
  }
17272
17273
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
17274
  // Note: "fake://dummy.test" is not a special URL, so we use
17275
  // QUERY_PERCENT_ENCODE
17276
561
  size_t idx = ada::unicode::percent_encode_index(
17277
561
      new_value, character_sets::QUERY_PERCENT_ENCODE);
17278
561
  if (idx == new_value.size()) {
17279
    // No encoding needed
17280
304
    return new_value;
17281
304
  }
17282
  // Percent-encode from the first character that needs encoding
17283
257
  return ada::unicode::percent_encode(
17284
257
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
17285
561
}
17286
17287
173k
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
17288
  // If value is the empty string, return value.
17289
173k
  if (input.empty()) [[unlikely]] {
17290
173k
    return "";
17291
173k
  }
17292
  // Remove leading '#' if present
17293
504
  std::string new_value;
17294
504
  new_value = input[0] == '#' ? input.substr(1) : input;
17295
  // Remove ASCII tab or newline characters
17296
504
  helpers::remove_ascii_tab_or_newline(new_value);
17297
17298
504
  if (new_value.empty()) {
17299
105
    return "";
17300
105
  }
17301
17302
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
17303
399
  size_t idx = ada::unicode::percent_encode_index(
17304
399
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
17305
399
  if (idx == new_value.size()) {
17306
    // No encoding needed
17307
219
    return new_value;
17308
219
  }
17309
  // Percent-encode from the first character that needs encoding
17310
180
  return ada::unicode::percent_encode(
17311
180
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
17312
399
}
17313
17314
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
17315
1.00M
                                                  token_policy policy) {
17316
1.00M
  ada_log("tokenize input: ", input);
17317
  // Let tokenizer be a new tokenizer.
17318
  // Set tokenizer's input to input.
17319
  // Set tokenizer's policy to policy.
17320
1.00M
  auto tokenizer = Tokenizer(input, policy);
17321
  // While tokenizer's index is less than tokenizer's input's code point length:
17322
3.76M
  while (tokenizer.index < tokenizer.input.size()) {
17323
    // Run seek and get the next code point given tokenizer and tokenizer's
17324
    // index.
17325
2.76M
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
17326
17327
    // Malformed UTF-8 must not stall tokenization: report an invalid-char
17328
    // token (lenient) or fail fast (strict), while always making progress.
17329
2.76M
    if (tokenizer.had_invalid_code_point()) {
17330
0
      if (auto error = tokenizer.process_tokenizing_error(tokenizer.next_index,
17331
0
                                                          tokenizer.index)) {
17332
0
        return tl::unexpected(*error);
17333
0
      }
17334
0
      continue;
17335
0
    }
17336
17337
    // If tokenizer's code point is U+002A (*):
17338
2.76M
    if (tokenizer.code_point == '*') {
17339
      // Run add a token with default position and length given tokenizer and
17340
      // "asterisk".
17341
534k
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
17342
534k
      ada_log("add ASTERISK token");
17343
      // Continue.
17344
534k
      continue;
17345
534k
    }
17346
17347
    // If tokenizer's code point is U+002B (+) or U+003F (?):
17348
2.22M
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
17349
      // Run add a token with default position and length given tokenizer and
17350
      // "other-modifier".
17351
4.76k
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
17352
      // Continue.
17353
4.76k
      continue;
17354
4.76k
    }
17355
17356
    // If tokenizer's code point is U+005C (\):
17357
2.22M
    if (tokenizer.code_point == '\\') {
17358
      // If tokenizer's index is equal to tokenizer's input's code point length
17359
      // - 1:
17360
4.28k
      if (tokenizer.index == tokenizer.input.size() - 1) {
17361
        // Run process a tokenizing error given tokenizer, tokenizer's next
17362
        // index, and tokenizer's index.
17363
637
        if (auto error = tokenizer.process_tokenizing_error(
17364
637
                tokenizer.next_index, tokenizer.index)) {
17365
574
          ada_log("process_tokenizing_error failed");
17366
574
          return tl::unexpected(*error);
17367
574
        }
17368
63
        continue;
17369
637
      }
17370
17371
      // Let escaped index be tokenizer's next index.
17372
3.65k
      auto escaped_index = tokenizer.next_index;
17373
      // Run get the next code point given tokenizer.
17374
3.65k
      tokenizer.get_next_code_point();
17375
3.65k
      if (tokenizer.had_invalid_code_point()) {
17376
0
        if (auto error = tokenizer.process_tokenizing_error(tokenizer.next_index,
17377
0
                                                            escaped_index)) {
17378
0
          return tl::unexpected(*error);
17379
0
        }
17380
0
        continue;
17381
0
      }
17382
      // Run add a token with default length given tokenizer, "escaped-char",
17383
      // tokenizer's next index, and escaped index.
17384
3.65k
      tokenizer.add_token_with_default_length(
17385
3.65k
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
17386
3.65k
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
17387
3.65k
              " with escaped index ", escaped_index);
17388
      // Continue.
17389
3.65k
      continue;
17390
3.65k
    }
17391
17392
    // If tokenizer's code point is U+007B ({):
17393
2.21M
    if (tokenizer.code_point == '{') {
17394
      // Run add a token with default position and length given tokenizer and
17395
      // "open".
17396
4.67k
      tokenizer.add_token_with_defaults(token_type::OPEN);
17397
4.67k
      ada_log("add OPEN token");
17398
4.67k
      continue;
17399
4.67k
    }
17400
17401
    // If tokenizer's code point is U+007D (}):
17402
2.21M
    if (tokenizer.code_point == '}') {
17403
      // Run add a token with default position and length given tokenizer and
17404
      // "close".
17405
4.94k
      tokenizer.add_token_with_defaults(token_type::CLOSE);
17406
4.94k
      ada_log("add CLOSE token");
17407
4.94k
      continue;
17408
4.94k
    }
17409
17410
    // If tokenizer's code point is U+003A (:):
17411
2.20M
    if (tokenizer.code_point == ':') {
17412
      // Let name position be tokenizer's next index.
17413
44.9k
      auto name_position = tokenizer.next_index;
17414
      // Let name start be name position.
17415
44.9k
      auto name_start = name_position;
17416
44.9k
      bool invalid_name = false;
17417
      // While name position is less than tokenizer's input's code point length:
17418
53.6k
      while (name_position < tokenizer.input.size()) {
17419
        // Run seek and get the next code point given tokenizer and name
17420
        // position.
17421
52.2k
        tokenizer.seek_and_get_next_code_point(name_position);
17422
52.2k
        if (tokenizer.had_invalid_code_point()) {
17423
0
          if (auto error = tokenizer.process_tokenizing_error(
17424
0
                  tokenizer.next_index, name_position)) {
17425
0
            return tl::unexpected(*error);
17426
0
          }
17427
0
          invalid_name = true;
17428
0
          break;
17429
0
        }
17430
        // Let first code point be true if name position equals name start and
17431
        // false otherwise.
17432
52.2k
        bool first_code_point = name_position == name_start;
17433
        // Let valid code point be the result of running is a valid name code
17434
        // point given tokenizer's code point and first code point.
17435
52.2k
        auto valid_code_point =
17436
52.2k
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
17437
52.2k
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
17438
52.2k
                " first_code_point=", first_code_point,
17439
52.2k
                " valid_code_point=", valid_code_point);
17440
        // If valid code point is false break.
17441
52.2k
        if (!valid_code_point) break;
17442
        // Set name position to tokenizer's next index.
17443
8.62k
        name_position = tokenizer.next_index;
17444
8.62k
      }
17445
17446
44.9k
      if (invalid_name) {
17447
0
        continue;
17448
0
      }
17449
17450
      // If name position is less than or equal to name start:
17451
44.9k
      if (name_position <= name_start) {
17452
        // Run process a tokenizing error given tokenizer, name start, and
17453
        // tokenizer's index.
17454
40.6k
        if (auto error = tokenizer.process_tokenizing_error(name_start,
17455
40.6k
                                                            tokenizer.index)) {
17456
272
          ada_log("process_tokenizing_error failed");
17457
272
          return tl::unexpected(*error);
17458
272
        }
17459
        // Continue
17460
40.3k
        continue;
17461
40.6k
      }
17462
17463
      // Run add a token with default length given tokenizer, "name", name
17464
      // position, and name start.
17465
4.34k
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
17466
4.34k
                                              name_start);
17467
4.34k
      continue;
17468
44.9k
    }
17469
17470
    // If tokenizer's code point is U+0028 (():
17471
2.16M
    if (tokenizer.code_point == '(') {
17472
      // Let depth be 1.
17473
6.63k
      size_t depth = 1;
17474
      // Let regexp position be tokenizer's next index.
17475
6.63k
      auto regexp_position = tokenizer.next_index;
17476
      // Let regexp start be regexp position.
17477
6.63k
      auto regexp_start = regexp_position;
17478
      // Let error be false.
17479
6.63k
      bool error = false;
17480
17481
      // While regexp position is less than tokenizer's input's code point
17482
      // length:
17483
23.5k
      while (regexp_position < tokenizer.input.size()) {
17484
        // Run seek and get the next code point given tokenizer and regexp
17485
        // position.
17486
22.9k
        tokenizer.seek_and_get_next_code_point(regexp_position);
17487
22.9k
        if (tokenizer.had_invalid_code_point()) {
17488
0
          if (auto process_error = tokenizer.process_tokenizing_error(
17489
0
                  tokenizer.next_index, regexp_position)) {
17490
0
            return tl::unexpected(*process_error);
17491
0
          }
17492
0
          error = true;
17493
0
          break;
17494
0
        }
17495
17496
        // TODO: Optimization opportunity: The next 2 if statements can be
17497
        // merged. If the result of running is ASCII given tokenizer's code
17498
        // point is false:
17499
22.9k
        if (!unicode::is_ascii(tokenizer.code_point)) {
17500
          // Run process a tokenizing error given tokenizer, regexp start, and
17501
          // tokenizer's index.
17502
0
          if (auto process_error = tokenizer.process_tokenizing_error(
17503
0
                  regexp_start, tokenizer.index)) {
17504
0
            return tl::unexpected(*process_error);
17505
0
          }
17506
          // Set error to true.
17507
0
          error = true;
17508
0
          break;
17509
0
        }
17510
17511
        // If regexp position equals regexp start and tokenizer's code point is
17512
        // U+003F (?):
17513
22.9k
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
17514
          // Run process a tokenizing error given tokenizer, regexp start, and
17515
          // tokenizer's index.
17516
531
          if (auto process_error = tokenizer.process_tokenizing_error(
17517
531
                  regexp_start, tokenizer.index)) {
17518
12
            return tl::unexpected(*process_error);
17519
12
          }
17520
          // Set error to true;
17521
519
          error = true;
17522
519
          break;
17523
531
        }
17524
17525
        // If tokenizer's code point is U+005C (\):
17526
22.4k
        if (tokenizer.code_point == '\\') {
17527
          // If regexp position equals tokenizer's input's code point length - 1
17528
1.89k
          if (regexp_position == tokenizer.input.size() - 1) {
17529
            // Run process a tokenizing error given tokenizer, regexp start, and
17530
            // tokenizer's index.
17531
38
            if (auto process_error = tokenizer.process_tokenizing_error(
17532
38
                    regexp_start, tokenizer.index)) {
17533
20
              return tl::unexpected(*process_error);
17534
20
            }
17535
            // Set error to true.
17536
18
            error = true;
17537
18
            break;
17538
38
          }
17539
          // Run get the next code point given tokenizer.
17540
1.86k
          auto escaped_index = tokenizer.next_index;
17541
1.86k
          tokenizer.get_next_code_point();
17542
1.86k
          if (tokenizer.had_invalid_code_point()) {
17543
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17544
0
                    tokenizer.next_index, escaped_index)) {
17545
0
              return tl::unexpected(*process_error);
17546
0
            }
17547
0
            error = true;
17548
0
            break;
17549
0
          }
17550
          // If the result of running is ASCII given tokenizer's code point is
17551
          // false:
17552
1.86k
          if (!unicode::is_ascii(tokenizer.code_point)) {
17553
            // Run process a tokenizing error given tokenizer, regexp start, and
17554
            // tokenizer's index.
17555
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17556
0
                    regexp_start, tokenizer.index);
17557
0
                process_error.has_value()) {
17558
0
              return tl::unexpected(*process_error);
17559
0
            }
17560
            // Set error to true.
17561
0
            error = true;
17562
0
            break;
17563
0
          }
17564
          // Set regexp position to tokenizer's next index.
17565
1.86k
          regexp_position = tokenizer.next_index;
17566
1.86k
          continue;
17567
1.86k
        }
17568
17569
        // If tokenizer's code point is U+0029 ()):
17570
20.5k
        if (tokenizer.code_point == ')') {
17571
          // Decrement depth by 1.
17572
4.19k
          depth--;
17573
          // If depth is 0:
17574
4.19k
          if (depth == 0) {
17575
            // Set regexp position to tokenizer's next index.
17576
3.74k
            regexp_position = tokenizer.next_index;
17577
            // Break.
17578
3.74k
            break;
17579
3.74k
          }
17580
16.3k
        } else if (tokenizer.code_point == '(') {
17581
          // Otherwise if tokenizer's code point is U+0028 (():
17582
          // Increment depth by 1.
17583
2.54k
          depth++;
17584
          // If regexp position equals tokenizer's input's code point length -
17585
          // 1:
17586
2.54k
          if (regexp_position == tokenizer.input.size() - 1) {
17587
            // Run process a tokenizing error given tokenizer, regexp start, and
17588
            // tokenizer's index.
17589
31
            if (auto process_error = tokenizer.process_tokenizing_error(
17590
31
                    regexp_start, tokenizer.index)) {
17591
22
              return tl::unexpected(*process_error);
17592
22
            }
17593
            // Set error to true.
17594
9
            error = true;
17595
9
            break;
17596
31
          }
17597
          // Let temporary position be tokenizer's next index.
17598
2.51k
          auto temporary_position = tokenizer.next_index;
17599
          // Run get the next code point given tokenizer.
17600
2.51k
          tokenizer.get_next_code_point();
17601
2.51k
          if (tokenizer.had_invalid_code_point()) {
17602
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17603
0
                    tokenizer.next_index, temporary_position)) {
17604
0
              return tl::unexpected(*process_error);
17605
0
            }
17606
0
            error = true;
17607
0
            break;
17608
0
          }
17609
          // If tokenizer's code point is not U+003F (?):
17610
2.51k
          if (tokenizer.code_point != '?') {
17611
            // Run process a tokenizing error given tokenizer, regexp start, and
17612
            // tokenizer's index.
17613
1.72k
            if (auto process_error = tokenizer.process_tokenizing_error(
17614
1.72k
                    regexp_start, tokenizer.index)) {
17615
21
              return tl::unexpected(*process_error);
17616
21
            }
17617
            // Set error to true.
17618
1.70k
            error = true;
17619
1.70k
            break;
17620
1.72k
          }
17621
          // Set tokenizer's next index to temporary position.
17622
788
          tokenizer.next_index = temporary_position;
17623
788
        }
17624
        // Set regexp position to tokenizer's next index.
17625
15.0k
        regexp_position = tokenizer.next_index;
17626
15.0k
      }
17627
17628
      // If error is true continue.
17629
6.55k
      if (error) continue;
17630
      // If depth is not zero:
17631
4.31k
      if (depth != 0) {
17632
        // Run process a tokenizing error given tokenizer, regexp start, and
17633
        // tokenizer's index.
17634
569
        if (auto process_error = tokenizer.process_tokenizing_error(
17635
569
                regexp_start, tokenizer.index)) {
17636
248
          return tl::unexpected(*process_error);
17637
248
        }
17638
321
        continue;
17639
569
      }
17640
      // Let regexp length be regexp position - regexp start - 1.
17641
3.74k
      auto regexp_length = regexp_position - regexp_start - 1;
17642
      // If regexp length is zero:
17643
3.74k
      if (regexp_length == 0) {
17644
        // Run process a tokenizing error given tokenizer, regexp start, and
17645
        // tokenizer's index.
17646
285
        if (auto process_error = tokenizer.process_tokenizing_error(
17647
285
                regexp_start, tokenizer.index)) {
17648
36
          ada_log("process_tokenizing_error failed");
17649
36
          return tl::unexpected(*process_error);
17650
36
        }
17651
249
        continue;
17652
285
      }
17653
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17654
      // start, and regexp length.
17655
3.45k
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17656
3.45k
                          regexp_length);
17657
3.45k
      continue;
17658
3.74k
    }
17659
    // Run add a token with default position and length given tokenizer and
17660
    // "char".
17661
2.15M
    tokenizer.add_token_with_defaults(token_type::CHAR);
17662
2.15M
  }
17663
  // Run add a token with default length given tokenizer, "end", tokenizer's
17664
  // index, and tokenizer's index.
17665
999k
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17666
999k
                                          tokenizer.index);
17667
17668
999k
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17669
  // Return tokenizer's token list.
17670
999k
  return tokenizer.token_list;
17671
1.00M
}
17672
17673
namespace {
17674
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
17675
  std::array<uint8_t, 256> out{};
17676
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
17677
    out[c] = 1;
17678
  }
17679
  return out;
17680
}();
17681
17682
1.73M
constexpr bool should_escape_pattern_char(char c) {
17683
1.73M
  return escape_pattern_table[static_cast<uint8_t>(c)];
17684
1.73M
}
Unexecuted instantiation: idna.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Unexecuted instantiation: ada.cpp:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Unexecuted instantiation: serializers.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Unexecuted instantiation: can_parse.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Unexecuted instantiation: unicode.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Unexecuted instantiation: parse.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
url_pattern.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
Line
Count
Source
17682
1.73M
constexpr bool should_escape_pattern_char(char c) {
17683
1.73M
  return escape_pattern_table[static_cast<uint8_t>(c)];
17684
1.73M
}
Unexecuted instantiation: url_search_params.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_pattern_char(char)
17685
}  // namespace
17686
17687
1.26M
std::string escape_pattern_string(std::string_view input) {
17688
1.26M
  ada_log("escape_pattern_string called with input=", input);
17689
1.26M
  if (input.empty()) [[unlikely]] {
17690
951k
    return "";
17691
951k
  }
17692
  // Assert: input is an ASCII string.
17693
309k
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17694
  // Let result be the empty string.
17695
309k
  std::string result{};
17696
  // Reserve extra space for potential escapes
17697
309k
  result.reserve(input.size() * 2);
17698
17699
  // While index is less than input's length:
17700
1.73M
  for (const char c : input) {
17701
1.73M
    if (should_escape_pattern_char(c)) {
17702
      // Append U+005C (\) to the end of result.
17703
1.20k
      result.push_back('\\');
17704
1.20k
    }
17705
    // Append c to the end of result.
17706
1.73M
    result.push_back(c);
17707
1.73M
  }
17708
  // Return result.
17709
309k
  return result;
17710
1.26M
}
17711
17712
namespace {
17713
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17714
  std::array<uint8_t, 256> out{};
17715
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17716
                  '|', '/', '\\'}) {
17717
    out[c] = 1;
17718
  }
17719
  return out;
17720
}();
17721
17722
275k
constexpr bool should_escape_regexp_char(char c) {
17723
275k
  return escape_regexp_table[(uint8_t)c];
17724
275k
}
Unexecuted instantiation: idna.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Unexecuted instantiation: ada.cpp:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Unexecuted instantiation: serializers.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Unexecuted instantiation: can_parse.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Unexecuted instantiation: unicode.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Unexecuted instantiation: parse.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
url_pattern.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
Line
Count
Source
17722
275k
constexpr bool should_escape_regexp_char(char c) {
17723
275k
  return escape_regexp_table[(uint8_t)c];
17724
275k
}
Unexecuted instantiation: url_search_params.cc:ada::url_pattern_helpers::(anonymous namespace)::should_escape_regexp_char(char)
17725
}  // namespace
17726
17727
1.01M
std::string escape_regexp_string(std::string_view input) {
17728
  // Assert: input is an ASCII string.
17729
1.01M
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17730
  // Let result be the empty string.
17731
1.01M
  std::string result{};
17732
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17733
1.01M
  result.reserve(input.size() * 2);
17734
1.01M
  for (const char c : input) {
17735
275k
    if (should_escape_regexp_char(c)) {
17736
      // Avoid temporary string allocation - directly append characters
17737
244k
      result.push_back('\\');
17738
244k
      result.push_back(c);
17739
244k
    } else {
17740
30.5k
      result.push_back(c);
17741
30.5k
    }
17742
275k
  }
17743
1.01M
  return result;
17744
1.01M
}
17745
17746
std::string process_base_url_string(std::string_view input,
17747
51.8k
                                    url_pattern_init::process_type type) {
17748
  // If type is not "pattern" return input.
17749
51.8k
  if (type != url_pattern_init::process_type::pattern) {
17750
0
    return std::string(input);
17751
0
  }
17752
  // Return the result of escaping a pattern string given input.
17753
51.8k
  return escape_pattern_string(input);
17754
51.8k
}
17755
17756
constexpr bool is_absolute_pathname(
17757
50.9k
    std::string_view input, url_pattern_init::process_type type) noexcept {
17758
  // If input is the empty string, then return false.
17759
50.9k
  if (input.empty()) [[unlikely]] {
17760
0
    return false;
17761
0
  }
17762
  // If input[0] is U+002F (/), then return true.
17763
50.9k
  if (input.starts_with("/")) return true;
17764
  // If type is "url", then return false.
17765
0
  if (type == url_pattern_init::process_type::url) return false;
17766
  // If input's code point length is less than 2, then return false.
17767
0
  if (input.size() < 2) return false;
17768
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17769
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17770
  // Return false.
17771
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17772
0
}
17773
17774
std::string generate_pattern_string(
17775
    std::vector<url_pattern_part>& part_list,
17776
920k
    url_pattern_compile_component_options& options) {
17777
  // Let result be the empty string.
17778
920k
  std::string result{};
17779
  // Let index list be the result of getting the indices for part list.
17780
  // For each index of index list:
17781
1.63M
  for (size_t index = 0; index < part_list.size(); index++) {
17782
    // Let part be part list[index].
17783
    // Use reference to avoid copy
17784
714k
    const auto& part = part_list[index];
17785
    // Let previous part be part list[index - 1] if index is greater than 0,
17786
    // otherwise let it be null.
17787
    // Use pointer to avoid copy
17788
714k
    const url_pattern_part* previous_part =
17789
714k
        index == 0 ? nullptr : &part_list[index - 1];
17790
    // Let next part be part list[index + 1] if index is less than index list's
17791
    // size - 1, otherwise let it be null.
17792
714k
    const url_pattern_part* next_part =
17793
714k
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17794
    // If part's type is "fixed-text" then:
17795
714k
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17796
      // If part's modifier is "none" then:
17797
218k
      if (part.modifier == url_pattern_part_modifier::none) {
17798
        // Append the result of running escape a pattern string given part's
17799
        // value to the end of result.
17800
218k
        result.append(escape_pattern_string(part.value));
17801
218k
        continue;
17802
218k
      }
17803
      // Append "{" to the end of result.
17804
345
      result += "{";
17805
      // Append the result of running escape a pattern string given part's value
17806
      // to the end of result.
17807
345
      result.append(escape_pattern_string(part.value));
17808
      // Append "}" to the end of result.
17809
345
      result += "}";
17810
      // Append the result of running convert a modifier to a string given
17811
      // part's modifier to the end of result.
17812
345
      result.append(convert_modifier_to_string(part.modifier));
17813
345
      continue;
17814
218k
    }
17815
    // Let custom name be true if part's name[0] is not an ASCII digit;
17816
    // otherwise false.
17817
495k
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17818
    // Let needs grouping be true if at least one of the following are true,
17819
    // otherwise let it be false:
17820
    // - part's suffix is not the empty string.
17821
    // - part's prefix is not the empty string and is not options's prefix code
17822
    // point.
17823
495k
    bool needs_grouping =
17824
495k
        !part.suffix.empty() ||
17825
494k
        (!part.prefix.empty() && !options.get_prefix().empty() &&
17826
39.1k
         part.prefix[0] != options.get_prefix()[0]);
17827
17828
    // If all of the following are true:
17829
    // - needs grouping is false; and
17830
    // - custom name is true; and
17831
    // - part's type is "segment-wildcard"; and
17832
    // - part's modifier is "none"; and
17833
    // - next part is not null; and
17834
    // - next part's prefix is the empty string; and
17835
    // - next part's suffix is the empty string
17836
495k
    if (!needs_grouping && custom_name &&
17837
1.61k
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17838
1.59k
        part.modifier == url_pattern_part_modifier::none && next_part &&
17839
620
        next_part->prefix.empty() && next_part->suffix.empty()) {
17840
      // If next part's type is "fixed-text":
17841
567
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17842
        // Set needs grouping to true if the result of running is a valid name
17843
        // code point given next part's value's first code point and the boolean
17844
        // false is true.
17845
221
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17846
60
          needs_grouping = true;
17847
60
        }
17848
346
      } else {
17849
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17850
346
        needs_grouping = !next_part->name.empty() &&
17851
346
                         unicode::is_ascii_digit(next_part->name[0]);
17852
346
      }
17853
567
    }
17854
17855
    // If all of the following are true:
17856
    // - needs grouping is false; and
17857
    // - part's prefix is the empty string; and
17858
    // - previous part is not null; and
17859
    // - previous part's type is "fixed-text"; and
17860
    // - previous part's value's last code point is options's prefix code point.
17861
    // then set needs grouping to true.
17862
495k
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17863
6.68k
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17864
3.91k
        !previous_part->value.empty() && !options.get_prefix().empty() &&
17865
567
        previous_part->value.back() == options.get_prefix()[0]) {
17866
170
      needs_grouping = true;
17867
170
    }
17868
17869
    // Assert: part's name is not the empty string or null.
17870
495k
    ADA_ASSERT_TRUE(!part.name.empty());
17871
17872
    // If needs grouping is true, then append "{" to the end of result.
17873
495k
    if (needs_grouping) {
17874
823
      result.append("{");
17875
823
    }
17876
17877
    // Append the result of running escape a pattern string given part's prefix
17878
    // to the end of result.
17879
495k
    result.append(escape_pattern_string(part.prefix));
17880
17881
    // If custom name is true:
17882
495k
    if (custom_name) {
17883
      // Append ":" to the end of result.
17884
1.79k
      result.append(":");
17885
      // Append part's name to the end of result.
17886
1.79k
      result.append(part.name);
17887
1.79k
    }
17888
17889
    // If part's type is "regexp" then:
17890
495k
    if (part.type == url_pattern_part_type::REGEXP) {
17891
      // Append "(" to the end of result.
17892
2.29k
      result.append("(");
17893
      // Append part's value to the end of result.
17894
2.29k
      result.append(part.value);
17895
      // Append ")" to the end of result.
17896
2.29k
      result.append(")");
17897
493k
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17898
1.80k
               !custom_name) {
17899
      // Otherwise if part's type is "segment-wildcard" and custom name is
17900
      // false: Append "(" to the end of result.
17901
35
      result.append("(");
17902
      // Append the result of running generate a segment wildcard regexp given
17903
      // options to the end of result.
17904
35
      result.append(generate_segment_wildcard_regexp(options));
17905
      // Append ")" to the end of result.
17906
35
      result.append(")");
17907
493k
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17908
      // Otherwise if part's type is "full-wildcard":
17909
      // If custom name is false and one of the following is true:
17910
      // - previous part is null; or
17911
      // - previous part's type is "fixed-text"; or
17912
      // - previous part's modifier is not "none"; or
17913
      // - needs grouping is true; or
17914
      // - part's prefix is not the empty string
17915
      // - then append "*" to the end of result.
17916
491k
      if (!custom_name &&
17917
491k
          (!previous_part ||
17918
6.05k
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17919
2.27k
           previous_part->modifier != url_pattern_part_modifier::none ||
17920
491k
           needs_grouping || !part.prefix.empty())) {
17921
491k
        result.append("*");
17922
491k
      } else {
17923
        // Append "(" to the end of result.
17924
        // Append full wildcard regexp value to the end of result.
17925
        // Append ")" to the end of result.
17926
53
        result.append("(.*)");
17927
53
      }
17928
491k
    }
17929
17930
    // If all of the following are true:
17931
    // - part's type is "segment-wildcard"; and
17932
    // - custom name is true; and
17933
    // - part's suffix is not the empty string; and
17934
    // - The result of running is a valid name code point given part's suffix's
17935
    // first code point and the boolean false is true then append U+005C (\) to
17936
    // the end of result.
17937
495k
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17938
1.77k
        !part.suffix.empty() &&
17939
175
        idna::valid_name_code_point(part.suffix[0], false)) {
17940
91
      result.append("\\");
17941
91
    }
17942
17943
    // Append the result of running escape a pattern string given part's suffix
17944
    // to the end of result.
17945
495k
    result.append(escape_pattern_string(part.suffix));
17946
    // If needs grouping is true, then append "}" to the end of result.
17947
495k
    if (needs_grouping) result.append("}");
17948
    // Append the result of running convert a modifier to a string given part's
17949
    // modifier to the end of result.
17950
495k
    result.append(convert_modifier_to_string(part.modifier));
17951
495k
  }
17952
  // Return result.
17953
920k
  return result;
17954
920k
}
17955
}  // namespace ada::url_pattern_helpers
17956
17957
#endif  // ADA_INCLUDE_URL_PATTERN
17958
/* end file src/url_pattern_helpers.cpp */
17959
/* begin file src/url_pattern_regex.cpp */
17960
#if ADA_INCLUDE_URL_PATTERN
17961
17962
17963
namespace ada::url_pattern_regex {
17964
17965
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17966
std::optional<std::regex> std_regex_provider::create_instance(
17967
44.0k
    std::string_view pattern, bool ignore_case) {
17968
  // Let flags be an empty string.
17969
  // If options's ignore case is true then set flags to "vi".
17970
  // Otherwise set flags to "v"
17971
44.0k
  auto flags = ignore_case
17972
44.0k
                   ? std::regex::icase | std::regex_constants::ECMAScript
17973
44.0k
                   : std::regex_constants::ECMAScript;
17974
44.0k
  try {
17975
44.0k
    return std::regex(pattern.data(), pattern.size(), flags);
17976
44.0k
  } catch (const std::regex_error& e) {
17977
1.17k
    (void)e;
17978
1.17k
    ada_log("std_regex_provider::create_instance failed:", e.what());
17979
1.17k
    return std::nullopt;
17980
1.17k
  }
17981
44.0k
}
17982
17983
std::optional<std::vector<std::optional<std::string>>>
17984
std_regex_provider::regex_search(std::string_view input,
17985
7.37k
                                 const std::regex& pattern) {
17986
  // Use iterator-based regex_search to avoid string allocation
17987
7.37k
  std::match_results<std::string_view::const_iterator> match_result;
17988
7.37k
  try {
17989
7.37k
    if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17990
7.37k
                           std::regex_constants::match_any)) {
17991
3.32k
      return std::nullopt;
17992
3.32k
    }
17993
7.37k
  } catch (const std::regex_error& e) {
17994
66
    (void)e;
17995
66
    ada_log("std_regex_provider::regex_search failed:", e.what());
17996
66
    return std::nullopt;
17997
66
  }
17998
3.98k
  std::vector<std::optional<std::string>> matches;
17999
  // If input is empty, let's assume the result will be empty as well.
18000
3.98k
  if (input.empty() || match_result.empty()) {
18001
1.20k
    return matches;
18002
1.20k
  }
18003
2.78k
  matches.reserve(match_result.size());
18004
9.25k
  for (size_t i = 1; i < match_result.size(); ++i) {
18005
6.47k
    if (auto entry = match_result[i]; entry.matched) {
18006
6.13k
      matches.emplace_back(entry.str());
18007
6.13k
    } else {
18008
      // A capture group that did not participate in the match is undefined,
18009
      // not absent. Emitting nullopt keeps the result aligned by position with
18010
      // the component's group name list; dropping it shifts every later group
18011
      // onto the wrong name.
18012
339
      matches.emplace_back(std::nullopt);
18013
339
    }
18014
6.47k
  }
18015
2.78k
  return matches;
18016
3.98k
}
18017
18018
bool std_regex_provider::regex_match(std::string_view input,
18019
11.4k
                                     const std::regex& pattern) {
18020
11.4k
  try {
18021
11.4k
    return std::regex_match(input.begin(), input.end(), pattern);
18022
11.4k
  } catch (const std::regex_error& e) {
18023
83
    (void)e;
18024
83
    ada_log("std_regex_provider::regex_match failed:", e.what());
18025
83
    return false;
18026
83
  }
18027
11.4k
}
18028
18029
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
18030
18031
}  // namespace ada::url_pattern_regex
18032
18033
#endif  // ADA_INCLUDE_URL_PATTERN
18034
/* end file src/url_pattern_regex.cpp */
18035
#endif  // ADA_INCLUDE_URL_PATTERN
18036
18037
/* begin file src/ada_c.cpp */
18038
// NOLINTBEGIN(bugprone-exception-escape,
18039
// bugprone-suspicious-stringview-data-usage)
18040
18041
230k
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
18042
230k
  return *(ada::result<ada::url_aggregator>*)result;
18043
230k
}
18044
18045
extern "C" {
18046
typedef void* ada_url;
18047
typedef void* ada_url_search_params;
18048
typedef void* ada_strings;
18049
typedef void* ada_url_search_params_keys_iter;
18050
typedef void* ada_url_search_params_values_iter;
18051
typedef void* ada_url_search_params_entries_iter;
18052
18053
struct ada_string {
18054
  const char* data;
18055
  size_t length;
18056
};
18057
18058
struct ada_owned_string {
18059
  const char* data;
18060
  size_t length;
18061
};
18062
18063
struct ada_string_pair {
18064
  ada_string key;
18065
  ada_string value;
18066
};
18067
18068
128k
ada_string ada_string_create(const char* data, size_t length) {
18069
128k
  ada_string out{};
18070
128k
  out.data = data;
18071
128k
  out.length = length;
18072
128k
  return out;
18073
128k
}
18074
18075
struct ada_url_components {
18076
  /*
18077
   * By using 32-bit integers, we implicitly assume that the URL string
18078
   * cannot exceed 4 GB.
18079
   *
18080
   * https://user:pass@example.com:1234/foo/bar?baz#quux
18081
   *       |     |    |          | ^^^^|       |   |
18082
   *       |     |    |          | |   |       |   `----- hash_start
18083
   *       |     |    |          | |   |       `--------- search_start
18084
   *       |     |    |          | |   `----------------- pathname_start
18085
   *       |     |    |          | `--------------------- port
18086
   *       |     |    |          `----------------------- host_end
18087
   *       |     |    `---------------------------------- host_start
18088
   *       |     `--------------------------------------- username_end
18089
   *       `--------------------------------------------- protocol_end
18090
   */
18091
  uint32_t protocol_end;
18092
  /**
18093
   * Username end is not `omitted` by default (-1) to make username and password
18094
   * getters less costly to implement.
18095
   */
18096
  uint32_t username_end;
18097
  uint32_t host_start;
18098
  uint32_t host_end;
18099
  uint32_t port;
18100
  uint32_t pathname_start;
18101
  uint32_t search_start;
18102
  uint32_t hash_start;
18103
};
18104
18105
13.1k
ada_url ada_parse(const char* input, size_t length) noexcept {
18106
13.1k
  return new ada::result<ada::url_aggregator>(
18107
13.1k
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
18108
13.1k
}
18109
18110
ada_url ada_parse_with_base(const char* input, size_t input_length,
18111
8.50k
                            const char* base, size_t base_length) noexcept {
18112
8.50k
  auto base_out =
18113
8.50k
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
18114
18115
8.50k
  if (!base_out) {
18116
7.70k
    return new ada::result<ada::url_aggregator>(base_out);
18117
7.70k
  }
18118
18119
799
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
18120
799
      std::string_view(input, input_length), &base_out.value()));
18121
8.50k
}
18122
18123
8.50k
bool ada_can_parse(const char* input, size_t length) noexcept {
18124
8.50k
  return ada::can_parse(std::string_view(input, length));
18125
8.50k
}
18126
18127
bool ada_can_parse_with_base(const char* input, size_t input_length,
18128
8.50k
                             const char* base, size_t base_length) noexcept {
18129
8.50k
  std::string_view base_view(base, base_length);
18130
8.50k
  return ada::can_parse(std::string_view(input, input_length), &base_view);
18131
8.50k
}
18132
18133
26.3k
void ada_free(ada_url result) noexcept {
18134
26.3k
  auto* r = (ada::result<ada::url_aggregator>*)result;
18135
26.3k
  delete r;
18136
26.3k
}
18137
18138
4.67k
ada_url ada_copy(ada_url input) noexcept {
18139
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(input);
18140
4.67k
  return new ada::result<ada::url_aggregator>(r);
18141
4.67k
}
18142
18143
26.3k
bool ada_is_valid(ada_url result) noexcept {
18144
26.3k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18145
26.3k
  return r.has_value();
18146
26.3k
}
18147
18148
// caller must free the result with ada_free_owned_string
18149
5.19k
ada_owned_string ada_get_origin(ada_url result) noexcept {
18150
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18151
5.19k
  ada_owned_string owned{};
18152
5.19k
  if (!r) {
18153
0
    owned.data = nullptr;
18154
0
    owned.length = 0;
18155
0
    return owned;
18156
0
  }
18157
5.19k
  std::string out = r->get_origin();
18158
5.19k
  owned.length = out.size();
18159
5.19k
  owned.data = new char[owned.length];
18160
5.19k
  memcpy((void*)owned.data, out.data(), owned.length);
18161
5.19k
  return owned;
18162
5.19k
}
18163
18164
30.7k
void ada_free_owned_string(ada_owned_string owned) noexcept {
18165
30.7k
  delete[] owned.data;
18166
30.7k
}
18167
18168
28.5k
ada_string ada_get_href(ada_url result) noexcept {
18169
28.5k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18170
28.5k
  if (!r) {
18171
0
    return ada_string_create(nullptr, 0);
18172
0
  }
18173
28.5k
  std::string_view out = r->get_href();
18174
28.5k
  return ada_string_create(out.data(), out.length());
18175
28.5k
}
18176
18177
5.19k
ada_string ada_get_username(ada_url result) noexcept {
18178
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18179
5.19k
  if (!r) {
18180
0
    return ada_string_create(nullptr, 0);
18181
0
  }
18182
5.19k
  std::string_view out = r->get_username();
18183
5.19k
  return ada_string_create(out.data(), out.length());
18184
5.19k
}
18185
18186
5.19k
ada_string ada_get_password(ada_url result) noexcept {
18187
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18188
5.19k
  if (!r) {
18189
0
    return ada_string_create(nullptr, 0);
18190
0
  }
18191
5.19k
  std::string_view out = r->get_password();
18192
5.19k
  return ada_string_create(out.data(), out.length());
18193
5.19k
}
18194
18195
5.19k
ada_string ada_get_port(ada_url result) noexcept {
18196
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18197
5.19k
  if (!r) {
18198
0
    return ada_string_create(nullptr, 0);
18199
0
  }
18200
5.19k
  std::string_view out = r->get_port();
18201
5.19k
  return ada_string_create(out.data(), out.length());
18202
5.19k
}
18203
18204
5.19k
ada_string ada_get_hash(ada_url result) noexcept {
18205
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18206
5.19k
  if (!r) {
18207
0
    return ada_string_create(nullptr, 0);
18208
0
  }
18209
5.19k
  std::string_view out = r->get_hash();
18210
5.19k
  return ada_string_create(out.data(), out.length());
18211
5.19k
}
18212
18213
4.67k
ada_string ada_get_host(ada_url result) noexcept {
18214
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18215
4.67k
  if (!r) {
18216
0
    return ada_string_create(nullptr, 0);
18217
0
  }
18218
4.67k
  std::string_view out = r->get_host();
18219
4.67k
  return ada_string_create(out.data(), out.length());
18220
4.67k
}
18221
18222
5.19k
ada_string ada_get_hostname(ada_url result) noexcept {
18223
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18224
5.19k
  if (!r) {
18225
0
    return ada_string_create(nullptr, 0);
18226
0
  }
18227
5.19k
  std::string_view out = r->get_hostname();
18228
5.19k
  return ada_string_create(out.data(), out.length());
18229
5.19k
}
18230
18231
5.19k
ada_string ada_get_pathname(ada_url result) noexcept {
18232
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18233
5.19k
  if (!r) {
18234
0
    return ada_string_create(nullptr, 0);
18235
0
  }
18236
5.19k
  std::string_view out = r->get_pathname();
18237
5.19k
  return ada_string_create(out.data(), out.length());
18238
5.19k
}
18239
18240
5.19k
ada_string ada_get_search(ada_url result) noexcept {
18241
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18242
5.19k
  if (!r) {
18243
0
    return ada_string_create(nullptr, 0);
18244
0
  }
18245
5.19k
  std::string_view out = r->get_search();
18246
5.19k
  return ada_string_create(out.data(), out.length());
18247
5.19k
}
18248
18249
5.19k
ada_string ada_get_protocol(ada_url result) noexcept {
18250
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18251
5.19k
  if (!r) {
18252
0
    return ada_string_create(nullptr, 0);
18253
0
  }
18254
5.19k
  std::string_view out = r->get_protocol();
18255
5.19k
  return ada_string_create(out.data(), out.length());
18256
5.19k
}
18257
18258
4.67k
uint8_t ada_get_host_type(ada_url result) noexcept {
18259
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18260
4.67k
  if (!r) {
18261
0
    return 0;
18262
0
  }
18263
4.67k
  return r->host_type;
18264
4.67k
}
18265
18266
4.67k
uint8_t ada_get_scheme_type(ada_url result) noexcept {
18267
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18268
4.67k
  if (!r) {
18269
0
    return 0;
18270
0
  }
18271
4.67k
  return r->type;
18272
4.67k
}
18273
18274
4.67k
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
18275
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18276
4.67k
  if (!r) {
18277
0
    return false;
18278
0
  }
18279
4.67k
  return r->set_href(std::string_view(input, length));
18280
4.67k
}
18281
18282
4.67k
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
18283
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18284
4.67k
  if (!r) {
18285
0
    return false;
18286
0
  }
18287
4.67k
  return r->set_host(std::string_view(input, length));
18288
4.67k
}
18289
18290
bool ada_set_hostname(ada_url result, const char* input,
18291
4.67k
                      size_t length) noexcept {
18292
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18293
4.67k
  if (!r) {
18294
0
    return false;
18295
0
  }
18296
4.67k
  return r->set_hostname(std::string_view(input, length));
18297
4.67k
}
18298
18299
bool ada_set_protocol(ada_url result, const char* input,
18300
4.67k
                      size_t length) noexcept {
18301
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18302
4.67k
  if (!r) {
18303
0
    return false;
18304
0
  }
18305
4.67k
  return r->set_protocol(std::string_view(input, length));
18306
4.67k
}
18307
18308
bool ada_set_username(ada_url result, const char* input,
18309
4.67k
                      size_t length) noexcept {
18310
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18311
4.67k
  if (!r) {
18312
0
    return false;
18313
0
  }
18314
4.67k
  return r->set_username(std::string_view(input, length));
18315
4.67k
}
18316
18317
bool ada_set_password(ada_url result, const char* input,
18318
4.67k
                      size_t length) noexcept {
18319
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18320
4.67k
  if (!r) {
18321
0
    return false;
18322
0
  }
18323
4.67k
  return r->set_password(std::string_view(input, length));
18324
4.67k
}
18325
18326
4.67k
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
18327
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18328
4.67k
  if (!r) {
18329
0
    return false;
18330
0
  }
18331
4.67k
  return r->set_port(std::string_view(input, length));
18332
4.67k
}
18333
18334
bool ada_set_pathname(ada_url result, const char* input,
18335
4.67k
                      size_t length) noexcept {
18336
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18337
4.67k
  if (!r) {
18338
0
    return false;
18339
0
  }
18340
4.67k
  return r->set_pathname(std::string_view(input, length));
18341
4.67k
}
18342
18343
/**
18344
 * Update the search/query of the URL.
18345
 *
18346
 * If a URL has `?` as the search value, passing empty string to this function
18347
 * does not remove the attribute. If you need to remove it, please use
18348
 * `ada_clear_search` method.
18349
 */
18350
4.67k
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
18351
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18352
4.67k
  if (r) {
18353
4.67k
    r->set_search(std::string_view(input, length));
18354
4.67k
  }
18355
4.67k
}
18356
18357
/**
18358
 * Update the hash/fragment of the URL.
18359
 *
18360
 * If a URL has `#` as the hash value, passing empty string to this function
18361
 * does not remove the attribute. If you need to remove it, please use
18362
 * `ada_clear_hash` method.
18363
 */
18364
4.67k
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
18365
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18366
4.67k
  if (r) {
18367
4.67k
    r->set_hash(std::string_view(input, length));
18368
4.67k
  }
18369
4.67k
}
18370
18371
4.67k
void ada_clear_port(ada_url result) noexcept {
18372
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18373
4.67k
  if (r) {
18374
4.67k
    r->clear_port();
18375
4.67k
  }
18376
4.67k
}
18377
18378
/**
18379
 * Removes the hash of the URL.
18380
 *
18381
 * Despite `ada_set_hash` method, this function allows the complete
18382
 * removal of the hash attribute, even if it has a value of `#`.
18383
 */
18384
4.67k
void ada_clear_hash(ada_url result) noexcept {
18385
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18386
4.67k
  if (r) {
18387
4.67k
    r->clear_hash();
18388
4.67k
  }
18389
4.67k
}
18390
18391
/**
18392
 * Removes the search of the URL.
18393
 *
18394
 * Despite `ada_set_search` method, this function allows the complete
18395
 * removal of the search attribute, even if it has a value of `?`.
18396
 */
18397
4.67k
void ada_clear_search(ada_url result) noexcept {
18398
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18399
4.67k
  if (r) {
18400
4.67k
    r->clear_search();
18401
4.67k
  }
18402
4.67k
}
18403
18404
5.19k
bool ada_has_credentials(ada_url result) noexcept {
18405
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18406
5.19k
  if (!r) {
18407
0
    return false;
18408
0
  }
18409
5.19k
  return r->has_credentials();
18410
5.19k
}
18411
18412
4.67k
bool ada_has_empty_hostname(ada_url result) noexcept {
18413
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18414
4.67k
  if (!r) {
18415
0
    return false;
18416
0
  }
18417
4.67k
  return r->has_empty_hostname();
18418
4.67k
}
18419
18420
4.67k
bool ada_has_hostname(ada_url result) noexcept {
18421
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18422
4.67k
  if (!r) {
18423
0
    return false;
18424
0
  }
18425
4.67k
  return r->has_hostname();
18426
4.67k
}
18427
18428
4.67k
bool ada_has_non_empty_username(ada_url result) noexcept {
18429
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18430
4.67k
  if (!r) {
18431
0
    return false;
18432
0
  }
18433
4.67k
  return r->has_non_empty_username();
18434
4.67k
}
18435
18436
4.67k
bool ada_has_non_empty_password(ada_url result) noexcept {
18437
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18438
4.67k
  if (!r) {
18439
0
    return false;
18440
0
  }
18441
4.67k
  return r->has_non_empty_password();
18442
4.67k
}
18443
18444
5.19k
bool ada_has_port(ada_url result) noexcept {
18445
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18446
5.19k
  if (!r) {
18447
0
    return false;
18448
0
  }
18449
5.19k
  return r->has_port();
18450
5.19k
}
18451
18452
4.67k
bool ada_has_password(ada_url result) noexcept {
18453
4.67k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18454
4.67k
  if (!r) {
18455
0
    return false;
18456
0
  }
18457
4.67k
  return r->has_password();
18458
4.67k
}
18459
18460
5.19k
bool ada_has_hash(ada_url result) noexcept {
18461
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18462
5.19k
  if (!r) {
18463
0
    return false;
18464
0
  }
18465
5.19k
  return r->has_hash();
18466
5.19k
}
18467
18468
5.19k
bool ada_has_search(ada_url result) noexcept {
18469
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18470
5.19k
  if (!r) {
18471
0
    return false;
18472
0
  }
18473
5.19k
  return r->has_search();
18474
5.19k
}
18475
18476
// returns a pointer to the internal url_aggregator::url_components
18477
5.19k
const ada_url_components* ada_get_components(ada_url result) noexcept {
18478
5.19k
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
18479
5.19k
  ada::result<ada::url_aggregator>& r = get_instance(result);
18480
5.19k
  if (!r) {
18481
0
    return nullptr;
18482
0
  }
18483
5.19k
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
18484
5.19k
}
18485
18486
8.50k
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
18487
8.50k
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
18488
8.50k
  ada_owned_string owned{};
18489
8.50k
  owned.length = out.length();
18490
8.50k
  owned.data = new char[owned.length];
18491
8.50k
  memcpy((void*)owned.data, out.data(), owned.length);
18492
8.50k
  return owned;
18493
8.50k
}
18494
18495
8.50k
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
18496
8.50k
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
18497
8.50k
  ada_owned_string owned{};
18498
8.50k
  owned.length = out.size();
18499
8.50k
  owned.data = new char[owned.length];
18500
8.50k
  memcpy((void*)owned.data, out.data(), owned.length);
18501
8.50k
  return owned;
18502
8.50k
}
18503
18504
ada_url_search_params ada_parse_search_params(const char* input,
18505
8.50k
                                              size_t length) {
18506
8.50k
  return new ada::result<ada::url_search_params>(
18507
8.50k
      ada::url_search_params(std::string_view(input, length)));
18508
8.50k
}
18509
18510
8.50k
void ada_free_search_params(ada_url_search_params result) {
18511
8.50k
  auto* r = (ada::result<ada::url_search_params>*)result;
18512
8.50k
  delete r;
18513
8.50k
}
18514
18515
8.50k
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
18516
8.50k
  ada::result<ada::url_search_params>& r =
18517
8.50k
      *(ada::result<ada::url_search_params>*)result;
18518
8.50k
  if (!r) return ada_owned_string{nullptr, 0};
18519
8.50k
  std::string out = r->to_string();
18520
8.50k
  ada_owned_string owned{};
18521
8.50k
  owned.length = out.size();
18522
8.50k
  owned.data = new char[owned.length];
18523
8.50k
  memcpy((void*)owned.data, out.data(), owned.length);
18524
8.50k
  return owned;
18525
8.50k
}
18526
18527
17.0k
size_t ada_search_params_size(ada_url_search_params result) {
18528
17.0k
  ada::result<ada::url_search_params>& r =
18529
17.0k
      *(ada::result<ada::url_search_params>*)result;
18530
17.0k
  if (!r) {
18531
0
    return 0;
18532
0
  }
18533
17.0k
  return r->size();
18534
17.0k
}
18535
18536
8.50k
void ada_search_params_sort(ada_url_search_params result) {
18537
8.50k
  ada::result<ada::url_search_params>& r =
18538
8.50k
      *(ada::result<ada::url_search_params>*)result;
18539
8.50k
  if (r) {
18540
8.50k
    r->sort();
18541
8.50k
  }
18542
8.50k
}
18543
18544
void ada_search_params_reset(ada_url_search_params result, const char* input,
18545
8.50k
                             size_t length) {
18546
8.50k
  ada::result<ada::url_search_params>& r =
18547
8.50k
      *(ada::result<ada::url_search_params>*)result;
18548
8.50k
  if (r) {
18549
8.50k
    r->reset(std::string_view(input, length));
18550
8.50k
  }
18551
8.50k
}
18552
18553
void ada_search_params_append(ada_url_search_params result, const char* key,
18554
                              size_t key_length, const char* value,
18555
8.50k
                              size_t value_length) {
18556
8.50k
  ada::result<ada::url_search_params>& r =
18557
8.50k
      *(ada::result<ada::url_search_params>*)result;
18558
8.50k
  if (r) {
18559
8.50k
    r->append(std::string_view(key, key_length),
18560
8.50k
              std::string_view(value, value_length));
18561
8.50k
  }
18562
8.50k
}
18563
18564
void ada_search_params_set(ada_url_search_params result, const char* key,
18565
                           size_t key_length, const char* value,
18566
8.50k
                           size_t value_length) {
18567
8.50k
  ada::result<ada::url_search_params>& r =
18568
8.50k
      *(ada::result<ada::url_search_params>*)result;
18569
8.50k
  if (r) {
18570
8.50k
    r->set(std::string_view(key, key_length),
18571
8.50k
           std::string_view(value, value_length));
18572
8.50k
  }
18573
8.50k
}
18574
18575
void ada_search_params_remove(ada_url_search_params result, const char* key,
18576
8.50k
                              size_t key_length) {
18577
8.50k
  ada::result<ada::url_search_params>& r =
18578
8.50k
      *(ada::result<ada::url_search_params>*)result;
18579
8.50k
  if (r) {
18580
8.50k
    r->remove(std::string_view(key, key_length));
18581
8.50k
  }
18582
8.50k
}
18583
18584
void ada_search_params_remove_value(ada_url_search_params result,
18585
                                    const char* key, size_t key_length,
18586
8.50k
                                    const char* value, size_t value_length) {
18587
8.50k
  ada::result<ada::url_search_params>& r =
18588
8.50k
      *(ada::result<ada::url_search_params>*)result;
18589
8.50k
  if (r) {
18590
8.50k
    r->remove(std::string_view(key, key_length),
18591
8.50k
              std::string_view(value, value_length));
18592
8.50k
  }
18593
8.50k
}
18594
18595
bool ada_search_params_has(ada_url_search_params result, const char* key,
18596
8.50k
                           size_t key_length) {
18597
8.50k
  ada::result<ada::url_search_params>& r =
18598
8.50k
      *(ada::result<ada::url_search_params>*)result;
18599
8.50k
  if (!r) {
18600
0
    return false;
18601
0
  }
18602
8.50k
  return r->has(std::string_view(key, key_length));
18603
8.50k
}
18604
18605
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
18606
                                 size_t key_length, const char* value,
18607
8.50k
                                 size_t value_length) {
18608
8.50k
  ada::result<ada::url_search_params>& r =
18609
8.50k
      *(ada::result<ada::url_search_params>*)result;
18610
8.50k
  if (!r) {
18611
0
    return false;
18612
0
  }
18613
8.50k
  return r->has(std::string_view(key, key_length),
18614
8.50k
                std::string_view(value, value_length));
18615
8.50k
}
18616
18617
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
18618
8.50k
                                 size_t key_length) {
18619
8.50k
  ada::result<ada::url_search_params>& r =
18620
8.50k
      *(ada::result<ada::url_search_params>*)result;
18621
8.50k
  if (!r) {
18622
0
    return ada_string_create(nullptr, 0);
18623
0
  }
18624
8.50k
  auto found = r->get(std::string_view(key, key_length));
18625
8.50k
  if (!found.has_value()) {
18626
0
    return ada_string_create(nullptr, 0);
18627
0
  }
18628
8.50k
  return ada_string_create(found->data(), found->length());
18629
8.50k
}
18630
18631
ada_strings ada_search_params_get_all(ada_url_search_params result,
18632
8.50k
                                      const char* key, size_t key_length) {
18633
8.50k
  ada::result<ada::url_search_params>& r =
18634
8.50k
      *(ada::result<ada::url_search_params>*)result;
18635
8.50k
  if (!r) {
18636
0
    return new ada::result<std::vector<std::string>>(
18637
0
        std::vector<std::string>());
18638
0
  }
18639
8.50k
  return new ada::result<std::vector<std::string>>(
18640
8.50k
      r->get_all(std::string_view(key, key_length)));
18641
8.50k
}
18642
18643
ada_url_search_params_keys_iter ada_search_params_get_keys(
18644
8.50k
    ada_url_search_params result) {
18645
8.50k
  ada::result<ada::url_search_params>& r =
18646
8.50k
      *(ada::result<ada::url_search_params>*)result;
18647
8.50k
  if (!r) {
18648
0
    return new ada::result<ada::url_search_params_keys_iter>(
18649
0
        ada::url_search_params_keys_iter());
18650
0
  }
18651
8.50k
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
18652
8.50k
}
18653
18654
ada_url_search_params_values_iter ada_search_params_get_values(
18655
8.50k
    ada_url_search_params result) {
18656
8.50k
  ada::result<ada::url_search_params>& r =
18657
8.50k
      *(ada::result<ada::url_search_params>*)result;
18658
8.50k
  if (!r) {
18659
0
    return new ada::result<ada::url_search_params_values_iter>(
18660
0
        ada::url_search_params_values_iter());
18661
0
  }
18662
8.50k
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
18663
8.50k
}
18664
18665
ada_url_search_params_entries_iter ada_search_params_get_entries(
18666
8.50k
    ada_url_search_params result) {
18667
8.50k
  ada::result<ada::url_search_params>& r =
18668
8.50k
      *(ada::result<ada::url_search_params>*)result;
18669
8.50k
  if (!r) {
18670
0
    return new ada::result<ada::url_search_params_entries_iter>(
18671
0
        ada::url_search_params_entries_iter());
18672
0
  }
18673
8.50k
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
18674
8.50k
}
18675
18676
8.50k
void ada_free_strings(ada_strings result) {
18677
8.50k
  auto* r = (ada::result<std::vector<std::string>>*)result;
18678
8.50k
  delete r;
18679
8.50k
}
18680
18681
8.50k
size_t ada_strings_size(ada_strings result) {
18682
8.50k
  auto* r = (ada::result<std::vector<std::string>>*)result;
18683
8.50k
  if (!r) {
18684
0
    return 0;
18685
0
  }
18686
8.50k
  return (*r)->size();
18687
8.50k
}
18688
18689
8.50k
ada_string ada_strings_get(ada_strings result, size_t index) {
18690
8.50k
  auto* r = (ada::result<std::vector<std::string>>*)result;
18691
8.50k
  if (!r) {
18692
0
    return ada_string_create(nullptr, 0);
18693
0
  }
18694
8.50k
  std::string_view view = (*r)->at(index);
18695
8.50k
  return ada_string_create(view.data(), view.length());
18696
8.50k
}
18697
18698
8.50k
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
18699
8.50k
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18700
8.50k
  delete r;
18701
8.50k
}
18702
18703
ada_string ada_search_params_keys_iter_next(
18704
9.07k
    ada_url_search_params_keys_iter result) {
18705
9.07k
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18706
9.07k
  if (!r) {
18707
0
    return ada_string_create(nullptr, 0);
18708
0
  }
18709
9.07k
  auto next = (*r)->next();
18710
9.07k
  if (!next.has_value()) {
18711
0
    return ada_string_create(nullptr, 0);
18712
0
  }
18713
9.07k
  return ada_string_create(next->data(), next->length());
18714
9.07k
}
18715
18716
bool ada_search_params_keys_iter_has_next(
18717
17.5k
    ada_url_search_params_keys_iter result) {
18718
17.5k
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
18719
17.5k
  if (!r) {
18720
0
    return false;
18721
0
  }
18722
17.5k
  return (*r)->has_next();
18723
17.5k
}
18724
18725
void ada_free_search_params_values_iter(
18726
8.50k
    ada_url_search_params_values_iter result) {
18727
8.50k
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18728
8.50k
  delete r;
18729
8.50k
}
18730
18731
ada_string ada_search_params_values_iter_next(
18732
9.07k
    ada_url_search_params_values_iter result) {
18733
9.07k
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18734
9.07k
  if (!r) {
18735
0
    return ada_string_create(nullptr, 0);
18736
0
  }
18737
9.07k
  auto next = (*r)->next();
18738
9.07k
  if (!next.has_value()) {
18739
0
    return ada_string_create(nullptr, 0);
18740
0
  }
18741
9.07k
  return ada_string_create(next->data(), next->length());
18742
9.07k
}
18743
18744
bool ada_search_params_values_iter_has_next(
18745
17.5k
    ada_url_search_params_values_iter result) {
18746
17.5k
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
18747
17.5k
  if (!r) {
18748
0
    return false;
18749
0
  }
18750
17.5k
  return (*r)->has_next();
18751
17.5k
}
18752
18753
void ada_free_search_params_entries_iter(
18754
8.50k
    ada_url_search_params_entries_iter result) {
18755
8.50k
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18756
8.50k
  delete r;
18757
8.50k
}
18758
18759
ada_string_pair ada_search_params_entries_iter_next(
18760
9.07k
    ada_url_search_params_entries_iter result) {
18761
9.07k
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18762
9.07k
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18763
9.07k
  auto next = (*r)->next();
18764
9.07k
  if (!next.has_value()) {
18765
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
18766
0
  }
18767
9.07k
  return ada_string_pair{
18768
9.07k
      ada_string_create(next->first.data(), next->first.length()),
18769
9.07k
      ada_string_create(next->second.data(), next->second.length())};
18770
9.07k
}
18771
18772
bool ada_search_params_entries_iter_has_next(
18773
17.5k
    ada_url_search_params_entries_iter result) {
18774
17.5k
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
18775
17.5k
  if (!r) {
18776
0
    return false;
18777
0
  }
18778
17.5k
  return (*r)->has_next();
18779
17.5k
}
18780
18781
0
void ada_set_max_input_length(uint32_t length) noexcept {
18782
0
  ada::set_max_input_length(length);
18783
0
}
18784
18785
0
uint32_t ada_get_max_input_length() noexcept {
18786
0
  return ada::get_max_input_length();
18787
0
}
18788
18789
typedef struct {
18790
  int major;
18791
  int minor;
18792
  int revision;
18793
} ada_version_components;
18794
18795
8.50k
const char* ada_get_version() { return ADA_VERSION; }
18796
18797
8.50k
ada_version_components ada_get_version_components() {
18798
8.50k
  return ada_version_components{
18799
8.50k
      .major = ada::ADA_VERSION_MAJOR,
18800
8.50k
      .minor = ada::ADA_VERSION_MINOR,
18801
8.50k
      .revision = ada::ADA_VERSION_REVISION,
18802
8.50k
  };
18803
8.50k
}
18804
18805
}  // extern "C"
18806
// NOLINTEND(bugprone-exception-escape,
18807
// bugprone-suspicious-stringview-data-usage)
18808
/* end file src/ada_c.cpp */
18809
/* end file src/ada.cpp */