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
10.7k
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
10.7k
  if (view.ends_with('.')) {
21
876
    view.remove_suffix(1);
22
876
    if (view.empty()) {
23
174
      return false;
24
174
    }
25
876
  }
26
10.6k
  char last_char = view.back();
27
10.6k
  bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
28
8.29k
                       (last_char >= 'a' && last_char <= 'f') ||
29
6.87k
                       last_char == 'x';
30
10.6k
  if (!possible_ipv4) {
31
6.48k
    return false;
32
6.48k
  }
33
  // From the last character, find the last dot.
34
4.12k
  size_t last_dot = view.rfind('.');
35
4.12k
  if (last_dot != std::string_view::npos) {
36
    // We have at least one dot.
37
530
    view.remove_prefix(last_dot + 1);
38
530
  }
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
4.12k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
43
1.95k
    return true;
44
1.95k
  }
45
  // It could be hex (0x), but not if there is a single character.
46
2.17k
  if (view.size() == 1) {
47
339
    return false;
48
339
  }
49
  // It must start with 0x.
50
1.83k
  if (!view.starts_with("0x")) {
51
1.07k
    return false;
52
1.07k
  }
53
  // We must allow "0x".
54
763
  if (view.size() == 2) {
55
129
    return true;
56
129
  }
57
  // We have 0x followed by some characters, we need to check that they are
58
  // hexadecimals.
59
634
  view.remove_prefix(2);
60
634
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
61
763
}
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
10.5k
    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
10.5k
  size_t i = 0;
94
10.5k
  uint8_t accumulator{};
95
102k
  for (; i + 7 < input.size(); i += 8) {
96
92.4k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
97
92.4k
                           path_signature_table[uint8_t(input[i + 1])] |
98
92.4k
                           path_signature_table[uint8_t(input[i + 2])] |
99
92.4k
                           path_signature_table[uint8_t(input[i + 3])] |
100
92.4k
                           path_signature_table[uint8_t(input[i + 4])] |
101
92.4k
                           path_signature_table[uint8_t(input[i + 5])] |
102
92.4k
                           path_signature_table[uint8_t(input[i + 6])] |
103
92.4k
                           path_signature_table[uint8_t(input[i + 7])]);
104
92.4k
  }
105
45.2k
  for (; i < input.size(); i++) {
106
34.7k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
107
34.7k
  }
108
10.5k
  return accumulator;
109
10.5k
}
110
111
ada_really_inline constexpr bool verify_dns_length(
112
0
    std::string_view input) noexcept {
113
0
  if (input.empty()) return false;
114
0
  if (input.back() == '.') {
115
0
    if (input.size() > 254) return false;
116
0
  } else if (input.size() > 253)
117
0
    return false;
118
119
0
  size_t start = 0;
120
0
  while (start < input.size()) {
121
0
    auto dot_location = input.find('.', start);
122
    // If not found, it's likely the end of the domain
123
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
124
125
0
    auto label_size = dot_location - start;
126
0
    if (label_size > 63 || label_size == 0) return false;
127
128
0
    start = dot_location + 1;
129
0
  }
130
131
0
  return true;
132
0
}
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
6.16k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
152
6.16k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
153
6.16k
  size_t pos = 0;
154
6.16k
  const char32_t* start{utf32_output};
155
161k
  while (pos < len) {
156
    // try to convert the next block of 16 ASCII bytes
157
159k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
158
                            // bytes, check that they are ascii
159
133k
      uint64_t v1;
160
133k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
161
133k
      uint64_t v2;
162
133k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
163
133k
      uint64_t v{v1 | v2};
164
133k
      if ((v & 0x8080808080808080) == 0) {
165
2.24k
        size_t final_pos = pos + 16;
166
38.1k
        while (pos < final_pos) {
167
35.9k
          *utf32_output++ = char32_t(buf[pos]);
168
35.9k
          pos++;
169
35.9k
        }
170
2.24k
        continue;
171
2.24k
      }
172
133k
    }
173
157k
    uint8_t leading_byte = data[pos];  // leading byte
174
157k
    if (leading_byte < 0b10000000) {
175
      // converting one ASCII byte !!!
176
79.2k
      *utf32_output++ = char32_t(leading_byte);
177
79.2k
      pos++;
178
79.2k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
179
      // We have a two-byte UTF-8
180
4.55k
      if (pos + 1 >= len) {
181
370
        return 0;
182
370
      }  // minimal bound checking
183
4.18k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
184
217
        return 0;
185
217
      }
186
      // range check
187
3.96k
      uint32_t code_point =
188
3.96k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
189
3.96k
      if (code_point < 0x80 || 0x7ff < code_point) {
190
6
        return 0;
191
6
      }
192
3.95k
      *utf32_output++ = char32_t(code_point);
193
3.95k
      pos += 2;
194
73.2k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
195
      // We have a three-byte UTF-8
196
70.8k
      if (pos + 2 >= len) {
197
1.56k
        return 0;
198
1.56k
      }  // minimal bound checking
199
200
69.3k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
201
137
        return 0;
202
137
      }
203
69.1k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
204
39
        return 0;
205
39
      }
206
      // range check
207
69.1k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
208
69.1k
                            (data[pos + 1] & 0b00111111) << 6 |
209
69.1k
                            (data[pos + 2] & 0b00111111);
210
69.1k
      if (code_point < 0x800 || 0xffff < code_point ||
211
69.1k
          (0xd7ff < code_point && code_point < 0xe000)) {
212
4
        return 0;
213
4
      }
214
69.1k
      *utf32_output++ = char32_t(code_point);
215
69.1k
      pos += 3;
216
69.1k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
217
      // we have a 4-byte UTF-8 word.
218
984
      if (pos + 3 >= len) {
219
196
        return 0;
220
196
      }  // minimal bound checking
221
788
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
222
89
        return 0;
223
89
      }
224
699
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
225
11
        return 0;
226
11
      }
227
688
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
228
2
        return 0;
229
2
      }
230
231
      // range check
232
686
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
233
686
                            (data[pos + 1] & 0b00111111) << 12 |
234
686
                            (data[pos + 2] & 0b00111111) << 6 |
235
686
                            (data[pos + 3] & 0b00111111);
236
686
      if (code_point <= 0xffff || 0x10ffff < code_point) {
237
5
        return 0;
238
5
      }
239
681
      *utf32_output++ = char32_t(code_point);
240
681
      pos += 4;
241
1.34k
    } else {
242
1.34k
      return 0;
243
1.34k
    }
244
157k
  }
245
2.17k
  return utf32_output - start;
246
6.16k
}
247
248
512
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
249
  // We are not BOM aware.
250
512
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
251
512
  size_t counter{0};
252
1.74k
  for (size_t i = 0; i != len; ++i) {
253
1.22k
    ++counter;                                      // ASCII
254
1.22k
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
255
1.22k
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
256
1.22k
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
257
1.22k
  }
258
512
  return counter;
259
512
}
260
261
6.16k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
262
6.16k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
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
  });
268
6.16k
}
269
270
512
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
271
512
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
272
512
  size_t pos = 0;
273
512
  const char* start{utf8_output};
274
1.71k
  while (pos < len) {
275
    // try to convert the next block of 2 ASCII characters
276
1.20k
    if (pos + 2 <= len) {  // if it is safe to read 8 more
277
                           // bytes, check that they are ascii
278
690
      uint64_t v;
279
690
      std::memcpy(&v, data + pos, sizeof(uint64_t));
280
690
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
281
28
        *utf8_output++ = char(buf[pos]);
282
28
        *utf8_output++ = char(buf[pos + 1]);
283
28
        pos += 2;
284
28
        continue;
285
28
      }
286
690
    }
287
1.17k
    uint32_t word = data[pos];
288
1.17k
    if ((word & 0xFFFFFF80) == 0) {
289
      // will generate one UTF-8 bytes
290
12
      *utf8_output++ = char(word);
291
12
      pos++;
292
1.16k
    } else if ((word & 0xFFFFF800) == 0) {
293
      // will generate two UTF-8 bytes
294
      // we have 0b110XXXXX 0b10XXXXXX
295
353
      *utf8_output++ = char((word >> 6) | 0b11000000);
296
353
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
297
353
      pos++;
298
807
    } else if ((word & 0xFFFF0000) == 0) {
299
      // will generate three UTF-8 bytes
300
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
301
807
      if (word >= 0xD800 && word <= 0xDFFF) {
302
0
        return 0;
303
0
      }
304
807
      *utf8_output++ = char((word >> 12) | 0b11100000);
305
807
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
306
807
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
307
807
      pos++;
308
807
    } else {
309
      // will generate four UTF-8 bytes
310
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
311
      // 0b10XXXXXX
312
0
      if (word > 0x10FFFF) {
313
0
        return 0;
314
0
      }
315
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
316
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
317
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
318
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
319
0
      pos++;
320
0
    }
321
1.17k
  }
322
512
  return utf8_output - start;
323
512
}
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
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
}
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
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
}
2834
2835
// --- ASCII fast path
2836
// ----------------------------------------------------------
2837
20.7k
void ascii_map(char* input, size_t length) {
2838
62.1k
  auto broadcast = [](uint8_t v) -> uint64_t {
2839
62.1k
    return 0x101010101010101ull * v;
2840
62.1k
  };
2841
20.7k
  uint64_t broadcast_80 = broadcast(0x80);
2842
20.7k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
2843
20.7k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
2844
20.7k
  size_t i = 0;
2845
2846
52.0k
  for (; i + 7 < length; i += 8) {
2847
31.3k
    uint64_t word{};
2848
31.3k
    std::memcpy(&word, input + i, sizeof(word));
2849
31.3k
    word ^=
2850
31.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2851
31.3k
    std::memcpy(input + i, &word, sizeof(word));
2852
31.3k
  }
2853
20.7k
  if (i < length) {
2854
19.2k
    uint64_t word{};
2855
19.2k
    std::memcpy(&word, input + i, length - i);
2856
19.2k
    word ^=
2857
19.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
2858
19.2k
    std::memcpy(input + i, &word, length - i);
2859
19.2k
  }
2860
20.7k
}
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
11.8k
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
11.8k
  out.clear();
2880
11.8k
  out.reserve(input.size());
2881
169k
  for (char32_t x : input) {
2882
169k
    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
2883
169k
    if (status == IDNA_DISALLOWED) {
2884
36
      return false;
2885
36
    }
2886
169k
    if (status == IDNA_VALID) {
2887
120k
      out.push_back(x);
2888
120k
      continue;
2889
120k
    }
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
48.5k
    const uint8_t* ptr = idna_utf8_mappings + status;
2895
402k
    while (*ptr != 0) {
2896
353k
      out.push_back(utf8_next(ptr));
2897
353k
    }
2898
48.5k
  }
2899
11.7k
  return true;
2900
11.8k
}
2901
2902
0
std::u32string map(std::u32string_view input) {
2903
0
  std::u32string answer;
2904
0
  if (!map(input, answer)) {
2905
0
    return {};
2906
0
  }
2907
0
  return answer;
2908
0
}
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
11.7k
    const std::u32string_view input) noexcept {
7829
11.7k
  bool decomposition_needed{false};
7830
11.7k
  size_t additional_elements{0};
7831
362k
  for (char32_t current_character : input) {
7832
362k
    size_t decomposition_length{0};
7833
7834
362k
    if (current_character >= hangul_sbase &&
7835
3.90k
        current_character < hangul_sbase + hangul_scount) {
7836
3.13k
      decomposition_length = 2;
7837
3.13k
      if ((current_character - hangul_sbase) % hangul_tcount) {
7838
2.57k
        decomposition_length = 3;
7839
2.57k
      }
7840
359k
    } else if (current_character < 0x110000) {
7841
359k
      const uint8_t di = decomposition_index[current_character >> 8];
7842
359k
      const uint16_t* const decomposition =
7843
359k
          decomposition_block[di] + (current_character % 256);
7844
359k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
7845
359k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
7846
0
        decomposition_length = 0;
7847
0
      }
7848
359k
    }
7849
362k
    if (decomposition_length != 0) {
7850
17.6k
      decomposition_needed = true;
7851
17.6k
      additional_elements += decomposition_length - 1;
7852
17.6k
    }
7853
362k
  }
7854
11.7k
  return {decomposition_needed, additional_elements};
7855
11.7k
}
7856
7857
2.74k
void decompose(std::u32string& input, size_t additional_elements) {
7858
2.74k
  input.resize(input.size() + additional_elements);
7859
2.74k
  for (size_t descending_idx = input.size(),
7860
2.74k
              input_count = descending_idx - additional_elements;
7861
76.1k
       input_count--;) {
7862
73.4k
    if (input[input_count] >= hangul_sbase &&
7863
3.40k
        input[input_count] < hangul_sbase + hangul_scount) {
7864
      // Hangul decomposition.
7865
3.13k
      char32_t s_index = input[input_count] - hangul_sbase;
7866
3.13k
      if (s_index % hangul_tcount != 0) {
7867
2.57k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
7868
2.57k
      }
7869
3.13k
      input[--descending_idx] =
7870
3.13k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
7871
3.13k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
7872
70.2k
    } else if (input[input_count] < 0x110000) {
7873
      // Check decomposition_data.
7874
70.2k
      const uint16_t* decomposition =
7875
70.2k
          decomposition_block[decomposition_index[input[input_count] >> 8]] +
7876
70.2k
          (input[input_count] % 256);
7877
70.2k
      uint16_t decomposition_length =
7878
70.2k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
7879
70.2k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
7880
0
        decomposition_length = 0;
7881
0
      }
7882
70.2k
      if (decomposition_length > 0) {
7883
        // Non-recursive decomposition.
7884
55.5k
        while (decomposition_length-- > 0) {
7885
40.9k
          input[--descending_idx] = decomposition_data[(decomposition[0] >> 2) +
7886
40.9k
                                                       decomposition_length];
7887
40.9k
        }
7888
55.7k
      } else {
7889
        // No decomposition.
7890
55.7k
        input[--descending_idx] = input[input_count];
7891
55.7k
      }
7892
70.2k
    } else {
7893
      // Non-Unicode character.
7894
0
      input[--descending_idx] = input[input_count];
7895
0
    }
7896
73.4k
  }
7897
2.74k
}
7898
7899
793k
uint8_t get_ccc(char32_t c) noexcept {
7900
793k
  return c < 0x110000 ? canonical_combining_class_block
7901
793k
                            [canonical_combining_class_index[c >> 8]][c % 256]
7902
793k
                      : 0;
7903
793k
}
7904
7905
11.7k
void sort_marks(std::u32string& input) {
7906
394k
  for (size_t idx = 1; idx < input.size(); idx++) {
7907
383k
    uint8_t ccc = get_ccc(input[idx]);
7908
383k
    if (ccc == 0) {
7909
353k
      continue;
7910
353k
    }  // Skip non-combining characters.
7911
30.0k
    auto current_character = input[idx];
7912
30.0k
    size_t back_idx = idx;
7913
36.1k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
7914
6.13k
      input[back_idx] = input[back_idx - 1];
7915
6.13k
      back_idx--;
7916
6.13k
    }
7917
30.0k
    input[back_idx] = current_character;
7918
30.0k
  }
7919
11.7k
}
7920
7921
11.7k
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
11.7k
  auto [decomposition_needed, additional_elements] =
7927
11.7k
      compute_decomposition_length(input);
7928
11.7k
  if (decomposition_needed) {
7929
2.74k
    decompose(input, additional_elements);
7930
2.74k
  }
7931
11.7k
  sort_marks(input);
7932
11.7k
}
7933
7934
11.7k
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
11.7k
  size_t input_count{0};
7940
11.7k
  size_t composition_count{0};
7941
370k
  for (; input_count < input.size(); input_count++, composition_count++) {
7942
359k
    input[composition_count] = input[input_count];
7943
359k
    if (input[input_count] >= hangul_lbase &&
7944
137k
        input[input_count] < hangul_lbase + hangul_lcount) {
7945
4.06k
      if (input_count + 1 < input.size() &&
7946
3.80k
          input[input_count + 1] >= hangul_vbase &&
7947
3.23k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
7948
3.13k
        input[composition_count] =
7949
3.13k
            hangul_sbase +
7950
3.13k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
7951
3.13k
             input[input_count + 1] - hangul_vbase) *
7952
3.13k
                hangul_tcount;
7953
3.13k
        input_count++;
7954
3.13k
        if (input_count + 1 < input.size() &&
7955
2.93k
            input[input_count + 1] > hangul_tbase &&
7956
2.58k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
7957
2.57k
          input[composition_count] += input[++input_count] - hangul_tbase;
7958
2.57k
        }
7959
3.13k
      }
7960
355k
    } else if (input[input_count] >= hangul_sbase &&
7961
624
               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
355k
    } else if (input[input_count] < 0x110000) {
7969
355k
      const uint16_t* composition =
7970
355k
          &composition_block[composition_index[input[input_count] >> 8]]
7971
355k
                            [input[input_count] % 256];
7972
355k
      size_t initial_composition_count = composition_count;
7973
385k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
7974
374k
           input_count++) {
7975
374k
        uint8_t ccc = get_ccc(input[input_count + 1]);
7976
7977
374k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
7978
          // Try finding a composition.
7979
74.1k
          int left = composition[0];
7980
74.1k
          int right = composition[1];
7981
175k
          while (left + 2 < right) {
7982
            // mean without overflow
7983
101k
            int middle = left + (((right - left) >> 1) & ~1);
7984
101k
            if (composition_data[middle] <= input[input_count + 1]) {
7985
29.1k
              left = middle;
7986
29.1k
            }
7987
101k
            if (composition_data[middle] >= input[input_count + 1]) {
7988
86.8k
              right = middle;
7989
86.8k
            }
7990
101k
          }
7991
74.1k
          if (composition_data[left] == input[input_count + 1]) {
7992
26.0k
            input[initial_composition_count] = composition_data[left + 1];
7993
26.0k
            composition =
7994
26.0k
                &composition_block
7995
26.0k
                    [composition_index[composition_data[left + 1] >> 8]]
7996
26.0k
                    [composition_data[left + 1] % 256];
7997
26.0k
            continue;
7998
26.0k
          }
7999
74.1k
        }
8000
8001
348k
        if (ccc == 0) {
8002
344k
          break;
8003
344k
        }  // Not a combining character.
8004
4.08k
        previous_ccc = ccc;
8005
4.08k
        input[++composition_count] = input[input_count + 1];
8006
4.08k
      }
8007
355k
    }
8008
359k
  }
8009
8010
11.7k
  if (composition_count < input_count) {
8011
2.74k
    input.resize(composition_count);
8012
2.74k
  }
8013
11.7k
}
8014
8015
11.7k
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
11.7k
  decompose_nfc(input);
8021
11.7k
  compose(input);
8022
11.7k
}
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
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
}
8045
8046
437k
static constexpr char digit_to_char(int32_t digit) {
8047
437k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
8048
437k
}
8049
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
}
8064
8065
10.5k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
8066
10.5k
  int32_t written_out{0};
8067
10.5k
  out.reserve(out.size() + input.size());
8068
10.5k
  uint32_t n = initial_n;
8069
10.5k
  int32_t i = 0;
8070
10.5k
  int32_t bias = initial_bias;
8071
  // grab ascii content
8072
10.5k
  size_t end_of_ascii = input.find_last_of('-');
8073
10.5k
  if (end_of_ascii != std::string_view::npos) {
8074
5.72k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8075
5.72k
      if (c >= 0x80) {
8076
0
        return false;
8077
0
      }
8078
5.72k
      out.push_back(c);
8079
5.72k
      written_out++;
8080
5.72k
    }
8081
708
    input.remove_prefix(end_of_ascii + 1);
8082
708
  }
8083
70.0k
  while (!input.empty()) {
8084
60.1k
    int32_t oldi = i;
8085
60.1k
    int32_t w = 1;
8086
117k
    for (int32_t k = base;; k += base) {
8087
117k
      if (input.empty()) {
8088
268
        return false;
8089
268
      }
8090
117k
      uint8_t code_point = input.front();
8091
117k
      input.remove_prefix(1);
8092
117k
      int32_t digit = char_to_digit_value(code_point);
8093
117k
      if (digit < 0) {
8094
491
        return false;
8095
491
      }
8096
117k
      if (digit > (0x7fffffff - i) / w) {
8097
10
        return false;
8098
10
      }
8099
117k
      i = i + digit * w;
8100
117k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8101
117k
      if (digit < t) {
8102
59.4k
        break;
8103
59.4k
      }
8104
57.7k
      if (w > 0x7fffffff / (base - t)) {
8105
0
        return false;
8106
0
      }
8107
57.7k
      w = w * (base - t);
8108
57.7k
    }
8109
59.4k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
8110
59.4k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
8111
0
      return false;
8112
0
    }
8113
59.4k
    n = n + i / (written_out + 1);
8114
59.4k
    i = i % (written_out + 1);
8115
59.4k
    if (n < 0x80) {
8116
0
      return false;
8117
0
    }
8118
59.4k
    out.insert(out.begin() + i, n);
8119
59.4k
    written_out++;
8120
59.4k
    ++i;
8121
59.4k
  }
8122
  // See https://github.com/whatwg/url/issues/803
8123
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
8124
9.82k
  if (out.size() >= 4 && out[0] == U'x' && out[1] == U'n' && out[2] == U'-' &&
8125
1
      out[3] == U'-') {
8126
0
    return false;
8127
0
  }
8128
9.82k
  return true;
8129
9.82k
}
8130
8131
0
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
0
  uint32_t first4[4]{};
8136
0
  size_t written_out{0};
8137
0
  uint32_t n = initial_n;
8138
0
  int32_t i = 0;
8139
0
  int32_t bias = initial_bias;
8140
  // grab ascii content
8141
0
  size_t end_of_ascii = input.find_last_of('-');
8142
0
  if (end_of_ascii != std::string_view::npos) {
8143
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
8144
0
      if (c >= 0x80) {
8145
0
        return false;
8146
0
      }
8147
0
      if (written_out < 4) {
8148
0
        first4[written_out] = c;
8149
0
      }
8150
0
      written_out++;
8151
0
    }
8152
0
    input.remove_prefix(end_of_ascii + 1);
8153
0
  }
8154
0
  while (!input.empty()) {
8155
0
    int32_t oldi = i;
8156
0
    int32_t w = 1;
8157
0
    for (int32_t k = base;; k += base) {
8158
0
      if (input.empty()) {
8159
0
        return false;
8160
0
      }
8161
0
      uint8_t code_point = input.front();
8162
0
      input.remove_prefix(1);
8163
0
      int32_t digit = char_to_digit_value(code_point);
8164
0
      if (digit < 0) {
8165
0
        return false;
8166
0
      }
8167
0
      if (digit > (0x7fffffff - i) / w) {
8168
0
        return false;
8169
0
      }
8170
0
      i = i + digit * w;
8171
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8172
0
      if (digit < t) {
8173
0
        break;
8174
0
      }
8175
0
      if (w > 0x7fffffff / (base - t)) {
8176
0
        return false;
8177
0
      }
8178
0
      w = w * (base - t);
8179
0
    }
8180
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
8181
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
8182
0
      return false;
8183
0
    }
8184
0
    n = n + i / int32_t(written_out + 1);
8185
0
    i = i % int32_t(written_out + 1);
8186
0
    if (n < 0x80) {
8187
0
      return false;
8188
0
    }
8189
    // Simulate insert at position i, maintaining only the first 4 slots.
8190
0
    size_t insert_pos = size_t(i);
8191
0
    if (insert_pos < 4) {
8192
0
      for (size_t j = 3; j > insert_pos; j--) {
8193
0
        first4[j] = first4[j - 1];
8194
0
      }
8195
0
      first4[insert_pos] = n;
8196
0
    }
8197
0
    written_out++;
8198
0
    ++i;
8199
0
  }
8200
  // See https://github.com/whatwg/url/issues/803
8201
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
8202
0
  if (written_out >= 4 && first4[0] == U'x' && first4[1] == U'n' &&
8203
0
      first4[2] == U'-' && first4[3] == U'-') {
8204
0
    return false;
8205
0
  }
8206
0
  return true;
8207
0
}
8208
8209
27.7k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
8210
27.7k
  out.reserve(input.size() + out.size());
8211
27.7k
  uint32_t n = initial_n;
8212
27.7k
  int32_t d = 0;
8213
27.7k
  int32_t bias = initial_bias;
8214
27.7k
  size_t h = 0;
8215
  // first push the ascii content
8216
217k
  for (uint32_t c : input) {
8217
217k
    if (c < 0x80) {
8218
28.3k
      ++h;
8219
28.3k
      out.push_back(char(c));
8220
28.3k
    }
8221
217k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
8222
0
      return false;
8223
0
    }
8224
217k
  }
8225
27.7k
  size_t b = h;
8226
27.7k
  if (b > 0) {
8227
2.38k
    out.push_back('-');
8228
2.38k
  }
8229
134k
  while (h < input.size()) {
8230
107k
    uint32_t m = 0x10FFFF;
8231
1.71M
    for (auto code_point : input) {
8232
1.71M
      if (code_point >= n && code_point < m) m = code_point;
8233
1.71M
    }
8234
8235
107k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
8236
0
      return false;
8237
0
    }
8238
107k
    d = d + int32_t((m - n) * (h + 1));
8239
107k
    n = m;
8240
1.71M
    for (auto c : input) {
8241
1.71M
      if (c < n) {
8242
971k
        if (d == 0x7fffffff) {
8243
0
          return false;
8244
0
        }
8245
971k
        ++d;
8246
971k
      }
8247
1.71M
      if (c == n) {
8248
188k
        int32_t q = d;
8249
437k
        for (int32_t k = base;; k += base) {
8250
437k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
8251
8252
437k
          if (q < t) {
8253
188k
            break;
8254
188k
          }
8255
248k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
8256
248k
          q = (q - t) / (base - t);
8257
248k
        }
8258
188k
        out.push_back(digit_to_char(q));
8259
188k
        bias = adapt(d, int32_t(h + 1), h == b);
8260
188k
        d = 0;
8261
188k
        ++h;
8262
188k
      }
8263
1.71M
    }
8264
107k
    ++d;
8265
107k
    ++n;
8266
107k
  }
8267
27.7k
  return true;
8268
27.7k
}
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
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
}
9053
9054
inline static size_t find_last_not_of_nsm(
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
}
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
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
}
9074
9075
37.6k
bool is_label_valid(const std::u32string_view label) {
9076
37.6k
  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
37.6k
  constexpr static uint32_t combining[] = {
9102
37.6k
      0x300,   0x301,   0x302,   0x303,   0x304,   0x305,   0x306,   0x307,
9103
37.6k
      0x308,   0x309,   0x30a,   0x30b,   0x30c,   0x30d,   0x30e,   0x30f,
9104
37.6k
      0x310,   0x311,   0x312,   0x313,   0x314,   0x315,   0x316,   0x317,
9105
37.6k
      0x318,   0x319,   0x31a,   0x31b,   0x31c,   0x31d,   0x31e,   0x31f,
9106
37.6k
      0x320,   0x321,   0x322,   0x323,   0x324,   0x325,   0x326,   0x327,
9107
37.6k
      0x328,   0x329,   0x32a,   0x32b,   0x32c,   0x32d,   0x32e,   0x32f,
9108
37.6k
      0x330,   0x331,   0x332,   0x333,   0x334,   0x335,   0x336,   0x337,
9109
37.6k
      0x338,   0x339,   0x33a,   0x33b,   0x33c,   0x33d,   0x33e,   0x33f,
9110
37.6k
      0x340,   0x341,   0x342,   0x343,   0x344,   0x345,   0x346,   0x347,
9111
37.6k
      0x348,   0x349,   0x34a,   0x34b,   0x34c,   0x34d,   0x34e,   0x34f,
9112
37.6k
      0x350,   0x351,   0x352,   0x353,   0x354,   0x355,   0x356,   0x357,
9113
37.6k
      0x358,   0x359,   0x35a,   0x35b,   0x35c,   0x35d,   0x35e,   0x35f,
9114
37.6k
      0x360,   0x361,   0x362,   0x363,   0x364,   0x365,   0x366,   0x367,
9115
37.6k
      0x368,   0x369,   0x36a,   0x36b,   0x36c,   0x36d,   0x36e,   0x36f,
9116
37.6k
      0x483,   0x484,   0x485,   0x486,   0x487,   0x488,   0x489,   0x591,
9117
37.6k
      0x592,   0x593,   0x594,   0x595,   0x596,   0x597,   0x598,   0x599,
9118
37.6k
      0x59a,   0x59b,   0x59c,   0x59d,   0x59e,   0x59f,   0x5a0,   0x5a1,
9119
37.6k
      0x5a2,   0x5a3,   0x5a4,   0x5a5,   0x5a6,   0x5a7,   0x5a8,   0x5a9,
9120
37.6k
      0x5aa,   0x5ab,   0x5ac,   0x5ad,   0x5ae,   0x5af,   0x5b0,   0x5b1,
9121
37.6k
      0x5b2,   0x5b3,   0x5b4,   0x5b5,   0x5b6,   0x5b7,   0x5b8,   0x5b9,
9122
37.6k
      0x5ba,   0x5bb,   0x5bc,   0x5bd,   0x5bf,   0x5c1,   0x5c2,   0x5c4,
9123
37.6k
      0x5c5,   0x5c7,   0x610,   0x611,   0x612,   0x613,   0x614,   0x615,
9124
37.6k
      0x616,   0x617,   0x618,   0x619,   0x61a,   0x64b,   0x64c,   0x64d,
9125
37.6k
      0x64e,   0x64f,   0x650,   0x651,   0x652,   0x653,   0x654,   0x655,
9126
37.6k
      0x656,   0x657,   0x658,   0x659,   0x65a,   0x65b,   0x65c,   0x65d,
9127
37.6k
      0x65e,   0x65f,   0x670,   0x6d6,   0x6d7,   0x6d8,   0x6d9,   0x6da,
9128
37.6k
      0x6db,   0x6dc,   0x6df,   0x6e0,   0x6e1,   0x6e2,   0x6e3,   0x6e4,
9129
37.6k
      0x6e7,   0x6e8,   0x6ea,   0x6eb,   0x6ec,   0x6ed,   0x711,   0x730,
9130
37.6k
      0x731,   0x732,   0x733,   0x734,   0x735,   0x736,   0x737,   0x738,
9131
37.6k
      0x739,   0x73a,   0x73b,   0x73c,   0x73d,   0x73e,   0x73f,   0x740,
9132
37.6k
      0x741,   0x742,   0x743,   0x744,   0x745,   0x746,   0x747,   0x748,
9133
37.6k
      0x749,   0x74a,   0x7a6,   0x7a7,   0x7a8,   0x7a9,   0x7aa,   0x7ab,
9134
37.6k
      0x7ac,   0x7ad,   0x7ae,   0x7af,   0x7b0,   0x7eb,   0x7ec,   0x7ed,
9135
37.6k
      0x7ee,   0x7ef,   0x7f0,   0x7f1,   0x7f2,   0x7f3,   0x7fd,   0x816,
9136
37.6k
      0x817,   0x818,   0x819,   0x81b,   0x81c,   0x81d,   0x81e,   0x81f,
9137
37.6k
      0x820,   0x821,   0x822,   0x823,   0x825,   0x826,   0x827,   0x829,
9138
37.6k
      0x82a,   0x82b,   0x82c,   0x82d,   0x859,   0x85a,   0x85b,   0x8d3,
9139
37.6k
      0x8d4,   0x8d5,   0x8d6,   0x8d7,   0x8d8,   0x8d9,   0x8da,   0x8db,
9140
37.6k
      0x8dc,   0x8dd,   0x8de,   0x8df,   0x8e0,   0x8e1,   0x8e3,   0x8e4,
9141
37.6k
      0x8e5,   0x8e6,   0x8e7,   0x8e8,   0x8e9,   0x8ea,   0x8eb,   0x8ec,
9142
37.6k
      0x8ed,   0x8ee,   0x8ef,   0x8f0,   0x8f1,   0x8f2,   0x8f3,   0x8f4,
9143
37.6k
      0x8f5,   0x8f6,   0x8f7,   0x8f8,   0x8f9,   0x8fa,   0x8fb,   0x8fc,
9144
37.6k
      0x8fd,   0x8fe,   0x8ff,   0x900,   0x901,   0x902,   0x903,   0x93a,
9145
37.6k
      0x93b,   0x93c,   0x93e,   0x93f,   0x940,   0x941,   0x942,   0x943,
9146
37.6k
      0x944,   0x945,   0x946,   0x947,   0x948,   0x949,   0x94a,   0x94b,
9147
37.6k
      0x94c,   0x94d,   0x94e,   0x94f,   0x951,   0x952,   0x953,   0x954,
9148
37.6k
      0x955,   0x956,   0x957,   0x962,   0x963,   0x981,   0x982,   0x983,
9149
37.6k
      0x9bc,   0x9be,   0x9bf,   0x9c0,   0x9c1,   0x9c2,   0x9c3,   0x9c4,
9150
37.6k
      0x9c7,   0x9c8,   0x9cb,   0x9cc,   0x9cd,   0x9d7,   0x9e2,   0x9e3,
9151
37.6k
      0x9fe,   0xa01,   0xa02,   0xa03,   0xa3c,   0xa3e,   0xa3f,   0xa40,
9152
37.6k
      0xa41,   0xa42,   0xa47,   0xa48,   0xa4b,   0xa4c,   0xa4d,   0xa51,
9153
37.6k
      0xa70,   0xa71,   0xa75,   0xa81,   0xa82,   0xa83,   0xabc,   0xabe,
9154
37.6k
      0xabf,   0xac0,   0xac1,   0xac2,   0xac3,   0xac4,   0xac5,   0xac7,
9155
37.6k
      0xac8,   0xac9,   0xacb,   0xacc,   0xacd,   0xae2,   0xae3,   0xafa,
9156
37.6k
      0xafb,   0xafc,   0xafd,   0xafe,   0xaff,   0xb01,   0xb02,   0xb03,
9157
37.6k
      0xb3c,   0xb3e,   0xb3f,   0xb40,   0xb41,   0xb42,   0xb43,   0xb44,
9158
37.6k
      0xb47,   0xb48,   0xb4b,   0xb4c,   0xb4d,   0xb55,   0xb56,   0xb57,
9159
37.6k
      0xb62,   0xb63,   0xb82,   0xbbe,   0xbbf,   0xbc0,   0xbc1,   0xbc2,
9160
37.6k
      0xbc6,   0xbc7,   0xbc8,   0xbca,   0xbcb,   0xbcc,   0xbcd,   0xbd7,
9161
37.6k
      0xc00,   0xc01,   0xc02,   0xc03,   0xc04,   0xc3e,   0xc3f,   0xc40,
9162
37.6k
      0xc41,   0xc42,   0xc43,   0xc44,   0xc46,   0xc47,   0xc48,   0xc4a,
9163
37.6k
      0xc4b,   0xc4c,   0xc4d,   0xc55,   0xc56,   0xc62,   0xc63,   0xc81,
9164
37.6k
      0xc82,   0xc83,   0xcbc,   0xcbe,   0xcbf,   0xcc0,   0xcc1,   0xcc2,
9165
37.6k
      0xcc3,   0xcc4,   0xcc6,   0xcc7,   0xcc8,   0xcca,   0xccb,   0xccc,
9166
37.6k
      0xccd,   0xcd5,   0xcd6,   0xce2,   0xce3,   0xd00,   0xd01,   0xd02,
9167
37.6k
      0xd03,   0xd3b,   0xd3c,   0xd3e,   0xd3f,   0xd40,   0xd41,   0xd42,
9168
37.6k
      0xd43,   0xd44,   0xd46,   0xd47,   0xd48,   0xd4a,   0xd4b,   0xd4c,
9169
37.6k
      0xd4d,   0xd57,   0xd62,   0xd63,   0xd81,   0xd82,   0xd83,   0xdca,
9170
37.6k
      0xdcf,   0xdd0,   0xdd1,   0xdd2,   0xdd3,   0xdd4,   0xdd6,   0xdd8,
9171
37.6k
      0xdd9,   0xdda,   0xddb,   0xddc,   0xddd,   0xdde,   0xddf,   0xdf2,
9172
37.6k
      0xdf3,   0xe31,   0xe34,   0xe35,   0xe36,   0xe37,   0xe38,   0xe39,
9173
37.6k
      0xe3a,   0xe47,   0xe48,   0xe49,   0xe4a,   0xe4b,   0xe4c,   0xe4d,
9174
37.6k
      0xe4e,   0xeb1,   0xeb4,   0xeb5,   0xeb6,   0xeb7,   0xeb8,   0xeb9,
9175
37.6k
      0xeba,   0xebb,   0xebc,   0xec8,   0xec9,   0xeca,   0xecb,   0xecc,
9176
37.6k
      0xecd,   0xf18,   0xf19,   0xf35,   0xf37,   0xf39,   0xf3e,   0xf3f,
9177
37.6k
      0xf71,   0xf72,   0xf73,   0xf74,   0xf75,   0xf76,   0xf77,   0xf78,
9178
37.6k
      0xf79,   0xf7a,   0xf7b,   0xf7c,   0xf7d,   0xf7e,   0xf7f,   0xf80,
9179
37.6k
      0xf81,   0xf82,   0xf83,   0xf84,   0xf86,   0xf87,   0xf8d,   0xf8e,
9180
37.6k
      0xf8f,   0xf90,   0xf91,   0xf92,   0xf93,   0xf94,   0xf95,   0xf96,
9181
37.6k
      0xf97,   0xf99,   0xf9a,   0xf9b,   0xf9c,   0xf9d,   0xf9e,   0xf9f,
9182
37.6k
      0xfa0,   0xfa1,   0xfa2,   0xfa3,   0xfa4,   0xfa5,   0xfa6,   0xfa7,
9183
37.6k
      0xfa8,   0xfa9,   0xfaa,   0xfab,   0xfac,   0xfad,   0xfae,   0xfaf,
9184
37.6k
      0xfb0,   0xfb1,   0xfb2,   0xfb3,   0xfb4,   0xfb5,   0xfb6,   0xfb7,
9185
37.6k
      0xfb8,   0xfb9,   0xfba,   0xfbb,   0xfbc,   0xfc6,   0x102b,  0x102c,
9186
37.6k
      0x102d,  0x102e,  0x102f,  0x1030,  0x1031,  0x1032,  0x1033,  0x1034,
9187
37.6k
      0x1035,  0x1036,  0x1037,  0x1038,  0x1039,  0x103a,  0x103b,  0x103c,
9188
37.6k
      0x103d,  0x103e,  0x1056,  0x1057,  0x1058,  0x1059,  0x105e,  0x105f,
9189
37.6k
      0x1060,  0x1062,  0x1063,  0x1064,  0x1067,  0x1068,  0x1069,  0x106a,
9190
37.6k
      0x106b,  0x106c,  0x106d,  0x1071,  0x1072,  0x1073,  0x1074,  0x1082,
9191
37.6k
      0x1083,  0x1084,  0x1085,  0x1086,  0x1087,  0x1088,  0x1089,  0x108a,
9192
37.6k
      0x108b,  0x108c,  0x108d,  0x108f,  0x109a,  0x109b,  0x109c,  0x109d,
9193
37.6k
      0x135d,  0x135e,  0x135f,  0x1712,  0x1713,  0x1714,  0x1732,  0x1733,
9194
37.6k
      0x1734,  0x1752,  0x1753,  0x1772,  0x1773,  0x17b4,  0x17b5,  0x17b6,
9195
37.6k
      0x17b7,  0x17b8,  0x17b9,  0x17ba,  0x17bb,  0x17bc,  0x17bd,  0x17be,
9196
37.6k
      0x17bf,  0x17c0,  0x17c1,  0x17c2,  0x17c3,  0x17c4,  0x17c5,  0x17c6,
9197
37.6k
      0x17c7,  0x17c8,  0x17c9,  0x17ca,  0x17cb,  0x17cc,  0x17cd,  0x17ce,
9198
37.6k
      0x17cf,  0x17d0,  0x17d1,  0x17d2,  0x17d3,  0x17dd,  0x180b,  0x180c,
9199
37.6k
      0x180d,  0x1885,  0x1886,  0x18a9,  0x1920,  0x1921,  0x1922,  0x1923,
9200
37.6k
      0x1924,  0x1925,  0x1926,  0x1927,  0x1928,  0x1929,  0x192a,  0x192b,
9201
37.6k
      0x1930,  0x1931,  0x1932,  0x1933,  0x1934,  0x1935,  0x1936,  0x1937,
9202
37.6k
      0x1938,  0x1939,  0x193a,  0x193b,  0x1a17,  0x1a18,  0x1a19,  0x1a1a,
9203
37.6k
      0x1a1b,  0x1a55,  0x1a56,  0x1a57,  0x1a58,  0x1a59,  0x1a5a,  0x1a5b,
9204
37.6k
      0x1a5c,  0x1a5d,  0x1a5e,  0x1a60,  0x1a61,  0x1a62,  0x1a63,  0x1a64,
9205
37.6k
      0x1a65,  0x1a66,  0x1a67,  0x1a68,  0x1a69,  0x1a6a,  0x1a6b,  0x1a6c,
9206
37.6k
      0x1a6d,  0x1a6e,  0x1a6f,  0x1a70,  0x1a71,  0x1a72,  0x1a73,  0x1a74,
9207
37.6k
      0x1a75,  0x1a76,  0x1a77,  0x1a78,  0x1a79,  0x1a7a,  0x1a7b,  0x1a7c,
9208
37.6k
      0x1a7f,  0x1ab0,  0x1ab1,  0x1ab2,  0x1ab3,  0x1ab4,  0x1ab5,  0x1ab6,
9209
37.6k
      0x1ab7,  0x1ab8,  0x1ab9,  0x1aba,  0x1abb,  0x1abc,  0x1abd,  0x1abe,
9210
37.6k
      0x1abf,  0x1ac0,  0x1b00,  0x1b01,  0x1b02,  0x1b03,  0x1b04,  0x1b34,
9211
37.6k
      0x1b35,  0x1b36,  0x1b37,  0x1b38,  0x1b39,  0x1b3a,  0x1b3b,  0x1b3c,
9212
37.6k
      0x1b3d,  0x1b3e,  0x1b3f,  0x1b40,  0x1b41,  0x1b42,  0x1b43,  0x1b44,
9213
37.6k
      0x1b6b,  0x1b6c,  0x1b6d,  0x1b6e,  0x1b6f,  0x1b70,  0x1b71,  0x1b72,
9214
37.6k
      0x1b73,  0x1b80,  0x1b81,  0x1b82,  0x1ba1,  0x1ba2,  0x1ba3,  0x1ba4,
9215
37.6k
      0x1ba5,  0x1ba6,  0x1ba7,  0x1ba8,  0x1ba9,  0x1baa,  0x1bab,  0x1bac,
9216
37.6k
      0x1bad,  0x1be6,  0x1be7,  0x1be8,  0x1be9,  0x1bea,  0x1beb,  0x1bec,
9217
37.6k
      0x1bed,  0x1bee,  0x1bef,  0x1bf0,  0x1bf1,  0x1bf2,  0x1bf3,  0x1c24,
9218
37.6k
      0x1c25,  0x1c26,  0x1c27,  0x1c28,  0x1c29,  0x1c2a,  0x1c2b,  0x1c2c,
9219
37.6k
      0x1c2d,  0x1c2e,  0x1c2f,  0x1c30,  0x1c31,  0x1c32,  0x1c33,  0x1c34,
9220
37.6k
      0x1c35,  0x1c36,  0x1c37,  0x1cd0,  0x1cd1,  0x1cd2,  0x1cd4,  0x1cd5,
9221
37.6k
      0x1cd6,  0x1cd7,  0x1cd8,  0x1cd9,  0x1cda,  0x1cdb,  0x1cdc,  0x1cdd,
9222
37.6k
      0x1cde,  0x1cdf,  0x1ce0,  0x1ce1,  0x1ce2,  0x1ce3,  0x1ce4,  0x1ce5,
9223
37.6k
      0x1ce6,  0x1ce7,  0x1ce8,  0x1ced,  0x1cf4,  0x1cf7,  0x1cf8,  0x1cf9,
9224
37.6k
      0x1dc0,  0x1dc1,  0x1dc2,  0x1dc3,  0x1dc4,  0x1dc5,  0x1dc6,  0x1dc7,
9225
37.6k
      0x1dc8,  0x1dc9,  0x1dca,  0x1dcb,  0x1dcc,  0x1dcd,  0x1dce,  0x1dcf,
9226
37.6k
      0x1dd0,  0x1dd1,  0x1dd2,  0x1dd3,  0x1dd4,  0x1dd5,  0x1dd6,  0x1dd7,
9227
37.6k
      0x1dd8,  0x1dd9,  0x1dda,  0x1ddb,  0x1ddc,  0x1ddd,  0x1dde,  0x1ddf,
9228
37.6k
      0x1de0,  0x1de1,  0x1de2,  0x1de3,  0x1de4,  0x1de5,  0x1de6,  0x1de7,
9229
37.6k
      0x1de8,  0x1de9,  0x1dea,  0x1deb,  0x1dec,  0x1ded,  0x1dee,  0x1def,
9230
37.6k
      0x1df0,  0x1df1,  0x1df2,  0x1df3,  0x1df4,  0x1df5,  0x1df6,  0x1df7,
9231
37.6k
      0x1df8,  0x1df9,  0x1dfb,  0x1dfc,  0x1dfd,  0x1dfe,  0x1dff,  0x20d0,
9232
37.6k
      0x20d1,  0x20d2,  0x20d3,  0x20d4,  0x20d5,  0x20d6,  0x20d7,  0x20d8,
9233
37.6k
      0x20d9,  0x20da,  0x20db,  0x20dc,  0x20dd,  0x20de,  0x20df,  0x20e0,
9234
37.6k
      0x20e1,  0x20e2,  0x20e3,  0x20e4,  0x20e5,  0x20e6,  0x20e7,  0x20e8,
9235
37.6k
      0x20e9,  0x20ea,  0x20eb,  0x20ec,  0x20ed,  0x20ee,  0x20ef,  0x20f0,
9236
37.6k
      0x2cef,  0x2cf0,  0x2cf1,  0x2d7f,  0x2de0,  0x2de1,  0x2de2,  0x2de3,
9237
37.6k
      0x2de4,  0x2de5,  0x2de6,  0x2de7,  0x2de8,  0x2de9,  0x2dea,  0x2deb,
9238
37.6k
      0x2dec,  0x2ded,  0x2dee,  0x2def,  0x2df0,  0x2df1,  0x2df2,  0x2df3,
9239
37.6k
      0x2df4,  0x2df5,  0x2df6,  0x2df7,  0x2df8,  0x2df9,  0x2dfa,  0x2dfb,
9240
37.6k
      0x2dfc,  0x2dfd,  0x2dfe,  0x2dff,  0x302a,  0x302b,  0x302c,  0x302d,
9241
37.6k
      0x302e,  0x302f,  0x3099,  0x309a,  0xa66f,  0xa670,  0xa671,  0xa672,
9242
37.6k
      0xa674,  0xa675,  0xa676,  0xa677,  0xa678,  0xa679,  0xa67a,  0xa67b,
9243
37.6k
      0xa67c,  0xa67d,  0xa69e,  0xa69f,  0xa6f0,  0xa6f1,  0xa802,  0xa806,
9244
37.6k
      0xa80b,  0xa823,  0xa824,  0xa825,  0xa826,  0xa827,  0xa82c,  0xa880,
9245
37.6k
      0xa881,  0xa8b4,  0xa8b5,  0xa8b6,  0xa8b7,  0xa8b8,  0xa8b9,  0xa8ba,
9246
37.6k
      0xa8bb,  0xa8bc,  0xa8bd,  0xa8be,  0xa8bf,  0xa8c0,  0xa8c1,  0xa8c2,
9247
37.6k
      0xa8c3,  0xa8c4,  0xa8c5,  0xa8e0,  0xa8e1,  0xa8e2,  0xa8e3,  0xa8e4,
9248
37.6k
      0xa8e5,  0xa8e6,  0xa8e7,  0xa8e8,  0xa8e9,  0xa8ea,  0xa8eb,  0xa8ec,
9249
37.6k
      0xa8ed,  0xa8ee,  0xa8ef,  0xa8f0,  0xa8f1,  0xa8ff,  0xa926,  0xa927,
9250
37.6k
      0xa928,  0xa929,  0xa92a,  0xa92b,  0xa92c,  0xa92d,  0xa947,  0xa948,
9251
37.6k
      0xa949,  0xa94a,  0xa94b,  0xa94c,  0xa94d,  0xa94e,  0xa94f,  0xa950,
9252
37.6k
      0xa951,  0xa952,  0xa953,  0xa980,  0xa981,  0xa982,  0xa983,  0xa9b3,
9253
37.6k
      0xa9b4,  0xa9b5,  0xa9b6,  0xa9b7,  0xa9b8,  0xa9b9,  0xa9ba,  0xa9bb,
9254
37.6k
      0xa9bc,  0xa9bd,  0xa9be,  0xa9bf,  0xa9c0,  0xa9e5,  0xaa29,  0xaa2a,
9255
37.6k
      0xaa2b,  0xaa2c,  0xaa2d,  0xaa2e,  0xaa2f,  0xaa30,  0xaa31,  0xaa32,
9256
37.6k
      0xaa33,  0xaa34,  0xaa35,  0xaa36,  0xaa43,  0xaa4c,  0xaa4d,  0xaa7b,
9257
37.6k
      0xaa7c,  0xaa7d,  0xaab0,  0xaab2,  0xaab3,  0xaab4,  0xaab7,  0xaab8,
9258
37.6k
      0xaabe,  0xaabf,  0xaac1,  0xaaeb,  0xaaec,  0xaaed,  0xaaee,  0xaaef,
9259
37.6k
      0xaaf5,  0xaaf6,  0xabe3,  0xabe4,  0xabe5,  0xabe6,  0xabe7,  0xabe8,
9260
37.6k
      0xabe9,  0xabea,  0xabec,  0xabed,  0xfb1e,  0xfe00,  0xfe01,  0xfe02,
9261
37.6k
      0xfe03,  0xfe04,  0xfe05,  0xfe06,  0xfe07,  0xfe08,  0xfe09,  0xfe0a,
9262
37.6k
      0xfe0b,  0xfe0c,  0xfe0d,  0xfe0e,  0xfe0f,  0xfe20,  0xfe21,  0xfe22,
9263
37.6k
      0xfe23,  0xfe24,  0xfe25,  0xfe26,  0xfe27,  0xfe28,  0xfe29,  0xfe2a,
9264
37.6k
      0xfe2b,  0xfe2c,  0xfe2d,  0xfe2e,  0xfe2f,  0x101fd, 0x102e0, 0x10376,
9265
37.6k
      0x10377, 0x10378, 0x10379, 0x1037a, 0x10a01, 0x10a02, 0x10a03, 0x10a05,
9266
37.6k
      0x10a06, 0x10a0c, 0x10a0d, 0x10a0e, 0x10a0f, 0x10a38, 0x10a39, 0x10a3a,
9267
37.6k
      0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d25, 0x10d26, 0x10d27, 0x10eab,
9268
37.6k
      0x10eac, 0x10f46, 0x10f47, 0x10f48, 0x10f49, 0x10f4a, 0x10f4b, 0x10f4c,
9269
37.6k
      0x10f4d, 0x10f4e, 0x10f4f, 0x10f50, 0x11000, 0x11001, 0x11002, 0x11038,
9270
37.6k
      0x11039, 0x1103a, 0x1103b, 0x1103c, 0x1103d, 0x1103e, 0x1103f, 0x11040,
9271
37.6k
      0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x1107f, 0x11080,
9272
37.6k
      0x11081, 0x11082, 0x110b0, 0x110b1, 0x110b2, 0x110b3, 0x110b4, 0x110b5,
9273
37.6k
      0x110b6, 0x110b7, 0x110b8, 0x110b9, 0x110ba, 0x11100, 0x11101, 0x11102,
9274
37.6k
      0x11127, 0x11128, 0x11129, 0x1112a, 0x1112b, 0x1112c, 0x1112d, 0x1112e,
9275
37.6k
      0x1112f, 0x11130, 0x11131, 0x11132, 0x11133, 0x11134, 0x11145, 0x11146,
9276
37.6k
      0x11173, 0x11180, 0x11181, 0x11182, 0x111b3, 0x111b4, 0x111b5, 0x111b6,
9277
37.6k
      0x111b7, 0x111b8, 0x111b9, 0x111ba, 0x111bb, 0x111bc, 0x111bd, 0x111be,
9278
37.6k
      0x111bf, 0x111c0, 0x111c9, 0x111ca, 0x111cb, 0x111cc, 0x111ce, 0x111cf,
9279
37.6k
      0x1122c, 0x1122d, 0x1122e, 0x1122f, 0x11230, 0x11231, 0x11232, 0x11233,
9280
37.6k
      0x11234, 0x11235, 0x11236, 0x11237, 0x1123e, 0x112df, 0x112e0, 0x112e1,
9281
37.6k
      0x112e2, 0x112e3, 0x112e4, 0x112e5, 0x112e6, 0x112e7, 0x112e8, 0x112e9,
9282
37.6k
      0x112ea, 0x11300, 0x11301, 0x11302, 0x11303, 0x1133b, 0x1133c, 0x1133e,
9283
37.6k
      0x1133f, 0x11340, 0x11341, 0x11342, 0x11343, 0x11344, 0x11347, 0x11348,
9284
37.6k
      0x1134b, 0x1134c, 0x1134d, 0x11357, 0x11362, 0x11363, 0x11366, 0x11367,
9285
37.6k
      0x11368, 0x11369, 0x1136a, 0x1136b, 0x1136c, 0x11370, 0x11371, 0x11372,
9286
37.6k
      0x11373, 0x11374, 0x11435, 0x11436, 0x11437, 0x11438, 0x11439, 0x1143a,
9287
37.6k
      0x1143b, 0x1143c, 0x1143d, 0x1143e, 0x1143f, 0x11440, 0x11441, 0x11442,
9288
37.6k
      0x11443, 0x11444, 0x11445, 0x11446, 0x1145e, 0x114b0, 0x114b1, 0x114b2,
9289
37.6k
      0x114b3, 0x114b4, 0x114b5, 0x114b6, 0x114b7, 0x114b8, 0x114b9, 0x114ba,
9290
37.6k
      0x114bb, 0x114bc, 0x114bd, 0x114be, 0x114bf, 0x114c0, 0x114c1, 0x114c2,
9291
37.6k
      0x114c3, 0x115af, 0x115b0, 0x115b1, 0x115b2, 0x115b3, 0x115b4, 0x115b5,
9292
37.6k
      0x115b8, 0x115b9, 0x115ba, 0x115bb, 0x115bc, 0x115bd, 0x115be, 0x115bf,
9293
37.6k
      0x115c0, 0x115dc, 0x115dd, 0x11630, 0x11631, 0x11632, 0x11633, 0x11634,
9294
37.6k
      0x11635, 0x11636, 0x11637, 0x11638, 0x11639, 0x1163a, 0x1163b, 0x1163c,
9295
37.6k
      0x1163d, 0x1163e, 0x1163f, 0x11640, 0x116ab, 0x116ac, 0x116ad, 0x116ae,
9296
37.6k
      0x116af, 0x116b0, 0x116b1, 0x116b2, 0x116b3, 0x116b4, 0x116b5, 0x116b6,
9297
37.6k
      0x116b7, 0x1171d, 0x1171e, 0x1171f, 0x11720, 0x11721, 0x11722, 0x11723,
9298
37.6k
      0x11724, 0x11725, 0x11726, 0x11727, 0x11728, 0x11729, 0x1172a, 0x1172b,
9299
37.6k
      0x1182c, 0x1182d, 0x1182e, 0x1182f, 0x11830, 0x11831, 0x11832, 0x11833,
9300
37.6k
      0x11834, 0x11835, 0x11836, 0x11837, 0x11838, 0x11839, 0x1183a, 0x11930,
9301
37.6k
      0x11931, 0x11932, 0x11933, 0x11934, 0x11935, 0x11937, 0x11938, 0x1193b,
9302
37.6k
      0x1193c, 0x1193d, 0x1193e, 0x11940, 0x11942, 0x11943, 0x119d1, 0x119d2,
9303
37.6k
      0x119d3, 0x119d4, 0x119d5, 0x119d6, 0x119d7, 0x119da, 0x119db, 0x119dc,
9304
37.6k
      0x119dd, 0x119de, 0x119df, 0x119e0, 0x119e4, 0x11a01, 0x11a02, 0x11a03,
9305
37.6k
      0x11a04, 0x11a05, 0x11a06, 0x11a07, 0x11a08, 0x11a09, 0x11a0a, 0x11a33,
9306
37.6k
      0x11a34, 0x11a35, 0x11a36, 0x11a37, 0x11a38, 0x11a39, 0x11a3b, 0x11a3c,
9307
37.6k
      0x11a3d, 0x11a3e, 0x11a47, 0x11a51, 0x11a52, 0x11a53, 0x11a54, 0x11a55,
9308
37.6k
      0x11a56, 0x11a57, 0x11a58, 0x11a59, 0x11a5a, 0x11a5b, 0x11a8a, 0x11a8b,
9309
37.6k
      0x11a8c, 0x11a8d, 0x11a8e, 0x11a8f, 0x11a90, 0x11a91, 0x11a92, 0x11a93,
9310
37.6k
      0x11a94, 0x11a95, 0x11a96, 0x11a97, 0x11a98, 0x11a99, 0x11c2f, 0x11c30,
9311
37.6k
      0x11c31, 0x11c32, 0x11c33, 0x11c34, 0x11c35, 0x11c36, 0x11c38, 0x11c39,
9312
37.6k
      0x11c3a, 0x11c3b, 0x11c3c, 0x11c3d, 0x11c3e, 0x11c3f, 0x11c92, 0x11c93,
9313
37.6k
      0x11c94, 0x11c95, 0x11c96, 0x11c97, 0x11c98, 0x11c99, 0x11c9a, 0x11c9b,
9314
37.6k
      0x11c9c, 0x11c9d, 0x11c9e, 0x11c9f, 0x11ca0, 0x11ca1, 0x11ca2, 0x11ca3,
9315
37.6k
      0x11ca4, 0x11ca5, 0x11ca6, 0x11ca7, 0x11ca9, 0x11caa, 0x11cab, 0x11cac,
9316
37.6k
      0x11cad, 0x11cae, 0x11caf, 0x11cb0, 0x11cb1, 0x11cb2, 0x11cb3, 0x11cb4,
9317
37.6k
      0x11cb5, 0x11cb6, 0x11d31, 0x11d32, 0x11d33, 0x11d34, 0x11d35, 0x11d36,
9318
37.6k
      0x11d3a, 0x11d3c, 0x11d3d, 0x11d3f, 0x11d40, 0x11d41, 0x11d42, 0x11d43,
9319
37.6k
      0x11d44, 0x11d45, 0x11d47, 0x11d8a, 0x11d8b, 0x11d8c, 0x11d8d, 0x11d8e,
9320
37.6k
      0x11d90, 0x11d91, 0x11d93, 0x11d94, 0x11d95, 0x11d96, 0x11d97, 0x11ef3,
9321
37.6k
      0x11ef4, 0x11ef5, 0x11ef6, 0x16af0, 0x16af1, 0x16af2, 0x16af3, 0x16af4,
9322
37.6k
      0x16b30, 0x16b31, 0x16b32, 0x16b33, 0x16b34, 0x16b35, 0x16b36, 0x16f4f,
9323
37.6k
      0x16f51, 0x16f52, 0x16f53, 0x16f54, 0x16f55, 0x16f56, 0x16f57, 0x16f58,
9324
37.6k
      0x16f59, 0x16f5a, 0x16f5b, 0x16f5c, 0x16f5d, 0x16f5e, 0x16f5f, 0x16f60,
9325
37.6k
      0x16f61, 0x16f62, 0x16f63, 0x16f64, 0x16f65, 0x16f66, 0x16f67, 0x16f68,
9326
37.6k
      0x16f69, 0x16f6a, 0x16f6b, 0x16f6c, 0x16f6d, 0x16f6e, 0x16f6f, 0x16f70,
9327
37.6k
      0x16f71, 0x16f72, 0x16f73, 0x16f74, 0x16f75, 0x16f76, 0x16f77, 0x16f78,
9328
37.6k
      0x16f79, 0x16f7a, 0x16f7b, 0x16f7c, 0x16f7d, 0x16f7e, 0x16f7f, 0x16f80,
9329
37.6k
      0x16f81, 0x16f82, 0x16f83, 0x16f84, 0x16f85, 0x16f86, 0x16f87, 0x16f8f,
9330
37.6k
      0x16f90, 0x16f91, 0x16f92, 0x16fe4, 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e,
9331
37.6k
      0x1d165, 0x1d166, 0x1d167, 0x1d168, 0x1d169, 0x1d16d, 0x1d16e, 0x1d16f,
9332
37.6k
      0x1d170, 0x1d171, 0x1d172, 0x1d17b, 0x1d17c, 0x1d17d, 0x1d17e, 0x1d17f,
9333
37.6k
      0x1d180, 0x1d181, 0x1d182, 0x1d185, 0x1d186, 0x1d187, 0x1d188, 0x1d189,
9334
37.6k
      0x1d18a, 0x1d18b, 0x1d1aa, 0x1d1ab, 0x1d1ac, 0x1d1ad, 0x1d242, 0x1d243,
9335
37.6k
      0x1d244, 0x1da00, 0x1da01, 0x1da02, 0x1da03, 0x1da04, 0x1da05, 0x1da06,
9336
37.6k
      0x1da07, 0x1da08, 0x1da09, 0x1da0a, 0x1da0b, 0x1da0c, 0x1da0d, 0x1da0e,
9337
37.6k
      0x1da0f, 0x1da10, 0x1da11, 0x1da12, 0x1da13, 0x1da14, 0x1da15, 0x1da16,
9338
37.6k
      0x1da17, 0x1da18, 0x1da19, 0x1da1a, 0x1da1b, 0x1da1c, 0x1da1d, 0x1da1e,
9339
37.6k
      0x1da1f, 0x1da20, 0x1da21, 0x1da22, 0x1da23, 0x1da24, 0x1da25, 0x1da26,
9340
37.6k
      0x1da27, 0x1da28, 0x1da29, 0x1da2a, 0x1da2b, 0x1da2c, 0x1da2d, 0x1da2e,
9341
37.6k
      0x1da2f, 0x1da30, 0x1da31, 0x1da32, 0x1da33, 0x1da34, 0x1da35, 0x1da36,
9342
37.6k
      0x1da3b, 0x1da3c, 0x1da3d, 0x1da3e, 0x1da3f, 0x1da40, 0x1da41, 0x1da42,
9343
37.6k
      0x1da43, 0x1da44, 0x1da45, 0x1da46, 0x1da47, 0x1da48, 0x1da49, 0x1da4a,
9344
37.6k
      0x1da4b, 0x1da4c, 0x1da4d, 0x1da4e, 0x1da4f, 0x1da50, 0x1da51, 0x1da52,
9345
37.6k
      0x1da53, 0x1da54, 0x1da55, 0x1da56, 0x1da57, 0x1da58, 0x1da59, 0x1da5a,
9346
37.6k
      0x1da5b, 0x1da5c, 0x1da5d, 0x1da5e, 0x1da5f, 0x1da60, 0x1da61, 0x1da62,
9347
37.6k
      0x1da63, 0x1da64, 0x1da65, 0x1da66, 0x1da67, 0x1da68, 0x1da69, 0x1da6a,
9348
37.6k
      0x1da6b, 0x1da6c, 0x1da75, 0x1da84, 0x1da9b, 0x1da9c, 0x1da9d, 0x1da9e,
9349
37.6k
      0x1da9f, 0x1daa1, 0x1daa2, 0x1daa3, 0x1daa4, 0x1daa5, 0x1daa6, 0x1daa7,
9350
37.6k
      0x1daa8, 0x1daa9, 0x1daaa, 0x1daab, 0x1daac, 0x1daad, 0x1daae, 0x1daaf,
9351
37.6k
      0x1e000, 0x1e001, 0x1e002, 0x1e003, 0x1e004, 0x1e005, 0x1e006, 0x1e008,
9352
37.6k
      0x1e009, 0x1e00a, 0x1e00b, 0x1e00c, 0x1e00d, 0x1e00e, 0x1e00f, 0x1e010,
9353
37.6k
      0x1e011, 0x1e012, 0x1e013, 0x1e014, 0x1e015, 0x1e016, 0x1e017, 0x1e018,
9354
37.6k
      0x1e01b, 0x1e01c, 0x1e01d, 0x1e01e, 0x1e01f, 0x1e020, 0x1e021, 0x1e023,
9355
37.6k
      0x1e024, 0x1e026, 0x1e027, 0x1e028, 0x1e029, 0x1e02a, 0x1e130, 0x1e131,
9356
37.6k
      0x1e132, 0x1e133, 0x1e134, 0x1e135, 0x1e136, 0x1e2ec, 0x1e2ed, 0x1e2ee,
9357
37.6k
      0x1e2ef, 0x1e8d0, 0x1e8d1, 0x1e8d2, 0x1e8d3, 0x1e8d4, 0x1e8d5, 0x1e8d6,
9358
37.6k
      0x1e944, 0x1e945, 0x1e946, 0x1e947, 0x1e948, 0x1e949, 0x1e94a, 0xe0100,
9359
37.6k
      0xe0101, 0xe0102, 0xe0103, 0xe0104, 0xe0105, 0xe0106, 0xe0107, 0xe0108,
9360
37.6k
      0xe0109, 0xe010a, 0xe010b, 0xe010c, 0xe010d, 0xe010e, 0xe010f, 0xe0110,
9361
37.6k
      0xe0111, 0xe0112, 0xe0113, 0xe0114, 0xe0115, 0xe0116, 0xe0117, 0xe0118,
9362
37.6k
      0xe0119, 0xe011a, 0xe011b, 0xe011c, 0xe011d, 0xe011e, 0xe011f, 0xe0120,
9363
37.6k
      0xe0121, 0xe0122, 0xe0123, 0xe0124, 0xe0125, 0xe0126, 0xe0127, 0xe0128,
9364
37.6k
      0xe0129, 0xe012a, 0xe012b, 0xe012c, 0xe012d, 0xe012e, 0xe012f, 0xe0130,
9365
37.6k
      0xe0131, 0xe0132, 0xe0133, 0xe0134, 0xe0135, 0xe0136, 0xe0137, 0xe0138,
9366
37.6k
      0xe0139, 0xe013a, 0xe013b, 0xe013c, 0xe013d, 0xe013e, 0xe013f, 0xe0140,
9367
37.6k
      0xe0141, 0xe0142, 0xe0143, 0xe0144, 0xe0145, 0xe0146, 0xe0147, 0xe0148,
9368
37.6k
      0xe0149, 0xe014a, 0xe014b, 0xe014c, 0xe014d, 0xe014e, 0xe014f, 0xe0150,
9369
37.6k
      0xe0151, 0xe0152, 0xe0153, 0xe0154, 0xe0155, 0xe0156, 0xe0157, 0xe0158,
9370
37.6k
      0xe0159, 0xe015a, 0xe015b, 0xe015c, 0xe015d, 0xe015e, 0xe015f, 0xe0160,
9371
37.6k
      0xe0161, 0xe0162, 0xe0163, 0xe0164, 0xe0165, 0xe0166, 0xe0167, 0xe0168,
9372
37.6k
      0xe0169, 0xe016a, 0xe016b, 0xe016c, 0xe016d, 0xe016e, 0xe016f, 0xe0170,
9373
37.6k
      0xe0171, 0xe0172, 0xe0173, 0xe0174, 0xe0175, 0xe0176, 0xe0177, 0xe0178,
9374
37.6k
      0xe0179, 0xe017a, 0xe017b, 0xe017c, 0xe017d, 0xe017e, 0xe017f, 0xe0180,
9375
37.6k
      0xe0181, 0xe0182, 0xe0183, 0xe0184, 0xe0185, 0xe0186, 0xe0187, 0xe0188,
9376
37.6k
      0xe0189, 0xe018a, 0xe018b, 0xe018c, 0xe018d, 0xe018e, 0xe018f, 0xe0190,
9377
37.6k
      0xe0191, 0xe0192, 0xe0193, 0xe0194, 0xe0195, 0xe0196, 0xe0197, 0xe0198,
9378
37.6k
      0xe0199, 0xe019a, 0xe019b, 0xe019c, 0xe019d, 0xe019e, 0xe019f, 0xe01a0,
9379
37.6k
      0xe01a1, 0xe01a2, 0xe01a3, 0xe01a4, 0xe01a5, 0xe01a6, 0xe01a7, 0xe01a8,
9380
37.6k
      0xe01a9, 0xe01aa, 0xe01ab, 0xe01ac, 0xe01ad, 0xe01ae, 0xe01af, 0xe01b0,
9381
37.6k
      0xe01b1, 0xe01b2, 0xe01b3, 0xe01b4, 0xe01b5, 0xe01b6, 0xe01b7, 0xe01b8,
9382
37.6k
      0xe01b9, 0xe01ba, 0xe01bb, 0xe01bc, 0xe01bd, 0xe01be, 0xe01bf, 0xe01c0,
9383
37.6k
      0xe01c1, 0xe01c2, 0xe01c3, 0xe01c4, 0xe01c5, 0xe01c6, 0xe01c7, 0xe01c8,
9384
37.6k
      0xe01c9, 0xe01ca, 0xe01cb, 0xe01cc, 0xe01cd, 0xe01ce, 0xe01cf, 0xe01d0,
9385
37.6k
      0xe01d1, 0xe01d2, 0xe01d3, 0xe01d4, 0xe01d5, 0xe01d6, 0xe01d7, 0xe01d8,
9386
37.6k
      0xe01d9, 0xe01da, 0xe01db, 0xe01dc, 0xe01dd, 0xe01de, 0xe01df, 0xe01e0,
9387
37.6k
      0xe01e1, 0xe01e2, 0xe01e3, 0xe01e4, 0xe01e5, 0xe01e6, 0xe01e7, 0xe01e8,
9388
37.6k
      0xe01e9, 0xe01ea, 0xe01eb, 0xe01ec, 0xe01ed, 0xe01ee, 0xe01ef};
9389
37.6k
  if (std::ranges::binary_search(combining, label.front())) {
9390
19
    return false;
9391
19
  }
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
37.6k
  constexpr static uint32_t virama[] = {
9404
37.6k
      0x094D,  0x09CD,  0x0A4D,  0x0ACD,  0x0B4D,  0x0BCD,  0x0C4D,  0x0CCD,
9405
37.6k
      0x0D3B,  0x0D3C,  0x0D4D,  0x0DCA,  0x0E3A,  0x0EBA,  0x0F84,  0x1039,
9406
37.6k
      0x103A,  0x1714,  0x1734,  0x17D2,  0x1A60,  0x1B44,  0x1BAA,  0x1BAB,
9407
37.6k
      0x1BF2,  0x1BF3,  0x2D7F,  0xA806,  0xA82C,  0xA8C4,  0xA953,  0xA9C0,
9408
37.6k
      0xAAF6,  0xABED,  0x10A3F, 0x11046, 0x1107F, 0x110B9, 0x11133, 0x11134,
9409
37.6k
      0x111C0, 0x11235, 0x112EA, 0x1134D, 0x11442, 0x114C2, 0x115BF, 0x1163F,
9410
37.6k
      0x116B6, 0x1172B, 0x11839, 0x1193D, 0x1193E, 0x119E0, 0x11A34, 0x11A47,
9411
37.6k
      0x11A99, 0x11C3F, 0x11D44, 0x11D45, 0x11D97};
9412
37.6k
  constexpr static uint32_t R[] = {
9413
37.6k
      0x622, 0x623, 0x624, 0x625, 0x627, 0x629, 0x62f, 0x630, 0x631,
9414
37.6k
      0x632, 0x648, 0x671, 0x672, 0x673, 0x675, 0x676, 0x677, 0x688,
9415
37.6k
      0x689, 0x68a, 0x68b, 0x68c, 0x68d, 0x68e, 0x68f, 0x690, 0x691,
9416
37.6k
      0x692, 0x693, 0x694, 0x695, 0x696, 0x697, 0x698, 0x699, 0x6c0,
9417
37.6k
      0x6c3, 0x6c4, 0x6c5, 0x6c6, 0x6c7, 0x6c8, 0x6c9, 0x6ca, 0x6cb,
9418
37.6k
      0x6cd, 0x6cf, 0x6d2, 0x6d3, 0x6d5, 0x6ee, 0x6ef, 0x710, 0x715,
9419
37.6k
      0x716, 0x717, 0x718, 0x719, 0x71e, 0x728, 0x72a, 0x72c, 0x72f,
9420
37.6k
      0x74d, 0x759, 0x75a, 0x75b, 0x854, 0x8aa, 0x8ab, 0x8ac};
9421
37.6k
  constexpr static uint32_t L[] = {0xa872};
9422
37.6k
  constexpr static uint32_t D[] = {
9423
37.6k
      0x620,  0x626,  0x628,  0x62a,  0x62b,  0x62c,  0x62d,  0x62e,  0x633,
9424
37.6k
      0x634,  0x635,  0x636,  0x637,  0x638,  0x639,  0x63a,  0x63b,  0x63c,
9425
37.6k
      0x63d,  0x63e,  0x63f,  0x641,  0x642,  0x643,  0x644,  0x645,  0x646,
9426
37.6k
      0x647,  0x649,  0x64a,  0x66e,  0x66f,  0x678,  0x679,  0x67a,  0x67b,
9427
37.6k
      0x67c,  0x67d,  0x67e,  0x67f,  0x680,  0x681,  0x682,  0x683,  0x684,
9428
37.6k
      0x685,  0x686,  0x687,  0x69a,  0x69b,  0x69c,  0x69d,  0x69e,  0x69f,
9429
37.6k
      0x6a0,  0x6a1,  0x6a2,  0x6a3,  0x6a4,  0x6a5,  0x6a6,  0x6a7,  0x6a8,
9430
37.6k
      0x6a9,  0x6aa,  0x6ab,  0x6ac,  0x6ad,  0x6ae,  0x6af,  0x6b0,  0x6b1,
9431
37.6k
      0x6b2,  0x6b3,  0x6b4,  0x6b5,  0x6b6,  0x6b7,  0x6b8,  0x6b9,  0x6ba,
9432
37.6k
      0x6bb,  0x6bc,  0x6bd,  0x6be,  0x6bf,  0x6c1,  0x6c2,  0x6cc,  0x6ce,
9433
37.6k
      0x6d0,  0x6d1,  0x6fa,  0x6fb,  0x6fc,  0x6ff,  0x712,  0x713,  0x714,
9434
37.6k
      0x71a,  0x71b,  0x71c,  0x71d,  0x71f,  0x720,  0x721,  0x722,  0x723,
9435
37.6k
      0x724,  0x725,  0x726,  0x727,  0x729,  0x72b,  0x72d,  0x72e,  0x74e,
9436
37.6k
      0x74f,  0x750,  0x751,  0x752,  0x753,  0x754,  0x755,  0x756,  0x757,
9437
37.6k
      0x758,  0x75c,  0x75d,  0x75e,  0x75f,  0x760,  0x761,  0x762,  0x763,
9438
37.6k
      0x764,  0x765,  0x766,  0x850,  0x851,  0x852,  0x853,  0x855,  0x8a0,
9439
37.6k
      0x8a2,  0x8a3,  0x8a4,  0x8a5,  0x8a6,  0x8a7,  0x8a8,  0x8a9,  0x1807,
9440
37.6k
      0x1820, 0x1821, 0x1822, 0x1823, 0x1824, 0x1825, 0x1826, 0x1827, 0x1828,
9441
37.6k
      0x1829, 0x182a, 0x182b, 0x182c, 0x182d, 0x182e, 0x182f, 0x1830, 0x1831,
9442
37.6k
      0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837, 0x1838, 0x1839, 0x183a,
9443
37.6k
      0x183b, 0x183c, 0x183d, 0x183e, 0x183f, 0x1840, 0x1841, 0x1842, 0x1843,
9444
37.6k
      0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x184a, 0x184b, 0x184c,
9445
37.6k
      0x184d, 0x184e, 0x184f, 0x1850, 0x1851, 0x1852, 0x1853, 0x1854, 0x1855,
9446
37.6k
      0x1856, 0x1857, 0x1858, 0x1859, 0x185a, 0x185b, 0x185c, 0x185d, 0x185e,
9447
37.6k
      0x185f, 0x1860, 0x1861, 0x1862, 0x1863, 0x1864, 0x1865, 0x1866, 0x1867,
9448
37.6k
      0x1868, 0x1869, 0x186a, 0x186b, 0x186c, 0x186d, 0x186e, 0x186f, 0x1870,
9449
37.6k
      0x1871, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876, 0x1877, 0x1887, 0x1888,
9450
37.6k
      0x1889, 0x188a, 0x188b, 0x188c, 0x188d, 0x188e, 0x188f, 0x1890, 0x1891,
9451
37.6k
      0x1892, 0x1893, 0x1894, 0x1895, 0x1896, 0x1897, 0x1898, 0x1899, 0x189a,
9452
37.6k
      0x189b, 0x189c, 0x189d, 0x189e, 0x189f, 0x18a0, 0x18a1, 0x18a2, 0x18a3,
9453
37.6k
      0x18a4, 0x18a5, 0x18a6, 0x18a7, 0x18a8, 0x18aa, 0xa840, 0xa841, 0xa842,
9454
37.6k
      0xa843, 0xa844, 0xa845, 0xa846, 0xa847, 0xa848, 0xa849, 0xa84a, 0xa84b,
9455
37.6k
      0xa84c, 0xa84d, 0xa84e, 0xa84f, 0xa850, 0xa851, 0xa852, 0xa853, 0xa854,
9456
37.6k
      0xa855, 0xa856, 0xa857, 0xa858, 0xa859, 0xa85a, 0xa85b, 0xa85c, 0xa85d,
9457
37.6k
      0xa85e, 0xa85f, 0xa860, 0xa861, 0xa862, 0xa863, 0xa864, 0xa865, 0xa866,
9458
37.6k
      0xa867, 0xa868, 0xa869, 0xa86a, 0xa86b, 0xa86c, 0xa86d, 0xa86e, 0xa86f,
9459
37.6k
      0xa870, 0xa871};
9460
9461
249k
  for (size_t i = 0; i < label.size(); i++) {
9462
212k
    uint32_t c = label[i];
9463
212k
    if (c == 0x200c) {
9464
502
      if (i > 0) {
9465
500
        if (std::ranges::binary_search(virama, label[i - 1])) {
9466
0
          return true;
9467
0
        }
9468
500
      }
9469
502
      if ((i == 0) || (i + 1 >= label.size())) {
9470
29
        return false;
9471
29
      }
9472
      // we go backward looking for L or D
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
      };
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
      };
9481
473
      std::u32string_view before = label.substr(0, i);
9482
473
      std::u32string_view after = label.substr(i + 1);
9483
473
      return (std::find_if(before.begin(), before.end(), is_l_or_d) !=
9484
473
              before.end()) &&
9485
468
             (std::find_if(after.begin(), after.end(), is_r_or_d) !=
9486
468
              after.end());
9487
211k
    } else if (c == 0x200d) {
9488
86
      if (i > 0) {
9489
84
        if (std::ranges::binary_search(virama, label[i - 1])) {
9490
84
          return true;
9491
84
        }
9492
84
      }
9493
2
      return false;
9494
86
    }
9495
212k
  }
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
37.0k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
9528
37.0k
  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
37.0k
  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
1.31k
    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
1.30k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9546
1.30k
        const direction d = find_direction(label[i]);
9547
1.30k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
9548
604
              d == direction::CS || d == direction::ET || d == direction::ON ||
9549
275
              d == direction::BN || d == direction::NSM)) {
9550
186
          return false;
9551
186
        }
9552
1.30k
      }
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
1.12k
    } 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
1.12k
      const direction first_dir = find_direction(label[0]);
9567
1.12k
      if (first_dir != direction::R && first_dir != direction::AL) {
9568
60
        return false;
9569
60
      }
9570
9571
1.06k
      bool has_an = false;
9572
1.06k
      bool has_en = false;
9573
4.84k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
9574
3.80k
        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
3.80k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
9579
3.80k
            (d == direction::AN && ((has_an = true) && has_en))) {
9580
0
          return false;
9581
0
        }
9582
9583
3.80k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
9584
226
              d == direction::EN || d == direction::ES || d == direction::CS ||
9585
135
              d == direction::ET || d == direction::ON || d == direction::BN ||
9586
131
              d == direction::NSM)) {
9587
23
          return false;
9588
23
        }
9589
9590
3.78k
        if (i == last_non_nsm_char &&
9591
1.04k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
9592
95
              d == direction::EN)) {
9593
6
          return false;
9594
6
        }
9595
3.78k
      }
9596
9597
1.03k
      return true;
9598
1.06k
    }
9599
1.31k
  }
9600
9601
35.7k
  return true;
9602
37.0k
}
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
38.8k
bool constexpr is_ascii(std::u32string_view view) {
9620
65.7k
  for (uint32_t c : view) {
9621
65.7k
    if (c >= 0x80) {
9622
37.7k
      return false;
9623
37.7k
    }
9624
65.7k
  }
9625
1.10k
  return true;
9626
38.8k
}
9627
9628
17.1k
bool constexpr is_ascii(std::string_view view) {
9629
382k
  for (uint8_t c : view) {
9630
382k
    if (c >= 0x80) {
9631
6.19k
      return false;
9632
6.19k
    }
9633
382k
  }
9634
10.9k
  return true;
9635
17.1k
}
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
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
9653
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
9654
0
}
9655
9656
0
bool contains_forbidden_domain_code_point(std::string_view view) {
9657
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
9658
0
}
9659
9660
// We return "" on error.
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
}
9726
9727
// We return "" on error.
9728
16.1k
std::string to_ascii(std::string_view ut8_string) {
9729
16.1k
  if (is_ascii(ut8_string)) {
9730
9.98k
    return from_ascii_to_ascii(ut8_string);
9731
9.98k
  }
9732
6.16k
  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
6.16k
  size_t utf32_length =
9743
6.16k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
9744
6.16k
  std::u32string utf32(utf32_length, '\0');
9745
6.16k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
9746
6.16k
      ut8_string.data(), ut8_string.size(), utf32.data());
9747
6.16k
#endif
9748
6.16k
  if (actual_utf32_length == 0) {
9749
3.98k
    return error;
9750
3.98k
  }
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
2.17k
  std::u32string tmp_buffer;
9754
2.17k
  std::u32string post_map;
9755
2.17k
  if (!ada::idna::map(utf32, tmp_buffer)) {
9756
11
    return error;
9757
11
  }
9758
2.16k
  utf32 = std::move(tmp_buffer);
9759
2.16k
  normalize(utf32);
9760
2.16k
  std::string out;
9761
2.16k
  out.reserve(ut8_string.size());
9762
2.16k
  size_t label_start = 0;
9763
9764
33.4k
  while (label_start != utf32.size()) {
9765
31.7k
    size_t loc_dot = utf32.find('.', label_start);
9766
31.7k
    bool is_last_label = (loc_dot == std::string_view::npos);
9767
31.7k
    size_t label_size =
9768
31.7k
        is_last_label ? utf32.size() - label_start : loc_dot - label_start;
9769
31.7k
    size_t label_size_with_dot = is_last_label ? label_size : label_size + 1;
9770
31.7k
    std::u32string_view label_view(utf32.data() + label_start, label_size);
9771
31.7k
    label_start += label_size_with_dot;
9772
31.7k
    if (label_size == 0) {
9773
      // empty label? Nothing to do.
9774
29.7k
    } 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
16.0k
      for (char32_t c : label_view) {
9779
16.0k
        if (c >= 0x80) {
9780
3
          return error;
9781
3
        }
9782
16.0k
      }
9783
740
      size_t label_out_start = out.size();
9784
740
      out.resize(label_out_start + label_size);
9785
740
      char* dest = out.data() + label_out_start;
9786
16.0k
      for (char32_t c : label_view) {
9787
16.0k
        *dest++ = static_cast<char>(c);
9788
16.0k
      }
9789
740
      std::string_view puny_segment_ascii(out.data() + label_out_start + 4,
9790
740
                                          label_size - 4);
9791
740
      tmp_buffer.clear();
9792
740
      bool is_ok = ada::idna::punycode_to_utf32(puny_segment_ascii, tmp_buffer);
9793
740
      if (!is_ok) {
9794
62
        return error;
9795
62
      }
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
678
      if (is_ascii(tmp_buffer)) {
9800
15
        return error;
9801
15
      }
9802
663
      if (!ada::idna::map(tmp_buffer, post_map)) {
9803
0
        return error;
9804
0
      }
9805
663
      if (tmp_buffer != post_map) {
9806
2
        return error;
9807
2
      }
9808
661
      normalize(post_map);
9809
661
      if (post_map != tmp_buffer) {
9810
3
        return error;
9811
3
      }
9812
658
      if (post_map.empty()) {
9813
0
        return error;
9814
0
      }
9815
658
      if (!is_label_valid(post_map)) {
9816
3
        return error;
9817
3
      }
9818
29.0k
    } else {
9819
      // The fast path here is an ascii label.
9820
29.0k
      if (is_ascii(label_view)) {
9821
        // no validation needed; bulk-copy with single resize.
9822
932
        size_t old_size = out.size();
9823
932
        out.resize(old_size + label_size);
9824
932
        char* dest = out.data() + old_size;
9825
20.5k
        for (char32_t c : label_view) {
9826
20.5k
          *dest++ = static_cast<char>(c);
9827
20.5k
        }
9828
28.1k
      } else {
9829
        // slow path.
9830
        // first check validity.
9831
28.1k
        if (!is_label_valid(label_view)) {
9832
334
          return error;
9833
334
        }
9834
        // It is valid! So now we must encode it as punycode...
9835
27.7k
        out.append("xn--");
9836
27.7k
        bool is_ok = ada::idna::utf32_to_punycode(label_view, out);
9837
27.7k
        if (!is_ok) {
9838
0
          return error;
9839
0
        }
9840
27.7k
      }
9841
29.0k
    }
9842
31.2k
    if (!is_last_label) {
9843
29.9k
      out.push_back('.');
9844
29.9k
    }
9845
31.2k
  }
9846
1.73k
  return out;
9847
2.16k
}
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
8.50k
std::string to_unicode(std::string_view input) {
9862
8.50k
  std::string output;
9863
8.50k
  output.reserve(input.size());
9864
9865
8.50k
  size_t label_start = 0;
9866
8.50k
  std::u32string tmp_buffer;
9867
8.50k
  std::u32string post_map;
9868
37.1k
  while (label_start < input.size()) {
9869
28.6k
    size_t loc_dot = input.find('.', label_start);
9870
28.6k
    bool is_last_label = (loc_dot == std::string_view::npos);
9871
28.6k
    size_t label_size =
9872
28.6k
        is_last_label ? input.size() - label_start : loc_dot - label_start;
9873
28.6k
    auto label_view = std::string_view(input.data() + label_start, label_size);
9874
9875
28.6k
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
9876
970
      label_view.remove_prefix(4);
9877
970
      tmp_buffer.clear();
9878
970
      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
544
        bool accept_decoded = true;
9883
544
        if (ada::idna::is_ascii(tmp_buffer)) {
9884
19
          accept_decoded = false;
9885
525
        } else {
9886
525
          post_map.clear();
9887
525
          if (!ada::idna::map(tmp_buffer, post_map) || post_map != tmp_buffer) {
9888
11
            accept_decoded = false;
9889
514
          } else {
9890
514
            ada::idna::normalize(post_map);
9891
514
            if (post_map != tmp_buffer || post_map.empty() ||
9892
514
                !ada::idna::is_label_valid(post_map)) {
9893
2
              accept_decoded = false;
9894
2
            }
9895
514
          }
9896
525
        }
9897
9898
544
        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
512
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
9919
512
                                                             tmp_buffer.size());
9920
512
          size_t old_size = output.size();
9921
512
          output.resize(old_size + utf8_size);
9922
512
          ada::idna::utf32_to_utf8(tmp_buffer.data(), tmp_buffer.size(),
9923
512
                                   output.data() + old_size);
9924
512
#endif
9925
512
        } else {
9926
          // ToUnicode never fails. If any step fails, return the original
9927
          // input sequence for the label.
9928
32
          output.append(
9929
32
              std::string_view(input.data() + label_start, label_size));
9930
32
        }
9931
544
      } else {
9932
        // ToUnicode never fails.  If any step fails, then the original input
9933
        // sequence is returned immediately in that step.
9934
426
        output.append(std::string_view(input.data() + label_start, label_size));
9935
426
      }
9936
27.6k
    } else {
9937
27.6k
      output.append(label_view);
9938
27.6k
    }
9939
9940
28.6k
    if (!is_last_label) {
9941
20.5k
      output.push_back('.');
9942
20.5k
    }
9943
9944
28.6k
    label_start += label_size + 1;
9945
28.6k
  }
9946
9947
8.50k
  return output;
9948
8.50k
}
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
0
constexpr bool is_ascii_letter(char32_t c) noexcept {
10531
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10532
0
}
10533
10534
0
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
10535
0
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
10536
0
         (c >= '0' && c <= '9');
10537
0
}
10538
10539
0
bool valid_name_code_point(char32_t code_point, bool first) {
10540
  // https://tc39.es/ecma262/#prod-IdentifierStart
10541
10542
  // Fast paths
10543
0
  if (first && (code_point == U'$' || code_point == U'_' ||
10544
0
                is_ascii_letter(code_point))) {
10545
0
    return true;
10546
0
  }
10547
0
  if (!first && (code_point == U'$' || is_ascii_letter_or_digit(code_point))) {
10548
0
    return true;
10549
0
  }
10550
10551
  // Minimal error handling for invalid code point
10552
0
  if (code_point > 0x10FFFF) {
10553
0
    return false;
10554
0
  }
10555
0
  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
0
  const std::span<const uint32_t[2]> ranges =
10562
0
      first ? std::span<const uint32_t[2]>{ada::idna::id_start}
10563
0
            : std::span<const uint32_t[2]>{ada::idna::id_continue};
10564
10565
0
  const auto iter = std::ranges::lower_bound(
10566
0
      ranges, code_point, {},
10567
0
      [](const auto& range) { return range[1]; });  // project to range-high
10568
10569
0
  return iter != ranges.end() && code_point >= (*iter)[0];
10570
0
}
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
178k
constexpr bool is_tabs_or_newline(char c) noexcept {
10595
178k
  return c == '\r' || c == '\n' || c == '\t';
10596
178k
}
10597
10598
54.8k
constexpr uint64_t broadcast(uint8_t v) noexcept {
10599
54.8k
  return 0x101010101010101ull * v;
10600
54.8k
}
10601
10602
18.2k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
10603
18.2k
  uint64_t broadcast_80 = broadcast(0x80);
10604
18.2k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
10605
18.2k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
10606
18.2k
  uint64_t non_ascii = 0;
10607
18.2k
  size_t i = 0;
10608
10609
20.7k
  for (; i + 7 < length; i += 8) {
10610
2.48k
    uint64_t word{};
10611
2.48k
    memcpy(&word, input + i, sizeof(word));
10612
2.48k
    non_ascii |= (word & broadcast_80);
10613
2.48k
    word ^=
10614
2.48k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10615
2.48k
    memcpy(input + i, &word, sizeof(word));
10616
2.48k
  }
10617
18.2k
  if (i < length) {
10618
18.2k
    uint64_t word{};
10619
18.2k
    memcpy(&word, input + i, length - i);
10620
18.2k
    non_ascii |= (word & broadcast_80);
10621
18.2k
    word ^=
10622
18.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
10623
18.2k
    memcpy(input + i, &word, length - i);
10624
18.2k
  }
10625
18.2k
  return non_ascii == 0;
10626
18.2k
}
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
49.0k
    std::string_view user_input) noexcept {
10700
  // first check for short strings in which case we do it naively.
10701
49.0k
  if (user_input.size() < 16) {  // slow path
10702
30.8k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
10703
30.8k
  }
10704
  // fast path for long strings (expected to be common)
10705
18.2k
  size_t i = 0;
10706
18.2k
  const __m128i mask1 = _mm_set1_epi8('\r');
10707
18.2k
  const __m128i mask2 = _mm_set1_epi8('\n');
10708
18.2k
  const __m128i mask3 = _mm_set1_epi8('\t');
10709
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
10710
18.2k
  __m128i running{0};
10711
203k
  for (; i + 15 < user_input.size(); i += 16) {
10712
185k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
10713
185k
    running = _mm_or_si128(
10714
185k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10715
185k
                                           _mm_cmpeq_epi8(word, mask2))),
10716
185k
        _mm_cmpeq_epi8(word, mask3));
10717
185k
  }
10718
18.2k
  if (i < user_input.size()) {
10719
16.0k
    __m128i word = _mm_loadu_si128(
10720
16.0k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
10721
16.0k
    running = _mm_or_si128(
10722
16.0k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
10723
16.0k
                                           _mm_cmpeq_epi8(word, mask2))),
10724
16.0k
        _mm_cmpeq_epi8(word, mask3));
10725
16.0k
  }
10726
18.2k
  return _mm_movemask_epi8(running) != 0;
10727
49.0k
}
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
118k
    const char c) noexcept {
10823
118k
  return is_forbidden_host_code_point_table[uint8_t(c)];
10824
118k
}
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
523k
    const char c) noexcept {
10846
523k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
10847
523k
}
10848
10849
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
10850
4.84k
    const char* input, size_t length) noexcept {
10851
4.84k
  size_t i = 0;
10852
4.84k
  uint8_t accumulator{};
10853
161k
  for (; i + 4 <= length; i += 4) {
10854
156k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10855
156k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
10856
156k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
10857
156k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
10858
156k
  }
10859
12.8k
  for (; i < length; i++) {
10860
7.98k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
10861
7.98k
  }
10862
4.84k
  return accumulator;
10863
4.84k
}
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
14.9k
                                              size_t length) noexcept {
10887
14.9k
  size_t i = 0;
10888
14.9k
  uint8_t accumulator{};
10889
144k
  for (; i + 4 <= length; i += 4) {
10890
129k
    accumulator |=
10891
129k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10892
129k
    accumulator |=
10893
129k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
10894
129k
    accumulator |=
10895
129k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
10896
129k
    accumulator |=
10897
129k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
10898
129k
  }
10899
38.6k
  for (; i < length; i++) {
10900
23.7k
    accumulator |=
10901
23.7k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
10902
23.7k
  }
10903
14.9k
  return accumulator;
10904
14.9k
}
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
201k
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
10917
201k
  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
201k
}
10922
10923
27.1k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
10924
27.1k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
10925
2.33k
         (c >= 'a' && c <= 'f');
10926
27.1k
}
10927
10928
7.25k
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
7.25k
  return (c >= '0' && c <= '9');
10932
7.25k
}
10933
10934
0
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
0
  return c <= 0x7F;
10937
0
}
10938
10939
181k
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
10940
181k
  return (unsigned char)c <= ' ';
10941
181k
}
10942
10943
ada_really_inline constexpr bool is_ascii_tab_or_newline(
10944
1.44M
    const char c) noexcept {
10945
1.44M
  return c == '\t' || c == '\n' || c == '\r';
10946
1.44M
}
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
14.2k
    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
14.2k
  uint64_t half_length = uint64_t(input.size()) / 2;
10958
14.2k
  if (half_length - 1 > 2) {
10959
9.26k
    return false;
10960
9.26k
  }
10961
  // We have a string of length 2, 4 or 6.
10962
  // We now check the first character:
10963
4.93k
  if ((input[0] != '.') && (input[0] != '%')) {
10964
1.56k
    return false;
10965
1.56k
  }
10966
  // We are unlikely the get beyond this point.
10967
3.37k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
10968
3.37k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
10969
3.37k
  if (target.size() != input.size()) {
10970
1.05k
    return false;
10971
1.05k
  }
10972
  // We almost never get here.
10973
  // Optimizing the rest is relatively unimportant.
10974
2.32k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
10975
2.32k
    uint16_t A, B;
10976
2.32k
    memcpy(&A, a.data(), sizeof(A));
10977
2.32k
    memcpy(&B, b.data(), sizeof(B));
10978
2.32k
    return A == B;
10979
2.32k
  };
10980
2.32k
  if (!prefix_equal_unsafe(input, target)) {
10981
302
    return false;
10982
302
  }
10983
2.48k
  for (size_t i = 2; i < input.size(); i++) {
10984
819
    char c = input[i];
10985
819
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
10986
349
      return false;
10987
349
    }
10988
819
  }
10989
1.66k
  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
2.01k
}
10999
11000
ada_really_inline constexpr bool is_single_dot_path_segment(
11001
24.8k
    std::string_view input) noexcept {
11002
24.8k
  return input == "." || input == "%2e" || input == "%2E";
11003
24.8k
}
11004
11005
10.7k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
11006
10.7k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
11007
10.7k
}
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
25.3k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
11014
25.3k
  return hex_to_binary_table[c - '0'];
11015
25.3k
}
11016
11017
18.1k
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
18.1k
  if (first_percent == std::string_view::npos) {
11021
17.1k
    return std::string(input);
11022
17.1k
  }
11023
990
  std::string dest;
11024
990
  dest.reserve(input.length());
11025
990
  dest.append(input.substr(0, first_percent));
11026
990
  const char* pointer = input.data() + first_percent;
11027
990
  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
55.4k
  while (pointer < end) {
11031
54.5k
    const char ch = pointer[0];
11032
54.5k
    size_t remaining = end - pointer - 1;
11033
54.5k
    if (ch != '%' || remaining < 2 ||
11034
13.9k
        (  // ch == '%' && // It is unnecessary to check that ch == '%'.
11035
13.9k
            (!is_ascii_hex_digit(pointer[1]) ||
11036
41.8k
             !is_ascii_hex_digit(pointer[2])))) {
11037
41.8k
      dest += ch;
11038
41.8k
      pointer++;
11039
41.8k
    } else {
11040
12.6k
      unsigned a = convert_hex_to_binary(pointer[1]);
11041
12.6k
      unsigned b = convert_hex_to_binary(pointer[2]);
11042
12.6k
      char c = static_cast<char>(a * 16 + b);
11043
12.6k
      dest += c;
11044
12.6k
      pointer += 3;
11045
12.6k
    }
11046
54.5k
  }
11047
990
  return dest;
11048
18.1k
}
11049
11050
std::string percent_encode(const std::string_view input,
11051
30.9k
                           const uint8_t character_set[]) {
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
  });
11055
  // Optimization: Don't iterate if percent encode is not required
11056
30.9k
  if (pointer == input.end()) {
11057
14.0k
    return std::string(input);
11058
14.0k
  }
11059
11060
16.8k
  std::string result;
11061
16.8k
  result.reserve(input.length());  // in the worst case, percent encoding might
11062
                                   // produce 3 characters.
11063
16.8k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
11064
11065
783k
  for (; pointer != input.end(); pointer++) {
11066
767k
    if (character_sets::bit_at(character_set, *pointer)) {
11067
590k
      result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11068
590k
    } else {
11069
176k
      result += *pointer;
11070
176k
    }
11071
767k
  }
11072
11073
16.8k
  return result;
11074
30.9k
}
11075
11076
template <bool append>
11077
bool percent_encode(const std::string_view input, const uint8_t character_set[],
11078
17.4k
                    std::string& out) {
11079
17.4k
  ada_log("percent_encode ", input, " to output string while ",
11080
17.4k
          append ? "appending" : "overwriting");
11081
162k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
162k
    return character_sets::bit_at(character_set, c);
11083
162k
  });
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
18.8k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
18.8k
    return character_sets::bit_at(character_set, c);
11083
18.8k
  });
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
143k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
143k
    return character_sets::bit_at(character_set, c);
11083
143k
  });
11084
17.4k
  ada_log("percent_encode done checking, moved to ",
11085
17.4k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
17.4k
  if (pointer == input.end()) {
11089
9.68k
    ada_log("percent_encode encoding not needed.");
11090
9.68k
    return false;
11091
9.68k
  }
11092
7.71k
  if constexpr (!append) {
11093
3.74k
    out.clear();
11094
3.74k
  }
11095
7.71k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
7.71k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
7.71k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
7.71k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
7.71k
          " bytes");
11101
618k
  for (; pointer != input.end(); pointer++) {
11102
610k
    if (character_sets::bit_at(character_set, *pointer)) {
11103
515k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
515k
    } else {
11105
95.3k
      out += *pointer;
11106
95.3k
    }
11107
610k
  }
11108
7.71k
  return true;
11109
17.4k
}
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
7.69k
                    std::string& out) {
11079
7.69k
  ada_log("percent_encode ", input, " to output string while ",
11080
7.69k
          append ? "appending" : "overwriting");
11081
7.69k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
7.69k
    return character_sets::bit_at(character_set, c);
11083
7.69k
  });
11084
7.69k
  ada_log("percent_encode done checking, moved to ",
11085
7.69k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
7.69k
  if (pointer == input.end()) {
11089
3.94k
    ada_log("percent_encode encoding not needed.");
11090
3.94k
    return false;
11091
3.94k
  }
11092
3.74k
  if constexpr (!append) {
11093
3.74k
    out.clear();
11094
3.74k
  }
11095
3.74k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
3.74k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
3.74k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
3.74k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
3.74k
          " bytes");
11101
249k
  for (; pointer != input.end(); pointer++) {
11102
245k
    if (character_sets::bit_at(character_set, *pointer)) {
11103
205k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
205k
    } else {
11105
40.0k
      out += *pointer;
11106
40.0k
    }
11107
245k
  }
11108
3.74k
  return true;
11109
7.69k
}
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
9.70k
                    std::string& out) {
11079
9.70k
  ada_log("percent_encode ", input, " to output string while ",
11080
9.70k
          append ? "appending" : "overwriting");
11081
9.70k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
11082
9.70k
    return character_sets::bit_at(character_set, c);
11083
9.70k
  });
11084
9.70k
  ada_log("percent_encode done checking, moved to ",
11085
9.70k
          std::distance(input.begin(), pointer));
11086
11087
  // Optimization: Don't iterate if percent encode is not required
11088
9.70k
  if (pointer == input.end()) {
11089
5.74k
    ada_log("percent_encode encoding not needed.");
11090
5.74k
    return false;
11091
5.74k
  }
11092
  if constexpr (!append) {
11093
    out.clear();
11094
  }
11095
3.96k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
11096
3.96k
          " bytes");
11097
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11098
3.96k
  out.append(input.data(), std::distance(input.begin(), pointer));
11099
3.96k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
11100
3.96k
          " bytes");
11101
369k
  for (; pointer != input.end(); pointer++) {
11102
365k
    if (character_sets::bit_at(character_set, *pointer)) {
11103
310k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11104
310k
    } else {
11105
55.3k
      out += *pointer;
11106
55.3k
    }
11107
365k
  }
11108
3.96k
  return true;
11109
9.70k
}
11110
11111
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
11112
7.63k
              size_t first_percent) {
11113
7.63k
  std::string percent_decoded_buffer;
11114
7.63k
  std::string_view input = plain;
11115
7.63k
  if (first_percent != std::string_view::npos) {
11116
393
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
11117
393
    input = percent_decoded_buffer;
11118
393
  }
11119
  // input is a non-empty UTF-8 string, must be percent decoded
11120
7.63k
  std::string idna_ascii = ada::idna::to_ascii(input);
11121
7.63k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
11122
4.84k
                                idna_ascii.data(), idna_ascii.size())) {
11123
4.13k
    return false;
11124
4.13k
  }
11125
3.49k
  out = std::move(idna_ascii);
11126
3.49k
  return true;
11127
7.63k
}
11128
11129
std::string percent_encode(const std::string_view input,
11130
5.95k
                           const uint8_t character_set[], size_t index) {
11131
5.95k
  std::string out;
11132
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
11133
5.95k
  out.append(input.data(), index);
11134
5.95k
  auto pointer = input.begin() + index;
11135
315k
  for (; pointer != input.end(); pointer++) {
11136
309k
    if (character_sets::bit_at(character_set, *pointer)) {
11137
210k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
11138
210k
    } else {
11139
98.5k
      out += *pointer;
11140
98.5k
    }
11141
309k
  }
11142
5.95k
  return out;
11143
5.95k
}
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
3
    size_t& compress_length) noexcept {
11157
6
  for (size_t i = 0; i < 8; i++) {
11158
3
    if (address[i] == 0) {
11159
3
      size_t next = i + 1;
11160
21
      while (next != 8 && address[next] == 0) ++next;
11161
3
      const size_t count = next - i;
11162
3
      if (compress_length < count) {
11163
3
        compress_length = count;
11164
3
        compress = i;
11165
3
        if (next == 8) break;
11166
3
        i = next;
11167
3
      }
11168
3
    }
11169
3
  }
11170
3
}
11171
11172
3
std::string ipv6(const std::array<uint16_t, 8>& address) {
11173
3
  size_t compress_length = 0;  // The length of a long sequence of zeros.
11174
3
  size_t compress = 0;         // The start of a long sequence of zeros.
11175
3
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
11176
11177
3
  if (compress_length <= 1) {
11178
    // Optimization opportunity: Find a faster way then snprintf for imploding
11179
    // and return here.
11180
0
    compress = compress_length = 8;
11181
0
  }
11182
11183
3
  std::string output(4 * 8 + 7 + 2, '\0');
11184
3
  size_t piece_index = 0;
11185
3
  char* point = output.data();
11186
3
  char* point_end = output.data() + output.size();
11187
3
  *point++ = '[';
11188
3
  while (true) {
11189
3
    if (piece_index == compress) {
11190
3
      *point++ = ':';
11191
      // If we skip a value initially, we need to write '::', otherwise
11192
      // a single ':' will do since it follows a previous ':'.
11193
3
      if (piece_index == 0) {
11194
3
        *point++ = ':';
11195
3
      }
11196
3
      piece_index += compress_length;
11197
3
      if (piece_index == 8) {
11198
0
        break;
11199
0
      }
11200
3
    }
11201
3
    point = std::to_chars(point, point_end, address[piece_index], 16).ptr;
11202
3
    piece_index++;
11203
3
    if (piece_index == 8) {
11204
3
      break;
11205
3
    }
11206
0
    *point++ = ':';
11207
0
  }
11208
3
  *point++ = ']';
11209
3
  output.resize(point - output.data());
11210
3
  return output;
11211
3
}
11212
11213
2.42k
std::string ipv4(const uint64_t address) {
11214
2.42k
  std::string output(15, '\0');
11215
2.42k
  char* point = output.data();
11216
2.42k
  char* point_end = output.data() + output.size();
11217
2.42k
  point = std::to_chars(point, point_end, uint8_t(address >> 24)).ptr;
11218
9.68k
  for (int i = 2; i >= 0; i--) {
11219
7.26k
    *point++ = '.';
11220
7.26k
    point = std::to_chars(point, point_end, uint8_t(address >> (i * 8))).ptr;
11221
7.26k
  }
11222
2.42k
  output.resize(point - output.data());
11223
2.42k
  return output;
11224
2.42k
}
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
92.3k
uint32_t get_max_input_length() {
11246
92.3k
  return max_input_length_.load(std::memory_order_relaxed);
11247
92.3k
}
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
}
11491
11492
}  // namespace
11493
11494
template <class result_type>
11495
ada_warn_unused tl::expected<result_type, errors> parse(
11496
27.9k
    std::string_view input, const result_type* base_url) {
11497
27.9k
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
11498
27.9k
  if (!u.is_valid) {
11499
12.4k
    return tl::unexpected(errors::type_error);
11500
12.4k
  }
11501
15.5k
  return u;
11502
27.9k
}
Unexecuted instantiation: tl::expected<ada::url, ada::errors> ada::parse<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
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
27.9k
    std::string_view input, const result_type* base_url) {
11497
27.9k
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
11498
27.9k
  if (!u.is_valid) {
11499
12.4k
    return tl::unexpected(errors::type_error);
11500
12.4k
  }
11501
15.5k
  return u;
11502
27.9k
}
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
0
std::string href_from_file(std::string_view input) {
11510
  // This is going to be much faster than constructing a URL.
11511
0
  std::string tmp_buffer;
11512
0
  std::string_view internal_input;
11513
0
  if (unicode::has_tabs_or_newline(input)) {
11514
0
    tmp_buffer = input;
11515
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
11516
0
    internal_input = tmp_buffer;
11517
0
  } else {
11518
0
    internal_input = input;
11519
0
  }
11520
0
  std::string path;
11521
0
  if (internal_input.empty()) {
11522
0
    path = "/";
11523
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
11524
0
    helpers::parse_prepared_path(internal_input.substr(1),
11525
0
                                 ada::scheme::type::FILE, path);
11526
0
  } else {
11527
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
11528
0
  }
11529
0
  return "file://" + path;
11530
0
}
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
0
void encode_json(std::string_view view, out_iter out) {
11603
  // trivial implementation. could be faster.
11604
0
  const char* hexvalues =
11605
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
11606
0
  for (uint8_t c : view) {
11607
0
    if (c == '\\') {
11608
0
      *out++ = '\\';
11609
0
      *out++ = '\\';
11610
0
    } else if (c == '"') {
11611
0
      *out++ = '\\';
11612
0
      *out++ = '"';
11613
0
    } 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
0
    } else {
11621
0
      *out++ = c;
11622
0
    }
11623
0
  }
11624
0
}
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
45.5k
    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
45.5k
  size_t location_of_first = input.find('#');
11678
45.5k
  if (location_of_first == std::string_view::npos) {
11679
44.7k
    return std::nullopt;
11680
44.7k
  }
11681
794
  std::string_view hash = input;
11682
794
  hash.remove_prefix(location_of_first + 1);
11683
794
  input.remove_suffix(input.size() - location_of_first);
11684
794
  return hash;
11685
45.5k
}
11686
11687
1.66k
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
1.66k
  if (type == ada::scheme::type::FILE &&
11692
1.06k
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11693
685
    if (checkers::is_normalized_windows_drive_letter(
11694
685
            helpers::substring(path, 1))) {
11695
189
      return false;
11696
189
    }
11697
685
  }
11698
11699
  // Remove path's last item, if any.
11700
1.48k
  size_t last_delimiter = path.rfind('/');
11701
1.48k
  if (last_delimiter != std::string::npos) {
11702
869
    path.erase(last_delimiter);
11703
869
    return true;
11704
869
  }
11705
11706
611
  return false;
11707
1.48k
}
11708
11709
ada_really_inline bool shorten_path(std::string_view& path,
11710
150
                                    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
150
  if (type == ada::scheme::type::FILE &&
11715
10
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
11716
4
    if (checkers::is_normalized_windows_drive_letter(
11717
4
            helpers::substring(path, 1))) {
11718
0
      return false;
11719
0
    }
11720
4
  }
11721
11722
  // Remove path's last item, if any.
11723
150
  if (!path.empty()) {
11724
65
    size_t slash_loc = path.rfind('/');
11725
65
    if (slash_loc != std::string_view::npos) {
11726
65
      path.remove_suffix(path.size() - slash_loc);
11727
65
      return true;
11728
65
    }
11729
65
  }
11730
11731
85
  return false;
11732
150
}
11733
11734
27.4k
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
27.4k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
11738
27.4k
}
11739
11740
ada_really_inline constexpr std::string_view substring(std::string_view input,
11741
5.36k
                                                       size_t pos) {
11742
5.36k
  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
5.36k
  return input.substr(pos);
11746
5.36k
}
11747
11748
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
11749
0
  ADA_ASSERT_TRUE(pos <= input.size());
11750
0
  input.remove_suffix(input.size() - pos);
11751
0
}
11752
11753
// computes the number of trailing zeroes
11754
// this is a private inline function only defined in this source file.
11755
5.04k
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
5.04k
  return __builtin_ctzl(input_num);
11764
5.04k
#endif  // ADA_REGULAR_VISUAL_STUDIO
11765
5.04k
}
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
17.6k
    std::string_view view, size_t location) noexcept {
11903
  // first check for short strings in which case we do it naively.
11904
17.6k
  if (view.size() - location < 16) {  // slow path
11905
41.7k
    for (size_t i = location; i < view.size(); i++) {
11906
34.1k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
11907
29.8k
          view[i] == '?' || view[i] == '[') {
11908
4.83k
        return i;
11909
4.83k
      }
11910
34.1k
    }
11911
7.62k
    return size_t(view.size());
11912
12.4k
  }
11913
  // fast path for long strings (expected to be common)
11914
5.23k
  size_t i = location;
11915
5.23k
  const __m128i mask1 = _mm_set1_epi8(':');
11916
5.23k
  const __m128i mask2 = _mm_set1_epi8('/');
11917
5.23k
  const __m128i mask3 = _mm_set1_epi8('\\');
11918
5.23k
  const __m128i mask4 = _mm_set1_epi8('?');
11919
5.23k
  const __m128i mask5 = _mm_set1_epi8('[');
11920
11921
24.3k
  for (; i + 15 < view.size(); i += 16) {
11922
22.3k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
11923
22.3k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11924
22.3k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11925
22.3k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11926
22.3k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11927
22.3k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11928
22.3k
    __m128i m = _mm_or_si128(
11929
22.3k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11930
22.3k
    int mask = _mm_movemask_epi8(m);
11931
22.3k
    if (mask != 0) {
11932
3.17k
      return i + trailing_zeroes(mask);
11933
3.17k
    }
11934
22.3k
  }
11935
2.06k
  if (i < view.size()) {
11936
1.86k
    __m128i word =
11937
1.86k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
11938
1.86k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
11939
1.86k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
11940
1.86k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
11941
1.86k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
11942
1.86k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
11943
1.86k
    __m128i m = _mm_or_si128(
11944
1.86k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
11945
1.86k
    int mask = _mm_movemask_epi8(m);
11946
1.86k
    if (mask != 0) {
11947
15
      return view.length() - 16 + trailing_zeroes(mask);
11948
15
    }
11949
1.86k
  }
11950
2.05k
  return size_t(view.length());
11951
2.06k
}
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
4.45k
                                                  size_t location) noexcept {
12192
  // first check for short strings in which case we do it naively.
12193
4.45k
  if (view.size() - location < 16) {  // slow path
12194
5.55k
    for (size_t i = location; i < view.size(); i++) {
12195
5.05k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
12196
3.70k
          view[i] == '[') {
12197
1.66k
        return i;
12198
1.66k
      }
12199
5.05k
    }
12200
498
    return size_t(view.size());
12201
2.16k
  }
12202
  // fast path for long strings (expected to be common)
12203
2.28k
  size_t i = location;
12204
2.28k
  const __m128i mask1 = _mm_set1_epi8(':');
12205
2.28k
  const __m128i mask2 = _mm_set1_epi8('/');
12206
2.28k
  const __m128i mask4 = _mm_set1_epi8('?');
12207
2.28k
  const __m128i mask5 = _mm_set1_epi8('[');
12208
12209
9.65k
  for (; i + 15 < view.size(); i += 16) {
12210
9.21k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
12211
9.21k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
12212
9.21k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
12213
9.21k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
12214
9.21k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
12215
9.21k
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
12216
9.21k
    int mask = _mm_movemask_epi8(m);
12217
9.21k
    if (mask != 0) {
12218
1.85k
      return i + trailing_zeroes(mask);
12219
1.85k
    }
12220
9.21k
  }
12221
438
  if (i < view.size()) {
12222
417
    __m128i word =
12223
417
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
12224
417
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
12225
417
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
12226
417
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
12227
417
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
12228
417
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
12229
417
    int mask = _mm_movemask_epi8(m);
12230
417
    if (mask != 0) {
12231
12
      return view.length() - 16 + trailing_zeroes(mask);
12232
12
    }
12233
417
  }
12234
426
  return size_t(view.length());
12235
438
}
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
20.6k
    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
20.6k
  const size_t view_size = view.size();
12335
20.6k
  size_t location = 0;
12336
20.6k
  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
20.6k
  if (is_special) {
12357
    // We move to the next delimiter.
12358
17.0k
    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
17.6k
    for (; location < view_size;
12362
17.0k
         location = find_next_host_delimiter_special(view, location)) {
12363
8.02k
      if (view[location] == '[') {
12364
936
        location = view.find(']', location);
12365
936
        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
325
          location = view_size;
12370
325
          break;
12371
325
        }
12372
7.08k
      } else {
12373
7.08k
        found_colon = view[location] == ':';
12374
7.08k
        break;
12375
7.08k
      }
12376
8.02k
    }
12377
17.0k
  } else {
12378
    // We move to the next delimiter.
12379
3.61k
    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
4.45k
    for (; location < view_size;
12383
3.61k
         location = find_next_host_delimiter(view, location)) {
12384
3.52k
      if (view[location] == '[') {
12385
904
        location = view.find(']', location);
12386
904
        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
62
          location = view_size;
12391
62
          break;
12392
62
        }
12393
2.62k
      } else {
12394
2.62k
        found_colon = view[location] == ':';
12395
2.62k
        break;
12396
2.62k
      }
12397
3.52k
    }
12398
3.61k
  }
12399
  // performance: remove_suffix may translate into a single instruction.
12400
20.6k
  view.remove_suffix(view_size - location);
12401
20.6k
  return {location, found_colon};
12402
20.6k
}
12403
12404
45.5k
void trim_c0_whitespace(std::string_view& input) noexcept {
12405
107k
  while (!input.empty() &&
12406
106k
         ada::unicode::is_c0_control_or_space(input.front())) {
12407
61.4k
    input.remove_prefix(1);
12408
61.4k
  }
12409
75.7k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
12410
30.2k
    input.remove_suffix(1);
12411
30.2k
  }
12412
45.5k
}
12413
12414
ada_really_inline void parse_prepared_path(std::string_view input,
12415
                                           ada::scheme::type type,
12416
0
                                           std::string& path) {
12417
0
  ada_log("parse_prepared_path ", input);
12418
0
  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
0
  constexpr uint8_t need_encoding = 1;
12424
0
  constexpr uint8_t backslash_char = 2;
12425
0
  constexpr uint8_t dot_char = 4;
12426
0
  constexpr uint8_t percent_char = 8;
12427
0
  bool special = type != ada::scheme::NOT_SPECIAL;
12428
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
12429
0
                                      checkers::is_windows_drive_letter(input));
12430
0
  bool trivial_path =
12431
0
      (special ? (accumulator == 0)
12432
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
12433
0
                  0)) &&
12434
0
      (!may_need_slow_file_handling);
12435
0
  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
0
    if (input[0] != '.') {
12444
0
      size_t slashdot = 0;
12445
0
      bool dot_is_file = true;
12446
0
      for (;;) {
12447
0
        slashdot = input.find("/.", slashdot);
12448
0
        if (slashdot == std::string_view::npos) {  // common case
12449
0
          break;
12450
0
        } else {  // uncommon
12451
          // only three cases matter: /./, /.. or a final /
12452
0
          slashdot += 2;
12453
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
12454
0
                           input[slashdot] == '/');
12455
0
        }
12456
0
      }
12457
0
      trivial_path = dot_is_file;
12458
0
    }
12459
0
  }
12460
0
  if (trivial_path) {
12461
0
    ada_log("parse_path trivial");
12462
0
    path += '/';
12463
0
    path += input;
12464
0
    return;
12465
0
  }
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
0
  bool fast_path =
12471
0
      (special &&
12472
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
12473
0
      (type != ada::scheme::type::FILE);
12474
0
  if (fast_path) {
12475
0
    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
0
    size_t previous_location = 0;  // We start at 0.
12481
0
    do {
12482
0
      size_t new_location = input.find('/', previous_location);
12483
      // std::string_view path_view = input;
12484
      //  We process the last segment separately:
12485
0
      if (new_location == std::string_view::npos) {
12486
0
        std::string_view path_view = input.substr(previous_location);
12487
0
        if (path_view == "..") {  // The path ends with ..
12488
          // e.g., if you receive ".." with an empty path, you go to "/".
12489
0
          if (path.empty()) {
12490
0
            path = '/';
12491
0
            return;
12492
0
          }
12493
          // Fast case where we have nothing to do:
12494
0
          if (path.back() == '/') {
12495
0
            return;
12496
0
          }
12497
          // If you have the path "/joe/myfriend",
12498
          // then you delete 'myfriend'.
12499
0
          path.resize(path.rfind('/') + 1);
12500
0
          return;
12501
0
        }
12502
0
        path += '/';
12503
0
        if (path_view != ".") {
12504
0
          path.append(path_view);
12505
0
        }
12506
0
        return;
12507
0
      } else {
12508
        // This is a non-final segment.
12509
0
        std::string_view path_view =
12510
0
            input.substr(previous_location, new_location - previous_location);
12511
0
        previous_location = new_location + 1;
12512
0
        if (path_view == "..") {
12513
0
          size_t last_delimiter = path.rfind('/');
12514
0
          if (last_delimiter != std::string::npos) {
12515
0
            path.erase(last_delimiter);
12516
0
          }
12517
0
        } else if (path_view != ".") {
12518
0
          path += '/';
12519
0
          path.append(path_view);
12520
0
        }
12521
0
      }
12522
0
    } while (true);
12523
0
  } else {
12524
0
    ada_log("parse_path slow");
12525
    // we have reached the general case
12526
0
    bool needs_percent_encoding = (accumulator & 1);
12527
0
    std::string path_buffer_tmp;
12528
0
    do {
12529
0
      size_t location = (special && (accumulator & 2))
12530
0
                            ? input.find_first_of("/\\")
12531
0
                            : input.find('/');
12532
0
      std::string_view path_view = input;
12533
0
      if (location != std::string_view::npos) {
12534
0
        path_view.remove_suffix(path_view.size() - location);
12535
0
        input.remove_prefix(location + 1);
12536
0
      }
12537
      // path_buffer is either path_view or it might point at a percent encoded
12538
      // temporary file.
12539
0
      std::string_view path_buffer =
12540
0
          (needs_percent_encoding &&
12541
0
           ada::unicode::percent_encode<false>(
12542
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
12543
0
              ? path_buffer_tmp
12544
0
              : path_view;
12545
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
12546
0
        helpers::shorten_path(path, type);
12547
0
        if (location == std::string_view::npos) {
12548
0
          path += '/';
12549
0
        }
12550
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
12551
0
                 (location == std::string_view::npos)) {
12552
0
        path += '/';
12553
0
      }
12554
      // Otherwise, if path_buffer is not a single-dot path segment, then:
12555
0
      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
0
        if (type == ada::scheme::type::FILE && path.empty() &&
12560
0
            checkers::is_windows_drive_letter(path_buffer)) {
12561
0
          path += '/';
12562
0
          path += path_buffer[0];
12563
0
          path += ':';
12564
0
          path_buffer.remove_prefix(2);
12565
0
          path.append(path_buffer);
12566
0
        } else {
12567
          // Append path_buffer to url's path.
12568
0
          path += '/';
12569
0
          path.append(path_buffer);
12570
0
        }
12571
0
      }
12572
0
      if (location == std::string_view::npos) {
12573
0
        return;
12574
0
      }
12575
0
    } while (true);
12576
0
  }
12577
0
}
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
0
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
12589
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
12590
0
  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
}
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url>(ada::url&)
Unexecuted instantiation: void ada::helpers::strip_trailing_spaces_from_opaque_path<ada::url_aggregator>(ada::url_aggregator&)
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
9.44k
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
409k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12616
409k
    if (authority_delimiter_special[(uint8_t)*pos]) {
12617
8.98k
      return pos - view.begin();
12618
8.98k
    }
12619
409k
  }
12620
461
  return size_t(view.size());
12621
9.44k
}
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
2.34k
find_authority_delimiter(std::string_view view) noexcept {
12634
  // performance note: we might be able to gain further performance
12635
  // with SIMD instrinsics.
12636
339k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
12637
339k
    if (authority_delimiter[(uint8_t)*pos]) {
12638
2.23k
      return pos - view.begin();
12639
2.23k
    }
12640
339k
  }
12641
112
  return size_t(view.size());
12642
2.34k
}
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
0
bool url::parse_opaque_host(std::string_view input) {
12665
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
12666
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
12667
0
    return is_valid = false;
12668
0
  }
12669
12670
  // Return the result of running UTF-8 percent-encode on input using the C0
12671
  // control percent-encode set.
12672
0
  host = ada::unicode::percent_encode(
12673
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
12674
0
  return true;
12675
0
}
12676
12677
0
bool url::parse_ipv4(std::string_view input) {
12678
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
12679
0
  if (input.back() == '.') {
12680
0
    input.remove_suffix(1);
12681
0
  }
12682
0
  size_t digit_count{0};
12683
0
  int pure_decimal_count = 0;  // entries that are decimal
12684
0
  std::string_view original_input =
12685
0
      input;  // we might use this if pure_decimal_count == 4.
12686
0
  uint64_t ipv4{0};
12687
  // we could unroll for better performance?
12688
0
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
12689
0
    uint32_t
12690
0
        segment_result{};  // If any number exceeds 32 bits, we have an error.
12691
0
    bool is_hex = checkers::has_hex_prefix(input);
12692
0
    if (is_hex && ((input.length() == 2) ||
12693
0
                   ((input.length() > 2) && (input[2] == '.')))) {
12694
      // special case
12695
0
      segment_result = 0;
12696
0
      input.remove_prefix(2);
12697
0
    } else {
12698
0
      std::from_chars_result r{};
12699
0
      if (is_hex) {
12700
0
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
12701
0
                            segment_result, 16);
12702
0
      } else if ((input.length() >= 2) && input[0] == '0' &&
12703
0
                 checkers::is_digit(input[1])) {
12704
0
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
12705
0
                            segment_result, 8);
12706
0
      } else {
12707
0
        pure_decimal_count++;
12708
0
        r = std::from_chars(input.data(), input.data() + input.size(),
12709
0
                            segment_result, 10);
12710
0
      }
12711
0
      if (r.ec != std::errc()) {
12712
0
        return is_valid = false;
12713
0
      }
12714
0
      input.remove_prefix(r.ptr - input.data());
12715
0
    }
12716
0
    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
0
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
12721
0
        return is_valid = false;
12722
0
      }
12723
0
      ipv4 <<= (32 - digit_count * 8);
12724
0
      ipv4 |= segment_result;
12725
0
      goto final;
12726
0
    } else {
12727
      // There is more, so that the value must no be larger than 255
12728
      // and we must have a '.'.
12729
0
      if ((segment_result > 255) || (input[0] != '.')) {
12730
0
        return is_valid = false;
12731
0
      }
12732
0
      ipv4 <<= 8;
12733
0
      ipv4 |= segment_result;
12734
0
      input.remove_prefix(1);  // remove '.'
12735
0
    }
12736
0
  }
12737
0
  if ((digit_count != 4) || (!input.empty())) {
12738
0
    return is_valid = false;
12739
0
  }
12740
0
final:
12741
  // We could also check r.ptr to see where the parsing ended.
12742
0
  if (pure_decimal_count == 4) {
12743
0
    host = original_input;  // The original input was already all decimal and we
12744
                            // validated it.
12745
0
  } else {
12746
0
    host = ada::serializers::ipv4(ipv4);  // We have to reserialize the address.
12747
0
  }
12748
0
  host_type = IPV4;
12749
0
  return true;
12750
0
}
12751
12752
0
bool url::parse_ipv6(std::string_view input) {
12753
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
12754
12755
0
  if (input.empty()) {
12756
0
    return is_valid = false;
12757
0
  }
12758
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
12759
0
  std::array<uint16_t, 8> address{};
12760
12761
  // Let pieceIndex be 0.
12762
0
  int piece_index = 0;
12763
12764
  // Let compress be null.
12765
0
  std::optional<int> compress{};
12766
12767
  // Let pointer be a pointer for input.
12768
0
  std::string_view::iterator pointer = input.begin();
12769
12770
  // If c is U+003A (:), then:
12771
0
  if (input[0] == ':') {
12772
    // If remaining does not start with U+003A (:), validation error, return
12773
    // failure.
12774
0
    if (input.size() == 1 || input[1] != ':') {
12775
0
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
12776
0
      return is_valid = false;
12777
0
    }
12778
12779
    // Increase pointer by 2.
12780
0
    pointer += 2;
12781
12782
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
12783
0
    compress = ++piece_index;
12784
0
  }
12785
12786
  // While c is not the EOF code point:
12787
0
  while (pointer != input.end()) {
12788
    // If pieceIndex is 8, validation error, return failure.
12789
0
    if (piece_index == 8) {
12790
0
      ada_log("parse_ipv6 piece_index == 8");
12791
0
      return is_valid = false;
12792
0
    }
12793
12794
    // If c is U+003A (:), then:
12795
0
    if (*pointer == ':') {
12796
      // If compress is non-null, validation error, return failure.
12797
0
      if (compress.has_value()) {
12798
0
        ada_log("parse_ipv6 compress is non-null");
12799
0
        return is_valid = false;
12800
0
      }
12801
12802
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
12803
      // then continue.
12804
0
      pointer++;
12805
0
      compress = ++piece_index;
12806
0
      continue;
12807
0
    }
12808
12809
    // Let value and length be 0.
12810
0
    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
0
    while (length < 4 && pointer != input.end() &&
12816
0
           unicode::is_ascii_hex_digit(*pointer)) {
12817
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
12818
0
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
12819
0
      pointer++;
12820
0
      length++;
12821
0
    }
12822
12823
    // If c is U+002E (.), then:
12824
0
    if (pointer != input.end() && *pointer == '.') {
12825
      // If length is 0, validation error, return failure.
12826
0
      if (length == 0) {
12827
0
        ada_log("parse_ipv6 length is 0");
12828
0
        return is_valid = false;
12829
0
      }
12830
12831
      // Decrease pointer by length.
12832
0
      pointer -= length;
12833
12834
      // If pieceIndex is greater than 6, validation error, return failure.
12835
0
      if (piece_index > 6) {
12836
0
        ada_log("parse_ipv6 piece_index > 6");
12837
0
        return is_valid = false;
12838
0
      }
12839
12840
      // Let numbersSeen be 0.
12841
0
      int numbers_seen = 0;
12842
12843
      // While c is not the EOF code point:
12844
0
      while (pointer != input.end()) {
12845
        // Let ipv4Piece be null.
12846
0
        std::optional<uint16_t> ipv4_piece{};
12847
12848
        // If numbersSeen is greater than 0, then:
12849
0
        if (numbers_seen > 0) {
12850
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
12851
          // pointer by 1.
12852
0
          if (*pointer == '.' && numbers_seen < 4) {
12853
0
            pointer++;
12854
0
          }
12855
          // Otherwise, validation error, return failure.
12856
0
          else {
12857
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
12858
0
            return is_valid = false;
12859
0
          }
12860
0
        }
12861
12862
        // If c is not an ASCII digit, validation error, return failure.
12863
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
12864
0
          ada_log(
12865
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
12866
0
              "failure");
12867
0
          return is_valid = false;
12868
0
        }
12869
12870
        // While c is an ASCII digit:
12871
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
12872
          // Let number be c interpreted as decimal number.
12873
0
          int number = *pointer - '0';
12874
12875
          // If ipv4Piece is null, then set ipv4Piece to number.
12876
0
          if (!ipv4_piece.has_value()) {
12877
0
            ipv4_piece = number;
12878
0
          }
12879
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
12880
0
          else if (ipv4_piece == 0) {
12881
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
12882
0
            return is_valid = false;
12883
0
          }
12884
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
12885
0
          else {
12886
0
            ipv4_piece = *ipv4_piece * 10 + number;
12887
0
          }
12888
12889
          // If ipv4Piece is greater than 255, validation error, return failure.
12890
0
          if (ipv4_piece > 255) {
12891
0
            ada_log("parse_ipv6 ipv4_piece > 255");
12892
0
            return is_valid = false;
12893
0
          }
12894
12895
          // Increase pointer by 1.
12896
0
          pointer++;
12897
0
        }
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
0
        address[piece_index] =
12903
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
12904
12905
        // Increase numbersSeen by 1.
12906
0
        numbers_seen++;
12907
12908
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
12909
0
        if (numbers_seen == 2 || numbers_seen == 4) {
12910
0
          piece_index++;
12911
0
        }
12912
0
      }
12913
12914
      // If numbersSeen is not 4, validation error, return failure.
12915
0
      if (numbers_seen != 4) {
12916
0
        return is_valid = false;
12917
0
      }
12918
12919
      // Break.
12920
0
      break;
12921
0
    }
12922
    // Otherwise, if c is U+003A (:):
12923
0
    else if ((pointer != input.end()) && (*pointer == ':')) {
12924
      // Increase pointer by 1.
12925
0
      pointer++;
12926
12927
      // If c is the EOF code point, validation error, return failure.
12928
0
      if (pointer == input.end()) {
12929
0
        ada_log(
12930
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
12931
0
            "failure");
12932
0
        return is_valid = false;
12933
0
      }
12934
0
    }
12935
    // Otherwise, if c is not the EOF code point, validation error, return
12936
    // failure.
12937
0
    else if (pointer != input.end()) {
12938
0
      ada_log(
12939
0
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
12940
0
          "error, return failure");
12941
0
      return is_valid = false;
12942
0
    }
12943
12944
    // Set address[pieceIndex] to value.
12945
0
    address[piece_index] = value;
12946
12947
    // Increase pieceIndex by 1.
12948
0
    piece_index++;
12949
0
  }
12950
12951
  // If compress is non-null, then:
12952
0
  if (compress.has_value()) {
12953
    // Let swaps be pieceIndex - compress.
12954
0
    int swaps = piece_index - *compress;
12955
12956
    // Set pieceIndex to 7.
12957
0
    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
0
    while (piece_index != 0 && swaps > 0) {
12963
0
      std::swap(address[piece_index], address[*compress + swaps - 1]);
12964
0
      piece_index--;
12965
0
      swaps--;
12966
0
    }
12967
0
  }
12968
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
12969
  // return failure.
12970
0
  else if (piece_index != 8) {
12971
0
    ada_log(
12972
0
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
12973
0
        "error, return failure");
12974
0
    return is_valid = false;
12975
0
  }
12976
0
  host = ada::serializers::ipv6(address);
12977
0
  ada_log("parse_ipv6 ", *host);
12978
0
  host_type = IPV6;
12979
0
  return true;
12980
0
}
12981
12982
template <bool has_state_override>
12983
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
12984
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
12985
0
  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
0
  if (is_input_special) {  // fast path!!!
12991
0
    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
0
      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
0
      if ((has_credentials() || port.has_value()) &&
13001
0
          parsed_type == ada::scheme::type::FILE) {
13002
0
        return false;
13003
0
      }
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
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
13008
0
          host->empty()) {
13009
0
        return false;
13010
0
      }
13011
0
    }
13012
13013
0
    type = parsed_type;
13014
13015
0
    if constexpr (has_state_override) {
13016
      // This is uncommon.
13017
0
      uint16_t urls_scheme_port = get_special_port();
13018
13019
0
      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
0
        if (port.has_value() && *port == urls_scheme_port) {
13023
0
          port = std::nullopt;
13024
0
        }
13025
0
      }
13026
0
    }
13027
0
  } else {  // slow path
13028
0
    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
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
13034
13035
0
    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
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
13045
0
        return false;
13046
0
      }
13047
13048
      // If url includes credentials or has a non-null port, and buffer is
13049
      // "file", then return.
13050
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
13051
0
        return false;
13052
0
      }
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
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
13057
0
          host->empty()) {
13058
0
        return false;
13059
0
      }
13060
0
    }
13061
13062
0
    set_scheme(std::move(_buffer));
13063
13064
0
    if constexpr (has_state_override) {
13065
      // This is uncommon.
13066
0
      uint16_t urls_scheme_port = get_special_port();
13067
13068
0
      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
0
        if (port.has_value() && *port == urls_scheme_port) {
13072
0
          port = std::nullopt;
13073
0
        }
13074
0
      }
13075
0
    }
13076
0
  }
13077
13078
0
  return true;
13079
0
}
Unexecuted instantiation: bool ada::url::parse_scheme<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::parse_scheme<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
13080
13081
0
ada_really_inline bool url::parse_host(std::string_view input) {
13082
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
13083
0
  if (input.empty()) {
13084
0
    return is_valid = false;
13085
0
  }  // technically unnecessary.
13086
  // If input starts with U+005B ([), then:
13087
0
  if (input[0] == '[') {
13088
    // If input does not end with U+005D (]), validation error, return failure.
13089
0
    if (input.back() != ']') {
13090
0
      return is_valid = false;
13091
0
    }
13092
0
    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
0
    input.remove_prefix(1);
13097
0
    input.remove_suffix(1);
13098
0
    return parse_ipv6(input);
13099
0
  }
13100
13101
  // If isNotSpecial is true, then return the result of opaque-host parsing
13102
  // input.
13103
0
  if (!is_special()) {
13104
0
    return parse_opaque_host(input);
13105
0
  }
13106
13107
  // Fast path: try to parse as pure decimal IPv4(a.b.c.d) first.
13108
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
13109
0
  if (fast_result < checkers::ipv4_fast_fail) {
13110
    // Fast path succeeded - input is pure decimal IPv4
13111
0
    if (!input.empty() && input.back() == '.') {
13112
0
      host = input.substr(0, input.size() - 1);
13113
0
    } else {
13114
0
      host = input;
13115
0
    }
13116
0
    host_type = IPV4;
13117
0
    is_valid = true;
13118
0
    ada_log("parse_host fast path decimal ipv4");
13119
0
    return true;
13120
0
  }
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
0
  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
0
  unicode::to_lower_ascii(buffer.data(), buffer.size());
13131
0
  bool is_forbidden = unicode::contains_forbidden_domain_code_point(
13132
0
      buffer.data(), buffer.size());
13133
0
  if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
13134
    // fast path
13135
0
    host = std::move(buffer);
13136
13137
    // Check for other IPv4 formats (hex, octal, etc.)
13138
0
    if (checkers::is_ipv4(host.value())) {
13139
0
      ada_log("parse_host fast path ipv4");
13140
0
      return parse_ipv4(host.value());
13141
0
    }
13142
0
    ada_log("parse_host fast path ", *host);
13143
0
    is_valid = true;
13144
0
    return true;
13145
0
  }
13146
0
  ada_log("parse_host calling to_ascii");
13147
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
13148
0
  if (!is_valid || !host.has_value()) {
13149
0
    ada_log("parse_host to_ascii returns false");
13150
0
    return is_valid = false;
13151
0
  }
13152
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
13153
0
          " bytes]");
13154
13155
0
  if (std::any_of(host->begin(), host->end(),
13156
0
                  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
0
  if (checkers::is_ipv4(*host)) {
13164
0
    ada_log("parse_host got ipv4 ", *host);
13165
0
    return parse_ipv4(*host);
13166
0
  }
13167
13168
0
  return true;
13169
0
}
13170
13171
0
ada_really_inline void url::parse_path(std::string_view input) {
13172
0
  ada_log("parse_path ", input);
13173
0
  std::string tmp_buffer;
13174
0
  std::string_view internal_input;
13175
0
  if (unicode::has_tabs_or_newline(input)) {
13176
0
    tmp_buffer = input;
13177
    // Optimization opportunity: Instead of copying and then pruning, we could
13178
    // just directly build the string from user_input.
13179
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13180
0
    internal_input = tmp_buffer;
13181
0
  } else {
13182
0
    internal_input = input;
13183
0
  }
13184
13185
  // If url is special, then:
13186
0
  if (is_special()) {
13187
0
    if (internal_input.empty()) {
13188
0
      path = "/";
13189
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
13190
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
13191
0
    } else {
13192
0
      helpers::parse_prepared_path(internal_input, type, path);
13193
0
    }
13194
0
  } 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
0
}
13206
13207
0
[[nodiscard]] std::string url::to_string() const {
13208
0
  if (!is_valid) {
13209
0
    return "null";
13210
0
  }
13211
0
  std::string answer;
13212
0
  auto back = std::back_insert_iterator(answer);
13213
0
  answer.append("{\n");
13214
0
  answer.append("\t\"protocol\":\"");
13215
0
  helpers::encode_json(get_protocol(), back);
13216
0
  answer.append("\",\n");
13217
0
  if (has_credentials()) {
13218
0
    answer.append("\t\"username\":\"");
13219
0
    helpers::encode_json(username, back);
13220
0
    answer.append("\",\n");
13221
0
    answer.append("\t\"password\":\"");
13222
0
    helpers::encode_json(password, back);
13223
0
    answer.append("\",\n");
13224
0
  }
13225
0
  if (host.has_value()) {
13226
0
    answer.append("\t\"host\":\"");
13227
0
    helpers::encode_json(host.value(), back);
13228
0
    answer.append("\",\n");
13229
0
  }
13230
0
  if (port.has_value()) {
13231
0
    answer.append("\t\"port\":\"");
13232
0
    answer.append(std::to_string(port.value()));
13233
0
    answer.append("\",\n");
13234
0
  }
13235
0
  answer.append("\t\"path\":\"");
13236
0
  helpers::encode_json(path, back);
13237
0
  answer.append("\",\n");
13238
0
  answer.append("\t\"opaque path\":");
13239
0
  answer.append((has_opaque_path ? "true" : "false"));
13240
0
  if (has_search()) {
13241
0
    answer.append(",\n");
13242
0
    answer.append("\t\"query\":\"");
13243
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
13244
0
    helpers::encode_json(query.value(), back);
13245
0
    answer.append("\"");
13246
0
  }
13247
0
  if (hash.has_value()) {
13248
0
    answer.append(",\n");
13249
0
    answer.append("\t\"hash\":\"");
13250
0
    helpers::encode_json(hash.value(), back);
13251
0
    answer.append("\"");
13252
0
  }
13253
0
  answer.append("\n}");
13254
0
  return answer;
13255
0
}
13256
13257
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
13258
0
  if (!host.has_value()) {
13259
0
    return false;
13260
0
  }
13261
0
  return checkers::verify_dns_length(*host);
13262
0
}
13263
13264
0
[[nodiscard]] std::string url::get_origin() const {
13265
0
  if (is_special()) {
13266
    // Return a new opaque origin.
13267
0
    if (type == scheme::FILE) {
13268
0
      return "null";
13269
0
    }
13270
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
13271
0
  }
13272
13273
0
  if (non_special_scheme == "blob") {
13274
0
    if (!path.empty()) {
13275
0
      auto result = ada::parse<ada::url>(path);
13276
0
      if (result &&
13277
0
          (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
0
        return ada::helpers::concat(result->get_protocol(), "//",
13281
0
                                    result->get_host());
13282
0
      }
13283
0
    }
13284
0
  }
13285
13286
  // Return a new opaque origin.
13287
0
  return "null";
13288
0
}
13289
13290
0
[[nodiscard]] std::string url::get_protocol() const {
13291
0
  if (is_special()) {
13292
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
13293
0
  }
13294
  // We only move the 'scheme' if it is non-special.
13295
0
  return helpers::concat(non_special_scheme, ":");
13296
0
}
13297
13298
0
[[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
0
  if (!host.has_value()) {
13304
0
    return "";
13305
0
  }
13306
0
  if (port.has_value()) {
13307
0
    return host.value() + ":" + get_port();
13308
0
  }
13309
0
  return host.value();
13310
0
}
13311
13312
0
[[nodiscard]] std::string url::get_hostname() const {
13313
0
  return host.value_or("");
13314
0
}
13315
13316
0
[[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
0
  return (!query.has_value() || (query->empty())) ? "" : "?" + query.value();
13320
0
}
13321
13322
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
13323
0
  return username;
13324
0
}
13325
13326
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
13327
0
  return password;
13328
0
}
13329
13330
0
[[nodiscard]] std::string url::get_port() const {
13331
0
  return port.has_value() ? std::to_string(port.value()) : "";
13332
0
}
13333
13334
0
[[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
0
  return (!hash.has_value() || (hash->empty())) ? "" : "#" + hash.value();
13338
0
}
13339
13340
template <bool override_hostname>
13341
0
bool url::set_host_or_hostname(const std::string_view input) {
13342
0
  if (has_opaque_path) {
13343
0
    return false;
13344
0
  }
13345
13346
0
  url saved_url(*this);
13347
13348
0
  std::optional<std::string> previous_host = host;
13349
0
  std::optional<uint16_t> previous_port = port;
13350
13351
0
  size_t host_end_pos = input.find('#');
13352
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
13353
0
                                      ? host_end_pos
13354
0
                                      : input.size());
13355
0
  helpers::remove_ascii_tab_or_newline(_host);
13356
0
  std::string_view new_host(_host);
13357
13358
0
  auto check_url_size = [&]() -> bool {
13359
0
    if (get_href_size() > ada::get_max_input_length()) {
13360
0
      *this = std::move(saved_url);
13361
0
      return false;
13362
0
    }
13363
0
    return true;
13364
0
  };
Unexecuted instantiation: ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Unexecuted instantiation: ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
13365
13366
  // If url's scheme is "file", then set state to file host state, instead of
13367
  // host state.
13368
0
  if (type != ada::scheme::type::FILE) {
13369
0
    std::string_view host_view(_host.data(), _host.length());
13370
0
    auto [location, found_colon] =
13371
0
        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
0
    if (found_colon) {
13377
      // If buffer is the empty string, host-missing validation error, return
13378
      // failure.
13379
0
      std::string_view buffer = host_view.substr(0, location);
13380
0
      if (buffer.empty()) {
13381
0
        return false;
13382
0
      }
13383
13384
      // If state override is given and state override is hostname state, then
13385
      // return failure.
13386
0
      if constexpr (override_hostname) {
13387
0
        return false;
13388
0
      }
13389
13390
      // Let host be the result of host parsing buffer with url is not special.
13391
0
      bool succeeded = parse_host(buffer);
13392
0
      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
0
      std::string_view port_buffer = new_host.substr(location + 1);
13401
0
      if (!port_buffer.empty()) {
13402
0
        set_port(port_buffer);
13403
0
      }
13404
0
      return check_url_size();
13405
0
    }
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
0
    else {
13410
      // If url is special and host_view is the empty string, host-missing
13411
      // validation error, return failure.
13412
0
      if (host_view.empty() && is_special()) {
13413
0
        return false;
13414
0
      }
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
0
      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
0
      if (host_view.empty() && !is_special()) {
13426
0
        host = "";
13427
0
        return check_url_size();
13428
0
      }
13429
13430
0
      bool succeeded = parse_host(host_view);
13431
0
      if (!succeeded) {
13432
0
        host = std::move(previous_host);
13433
0
        update_base_port(previous_port);
13434
0
        return false;
13435
0
      }
13436
0
      return check_url_size();
13437
0
    }
13438
0
  }
13439
13440
0
  size_t location = new_host.find_first_of("/\\?");
13441
0
  if (location != std::string_view::npos) {
13442
0
    new_host.remove_suffix(new_host.length() - location);
13443
0
  }
13444
13445
0
  if (new_host.empty()) {
13446
    // Set url's host to the empty string.
13447
0
    host = "";
13448
0
  } else {
13449
    // Let host be the result of host parsing buffer with url is not special.
13450
0
    if (!parse_host(new_host)) {
13451
0
      host = std::move(previous_host);
13452
0
      update_base_port(previous_port);
13453
0
      return false;
13454
0
    }
13455
13456
    // If host is "localhost", then set host to the empty string.
13457
0
    if (host == "localhost") {
13458
0
      host = "";
13459
0
    }
13460
0
  }
13461
0
  return check_url_size();
13462
0
}
Unexecuted instantiation: bool ada::url::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: bool ada::url::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
13463
13464
0
bool url::set_host(const std::string_view input) {
13465
0
  return set_host_or_hostname<false>(input);
13466
0
}
13467
13468
0
bool url::set_hostname(const std::string_view input) {
13469
0
  return set_host_or_hostname<true>(input);
13470
0
}
13471
13472
0
bool url::set_username(const std::string_view input) {
13473
0
  if (cannot_have_credentials_or_port()) {
13474
0
    return false;
13475
0
  }
13476
0
  auto previous_username = std::move(username);
13477
0
  username = ada::unicode::percent_encode(
13478
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13479
0
  if (get_href_size() > ada::get_max_input_length()) {
13480
0
    username = std::move(previous_username);
13481
0
    return false;
13482
0
  }
13483
0
  return true;
13484
0
}
13485
13486
0
bool url::set_password(const std::string_view input) {
13487
0
  if (cannot_have_credentials_or_port()) {
13488
0
    return false;
13489
0
  }
13490
0
  auto previous_password = std::move(password);
13491
0
  password = ada::unicode::percent_encode(
13492
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
13493
0
  if (get_href_size() > ada::get_max_input_length()) {
13494
0
    password = std::move(previous_password);
13495
0
    return false;
13496
0
  }
13497
0
  return true;
13498
0
}
13499
13500
0
bool url::set_port(const std::string_view input) {
13501
0
  if (cannot_have_credentials_or_port()) {
13502
0
    return false;
13503
0
  }
13504
13505
0
  if (input.empty()) {
13506
0
    port = std::nullopt;
13507
0
    return true;
13508
0
  }
13509
13510
0
  std::string trimmed(input);
13511
0
  helpers::remove_ascii_tab_or_newline(trimmed);
13512
13513
0
  if (trimmed.empty()) {
13514
0
    return true;
13515
0
  }
13516
13517
  // Input should not start with a non-digit character.
13518
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
13519
0
    return false;
13520
0
  }
13521
13522
  // Find the first non-digit character to determine the length of digits
13523
0
  auto first_non_digit =
13524
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
13525
0
  std::string_view digits_to_parse =
13526
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
13527
13528
  // Revert changes if parse_port fails.
13529
0
  std::optional<uint16_t> previous_port = port;
13530
0
  parse_port(digits_to_parse);
13531
0
  if (is_valid) {
13532
0
    if (get_href_size() > ada::get_max_input_length()) {
13533
0
      port = std::move(previous_port);
13534
0
      return false;
13535
0
    }
13536
0
    return true;
13537
0
  }
13538
0
  port = std::move(previous_port);
13539
0
  is_valid = true;
13540
0
  return false;
13541
0
}
13542
13543
0
void url::set_hash(const std::string_view input) {
13544
0
  if (input.empty()) {
13545
0
    hash = std::nullopt;
13546
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13547
0
    return;
13548
0
  }
13549
13550
0
  std::string new_value;
13551
0
  new_value = input[0] == '#' ? input.substr(1) : input;
13552
0
  helpers::remove_ascii_tab_or_newline(new_value);
13553
0
  auto previous_hash = std::move(hash);
13554
0
  hash = unicode::percent_encode(new_value,
13555
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
13556
0
  if (get_href_size() > ada::get_max_input_length()) {
13557
0
    hash = std::move(previous_hash);
13558
0
  }
13559
0
}
13560
13561
0
void url::set_search(const std::string_view input) {
13562
0
  if (input.empty()) {
13563
0
    query = std::nullopt;
13564
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
13565
0
    return;
13566
0
  }
13567
13568
0
  std::string new_value;
13569
0
  new_value = input[0] == '?' ? input.substr(1) : input;
13570
0
  helpers::remove_ascii_tab_or_newline(new_value);
13571
13572
0
  auto query_percent_encode_set =
13573
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13574
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
13575
13576
0
  auto previous_query = std::move(query);
13577
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
13578
0
  if (get_href_size() > ada::get_max_input_length()) {
13579
0
    query = std::move(previous_query);
13580
0
  }
13581
0
}
13582
13583
0
bool url::set_pathname(const std::string_view input) {
13584
0
  if (has_opaque_path) {
13585
0
    return false;
13586
0
  }
13587
0
  auto previous_path = std::move(path);
13588
0
  path.clear();
13589
0
  parse_path(input);
13590
0
  if (get_href_size() > ada::get_max_input_length()) {
13591
0
    path = std::move(previous_path);
13592
0
    return false;
13593
0
  }
13594
0
  return true;
13595
0
}
13596
13597
0
bool url::set_protocol(const std::string_view input) {
13598
0
  std::string view(input);
13599
0
  helpers::remove_ascii_tab_or_newline(view);
13600
0
  if (view.empty()) {
13601
0
    return true;
13602
0
  }
13603
13604
  // Schemes should start with alpha values.
13605
0
  if (!checkers::is_alpha(view[0])) {
13606
0
    return false;
13607
0
  }
13608
13609
0
  view.append(":");
13610
13611
0
  std::string::iterator pointer =
13612
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
13613
13614
0
  if (pointer != view.end() && *pointer == ':') {
13615
0
    url saved_url(*this);
13616
0
    bool result = parse_scheme<true>(
13617
0
        std::string_view(view.data(), pointer - view.begin()));
13618
0
    if (result && get_href_size() > ada::get_max_input_length()) {
13619
0
      *this = std::move(saved_url);
13620
0
      return false;
13621
0
    }
13622
0
    return result;
13623
0
  }
13624
0
  return false;
13625
0
}
13626
13627
0
bool url::set_href(const std::string_view input) {
13628
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
13629
13630
0
  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
0
    if (out->get_href_size() > ada::get_max_input_length()) {
13634
0
      return false;
13635
0
    }
13636
0
    *this = *out;
13637
0
  }
13638
13639
0
  return out.has_value();
13640
0
}
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
45.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
45.5k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
45.5k
  constexpr bool result_type_is_ada_url_aggregator =
13662
45.5k
      std::is_same_v<url_aggregator, result_type>;
13663
45.5k
  static_assert(result_type_is_ada_url ||
13664
45.5k
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
45.5k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
45.5k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
45.5k
          ")");
13670
13671
45.5k
  state state = state::SCHEME_START;
13672
45.5k
  result_type url{};
13673
13674
45.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
45.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
45.5k
  if (base_url != nullptr) {
13686
1.59k
    url.is_valid &= base_url->is_valid;
13687
1.59k
  }
13688
45.5k
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
45.5k
  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
27.9k
    uint32_t reserve_capacity =
13704
27.9k
        (0xFFFFFFFF >>
13705
27.9k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
27.9k
        1;
13707
27.9k
    url.reserve(reserve_capacity);
13708
27.9k
  }
13709
45.5k
  std::string tmp_buffer;
13710
45.5k
  std::string_view url_data;
13711
45.5k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
1.02k
    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
1.02k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
1.02k
    url_data = tmp_buffer;
13717
44.5k
  } else [[likely]] {
13718
44.5k
    url_data = user_input;
13719
44.5k
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
45.5k
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
45.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
45.5k
  size_t input_position = 0;
13736
45.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
188k
  while (input_position <= input_size) {
13742
177k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
177k
            " in state ", ada::to_string(state));
13744
177k
    switch (state) {
13745
45.5k
      case state::SCHEME_START: {
13746
45.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
45.5k
        if ((input_position != input_size) &&
13750
44.7k
            checkers::is_alpha(url_data[input_position])) {
13751
31.7k
          state = state::SCHEME;
13752
31.7k
          input_position++;
13753
31.7k
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
13.7k
          state = state::NO_SCHEME;
13757
13.7k
        }
13758
45.5k
        break;
13759
0
      }
13760
31.7k
      case state::SCHEME: {
13761
31.7k
        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
178k
        while ((input_position != input_size) &&
13765
174k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
146k
          input_position++;
13767
146k
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
31.7k
        if ((input_position != input_size) &&
13770
27.9k
            (url_data[input_position] == ':')) {
13771
26.9k
          ada_log("SCHEME the scheme should be ",
13772
26.9k
                  url_data.substr(0, input_position));
13773
26.9k
          if constexpr (result_type_is_ada_url) {
13774
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13775
0
              return url;
13776
0
            }
13777
26.9k
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
26.9k
            if (!url.parse_scheme_with_colon(
13780
26.9k
                    url_data.substr(0, input_position + 1))) {
13781
0
              return url;
13782
0
            }
13783
26.9k
          }
13784
26.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
26.9k
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
3.62k
            state = state::FILE;
13791
3.62k
          }
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
23.3k
          else if (url.is_special() && base_url != nullptr &&
13796
314
                   base_url->type == url.type) {
13797
            // Set state to special relative or authority state.
13798
4
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13799
4
          }
13800
          // Otherwise, if url is special, set state to special authority
13801
          // slashes state.
13802
23.3k
          else if (url.is_special()) {
13803
13.4k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
13.4k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
9.88k
          else if (input_position + 1 < input_size &&
13808
7.90k
                   url_data[input_position + 1] == '/') {
13809
3.89k
            state = state::PATH_OR_AUTHORITY;
13810
3.89k
            input_position++;
13811
3.89k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
5.99k
          else {
13815
5.99k
            state = state::OPAQUE_PATH;
13816
5.99k
          }
13817
26.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
4.80k
        else {
13822
4.80k
          state = state::NO_SCHEME;
13823
4.80k
          input_position = 0;
13824
4.80k
          break;
13825
4.80k
        }
13826
26.9k
        input_position++;
13827
26.9k
        break;
13828
31.7k
      }
13829
18.5k
      case state::NO_SCHEME: {
13830
18.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
18.5k
        if (base_url == nullptr ||
13834
18.2k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
18.2k
          ada_log("NO_SCHEME validation error");
13836
18.2k
          url.is_valid = false;
13837
18.2k
          return url;
13838
18.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
354
        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
0
          if constexpr (result_type_is_ada_url) {
13849
0
            url.path = base_url->path;
13850
0
            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
354
        else if (base_url->type != scheme::type::FILE) {
13868
348
          ada_log("NO_SCHEME non-file relative path");
13869
348
          state = state::RELATIVE_SCHEME;
13870
348
        }
13871
        // Otherwise, set state to file state and decrease pointer by 1.
13872
6
        else {
13873
6
          ada_log("NO_SCHEME file base type");
13874
6
          state = state::FILE;
13875
6
        }
13876
354
        break;
13877
18.5k
      }
13878
15.4k
      case state::AUTHORITY: {
13879
15.4k
        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
15.4k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
12.1k
          state = state::HOST;
13892
12.1k
          break;
13893
12.1k
        }
13894
3.35k
        bool at_sign_seen{false};
13895
3.35k
        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
11.7k
        do {
13902
11.7k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
11.7k
          size_t location =
13905
11.7k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
11.7k
                               : helpers::find_authority_delimiter(view);
13907
11.7k
          std::string_view authority_view = view.substr(0, location);
13908
11.7k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
11.7k
          if ((end_of_authority != input_size) &&
13911
11.2k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
8.43k
            if (at_sign_seen) {
13914
5.12k
              if (password_token_seen) {
13915
1.89k
                if constexpr (result_type_is_ada_url) {
13916
0
                  url.password += "%40";
13917
1.89k
                } else {
13918
1.89k
                  url.append_base_password("%40");
13919
1.89k
                }
13920
3.22k
              } else {
13921
3.22k
                if constexpr (result_type_is_ada_url) {
13922
0
                  url.username += "%40";
13923
3.22k
                } else {
13924
3.22k
                  url.append_base_username("%40");
13925
3.22k
                }
13926
3.22k
              }
13927
5.12k
            }
13928
13929
8.43k
            at_sign_seen = true;
13930
13931
8.43k
            if (!password_token_seen) {
13932
6.54k
              size_t password_token_location = authority_view.find(':');
13933
6.54k
              password_token_seen =
13934
6.54k
                  password_token_location != std::string_view::npos;
13935
13936
6.54k
              if constexpr (store_values) {
13937
4.74k
                if (!password_token_seen) {
13938
1.91k
                  if constexpr (result_type_is_ada_url) {
13939
0
                    url.username += unicode::percent_encode(
13940
0
                        authority_view,
13941
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13942
1.91k
                  } else {
13943
1.91k
                    url.append_base_username(unicode::percent_encode(
13944
1.91k
                        authority_view,
13945
1.91k
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
1.91k
                  }
13947
2.83k
                } else {
13948
2.83k
                  if constexpr (result_type_is_ada_url) {
13949
0
                    url.username += unicode::percent_encode(
13950
0
                        authority_view.substr(0, password_token_location),
13951
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13952
0
                    url.password += unicode::percent_encode(
13953
0
                        authority_view.substr(password_token_location + 1),
13954
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13955
2.83k
                  } else {
13956
2.83k
                    url.append_base_username(unicode::percent_encode(
13957
2.83k
                        authority_view.substr(0, password_token_location),
13958
2.83k
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
2.83k
                    url.append_base_password(unicode::percent_encode(
13960
2.83k
                        authority_view.substr(password_token_location + 1),
13961
2.83k
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
2.83k
                  }
13963
2.83k
                }
13964
4.74k
              }
13965
6.54k
            } else if constexpr (store_values) {
13966
997
              if constexpr (result_type_is_ada_url) {
13967
0
                url.password += unicode::percent_encode(
13968
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13969
997
              } else {
13970
997
                url.append_base_password(unicode::percent_encode(
13971
997
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
997
              }
13973
997
            }
13974
8.43k
          }
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
3.35k
          else if (end_of_authority == input_size ||
13979
2.78k
                   url_data[end_of_authority] == '/' ||
13980
14
                   url_data[end_of_authority] == '?' ||
13981
3.35k
                   (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
3.35k
            if (at_sign_seen && authority_view.empty()) {
13985
248
              url.is_valid = false;
13986
248
              return url;
13987
248
            }
13988
3.10k
            state = state::HOST;
13989
3.10k
            break;
13990
3.35k
          }
13991
8.43k
          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
8.43k
          input_position = end_of_authority + 1;
14000
8.43k
        } while (true);
14001
14002
3.10k
        break;
14003
3.35k
      }
14004
3.10k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
14005
4
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
14006
4
                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
4
        if (url_data.substr(input_position, 2) == "//") {
14012
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
14013
0
          input_position += 2;
14014
4
        } else {
14015
          // Otherwise, validation error, set state to relative state and
14016
          // decrease pointer by 1.
14017
4
          state = state::RELATIVE_SCHEME;
14018
4
        }
14019
14020
4
        break;
14021
3.35k
      }
14022
3.89k
      case state::PATH_OR_AUTHORITY: {
14023
3.89k
        ada_log("PATH_OR_AUTHORITY ",
14024
3.89k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
3.89k
        if ((input_position != input_size) &&
14028
3.25k
            (url_data[input_position] == '/')) {
14029
2.04k
          state = state::AUTHORITY;
14030
2.04k
          input_position++;
14031
2.04k
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
1.85k
          state = state::PATH;
14034
1.85k
        }
14035
14036
3.89k
        break;
14037
3.35k
      }
14038
352
      case state::RELATIVE_SCHEME: {
14039
352
        ada_log("RELATIVE_SCHEME ",
14040
352
                helpers::substring(url_data, input_position));
14041
14042
        // Set url's scheme to base's scheme.
14043
352
        url.copy_scheme(*base_url);
14044
14045
        // If c is U+002F (/), then set state to relative slash state.
14046
352
        if ((input_position != input_size) &&
14047
            // NOLINTNEXTLINE(bugprone-branch-clone)
14048
140
            (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
352
        } else if (url.is_special() && (input_position != input_size) &&
14054
4
                   (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
352
        } else {
14062
352
          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
352
          if constexpr (result_type_is_ada_url) {
14068
0
            url.username = base_url->username;
14069
0
            url.password = base_url->password;
14070
0
            url.host = base_url->host;
14071
0
            url.port = base_url->port;
14072
            // cloning the base path includes cloning the has_opaque_path flag
14073
0
            url.has_opaque_path = base_url->has_opaque_path;
14074
0
            url.path = base_url->path;
14075
0
            url.query = base_url->query;
14076
352
          } else {
14077
352
            url.update_base_authority(base_url->get_href(),
14078
352
                                      base_url->get_components());
14079
352
            url.update_host_to_base_host(base_url->get_hostname());
14080
352
            url.update_base_port(base_url->retrieve_base_port());
14081
            // cloning the base path includes cloning the has_opaque_path flag
14082
352
            url.has_opaque_path = base_url->has_opaque_path;
14083
352
            url.update_base_pathname(base_url->get_pathname());
14084
352
            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
5
              auto s = base_url->get_search();
14089
5
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
5
            }
14091
352
          }
14092
14093
352
          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
352
          if ((input_position != input_size) &&
14098
140
              (url_data[input_position] == '?')) {
14099
0
            state = state::QUERY;
14100
0
          }
14101
          // Otherwise, if c is not the EOF code point:
14102
352
          else if (input_position != input_size) {
14103
            // Set url's query to null.
14104
140
            url.clear_search();
14105
140
            if constexpr (result_type_is_ada_url) {
14106
              // Shorten url's path.
14107
0
              helpers::shorten_path(url.path, url.type);
14108
140
            } else {
14109
140
              std::string_view path = url.get_pathname();
14110
140
              if (helpers::shorten_path(path, url.type)) {
14111
60
                url.update_base_pathname(std::move(std::string(path)));
14112
60
              }
14113
140
            }
14114
            // Set state to path state and decrease pointer by 1.
14115
140
            state = state::PATH;
14116
140
            break;
14117
140
          }
14118
352
        }
14119
212
        input_position++;
14120
212
        break;
14121
352
      }
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
0
          if constexpr (result_type_is_ada_url) {
14147
0
            url.username = base_url->username;
14148
0
            url.password = base_url->password;
14149
0
            url.host = base_url->host;
14150
0
            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
13.4k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
13.4k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
13.4k
                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
13.4k
        if (url_data.substr(input_position, 2) == "//") {
14172
1.95k
          input_position += 2;
14173
1.95k
        }
14174
14175
13.4k
        [[fallthrough]];
14176
13.4k
      }
14177
13.4k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
13.4k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
13.4k
                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
14.3k
        while ((input_position != input_size) &&
14184
12.2k
               ((url_data[input_position] == '/') ||
14185
11.7k
                (url_data[input_position] == '\\'))) {
14186
942
          input_position++;
14187
942
        }
14188
13.4k
        state = state::AUTHORITY;
14189
14190
13.4k
        break;
14191
13.4k
      }
14192
303
      case state::QUERY: {
14193
303
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
303
        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
303
          const uint8_t* query_percent_encode_set =
14198
303
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
303
                               : 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
303
          url.update_base_search(url_data.substr(input_position),
14204
303
                                 query_percent_encode_set);
14205
303
          ada_log("QUERY update_base_search completed ");
14206
303
          if (fragment.has_value()) {
14207
13
            url.update_unencoded_base_hash(*fragment);
14208
13
          }
14209
303
        }
14210
303
        return url;
14211
13.4k
      }
14212
15.2k
      case state::HOST: {
14213
15.2k
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
15.2k
        std::string_view host_view = url_data.substr(input_position);
14216
15.2k
        auto [location, found_colon] =
14217
15.2k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
15.2k
        input_position = (location != std::string_view::npos)
14219
15.2k
                             ? input_position + location
14220
15.2k
                             : 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
15.2k
        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
520
          ada_log("HOST parsing ", host_view);
14229
520
          if (!url.parse_host(host_view)) {
14230
109
            return url;
14231
109
          }
14232
411
          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
411
          state = state::PORT;
14236
411
          input_position++;
14237
411
        }
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
14.7k
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
14.7k
          if (host_view.empty() && url.is_special()) {
14247
2.13k
            url.is_valid = false;
14248
2.13k
            return url;
14249
2.13k
          }
14250
12.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
12.5k
          if (host_view.empty()) {
14254
224
            url.update_base_hostname("");
14255
12.3k
          } else if (!url.parse_host(host_view)) {
14256
3.04k
            return url;
14257
3.04k
          }
14258
9.55k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
9.55k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
9.55k
          state = state::PATH_START;
14263
9.55k
        }
14264
14265
9.96k
        break;
14266
15.2k
      }
14267
9.96k
      case state::OPAQUE_PATH: {
14268
5.99k
        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
5.99k
        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
5.99k
        size_t location = view.find('?');
14284
5.99k
        if (location != std::string_view::npos) {
14285
43
          view.remove_suffix(view.size() - location);
14286
43
          state = state::QUERY;
14287
43
          input_position += location + 1;
14288
5.94k
        } else {
14289
5.94k
          input_position = input_size + 1;
14290
5.94k
        }
14291
5.99k
        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
5.99k
        if (view.ends_with(' ')) {
14296
2
          std::string modified_view =
14297
2
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
2
          url.update_base_pathname(unicode::percent_encode(
14299
2
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
5.99k
        } else {
14301
5.99k
          url.update_base_pathname(unicode::percent_encode(
14302
5.99k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
5.99k
        }
14304
5.99k
        break;
14305
15.2k
      }
14306
411
      case state::PORT: {
14307
411
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
411
        std::string_view port_view = url_data.substr(input_position);
14309
411
        input_position += url.parse_port(port_view, true);
14310
411
        if (!url.is_valid) {
14311
51
          return url;
14312
51
        }
14313
360
        state = state::PATH_START;
14314
360
        [[fallthrough]];
14315
360
      }
14316
11.2k
      case state::PATH_START: {
14317
11.2k
        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
11.2k
        if constexpr (!store_values) {
14323
2.61k
          return url;
14324
2.61k
        }
14325
14326
        // If url is special, then:
14327
11.2k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
7.17k
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
7.17k
          if (input_position == input_size) {
14334
3.72k
            if constexpr (store_values) {
14335
3.72k
              url.update_base_pathname("/");
14336
3.72k
              if (fragment.has_value()) {
14337
8
                url.update_unencoded_base_hash(*fragment);
14338
8
              }
14339
3.72k
            }
14340
3.72k
            return url;
14341
3.72k
          }
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
3.44k
          if ((url_data[input_position] != '/') &&
14346
112
              (url_data[input_position] != '\\')) {
14347
69
            break;
14348
69
          }
14349
3.44k
        }
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
4.05k
        else if ((input_position != input_size) &&
14353
908
                 (url_data[input_position] == '?')) {
14354
27
          state = state::QUERY;
14355
27
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
4.02k
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
881
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
881
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
881
        }
14366
14367
7.43k
        input_position++;
14368
7.43k
        break;
14369
11.2k
      }
14370
8.39k
      case state::PATH: {
14371
8.39k
        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
8.39k
        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
8.39k
        size_t locofquestionmark = view.find('?');
14384
8.39k
        if (locofquestionmark != std::string_view::npos) {
14385
233
          state = state::QUERY;
14386
233
          view.remove_suffix(view.size() - locofquestionmark);
14387
233
          input_position += locofquestionmark + 1;
14388
8.16k
        } else {
14389
8.16k
          input_position = input_size + 1;
14390
8.16k
        }
14391
8.39k
        if constexpr (store_values) {
14392
6.97k
          if constexpr (result_type_is_ada_url) {
14393
0
            helpers::parse_prepared_path(view, url.type, url.path);
14394
6.97k
          } else {
14395
6.97k
            url.consume_prepared_path(view);
14396
6.97k
            ADA_ASSERT_TRUE(url.validate());
14397
6.97k
          }
14398
6.97k
        }
14399
8.39k
        break;
14400
11.2k
      }
14401
1.73k
      case state::FILE_SLASH: {
14402
1.73k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
1.73k
        if ((input_position != input_size) &&
14406
1.61k
            (url_data[input_position] == '/' ||
14407
1.55k
             url_data[input_position] == '\\')) {
14408
1.55k
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
1.55k
          state = state::FILE_HOST;
14411
1.55k
          input_position++;
14412
1.55k
        } else {
14413
182
          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
182
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
14418
            // Set url's host to base's host.
14419
0
            if constexpr (result_type_is_ada_url) {
14420
0
              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
0
                  if constexpr (result_type_is_ada_url) {
14440
0
                    url.path += '/';
14441
0
                    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
182
          state = state::PATH;
14453
182
        }
14454
14455
1.73k
        break;
14456
11.2k
      }
14457
1.55k
      case state::FILE_HOST: {
14458
1.55k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
1.55k
        std::string_view view = url_data.substr(input_position);
14460
14461
1.55k
        size_t location = view.find_first_of("/\\?");
14462
1.55k
        std::string_view file_host_buffer = view.substr(
14463
1.55k
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
1.55k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
0
          state = state::PATH;
14467
1.55k
        } else if (file_host_buffer.empty()) {
14468
          // Set url's host to the empty string.
14469
741
          if constexpr (result_type_is_ada_url) {
14470
0
            url.host = "";
14471
741
          } else {
14472
741
            url.update_base_hostname("");
14473
741
          }
14474
          // Set state to path start state.
14475
741
          state = state::PATH_START;
14476
811
        } else {
14477
811
          size_t consumed_bytes = file_host_buffer.size();
14478
811
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
811
          if (!url.parse_host(file_host_buffer)) {
14482
239
            return url;
14483
239
          }
14484
14485
572
          if constexpr (result_type_is_ada_url) {
14486
            // If host is "localhost", then set host to the empty string.
14487
0
            if (url.host.has_value() && url.host.value() == "localhost") {
14488
0
              url.host = "";
14489
0
            }
14490
572
          } else {
14491
572
            if (url.get_hostname() == "localhost") {
14492
0
              url.update_base_hostname("");
14493
0
            }
14494
572
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
572
          state = state::PATH_START;
14498
572
        }
14499
14500
1.31k
        break;
14501
1.55k
      }
14502
3.63k
      case state::FILE: {
14503
3.63k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
3.63k
        std::string_view file_view = url_data.substr(input_position);
14505
14506
3.63k
        url.set_protocol_as_file();
14507
3.63k
        if constexpr (result_type_is_ada_url) {
14508
          // Set url's host to the empty string.
14509
0
          url.host = "";
14510
3.63k
        } else {
14511
3.63k
          url.update_base_hostname("");
14512
3.63k
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
3.63k
        if (input_position != input_size &&
14515
3.15k
            (url_data[input_position] == '/' ||
14516
1.73k
             url_data[input_position] == '\\')) {
14517
1.73k
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
1.73k
          state = state::FILE_SLASH;
14520
1.73k
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
1.90k
        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
14
          ada_log("FILE base non-null");
14526
14
          if constexpr (result_type_is_ada_url) {
14527
0
            url.host = base_url->host;
14528
0
            url.path = base_url->path;
14529
0
            url.query = base_url->query;
14530
14
          } else {
14531
14
            url.update_host_to_base_host(base_url->get_hostname());
14532
14
            url.update_base_pathname(base_url->get_pathname());
14533
14
            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
1
              auto s = base_url->get_search();
14538
1
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
1
            }
14540
14
          }
14541
14
          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
14
          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
14
          else if (input_position != input_size) {
14550
            // Set url's query to null.
14551
10
            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
10
            if (!checkers::is_windows_drive_letter(file_view)) {
14555
10
              if constexpr (result_type_is_ada_url) {
14556
0
                helpers::shorten_path(url.path, url.type);
14557
10
              } else {
14558
10
                std::string_view path = url.get_pathname();
14559
10
                if (helpers::shorten_path(path, url.type)) {
14560
5
                  url.update_base_pathname(std::move(std::string(path)));
14561
5
                }
14562
10
              }
14563
10
            }
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
10
            state = state::PATH;
14573
10
            break;
14574
10
          }
14575
14
        }
14576
        // Otherwise, set state to path state, and decrease pointer by 1.
14577
1.88k
        else {
14578
1.88k
          ada_log("FILE go to path");
14579
1.88k
          state = state::PATH;
14580
1.88k
          break;
14581
1.88k
        }
14582
14583
1.73k
        input_position++;
14584
1.73k
        break;
14585
3.63k
      }
14586
0
      default:
14587
0
        unreachable();
14588
177k
    }
14589
177k
  }
14590
11.5k
  if constexpr (store_values) {
14591
11.4k
    if (fragment.has_value()) {
14592
76
      url.update_unencoded_base_hash(*fragment);
14593
76
    }
14594
11.4k
  }
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
11.5k
  if constexpr (store_values) {
14599
11.4k
    if (url.is_valid) {
14600
11.4k
      if constexpr (result_type_is_ada_url_aggregator) {
14601
11.4k
        if (url.buffer.size() > max_input_length) {
14602
0
          url.is_valid = false;
14603
0
        }
14604
11.4k
      } else {
14605
0
        if (url.get_href_size() > max_input_length) {
14606
0
          url.is_valid = false;
14607
0
        }
14608
0
      }
14609
11.4k
    }
14610
11.4k
  }
14611
11.5k
  return url;
14612
45.5k
}
Unexecuted instantiation: ada::url ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)
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
27.9k
                           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
27.9k
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
13661
27.9k
  constexpr bool result_type_is_ada_url_aggregator =
13662
27.9k
      std::is_same_v<url_aggregator, result_type>;
13663
27.9k
  static_assert(result_type_is_ada_url ||
13664
27.9k
                result_type_is_ada_url_aggregator);  // We don't support
13665
                                                     // anything else for now.
13666
13667
27.9k
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
13668
27.9k
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
13669
27.9k
          ")");
13670
13671
27.9k
  state state = state::SCHEME_START;
13672
27.9k
  result_type url{};
13673
13674
27.9k
  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
27.9k
  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
27.9k
  if (base_url != nullptr) {
13686
799
    url.is_valid &= base_url->is_valid;
13687
799
  }
13688
27.9k
  if (!url.is_valid) {
13689
0
    return url;
13690
0
  }
13691
27.9k
  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
27.9k
    uint32_t reserve_capacity =
13704
27.9k
        (0xFFFFFFFF >>
13705
27.9k
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
13706
27.9k
        1;
13707
27.9k
    url.reserve(reserve_capacity);
13708
27.9k
  }
13709
27.9k
  std::string tmp_buffer;
13710
27.9k
  std::string_view url_data;
13711
27.9k
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
13712
603
    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
603
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
13716
603
    url_data = tmp_buffer;
13717
27.3k
  } else [[likely]] {
13718
27.3k
    url_data = user_input;
13719
27.3k
  }
13720
13721
  // Leading and trailing control characters are uncommon and easy to deal with
13722
  // (no performance concern).
13723
27.9k
  helpers::trim_c0_whitespace(url_data);
13724
13725
  // Optimization opportunity. Most websites do not have fragment.
13726
27.9k
  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
27.9k
  size_t input_position = 0;
13736
27.9k
  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
127k
  while (input_position <= input_size) {
13742
116k
    ada_log("In parsing at ", input_position, " out of ", input_size,
13743
116k
            " in state ", ada::to_string(state));
13744
116k
    switch (state) {
13745
27.9k
      case state::SCHEME_START: {
13746
27.9k
        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
27.9k
        if ((input_position != input_size) &&
13750
27.4k
            checkers::is_alpha(url_data[input_position])) {
13751
20.9k
          state = state::SCHEME;
13752
20.9k
          input_position++;
13753
20.9k
        } else {
13754
          // Otherwise, if state override is not given, set state to no scheme
13755
          // state and decrease pointer by 1.
13756
7.01k
          state = state::NO_SCHEME;
13757
7.01k
        }
13758
27.9k
        break;
13759
0
      }
13760
20.9k
      case state::SCHEME: {
13761
20.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
101k
        while ((input_position != input_size) &&
13765
99.7k
               (unicode::is_alnum_plus(url_data[input_position]))) {
13766
80.8k
          input_position++;
13767
80.8k
        }
13768
        // Otherwise, if c is U+003A (:), then:
13769
20.9k
        if ((input_position != input_size) &&
13770
18.8k
            (url_data[input_position] == ':')) {
13771
18.3k
          ada_log("SCHEME the scheme should be ",
13772
18.3k
                  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
18.3k
          } else {
13778
            // we pass the colon along instead of painfully adding it back.
13779
18.3k
            if (!url.parse_scheme_with_colon(
13780
18.3k
                    url_data.substr(0, input_position + 1))) {
13781
0
              return url;
13782
0
            }
13783
18.3k
          }
13784
18.3k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13785
13786
          // If url's scheme is "file", then:
13787
          // NOLINTNEXTLINE(bugprone-branch-clone)
13788
18.3k
          if (url.type == scheme::type::FILE) {
13789
            // Set state to file state.
13790
2.65k
            state = state::FILE;
13791
2.65k
          }
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
15.7k
          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
15.7k
          else if (url.is_special()) {
13803
8.80k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13804
8.80k
          }
13805
          // Otherwise, if remaining starts with an U+002F (/), set state to
13806
          // path or authority state and increase pointer by 1.
13807
6.93k
          else if (input_position + 1 < input_size &&
13808
5.57k
                   url_data[input_position + 1] == '/') {
13809
2.79k
            state = state::PATH_OR_AUTHORITY;
13810
2.79k
            input_position++;
13811
2.79k
          }
13812
          // Otherwise, set url's path to the empty string and set state to
13813
          // opaque path state.
13814
4.14k
          else {
13815
4.14k
            state = state::OPAQUE_PATH;
13816
4.14k
          }
13817
18.3k
        }
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.56k
        else {
13822
2.56k
          state = state::NO_SCHEME;
13823
2.56k
          input_position = 0;
13824
2.56k
          break;
13825
2.56k
        }
13826
18.3k
        input_position++;
13827
18.3k
        break;
13828
20.9k
      }
13829
9.58k
      case state::NO_SCHEME: {
13830
9.58k
        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
9.58k
        if (base_url == nullptr ||
13834
9.41k
            (base_url->has_opaque_path && !fragment.has_value())) {
13835
9.41k
          ada_log("NO_SCHEME validation error");
13836
9.41k
          url.is_valid = false;
13837
9.41k
          return url;
13838
9.41k
        }
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
9.58k
      }
13878
10.3k
      case state::AUTHORITY: {
13879
10.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
10.3k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13891
7.31k
          state = state::HOST;
13892
7.31k
          break;
13893
7.31k
        }
13894
3.08k
        bool at_sign_seen{false};
13895
3.08k
        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
8.82k
        do {
13902
8.82k
          std::string_view view = url_data.substr(input_position);
13903
          // The delimiters are @, /, ? \\.
13904
8.82k
          size_t location =
13905
8.82k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13906
8.82k
                               : helpers::find_authority_delimiter(view);
13907
8.82k
          std::string_view authority_view = view.substr(0, location);
13908
8.82k
          size_t end_of_authority = input_position + authority_view.size();
13909
          // If c is U+0040 (@), then:
13910
8.82k
          if ((end_of_authority != input_size) &&
13911
8.49k
              (url_data[end_of_authority] == '@')) {
13912
            // If atSignSeen is true, then prepend "%40" to buffer.
13913
5.74k
            if (at_sign_seen) {
13914
2.68k
              if (password_token_seen) {
13915
                if constexpr (result_type_is_ada_url) {
13916
                  url.password += "%40";
13917
997
                } else {
13918
997
                  url.append_base_password("%40");
13919
997
                }
13920
1.68k
              } else {
13921
                if constexpr (result_type_is_ada_url) {
13922
                  url.username += "%40";
13923
1.68k
                } else {
13924
1.68k
                  url.append_base_username("%40");
13925
1.68k
                }
13926
1.68k
              }
13927
2.68k
            }
13928
13929
5.74k
            at_sign_seen = true;
13930
13931
5.74k
            if (!password_token_seen) {
13932
4.74k
              size_t password_token_location = authority_view.find(':');
13933
4.74k
              password_token_seen =
13934
4.74k
                  password_token_location != std::string_view::npos;
13935
13936
4.74k
              if constexpr (store_values) {
13937
4.74k
                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
1.91k
                  } else {
13943
1.91k
                    url.append_base_username(unicode::percent_encode(
13944
1.91k
                        authority_view,
13945
1.91k
                        character_sets::USERINFO_PERCENT_ENCODE));
13946
1.91k
                  }
13947
2.83k
                } 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
2.83k
                  } else {
13956
2.83k
                    url.append_base_username(unicode::percent_encode(
13957
2.83k
                        authority_view.substr(0, password_token_location),
13958
2.83k
                        character_sets::USERINFO_PERCENT_ENCODE));
13959
2.83k
                    url.append_base_password(unicode::percent_encode(
13960
2.83k
                        authority_view.substr(password_token_location + 1),
13961
2.83k
                        character_sets::USERINFO_PERCENT_ENCODE));
13962
2.83k
                  }
13963
2.83k
                }
13964
4.74k
              }
13965
4.74k
            } 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
997
              } else {
13970
997
                url.append_base_password(unicode::percent_encode(
13971
997
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13972
997
              }
13973
997
            }
13974
5.74k
          }
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
3.08k
          else if (end_of_authority == input_size ||
13979
2.75k
                   url_data[end_of_authority] == '/' ||
13980
9
                   url_data[end_of_authority] == '?' ||
13981
3.08k
                   (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
3.08k
            if (at_sign_seen && authority_view.empty()) {
13985
126
              url.is_valid = false;
13986
126
              return url;
13987
126
            }
13988
2.95k
            state = state::HOST;
13989
2.95k
            break;
13990
3.08k
          }
13991
5.74k
          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
5.74k
          input_position = end_of_authority + 1;
14000
5.74k
        } while (true);
14001
14002
2.95k
        break;
14003
3.08k
      }
14004
2.95k
      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
3.08k
      }
14022
2.79k
      case state::PATH_OR_AUTHORITY: {
14023
2.79k
        ada_log("PATH_OR_AUTHORITY ",
14024
2.79k
                helpers::substring(url_data, input_position));
14025
14026
        // If c is U+002F (/), then set state to authority state.
14027
2.79k
        if ((input_position != input_size) &&
14028
2.37k
            (url_data[input_position] == '/')) {
14029
1.58k
          state = state::AUTHORITY;
14030
1.58k
          input_position++;
14031
1.58k
        } else {
14032
          // Otherwise, set state to path state, and decrease pointer by 1.
14033
1.20k
          state = state::PATH;
14034
1.20k
        }
14035
14036
2.79k
        break;
14037
3.08k
      }
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
5
              auto s = base_url->get_search();
14089
5
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14090
5
            }
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
60
                url.update_base_pathname(std::move(std::string(path)));
14112
60
              }
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
8.80k
      case state::SPECIAL_AUTHORITY_SLASHES: {
14165
8.80k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
14166
8.80k
                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
8.80k
        if (url_data.substr(input_position, 2) == "//") {
14172
1.94k
          input_position += 2;
14173
1.94k
        }
14174
14175
8.80k
        [[fallthrough]];
14176
8.80k
      }
14177
8.80k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
14178
8.80k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
14179
8.80k
                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
9.31k
        while ((input_position != input_size) &&
14184
8.22k
               ((url_data[input_position] == '/') ||
14185
7.91k
                (url_data[input_position] == '\\'))) {
14186
514
          input_position++;
14187
514
        }
14188
8.80k
        state = state::AUTHORITY;
14189
14190
8.80k
        break;
14191
8.80k
      }
14192
303
      case state::QUERY: {
14193
303
        ada_log("QUERY ", helpers::substring(url_data, input_position));
14194
303
        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
303
          const uint8_t* query_percent_encode_set =
14198
303
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14199
303
                               : 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
303
          url.update_base_search(url_data.substr(input_position),
14204
303
                                 query_percent_encode_set);
14205
303
          ada_log("QUERY update_base_search completed ");
14206
303
          if (fragment.has_value()) {
14207
13
            url.update_unencoded_base_hash(*fragment);
14208
13
          }
14209
303
        }
14210
303
        return url;
14211
8.80k
      }
14212
10.2k
      case state::HOST: {
14213
10.2k
        ada_log("HOST ", helpers::substring(url_data, input_position));
14214
14215
10.2k
        std::string_view host_view = url_data.substr(input_position);
14216
10.2k
        auto [location, found_colon] =
14217
10.2k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
14218
10.2k
        input_position = (location != std::string_view::npos)
14219
10.2k
                             ? input_position + location
14220
10.2k
                             : 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
10.2k
        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
324
          ada_log("HOST parsing ", host_view);
14229
324
          if (!url.parse_host(host_view)) {
14230
56
            return url;
14231
56
          }
14232
268
          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
268
          state = state::PORT;
14236
268
          input_position++;
14237
268
        }
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
9.94k
        else {
14244
          // If url is special and host_view is the empty string, validation
14245
          // error, return failure.
14246
9.94k
          if (host_view.empty() && url.is_special()) {
14247
1.09k
            url.is_valid = false;
14248
1.09k
            return url;
14249
1.09k
          }
14250
8.85k
          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
8.85k
          if (host_view.empty()) {
14254
142
            url.update_base_hostname("");
14255
8.71k
          } else if (!url.parse_host(host_view)) {
14256
1.63k
            return url;
14257
1.63k
          }
14258
7.22k
          ada_log("HOST parsing results in ", url.get_hostname(),
14259
7.22k
                  " href=", url.get_href());
14260
14261
          // Set url's host to host, and state to path start state.
14262
7.22k
          state = state::PATH_START;
14263
7.22k
        }
14264
14265
7.49k
        break;
14266
10.2k
      }
14267
7.49k
      case state::OPAQUE_PATH: {
14268
4.14k
        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.14k
        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.14k
        size_t location = view.find('?');
14284
4.14k
        if (location != std::string_view::npos) {
14285
43
          view.remove_suffix(view.size() - location);
14286
43
          state = state::QUERY;
14287
43
          input_position += location + 1;
14288
4.10k
        } else {
14289
4.10k
          input_position = input_size + 1;
14290
4.10k
        }
14291
4.14k
        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.14k
        if (view.ends_with(' ')) {
14296
2
          std::string modified_view =
14297
2
              std::string(view.substr(0, view.size() - 1)) + "%20";
14298
2
          url.update_base_pathname(unicode::percent_encode(
14299
2
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14300
4.14k
        } else {
14301
4.14k
          url.update_base_pathname(unicode::percent_encode(
14302
4.14k
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
14303
4.14k
        }
14304
4.14k
        break;
14305
10.2k
      }
14306
268
      case state::PORT: {
14307
268
        ada_log("PORT ", helpers::substring(url_data, input_position));
14308
268
        std::string_view port_view = url_data.substr(input_position);
14309
268
        input_position += url.parse_port(port_view, true);
14310
268
        if (!url.is_valid) {
14311
30
          return url;
14312
30
        }
14313
238
        state = state::PATH_START;
14314
238
        [[fallthrough]];
14315
238
      }
14316
8.60k
      case state::PATH_START: {
14317
8.60k
        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
8.60k
        if (url.is_special()) {
14328
          // Set state to path state.
14329
7.17k
          state = state::PATH;
14330
14331
          // Optimization: Avoiding going into PATH state improves the
14332
          // performance of urls ending with /.
14333
7.17k
          if (input_position == input_size) {
14334
3.72k
            if constexpr (store_values) {
14335
3.72k
              url.update_base_pathname("/");
14336
3.72k
              if (fragment.has_value()) {
14337
8
                url.update_unencoded_base_hash(*fragment);
14338
8
              }
14339
3.72k
            }
14340
3.72k
            return url;
14341
3.72k
          }
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
3.44k
          if ((url_data[input_position] != '/') &&
14346
112
              (url_data[input_position] != '\\')) {
14347
69
            break;
14348
69
          }
14349
3.44k
        }
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
1.43k
        else if ((input_position != input_size) &&
14353
908
                 (url_data[input_position] == '?')) {
14354
27
          state = state::QUERY;
14355
27
        }
14356
        // Otherwise, if c is not the EOF code point:
14357
1.41k
        else if (input_position != input_size) {
14358
          // Set state to path state.
14359
881
          state = state::PATH;
14360
14361
          // If c is not U+002F (/), then decrease pointer by 1.
14362
881
          if (url_data[input_position] != '/') {
14363
0
            break;
14364
0
          }
14365
881
        }
14366
14367
4.81k
        input_position++;
14368
4.81k
        break;
14369
8.60k
      }
14370
6.97k
      case state::PATH: {
14371
6.97k
        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
6.97k
        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
6.97k
        size_t locofquestionmark = view.find('?');
14384
6.97k
        if (locofquestionmark != std::string_view::npos) {
14385
233
          state = state::QUERY;
14386
233
          view.remove_suffix(view.size() - locofquestionmark);
14387
233
          input_position += locofquestionmark + 1;
14388
6.74k
        } else {
14389
6.74k
          input_position = input_size + 1;
14390
6.74k
        }
14391
6.97k
        if constexpr (store_values) {
14392
          if constexpr (result_type_is_ada_url) {
14393
            helpers::parse_prepared_path(view, url.type, url.path);
14394
6.97k
          } else {
14395
6.97k
            url.consume_prepared_path(view);
14396
6.97k
            ADA_ASSERT_TRUE(url.validate());
14397
6.97k
          }
14398
6.97k
        }
14399
6.97k
        break;
14400
8.60k
      }
14401
1.39k
      case state::FILE_SLASH: {
14402
1.39k
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
14403
14404
        // If c is U+002F (/) or U+005C (\), then:
14405
1.39k
        if ((input_position != input_size) &&
14406
1.32k
            (url_data[input_position] == '/' ||
14407
1.27k
             url_data[input_position] == '\\')) {
14408
1.27k
          ada_log("FILE_SLASH c is U+002F or U+005C");
14409
          // Set state to file host state.
14410
1.27k
          state = state::FILE_HOST;
14411
1.27k
          input_position++;
14412
1.27k
        } else {
14413
123
          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
123
          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
123
          state = state::PATH;
14453
123
        }
14454
14455
1.39k
        break;
14456
8.60k
      }
14457
1.27k
      case state::FILE_HOST: {
14458
1.27k
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
14459
1.27k
        std::string_view view = url_data.substr(input_position);
14460
14461
1.27k
        size_t location = view.find_first_of("/\\?");
14462
1.27k
        std::string_view file_host_buffer = view.substr(
14463
1.27k
            0, (location != std::string_view::npos) ? location : view.size());
14464
14465
1.27k
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
14466
0
          state = state::PATH;
14467
1.27k
        } 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
719
          } else {
14472
719
            url.update_base_hostname("");
14473
719
          }
14474
          // Set state to path start state.
14475
719
          state = state::PATH_START;
14476
719
        } else {
14477
557
          size_t consumed_bytes = file_host_buffer.size();
14478
557
          input_position += consumed_bytes;
14479
          // Let host be the result of host parsing buffer with url is not
14480
          // special.
14481
557
          if (!url.parse_host(file_host_buffer)) {
14482
128
            return url;
14483
128
          }
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
429
          } else {
14491
429
            if (url.get_hostname() == "localhost") {
14492
0
              url.update_base_hostname("");
14493
0
            }
14494
429
          }
14495
14496
          // Set buffer to the empty string and state to path start state.
14497
429
          state = state::PATH_START;
14498
429
        }
14499
14500
1.14k
        break;
14501
1.27k
      }
14502
2.65k
      case state::FILE: {
14503
2.65k
        ada_log("FILE ", helpers::substring(url_data, input_position));
14504
2.65k
        std::string_view file_view = url_data.substr(input_position);
14505
14506
2.65k
        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
2.65k
        } else {
14511
2.65k
          url.update_base_hostname("");
14512
2.65k
        }
14513
        // If c is U+002F (/) or U+005C (\), then:
14514
2.65k
        if (input_position != input_size &&
14515
2.33k
            (url_data[input_position] == '/' ||
14516
1.39k
             url_data[input_position] == '\\')) {
14517
1.39k
          ada_log("FILE c is U+002F or U+005C");
14518
          // Set state to file slash state.
14519
1.39k
          state = state::FILE_SLASH;
14520
1.39k
        }
14521
        // Otherwise, if base is non-null and base's scheme is "file":
14522
1.25k
        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
1
              auto s = base_url->get_search();
14538
1
              url.update_base_search(s.empty() ? std::string_view("?") : s);
14539
1
            }
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
5
                  url.update_base_pathname(std::move(std::string(path)));
14561
5
                }
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
1.25k
        else {
14578
1.25k
          ada_log("FILE go to path");
14579
1.25k
          state = state::PATH;
14580
1.25k
          break;
14581
1.25k
        }
14582
14583
1.40k
        input_position++;
14584
1.40k
        break;
14585
2.65k
      }
14586
0
      default:
14587
0
        unreachable();
14588
116k
    }
14589
116k
  }
14590
11.4k
  if constexpr (store_values) {
14591
11.4k
    if (fragment.has_value()) {
14592
76
      url.update_unencoded_base_hash(*fragment);
14593
76
    }
14594
11.4k
  }
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
11.4k
  if constexpr (store_values) {
14599
11.4k
    if (url.is_valid) {
14600
11.4k
      if constexpr (result_type_is_ada_url_aggregator) {
14601
11.4k
        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
11.4k
    }
14610
11.4k
  }
14611
11.4k
  return url;
14612
27.9k
}
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
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
}
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
31.3k
    const std::string_view input_with_colon) {
14712
31.3k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
31.3k
  ADA_ASSERT_TRUE(validate());
14714
31.3k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
31.3k
  std::string_view input{input_with_colon};
14716
31.3k
  input.remove_suffix(1);
14717
31.3k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
31.3k
  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
31.3k
  if (is_input_special) {  // fast path!!!
14724
13.1k
    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
1.65k
      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
1.65k
      if ((has_credentials() || components.port != url_components::omitted) &&
14734
415
          parsed_type == ada::scheme::type::FILE) {
14735
0
        return false;
14736
0
      }
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
1.65k
      if (type == ada::scheme::type::FILE &&
14741
483
          components.host_start == components.host_end) {
14742
396
        return false;
14743
396
      }
14744
1.65k
    }
14745
14746
1.26k
    type = parsed_type;
14747
13.1k
    set_scheme_from_view_with_colon(input_with_colon);
14748
14749
13.1k
    if constexpr (has_state_override) {
14750
      // This is uncommon.
14751
1.65k
      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
1.65k
      if (components.port == urls_scheme_port) {
14756
0
        clear_port();
14757
0
      }
14758
1.65k
    }
14759
18.2k
  } else {  // slow path
14760
18.2k
    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
18.2k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14765
14766
18.2k
    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
2.76k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14776
0
        return false;
14777
0
      }
14778
14779
      // If url includes credentials or has a non-null port, and buffer is
14780
      // "file", then return.
14781
2.76k
      if ((has_credentials() || components.port != url_components::omitted) &&
14782
380
          _buffer == "file") {
14783
0
        return false;
14784
0
      }
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
2.76k
      if (type == ada::scheme::type::FILE &&
14789
312
          components.host_start == components.host_end) {
14790
262
        return false;
14791
262
      }
14792
2.76k
    }
14793
14794
2.50k
    set_scheme(_buffer);
14795
14796
18.2k
    if constexpr (has_state_override) {
14797
      // This is uncommon.
14798
2.76k
      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
2.76k
      if (components.port == urls_scheme_port) {
14803
18
        clear_port();
14804
18
      }
14805
2.76k
    }
14806
18.2k
  }
14807
0
  ADA_ASSERT_TRUE(validate());
14808
31.3k
  return true;
14809
31.3k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14711
26.9k
    const std::string_view input_with_colon) {
14712
26.9k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
26.9k
  ADA_ASSERT_TRUE(validate());
14714
26.9k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
26.9k
  std::string_view input{input_with_colon};
14716
26.9k
  input.remove_suffix(1);
14717
26.9k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
26.9k
  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
26.9k
  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
11.4k
    type = parsed_type;
14747
11.4k
    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
15.5k
  } else {  // slow path
14760
15.5k
    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
15.5k
    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
15.5k
    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
15.5k
  }
14807
26.9k
  ADA_ASSERT_TRUE(validate());
14808
26.9k
  return true;
14809
26.9k
}
bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14711
4.42k
    const std::string_view input_with_colon) {
14712
4.42k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
14713
4.42k
  ADA_ASSERT_TRUE(validate());
14714
4.42k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
14715
4.42k
  std::string_view input{input_with_colon};
14716
4.42k
  input.remove_suffix(1);
14717
4.42k
  auto parsed_type = ada::scheme::get_scheme_type(input);
14718
4.42k
  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
4.42k
  if (is_input_special) {  // fast path!!!
14724
1.65k
    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
1.65k
      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
1.65k
      if ((has_credentials() || components.port != url_components::omitted) &&
14734
415
          parsed_type == ada::scheme::type::FILE) {
14735
0
        return false;
14736
0
      }
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
1.65k
      if (type == ada::scheme::type::FILE &&
14741
483
          components.host_start == components.host_end) {
14742
396
        return false;
14743
396
      }
14744
1.65k
    }
14745
14746
1.26k
    type = parsed_type;
14747
1.65k
    set_scheme_from_view_with_colon(input_with_colon);
14748
14749
1.65k
    if constexpr (has_state_override) {
14750
      // This is uncommon.
14751
1.65k
      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
1.65k
      if (components.port == urls_scheme_port) {
14756
0
        clear_port();
14757
0
      }
14758
1.65k
    }
14759
2.76k
  } else {  // slow path
14760
2.76k
    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
2.76k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14765
14766
2.76k
    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
2.76k
      if (is_special() != ada::scheme::is_special(_buffer)) {
14776
0
        return false;
14777
0
      }
14778
14779
      // If url includes credentials or has a non-null port, and buffer is
14780
      // "file", then return.
14781
2.76k
      if ((has_credentials() || components.port != url_components::omitted) &&
14782
380
          _buffer == "file") {
14783
0
        return false;
14784
0
      }
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
2.76k
      if (type == ada::scheme::type::FILE &&
14789
312
          components.host_start == components.host_end) {
14790
262
        return false;
14791
262
      }
14792
2.76k
    }
14793
14794
2.50k
    set_scheme(_buffer);
14795
14796
2.76k
    if constexpr (has_state_override) {
14797
      // This is uncommon.
14798
2.76k
      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
2.76k
      if (components.port == urls_scheme_port) {
14803
18
        clear_port();
14804
18
      }
14805
2.76k
    }
14806
2.76k
  }
14807
0
  ADA_ASSERT_TRUE(validate());
14808
4.42k
  return true;
14809
4.42k
}
14810
14811
352
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14812
352
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14813
352
  ADA_ASSERT_TRUE(validate());
14814
  // next line could overflow but unsigned arithmetic has well-defined
14815
  // overflows.
14816
352
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14817
14818
352
  type = u.type;
14819
352
  buffer.erase(0, components.protocol_end);
14820
352
  buffer.insert(0, u.get_protocol());
14821
352
  components.protocol_end = u.components.protocol_end;
14822
14823
  // No need to update the components
14824
352
  if (new_difference == 0) {
14825
4
    return;
14826
4
  }
14827
14828
348
  apply_shifted_non_scheme_offsets(components, new_difference);
14829
348
  ADA_ASSERT_TRUE(validate());
14830
348
}
14831
14832
inline void url_aggregator::set_scheme_from_view_with_colon(
14833
12.7k
    std::string_view new_scheme_with_colon) {
14834
12.7k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14835
12.7k
          new_scheme_with_colon);
14836
12.7k
  ADA_ASSERT_TRUE(validate());
14837
12.7k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14838
12.7k
                  new_scheme_with_colon.back() == ':');
14839
  // next line could overflow but unsigned arithmetic has well-defined
14840
  // overflows.
14841
12.7k
  uint32_t new_difference =
14842
12.7k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14843
14844
12.7k
  if (buffer.empty()) {
14845
11.4k
    buffer.append(new_scheme_with_colon);
14846
11.4k
  } else {
14847
1.26k
    buffer.erase(0, components.protocol_end);
14848
1.26k
    buffer.insert(0, new_scheme_with_colon);
14849
1.26k
  }
14850
12.7k
  components.protocol_end += new_difference;
14851
14852
12.7k
  apply_shifted_non_scheme_offsets(components, new_difference);
14853
12.7k
  ADA_ASSERT_TRUE(validate());
14854
12.7k
}
14855
14856
18.0k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14857
18.0k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14858
18.0k
  ADA_ASSERT_TRUE(validate());
14859
18.0k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14860
  // next line could overflow but unsigned arithmetic has well-defined
14861
  // overflows.
14862
18.0k
  uint32_t new_difference =
14863
18.0k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14864
14865
18.0k
  type = ada::scheme::get_scheme_type(new_scheme);
14866
18.0k
  if (buffer.empty()) {
14867
15.5k
    buffer.append(helpers::concat(new_scheme, ":"));
14868
15.5k
  } else {
14869
2.50k
    buffer.erase(0, components.protocol_end);
14870
2.50k
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14871
2.50k
  }
14872
18.0k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14873
14874
18.0k
  apply_shifted_non_scheme_offsets(components, new_difference);
14875
18.0k
  ADA_ASSERT_TRUE(validate());
14876
18.0k
}
14877
14878
4.67k
bool url_aggregator::set_protocol(const std::string_view input) {
14879
4.67k
  ada_log("url_aggregator::set_protocol ", input);
14880
4.67k
  ADA_ASSERT_TRUE(validate());
14881
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14882
4.67k
  std::string view(input);
14883
4.67k
  helpers::remove_ascii_tab_or_newline(view);
14884
4.67k
  if (view.empty()) {
14885
0
    return true;
14886
0
  }
14887
14888
  // Schemes should start with alpha values.
14889
4.67k
  if (!checkers::is_alpha(view[0])) {
14890
251
    return false;
14891
251
  }
14892
14893
4.42k
  view.append(":");
14894
14895
4.42k
  std::string::iterator pointer =
14896
4.42k
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14897
14898
4.42k
  if (pointer != view.end() && *pointer == ':') {
14899
4.42k
    url_aggregator saved_url(*this);
14900
4.42k
    bool result = parse_scheme_with_colon<true>(
14901
4.42k
        view.substr(0, pointer - view.begin() + 1));
14902
4.42k
    if (result && buffer.size() > ada::get_max_input_length()) {
14903
0
      *this = std::move(saved_url);
14904
0
      return false;
14905
0
    }
14906
4.42k
    return result;
14907
4.42k
  }
14908
0
  return false;
14909
4.42k
}
14910
14911
4.67k
bool url_aggregator::set_username(const std::string_view input) {
14912
4.67k
  ada_log("url_aggregator::set_username '", input, "' ");
14913
4.67k
  ADA_ASSERT_TRUE(validate());
14914
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14915
4.67k
  if (cannot_have_credentials_or_port()) {
14916
1.95k
    return false;
14917
1.95k
  }
14918
2.71k
  url_aggregator saved_url(*this);
14919
2.71k
  size_t idx = ada::unicode::percent_encode_index(
14920
2.71k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14921
2.71k
  if (idx == input.size()) {
14922
0
    update_base_username(input);
14923
2.71k
  } else {
14924
    // We only create a temporary string if we have to!
14925
2.71k
    update_base_username(ada::unicode::percent_encode(
14926
2.71k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14927
2.71k
  }
14928
2.71k
  if (buffer.size() > ada::get_max_input_length()) {
14929
0
    *this = std::move(saved_url);
14930
0
    return false;
14931
0
  }
14932
2.71k
  ADA_ASSERT_TRUE(validate());
14933
2.71k
  return true;
14934
2.71k
}
14935
14936
4.67k
bool url_aggregator::set_password(const std::string_view input) {
14937
4.67k
  ada_log("url_aggregator::set_password '", input, "'");
14938
4.67k
  ADA_ASSERT_TRUE(validate());
14939
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14940
4.67k
  if (cannot_have_credentials_or_port()) {
14941
1.95k
    return false;
14942
1.95k
  }
14943
2.71k
  url_aggregator saved_url(*this);
14944
2.71k
  size_t idx = ada::unicode::percent_encode_index(
14945
2.71k
      input, character_sets::USERINFO_PERCENT_ENCODE);
14946
2.71k
  if (idx == input.size()) {
14947
0
    update_base_password(input);
14948
2.71k
  } else {
14949
    // We only create a temporary string if we have to!
14950
2.71k
    update_base_password(ada::unicode::percent_encode(
14951
2.71k
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14952
2.71k
  }
14953
2.71k
  if (buffer.size() > ada::get_max_input_length()) {
14954
0
    *this = std::move(saved_url);
14955
0
    return false;
14956
0
  }
14957
2.71k
  ADA_ASSERT_TRUE(validate());
14958
2.71k
  return true;
14959
2.71k
}
14960
14961
7.20k
bool url_aggregator::set_port(const std::string_view input) {
14962
7.20k
  ada_log("url_aggregator::set_port ", input);
14963
7.20k
  ADA_ASSERT_TRUE(validate());
14964
7.20k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14965
7.20k
  if (cannot_have_credentials_or_port()) {
14966
1.95k
    return false;
14967
1.95k
  }
14968
14969
5.24k
  if (input.empty()) {
14970
0
    clear_port();
14971
0
    return true;
14972
0
  }
14973
14974
5.24k
  std::string trimmed(input);
14975
5.24k
  helpers::remove_ascii_tab_or_newline(trimmed);
14976
14977
5.24k
  if (trimmed.empty()) {
14978
0
    return true;
14979
0
  }
14980
14981
  // Input should not start with a non-digit character.
14982
5.24k
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14983
4.45k
    return false;
14984
4.45k
  }
14985
14986
  // Find the first non-digit character to determine the length of digits
14987
788
  auto first_non_digit =
14988
788
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14989
788
  std::string_view digits_to_parse =
14990
788
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14991
14992
  // Revert changes if parse_port fails.
14993
788
  url_aggregator saved_url(*this);
14994
788
  parse_port(digits_to_parse);
14995
788
  if (is_valid) {
14996
768
    if (buffer.size() > ada::get_max_input_length()) {
14997
0
      *this = std::move(saved_url);
14998
0
      return false;
14999
0
    }
15000
768
    return true;
15001
768
  }
15002
20
  *this = std::move(saved_url);
15003
20
  is_valid = true;
15004
20
  ADA_ASSERT_TRUE(validate());
15005
20
  return false;
15006
788
}
15007
15008
4.67k
bool url_aggregator::set_pathname(const std::string_view input) {
15009
4.67k
  ada_log("url_aggregator::set_pathname ", input);
15010
4.67k
  ADA_ASSERT_TRUE(validate());
15011
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15012
4.67k
  if (has_opaque_path) {
15013
1.13k
    return false;
15014
1.13k
  }
15015
3.54k
  url_aggregator saved_url(*this);
15016
3.54k
  clear_pathname();
15017
3.54k
  parse_path(input);
15018
3.54k
  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
3.54k
  if (buffer.size() > ada::get_max_input_length()) {
15029
0
    *this = std::move(saved_url);
15030
0
    return false;
15031
0
  }
15032
3.54k
  ADA_ASSERT_TRUE(validate());
15033
3.54k
  return true;
15034
3.54k
}
15035
15036
3.54k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
15037
3.54k
  ada_log("url_aggregator::parse_path ", input);
15038
3.54k
  ADA_ASSERT_TRUE(validate());
15039
3.54k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15040
3.54k
  std::string tmp_buffer;
15041
3.54k
  std::string_view internal_input;
15042
3.54k
  if (unicode::has_tabs_or_newline(input)) {
15043
110
    tmp_buffer = input;
15044
    // Optimization opportunity: Instead of copying and then pruning, we could
15045
    // just directly build the string from user_input.
15046
110
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
15047
110
    internal_input = tmp_buffer;
15048
3.43k
  } else {
15049
3.43k
    internal_input = input;
15050
3.43k
  }
15051
15052
  // If url is special, then:
15053
3.54k
  if (is_special()) {
15054
2.74k
    if (internal_input.empty()) {
15055
0
      update_base_pathname("/");
15056
2.74k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
15057
0
      consume_prepared_path(internal_input.substr(1));
15058
2.74k
    } else {
15059
2.74k
      consume_prepared_path(internal_input);
15060
2.74k
    }
15061
2.74k
  } 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
3.54k
  ADA_ASSERT_TRUE(validate());
15075
3.54k
}
15076
15077
4.67k
void url_aggregator::set_search(const std::string_view input) {
15078
4.67k
  ada_log("url_aggregator::set_search ", input);
15079
4.67k
  ADA_ASSERT_TRUE(validate());
15080
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15081
4.67k
  if (input.empty()) {
15082
0
    clear_search();
15083
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
15084
0
    return;
15085
0
  }
15086
15087
4.67k
  std::string new_value;
15088
4.67k
  new_value = input[0] == '?' ? input.substr(1) : input;
15089
4.67k
  helpers::remove_ascii_tab_or_newline(new_value);
15090
15091
4.67k
  auto query_percent_encode_set =
15092
4.67k
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
15093
4.67k
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
15094
15095
4.67k
  url_aggregator saved_url(*this);
15096
4.67k
  update_base_search(new_value, query_percent_encode_set);
15097
4.67k
  if (buffer.size() > ada::get_max_input_length()) {
15098
0
    *this = std::move(saved_url);
15099
0
    return;
15100
0
  }
15101
4.67k
  ADA_ASSERT_TRUE(validate());
15102
4.67k
}
15103
15104
4.67k
void url_aggregator::set_hash(const std::string_view input) {
15105
4.67k
  ada_log("url_aggregator::set_hash ", input);
15106
4.67k
  ADA_ASSERT_TRUE(validate());
15107
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15108
4.67k
  if (input.empty()) {
15109
0
    if (components.hash_start != url_components::omitted) {
15110
0
      buffer.resize(components.hash_start);
15111
0
      components.hash_start = url_components::omitted;
15112
0
    }
15113
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
15114
0
    return;
15115
0
  }
15116
15117
4.67k
  std::string new_value;
15118
4.67k
  new_value = input[0] == '#' ? input.substr(1) : input;
15119
4.67k
  helpers::remove_ascii_tab_or_newline(new_value);
15120
4.67k
  url_aggregator saved_url(*this);
15121
4.67k
  update_unencoded_base_hash(new_value);
15122
4.67k
  if (buffer.size() > ada::get_max_input_length()) {
15123
0
    *this = std::move(saved_url);
15124
0
    return;
15125
0
  }
15126
4.67k
  ADA_ASSERT_TRUE(validate());
15127
4.67k
}
15128
15129
4.67k
bool url_aggregator::set_href(const std::string_view input) {
15130
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15131
4.67k
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
15132
4.67k
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
15133
4.67k
  ada_log("url_aggregator::set_href, success :", out.has_value());
15134
15135
4.67k
  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
4.67k
    if (out->buffer.size() > ada::get_max_input_length()) {
15139
0
      return false;
15140
0
    }
15141
4.67k
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
15142
    // TODO: Figure out why the following line puts test to never finish.
15143
4.67k
    *this = *out;
15144
4.67k
  }
15145
15146
4.67k
  return out.has_value();
15147
4.67k
}
15148
15149
18.0k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
15150
18.0k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
15151
18.0k
          " bytes]");
15152
18.0k
  ADA_ASSERT_TRUE(validate());
15153
18.0k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15154
18.0k
  if (input.empty()) {
15155
70
    return is_valid = false;
15156
70
  }  // technically unnecessary.
15157
  // If input starts with U+005B ([), then:
15158
17.9k
  if (input[0] == '[') {
15159
    // If input does not end with U+005D (]), validation error, return failure.
15160
600
    if (input.back() != ']') {
15161
510
      return is_valid = false;
15162
510
    }
15163
90
    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
90
    input.remove_prefix(1);
15168
90
    input.remove_suffix(1);
15169
90
    return parse_ipv6(input);
15170
600
  }
15171
15172
  // If isNotSpecial is true, then return the result of opaque-host parsing
15173
  // input.
15174
17.3k
  if (!is_special()) {
15175
2.42k
    return parse_opaque_host(input);
15176
2.42k
  }
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
14.9k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
15189
14.9k
  if (fast_result < checkers::ipv4_fast_fail) {
15190
    // Fast path succeeded - input is pure decimal IPv4
15191
46
    if (!input.empty() && input.back() == '.') {
15192
0
      update_base_hostname(input.substr(0, input.size() - 1));
15193
46
    } else {
15194
46
      update_base_hostname(input);
15195
46
    }
15196
46
    host_type = IPV4;
15197
46
    is_valid = true;
15198
46
    ada_log("parse_host fast path decimal ipv4");
15199
46
    ADA_ASSERT_TRUE(validate());
15200
46
    return true;
15201
46
  }
15202
14.9k
  uint8_t is_forbidden_or_upper =
15203
14.9k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
15204
14.9k
                                                             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
14.9k
  if (is_forbidden_or_upper == 0 &&
15212
8.06k
      input.find("xn-") == std::string_view::npos) {
15213
    // fast path
15214
7.29k
    update_base_hostname(input);
15215
15216
    // Check for other IPv4 formats (hex, octal, etc.)
15217
7.29k
    if (checkers::is_ipv4(get_hostname())) {
15218
2.43k
      ada_log("parse_host fast path ipv4");
15219
2.43k
      return parse_ipv4(get_hostname(), true);
15220
2.43k
    }
15221
4.86k
    ada_log("parse_host fast path ", get_hostname());
15222
4.86k
    is_valid = true;
15223
4.86k
    return true;
15224
7.29k
  }
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
7.63k
  ada_log("parse_host calling to_ascii");
15230
7.63k
  std::optional<std::string> host = std::string(get_hostname());
15231
7.63k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
15232
7.63k
  if (!is_valid) {
15233
4.13k
    ada_log("parse_host to_ascii returns false");
15234
4.13k
    return is_valid = false;
15235
4.13k
  }
15236
3.49k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
15237
3.49k
          " bytes]");
15238
15239
3.49k
  if (std::ranges::any_of(host.value(),
15240
3.49k
                          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
3.49k
  if (checkers::is_ipv4(host.value())) {
15247
242
    ada_log("parse_host got ipv4 ", *host);
15248
242
    return parse_ipv4(host.value(), false);
15249
242
  }
15250
15251
3.25k
  update_base_hostname(host.value());
15252
3.25k
  ADA_ASSERT_TRUE(validate());
15253
3.25k
  return true;
15254
3.49k
}
15255
15256
template <bool override_hostname>
15257
9.34k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
9.34k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
9.34k
  ADA_ASSERT_TRUE(validate());
15260
9.34k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
9.34k
  if (has_opaque_path) {
15262
2.26k
    return false;
15263
2.26k
  }
15264
15265
7.08k
  url_aggregator saved_url(*this);
15266
15267
7.08k
  std::string previous_host(get_hostname());
15268
7.08k
  uint32_t previous_port = components.port;
15269
15270
7.08k
  size_t host_end_pos = input.find('#');
15271
7.08k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
7.08k
                                      ? host_end_pos
15273
7.08k
                                      : input.size());
15274
7.08k
  helpers::remove_ascii_tab_or_newline(_host);
15275
7.08k
  std::string_view new_host(_host);
15276
15277
7.08k
  auto check_url_size = [&]() -> bool {
15278
2.52k
    if (buffer.size() > ada::get_max_input_length()) {
15279
0
      *this = std::move(saved_url);
15280
0
      return false;
15281
0
    }
15282
2.52k
    return true;
15283
2.52k
  };
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
2.52k
  auto check_url_size = [&]() -> bool {
15278
2.52k
    if (buffer.size() > ada::get_max_input_length()) {
15279
0
      *this = std::move(saved_url);
15280
0
      return false;
15281
0
    }
15282
2.52k
    return true;
15283
2.52k
  };
Unexecuted instantiation: ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
7.08k
  if (type != ada::scheme::type::FILE) {
15288
5.44k
    std::string_view host_view(_host.data(), _host.length());
15289
5.44k
    auto [location, found_colon] =
15290
5.44k
        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
5.44k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
5.44k
      std::string_view host_buffer = host_view.substr(0, location);
15299
5.44k
      if (host_buffer.empty()) {
15300
0
        return false;
15301
0
      }
15302
15303
      // If state override is given and state override is hostname state, then
15304
      // return failure.
15305
5.44k
      if constexpr (override_hostname) {
15306
2.72k
        return false;
15307
2.72k
      }
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
5.44k
      if (!succeeded) {
15312
193
        update_base_hostname(previous_host);
15313
193
        update_base_port(previous_port);
15314
193
        return false;
15315
193
      }
15316
15317
      // Set url's host to host, buffer to the empty string, and state to port
15318
      // state.
15319
5.25k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
5.25k
      if (!port_buffer.empty()) {
15321
2.52k
        set_port(port_buffer);
15322
2.52k
      }
15323
5.25k
      return check_url_size();
15324
5.44k
    }
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
0
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
0
      if (host_view.empty() && is_special()) {
15332
0
        return false;
15333
0
      }
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
0
      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
0
      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
0
      bool succeeded = parse_host(host_view);
15355
0
      if (!succeeded) {
15356
0
        update_base_hostname(previous_host);
15357
0
        update_base_port(previous_port);
15358
0
        return false;
15359
0
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
0
      return check_url_size();
15364
0
    }
15365
5.44k
  }
15366
15367
1.63k
  size_t location = new_host.find_first_of("/\\?");
15368
1.63k
  if (location != std::string_view::npos) {
15369
564
    new_host.remove_suffix(new_host.length() - location);
15370
564
  }
15371
15372
1.63k
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
0
    clear_hostname();
15375
1.63k
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
1.63k
    if (!parse_host(new_host)) {
15378
1.63k
      update_base_hostname(previous_host);
15379
1.63k
      update_base_port(previous_port);
15380
1.63k
      return false;
15381
1.63k
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
0
    if (helpers::substring(buffer, components.host_start,
15385
0
                           components.host_end) == "localhost") {
15386
0
      clear_hostname();
15387
0
    }
15388
0
  }
15389
0
  ADA_ASSERT_TRUE(validate());
15390
0
  return check_url_size();
15391
1.63k
}
bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
15257
4.67k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
4.67k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
4.67k
  ADA_ASSERT_TRUE(validate());
15260
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
4.67k
  if (has_opaque_path) {
15262
1.13k
    return false;
15263
1.13k
  }
15264
15265
3.54k
  url_aggregator saved_url(*this);
15266
15267
3.54k
  std::string previous_host(get_hostname());
15268
3.54k
  uint32_t previous_port = components.port;
15269
15270
3.54k
  size_t host_end_pos = input.find('#');
15271
3.54k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
3.54k
                                      ? host_end_pos
15273
3.54k
                                      : input.size());
15274
3.54k
  helpers::remove_ascii_tab_or_newline(_host);
15275
3.54k
  std::string_view new_host(_host);
15276
15277
3.54k
  auto check_url_size = [&]() -> bool {
15278
3.54k
    if (buffer.size() > ada::get_max_input_length()) {
15279
3.54k
      *this = std::move(saved_url);
15280
3.54k
      return false;
15281
3.54k
    }
15282
3.54k
    return true;
15283
3.54k
  };
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
3.54k
  if (type != ada::scheme::type::FILE) {
15288
2.72k
    std::string_view host_view(_host.data(), _host.length());
15289
2.72k
    auto [location, found_colon] =
15290
2.72k
        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
2.72k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
2.72k
      std::string_view host_buffer = host_view.substr(0, location);
15299
2.72k
      if (host_buffer.empty()) {
15300
0
        return false;
15301
0
      }
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
2.72k
      bool succeeded = parse_host(host_buffer);
15311
2.72k
      if (!succeeded) {
15312
193
        update_base_hostname(previous_host);
15313
193
        update_base_port(previous_port);
15314
193
        return false;
15315
193
      }
15316
15317
      // Set url's host to host, buffer to the empty string, and state to port
15318
      // state.
15319
2.52k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
2.52k
      if (!port_buffer.empty()) {
15321
2.52k
        set_port(port_buffer);
15322
2.52k
      }
15323
2.52k
      return check_url_size();
15324
2.72k
    }
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
0
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
0
      if (host_view.empty() && is_special()) {
15332
0
        return false;
15333
0
      }
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
0
      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
0
      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
0
      bool succeeded = parse_host(host_view);
15355
0
      if (!succeeded) {
15356
0
        update_base_hostname(previous_host);
15357
0
        update_base_port(previous_port);
15358
0
        return false;
15359
0
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
0
      return check_url_size();
15364
0
    }
15365
2.72k
  }
15366
15367
818
  size_t location = new_host.find_first_of("/\\?");
15368
818
  if (location != std::string_view::npos) {
15369
282
    new_host.remove_suffix(new_host.length() - location);
15370
282
  }
15371
15372
818
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
0
    clear_hostname();
15375
818
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
818
    if (!parse_host(new_host)) {
15378
818
      update_base_hostname(previous_host);
15379
818
      update_base_port(previous_port);
15380
818
      return false;
15381
818
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
0
    if (helpers::substring(buffer, components.host_start,
15385
0
                           components.host_end) == "localhost") {
15386
0
      clear_hostname();
15387
0
    }
15388
0
  }
15389
0
  ADA_ASSERT_TRUE(validate());
15390
0
  return check_url_size();
15391
818
}
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
15257
4.67k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
15258
4.67k
  ada_log("url_aggregator::set_host_or_hostname ", input);
15259
4.67k
  ADA_ASSERT_TRUE(validate());
15260
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15261
4.67k
  if (has_opaque_path) {
15262
1.13k
    return false;
15263
1.13k
  }
15264
15265
3.54k
  url_aggregator saved_url(*this);
15266
15267
3.54k
  std::string previous_host(get_hostname());
15268
3.54k
  uint32_t previous_port = components.port;
15269
15270
3.54k
  size_t host_end_pos = input.find('#');
15271
3.54k
  std::string _host(input.data(), host_end_pos != std::string_view::npos
15272
3.54k
                                      ? host_end_pos
15273
3.54k
                                      : input.size());
15274
3.54k
  helpers::remove_ascii_tab_or_newline(_host);
15275
3.54k
  std::string_view new_host(_host);
15276
15277
3.54k
  auto check_url_size = [&]() -> bool {
15278
3.54k
    if (buffer.size() > ada::get_max_input_length()) {
15279
3.54k
      *this = std::move(saved_url);
15280
3.54k
      return false;
15281
3.54k
    }
15282
3.54k
    return true;
15283
3.54k
  };
15284
15285
  // If url's scheme is "file", then set state to file host state, instead of
15286
  // host state.
15287
3.54k
  if (type != ada::scheme::type::FILE) {
15288
2.72k
    std::string_view host_view(_host.data(), _host.length());
15289
2.72k
    auto [location, found_colon] =
15290
2.72k
        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
2.72k
    if (found_colon) {
15296
      // If buffer is the empty string, host-missing validation error, return
15297
      // failure.
15298
2.72k
      std::string_view host_buffer = host_view.substr(0, location);
15299
2.72k
      if (host_buffer.empty()) {
15300
0
        return false;
15301
0
      }
15302
15303
      // If state override is given and state override is hostname state, then
15304
      // return failure.
15305
2.72k
      if constexpr (override_hostname) {
15306
2.72k
        return false;
15307
2.72k
      }
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
2.72k
      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
2.72k
      std::string_view port_buffer = new_host.substr(location + 1);
15320
2.72k
      if (!port_buffer.empty()) {
15321
0
        set_port(port_buffer);
15322
0
      }
15323
2.72k
      return check_url_size();
15324
2.72k
    }
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
0
    else {
15329
      // If url is special and host_view is the empty string, host-missing
15330
      // validation error, return failure.
15331
0
      if (host_view.empty() && is_special()) {
15332
0
        return false;
15333
0
      }
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
0
      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
0
      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
0
      bool succeeded = parse_host(host_view);
15355
0
      if (!succeeded) {
15356
0
        update_base_hostname(previous_host);
15357
0
        update_base_port(previous_port);
15358
0
        return false;
15359
0
      } else if (has_dash_dot()) {
15360
        // Should remove dash_dot from pathname
15361
0
        delete_dash_dot();
15362
0
      }
15363
0
      return check_url_size();
15364
0
    }
15365
2.72k
  }
15366
15367
818
  size_t location = new_host.find_first_of("/\\?");
15368
818
  if (location != std::string_view::npos) {
15369
282
    new_host.remove_suffix(new_host.length() - location);
15370
282
  }
15371
15372
818
  if (new_host.empty()) {
15373
    // Set url's host to the empty string.
15374
0
    clear_hostname();
15375
818
  } else {
15376
    // Let host be the result of host parsing buffer with url is not special.
15377
818
    if (!parse_host(new_host)) {
15378
818
      update_base_hostname(previous_host);
15379
818
      update_base_port(previous_port);
15380
818
      return false;
15381
818
    }
15382
15383
    // If host is "localhost", then set host to the empty string.
15384
0
    if (helpers::substring(buffer, components.host_start,
15385
0
                           components.host_end) == "localhost") {
15386
0
      clear_hostname();
15387
0
    }
15388
0
  }
15389
0
  ADA_ASSERT_TRUE(validate());
15390
0
  return check_url_size();
15391
818
}
15392
15393
4.67k
bool url_aggregator::set_host(const std::string_view input) {
15394
4.67k
  ada_log("url_aggregator::set_host '", input, "'");
15395
4.67k
  ADA_ASSERT_TRUE(validate());
15396
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15397
4.67k
  return set_host_or_hostname<false>(input);
15398
4.67k
}
15399
15400
4.67k
bool url_aggregator::set_hostname(const std::string_view input) {
15401
4.67k
  ada_log("url_aggregator::set_hostname '", input, "'");
15402
4.67k
  ADA_ASSERT_TRUE(validate());
15403
4.67k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15404
4.67k
  return set_host_or_hostname<true>(input);
15405
4.67k
}
15406
15407
5.19k
[[nodiscard]] std::string url_aggregator::get_origin() const {
15408
5.19k
  ada_log("url_aggregator::get_origin");
15409
5.19k
  if (is_special()) {
15410
    // Return a new opaque origin.
15411
2.90k
    if (type == scheme::FILE) {
15412
856
      return "null";
15413
856
    }
15414
15415
2.04k
    return helpers::concat(get_protocol(), "//", get_host());
15416
2.90k
  }
15417
15418
2.29k
  if (get_protocol() == "blob:") {
15419
1.01k
    std::string_view path = get_pathname();
15420
1.01k
    if (!path.empty()) {
15421
825
      auto out = ada::parse<ada::url_aggregator>(path);
15422
825
      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
14
        return helpers::concat(out->get_protocol(), "//", out->get_host());
15426
14
      }
15427
825
    }
15428
1.01k
  }
15429
15430
  // Return a new opaque origin.
15431
2.27k
  return "null";
15432
2.29k
}
15433
15434
[[nodiscard]] std::string_view url_aggregator::get_username() const
15435
5.19k
    ada_lifetime_bound {
15436
5.19k
  ada_log("url_aggregator::get_username");
15437
5.19k
  if (has_non_empty_username()) {
15438
2.72k
    return helpers::substring(buffer, components.protocol_end + 2,
15439
2.72k
                              components.username_end);
15440
2.72k
  }
15441
2.47k
  return "";
15442
5.19k
}
15443
15444
[[nodiscard]] std::string_view url_aggregator::get_password() const
15445
5.19k
    ada_lifetime_bound {
15446
5.19k
  ada_log("url_aggregator::get_password");
15447
5.19k
  if (has_non_empty_password()) {
15448
2.71k
    return helpers::substring(buffer, components.username_end + 1,
15449
2.71k
                              components.host_start);
15450
2.71k
  }
15451
2.47k
  return "";
15452
5.19k
}
15453
15454
[[nodiscard]] std::string_view url_aggregator::get_port() const
15455
5.19k
    ada_lifetime_bound {
15456
5.19k
  ada_log("url_aggregator::get_port");
15457
5.19k
  if (components.port == url_components::omitted) {
15458
4.44k
    return "";
15459
4.44k
  }
15460
752
  return helpers::substring(buffer, components.host_end + 1,
15461
752
                            components.pathname_start);
15462
5.19k
}
15463
15464
[[nodiscard]] std::string_view url_aggregator::get_hash() const
15465
5.19k
    ada_lifetime_bound {
15466
5.19k
  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
5.19k
  if (components.hash_start == url_components::omitted) {
15470
520
    return "";
15471
520
  }
15472
4.67k
  if (buffer.size() - components.hash_start <= 1) {
15473
0
    return "";
15474
0
  }
15475
4.67k
  return helpers::substring(buffer, components.hash_start);
15476
4.67k
}
15477
15478
[[nodiscard]] std::string_view url_aggregator::get_host() const
15479
6.73k
    ada_lifetime_bound {
15480
6.73k
  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
6.73k
  size_t start = components.host_start;
15485
6.73k
  if (components.host_end > components.host_start &&
15486
4.91k
      buffer[components.host_start] == '@') {
15487
4.64k
    start++;
15488
4.64k
  }
15489
  // if we have an empty host, then the space between components.host_end and
15490
  // components.pathname_start may be occupied by /.
15491
6.73k
  if (start == components.host_end) {
15492
1.81k
    return {};
15493
1.81k
  }
15494
4.91k
  return helpers::substring(buffer, start, components.pathname_start);
15495
6.73k
}
15496
15497
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
15498
30.5k
    ada_lifetime_bound {
15499
30.5k
  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
30.5k
  size_t start = components.host_start;
15504
  // So host_start is not where the host begins.
15505
30.5k
  if (components.host_end > components.host_start &&
15506
19.7k
      buffer[components.host_start] == '@') {
15507
4.98k
    start++;
15508
4.98k
  }
15509
30.5k
  return helpers::substring(buffer, start, components.host_end);
15510
30.5k
}
15511
15512
[[nodiscard]] std::string_view url_aggregator::get_search() const
15513
5.20k
    ada_lifetime_bound {
15514
5.20k
  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
5.20k
  if (components.search_start == url_components::omitted) {
15518
515
    return "";
15519
515
  }
15520
4.68k
  auto ending_index = uint32_t(buffer.size());
15521
4.68k
  if (components.hash_start != url_components::omitted) {
15522
4.67k
    ending_index = components.hash_start;
15523
4.67k
  }
15524
4.68k
  if (ending_index - components.search_start <= 1) {
15525
2
    return "";
15526
2
  }
15527
4.68k
  return helpers::substring(buffer, components.search_start, ending_index);
15528
4.68k
}
15529
15530
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
15531
9.89k
    ada_lifetime_bound {
15532
9.89k
  ada_log("url_aggregator::get_protocol");
15533
9.89k
  return helpers::substring(buffer, 0, components.protocol_end);
15534
9.89k
}
15535
15536
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
15537
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
15538
0
          " bytes]");
15539
0
  if (!is_valid) {
15540
0
    return "null";
15541
0
  }
15542
15543
0
  std::string answer;
15544
0
  auto back = std::back_insert_iterator(answer);
15545
0
  answer.append("{\n");
15546
15547
0
  answer.append("\t\"buffer\":\"");
15548
0
  helpers::encode_json(buffer, back);
15549
0
  answer.append("\",\n");
15550
15551
0
  answer.append("\t\"protocol\":\"");
15552
0
  helpers::encode_json(get_protocol(), back);
15553
0
  answer.append("\",\n");
15554
15555
0
  if (has_credentials()) {
15556
0
    answer.append("\t\"username\":\"");
15557
0
    helpers::encode_json(get_username(), back);
15558
0
    answer.append("\",\n");
15559
0
    answer.append("\t\"password\":\"");
15560
0
    helpers::encode_json(get_password(), back);
15561
0
    answer.append("\",\n");
15562
0
  }
15563
15564
0
  answer.append("\t\"host\":\"");
15565
0
  helpers::encode_json(get_host(), back);
15566
0
  answer.append("\",\n");
15567
15568
0
  answer.append("\t\"path\":\"");
15569
0
  helpers::encode_json(get_pathname(), back);
15570
0
  answer.append("\",\n");
15571
0
  answer.append("\t\"opaque path\":");
15572
0
  answer.append((has_opaque_path ? "true" : "false"));
15573
0
  answer.append(",\n");
15574
15575
0
  if (components.search_start != url_components::omitted) {
15576
0
    answer.append("\t\"query\":\"");
15577
0
    helpers::encode_json(get_search(), back);
15578
0
    answer.append("\",\n");
15579
0
  }
15580
0
  if (components.hash_start != url_components::omitted) {
15581
0
    answer.append("\t\"fragment\":\"");
15582
0
    helpers::encode_json(get_hash(), back);
15583
0
    answer.append("\",\n");
15584
0
  }
15585
15586
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
15587
0
    if (offset == url_components::omitted) {
15588
0
      return "null";
15589
0
    } else {
15590
0
      return std::to_string(offset);
15591
0
    }
15592
0
  };
15593
15594
0
  answer.append("\t\"protocol_end\":");
15595
0
  answer.append(convert_offset_to_string(components.protocol_end));
15596
0
  answer.append(",\n");
15597
15598
0
  answer.append("\t\"username_end\":");
15599
0
  answer.append(convert_offset_to_string(components.username_end));
15600
0
  answer.append(",\n");
15601
15602
0
  answer.append("\t\"host_start\":");
15603
0
  answer.append(convert_offset_to_string(components.host_start));
15604
0
  answer.append(",\n");
15605
15606
0
  answer.append("\t\"host_end\":");
15607
0
  answer.append(convert_offset_to_string(components.host_end));
15608
0
  answer.append(",\n");
15609
15610
0
  answer.append("\t\"port\":");
15611
0
  answer.append(convert_offset_to_string(components.port));
15612
0
  answer.append(",\n");
15613
15614
0
  answer.append("\t\"pathname_start\":");
15615
0
  answer.append(convert_offset_to_string(components.pathname_start));
15616
0
  answer.append(",\n");
15617
15618
0
  answer.append("\t\"search_start\":");
15619
0
  answer.append(convert_offset_to_string(components.search_start));
15620
0
  answer.append(",\n");
15621
15622
0
  answer.append("\t\"hash_start\":");
15623
0
  answer.append(convert_offset_to_string(components.hash_start));
15624
0
  answer.append("\n}");
15625
15626
0
  return answer;
15627
0
}
15628
15629
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15630
0
  if (components.host_start == components.host_end) {
15631
0
    return false;
15632
0
  }
15633
  // Avoid allocation: construct a string_view directly into the buffer.
15634
0
  size_t start = components.host_start;
15635
0
  if (components.host_end > components.host_start &&
15636
0
      buffer[components.host_start] == '@') {
15637
0
    start++;
15638
0
  }
15639
0
  return checkers::verify_dns_length(
15640
0
      std::string_view(buffer.data() + start, components.host_end - start));
15641
0
}
15642
15643
2.67k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15644
2.67k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15645
2.67k
          " bytes], overlaps with buffer: ",
15646
2.67k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15647
2.67k
  ADA_ASSERT_TRUE(validate());
15648
2.67k
  const bool trailing_dot = (input.back() == '.');
15649
2.67k
  if (trailing_dot) {
15650
142
    input.remove_suffix(1);
15651
142
  }
15652
2.67k
  size_t digit_count{0};
15653
2.67k
  int pure_decimal_count = 0;  // entries that are decimal
15654
2.67k
  uint64_t ipv4{0};
15655
  // we could unroll for better performance?
15656
2.89k
  for (; (digit_count < 4) && !(input.empty()); digit_count++) {
15657
2.89k
    uint32_t
15658
2.89k
        segment_result{};  // If any number exceeds 32 bits, we have an error.
15659
2.89k
    bool is_hex = checkers::has_hex_prefix(input);
15660
2.89k
    if (is_hex && ((input.length() == 2) ||
15661
601
                   ((input.length() > 2) && (input[2] == '.')))) {
15662
      // special case
15663
127
      segment_result = 0;
15664
127
      input.remove_prefix(2);
15665
2.76k
    } else {
15666
2.76k
      std::from_chars_result r{};
15667
2.76k
      if (is_hex) {
15668
601
        ada_log("parse_ipv4 trying to parse hex number");
15669
601
        r = std::from_chars(input.data() + 2, input.data() + input.size(),
15670
601
                            segment_result, 16);
15671
2.16k
      } else if ((input.length() >= 2) && input[0] == '0' &&
15672
421
                 checkers::is_digit(input[1])) {
15673
390
        ada_log("parse_ipv4 trying to parse octal number");
15674
390
        r = std::from_chars(input.data() + 1, input.data() + input.size(),
15675
390
                            segment_result, 8);
15676
1.77k
      } else {
15677
1.77k
        ada_log("parse_ipv4 trying to parse decimal number");
15678
1.77k
        pure_decimal_count++;
15679
1.77k
        r = std::from_chars(input.data(), input.data() + input.size(),
15680
1.77k
                            segment_result, 10);
15681
1.77k
      }
15682
2.76k
      if (r.ec != std::errc()) {
15683
238
        ada_log("parse_ipv4 parsing failed");
15684
238
        return is_valid = false;
15685
238
      }
15686
2.52k
      ada_log("parse_ipv4 parsed ", segment_result);
15687
2.52k
      input.remove_prefix(r.ptr - input.data());
15688
2.52k
    }
15689
2.65k
    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
2.42k
      if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
15694
2
        return is_valid = false;
15695
2
      }
15696
2.42k
      ipv4 <<= (32 - digit_count * 8);
15697
2.42k
      ipv4 |= segment_result;
15698
2.42k
      goto final;
15699
2.42k
    } else {
15700
      // There is more, so that the value must no be larger than 255
15701
      // and we must have a '.'.
15702
230
      if ((segment_result > 255) || (input[0] != '.')) {
15703
12
        return is_valid = false;
15704
12
      }
15705
218
      ipv4 <<= 8;
15706
218
      ipv4 |= segment_result;
15707
218
      input.remove_prefix(1);  // remove '.'
15708
218
    }
15709
2.65k
  }
15710
0
  if ((digit_count != 4) || (!input.empty())) {
15711
0
    ada_log("parse_ipv4 found invalid (more than 4 numbers or empty) ");
15712
0
    return is_valid = false;
15713
0
  }
15714
2.42k
final:
15715
2.42k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15716
2.42k
          " host: ", get_host());
15717
15718
  // We could also check r.ptr to see where the parsing ended.
15719
2.42k
  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
2.42k
  } else {
15726
2.42k
    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
2.42k
    update_base_hostname(
15732
2.42k
        ada::serializers::ipv4(ipv4));  // We have to reserialize the address.
15733
2.42k
  }
15734
2.42k
  host_type = IPV4;
15735
2.42k
  ADA_ASSERT_TRUE(validate());
15736
2.42k
  return true;
15737
0
}
15738
15739
90
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
90
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15745
90
  ADA_ASSERT_TRUE(validate());
15746
90
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15747
90
  if (input.empty()) {
15748
36
    return is_valid = false;
15749
36
  }
15750
  // Let address be a new IPv6 address whose IPv6 pieces are all 0.
15751
54
  std::array<uint16_t, 8> address{};
15752
15753
  // Let pieceIndex be 0.
15754
54
  int piece_index = 0;
15755
15756
  // Let compress be null.
15757
54
  std::optional<int> compress{};
15758
15759
  // Let pointer be a pointer for input.
15760
54
  std::string_view::iterator pointer = input.begin();
15761
15762
  // If c is U+003A (:), then:
15763
54
  if (input[0] == ':') {
15764
    // If remaining does not start with U+003A (:), validation error, return
15765
    // failure.
15766
5
    if (input.size() == 1 || input[1] != ':') {
15767
2
      ada_log("parse_ipv6 starts with : but the rest does not start with :");
15768
2
      return is_valid = false;
15769
2
    }
15770
15771
    // Increase pointer by 2.
15772
3
    pointer += 2;
15773
15774
    // Increase pieceIndex by 1 and then set compress to pieceIndex.
15775
3
    compress = ++piece_index;
15776
3
  }
15777
15778
  // While c is not the EOF code point:
15779
59
  while (pointer != input.end()) {
15780
    // If pieceIndex is 8, validation error, return failure.
15781
52
    if (piece_index == 8) {
15782
0
      ada_log("parse_ipv6 piece_index == 8");
15783
0
      return is_valid = false;
15784
0
    }
15785
15786
    // If c is U+003A (:), then:
15787
52
    if (*pointer == ':') {
15788
      // If compress is non-null, validation error, return failure.
15789
0
      if (compress.has_value()) {
15790
0
        ada_log("parse_ipv6 compress is non-null");
15791
0
        return is_valid = false;
15792
0
      }
15793
15794
      // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
15795
      // then continue.
15796
0
      pointer++;
15797
0
      compress = ++piece_index;
15798
0
      continue;
15799
0
    }
15800
15801
    // Let value and length be 0.
15802
52
    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
59
    while (length < 4 && pointer != input.end() &&
15808
52
           unicode::is_ascii_hex_digit(*pointer)) {
15809
      // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
15810
7
      value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
15811
7
      pointer++;
15812
7
      length++;
15813
7
    }
15814
15815
    // If c is U+002E (.), then:
15816
52
    if (pointer != input.end() && *pointer == '.') {
15817
      // If length is 0, validation error, return failure.
15818
2
      if (length == 0) {
15819
2
        ada_log("parse_ipv6 length is 0");
15820
2
        return is_valid = false;
15821
2
      }
15822
15823
      // Decrease pointer by length.
15824
0
      pointer -= length;
15825
15826
      // If pieceIndex is greater than 6, validation error, return failure.
15827
0
      if (piece_index > 6) {
15828
0
        ada_log("parse_ipv6 piece_index > 6");
15829
0
        return is_valid = false;
15830
0
      }
15831
15832
      // Let numbersSeen be 0.
15833
0
      int numbers_seen = 0;
15834
15835
      // While c is not the EOF code point:
15836
0
      while (pointer != input.end()) {
15837
        // Let ipv4Piece be null.
15838
0
        std::optional<uint16_t> ipv4_piece{};
15839
15840
        // If numbersSeen is greater than 0, then:
15841
0
        if (numbers_seen > 0) {
15842
          // If c is a U+002E (.) and numbersSeen is less than 4, then increase
15843
          // pointer by 1.
15844
0
          if (*pointer == '.' && numbers_seen < 4) {
15845
0
            pointer++;
15846
0
          } else {
15847
            // Otherwise, validation error, return failure.
15848
0
            ada_log("parse_ipv6 Otherwise, validation error, return failure");
15849
0
            return is_valid = false;
15850
0
          }
15851
0
        }
15852
15853
        // If c is not an ASCII digit, validation error, return failure.
15854
0
        if (pointer == input.end() || !checkers::is_digit(*pointer)) {
15855
0
          ada_log(
15856
0
              "parse_ipv6 If c is not an ASCII digit, validation error, return "
15857
0
              "failure");
15858
0
          return is_valid = false;
15859
0
        }
15860
15861
        // While c is an ASCII digit:
15862
0
        while (pointer != input.end() && checkers::is_digit(*pointer)) {
15863
          // Let number be c interpreted as decimal number.
15864
0
          int number = *pointer - '0';
15865
15866
          // If ipv4Piece is null, then set ipv4Piece to number.
15867
0
          if (!ipv4_piece.has_value()) {
15868
0
            ipv4_piece = number;
15869
0
          }
15870
          // Otherwise, if ipv4Piece is 0, validation error, return failure.
15871
0
          else if (ipv4_piece == 0) {
15872
0
            ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
15873
0
            return is_valid = false;
15874
0
          }
15875
          // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
15876
0
          else {
15877
0
            ipv4_piece = *ipv4_piece * 10 + number;
15878
0
          }
15879
15880
          // If ipv4Piece is greater than 255, validation error, return failure.
15881
0
          if (ipv4_piece > 255) {
15882
0
            ada_log("parse_ipv6 ipv4_piece > 255");
15883
0
            return is_valid = false;
15884
0
          }
15885
15886
          // Increase pointer by 1.
15887
0
          pointer++;
15888
0
        }
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
0
        if (!ipv4_piece.has_value()) {
15894
0
          return is_valid = false;
15895
0
        }
15896
0
        address[piece_index] =
15897
0
            uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
15898
15899
        // Increase numbersSeen by 1.
15900
0
        numbers_seen++;
15901
15902
        // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
15903
0
        if (numbers_seen == 2 || numbers_seen == 4) {
15904
0
          piece_index++;
15905
0
        }
15906
0
      }
15907
15908
      // If numbersSeen is not 4, validation error, return failure.
15909
0
      if (numbers_seen != 4) {
15910
0
        return is_valid = false;
15911
0
      }
15912
15913
      // Break.
15914
0
      break;
15915
0
    }
15916
    // Otherwise, if c is U+003A (:):
15917
50
    else if ((pointer != input.end()) && (*pointer == ':')) {
15918
      // Increase pointer by 1.
15919
0
      pointer++;
15920
15921
      // If c is the EOF code point, validation error, return failure.
15922
0
      if (pointer == input.end()) {
15923
0
        ada_log(
15924
0
            "parse_ipv6 If c is the EOF code point, validation error, return "
15925
0
            "failure");
15926
0
        return is_valid = false;
15927
0
      }
15928
0
    }
15929
    // Otherwise, if c is not the EOF code point, validation error, return
15930
    // failure.
15931
50
    else if (pointer != input.end()) {
15932
43
      ada_log(
15933
43
          "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
15934
43
          "error, return failure");
15935
43
      return is_valid = false;
15936
43
    }
15937
15938
    // Set address[pieceIndex] to value.
15939
7
    address[piece_index] = value;
15940
15941
    // Increase pieceIndex by 1.
15942
7
    piece_index++;
15943
7
  }
15944
15945
  // If compress is non-null, then:
15946
7
  if (compress.has_value()) {
15947
    // Let swaps be pieceIndex - compress.
15948
3
    int swaps = piece_index - *compress;
15949
15950
    // Set pieceIndex to 7.
15951
3
    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
6
    while (piece_index != 0 && swaps > 0) {
15957
3
      std::swap(address[piece_index], address[*compress + swaps - 1]);
15958
3
      piece_index--;
15959
3
      swaps--;
15960
3
    }
15961
3
  }
15962
  // Otherwise, if compress is null and pieceIndex is not 8, validation error,
15963
  // return failure.
15964
4
  else if (piece_index != 8) {
15965
4
    ada_log(
15966
4
        "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
15967
4
        "error, return failure");
15968
4
    return is_valid = false;
15969
4
  }
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
  update_base_hostname(ada::serializers::ipv6(address));
15974
3
  ada_log("parse_ipv6 ", get_hostname());
15975
3
  ADA_ASSERT_TRUE(validate());
15976
3
  host_type = IPV6;
15977
3
  return true;
15978
7
}
15979
15980
2.42k
bool url_aggregator::parse_opaque_host(std::string_view input) {
15981
2.42k
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15982
2.42k
  ADA_ASSERT_TRUE(validate());
15983
2.42k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15984
2.42k
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15985
167
    return is_valid = false;
15986
167
  }
15987
15988
  // Return the result of running UTF-8 percent-encode on input using the C0
15989
  // control percent-encode set.
15990
2.25k
  size_t idx = ada::unicode::percent_encode_index(
15991
2.25k
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15992
2.25k
  if (idx == input.size()) {
15993
1.73k
    update_base_hostname(input);
15994
1.73k
  } else {
15995
    // We only create a temporary string if we need to.
15996
524
    update_base_hostname(ada::unicode::percent_encode(
15997
524
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15998
524
  }
15999
2.25k
  ADA_ASSERT_TRUE(validate());
16000
2.25k
  return true;
16001
2.42k
}
16002
16003
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
16004
0
  if (!is_valid) {
16005
0
    return "invalid";
16006
0
  }
16007
0
  std::string answer;
16008
0
  answer.append(buffer);
16009
0
  answer.append(" [");
16010
0
  answer.append(std::to_string(buffer.size()));
16011
0
  answer.append(" bytes]");
16012
0
  answer.append("\n");
16013
  // first line
16014
0
  std::string line1;
16015
0
  line1.resize(buffer.size(), ' ');
16016
0
  if (components.hash_start != url_components::omitted) {
16017
0
    line1[components.hash_start] = '|';
16018
0
  }
16019
0
  if (components.search_start != url_components::omitted) {
16020
0
    line1[components.search_start] = '|';
16021
0
  }
16022
0
  if (components.pathname_start != buffer.size()) {
16023
0
    line1[components.pathname_start] = '|';
16024
0
  }
16025
0
  if (components.host_end != buffer.size()) {
16026
0
    line1[components.host_end] = '|';
16027
0
  }
16028
0
  if (components.host_start != buffer.size()) {
16029
0
    line1[components.host_start] = '|';
16030
0
  }
16031
0
  if (components.username_end != buffer.size()) {
16032
0
    line1[components.username_end] = '|';
16033
0
  }
16034
0
  if (components.protocol_end != buffer.size()) {
16035
0
    line1[components.protocol_end] = '|';
16036
0
  }
16037
0
  answer.append(line1);
16038
0
  answer.append("\n");
16039
16040
0
  std::string line2 = line1;
16041
0
  if (components.hash_start != url_components::omitted) {
16042
0
    line2[components.hash_start] = '`';
16043
0
    line1[components.hash_start] = ' ';
16044
16045
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
16046
0
      line2[i] = '-';
16047
0
    }
16048
0
    line2.append(" hash_start");
16049
0
    answer.append(line2);
16050
0
    answer.append("\n");
16051
0
  }
16052
16053
0
  std::string line3 = line1;
16054
0
  if (components.search_start != url_components::omitted) {
16055
0
    line3[components.search_start] = '`';
16056
0
    line1[components.search_start] = ' ';
16057
16058
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
16059
0
      line3[i] = '-';
16060
0
    }
16061
0
    line3.append(" search_start ");
16062
0
    line3.append(std::to_string(components.search_start));
16063
0
    answer.append(line3);
16064
0
    answer.append("\n");
16065
0
  }
16066
16067
0
  std::string line4 = line1;
16068
0
  if (components.pathname_start != buffer.size()) {
16069
0
    line4[components.pathname_start] = '`';
16070
0
    line1[components.pathname_start] = ' ';
16071
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
16072
0
      line4[i] = '-';
16073
0
    }
16074
0
    line4.append(" pathname_start ");
16075
0
    line4.append(std::to_string(components.pathname_start));
16076
0
    answer.append(line4);
16077
0
    answer.append("\n");
16078
0
  }
16079
16080
0
  std::string line5 = line1;
16081
0
  if (components.host_end != buffer.size()) {
16082
0
    line5[components.host_end] = '`';
16083
0
    line1[components.host_end] = ' ';
16084
16085
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
16086
0
      line5[i] = '-';
16087
0
    }
16088
0
    line5.append(" host_end ");
16089
0
    line5.append(std::to_string(components.host_end));
16090
0
    answer.append(line5);
16091
0
    answer.append("\n");
16092
0
  }
16093
16094
0
  std::string line6 = line1;
16095
0
  if (components.host_start != buffer.size()) {
16096
0
    line6[components.host_start] = '`';
16097
0
    line1[components.host_start] = ' ';
16098
16099
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
16100
0
      line6[i] = '-';
16101
0
    }
16102
0
    line6.append(" host_start ");
16103
0
    line6.append(std::to_string(components.host_start));
16104
0
    answer.append(line6);
16105
0
    answer.append("\n");
16106
0
  }
16107
16108
0
  std::string line7 = line1;
16109
0
  if (components.username_end != buffer.size()) {
16110
0
    line7[components.username_end] = '`';
16111
0
    line1[components.username_end] = ' ';
16112
16113
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
16114
0
      line7[i] = '-';
16115
0
    }
16116
0
    line7.append(" username_end ");
16117
0
    line7.append(std::to_string(components.username_end));
16118
0
    answer.append(line7);
16119
0
    answer.append("\n");
16120
0
  }
16121
16122
0
  std::string line8 = line1;
16123
0
  if (components.protocol_end != buffer.size()) {
16124
0
    line8[components.protocol_end] = '`';
16125
0
    line1[components.protocol_end] = ' ';
16126
16127
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
16128
0
      line8[i] = '-';
16129
0
    }
16130
0
    line8.append(" protocol_end ");
16131
0
    line8.append(std::to_string(components.protocol_end));
16132
0
    answer.append(line8);
16133
0
    answer.append("\n");
16134
0
  }
16135
16136
0
  if (components.hash_start == url_components::omitted) {
16137
0
    answer.append("note: hash omitted\n");
16138
0
  }
16139
0
  if (components.search_start == url_components::omitted) {
16140
0
    answer.append("note: search omitted\n");
16141
0
  }
16142
0
  if (components.protocol_end > buffer.size()) {
16143
0
    answer.append("warning: protocol_end overflows\n");
16144
0
  }
16145
0
  if (components.username_end > buffer.size()) {
16146
0
    answer.append("warning: username_end overflows\n");
16147
0
  }
16148
0
  if (components.host_start > buffer.size()) {
16149
0
    answer.append("warning: host_start overflows\n");
16150
0
  }
16151
0
  if (components.host_end > buffer.size()) {
16152
0
    answer.append("warning: host_end overflows\n");
16153
0
  }
16154
0
  if (components.pathname_start > buffer.size()) {
16155
0
    answer.append("warning: pathname_start overflows\n");
16156
0
  }
16157
0
  return answer;
16158
0
}
16159
16160
0
void url_aggregator::delete_dash_dot() {
16161
0
  ada_log("url_aggregator::delete_dash_dot");
16162
0
  ADA_ASSERT_TRUE(validate());
16163
0
  ADA_ASSERT_TRUE(has_dash_dot());
16164
0
  buffer.erase(components.host_end, 2);
16165
0
  components.pathname_start -= 2;
16166
0
  if (components.search_start != url_components::omitted) {
16167
0
    components.search_start -= 2;
16168
0
  }
16169
0
  if (components.hash_start != url_components::omitted) {
16170
0
    components.hash_start -= 2;
16171
0
  }
16172
0
  ADA_ASSERT_TRUE(validate());
16173
0
  ADA_ASSERT_TRUE(!has_dash_dot());
16174
0
}
16175
16176
10.5k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
16177
10.5k
  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
10.5k
  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
10.5k
  constexpr uint8_t need_encoding = 1;
16193
10.5k
  constexpr uint8_t backslash_char = 2;
16194
10.5k
  constexpr uint8_t dot_char = 4;
16195
10.5k
  constexpr uint8_t percent_char = 8;
16196
10.5k
  bool special = type != ada::scheme::NOT_SPECIAL;
16197
10.5k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
16198
3.01k
                                      checkers::is_windows_drive_letter(input));
16199
10.5k
  bool trivial_path =
16200
10.5k
      (special ? (accumulator == 0)
16201
10.5k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
16202
2.94k
                  0)) &&
16203
4.49k
      (!may_need_slow_file_handling);
16204
10.5k
  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
1.64k
    if (input[0] != '.') {
16213
1.24k
      size_t slashdot = 0;
16214
1.24k
      bool dot_is_file = true;
16215
3.10k
      for (;;) {
16216
3.10k
        slashdot = input.find("/.", slashdot);
16217
3.10k
        if (slashdot == std::string_view::npos) {  // common case
16218
1.24k
          break;
16219
1.86k
        } else {  // uncommon
16220
          // only three cases matter: /./, /.. or a final /
16221
1.86k
          slashdot += 2;
16222
1.86k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
16223
484
                           input[slashdot] == '/');
16224
1.86k
        }
16225
3.10k
      }
16226
1.24k
      trivial_path = dot_is_file;
16227
1.24k
    }
16228
1.64k
  }
16229
10.5k
  if (trivial_path && is_at_path()) {
16230
5.24k
    ada_log("parse_path trivial");
16231
5.24k
    buffer += '/';
16232
5.24k
    buffer += input;
16233
5.24k
    return;
16234
5.24k
  }
16235
5.27k
  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
5.27k
  bool fast_path =
16241
5.27k
      (special &&
16242
3.43k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
16243
665
      (type != ada::scheme::type::FILE);
16244
5.27k
  if (fast_path) {
16245
529
    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
529
    size_t previous_location = 0;  // We start at 0.
16251
6.80k
    do {
16252
6.80k
      size_t new_location = input.find('/', previous_location);
16253
      // std::string_view path_view = input;
16254
      //  We process the last segment separately:
16255
6.80k
      if (new_location == std::string_view::npos) {
16256
529
        std::string_view path_view = input.substr(previous_location);
16257
529
        if (path_view == "..") {  // The path ends with ..
16258
          // e.g., if you receive ".." with an empty path, you go to "/".
16259
25
          if (path.empty()) {
16260
11
            path = '/';
16261
11
            update_base_pathname(path);
16262
11
            return;
16263
11
          }
16264
          // Fast case where we have nothing to do:
16265
14
          if (path.back() == '/') {
16266
13
            update_base_pathname(path);
16267
13
            return;
16268
13
          }
16269
          // If you have the path "/joe/myfriend",
16270
          // then you delete 'myfriend'.
16271
1
          path.resize(path.rfind('/') + 1);
16272
1
          update_base_pathname(path);
16273
1
          return;
16274
14
        }
16275
504
        path += '/';
16276
504
        if (path_view != ".") {
16277
455
          path.append(path_view);
16278
455
        }
16279
504
        update_base_pathname(path);
16280
504
        return;
16281
6.27k
      } else {
16282
        // This is a non-final segment.
16283
6.27k
        std::string_view path_view =
16284
6.27k
            input.substr(previous_location, new_location - previous_location);
16285
6.27k
        previous_location = new_location + 1;
16286
6.27k
        if (path_view == "..") {
16287
517
          size_t last_delimiter = path.rfind('/');
16288
517
          if (last_delimiter != std::string::npos) {
16289
348
            path.erase(last_delimiter);
16290
348
          }
16291
5.75k
        } else if (path_view != ".") {
16292
5.46k
          path += '/';
16293
5.46k
          path.append(path_view);
16294
5.46k
        }
16295
6.27k
      }
16296
6.80k
    } while (true);
16297
4.74k
  } else {
16298
4.74k
    ada_log("parse_path slow");
16299
    // we have reached the general case
16300
4.74k
    bool needs_percent_encoding = (accumulator & 1);
16301
4.74k
    std::string path_buffer_tmp;
16302
14.2k
    do {
16303
14.2k
      size_t location = (special && (accumulator & 2))
16304
14.2k
                            ? input.find_first_of("/\\")
16305
14.2k
                            : input.find('/');
16306
14.2k
      std::string_view path_view = input;
16307
14.2k
      if (location != std::string_view::npos) {
16308
9.45k
        path_view.remove_suffix(path_view.size() - location);
16309
9.45k
        input.remove_prefix(location + 1);
16310
9.45k
      }
16311
      // path_buffer is either path_view or it might point at a percent encoded
16312
      // temporary string.
16313
14.2k
      std::string_view path_buffer =
16314
14.2k
          (needs_percent_encoding &&
16315
7.69k
           ada::unicode::percent_encode<false>(
16316
7.69k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
16317
14.2k
              ? path_buffer_tmp
16318
14.2k
              : path_view;
16319
14.2k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
16320
1.66k
        helpers::shorten_path(path, type);
16321
1.66k
        if (location == std::string_view::npos) {
16322
75
          path += '/';
16323
75
        }
16324
12.5k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
16325
656
                 (location == std::string_view::npos)) {
16326
186
        path += '/';
16327
186
      }
16328
      // Otherwise, if path_buffer is not a single-dot path segment, then:
16329
12.3k
      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
11.8k
        if (type == ada::scheme::type::FILE && path.empty() &&
16334
2.23k
            checkers::is_windows_drive_letter(path_buffer)) {
16335
50
          path += '/';
16336
50
          path += path_buffer[0];
16337
50
          path += ':';
16338
50
          path_buffer.remove_prefix(2);
16339
50
          path.append(path_buffer);
16340
11.8k
        } else {
16341
          // Append path_buffer to url's path.
16342
11.8k
          path += '/';
16343
11.8k
          path.append(path_buffer);
16344
11.8k
        }
16345
11.8k
      }
16346
14.2k
      if (location == std::string_view::npos) {
16347
4.74k
        update_base_pathname(path);
16348
4.74k
        return;
16349
4.74k
      }
16350
14.2k
    } while (true);
16351
4.74k
  }
16352
5.27k
}
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
0
    std::optional<std::string_view> hash) {
16377
  // Let result be the result of creating a new URLPatternInit.
16378
0
  auto result = url_pattern_init{};
16379
16380
  // If protocol is not null, set result["protocol"] to protocol.
16381
0
  if (protocol.has_value()) result.protocol = *protocol;
16382
16383
  // If username is not null, set result["username"] to username.
16384
0
  if (username.has_value()) result.username = *username;
16385
16386
  // If password is not null, set result["password"] to password.
16387
0
  if (password.has_value()) result.password = *password;
16388
16389
  // If hostname is not null, set result["hostname"] to hostname.
16390
0
  if (hostname.has_value()) result.hostname = *hostname;
16391
16392
  // If port is not null, set result["port"] to port.
16393
0
  if (port.has_value()) result.port = *port;
16394
16395
  // If pathname is not null, set result["pathname"] to pathname.
16396
0
  if (pathname.has_value()) result.pathname = *pathname;
16397
16398
  // If search is not null, set result["search"] to search.
16399
0
  if (search.has_value()) result.search = *search;
16400
16401
  // If hash is not null, set result["hash"] to hash.
16402
0
  if (hash.has_value()) result.hash = *hash;
16403
16404
  // Let baseURL be null.
16405
0
  std::optional<url_aggregator> base_url{};
16406
16407
  // If init["baseURL"] exists:
16408
0
  if (init.base_url.has_value()) {
16409
    // Set baseURL to the result of parsing init["baseURL"].
16410
0
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
16411
    // If baseURL is failure, then throw a TypeError.
16412
0
    if (!parsing_result) {
16413
0
      return tl::unexpected(errors::type_error);
16414
0
    }
16415
0
    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
0
    if (!init.protocol.has_value()) {
16420
0
      ADA_ASSERT_TRUE(base_url.has_value());
16421
0
      std::string_view base_url_protocol = base_url->get_protocol();
16422
0
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
16423
0
      result.protocol =
16424
0
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
16425
0
    }
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
0
    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
0
    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
0
    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
0
      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
0
      result.hostname =
16455
0
          url_pattern_helpers::process_base_url_string(base_host, type);
16456
0
    }
16457
16458
    // If init contains none of "protocol", "hostname", and "port", then:
16459
0
    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
0
      result.port = base_url->get_port();
16463
0
    }
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
0
    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
0
    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
0
    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
0
  }
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
0
  if (init.protocol) {
16499
0
    auto process_result = process_protocol(*init.protocol, type);
16500
0
    if (!process_result) {
16501
0
      return tl::unexpected(process_result.error());
16502
0
    }
16503
0
    result.protocol = std::move(*process_result);
16504
0
  }
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
0
  if (init.username.has_value()) {
16509
0
    auto process_result = process_username(*init.username, type);
16510
0
    if (!process_result) {
16511
0
      return tl::unexpected(process_result.error());
16512
0
    }
16513
0
    result.username = std::move(*process_result);
16514
0
  }
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
0
  if (init.password.has_value()) {
16519
0
    auto process_result = process_password(*init.password, type);
16520
0
    if (!process_result) {
16521
0
      return tl::unexpected(process_result.error());
16522
0
    }
16523
0
    result.password = std::move(*process_result);
16524
0
  }
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
0
  if (init.hostname.has_value()) {
16529
0
    auto process_result = process_hostname(*init.hostname, type);
16530
0
    if (!process_result) {
16531
0
      return tl::unexpected(process_result.error());
16532
0
    }
16533
0
    result.hostname = std::move(*process_result);
16534
0
  }
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
0
  if (init.port) {
16539
0
    auto process_result =
16540
0
        process_port(*init.port, result.protocol.value_or("fake"), type);
16541
0
    if (!process_result) {
16542
0
      return tl::unexpected(process_result.error());
16543
0
    }
16544
0
    result.port = std::move(*process_result);
16545
0
  }
16546
16547
  // If init["pathname"] exists:
16548
0
  if (init.pathname.has_value()) {
16549
    // Set result["pathname"] to init["pathname"].
16550
0
    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
0
    if (base_url && !base_url->has_opaque_path &&
16558
0
        !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
0
    auto pathname_processing_result =
16587
0
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
16588
0
    if (!pathname_processing_result) {
16589
0
      return tl::unexpected(pathname_processing_result.error());
16590
0
    }
16591
0
    result.pathname = std::move(*pathname_processing_result);
16592
0
  }
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
0
  if (init.search) {
16597
0
    auto process_result = process_search(*init.search, type);
16598
0
    if (!process_result) {
16599
0
      return tl::unexpected(process_result.error());
16600
0
    }
16601
0
    result.search = std::move(*process_result);
16602
0
  }
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
0
  if (init.hash) {
16607
0
    auto process_result = process_hash(*init.hash, type);
16608
0
    if (!process_result) {
16609
0
      return tl::unexpected(process_result.error());
16610
0
    }
16611
0
    result.hash = std::move(*process_result);
16612
0
  }
16613
  // Return result.
16614
0
  return result;
16615
0
}
16616
16617
tl::expected<std::string, errors> url_pattern_init::process_protocol(
16618
0
    std::string_view value, process_type type) {
16619
0
  ada_log("process_protocol=", value, " [", type, "]");
16620
  // Let strippedValue be the given value with a single trailing U+003A (:)
16621
  // removed, if any.
16622
0
  if (value.ends_with(":")) {
16623
0
    value.remove_suffix(1);
16624
0
  }
16625
  // If type is "pattern" then return strippedValue.
16626
0
  if (type == process_type::pattern) {
16627
0
    return std::string(value);
16628
0
  }
16629
  // Return the result of running canonicalize a protocol given strippedValue.
16630
0
  return url_pattern_helpers::canonicalize_protocol(value);
16631
0
}
16632
16633
tl::expected<std::string, errors> url_pattern_init::process_username(
16634
0
    std::string_view value, process_type type) {
16635
  // If type is "pattern" then return value.
16636
0
  if (type == process_type::pattern) {
16637
0
    return std::string(value);
16638
0
  }
16639
  // Return the result of running canonicalize a username given value.
16640
0
  return url_pattern_helpers::canonicalize_username(value);
16641
0
}
16642
16643
tl::expected<std::string, errors> url_pattern_init::process_password(
16644
0
    std::string_view value, process_type type) {
16645
  // If type is "pattern" then return value.
16646
0
  if (type == process_type::pattern) {
16647
0
    return std::string(value);
16648
0
  }
16649
  // Return the result of running canonicalize a password given value.
16650
0
  return url_pattern_helpers::canonicalize_password(value);
16651
0
}
16652
16653
tl::expected<std::string, errors> url_pattern_init::process_hostname(
16654
0
    std::string_view value, process_type type) {
16655
0
  ada_log("process_hostname value=", value, " type=", type);
16656
  // If type is "pattern" then return value.
16657
0
  if (type == process_type::pattern) {
16658
0
    return std::string(value);
16659
0
  }
16660
  // Return the result of running canonicalize a hostname given value.
16661
0
  return url_pattern_helpers::canonicalize_hostname(value);
16662
0
}
16663
16664
tl::expected<std::string, errors> url_pattern_init::process_port(
16665
0
    std::string_view port, std::string_view protocol, process_type type) {
16666
  // If type is "pattern" then return portValue.
16667
0
  if (type == process_type::pattern) {
16668
0
    return std::string(port);
16669
0
  }
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
0
}
16674
16675
tl::expected<std::string, errors> url_pattern_init::process_pathname(
16676
0
    std::string_view value, std::string_view protocol, process_type type) {
16677
  // If type is "pattern" then return pathnameValue.
16678
0
  if (type == process_type::pattern) {
16679
0
    return std::string(value);
16680
0
  }
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
0
  if (protocol.empty() || scheme::is_special(protocol)) {
16685
0
    return url_pattern_helpers::canonicalize_pathname(value);
16686
0
  }
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
0
}
16692
16693
tl::expected<std::string, errors> url_pattern_init::process_search(
16694
0
    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
0
  if (value.starts_with("?")) {
16698
0
    value.remove_prefix(1);
16699
0
  }
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
0
  if (type == process_type::pattern) {
16707
0
    return std::string(value);
16708
0
  }
16709
  // Return the result of running canonicalize a search given strippedValue.
16710
0
  return url_pattern_helpers::canonicalize_search(value);
16711
0
}
16712
16713
tl::expected<std::string, errors> url_pattern_init::process_hash(
16714
0
    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
0
  if (value.starts_with("#")) {
16718
0
    value.remove_prefix(1);
16719
0
  }
16720
0
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16721
  // If type is "pattern" then return strippedValue.
16722
0
  if (type == process_type::pattern) {
16723
0
    return std::string(value);
16724
0
  }
16725
  // Return the result of running canonicalize a hash given strippedValue.
16726
0
  return url_pattern_helpers::canonicalize_hash(value);
16727
0
}
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
0
    url_pattern_compile_component_options options) {
16750
  // Let result be "^"
16751
0
  std::string result = "^";
16752
  // Reserve capacity to reduce reallocations
16753
0
  result.reserve(part_list.size() * 16);
16754
16755
  // Let name list be a new list
16756
0
  std::vector<std::string> name_list{};
16757
0
  name_list.reserve(part_list.size());
16758
16759
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16760
0
  std::string segment_wildcard_regexp;
16761
16762
  // For each part of part list:
16763
0
  for (const url_pattern_part& part : part_list) {
16764
    // If part's type is "fixed-text":
16765
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16766
      // If part's modifier is "none"
16767
0
      if (part.modifier == url_pattern_part_modifier::none) {
16768
0
        result.append(escape_regexp_string(part.value));
16769
0
      } else {
16770
        // (?:<fixed text>)<modifier>
16771
0
        result.append("(?:");
16772
0
        result.append(escape_regexp_string(part.value));
16773
0
        result.push_back(')');
16774
0
        result.append(convert_modifier_to_string(part.modifier));
16775
0
      }
16776
0
      continue;
16777
0
    }
16778
16779
    // Assert: part's name is not the empty string
16780
0
    ADA_ASSERT_TRUE(!part.name.empty());
16781
0
    name_list.push_back(part.name);
16782
16783
    // Use string_view to avoid copies where possible
16784
0
    std::string_view regexp_value = part.value;
16785
16786
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16787
      // Lazy generate segment wildcard regexp
16788
0
      if (segment_wildcard_regexp.empty()) {
16789
0
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16790
0
      }
16791
0
      regexp_value = segment_wildcard_regexp;
16792
0
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16793
0
      regexp_value = ".*";
16794
0
    }
16795
16796
    // If part's prefix is the empty string and part's suffix is the empty
16797
    // string
16798
0
    if (part.prefix.empty() && part.suffix.empty()) {
16799
      // If part's modifier is "none" or "optional"
16800
0
      if (part.modifier == url_pattern_part_modifier::none ||
16801
0
          part.modifier == url_pattern_part_modifier::optional) {
16802
        // (<regexp value>)<modifier>
16803
0
        result.push_back('(');
16804
0
        result.append(regexp_value);
16805
0
        result.push_back(')');
16806
0
        result.append(convert_modifier_to_string(part.modifier));
16807
0
      } else {
16808
        // ((?:<regexp value>)<modifier>)
16809
0
        result.append("((?:");
16810
0
        result.append(regexp_value);
16811
0
        result.push_back(')');
16812
0
        result.append(convert_modifier_to_string(part.modifier));
16813
0
        result.push_back(')');
16814
0
      }
16815
0
      continue;
16816
0
    }
16817
16818
    // If part's modifier is "none" or "optional"
16819
0
    if (part.modifier == url_pattern_part_modifier::none ||
16820
0
        part.modifier == url_pattern_part_modifier::optional) {
16821
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16822
0
      result.append("(?:");
16823
0
      result.append(escape_regexp_string(part.prefix));
16824
0
      result.push_back('(');
16825
0
      result.append(regexp_value);
16826
0
      result.push_back(')');
16827
0
      result.append(escape_regexp_string(part.suffix));
16828
0
      result.push_back(')');
16829
0
      result.append(convert_modifier_to_string(part.modifier));
16830
0
      continue;
16831
0
    }
16832
16833
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16834
0
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16835
0
                    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
0
    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
0
    result.append("(?:");
16845
    // Append the result of running escape a regexp string given part's prefix
16846
    // to the end of result.
16847
0
    result.append(escape_regexp_string(part.prefix));
16848
    // Append "((?:" to the end of result.
16849
0
    result.append("((?:");
16850
    // Append regexp value to the end of result.
16851
0
    result.append(regexp_value);
16852
    // Append ")(?:" to the end of result.
16853
0
    result.append(")(?:");
16854
    // Append the result of running escape a regexp string given part's suffix
16855
    // to the end of result.
16856
0
    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
0
    result.append(escape_regexp_string(part.prefix));
16860
    // Append "(?:" to the end of result.
16861
0
    result.append("(?:");
16862
    // Append regexp value to the end of result.
16863
0
    result.append(regexp_value);
16864
    // Append "))*)" to the end of result.
16865
0
    result.append("))*)");
16866
    // Append the result of running escape a regexp string given part's suffix
16867
    // to the end of result.
16868
0
    result.append(escape_regexp_string(part.suffix));
16869
    // Append ")" to the end of result.
16870
0
    result.append(")");
16871
16872
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16873
0
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16874
0
      result += "?";
16875
0
    }
16876
0
  }
16877
16878
  // Append "$" to the end of result
16879
0
  result += "$";
16880
16881
  // Return (result, name list)
16882
0
  return {std::move(result), std::move(name_list)};
16883
0
}
16884
16885
0
bool is_ipv6_address(std::string_view input) noexcept {
16886
  // If input's code point length is less than 2, then return false.
16887
0
  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
0
  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
0
  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
0
  return input.starts_with("\\[");
16898
0
}
16899
16900
std::string_view convert_modifier_to_string(
16901
0
    url_pattern_part_modifier modifier) {
16902
0
  switch (modifier) {
16903
      // If modifier is "zero-or-more", then return "*".
16904
0
    case url_pattern_part_modifier::zero_or_more:
16905
0
      return "*";
16906
    // If modifier is "optional", then return "?".
16907
0
    case url_pattern_part_modifier::optional:
16908
0
      return "?";
16909
    // If modifier is "one-or-more", then return "+".
16910
0
    case url_pattern_part_modifier::one_or_more:
16911
0
      return "+";
16912
    // Return the empty string.
16913
0
    default:
16914
0
      return "";
16915
0
  }
16916
0
}
16917
16918
std::string generate_segment_wildcard_regexp(
16919
0
    url_pattern_compile_component_options options) {
16920
  // Let result be "[^".
16921
0
  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
0
  result.append(escape_regexp_string(options.get_delimiter()));
16925
  // Append "]+?" to the end of result.
16926
0
  result.append("]+?");
16927
  // Return result.
16928
0
  ada_log("generate_segment_wildcard_regexp result: ", result);
16929
0
  return result;
16930
0
}
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
0
    std::string_view input) {
16962
0
  ada_log("canonicalize_protocol called with input=", input);
16963
0
  if (input.empty()) [[unlikely]] {
16964
0
    return "";
16965
0
  }
16966
16967
0
  if (input.ends_with(":")) {
16968
0
    input.remove_suffix(1);
16969
0
  }
16970
16971
  // Fast path: special schemes are already canonical
16972
0
  if (scheme::is_special(input)) {
16973
0
    return std::string(input);
16974
0
  }
16975
16976
  // Fast path: validate scheme chars and check for uppercase
16977
  // First char must be alpha (not +, -, ., or digit)
16978
0
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16979
0
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16980
0
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16981
0
    return tl::unexpected(errors::type_error);
16982
0
  }
16983
16984
0
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16985
0
  for (size_t i = 1; i < input.size(); i++) {
16986
0
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16987
0
    if (!(flags & CHAR_SCHEME)) {
16988
0
      return tl::unexpected(errors::type_error);
16989
0
    }
16990
0
    needs_lowercase |= flags & CHAR_UPPER;
16991
0
  }
16992
16993
0
  if (needs_lowercase == 0) {
16994
0
    return std::string(input);
16995
0
  }
16996
16997
0
  std::string result(input);
16998
0
  unicode::to_lower_ascii(result.data(), result.size());
16999
0
  return result;
17000
0
}
17001
17002
tl::expected<std::string, errors> canonicalize_username(
17003
0
    std::string_view input) {
17004
  // If value is the empty string, return value.
17005
0
  if (input.empty()) [[unlikely]] {
17006
0
    return "";
17007
0
  }
17008
  // Percent-encode the input using the userinfo percent-encode set.
17009
0
  size_t idx = ada::unicode::percent_encode_index(
17010
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
17011
0
  if (idx == input.size()) {
17012
    // No encoding needed, return input as-is
17013
0
    return std::string(input);
17014
0
  }
17015
  // Percent-encode from the first character that needs encoding
17016
0
  return ada::unicode::percent_encode(
17017
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
17018
0
}
17019
17020
tl::expected<std::string, errors> canonicalize_password(
17021
0
    std::string_view input) {
17022
  // If value is the empty string, return value.
17023
0
  if (input.empty()) [[unlikely]] {
17024
0
    return "";
17025
0
  }
17026
  // Percent-encode the input using the userinfo percent-encode set.
17027
0
  size_t idx = ada::unicode::percent_encode_index(
17028
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
17029
0
  if (idx == input.size()) {
17030
    // No encoding needed, return input as-is
17031
0
    return std::string(input);
17032
0
  }
17033
  // Percent-encode from the first character that needs encoding
17034
0
  return ada::unicode::percent_encode(
17035
0
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
17036
0
}
17037
17038
tl::expected<std::string, errors> canonicalize_hostname(
17039
0
    std::string_view input) {
17040
0
  ada_log("canonicalize_hostname input=", input);
17041
0
  if (input.empty()) [[unlikely]] {
17042
0
    return "";
17043
0
  }
17044
17045
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA
17046
0
  bool needs_processing = false;
17047
0
  for (char c : input) {
17048
0
    needs_processing |=
17049
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
17050
0
  }
17051
0
  if (!needs_processing) {
17052
0
    return std::string(input);
17053
0
  }
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
0
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
17062
0
  ADA_ASSERT_TRUE(url);
17063
  // if (!isValidHostnameInput(hostname)) return kj::none;
17064
0
  if (!url->set_hostname(input)) {
17065
    // If parseResult is failure, then throw a TypeError.
17066
0
    return tl::unexpected(errors::type_error);
17067
0
  }
17068
  // Return dummyURL's host, serialized, or empty string if it is null.
17069
0
  return std::string(url->get_hostname());
17070
0
}
17071
17072
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
17073
0
    std::string_view input) {
17074
0
  ada_log("canonicalize_ipv6_hostname input=", input);
17075
  // TODO: Optimization opportunity: Use lookup table to speed up checking
17076
0
  if (std::ranges::any_of(input, [](char c) {
17077
0
        return c != '[' && c != ']' && c != ':' &&
17078
0
               !unicode::is_ascii_hex_digit(c);
17079
0
      })) {
17080
0
    return tl::unexpected(errors::type_error);
17081
0
  }
17082
  // Append the result of running ASCII lowercase given code point to the end of
17083
  // result.
17084
0
  auto hostname = std::string(input);
17085
0
  unicode::to_lower_ascii(hostname.data(), hostname.size());
17086
0
  return hostname;
17087
0
}
17088
17089
tl::expected<std::string, errors> canonicalize_port(
17090
0
    std::string_view port_value) {
17091
  // If portValue is the empty string, return portValue.
17092
0
  if (port_value.empty()) [[unlikely]] {
17093
0
    return "";
17094
0
  }
17095
17096
  // Remove ASCII tab or newline characters
17097
0
  std::string trimmed(port_value);
17098
0
  helpers::remove_ascii_tab_or_newline(trimmed);
17099
17100
0
  if (trimmed.empty()) {
17101
0
    return "";
17102
0
  }
17103
17104
  // Input should start with a digit character
17105
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
17106
0
    return tl::unexpected(errors::type_error);
17107
0
  }
17108
17109
  // Find the first non-digit character
17110
0
  auto first_non_digit =
17111
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
17112
0
  std::string_view digits_to_parse =
17113
0
      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
0
  if (digits_to_parse.size() == 5) {
17122
0
    if (digits_to_parse > "65535") {
17123
0
      return tl::unexpected(errors::type_error);
17124
0
    }
17125
0
  } else if (digits_to_parse.size() > 5) {
17126
0
    return tl::unexpected(errors::type_error);
17127
0
  }
17128
0
  if (digits_to_parse[0] == '0' && digits_to_parse.size() > 1) {
17129
    // Leading zeros are not allowed for multi-digit ports
17130
0
    return tl::unexpected(errors::type_error);
17131
0
  }
17132
  // It is valid! Most times, we do not need to parse it into an integer.
17133
0
  return std::string(digits_to_parse);
17134
0
}
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
0
    std::string_view input) {
17198
0
  if (input.empty()) [[unlikely]] {
17199
0
    return "";
17200
0
  }
17201
17202
  // Fast path: simple pathnames (no . which needs normalization) can be
17203
  // returned as-is
17204
0
  bool needs_processing = false;
17205
0
  for (char c : input) {
17206
0
    needs_processing |=
17207
0
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
17208
0
  }
17209
0
  if (!needs_processing) {
17210
0
    return std::string(input);
17211
0
  }
17212
17213
  // Let leading slash be true if the first code point in value is U+002F (/)
17214
  // and otherwise false.
17215
0
  const bool leading_slash = input.starts_with("/");
17216
  // Let modified value be "/-" if leading slash is false and otherwise the
17217
  // empty string.
17218
0
  const auto modified_value = leading_slash ? "" : "/-";
17219
0
  const auto full_url =
17220
0
      std::string("fake://fake-url") + modified_value + std::string(input);
17221
0
  if (auto url = ada::parse<url_aggregator>(full_url, nullptr)) {
17222
0
    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
0
    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
0
      if (pathname.size() < 2) {
17229
0
        return tl::unexpected(errors::type_error);
17230
0
      }
17231
0
      return std::string(pathname.substr(2));
17232
0
    }
17233
0
    return std::string(pathname);
17234
0
  }
17235
  // If parseResult is failure, then throw a TypeError.
17236
0
  return tl::unexpected(errors::type_error);
17237
0
}
17238
17239
tl::expected<std::string, errors> canonicalize_opaque_pathname(
17240
0
    std::string_view input) {
17241
  // If value is the empty string, return value.
17242
0
  if (input.empty()) [[unlikely]] {
17243
0
    return "";
17244
0
  }
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
0
  if (auto url =
17250
0
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
17251
    // Return the result of URL path serializing dummyURL.
17252
0
    return std::string(url->get_pathname());
17253
0
  }
17254
  // If parseResult is failure, then throw a TypeError.
17255
0
  return tl::unexpected(errors::type_error);
17256
0
}
17257
17258
0
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
17259
  // If value is the empty string, return value.
17260
0
  if (input.empty()) [[unlikely]] {
17261
0
    return "";
17262
0
  }
17263
  // Remove leading '?' if present
17264
0
  std::string new_value;
17265
0
  new_value = input[0] == '?' ? input.substr(1) : input;
17266
  // Remove ASCII tab or newline characters
17267
0
  helpers::remove_ascii_tab_or_newline(new_value);
17268
17269
0
  if (new_value.empty()) {
17270
0
    return "";
17271
0
  }
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
0
  size_t idx = ada::unicode::percent_encode_index(
17277
0
      new_value, character_sets::QUERY_PERCENT_ENCODE);
17278
0
  if (idx == new_value.size()) {
17279
    // No encoding needed
17280
0
    return new_value;
17281
0
  }
17282
  // Percent-encode from the first character that needs encoding
17283
0
  return ada::unicode::percent_encode(
17284
0
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
17285
0
}
17286
17287
0
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
17288
  // If value is the empty string, return value.
17289
0
  if (input.empty()) [[unlikely]] {
17290
0
    return "";
17291
0
  }
17292
  // Remove leading '#' if present
17293
0
  std::string new_value;
17294
0
  new_value = input[0] == '#' ? input.substr(1) : input;
17295
  // Remove ASCII tab or newline characters
17296
0
  helpers::remove_ascii_tab_or_newline(new_value);
17297
17298
0
  if (new_value.empty()) {
17299
0
    return "";
17300
0
  }
17301
17302
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
17303
0
  size_t idx = ada::unicode::percent_encode_index(
17304
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
17305
0
  if (idx == new_value.size()) {
17306
    // No encoding needed
17307
0
    return new_value;
17308
0
  }
17309
  // Percent-encode from the first character that needs encoding
17310
0
  return ada::unicode::percent_encode(
17311
0
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
17312
0
}
17313
17314
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
17315
0
                                                  token_policy policy) {
17316
0
  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
0
  auto tokenizer = Tokenizer(input, policy);
17321
  // While tokenizer's index is less than tokenizer's input's code point length:
17322
0
  while (tokenizer.index < tokenizer.input.size()) {
17323
    // Run seek and get the next code point given tokenizer and tokenizer's
17324
    // index.
17325
0
    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
0
    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
0
    if (tokenizer.code_point == '*') {
17339
      // Run add a token with default position and length given tokenizer and
17340
      // "asterisk".
17341
0
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
17342
0
      ada_log("add ASTERISK token");
17343
      // Continue.
17344
0
      continue;
17345
0
    }
17346
17347
    // If tokenizer's code point is U+002B (+) or U+003F (?):
17348
0
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
17349
      // Run add a token with default position and length given tokenizer and
17350
      // "other-modifier".
17351
0
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
17352
      // Continue.
17353
0
      continue;
17354
0
    }
17355
17356
    // If tokenizer's code point is U+005C (\):
17357
0
    if (tokenizer.code_point == '\\') {
17358
      // If tokenizer's index is equal to tokenizer's input's code point length
17359
      // - 1:
17360
0
      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
0
        if (auto error = tokenizer.process_tokenizing_error(
17364
0
                tokenizer.next_index, tokenizer.index)) {
17365
0
          ada_log("process_tokenizing_error failed");
17366
0
          return tl::unexpected(*error);
17367
0
        }
17368
0
        continue;
17369
0
      }
17370
17371
      // Let escaped index be tokenizer's next index.
17372
0
      auto escaped_index = tokenizer.next_index;
17373
      // Run get the next code point given tokenizer.
17374
0
      tokenizer.get_next_code_point();
17375
0
      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
0
      tokenizer.add_token_with_default_length(
17385
0
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
17386
0
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
17387
0
              " with escaped index ", escaped_index);
17388
      // Continue.
17389
0
      continue;
17390
0
    }
17391
17392
    // If tokenizer's code point is U+007B ({):
17393
0
    if (tokenizer.code_point == '{') {
17394
      // Run add a token with default position and length given tokenizer and
17395
      // "open".
17396
0
      tokenizer.add_token_with_defaults(token_type::OPEN);
17397
0
      ada_log("add OPEN token");
17398
0
      continue;
17399
0
    }
17400
17401
    // If tokenizer's code point is U+007D (}):
17402
0
    if (tokenizer.code_point == '}') {
17403
      // Run add a token with default position and length given tokenizer and
17404
      // "close".
17405
0
      tokenizer.add_token_with_defaults(token_type::CLOSE);
17406
0
      ada_log("add CLOSE token");
17407
0
      continue;
17408
0
    }
17409
17410
    // If tokenizer's code point is U+003A (:):
17411
0
    if (tokenizer.code_point == ':') {
17412
      // Let name position be tokenizer's next index.
17413
0
      auto name_position = tokenizer.next_index;
17414
      // Let name start be name position.
17415
0
      auto name_start = name_position;
17416
0
      bool invalid_name = false;
17417
      // While name position is less than tokenizer's input's code point length:
17418
0
      while (name_position < tokenizer.input.size()) {
17419
        // Run seek and get the next code point given tokenizer and name
17420
        // position.
17421
0
        tokenizer.seek_and_get_next_code_point(name_position);
17422
0
        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
0
        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
0
        auto valid_code_point =
17436
0
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
17437
0
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
17438
0
                " first_code_point=", first_code_point,
17439
0
                " valid_code_point=", valid_code_point);
17440
        // If valid code point is false break.
17441
0
        if (!valid_code_point) break;
17442
        // Set name position to tokenizer's next index.
17443
0
        name_position = tokenizer.next_index;
17444
0
      }
17445
17446
0
      if (invalid_name) {
17447
0
        continue;
17448
0
      }
17449
17450
      // If name position is less than or equal to name start:
17451
0
      if (name_position <= name_start) {
17452
        // Run process a tokenizing error given tokenizer, name start, and
17453
        // tokenizer's index.
17454
0
        if (auto error = tokenizer.process_tokenizing_error(name_start,
17455
0
                                                            tokenizer.index)) {
17456
0
          ada_log("process_tokenizing_error failed");
17457
0
          return tl::unexpected(*error);
17458
0
        }
17459
        // Continue
17460
0
        continue;
17461
0
      }
17462
17463
      // Run add a token with default length given tokenizer, "name", name
17464
      // position, and name start.
17465
0
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
17466
0
                                              name_start);
17467
0
      continue;
17468
0
    }
17469
17470
    // If tokenizer's code point is U+0028 (():
17471
0
    if (tokenizer.code_point == '(') {
17472
      // Let depth be 1.
17473
0
      size_t depth = 1;
17474
      // Let regexp position be tokenizer's next index.
17475
0
      auto regexp_position = tokenizer.next_index;
17476
      // Let regexp start be regexp position.
17477
0
      auto regexp_start = regexp_position;
17478
      // Let error be false.
17479
0
      bool error = false;
17480
17481
      // While regexp position is less than tokenizer's input's code point
17482
      // length:
17483
0
      while (regexp_position < tokenizer.input.size()) {
17484
        // Run seek and get the next code point given tokenizer and regexp
17485
        // position.
17486
0
        tokenizer.seek_and_get_next_code_point(regexp_position);
17487
0
        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
0
        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
0
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
17514
          // Run process a tokenizing error given tokenizer, regexp start, and
17515
          // tokenizer's index.
17516
0
          if (auto process_error = tokenizer.process_tokenizing_error(
17517
0
                  regexp_start, tokenizer.index)) {
17518
0
            return tl::unexpected(*process_error);
17519
0
          }
17520
          // Set error to true;
17521
0
          error = true;
17522
0
          break;
17523
0
        }
17524
17525
        // If tokenizer's code point is U+005C (\):
17526
0
        if (tokenizer.code_point == '\\') {
17527
          // If regexp position equals tokenizer's input's code point length - 1
17528
0
          if (regexp_position == tokenizer.input.size() - 1) {
17529
            // Run process a tokenizing error given tokenizer, regexp start, and
17530
            // tokenizer's index.
17531
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17532
0
                    regexp_start, tokenizer.index)) {
17533
0
              return tl::unexpected(*process_error);
17534
0
            }
17535
            // Set error to true.
17536
0
            error = true;
17537
0
            break;
17538
0
          }
17539
          // Run get the next code point given tokenizer.
17540
0
          auto escaped_index = tokenizer.next_index;
17541
0
          tokenizer.get_next_code_point();
17542
0
          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
0
          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
0
          regexp_position = tokenizer.next_index;
17566
0
          continue;
17567
0
        }
17568
17569
        // If tokenizer's code point is U+0029 ()):
17570
0
        if (tokenizer.code_point == ')') {
17571
          // Decrement depth by 1.
17572
0
          depth--;
17573
          // If depth is 0:
17574
0
          if (depth == 0) {
17575
            // Set regexp position to tokenizer's next index.
17576
0
            regexp_position = tokenizer.next_index;
17577
            // Break.
17578
0
            break;
17579
0
          }
17580
0
        } else if (tokenizer.code_point == '(') {
17581
          // Otherwise if tokenizer's code point is U+0028 (():
17582
          // Increment depth by 1.
17583
0
          depth++;
17584
          // If regexp position equals tokenizer's input's code point length -
17585
          // 1:
17586
0
          if (regexp_position == tokenizer.input.size() - 1) {
17587
            // Run process a tokenizing error given tokenizer, regexp start, and
17588
            // tokenizer's index.
17589
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17590
0
                    regexp_start, tokenizer.index)) {
17591
0
              return tl::unexpected(*process_error);
17592
0
            }
17593
            // Set error to true.
17594
0
            error = true;
17595
0
            break;
17596
0
          }
17597
          // Let temporary position be tokenizer's next index.
17598
0
          auto temporary_position = tokenizer.next_index;
17599
          // Run get the next code point given tokenizer.
17600
0
          tokenizer.get_next_code_point();
17601
0
          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
0
          if (tokenizer.code_point != '?') {
17611
            // Run process a tokenizing error given tokenizer, regexp start, and
17612
            // tokenizer's index.
17613
0
            if (auto process_error = tokenizer.process_tokenizing_error(
17614
0
                    regexp_start, tokenizer.index)) {
17615
0
              return tl::unexpected(*process_error);
17616
0
            }
17617
            // Set error to true.
17618
0
            error = true;
17619
0
            break;
17620
0
          }
17621
          // Set tokenizer's next index to temporary position.
17622
0
          tokenizer.next_index = temporary_position;
17623
0
        }
17624
        // Set regexp position to tokenizer's next index.
17625
0
        regexp_position = tokenizer.next_index;
17626
0
      }
17627
17628
      // If error is true continue.
17629
0
      if (error) continue;
17630
      // If depth is not zero:
17631
0
      if (depth != 0) {
17632
        // Run process a tokenizing error given tokenizer, regexp start, and
17633
        // tokenizer's index.
17634
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17635
0
                regexp_start, tokenizer.index)) {
17636
0
          return tl::unexpected(*process_error);
17637
0
        }
17638
0
        continue;
17639
0
      }
17640
      // Let regexp length be regexp position - regexp start - 1.
17641
0
      auto regexp_length = regexp_position - regexp_start - 1;
17642
      // If regexp length is zero:
17643
0
      if (regexp_length == 0) {
17644
        // Run process a tokenizing error given tokenizer, regexp start, and
17645
        // tokenizer's index.
17646
0
        if (auto process_error = tokenizer.process_tokenizing_error(
17647
0
                regexp_start, tokenizer.index)) {
17648
0
          ada_log("process_tokenizing_error failed");
17649
0
          return tl::unexpected(*process_error);
17650
0
        }
17651
0
        continue;
17652
0
      }
17653
      // Run add a token given tokenizer, "regexp", regexp position, regexp
17654
      // start, and regexp length.
17655
0
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
17656
0
                          regexp_length);
17657
0
      continue;
17658
0
    }
17659
    // Run add a token with default position and length given tokenizer and
17660
    // "char".
17661
0
    tokenizer.add_token_with_defaults(token_type::CHAR);
17662
0
  }
17663
  // Run add a token with default length given tokenizer, "end", tokenizer's
17664
  // index, and tokenizer's index.
17665
0
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
17666
0
                                          tokenizer.index);
17667
17668
0
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
17669
  // Return tokenizer's token list.
17670
0
  return tokenizer.token_list;
17671
0
}
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
0
constexpr bool should_escape_pattern_char(char c) {
17683
0
  return escape_pattern_table[static_cast<uint8_t>(c)];
17684
0
}
17685
}  // namespace
17686
17687
0
std::string escape_pattern_string(std::string_view input) {
17688
0
  ada_log("escape_pattern_string called with input=", input);
17689
0
  if (input.empty()) [[unlikely]] {
17690
0
    return "";
17691
0
  }
17692
  // Assert: input is an ASCII string.
17693
0
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17694
  // Let result be the empty string.
17695
0
  std::string result{};
17696
  // Reserve extra space for potential escapes
17697
0
  result.reserve(input.size() * 2);
17698
17699
  // While index is less than input's length:
17700
0
  for (const char c : input) {
17701
0
    if (should_escape_pattern_char(c)) {
17702
      // Append U+005C (\) to the end of result.
17703
0
      result.push_back('\\');
17704
0
    }
17705
    // Append c to the end of result.
17706
0
    result.push_back(c);
17707
0
  }
17708
  // Return result.
17709
0
  return result;
17710
0
}
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
0
constexpr bool should_escape_regexp_char(char c) {
17723
0
  return escape_regexp_table[(uint8_t)c];
17724
0
}
17725
}  // namespace
17726
17727
0
std::string escape_regexp_string(std::string_view input) {
17728
  // Assert: input is an ASCII string.
17729
0
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17730
  // Let result be the empty string.
17731
0
  std::string result{};
17732
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17733
0
  result.reserve(input.size() * 2);
17734
0
  for (const char c : input) {
17735
0
    if (should_escape_regexp_char(c)) {
17736
      // Avoid temporary string allocation - directly append characters
17737
0
      result.push_back('\\');
17738
0
      result.push_back(c);
17739
0
    } else {
17740
0
      result.push_back(c);
17741
0
    }
17742
0
  }
17743
0
  return result;
17744
0
}
17745
17746
std::string process_base_url_string(std::string_view input,
17747
0
                                    url_pattern_init::process_type type) {
17748
  // If type is not "pattern" return input.
17749
0
  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
0
  return escape_pattern_string(input);
17754
0
}
17755
17756
constexpr bool is_absolute_pathname(
17757
0
    std::string_view input, url_pattern_init::process_type type) noexcept {
17758
  // If input is the empty string, then return false.
17759
0
  if (input.empty()) [[unlikely]] {
17760
0
    return false;
17761
0
  }
17762
  // If input[0] is U+002F (/), then return true.
17763
0
  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
0
    url_pattern_compile_component_options& options) {
17777
  // Let result be the empty string.
17778
0
  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
0
  for (size_t index = 0; index < part_list.size(); index++) {
17782
    // Let part be part list[index].
17783
    // Use reference to avoid copy
17784
0
    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
0
    const url_pattern_part* previous_part =
17789
0
        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
0
    const url_pattern_part* next_part =
17793
0
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17794
    // If part's type is "fixed-text" then:
17795
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17796
      // If part's modifier is "none" then:
17797
0
      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
0
        result.append(escape_pattern_string(part.value));
17801
0
        continue;
17802
0
      }
17803
      // Append "{" to the end of result.
17804
0
      result += "{";
17805
      // Append the result of running escape a pattern string given part's value
17806
      // to the end of result.
17807
0
      result.append(escape_pattern_string(part.value));
17808
      // Append "}" to the end of result.
17809
0
      result += "}";
17810
      // Append the result of running convert a modifier to a string given
17811
      // part's modifier to the end of result.
17812
0
      result.append(convert_modifier_to_string(part.modifier));
17813
0
      continue;
17814
0
    }
17815
    // Let custom name be true if part's name[0] is not an ASCII digit;
17816
    // otherwise false.
17817
0
    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
0
    bool needs_grouping =
17824
0
        !part.suffix.empty() ||
17825
0
        (!part.prefix.empty() && !options.get_prefix().empty() &&
17826
0
         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
0
    if (!needs_grouping && custom_name &&
17837
0
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17838
0
        part.modifier == url_pattern_part_modifier::none && next_part &&
17839
0
        next_part->prefix.empty() && next_part->suffix.empty()) {
17840
      // If next part's type is "fixed-text":
17841
0
      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
0
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17846
0
          needs_grouping = true;
17847
0
        }
17848
0
      } else {
17849
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17850
0
        needs_grouping = !next_part->name.empty() &&
17851
0
                         unicode::is_ascii_digit(next_part->name[0]);
17852
0
      }
17853
0
    }
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
0
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17863
0
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17864
0
        !previous_part->value.empty() && !options.get_prefix().empty() &&
17865
0
        previous_part->value.back() == options.get_prefix()[0]) {
17866
0
      needs_grouping = true;
17867
0
    }
17868
17869
    // Assert: part's name is not the empty string or null.
17870
0
    ADA_ASSERT_TRUE(!part.name.empty());
17871
17872
    // If needs grouping is true, then append "{" to the end of result.
17873
0
    if (needs_grouping) {
17874
0
      result.append("{");
17875
0
    }
17876
17877
    // Append the result of running escape a pattern string given part's prefix
17878
    // to the end of result.
17879
0
    result.append(escape_pattern_string(part.prefix));
17880
17881
    // If custom name is true:
17882
0
    if (custom_name) {
17883
      // Append ":" to the end of result.
17884
0
      result.append(":");
17885
      // Append part's name to the end of result.
17886
0
      result.append(part.name);
17887
0
    }
17888
17889
    // If part's type is "regexp" then:
17890
0
    if (part.type == url_pattern_part_type::REGEXP) {
17891
      // Append "(" to the end of result.
17892
0
      result.append("(");
17893
      // Append part's value to the end of result.
17894
0
      result.append(part.value);
17895
      // Append ")" to the end of result.
17896
0
      result.append(")");
17897
0
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17898
0
               !custom_name) {
17899
      // Otherwise if part's type is "segment-wildcard" and custom name is
17900
      // false: Append "(" to the end of result.
17901
0
      result.append("(");
17902
      // Append the result of running generate a segment wildcard regexp given
17903
      // options to the end of result.
17904
0
      result.append(generate_segment_wildcard_regexp(options));
17905
      // Append ")" to the end of result.
17906
0
      result.append(")");
17907
0
    } 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
0
      if (!custom_name &&
17917
0
          (!previous_part ||
17918
0
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17919
0
           previous_part->modifier != url_pattern_part_modifier::none ||
17920
0
           needs_grouping || !part.prefix.empty())) {
17921
0
        result.append("*");
17922
0
      } 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
0
        result.append("(.*)");
17927
0
      }
17928
0
    }
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
0
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17938
0
        !part.suffix.empty() &&
17939
0
        idna::valid_name_code_point(part.suffix[0], false)) {
17940
0
      result.append("\\");
17941
0
    }
17942
17943
    // Append the result of running escape a pattern string given part's suffix
17944
    // to the end of result.
17945
0
    result.append(escape_pattern_string(part.suffix));
17946
    // If needs grouping is true, then append "}" to the end of result.
17947
0
    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
0
    result.append(convert_modifier_to_string(part.modifier));
17951
0
  }
17952
  // Return result.
17953
0
  return result;
17954
0
}
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
    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
  auto flags = ignore_case
17972
                   ? std::regex::icase | std::regex_constants::ECMAScript
17973
                   : std::regex_constants::ECMAScript;
17974
  try {
17975
    return std::regex(pattern.data(), pattern.size(), flags);
17976
  } catch (const std::regex_error& e) {
17977
    (void)e;
17978
    ada_log("std_regex_provider::create_instance failed:", e.what());
17979
    return std::nullopt;
17980
  }
17981
}
17982
17983
std::optional<std::vector<std::optional<std::string>>>
17984
std_regex_provider::regex_search(std::string_view input,
17985
                                 const std::regex& pattern) {
17986
  // Use iterator-based regex_search to avoid string allocation
17987
  std::match_results<std::string_view::const_iterator> match_result;
17988
  try {
17989
    if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17990
                           std::regex_constants::match_any)) {
17991
      return std::nullopt;
17992
    }
17993
  } catch (const std::regex_error& e) {
17994
    (void)e;
17995
    ada_log("std_regex_provider::regex_search failed:", e.what());
17996
    return std::nullopt;
17997
  }
17998
  std::vector<std::optional<std::string>> matches;
17999
  // If input is empty, let's assume the result will be empty as well.
18000
  if (input.empty() || match_result.empty()) {
18001
    return matches;
18002
  }
18003
  matches.reserve(match_result.size());
18004
  for (size_t i = 1; i < match_result.size(); ++i) {
18005
    if (auto entry = match_result[i]; entry.matched) {
18006
      matches.emplace_back(entry.str());
18007
    } 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
      matches.emplace_back(std::nullopt);
18013
    }
18014
  }
18015
  return matches;
18016
}
18017
18018
bool std_regex_provider::regex_match(std::string_view input,
18019
                                     const std::regex& pattern) {
18020
  try {
18021
    return std::regex_match(input.begin(), input.end(), pattern);
18022
  } catch (const std::regex_error& e) {
18023
    (void)e;
18024
    ada_log("std_regex_provider::regex_match failed:", e.what());
18025
    return false;
18026
  }
18027
}
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 */