Coverage Report

Created: 2026-10-17 07:11

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-10-15 09:03:13 -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 <cstddef>
9
#include <cstdint>
10
#include <string_view>
11
12
namespace ada::checkers {
13
14
254k
ada_really_inline constexpr bool is_ipv4(std::string_view view) noexcept {
15
  // The string is not empty and does not contain upper case ASCII characters.
16
254k
  if (!last_label_may_be_a_number(view)) {
17
200k
    return false;
18
200k
  }
19
  // If the address ends with a dot, we need to prune it (special case).
20
53.7k
  if (view.ends_with('.')) {
21
1.54k
    view.remove_suffix(1);
22
1.54k
  }
23
  // From the last character, find the last dot.
24
53.7k
  size_t last_dot = view.rfind('.');
25
53.7k
  if (last_dot != std::string_view::npos) {
26
    // We have at least one dot.
27
13.2k
    view.remove_prefix(last_dot + 1);
28
13.2k
  }
29
  /** Optimization opportunity: we have basically identified the last number of
30
     the ipv4 if we return true here. We might as well parse it and have at
31
     least one number parsed when we get to parse_ipv4. */
32
53.7k
  if (std::ranges::all_of(view, ada::checkers::is_digit)) {
33
38.2k
    return true;
34
38.2k
  }
35
  // It could be hex (0x), but not if there is a single character.
36
15.5k
  if (view.size() == 1) {
37
0
    return false;
38
0
  }
39
  // It must start with 0x.
40
15.5k
  if (!view.starts_with("0x")) {
41
3.91k
    return false;
42
3.91k
  }
43
  // We must allow "0x".
44
11.6k
  if (view.size() == 2) {
45
1.11k
    return true;
46
1.11k
  }
47
  // We have 0x followed by some characters, we need to check that they are
48
  // hexadecimals.
49
10.5k
  view.remove_prefix(2);
50
10.5k
  return std::ranges::all_of(view, ada::unicode::is_lowercase_hex);
51
11.6k
}
52
53
// for use with path_signature, we include all characters that need percent
54
// encoding.
55
static constexpr std::array<uint8_t, 256> path_signature_table =
56
    []() consteval {
57
      std::array<uint8_t, 256> result{};
58
      for (size_t i = 0; i < 256; i++) {
59
        if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
60
            i == 0x3f || i == 0x5e || i == 0x60 || i == 0x7b || i == 0x7d ||
61
            i > 0x7e) {
62
          result[i] = 1;
63
        } else if (i == 0x25) {
64
          result[i] = 8;
65
        } else if (i == 0x2e) {
66
          result[i] = 4;
67
        } else if (i == 0x5c) {
68
          result[i] = 2;
69
        } else {
70
          result[i] = 0;
71
        }
72
      }
73
      return result;
74
    }();
75
76
ada_really_inline constexpr uint8_t path_signature(
77
437k
    std::string_view input) noexcept {
78
  // The path percent-encode set is the query percent-encode set and U+003F (?),
79
  // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
80
  // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
81
  // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
82
  // controls and all code points greater than U+007E (~).
83
437k
  size_t i = 0;
84
437k
  uint8_t accumulator{};
85
891k
  for (; i + 7 < input.size(); i += 8) {
86
454k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
87
454k
                           path_signature_table[uint8_t(input[i + 1])] |
88
454k
                           path_signature_table[uint8_t(input[i + 2])] |
89
454k
                           path_signature_table[uint8_t(input[i + 3])] |
90
454k
                           path_signature_table[uint8_t(input[i + 4])] |
91
454k
                           path_signature_table[uint8_t(input[i + 5])] |
92
454k
                           path_signature_table[uint8_t(input[i + 6])] |
93
454k
                           path_signature_table[uint8_t(input[i + 7])]);
94
454k
  }
95
1.28M
  for (; i < input.size(); i++) {
96
846k
    accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
97
846k
  }
98
437k
  return accumulator;
99
437k
}
100
101
ada_really_inline constexpr bool verify_dns_length(
102
0
    std::string_view input) noexcept {
103
0
  if (input.empty()) return false;
104
0
  if (input.back() == '.') {
105
0
    if (input.size() > 254) return false;
106
0
  } else if (input.size() > 253)
107
0
    return false;
108
109
0
  size_t start = 0;
110
0
  while (start < input.size()) {
111
0
    auto dot_location = input.find('.', start);
112
    // If not found, it's likely the end of the domain
113
0
    if (dot_location == std::string_view::npos) dot_location = input.size();
114
115
0
    auto label_size = dot_location - start;
116
0
    if (label_size > 63 || label_size == 0) return false;
117
118
0
    start = dot_location + 1;
119
0
  }
120
121
0
  return true;
122
0
}
123
124
}  // namespace ada::checkers
125
/* end file src/checkers.cpp */
126
/* begin file src/unicode.cpp */
127
128
129
ADA_PUSH_DISABLE_ALL_WARNINGS
130
/* begin file src/ada_idna.cpp */
131
/* auto-generated on 2026-10-09 11:29:39 -0400. Do not edit! */
132
/* begin file src/idna.cpp */
133
/* begin file src/unicode_transcoding.cpp */
134
/* begin file include/ada/idna/unicode_transcoding.h */
135
#ifndef ADA_IDNA_UNICODE_TRANSCODING_H
136
#define ADA_IDNA_UNICODE_TRANSCODING_H
137
138
#include <string>
139
#include <string_view>
140
141
namespace ada::idna {
142
143
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output);
144
145
size_t utf8_length_from_utf32(const char32_t* buf, size_t len);
146
147
size_t utf32_length_from_utf8(const char* buf, size_t len);
148
149
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output);
150
151
}  // namespace ada::idna
152
153
#endif  // ADA_IDNA_UNICODE_TRANSCODING_H
154
/* end file include/ada/idna/unicode_transcoding.h */
155
156
#include <algorithm>
157
#include <cstdint>
158
#include <cstring>
159
160
namespace ada::idna {
161
162
73.4k
size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) {
163
73.4k
  const uint8_t* data = reinterpret_cast<const uint8_t*>(buf);
164
73.4k
  size_t pos = 0;
165
73.4k
  const char32_t* start{utf32_output};
166
606k
  while (pos < len) {
167
    // try to convert the next block of 16 ASCII bytes
168
537k
    if (pos + 16 <= len) {  // if it is safe to read 16 more
169
                            // bytes, check that they are ascii
170
53.2k
      uint64_t v1;
171
53.2k
      std::memcpy(&v1, data + pos, sizeof(uint64_t));
172
53.2k
      uint64_t v2;
173
53.2k
      std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
174
53.2k
      uint64_t v{v1 | v2};
175
53.2k
      if ((v & 0x8080808080808080) == 0) {
176
8.84k
        size_t final_pos = pos + 16;
177
150k
        while (pos < final_pos) {
178
141k
          *utf32_output++ = char32_t(buf[pos]);
179
141k
          pos++;
180
141k
        }
181
8.84k
        continue;
182
8.84k
      }
183
53.2k
    }
184
528k
    uint8_t leading_byte = data[pos];  // leading byte
185
528k
    if (leading_byte < 0b10000000) {
186
      // converting one ASCII byte !!!
187
441k
      *utf32_output++ = char32_t(leading_byte);
188
441k
      pos++;
189
441k
    } else if ((leading_byte & 0b11100000) == 0b11000000) {
190
      // We have a two-byte UTF-8
191
56.4k
      if (pos + 1 >= len) {
192
215
        return 0;
193
215
      }  // minimal bound checking
194
56.2k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
195
712
        return 0;
196
712
      }
197
      // range check
198
55.5k
      uint32_t code_point =
199
55.5k
          (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
200
55.5k
      if (code_point < 0x80 || 0x7ff < code_point) {
201
203
        return 0;
202
203
      }
203
55.3k
      *utf32_output++ = char32_t(code_point);
204
55.3k
      pos += 2;
205
55.3k
    } else if ((leading_byte & 0b11110000) == 0b11100000) {
206
      // We have a three-byte UTF-8
207
23.5k
      if (pos + 2 >= len) {
208
209
        return 0;
209
209
      }  // minimal bound checking
210
211
23.3k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
212
368
        return 0;
213
368
      }
214
23.0k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
215
148
        return 0;
216
148
      }
217
      // range check
218
22.8k
      uint32_t code_point = (leading_byte & 0b00001111) << 12 |
219
22.8k
                            (data[pos + 1] & 0b00111111) << 6 |
220
22.8k
                            (data[pos + 2] & 0b00111111);
221
22.8k
      if (code_point < 0x800 || 0xffff < code_point ||
222
22.6k
          (0xd7ff < code_point && code_point < 0xe000)) {
223
292
        return 0;
224
292
      }
225
22.5k
      *utf32_output++ = char32_t(code_point);
226
22.5k
      pos += 3;
227
22.5k
    } else if ((leading_byte & 0b11111000) == 0b11110000) {  // 0b11110000
228
      // we have a 4-byte UTF-8 word.
229
6.12k
      if (pos + 3 >= len) {
230
214
        return 0;
231
214
      }  // minimal bound checking
232
5.90k
      if ((data[pos + 1] & 0b11000000) != 0b10000000) {
233
312
        return 0;
234
312
      }
235
5.59k
      if ((data[pos + 2] & 0b11000000) != 0b10000000) {
236
94
        return 0;
237
94
      }
238
5.50k
      if ((data[pos + 3] & 0b11000000) != 0b10000000) {
239
148
        return 0;
240
148
      }
241
242
      // range check
243
5.35k
      uint32_t code_point = (leading_byte & 0b00000111) << 18 |
244
5.35k
                            (data[pos + 1] & 0b00111111) << 12 |
245
5.35k
                            (data[pos + 2] & 0b00111111) << 6 |
246
5.35k
                            (data[pos + 3] & 0b00111111);
247
5.35k
      if (code_point <= 0xffff || 0x10ffff < code_point) {
248
504
        return 0;
249
504
      }
250
4.85k
      *utf32_output++ = char32_t(code_point);
251
4.85k
      pos += 4;
252
4.85k
    } else {
253
1.24k
      return 0;
254
1.24k
    }
255
528k
  }
256
68.7k
  return utf32_output - start;
257
73.4k
}
258
259
0
size_t utf8_length_from_utf32(const char32_t* buf, size_t len) {
260
  // We are not BOM aware.
261
0
  const uint32_t* p = reinterpret_cast<const uint32_t*>(buf);
262
0
  size_t counter{0};
263
0
  for (size_t i = 0; i != len; ++i) {
264
0
    ++counter;                                      // ASCII
265
0
    counter += static_cast<size_t>(p[i] > 0x7F);    // two-byte
266
0
    counter += static_cast<size_t>(p[i] > 0x7FF);   // three-byte
267
0
    counter += static_cast<size_t>(p[i] > 0xFFFF);  // four-bytes
268
0
  }
269
0
  return counter;
270
0
}
271
272
73.9k
size_t utf32_length_from_utf8(const char* buf, size_t len) {
273
73.9k
  const int8_t* p = reinterpret_cast<const int8_t*>(buf);
274
799k
  return std::count_if(p, std::next(p, len), [](int8_t c) {
275
    // -65 is 0b10111111, anything larger in two-complement's
276
    // should start a new code point.
277
799k
    return c > -65;
278
799k
  });
279
73.9k
}
280
281
0
size_t utf32_to_utf8(const char32_t* buf, size_t len, char* utf8_output) {
282
0
  const uint32_t* data = reinterpret_cast<const uint32_t*>(buf);
283
0
  size_t pos = 0;
284
0
  const char* start{utf8_output};
285
0
  while (pos < len) {
286
    // try to convert the next block of 2 ASCII characters
287
0
    if (pos + 2 <= len) {  // if it is safe to read 8 more
288
                           // bytes, check that they are ascii
289
0
      uint64_t v;
290
0
      std::memcpy(&v, data + pos, sizeof(uint64_t));
291
0
      if ((v & 0xFFFFFF80FFFFFF80) == 0) {
292
0
        *utf8_output++ = char(buf[pos]);
293
0
        *utf8_output++ = char(buf[pos + 1]);
294
0
        pos += 2;
295
0
        continue;
296
0
      }
297
0
    }
298
0
    uint32_t word = data[pos];
299
0
    if ((word & 0xFFFFFF80) == 0) {
300
      // will generate one UTF-8 bytes
301
0
      *utf8_output++ = char(word);
302
0
      pos++;
303
0
    } else if ((word & 0xFFFFF800) == 0) {
304
      // will generate two UTF-8 bytes
305
      // we have 0b110XXXXX 0b10XXXXXX
306
0
      *utf8_output++ = char((word >> 6) | 0b11000000);
307
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
308
0
      pos++;
309
0
    } else if ((word & 0xFFFF0000) == 0) {
310
      // will generate three UTF-8 bytes
311
      // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
312
0
      if (word >= 0xD800 && word <= 0xDFFF) {
313
0
        return 0;
314
0
      }
315
0
      *utf8_output++ = char((word >> 12) | 0b11100000);
316
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
317
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
318
0
      pos++;
319
0
    } else {
320
      // will generate four UTF-8 bytes
321
      // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX
322
      // 0b10XXXXXX
323
0
      if (word > 0x10FFFF) {
324
0
        return 0;
325
0
      }
326
0
      *utf8_output++ = char((word >> 18) | 0b11110000);
327
0
      *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
328
0
      *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
329
0
      *utf8_output++ = char((word & 0b111111) | 0b10000000);
330
0
      pos++;
331
0
    }
332
0
  }
333
0
  return utf8_output - start;
334
0
}
335
}  // namespace ada::idna
336
/* end file src/unicode_transcoding.cpp */
337
/* begin file src/mapping.cpp */
338
/* begin file include/ada/idna/mapping.h */
339
#ifndef ADA_IDNA_MAPPING_H
340
#define ADA_IDNA_MAPPING_H
341
342
#include <string>
343
#include <string_view>
344
345
namespace ada::idna {
346
347
// If the input is ascii, then the mapping is just -> lower case.
348
void ascii_map(char* input, size_t length);
349
// Map the characters according to IDNA, returning the empty string on error.
350
std::u32string map(std::u32string_view input);
351
// Map into an existing buffer (cleared on entry). Returns false if any code
352
// point is disallowed. Reusing the buffer avoids repeated heap allocations
353
// when called in a loop over multiple labels.
354
bool map(std::u32string_view input, std::u32string& out);
355
356
}  // namespace ada::idna
357
358
#endif
359
/* end file include/ada/idna/mapping.h */
360
361
#include <array>
362
#include <cstring>
363
#include <cstdint>
364
#include <string>
365
366
/* begin file src/table_store.hpp */
367
// Runtime store for compressed Unicode/IDNA tables.
368
// Large tables are DEFLATE-compressed (read-only) and expanded once on first
369
// use into a heap buffer so the working set does not bloat the on-disk binary.
370
// Hot-path lookups use the same O(1) multi-stage layout as the pre-compression
371
// code; compression only affects on-disk size and one-time init.
372
//
373
// Thread-safe without mutex: atomic CAS + spin-wait. ensure_tables() returns
374
// false if initialization fails (OOM, corrupt blob); callers must treat that
375
// as a hard error and not touch table pointers.
376
377
/* begin file src/raw_inflate.hpp */
378
// Minimal raw DEFLATE inflater (RFC 1951), enough for zlib raw streams.
379
// Returns number of output bytes written, or 0 on failure.
380
#include <cstdint>
381
#include <cstring>
382
383
namespace ada::idna::deflate {
384
385
struct BitReader {
386
  const uint8_t* p;
387
  const uint8_t* end;
388
  uint32_t acc = 0;
389
  int bits = 0;
390
391
  explicit BitReader(const uint8_t* data, size_t len)
392
1
      : p(data), end(data + len) {}
393
394
475k
  bool ensure(int n) {
395
540k
    while (bits < n) {
396
65.3k
      if (p >= end) return false;
397
65.3k
      acc |= uint32_t(*p++) << bits;
398
65.3k
      bits += 8;
399
65.3k
    }
400
475k
    return true;
401
475k
  }
402
475k
  uint32_t get(int n) {
403
475k
    if (!ensure(n)) return UINT32_MAX;
404
475k
    uint32_t v = acc & ((1u << n) - 1);
405
475k
    acc >>= n;
406
475k
    bits -= n;
407
475k
    return v;
408
475k
  }
409
0
  void align_byte() {
410
0
    acc >>= (bits & 7);
411
0
    bits -= (bits & 7);
412
0
  }
413
};
414
415
struct Huff {
416
  // canonical codes: for each length, list of symbols
417
  // Fast path: table for codes up to max_bits
418
  static constexpr int MAXBITS = 15;
419
  uint8_t lengths[288]{};
420
  int counts[MAXBITS + 1]{};
421
  int first_code[MAXBITS + 1]{};
422
  int16_t symbols[288]{};
423
  int nsymbols = 0;
424
  int max_bits = 0;
425
426
  // Base index into symbols[] for each code length (used by decode).
427
  int base_idx[MAXBITS + 1]{};
428
429
16
  bool build(const uint8_t* lens, int n) {
430
16
    std::memset(counts, 0, sizeof(counts));
431
16
    std::memset(first_code, 0, sizeof(first_code));
432
16
    std::memset(base_idx, 0, sizeof(base_idx));
433
16
    nsymbols = n;
434
16
    max_bits = 0;
435
1.99k
    for (int i = 0; i < n; i++) {
436
1.97k
      lengths[i] = lens[i];
437
1.97k
      if (lens[i]) {
438
1.93k
        counts[lens[i]]++;
439
1.93k
        if (lens[i] > max_bits) max_bits = lens[i];
440
1.93k
      }
441
1.97k
    }
442
    // Canonical first code for each bit length (RFC 1951).
443
16
    int code = 0;
444
256
    for (int bits = 1; bits <= MAXBITS; bits++) {
445
240
      code = (code + counts[bits - 1]) << 1;
446
240
      first_code[bits] = code;
447
240
    }
448
16
    int idx = 0;
449
159
    for (int bits = 1; bits <= max_bits; bits++) {
450
143
      base_idx[bits] = idx;
451
      // assign symbols in symbol order for codes of this length
452
21.8k
      for (int sym = 0; sym < n; sym++) {
453
21.6k
        if (lengths[sym] == bits) {
454
1.93k
          symbols[idx++] = static_cast<int16_t>(sym);
455
1.93k
        }
456
21.6k
      }
457
143
    }
458
16
    return true;
459
16
  }
460
461
71.4k
  int decode(BitReader& br) const {
462
71.4k
    if (max_bits == 0) return -1;
463
71.4k
    int code = 0;
464
442k
    for (int len = 1; len <= max_bits; len++) {
465
442k
      uint32_t b = br.get(1);
466
442k
      if (b == UINT32_MAX) return -1;
467
442k
      code = (code << 1) | int(b);
468
442k
      int first = first_code[len];
469
442k
      int cnt = counts[len];
470
442k
      if (cnt && code - first < cnt) {
471
71.4k
        return symbols[base_idx[len] + (code - first)];
472
71.4k
      }
473
442k
    }
474
0
    return -1;
475
71.4k
  }
476
};
477
478
// Fixed Huffman tables are built once at dynamic initialization (before main /
479
// single-threaded), so concurrent first-use of inflate cannot race.
480
2
inline Huff make_fixed_litlen_huff() {
481
2
  Huff h;
482
2
  uint8_t lens[288];
483
  // Fixed Huffman: 0-143:8, 144-255:9, 256-279:7, 280-287:8
484
290
  for (int i = 0; i <= 143; i++) lens[i] = 8;
485
226
  for (int i = 144; i <= 255; i++) lens[i] = 9;
486
50
  for (int i = 256; i <= 279; i++) lens[i] = 7;
487
18
  for (int i = 280; i <= 287; i++) lens[i] = 8;
488
2
  h.build(lens, 288);
489
2
  return h;
490
2
}
491
492
2
inline Huff make_fixed_dist_huff() {
493
2
  Huff h;
494
2
  uint8_t lens[32];
495
66
  for (int i = 0; i < 32; i++) lens[i] = 5;
496
2
  h.build(lens, 32);
497
2
  return h;
498
2
}
499
500
// NOLINTNEXTLINE(cert-err58-cpp) -- intentional process-lifetime tables
501
inline const Huff kFixedLitLenHuff = make_fixed_litlen_huff();
502
// NOLINTNEXTLINE(cert-err58-cpp)
503
inline const Huff kFixedDistHuff = make_fixed_dist_huff();
504
505
0
inline int fixed_litlen(BitReader& br) { return kFixedLitLenHuff.decode(br); }
506
507
0
inline int fixed_dist(BitReader& br) { return kFixedDistHuff.decode(br); }
508
509
// length and distance base tables
510
static const uint16_t len_base[29] = {
511
    3,  4,  5,  6,  7,  8,  9,  10, 11,  13,  15,  17,  19,  23, 27,
512
    31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
513
static const uint8_t len_extra[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
514
                                      1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
515
                                      4, 4, 4, 4, 5, 5, 5, 5, 0};
516
static const uint16_t dist_base[30] = {
517
    1,    2,    3,    4,    5,    7,    9,    13,    17,    25,
518
    33,   49,   65,   97,   129,  193,  257,  385,   513,   769,
519
    1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
520
static const uint8_t dist_extra[30] = {0, 0, 0,  0,  1,  1,  2,  2,  3,  3,
521
                                       4, 4, 5,  5,  6,  6,  7,  7,  8,  8,
522
                                       9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
523
524
inline size_t inflate_raw(const uint8_t* src, size_t src_len, uint8_t* dst,
525
1
                          size_t dst_cap) {
526
1
  BitReader br(src, src_len);
527
1
  size_t out = 0;
528
4
  for (;;) {
529
4
    uint32_t bfinal = br.get(1);
530
4
    uint32_t btype = br.get(2);
531
4
    if (bfinal == UINT32_MAX || btype == UINT32_MAX) return 0;
532
4
    if (btype == 0) {
533
      // stored
534
0
      br.align_byte();
535
0
      if (!br.ensure(16)) return 0;
536
      // read 16+16 from bit buffer awkwardly - use byte path
537
      // Align: bits is multiple of 8
538
      // Get len from remaining bits then bytes
539
0
      uint32_t len = br.get(16);
540
0
      uint32_t nlen = br.get(16);
541
0
      if (len == UINT32_MAX || nlen == UINT32_MAX) return 0;
542
0
      if ((len ^ 0xFFFF) != nlen) return 0;
543
      // After get, may have bits in acc from previous - for stored, should be
544
      // byte aligned Copy len bytes from p
545
0
      if (br.bits != 0) {
546
        // leftover bits should be 0 if aligned
547
0
      }
548
0
      if (size_t(br.end - br.p) < len) return 0;
549
0
      if (out + len > dst_cap) return 0;
550
0
      std::memcpy(dst + out, br.p, len);
551
0
      br.p += len;
552
0
      out += len;
553
4
    } else if (btype == 1 || btype == 2) {
554
4
      Huff lit, dist;
555
4
      if (btype == 1) {
556
        // use fixed via functions
557
4
      } else {
558
        // dynamic
559
4
        uint32_t hlit = br.get(5);
560
4
        if (hlit == UINT32_MAX) return 0;
561
4
        hlit += 257;
562
4
        uint32_t hdist = br.get(5);
563
4
        if (hdist == UINT32_MAX) return 0;
564
4
        hdist += 1;
565
4
        uint32_t hclen = br.get(4);
566
4
        if (hclen == UINT32_MAX) return 0;
567
4
        hclen += 4;
568
4
        static const int order[19] = {16, 17, 18, 0, 8,  7, 9,  6, 10, 5,
569
4
                                      11, 4,  12, 3, 13, 2, 14, 1, 15};
570
4
        uint8_t clen[19]{};
571
69
        for (uint32_t i = 0; i < hclen; i++) {
572
65
          uint32_t v = br.get(3);
573
65
          if (v == UINT32_MAX) return 0;
574
65
          clen[order[i]] = uint8_t(v);
575
65
        }
576
4
        Huff cl;
577
4
        if (!cl.build(clen, 19)) return 0;
578
4
        uint8_t lens[288 + 32]{};
579
4
        uint32_t n = hlit + hdist;
580
1.04k
        for (uint32_t i = 0; i < n;) {
581
1.03k
          int sym = cl.decode(br);
582
1.03k
          if (sym < 0) return 0;
583
1.03k
          if (sym < 16) {
584
973
            lens[i++] = uint8_t(sym);
585
973
          } else if (sym == 16) {
586
63
            uint32_t rep = br.get(2);
587
63
            if (rep == UINT32_MAX) return 0;
588
63
            rep += 3;
589
63
            if (i == 0) return 0;
590
63
            uint8_t v = lens[i - 1];
591
350
            while (rep--) lens[i++] = v;
592
63
          } else if (sym == 17) {
593
0
            uint32_t rep = br.get(3);
594
0
            if (rep == UINT32_MAX) return 0;
595
0
            rep += 3;
596
0
            while (rep--) lens[i++] = 0;
597
0
          } else if (sym == 18) {
598
0
            uint32_t rep = br.get(7);
599
0
            if (rep == UINT32_MAX) return 0;
600
0
            rep += 11;
601
0
            while (rep--) lens[i++] = 0;
602
0
          } else
603
0
            return 0;
604
1.03k
        }
605
4
        if (!lit.build(lens, int(hlit))) return 0;
606
4
        if (!dist.build(lens + hlit, int(hdist))) return 0;
607
4
      }
608
54.4k
      for (;;) {
609
54.4k
        int sym;
610
54.4k
        if (btype == 1)
611
0
          sym = fixed_litlen(br);
612
54.4k
        else
613
54.4k
          sym = lit.decode(br);
614
54.4k
        if (sym < 0) return 0;
615
54.4k
        if (sym < 256) {
616
38.5k
          if (out >= dst_cap) return 0;
617
38.5k
          dst[out++] = uint8_t(sym);
618
38.5k
        } else if (sym == 256) {
619
4
          break;
620
15.9k
        } else {
621
15.9k
          int len_code = sym - 257;
622
15.9k
          if (len_code < 0 || len_code > 28) return 0;
623
15.9k
          uint32_t extra = br.get(len_extra[len_code]);
624
15.9k
          if (len_extra[len_code] && extra == UINT32_MAX) return 0;
625
15.9k
          uint32_t length =
626
15.9k
              len_base[len_code] + (len_extra[len_code] ? extra : 0);
627
15.9k
          int dsym;
628
15.9k
          if (btype == 1)
629
0
            dsym = fixed_dist(br);
630
15.9k
          else
631
15.9k
            dsym = dist.decode(br);
632
15.9k
          if (dsym < 0 || dsym > 29) return 0;
633
15.9k
          uint32_t dextra = br.get(dist_extra[dsym]);
634
15.9k
          if (dist_extra[dsym] && dextra == UINT32_MAX) return 0;
635
15.9k
          uint32_t distance = dist_base[dsym] + (dist_extra[dsym] ? dextra : 0);
636
15.9k
          if (distance > out || out + length > dst_cap) return 0;
637
193k
          for (uint32_t k = 0; k < length; k++) {
638
177k
            dst[out] = dst[out - distance];
639
177k
            out++;
640
177k
          }
641
15.9k
        }
642
54.4k
      }
643
4
    } else {
644
0
      return 0;  // reserved
645
0
    }
646
4
    if (bfinal) break;
647
4
  }
648
1
  return out;
649
1
}
650
651
}  // namespace ada::idna::deflate
652
/* end file src/raw_inflate.hpp */
653
/* begin file src/table_blob.inc */
654
// Auto-generated by scripts/pack_tables.py - do not edit.
655
// Compressed Unicode/IDNA tables (raw DEFLATE).
656
// clang-format off
657
#ifndef ADA_IDNA_TABLE_BLOB_H
658
#define ADA_IDNA_TABLE_BLOB_H
659
#include <cstdint>
660
#include <cstddef>
661
namespace ada::idna::table_blob {
662
constexpr size_t uncompressed_size = 216077;
663
constexpr size_t compressed_size = 65331;
664
constexpr uint32_t uncompressed_crc32 = 0xC16EA7DEu;
665
constexpr size_t decomposition_block_rows = 70;
666
constexpr size_t decomposition_block_cols = 257;
667
constexpr size_t ccc_block_rows = 69;
668
constexpr size_t ccc_block_cols = 256;
669
constexpr size_t composition_block_rows = 27;
670
constexpr size_t composition_block_cols = 257;
671
constexpr size_t id_continue_count = 1437;
672
constexpr size_t id_start_count = 789;
673
constexpr size_t dir_table_count = 1608;
674
constexpr size_t combining_range_count = 333;
675
constexpr size_t joining_table_count = 533;
676
// Offsets into the decompressed buffer:
677
constexpr size_t off_idna_stage1 = 0;
678
constexpr size_t count_idna_stage1 = 4081;
679
constexpr size_t off_idna_stage2 = 8162;
680
constexpr size_t count_idna_stage2 = 11712;
681
constexpr size_t off_idna_bool_blocks = 31592;
682
constexpr size_t count_idna_bool_blocks = 225;
683
constexpr size_t off_idna_utf8_mappings = 33392;
684
constexpr size_t count_idna_utf8_mappings = 17651;
685
constexpr size_t off_decomposition_index = 51043;
686
constexpr size_t count_decomposition_index = 4352;
687
constexpr size_t off_decomposition_block = 55396;
688
constexpr size_t count_decomposition_block = 17990;
689
constexpr size_t off_decomposition_data = 91376;
690
constexpr size_t count_decomposition_data = 9255;
691
constexpr size_t off_ccc_index = 128396;
692
constexpr size_t count_ccc_index = 4352;
693
constexpr size_t off_ccc_block = 132748;
694
constexpr size_t count_ccc_block = 17664;
695
constexpr size_t off_composition_index = 150412;
696
constexpr size_t count_composition_index = 4352;
697
constexpr size_t off_composition_block = 154764;
698
constexpr size_t count_composition_block = 6939;
699
constexpr size_t off_composition_data = 168644;
700
constexpr size_t count_composition_data = 1923;
701
constexpr size_t off_id_continue_flat = 176336;
702
constexpr size_t count_id_continue_flat = 2874;
703
constexpr size_t off_id_start_flat = 187832;
704
constexpr size_t count_id_start_flat = 1578;
705
constexpr size_t off_dir_start = 194144;
706
constexpr size_t count_dir_start = 1608;
707
constexpr size_t off_dir_final = 200576;
708
constexpr size_t count_dir_final = 1608;
709
constexpr size_t off_dir_value = 207008;
710
constexpr size_t count_dir_value = 1608;
711
constexpr size_t off_combining_flat = 208616;
712
constexpr size_t count_combining_flat = 666;
713
constexpr size_t off_joining_start = 211280;
714
constexpr size_t count_joining_start = 533;
715
constexpr size_t off_joining_final = 213412;
716
constexpr size_t count_joining_final = 533;
717
constexpr size_t off_joining_value = 215544;
718
constexpr size_t count_joining_value = 533;
719
alignas(8) inline constexpr uint8_t compressed[] = {
720
0xec,0x9c,0x09,0x40,0x54,0x55,0xfb,0xff,0x1f,0x18,0x59,0x94,0x65,0x9c,0x19,0xb6,
721
0x51,0x61,0x10,0x18,0x98,0x61,0x9f,0x19,0x18,0x76,0x66,0x58,0xda,0xcb,0xb6,0xb7,
722
0x3d,0x2b,0xf7,0xdc,0xb7,0xb4,0xb4,0xd2,0xcb,0x2e,0x28,0xe0,0x86,0x0a,0xb2,0x08,
723
0x8a,0x1b,0xa2,0x02,0xa2,0xec,0x60,0x88,0x8a,0xa5,0x88,0x88,0x65,0x6f,0x96,0x9a,
724
0x20,0x58,0x5a,0x56,0xb6,0x58,0x32,0xff,0xef,0xbd,0x33,0xa0,0x99,0xbd,0xf5,0x96,
725
0xbd,0xbf,0xdf,0xfb,0xfb,0x37,0x0f,0x9f,0x73,0xce,0x3d,0xf7,0x9c,0xf3,0x3c,0xe7,
726
0xb9,0xe7,0x9e,0x7b,0xce,0x1d,0x80,0x18,0x22,0x2d,0x31,0xd4,0x44,0x64,0xa4,0x35,
727
0x62,0x8c,0x9a,0x8c,0xc8,0x58,0x6b,0xcc,0x18,0x13,0xd3,0x64,0x4c,0x3c,0x2d,0x8f,
728
0xe1,0x35,0xf1,0x68,0x90,0x76,0x10,0x33,0xa8,0x69,0x10,0x99,0x18,0x31,0xc6,0x8c,
729
0xd6,0x84,0x18,0x1e,0x33,0x88,0x31,0x61,0x4c,0x19,0x33,0xc6,0x9c,0x19,0xcc,0x0c,
730
0x61,0x2c,0x18,0x62,0x18,0x13,0x4b,0xa6,0xc9,0x84,0x4c,0xb5,0xa6,0x56,0x8c,0x35,
731
0xc3,0x67,0x18,0xd3,0xa1,0x8c,0x80,0x11,0x32,0x22,0xc6,0x86,0xb1,0x65,0xec,0x18,
732
0x7b,0xc6,0x81,0x11,0x33,0x4d,0xa6,0xc3,0x18,0x32,0xd3,0x9a,0x31,0x66,0x4d,0x66,
733
0x64,0x3e,0x1c,0xf5,0x88,0xd1,0x9a,0x33,0xe6,0xd0,0x67,0x4e,0xdc,0xd1,0x08,0xc6,
734
0x91,0x71,0x62,0x24,0x8c,0x33,0x33,0x92,0xa1,0xc1,0xfa,0xbc,0x9f,0x8b,0x0b,0xe3,
735
0xca,0xb8,0x31,0x52,0x46,0x3b,0xd8,0x9d,0x61,0x06,0xbb,0x32,0x1e,0x8c,0x8c,0x91,
736
0x33,0x9e,0x8c,0x17,0xe3,0xcd,0xf8,0x30,0xbe,0x8c,0x1f,0xe3,0x8f,0x52,0x0a,0xa0,
737
0x64,0x54,0x4c,0x00,0xd3,0x34,0x38,0x90,0xa1,0x21,0xda,0x21,0xcc,0x10,0x68,0x19,
738
0x42,0x16,0x5a,0x0b,0xc6,0xa2,0xc9,0x82,0x2c,0xb5,0x96,0x8c,0x65,0x93,0x25,0x59,
739
0x69,0xad,0xd4,0x0c,0x63,0xd5,0x64,0x45,0xd6,0xb0,0xc5,0x5a,0xaf,0x83,0x31,0xc4,
740
0x41,0x4c,0x93,0x35,0xf1,0xb5,0xfc,0x3b,0xd9,0x71,0x27,0x61,0xf8,0x4d,0x6c,0xd9,
741
0xa1,0xc4,0x04,0xeb,0xfb,0x36,0x94,0x19,0xda,0x34,0x94,0x04,0x21,0x8c,0x56,0x10,
742
0xca,0x84,0x21,0x27,0x9c,0x61,0x04,0x4d,0x02,0x12,0x6a,0x85,0x8c,0xb0,0x49,0x48,
743
0xa2,0x08,0x46,0x2b,0x62,0x44,0x4d,0x22,0xb2,0xd1,0xda,0x44,0x32,0x8c,0x4d,0x93,
744
0x0d,0xd9,0x6a,0x6d,0x19,0xdb,0x26,0x5b,0xb2,0xd3,0xda,0xfd,0x5e,0xbd,0x7f,0xcb,
745
0xdf,0xf2,0xb7,0xfc,0x35,0xa2,0x61,0xb4,0x03,0xe9,0x28,0x86,0xb1,0x6b,0xb2,0x8b,
746
0x66,0xc8,0x5e,0x6b,0xcf,0xd8,0x37,0xd9,0xc7,0x30,0x48,0x33,0xb1,0xe0,0x1e,0x70,
747
0x2f,0x73,0x1f,0x73,0x3f,0xe2,0x07,0x98,0x07,0x19,0x72,0xd0,0x3a,0x3c,0xf4,0xb7,
748
0xf7,0xfe,0x42,0x79,0x98,0x79,0x84,0x19,0xf5,0xb7,0x70,0xc2,0x38,0x34,0x39,0x90,
749
0x58,0x2b,0x66,0xc4,0x4d,0x62,0x1a,0xa6,0x1d,0xc6,0x0c,0x6b,0x1a,0x46,0xc3,0xb5,
750
0xc3,0x99,0xe1,0x4d,0xc3,0x69,0x84,0x76,0x04,0x33,0xa2,0x69,0x04,0x39,0x6a,0x1d,
751
0x19,0xc7,0x26,0x47,0x72,0xd2,0x3a,0x31,0x4e,0x4d,0x4e,0x24,0xd1,0x4a,0x1e,0x65,
752
0x1e,0x83,0x27,0x1f,0x67,0x9e,0x40,0xf8,0x24,0xf3,0x0f,0xae,0xad,0xa7,0x98,0xa7,
753
0x99,0x67,0x98,0x67,0x99,0xe7,0x98,0xe7,0x19,0x46,0x82,0x67,0xa6,0x84,0x9c,0x5f,
754
0x60,0xb4,0xce,0x8c,0xf3,0x8b,0x03,0xbe,0xbf,0x8f,0x19,0xcd,0x34,0x39,0x8f,0x62,
755
0x5e,0x62,0x5e,0x66,0x5e,0x61,0xc6,0x30,0x63,0x99,0x71,0xcc,0x78,0x66,0x02,0x33,
756
0x91,0x99,0xc4,0xbc,0xca,0x4c,0x66,0xa6,0x30,0x53,0x99,0x69,0x68,0x8b,0x98,0xe9,
757
0x0c,0x8d,0x9c,0xc1,0xcc,0x64,0xb4,0x23,0x67,0x71,0xad,0xcf,0x66,0xe6,0x30,0x73,
758
0x99,0x17,0x98,0xd7,0x98,0x79,0xcc,0x7c,0x9c,0x7f,0x9d,0x79,0x83,0x59,0xc0,0x2c,
759
0x64,0xde,0x44,0xfa,0x2d,0xe6,0x6d,0x66,0x11,0xb3,0x98,0x61,0x98,0x38,0x26,0x9e,
760
0x49,0x60,0x12,0x91,0x97,0x04,0x92,0xb9,0x9a,0x29,0xcc,0x12,0xa4,0x53,0x99,0x34,
761
0x66,0x29,0xb3,0x8c,0x49,0xe7,0xf2,0x32,0xd8,0xbe,0x8f,0xcc,0x64,0x96,0x33,0x2b,
762
0x98,0x95,0xcc,0x2a,0x9c,0x5f,0xcd,0x64,0x61,0x7d,0xb0,0x86,0x59,0x8b,0x33,0xeb,
763
0x98,0x6c,0x26,0x87,0x59,0x8f,0x54,0x2e,0x93,0xc7,0xe4,0x33,0x05,0x06,0x6f,0x6d,
764
0x60,0x0a,0x99,0x22,0x66,0x23,0xb3,0xe9,0x5f,0x8e,0xaf,0x71,0x9c,0xfd,0xfd,0x52,
765
0x3c,0x90,0x4a,0xbf,0x4b,0xd7,0x6c,0x33,0xb3,0xe5,0x37,0xc7,0xf8,0x56,0x66,0xdb,
766
0xff,0xe0,0x1d,0xf6,0xf8,0x1d,0xf2,0xd2,0xff,0x4f,0xde,0x3f,0x69,0x7f,0xb0,0xde,
767
0xed,0xde,0x71,0x65,0xb6,0x33,0x25,0xcc,0x0e,0xa4,0x4a,0x99,0x9d,0x77,0xd4,0xd0,
768
0x34,0x92,0x5c,0x76,0xe1,0xfc,0x6e,0xa6,0x8c,0x29,0xff,0xff,0x64,0xa6,0xae,0x60,
769
0xf6,0x70,0xbe,0xfa,0xd7,0xe3,0xbd,0x92,0xd9,0xfb,0xff,0xd9,0xac,0xbd,0x6f,0xa0,
770
0xef,0x5a,0x97,0xaa,0x5b,0x3c,0x91,0x71,0xd7,0x34,0x10,0x53,0xcd,0x30,0x2e,0xff,
771
0x73,0x3d,0xd4,0xf7,0xa7,0xc9,0xe5,0xd6,0xeb,0x5c,0xc3,0xd4,0x32,0x75,0xdc,0x9a,
772
0xaa,0xde,0x90,0x23,0x63,0x43,0x57,0xad,0x2b,0xe3,0x4a,0x4c,0x03,0x9e,0x00,0x8d,
773
0x6c,0x1d,0xfd,0xdd,0xe2,0x4a,0x6e,0x5a,0x37,0xc6,0xad,0xc9,0x8d,0xa4,0x5a,0x29,
774
0x23,0x6d,0x92,0x92,0xbb,0xd6,0x9d,0x71,0x6f,0x72,0x27,0x0f,0xad,0x07,0xe3,0x71,
775
0xa7,0x71,0xb4,0x1f,0xf5,0xde,0xf9,0x4d,0xbb,0x9a,0x3c,0x48,0xa6,0x95,0x31,0xb2,
776
0x26,0x59,0x33,0x8e,0x0f,0x30,0x2d,0x03,0xe7,0x0e,0x32,0x87,0x6e,0x2b,0x7d,0xd8,
777
0x10,0xb7,0x1a,0xe2,0x23,0x86,0xf8,0x5d,0x83,0xc6,0xf7,0x18,0x92,0x1f,0xfd,0x15,
778
0x4d,0xc7,0x98,0x36,0x84,0xc7,0x0d,0x47,0x5a,0x39,0x23,0x6f,0x92,0xb7,0x0f,0x9c,
779
0xf5,0x42,0xed,0x13,0x4c,0x07,0x43,0x9e,0x5a,0x4f,0xc6,0xf3,0x24,0xd3,0xe4,0x49,
780
0x5e,0x77,0x9a,0x57,0x7e,0x2e,0x9d,0x86,0xf8,0x14,0xf3,0x3e,0xf3,0x01,0x73,0x9a,
781
0xf9,0xf0,0x96,0x73,0xff,0x04,0x1f,0x71,0xa9,0x33,0x8c,0xd6,0xeb,0xdf,0x9d,0xbf,
782
0xfe,0x96,0xbf,0xe5,0x6f,0xf9,0x5b,0xfe,0x96,0x7f,0x25,0xaf,0xfe,0xaf,0xb1,0xe4,
783
0xe3,0xff,0x42,0xef,0xd5,0xfd,0x7f,0x33,0x4e,0x3e,0xb9,0x43,0xde,0x92,0xbb,0xbb,
784
0xef,0xf7,0x6a,0xf2,0x22,0x6f,0xad,0x37,0xe3,0xdd,0xe4,0x4d,0x3e,0x5a,0x1f,0xc6,
785
0xe7,0xcf,0xed,0x5f,0xfe,0xf7,0xc8,0xd9,0xbf,0xe7,0x19,0x4e,0xd2,0xfe,0x7e,0xbb,
786
0xf5,0xb7,0xfc,0x2d,0x7f,0xcb,0xff,0x49,0xf9,0x7b,0x7e,0xff,0xab,0x45,0xa7,0x33,
787
0x22,0x1e,0x99,0x90,0x19,0x0d,0x26,0x0b,0xb2,0x22,0x3e,0x09,0x48,0x44,0xb6,0x64,
788
0x4f,0x62,0x1a,0x4e,0x8e,0x24,0xa1,0x91,0xe4,0x4a,0x52,0xf2,0x20,0x39,0x79,0x91,
789
0x0f,0xf9,0x91,0x82,0x54,0xa4,0xbb,0x6b,0x9f,0xbe,0x3f,0x29,0x81,0xb7,0xd9,0x12,
790
0x44,0x6c,0x8f,0xd8,0x14,0x21,0x0c,0xe3,0x52,0x1a,0x8a,0xa2,0x18,0xba,0x8f,0x4b,
791
0x3f,0x48,0xa3,0xd0,0x2b,0x9d,0xee,0x31,0x7a,0x9a,0x5e,0x44,0x3c,0x96,0x26,0xd0,
792
0xab,0x34,0x95,0x66,0xd0,0x6c,0x7a,0x8d,0x5e,0xa7,0x85,0xf4,0x36,0xdc,0x92,0x40,
793
0xc9,0x94,0x4a,0xcb,0x28,0x93,0x56,0x52,0x16,0xad,0xa3,0xf5,0x94,0x4f,0x85,0xb4,
794
0x09,0xe5,0xb7,0xd0,0x76,0x2a,0xa5,0xdd,0x54,0x41,0x7b,0xa9,0xfa,0x2e,0xf8,0xa1,
795
0x0e,0x6d,0x34,0x82,0x77,0x40,0x0b,0x38,0x0c,0xde,0x05,0xc7,0x40,0x3b,0x38,0x09,
796
0xde,0x07,0x1f,0x82,0x33,0xe0,0x2c,0xf8,0x14,0x74,0x83,0x5e,0xf0,0x39,0xf8,0x02,
797
0x7c,0x05,0xae,0x81,0xef,0xc1,0x8f,0xa0,0x8f,0xf5,0x83,0x91,0x4e,0x37,0x08,0x98,
798
0x1b,0x99,0x1b,0x59,0x20,0xb6,0x36,0x62,0x35,0x0a,0x10,0xda,0x00,0x7b,0x30,0xcc,
799
0x68,0x98,0x91,0x13,0xe2,0x91,0xc0,0x0d,0x78,0x00,0x4f,0x23,0x5f,0x84,0x0a,0x10,
800
0x00,0x82,0x40,0x28,0x88,0x00,0x5a,0x10,0x03,0xee,0x05,0x0f,0x80,0x87,0xc1,0xa3,
801
0xe0,0x09,0xf0,0x14,0x78,0x16,0xbc,0x00,0x5e,0x02,0x63,0xc0,0x78,0x30,0x09,0x4c,
802
0x01,0xd3,0xc1,0x2c,0x30,0xd7,0x68,0x3e,0xc2,0x05,0xe0,0x2d,0x20,0x85,0x95,0x8b,
803
0x8d,0xe2,0x91,0x4a,0x02,0x4b,0x8c,0x96,0x22,0xcc,0x30,0x5a,0x61,0xb4,0x9a,0xb3,
804
0x74,0xad,0x51,0x8e,0x51,0x9e,0xd1,0x06,0xa4,0x37,0x1a,0x6d,0x46,0xb8,0xcd,0x68,
805
0x87,0xd1,0x2e,0x23,0xbd,0xdf,0xca,0x8d,0x2a,0x91,0xaa,0x32,0xaa,0x45,0xd8,0x00,
806
0xf6,0x83,0x03,0x46,0x87,0x10,0x1e,0xe1,0x4a,0x1c,0x45,0x78,0xdc,0xa8,0x03,0xe1,
807
0x29,0xa3,0xd3,0x46,0x1f,0x21,0xfe,0x04,0x9c,0x37,0xea,0x32,0xd4,0xef,0x31,0xfa,
808
0xf9,0x75,0xf8,0xcc,0x88,0x95,0x2f,0x38,0xf9,0x8a,0x93,0x6b,0x28,0xf1,0x3d,0xf8,
809
0x11,0xf4,0x01,0x23,0x63,0x78,0x13,0x98,0x81,0x21,0xc6,0x6c,0x1d,0x2b,0x84,0x43,
810
0x81,0x08,0xd8,0x01,0x31,0x18,0x01,0x24,0xc0,0x05,0x48,0xb9,0x52,0x32,0x63,0x56,
811
0xbc,0x90,0xf6,0x35,0x56,0x18,0x07,0x20,0x0e,0x02,0xa1,0x20,0x02,0x68,0x41,0x0c,
812
0xb8,0x17,0x3c,0x00,0x1e,0x06,0x8f,0x82,0x27,0xc0,0x53,0xe0,0x59,0xf0,0x02,0x78,
813
0x09,0x8c,0x01,0xe3,0xc1,0x24,0x30,0x05,0x4c,0x07,0xb3,0xc0,0x5c,0x30,0x1f,0x2c,
814
0x00,0x6f,0x81,0xc5,0x20,0x1e,0x24,0x81,0x25,0x60,0xa9,0xf1,0xcf,0xfb,0x9a,0x61,
815
0xbc,0x12,0x39,0x59,0xc6,0xeb,0xb8,0xfc,0x5c,0x84,0x05,0xc6,0x45,0xc6,0xc5,0xc6,
816
0x5b,0x91,0x2a,0x01,0x3b,0x41,0x19,0xd8,0x63,0xac,0xfb,0xaf,0xff,0xf0,0x69,0x9f,
817
0xb1,0x08,0x33,0x58,0x8d,0x71,0xbd,0x71,0x93,0xb1,0x0f,0x66,0xaf,0x3f,0xd7,0x5e,
818
0xb3,0xf1,0x21,0xe3,0x77,0x8d,0xdb,0x8c,0x3b,0x8c,0xdf,0xe7,0xbc,0xb3,0xd9,0xc8,
819
0x1e,0xb3,0xa3,0x1f,0xfd,0xf3,0x0f,0xfa,0xea,0x63,0xe3,0x73,0xa8,0x79,0xc1,0xf8,
820
0xa2,0xf1,0xe7,0x77,0x68,0x81,0xfe,0xf4,0x0c,0xf3,0x05,0x5a,0xfd,0x0a,0x5c,0x03,
821
0xdf,0x1b,0xeb,0xe7,0xdb,0x1f,0xfb,0x35,0x19,0x1b,0xf1,0xfa,0xe7,0xd1,0x18,0x1a,
822
0xc4,0x1b,0xc2,0xb3,0xe2,0x0d,0xe5,0x89,0x78,0x76,0xc8,0x15,0x83,0x11,0x3c,0x09,
823
0x0f,0x23,0x99,0x27,0xe5,0xc9,0x78,0x5e,0x3c,0x5f,0x9e,0x82,0x17,0xc0,0x0b,0xe2,
824
0x7d,0x6e,0x1c,0xca,0x8b,0xe0,0xdd,0x47,0x5a,0x5e,0x0c,0xef,0x5e,0xde,0x03,0xbc,
825
0x87,0x51,0xf2,0x51,0xde,0x13,0xbc,0xa7,0x78,0xcf,0xf2,0x5e,0xe0,0xbd,0xc4,0x1b,
826
0xc3,0x1b,0xcf,0x9b,0xc4,0xbb,0x3b,0x57,0x6f,0x0a,0x74,0x07,0xa1,0xe5,0x11,0x68,
827
0xf1,0x59,0xe8,0xc2,0x98,0x07,0xb3,0xc0,0x5c,0x30,0x1f,0x2c,0x00,0x6f,0x81,0xc5,
828
0x20,0x1e,0x24,0x81,0x25,0x60,0x29,0xc8,0x00,0xa1,0xb0,0xef,0x51,0xc4,0x41,0xb0,
829
0x5f,0xa7,0x5b,0x01,0x1e,0xe5,0xad,0xe6,0xac,0x5b,0xcb,0xcb,0xe1,0xe5,0xf1,0x36,
830
0xf0,0x36,0xf2,0x36,0xf3,0xb6,0xf1,0x76,0xf0,0x76,0xf1,0xca,0x79,0x95,0xbc,0x2a,
831
0x5e,0x2d,0xaf,0x81,0xb7,0x9f,0x77,0x80,0x77,0x88,0x77,0x84,0x77,0x94,0x77,0x9c,
832
0xd7,0xc1,0x3b,0xc5,0x3b,0xcd,0xfb,0x88,0xf7,0x09,0xef,0x3c,0xaf,0x8b,0xd7,0xc3,
833
0xfb,0x8c,0x77,0x85,0x77,0x95,0xf7,0x0d,0xef,0x3b,0xde,0x75,0xde,0x0d,0x1e,0xdc,
834
0x36,0xc8,0x74,0xd0,0xe0,0x41,0x96,0x83,0xf8,0x83,0x84,0x83,0x6c,0x07,0x39,0x0c,
835
0x1a,0x3e,0xc8,0x69,0xd0,0xc8,0x41,0x6e,0x83,0x3c,0x06,0x79,0x0e,0xf2,0x19,0xf4,
836
0x57,0x8f,0x6f,0x7f,0x68,0x50,0x01,0x35,0x08,0x01,0xe1,0x40,0x03,0xa2,0xc1,0x3d,
837
0xe0,0x7e,0xf0,0x10,0x18,0x05,0x1e,0x07,0xff,0x00,0xcf,0x80,0xe7,0xc1,0x68,0xf0,
838
0xca,0x1d,0x2c,0x1c,0x87,0xbc,0x89,0x60,0x32,0x98,0x06,0x66,0x82,0x39,0x60,0x1e,
839
0x78,0x03,0xbc,0x09,0x16,0x81,0x38,0x90,0x08,0x52,0x40,0x1a,0x48,0x07,0xcb,0xc1,
840
0x2a,0xb0,0x06,0x64,0x83,0x5c,0x50,0x00,0x8a,0x40,0x31,0xd8,0x0a,0x4a,0xc0,0x4e,
841
0x50,0x06,0xf6,0x0c,0xda,0x87,0xb0,0x06,0xd4,0x83,0x26,0xd0,0x0c,0x0e,0x82,0x56,
842
0xce,0xb2,0xf7,0x10,0xb6,0x81,0x13,0xa0,0x13,0x7c,0x00,0xfe,0x09,0x3e,0x06,0xe7,
843
0xc0,0x05,0x70,0x11,0x5c,0x02,0x97,0xc1,0x97,0xe0,0x6b,0xf0,0x2d,0xf8,0x01,0xfc,
844
0xc4,0xb6,0x02,0x8c,0x4d,0x74,0x3a,0x13,0x60,0x0e,0x2c,0x80,0x35,0x10,0x00,0x1b,
845
0x60,0x0f,0x86,0x01,0x47,0xe0,0x0c,0x5c,0x81,0x3b,0x90,0x03,0x6f,0xe0,0x07,0x94,
846
0x20,0x10,0x04,0x83,0x30,0x10,0x09,0xa2,0x40,0x2c,0xb8,0x0f,0x3c,0x08,0x1e,0x01,
847
0x8f,0x81,0x27,0xc1,0xd3,0xe0,0x39,0x13,0xf6,0x7e,0x7b,0xd1,0xe4,0x65,0x93,0xb1,
848
0x26,0x13,0x4c,0x5e,0x35,0x99,0x6a,0x32,0xc3,0x64,0xb6,0xc9,0x6b,0x26,0xaf,0x9b,
849
0x2c,0x34,0x79,0xdb,0x84,0x31,0x49,0x30,0x49,0x36,0x49,0x35,0x59,0x66,0x92,0x69,
850
0xb2,0xd2,0x24,0xcb,0x64,0x9d,0xc9,0x7a,0x93,0x7c,0x93,0x42,0x93,0x4d,0x26,0x5b,
851
0x4c,0xb6,0x9b,0x94,0x9a,0xec,0x36,0xa9,0x30,0xd9,0x6b,0x52,0x6d,0x52,0x67,0xd2,
852
0x68,0xf2,0x8e,0x49,0x8b,0xc9,0x61,0x93,0x77,0x4d,0xfa,0x74,0x33,0x4c,0xfe,0xca,
853
0xd1,0x74,0xcc,0xd0,0xfa,0x42,0x58,0xd3,0xbf,0x3e,0xfb,0xbf,0xf2,0xe9,0x30,0xf9,
854
0xc0,0xe4,0x8c,0xc9,0xf9,0x3f,0xe9,0xbf,0x8b,0x26,0x57,0x4c,0xae,0x99,0xfc,0x64,
855
0xc2,0x33,0x1d,0x62,0x2a,0x30,0x75,0x30,0xbd,0xbb,0x2b,0xe1,0x5b,0xe3,0x3b,0xad,
856
0x8e,0x6f,0xe6,0x48,0x4c,0xdd,0x4d,0xfb,0x74,0x3e,0xa6,0xb7,0xd7,0xfe,0x63,0x3a,
857
0x6f,0xbf,0xce,0x37,0xf5,0xfd,0xfb,0x2d,0xf7,0xdd,0xe1,0x38,0xc0,0x94,0x0d,0xc3,
858
0x4c,0x6f,0x6d,0xb1,0xef,0x37,0xf5,0xdd,0xde,0x67,0xbd,0x44,0x9b,0x3e,0x60,0xfa,
859
0x98,0x29,0x9b,0xfb,0x8c,0xe9,0xed,0xde,0xf9,0xf7,0x77,0x1b,0xff,0xca,0xff,0xbf,
860
0x56,0x8a,0x95,0x97,0x4c,0x27,0x98,0xf6,0xdd,0xd1,0x93,0x7f,0xdc,0x82,0xbf,0xee,
861
0x33,0xcd,0x54,0xf7,0x2b,0xd7,0xb7,0x6f,0xe0,0x1a,0xf5,0xfd,0x8b,0x6b,0xf8,0xfb,
862
0xae,0xfa,0xaf,0xd7,0x9a,0x6b,0xfa,0xaf,0x47,0xdf,0xaf,0xb5,0xd0,0xf7,0xab,0x3e,
863
0x5c,0x68,0x1a,0x67,0x7a,0x37,0xf6,0x8f,0xbf,0xf6,0x59,0x62,0xfa,0x9f,0x9c,0x9b,
864
0x96,0x99,0xfe,0xb2,0xc7,0xab,0x06,0xf2,0x72,0x06,0x52,0x85,0x03,0xa9,0xad,0xbf,
865
0x6a,0xdf,0x2e,0xd3,0x5f,0xde,0x53,0x7b,0x91,0x57,0x6f,0x7a,0xc0,0xf4,0x5d,0xd3,
866
0x4e,0xd3,0x8f,0x6e,0xab,0xd9,0xfd,0x3b,0x7a,0x7a,0xf9,0x0e,0xf6,0x7d,0x33,0x90,
867
0xf7,0xe3,0x40,0xca,0xd8,0xac,0x3f,0x35,0xd8,0xec,0xd7,0xda,0x1a,0x6a,0x76,0x37,
868
0x9f,0x2c,0xf6,0x66,0xc3,0xcd,0x24,0x66,0xae,0x66,0x1e,0x66,0x5e,0x66,0x7e,0x66,
869
0x2a,0xb3,0x20,0xb3,0x30,0x33,0x8d,0x59,0x8c,0xd9,0x7d,0x66,0x0f,0x99,0x3d,0x6a,
870
0xf6,0xa4,0xd9,0x33,0x66,0x2f,0x98,0xbd,0x6c,0x36,0xce,0x6c,0x92,0xd9,0x54,0xb3,
871
0x99,0x66,0x73,0xcd,0x5e,0x37,0x7b,0xd3,0x6c,0xb1,0x59,0x82,0x59,0x8a,0xd9,0x52,
872
0xb3,0x4c,0xb3,0x55,0x66,0x6b,0xcd,0xd6,0x9b,0x15,0x98,0x6d,0x34,0xdb,0x62,0x56,
873
0x62,0xd6,0xa7,0xdb,0x65,0x76,0x73,0x64,0x54,0x98,0xfd,0x95,0x77,0xe7,0x3e,0xb3,
874
0xbb,0xd1,0x0a,0x11,0x91,0xee,0xbf,0xe6,0xc3,0xfa,0xb3,0xd6,0xac,0xd1,0xac,0xd9,
875
0xec,0x90,0xd9,0xbb,0x66,0x6d,0x66,0x7d,0xff,0xc1,0xd5,0xc5,0xbf,0xe7,0x29,0x1a,
876
0xf8,0xfc,0xd6,0x1c,0xfe,0x67,0x3f,0xa7,0xb0,0xb3,0xb8,0xce,0x63,0xf7,0x10,0xa6,
877
0xd8,0x37,0xa8,0x06,0x75,0x98,0xbd,0x6f,0x76,0xab,0x86,0x7f,0x9a,0x7d,0x62,0xf6,
878
0xa9,0xd9,0x45,0xb3,0xcf,0xcc,0xbe,0x30,0xfb,0xda,0xec,0x3b,0xb3,0x1f,0xcd,0x74,
879
0x66,0x3c,0x73,0x33,0xf3,0x7d,0x66,0x16,0xe6,0x7c,0x73,0x91,0xb9,0xbd,0xf9,0x70,
880
0x73,0x89,0xb9,0xab,0xb9,0x87,0xb9,0x97,0xb9,0x9f,0xb9,0xca,0x3c,0xc8,0x3c,0xcc,
881
0x5c,0x63,0x1e,0x63,0x7e,0x9f,0xf9,0x43,0xe6,0x8f,0x9a,0x3f,0x69,0xfe,0x8c,0xf9,
882
0x0b,0xe6,0x2f,0x9b,0x8f,0x33,0x9f,0x64,0x3e,0xd5,0x7c,0xa6,0xf9,0x5c,0xf3,0xd7,
883
0xcd,0xdf,0x34,0x5f,0x6c,0xce,0xb6,0x9c,0x60,0x9e,0x62,0xbe,0xd4,0xfc,0xaf,0xf2,
884
0xb7,0x11,0xbd,0x46,0x3c,0x78,0x8f,0x7d,0xaf,0xb8,0xd6,0xe8,0xf6,0xf7,0x8a,0x58,
885
0x6b,0xd3,0x5c,0x63,0x09,0xf6,0xe5,0xec,0x7b,0x45,0x1f,0x32,0xa2,0x4c,0xf3,0x95,
886
0xe6,0x59,0xe6,0x3c,0xee,0x3d,0x24,0xfb,0xd6,0x27,0xdb,0xdc,0x0a,0xa5,0x6c,0x51,
887
0xda,0xd7,0xc8,0x91,0x96,0x18,0xe5,0x9a,0x6f,0x30,0x97,0x70,0xa5,0x37,0x99,0x97,
888
0x1b,0x79,0xd1,0x56,0x73,0xfd,0xae,0x94,0xdd,0x73,0x0a,0xd0,0x0e,0xfb,0x76,0x92,
889
0xcd,0x79,0x98,0xcb,0xf9,0x75,0xbb,0xbe,0xbb,0x2b,0x3b,0xd3,0x1d,0xe6,0x26,0xb4,
890
0xcb,0x7c,0x25,0x65,0x9b,0x5b,0x50,0xb9,0x79,0xa5,0x79,0x95,0xf9,0x0e,0xa3,0x6d,
891
0x46,0xb5,0xe6,0x0d,0xe6,0xef,0x98,0xb7,0x98,0x1f,0x36,0x7f,0xcf,0xbc,0xcd,0xfc,
892
0x84,0x79,0xa5,0x51,0xa7,0xf9,0x07,0xe6,0x55,0x46,0xff,0x34,0xff,0xd8,0xfc,0x88,
893
0xd1,0x39,0xf3,0x22,0xe3,0x53,0x46,0x17,0xcc,0x4f,0x1b,0x15,0x1b,0xab,0xa8,0xc7,
894
0xfc,0x33,0xf3,0xf3,0x46,0x41,0xbc,0x2b,0xb8,0x02,0x5f,0x81,0x6f,0xc1,0x75,0xd0,
895
0x07,0x8c,0x07,0xeb,0x74,0xa6,0x60,0x08,0xb0,0x06,0x42,0x60,0x07,0x86,0x01,0x27,
896
0xe0,0x02,0xdc,0x81,0x27,0xf0,0x05,0x4a,0xa0,0x06,0xa1,0x20,0x12,0x44,0x83,0x7b,
897
0xc1,0x83,0x60,0x14,0x78,0x02,0x3c,0x0d,0x9e,0x07,0x2f,0x81,0xb1,0x60,0x22,0x98,
898
0x02,0x66,0x80,0x39,0x60,0x3e,0x58,0x08,0x16,0x81,0x78,0x90,0x0c,0xd2,0x40,0x06,
899
0x58,0x09,0xd6,0x80,0x1c,0x90,0x0f,0x8a,0xc0,0x66,0xb0,0x1d,0xec,0x04,0xe5,0x60,
900
0x2f,0xa8,0x01,0x0d,0xe0,0x1d,0x70,0x10,0x1c,0x01,0xc7,0xc0,0x09,0x70,0x0a,0x7c,
901
0x08,0x3e,0x06,0xe7,0x41,0x37,0xb8,0x04,0xae,0x80,0xaf,0xc0,0xb7,0xe0,0x3a,0xe8,
902
0x03,0xc6,0x43,0xd0,0x7f,0x30,0x04,0x58,0x03,0x21,0xb0,0x1b,0x72,0xd3,0xfb,0xc3,
903
0x86,0xb0,0x5a,0xe1,0x0b,0xe4,0x8d,0x04,0x52,0x20,0x07,0x3e,0x40,0x01,0x02,0x41,
904
0x08,0x88,0x00,0x51,0xe0,0x1e,0xf0,0x00,0x78,0x04,0x3c,0x0e,0x9e,0x02,0xcf,0x81,
905
0xd1,0x60,0x0c,0x98,0x00,0x26,0x83,0xe9,0x60,0x36,0x98,0x07,0x16,0x80,0xb7,0x41,
906
0x1c,0x48,0x02,0xa9,0x20,0x1d,0xac,0x00,0x59,0x20,0x1b,0xe4,0x81,0x42,0x50,0x0c,
907
0xb6,0x81,0x52,0x50,0x06,0x2a,0x41,0x35,0xa8,0x07,0xfb,0x41,0x0b,0x68,0x05,0x47,
908
0x41,0x3b,0xe8,0x04,0xa7,0xc1,0x99,0x21,0xbf,0x1c,0x59,0xe7,0x86,0x74,0x0d,0xe9,
909
0x1d,0x72,0x79,0xc8,0xd5,0x21,0xd7,0x86,0xfc,0x30,0xe4,0xc6,0x90,0xdb,0xe7,0x1d,
910
0x23,0x0b,0x13,0x8b,0xc1,0x16,0x56,0x16,0x02,0x0b,0x5b,0x8b,0x3b,0xcd,0x3f,0x62,
911
0x0b,0x47,0x8b,0x91,0x16,0x52,0x0b,0xb9,0x85,0x8f,0x85,0xc2,0x22,0xd0,0xe2,0xf6,
912
0xf3,0x21,0x16,0x11,0x16,0x51,0x16,0xf7,0x58,0x3c,0x60,0xf1,0x88,0xc5,0xe3,0x16,
913
0x4f,0x59,0xdc,0xde,0xfe,0x73,0x16,0xa3,0x2d,0xc6,0x58,0x4c,0xb0,0x98,0x6c,0x31,
914
0xfd,0x8e,0xed,0xf7,0xe9,0x66,0x23,0x7f,0x1e,0x58,0x00,0xde,0xfe,0x45,0xfb,0x71,
915
0x16,0x49,0x16,0xa9,0x16,0xe9,0x16,0x2b,0x2c,0xb2,0x2c,0xb2,0x2d,0xf2,0x70,0x7e,
916
0x08,0xee,0xb8,0xa1,0x40,0x04,0xec,0x80,0x18,0x8c,0x00,0x12,0xee,0xdd,0x53,0xa1,
917
0xc5,0x16,0x8b,0x52,0x8b,0x0a,0x8b,0x6a,0x8b,0x46,0x8b,0x16,0x8b,0x77,0x2d,0x6e,
918
0x3f,0x6e,0xb7,0x78,0xdf,0xe2,0x8c,0xc5,0xa7,0x16,0xbd,0x16,0x5f,0x58,0x5c,0xb3,
919
0xf8,0xf1,0x17,0xc7,0x46,0x96,0x66,0x96,0x56,0x96,0x22,0x4b,0xb1,0xa5,0xc4,0x52,
920
0x6a,0xe9,0x65,0x79,0xfb,0x31,0x6b,0x93,0xc2,0x32,0xc8,0x32,0xdc,0x92,0xed,0x4b,
921
0x94,0xe5,0x7d,0x96,0x0f,0x59,0x3e,0x6a,0x39,0x84,0x17,0x64,0xf9,0xa4,0xe5,0xe7,
922
0xc6,0x4f,0x5a,0x3e,0x63,0xf9,0x82,0xe5,0x18,0xcb,0x49,0x96,0xd3,0xb8,0xf3,0xb3,
923
0x2d,0x5f,0xb7,0x1c,0xca,0x7b,0xd3,0x52,0xc4,0x9b,0x64,0xb9,0xd8,0x32,0xc9,0x72,
924
0xa9,0xa5,0xbe,0x57,0x2b,0x2c,0xfb,0x7d,0xb1,0xda,0x72,0x9d,0x65,0xae,0x25,0xfb,
925
0x86,0x6c,0x83,0xe5,0x66,0xcb,0x1d,0x86,0xf3,0xe5,0x96,0xfd,0xfd,0xaf,0xb4,0xac,
926
0xb6,0xac,0xb7,0x1c,0xc1,0xdb,0x6f,0xd9,0x62,0x39,0x88,0xf7,0x2e,0x57,0xef,0xa8,
927
0x65,0x87,0xe5,0x07,0x5c,0xfb,0x67,0x2c,0x3f,0xb5,0x14,0xf3,0x2e,0x5a,0x4a,0x78,
928
0x1d,0x96,0x31,0xf4,0x99,0x25,0xfb,0xfd,0xc5,0x9d,0x44,0xff,0xdc,0xd1,0xeb,0xfc,
929
0xc2,0xf2,0xa6,0x77,0xbf,0xb6,0xfc,0xd7,0xfb,0x0a,0xdd,0xaf,0x7c,0x3b,0xf2,0x9d,
930
0x65,0x1f,0x6a,0x9a,0x5b,0xf1,0xad,0x06,0xc6,0x09,0x52,0x23,0xac,0x6e,0x6f,0xc5,
931
0xd9,0xca,0xd5,0xca,0xdd,0xea,0xd7,0xe7,0x3d,0xf9,0x6d,0xe7,0x02,0x6f,0x3e,0x28,
932
0xe9,0xa6,0xd6,0x5b,0x32,0x49,0x6d,0x25,0xe0,0xce,0x04,0x5b,0x85,0x5a,0x85,0x5b,
933
0x45,0x5a,0x69,0xad,0xa2,0xad,0x62,0xad,0xee,0xb5,0x7a,0xd0,0xea,0x61,0xab,0x51,
934
0x56,0xc3,0x71,0x7e,0x14,0xb1,0xdf,0xcf,0xdc,0xf9,0x3c,0xfb,0x1c,0x19,0x4c,0x8e,
935
0xe4,0x87,0x67,0x02,0x7f,0xe0,0xe9,0x21,0xe1,0xbe,0x8f,0xf2,0xb9,0xe3,0x37,0x51,
936
0x8f,0x59,0xfd,0x7b,0x33,0xf9,0x93,0x56,0xcf,0x58,0x99,0xd0,0x0b,0xa8,0xf5,0xb2,
937
0xd5,0x38,0xab,0x3c,0xf6,0x1b,0x0b,0x2b,0xf6,0x69,0xa5,0x97,0x6b,0x78,0x6a,0x09,
938
0xa0,0xd5,0x1e,0x7a,0x86,0xd3,0x54,0xae,0x6d,0xfd,0x37,0x62,0xac,0xb0,0x47,0x33,
939
0xac,0x66,0x5b,0xcd,0x43,0x3e,0x6b,0xc9,0x18,0x9e,0x3e,0xb6,0xa5,0xd9,0xdc,0x77,
940
0x6a,0x58,0x05,0x73,0xdf,0xaa,0xbd,0x61,0x25,0x46,0x1f,0xde,0xb2,0x5a,0x6c,0x15,
941
0x6f,0x95,0x04,0x7f,0x60,0x77,0x61,0xf5,0x00,0x9e,0x55,0x32,0xde,0x03,0xbc,0x65,
942
0x03,0xf6,0x9a,0x71,0xcf,0x3e,0xf6,0x29,0x79,0xab,0x7d,0xcb,0xad,0xd6,0x58,0xe5,
943
0x5a,0x6d,0xb4,0xda,0x66,0xb5,0xcb,0xaa,0xd2,0xaa,0xd6,0x6a,0xbf,0xd5,0x21,0xab,
944
0xa3,0x56,0x1d,0x56,0xa7,0xad,0x3e,0xb1,0xea,0xb2,0xfa,0x0c,0xad,0x7d,0x69,0xf5,
945
0xb5,0xd5,0x77,0x56,0x5e,0x74,0xdd,0xea,0x86,0x95,0x91,0xb5,0xa9,0xb5,0x1f,0x0d,
946
0xb6,0xb6,0xb4,0xb6,0xe7,0xbe,0xd3,0x13,0xd3,0x6f,0x9d,0x37,0xac,0xc9,0xad,0x6f,
947
0x6a,0xb4,0xb1,0xbe,0x7d,0xf7,0xf0,0xdf,0xf8,0x19,0x66,0x3d,0x12,0xfd,0xf0,0xb2,
948
0x56,0x5a,0xff,0xa7,0x35,0x87,0x5b,0x6b,0xff,0xb4,0xce,0xdf,0xbf,0x7f,0xbd,0xc3,
949
0xdd,0x63,0x7d,0x9f,0xf5,0x83,0xd6,0x8f,0x58,0x3f,0x66,0xfd,0xa4,0xf5,0xd3,0xd6,
950
0xcf,0x59,0xbf,0x68,0xfd,0xb2,0xf5,0x58,0xeb,0x09,0xd6,0x93,0xad,0xa7,0x5b,0xcf,
951
0xb6,0x9e,0x67,0xbd,0xc0,0xfa,0x6d,0xeb,0x38,0xeb,0x24,0xeb,0x54,0xeb,0x0c,0xeb,
952
0x55,0xd6,0xeb,0xac,0xf3,0xac,0x8b,0xac,0xb7,0x58,0xef,0xb0,0x2e,0xb3,0xde,0x6b,
953
0x5d,0x6b,0xfd,0x7b,0xf5,0x36,0x59,0x1f,0xb0,0x3e,0x6c,0xfd,0x9e,0xf5,0x71,0xeb,
954
0x93,0xd6,0x1f,0x58,0x7f,0x64,0x7d,0xd6,0xfa,0x82,0x75,0x8f,0xf5,0xe7,0xd6,0x5f,
955
0x5a,0x7f,0x63,0xfd,0xbd,0xf5,0x4f,0xd6,0xc4,0x1f,0xc4,0x37,0xe7,0x5b,0xf2,0x87,
956
0xf2,0x6d,0xf8,0x0e,0xfc,0x11,0x7c,0x67,0xbe,0x1b,0xff,0x8f,0x7c,0xd3,0xfc,0x47,
957
0xea,0xa8,0xad,0xfe,0xfc,0x55,0x94,0xf1,0x75,0xff,0xa7,0x3e,0x81,0xfc,0x10,0x7e,
958
0xf8,0x5d,0xec,0x93,0xf6,0x2e,0xb5,0x75,0x2f,0xff,0x41,0xfe,0x28,0xfe,0x13,0xfc,
959
0xa7,0xf9,0xcf,0xf3,0x5f,0xe2,0x8f,0xe5,0x4f,0xe4,0x4f,0xe1,0xcf,0xe0,0xcf,0xe1,
960
0xcf,0xe7,0x2f,0xe4,0x2f,0xe2,0xc7,0xf3,0x93,0xf9,0x69,0xfc,0x0c,0xfe,0x4a,0xfe,
961
0x1a,0x7e,0x0e,0x3f,0x9f,0x5f,0xc4,0xdf,0xcc,0xdf,0xce,0xdf,0xc9,0x2f,0xe7,0xef,
962
0xe5,0xd7,0xf0,0x1b,0xf8,0xef,0xf0,0x0f,0xf2,0x8f,0xf0,0x8f,0xf1,0x4f,0xf0,0x4f,
963
0xf1,0x3f,0xe4,0x7f,0xcc,0x3f,0xcf,0xef,0xe6,0x5f,0xe2,0x5f,0xe1,0x7f,0xc5,0xff,
964
0x96,0x7f,0x9d,0xdf,0xc7,0x37,0x1e,0xfa,0x57,0xfb,0xd5,0x14,0x1a,0x86,0x0c,0xb5,
965
0x1a,0x2a,0xe0,0x34,0xd9,0x20,0x74,0x00,0x23,0xc0,0x4a,0xec,0x01,0x32,0xcd,0x77,
966
0x60,0x3d,0xef,0xcc,0x9d,0x73,0xfb,0x99,0x2d,0x22,0x8c,0x57,0xd9,0x50,0xaf,0xa1,
967
0xbe,0xc8,0x55,0x02,0x35,0x08,0x05,0x91,0x20,0x1a,0xdc,0x0b,0x1e,0x04,0xa3,0xc0,
968
0x13,0xe0,0x69,0xf0,0x3c,0x78,0x09,0x8c,0x05,0x13,0xc1,0x14,0x30,0x03,0xcc,0x01,
969
0xf3,0xc1,0x42,0xb0,0x08,0xc4,0x83,0x64,0x90,0x06,0x32,0x58,0x4b,0xc0,0x1a,0x90,
970
0x03,0xf2,0x41,0x11,0xd8,0x0c,0xb6,0x83,0x9d,0xa0,0x1c,0xec,0x05,0x35,0xa0,0x01,
971
0xbc,0x03,0x0e,0x82,0x23,0xe0,0x18,0x38,0x01,0x4e,0x81,0x0f,0xc1,0xc7,0xe0,0x3c,
972
0xe8,0x06,0x97,0xc0,0x15,0xf0,0xd5,0x2f,0xbc,0xfc,0x2d,0x72,0xae,0x0f,0xe4,0xf6,
973
0x0d,0xd5,0xfd,0xc7,0xde,0x77,0xfe,0x7c,0x96,0x32,0x16,0xe8,0xfe,0xd0,0xdb,0xbf,
974
0xdf,0xfb,0x86,0xdb,0x54,0xf0,0xdf,0x71,0xf7,0x0f,0x11,0xfc,0x9a,0x07,0xac,0x05,
975
0x42,0x81,0x9d,0x60,0x98,0xc0,0x49,0xe0,0x22,0x70,0x17,0x78,0x0a,0x7c,0x05,0x4a,
976
0x81,0x5a,0x10,0x2a,0x88,0x14,0x44,0x0b,0xee,0x15,0x3c,0x28,0x18,0x25,0x78,0x42,
977
0xf0,0xb4,0xe0,0x79,0xc1,0x4b,0x82,0xb1,0x82,0x89,0x82,0x29,0x82,0x19,0x82,0x39,
978
0x82,0xf9,0x82,0x85,0x82,0x45,0x82,0x78,0x41,0xb2,0x20,0x4d,0x90,0x21,0x58,0x29,
979
0x58,0x23,0xc8,0x11,0xe4,0x0b,0x8a,0x04,0x9b,0x05,0xdb,0x05,0x3b,0x05,0xe5,0x82,
980
0xbd,0x82,0x1a,0x41,0x83,0xe0,0x1d,0xc1,0x41,0xc1,0x11,0xc1,0x31,0xc1,0x09,0xc1,
981
0x29,0xc1,0x87,0x82,0x8f,0x05,0xe7,0x05,0xdd,0x82,0x4b,0x82,0x2b,0x82,0xaf,0x04,
982
0xdf,0x0a,0xae,0x0b,0xfa,0x04,0xc6,0x42,0x53,0xe1,0x10,0xa1,0xb5,0x50,0x28,0xb4,
983
0x13,0x0e,0x13,0x3a,0x09,0x5d,0x84,0xee,0x42,0x4f,0xa1,0xaf,0x50,0x29,0x54,0x0b,
984
0x43,0x85,0x91,0xc2,0x68,0xe1,0xbd,0xc2,0x07,0x85,0xa3,0x84,0x4f,0x08,0x9f,0x16,
985
0x3e,0x2f,0x7c,0x49,0x38,0x56,0x38,0x51,0x38,0x45,0x38,0x43,0x38,0x47,0x38,0x5f,
986
0xb8,0x50,0xb8,0x48,0x18,0x2f,0x4c,0x16,0xa6,0x09,0x33,0x84,0x2b,0x85,0x6b,0x84,
987
0x39,0xc2,0x7c,0x61,0x91,0x70,0xb3,0x70,0xbb,0x70,0xa7,0xb0,0x5c,0xb8,0x57,0x58,
988
0x23,0x6c,0x10,0xbe,0x23,0x3c,0x28,0x3c,0x22,0x3c,0x26,0x3c,0x21,0x3c,0x25,0xfc,
989
0x50,0xf8,0xb1,0xf0,0xbc,0xb0,0x5b,0x78,0x49,0x78,0x45,0xf8,0x95,0xf0,0x5b,0xe1,
990
0x75,0x61,0x9f,0xd0,0x58,0x64,0x2a,0x1a,0x22,0xb2,0x16,0x09,0x45,0x76,0xa2,0x61,
991
0x22,0x27,0x91,0x8b,0xc8,0x5d,0xe4,0x29,0xf2,0x15,0x29,0x45,0x6a,0x51,0xa8,0x28,
992
0x52,0x14,0x2d,0xba,0x57,0xf4,0xa0,0x68,0x94,0xe8,0x09,0xd1,0xd3,0xa2,0xe7,0x45,
993
0x2f,0x89,0xc6,0x8a,0x26,0x8a,0xa6,0x88,0x66,0x88,0xe6,0x88,0xe6,0x8b,0x16,0x8a,
994
0x16,0x89,0xe2,0x45,0xc9,0xa2,0x34,0x51,0x86,0x68,0xa5,0x68,0x8d,0x28,0x47,0x94,
995
0x2f,0x2a,0x12,0x6d,0x16,0x6d,0x17,0xed,0x14,0x95,0x8b,0xf6,0x8a,0x6a,0x44,0x0d,
996
0xa2,0x77,0x44,0x07,0x45,0x47,0x44,0xc7,0x44,0x27,0x44,0xa7,0x44,0x1f,0x8a,0x3e,
997
0x16,0x9d,0x17,0x75,0x8b,0x2e,0x89,0xae,0x88,0xbe,0x12,0x7d,0x2b,0xba,0x2e,0xea,
998
0x13,0x19,0xdb,0x98,0xda,0x0c,0xb1,0xb1,0xb6,0x11,0xda,0xd8,0xd9,0x0c,0xb3,0x71,
999
0xb2,0x71,0xb1,0x71,0xb7,0xf1,0xb4,0xf1,0xb5,0x51,0xda,0xa8,0x6d,0x42,0x6d,0x22,
1000
0x6d,0xa2,0x6d,0xee,0xb5,0x79,0xd0,0x66,0x94,0xcd,0x13,0x36,0x4f,0xdb,0x3c,0x6f,
1001
0xf3,0x92,0xcd,0x58,0x9b,0x3e,0xdd,0xdd,0x17,0x76,0x87,0x30,0xd1,0xe6,0x3f,0x33,
1002
0x0a,0x5f,0x85,0x9e,0x29,0x82,0x69,0x36,0xb3,0x6c,0xfe,0xcc,0xdd,0xcd,0x7e,0x5e,
1003
0xb3,0x59,0xc0,0xb5,0xb1,0xc8,0xe6,0xbf,0xfb,0xa9,0x9c,0x64,0xf3,0x57,0xcf,0x8b,
1004
0x7d,0xba,0x65,0x36,0xcb,0x6d,0x56,0xdb,0xac,0xb3,0xc9,0xb5,0xd9,0x60,0xb3,0xc9,
1005
0x66,0xab,0xcd,0x0e,0x9b,0xdd,0x36,0x7b,0x6c,0xaa,0x6c,0xea,0x6c,0x9a,0x6c,0x0e,
1006
0xd8,0x1c,0xb6,0x79,0xcf,0xe6,0xb8,0xcd,0x49,0x9b,0x0f,0x6c,0x3e,0xb2,0x39,0x6b,
1007
0x73,0xc1,0xa6,0xc7,0xe6,0x73,0x9b,0x2f,0x6d,0xbe,0xb1,0xf9,0xde,0xe6,0x27,0x1b,
1008
0xb2,0x1d,0x64,0x6b,0x6e,0x6b,0x69,0x3b,0xd4,0xd6,0xc6,0xd6,0xc1,0x76,0x84,0xad,
1009
0xb3,0xad,0x9b,0xad,0xcc,0xd6,0xdb,0xd6,0xdf,0x36,0xc0,0x36,0xd8,0x36,0xdc,0x56,
1010
0x6b,0x1b,0x6b,0x7b,0xbf,0xed,0xc3,0xb6,0x8f,0xd9,0xfe,0xc3,0x96,0xe8,0x59,0xdb,
1011
0x17,0x6d,0x5f,0xb1,0x1d,0x6f,0xfb,0xaa,0xed,0x34,0xdb,0x59,0xb6,0xaf,0xd9,0xbe,
1012
0x61,0xfb,0x96,0x2d,0x63,0x9b,0x68,0xbb,0xc4,0x76,0x99,0xed,0x72,0xdb,0xd5,0xb6,
1013
0xeb,0x6c,0x73,0x6d,0x37,0xd8,0x6e,0xb2,0xdd,0x6a,0xbb,0xc3,0x76,0xb7,0xed,0x1e,
1014
0xdb,0x2a,0xdb,0x3a,0xdb,0x26,0xdb,0x03,0xb6,0x87,0x6d,0xdf,0xb3,0x3d,0x6e,0x7b,
1015
0xd2,0xf6,0x03,0xdb,0x8f,0x6c,0xcf,0xda,0x5e,0xb0,0xed,0xb1,0xfd,0xdc,0xf6,0x4b,
1016
0xdb,0x6f,0x6c,0xbf,0xb7,0xfd,0xc9,0x56,0xef,0x15,0x6b,0xcc,0x4c,0x64,0x37,0xc8,
1017
0xce,0xdc,0xce,0xd2,0x6e,0xa8,0x9d,0x8d,0x9d,0x93,0xc0,0xc1,0x6e,0x84,0x9d,0xb3,
1018
0x9d,0x9b,0x9d,0xef,0x9f,0x9e,0x7f,0x65,0x76,0xbe,0x76,0x01,0x76,0xa1,0x76,0x5a,
1019
0xbb,0x7b,0xed,0x1e,0xb6,0x7b,0xc2,0xee,0x59,0xbb,0x97,0xec,0xc6,0xdb,0x4d,0xb1,
1020
0x9b,0x65,0x37,0xdf,0xee,0x2d,0xbb,0x78,0xbb,0x25,0x76,0x19,0x76,0xab,0xed,0x72,
1021
0xec,0x36,0xd8,0x6d,0xb6,0xdb,0x61,0x57,0x6e,0x57,0x65,0xd7,0x60,0x77,0xc0,0xee,
1022
0x88,0xdd,0x71,0xbb,0x53,0x76,0x9f,0xd8,0xf5,0xe9,0x7a,0xec,0xae,0xd8,0x7d,0x63,
1023
0x77,0xdd,0x8e,0xec,0x4d,0xed,0x2d,0xed,0x85,0xf6,0x0e,0xf6,0x4e,0xf6,0x6e,0xf6,
1024
0x9e,0xf6,0xfe,0xf6,0x6a,0xfb,0x70,0xfb,0x68,0xfb,0xfb,0xed,0x47,0xd9,0xff,0xc3,
1025
0xfe,0x79,0xfb,0x57,0xec,0x27,0xda,0x4f,0xb3,0x9f,0x63,0xff,0x86,0xfd,0x22,0xfb,
1026
0x44,0xfb,0x34,0xfb,0xe5,0xf6,0x6b,0xec,0x73,0xed,0x8b,0xec,0xb7,0xda,0xef,0xb4,
1027
0xdf,0x63,0x5f,0x63,0xdf,0x64,0x7f,0xc0,0xde,0x4e,0x78,0xd8,0xfe,0x76,0xfb,0xde,
1028
0xb3,0x3f,0x6e,0xdf,0x61,0x7f,0xca,0xfe,0xb4,0xfd,0x47,0xf6,0x9f,0xd8,0x9f,0xb7,
1029
0xef,0xb2,0xef,0xb1,0xff,0xcc,0xfe,0x8a,0xfd,0x55,0xfb,0x6f,0xec,0xbf,0xb3,0xbf,
1030
0x6e,0xbf,0x0c,0x57,0x76,0x13,0xae,0x29,0x7b,0x15,0x3f,0xe2,0xae,0xdf,0xcd,0xab,
1031
0x77,0xc3,0xde,0xc8,0xc1,0xc4,0x61,0xb0,0x83,0x95,0x83,0xc0,0xc1,0xd6,0x41,0xec,
1032
0xe0,0xe8,0x30,0xd2,0x41,0xea,0x20,0x77,0xf0,0x71,0x50,0x38,0x04,0x3a,0x84,0x3b,
1033
0xc4,0x38,0xdc,0xf4,0xed,0x7d,0x0e,0x0f,0x39,0x3c,0xea,0x10,0x2a,0x78,0xd2,0x61,
1034
0x8a,0x40,0x89,0xb9,0xf6,0x25,0xcc,0xc2,0x9b,0x45,0x69,0x02,0x4f,0xe1,0x33,0x0e,
1035
0x2f,0x38,0xbc,0xec,0x30,0xce,0x61,0x92,0xc3,0x54,0x87,0x99,0x0e,0x73,0x1d,0x5e,
1036
0x77,0x78,0xd3,0xa1,0x48,0xb0,0xd8,0x21,0xc1,0x21,0xc5,0x61,0xa9,0x43,0xa6,0xc3,
1037
0x2a,0x87,0xb5,0x0e,0xeb,0x1d,0xf4,0xd7,0xa6,0xc0,0x61,0xa3,0xc3,0x16,0x87,0x12,
1038
0x87,0x5d,0x0e,0x15,0x0e,0xfb,0x1c,0x6a,0x1d,0x1a,0x1d,0x9a,0x1d,0x0e,0x39,0x1c,
1039
0x71,0x38,0xea,0x70,0xdc,0xa1,0xc3,0xe1,0x94,0xc3,0x69,0x87,0x8f,0x1c,0x3e,0x71,
1040
0x38,0xef,0xd0,0xe5,0xd0,0xe3,0xf0,0x99,0xc3,0x15,0x87,0xab,0x0e,0xdf,0x38,0xfc,
1041
0xe0,0xd0,0xe7,0xc0,0x13,0x9b,0x8b,0xad,0xc4,0x42,0xb1,0xbd,0x78,0x84,0x78,0xa4,
1042
0xd8,0x43,0xec,0x23,0x56,0x89,0xd5,0xe2,0x50,0x71,0x84,0x38,0x4a,0x7c,0x8f,0xf8,
1043
0x01,0xf1,0x23,0xe2,0xc7,0xc5,0x4f,0x89,0x9f,0x13,0x8f,0x16,0x8f,0x11,0x4f,0x10,
1044
0x4f,0x16,0x4f,0x17,0xcf,0x16,0xcf,0x13,0x2f,0x10,0xbf,0x2d,0x8e,0x13,0x27,0x89,
1045
0x53,0xc5,0xe9,0xe2,0x15,0xe2,0x2c,0x71,0xb6,0x38,0x4f,0x5c,0x28,0x2e,0x16,0x6f,
1046
0x13,0x97,0x8a,0xcb,0xc4,0x95,0xe2,0x6a,0x71,0xbd,0x78,0xbf,0xb8,0x45,0xdc,0x2a,
1047
0x3e,0x2a,0x6e,0x17,0x77,0x8a,0x4f,0x8b,0xcf,0x88,0xcf,0x89,0xbb,0xc4,0xbd,0xe2,
1048
0xcb,0xe2,0xab,0xe2,0x6b,0xe2,0x1f,0xc4,0x37,0xc4,0x83,0x86,0x09,0x86,0x39,0x0d,
1049
0xf3,0x1a,0x16,0x38,0x2c,0x7a,0xd8,0xc3,0xc3,0x9e,0x1e,0x36,0x71,0xd8,0xdc,0x61,
1050
0x6f,0x0f,0x4b,0x19,0xb6,0x62,0x58,0xfe,0xb0,0x92,0x61,0x95,0xc3,0x1a,0x87,0x1d,
1051
0x1c,0x76,0x7c,0xd8,0x99,0x61,0x97,0x86,0x5d,0x1d,0x66,0x34,0xdc,0x66,0xb8,0xdb,
1052
0x70,0xdf,0xe1,0x91,0xc3,0x47,0x0d,0x7f,0x61,0xf8,0x84,0xe1,0x33,0x87,0x2f,0x18,
1053
0x9e,0x3c,0x7c,0xcd,0xf0,0x8d,0xc3,0x4b,0x87,0xef,0x1b,0xbe,0x7f,0xf8,0xe1,0xe1,
1054
0x6d,0xc3,0x4f,0x0d,0x3f,0x33,0xfc,0xe2,0xf0,0xab,0xc3,0x8d,0x46,0x58,0x8c,0x70,
1055
0x18,0x21,0x1b,0xa1,0x1c,0x11,0x32,0x42,0x3b,0xe2,0xb1,0x11,0xa3,0x47,0x4c,0x1f,
1056
0xf1,0xfa,0x88,0x94,0x11,0x19,0x23,0xd6,0x8d,0x28,0x1a,0xb1,0x63,0xc4,0xde,0x11,
1057
0x4d,0x23,0x8e,0x8e,0x78,0x7f,0xc4,0xc7,0x23,0x7a,0x46,0x7c,0x35,0xe2,0xa7,0x11,
1058
0x83,0x1d,0x45,0x8e,0x8e,0x8e,0x1e,0x8e,0x41,0x8e,0xb1,0x8e,0x0f,0x39,0xbe,0xe0,
1059
0x38,0xd6,0x71,0xa6,0xe3,0x5b,0x8e,0xc9,0x8e,0xcb,0x1d,0x73,0x1c,0xb7,0x38,0xee,
1060
0x74,0xac,0x72,0x6c,0x71,0x7c,0xcf,0xf1,0x23,0xc7,0x6e,0xc7,0xcf,0x1c,0xbf,0x74,
1061
0xbc,0xe6,0x78,0xdd,0x51,0xe7,0x38,0xc8,0x69,0xb0,0x93,0xb5,0x93,0xc8,0xc9,0xc1,
1062
0xc9,0xc9,0xc9,0xcd,0xc9,0xd3,0xc9,0xdf,0x49,0xed,0x14,0xee,0x14,0xed,0x74,0xbf,
1063
0xd3,0x28,0xa7,0x7f,0x38,0x3d,0xef,0xf4,0x8a,0xd3,0x44,0xa7,0x69,0x4e,0x73,0x9c,
1064
0xe6,0x3b,0x2d,0x70,0x7a,0xcb,0x89,0x71,0x4a,0x70,0x4a,0x76,0x4a,0x75,0x4a,0x77,
1065
0x5a,0xe1,0xb4,0xda,0x69,0xbd,0x53,0x91,0xd3,0x36,0xa7,0xdd,0x4e,0xf5,0x4e,0x4d,
1066
0x4e,0xcd,0x4e,0x87,0x9c,0x8e,0x38,0x1d,0x75,0x3a,0xee,0xd4,0xe1,0x74,0xca,0xe9,
1067
0x43,0xa7,0x4f,0x9c,0xce,0x3b,0x75,0x39,0xf5,0x3a,0x5d,0x76,0xfa,0xd2,0xe9,0x6b,
1068
0xa7,0x6f,0x9d,0xae,0x3b,0xf5,0x39,0x19,0x4b,0x4c,0x25,0x43,0x24,0x56,0x92,0xa1,
1069
0x12,0x91,0xc4,0x4e,0x22,0x96,0x38,0x4a,0x9c,0x25,0xae,0x12,0x77,0x89,0xa7,0xc4,
1070
0x57,0xa2,0x90,0x04,0x4a,0x42,0x24,0x11,0x12,0xad,0x24,0x56,0xf2,0xa0,0xa4,0xde,
1071
0xe9,0x71,0xc9,0x53,0x92,0xe7,0x24,0xa3,0x25,0x63,0x24,0x93,0x25,0x73,0x24,0xf3,
1072
0x24,0x6f,0x48,0xde,0x92,0x2c,0x96,0xc4,0x4b,0x92,0x24,0xa9,0x92,0x65,0x20,0x53,
1073
0xb2,0x52,0x92,0x25,0xc9,0x96,0xe4,0x82,0x02,0xc9,0x46,0x49,0x9f,0x6e,0x8b,0x64,
1074
0xbb,0xa4,0x54,0xb2,0x1b,0xa9,0x7d,0x92,0x1a,0x49,0xbd,0xa4,0x49,0xd2,0x2c,0x39,
1075
0x88,0xf6,0x5b,0x25,0xef,0x49,0xda,0x24,0x27,0x24,0xa7,0x24,0xc7,0x9d,0x4e,0x4b,
1076
0xce,0x48,0xce,0xa1,0xc4,0x05,0x49,0x8f,0xe4,0x33,0xc9,0x15,0xc9,0x55,0xc9,0x37,
1077
0x92,0xeb,0x12,0x72,0x36,0x71,0x1e,0xe2,0xcc,0x77,0xb6,0x71,0x16,0x3b,0x3b,0x39,
1078
0xbb,0x3a,0xcb,0x9c,0x7d,0x9c,0x55,0xce,0x21,0xce,0x1a,0xe7,0x7b,0x9c,0x1f,0x72,
1079
0x7e,0xdc,0xf9,0x19,0xe7,0xd1,0xce,0xe3,0x9c,0x27,0x3b,0xcf,0x74,0x9e,0xe7,0xfc,
1080
0xa6,0x73,0x9c,0x73,0x8a,0x73,0xba,0xf3,0x2a,0xe7,0x6c,0xe7,0x02,0xe7,0x62,0xe7,
1081
0x12,0xe7,0x32,0xe7,0x4a,0x67,0x9d,0xae,0x1a,0xd4,0x83,0xfd,0xa0,0x05,0x74,0x98,
1082
0xe9,0x74,0xad,0x88,0x8f,0x82,0x76,0xd0,0x09,0x4e,0x83,0x33,0xe0,0x1c,0xe8,0x02,
1083
0xbd,0xe0,0x32,0xb8,0x0a,0xae,0x81,0x1f,0xc0,0x0d,0x60,0x34,0x52,0xa7,0x33,0x01,
1084
0x83,0x47,0xfe,0xbe,0xf9,0xc7,0x0a,0xe5,0x04,0xc0,0x16,0x88,0x81,0x23,0x18,0x09,
1085
0xa4,0x40,0x0e,0x7c,0x80,0x02,0x04,0x82,0x10,0x10,0x01,0xa2,0x80,0xd3,0x20,0xb7,
1086
0x41,0xff,0x5b,0x9e,0x62,0xf7,0xc0,0x9e,0x07,0xc0,0x23,0xe0,0x71,0xf0,0x14,0x78,
1087
0x0e,0x8c,0x36,0xf8,0x60,0x0c,0xe2,0x09,0x60,0x32,0x98,0x0e,0x66,0x83,0x79,0x60,
1088
0x01,0x78,0x1b,0xc4,0x81,0x24,0x90,0x0a,0xd2,0xc1,0x0a,0x90,0x05,0xb2,0x41,0x1e,
1089
0x28,0x04,0xc5,0x60,0x1b,0x28,0x05,0x65,0xa0,0x12,0x54,0x83,0x7a,0xb0,0x1f,0xb4,
1090
0x80,0x56,0x70,0x14,0xb4,0x83,0x4e,0x70,0xda,0xc0,0xcf,0x3f,0x67,0x90,0x73,0x0e,
1091
0x74,0x8d,0xec,0x45,0x78,0x19,0x5c,0x05,0xd7,0xc0,0x0f,0x03,0x65,0x6f,0x20,0x55,
1092
0xc5,0x7d,0x37,0x66,0xe4,0x82,0xeb,0xe9,0x62,0xf8,0x4e,0x1b,0xb1,0x15,0x10,0x00,
1093
0x5b,0x20,0x06,0x8e,0x60,0x24,0x90,0x02,0x39,0xf0,0x01,0xfb,0x8c,0xb3,0xcd,0x2b,
1094
0xcd,0x15,0x2e,0xb5,0x68,0x21,0xc0,0x25,0xc8,0xe5,0x1d,0xf3,0x50,0x97,0x48,0xe4,
1095
0x47,0x83,0x7b,0xc1,0x83,0x60,0x14,0x78,0x02,0x3c,0x0d,0x9e,0x07,0x2f,0xb9,0x7c,
1096
0x6c,0x3e,0xd6,0x65,0x22,0x52,0x53,0xc0,0x0c,0x97,0xd9,0x08,0xe7,0x81,0x05,0xe0,
1097
0x6d,0x10,0x07,0x92,0x40,0x2a,0x48,0x07,0x2b,0x5c,0x56,0xbb,0xf4,0xaf,0x1c,0xd6,
1098
0xba,0xfc,0xab,0x15,0x9e,0x94,0x4c,0xc8,0x82,0x46,0x52,0x0e,0xd7,0x8b,0x6b,0x14,
1099
0x6a,0x74,0x37,0xae,0xf9,0x23,0x23,0xf3,0x5d,0x86,0x0c,0x2d,0x72,0xf9,0xe5,0x99,
1100
0xcd,0x5c,0xde,0x36,0x97,0x52,0xce,0xaa,0x32,0x97,0x4a,0x97,0x6a,0x97,0x7a,0x97,
1101
0xfd,0x2e,0x2d,0x2e,0xad,0x2e,0x47,0x5d,0xda,0x5d,0x3a,0x5d,0x4e,0xbb,0x9c,0x71,
1102
0x39,0xe7,0xd2,0xe5,0xd2,0xeb,0x72,0xd9,0xe5,0xaa,0xcb,0x35,0x97,0x1f,0x5c,0x6e,
1103
0xb8,0x18,0xb9,0x9a,0xb8,0x0e,0x76,0xb5,0x72,0x15,0xb8,0xda,0xba,0x8a,0x5d,0x1d,
1104
0x5d,0x47,0xba,0x4a,0x5d,0xe5,0xae,0x3e,0xae,0x0a,0xd7,0x40,0xd7,0x10,0xd7,0x08,
1105
0xd7,0x28,0xd7,0x7b,0x5c,0x1f,0x70,0x7d,0xc4,0xf5,0x71,0xd7,0xa7,0x5c,0x9f,0x73,
1106
0x1d,0xed,0x3a,0xc6,0x75,0x82,0xeb,0x64,0xd7,0xe9,0xae,0xb3,0x5d,0xe7,0xb9,0x2e,
1107
0x70,0x7d,0xdb,0x35,0xce,0x35,0xc9,0x35,0xd5,0x35,0xdd,0x75,0x85,0x6b,0x96,0x6b,
1108
0xb6,0x6b,0x9e,0x6b,0xa1,0x6b,0xb1,0xeb,0x36,0xd7,0x52,0xd7,0x32,0xd7,0x4a,0xd7,
1109
0x6a,0xd7,0x7a,0xd7,0xfd,0xae,0x2d,0xae,0xad,0xae,0x47,0x5d,0xdb,0x5d,0x3b,0x5d,
1110
0x4f,0xbb,0x9e,0x71,0x3d,0xe7,0xda,0xe5,0xda,0xeb,0x7a,0xd9,0xf5,0xaa,0xeb,0x35,
1111
0xd7,0x64,0xd1,0x0f,0xae,0x37,0x5c,0x8d,0xdc,0x4c,0xdc,0x5e,0xc2,0x3a,0x7b,0xb0,
1112
0xdb,0x66,0x91,0x95,0x9b,0xc0,0xcd,0xd6,0x4d,0xec,0xe6,0xe8,0x36,0xd2,0x4d,0xea,
1113
0x26,0x77,0xf3,0x71,0x53,0xb8,0x05,0xba,0x85,0xb8,0x45,0xb8,0x45,0xb9,0xdd,0xe3,
1114
0xf6,0x80,0xdb,0x23,0x6e,0x8f,0xbb,0x3d,0xe5,0xf6,0x9c,0xdb,0x68,0xb7,0x31,0x6e,
1115
0x13,0xdc,0x26,0xbb,0x4d,0x77,0x9b,0xed,0x36,0xcf,0x6d,0x81,0xdb,0xdb,0x6e,0x71,
1116
0x6e,0x49,0x6e,0xa9,0x6e,0xe9,0x6e,0x2b,0xdc,0xb2,0xdc,0xb2,0xdd,0xf2,0xdc,0x0a,
1117
0xdd,0x8a,0xdd,0xb6,0xb9,0x95,0xba,0xf5,0x09,0xcb,0xdc,0x2a,0xdd,0xaa,0xdd,0xea,
1118
0xdd,0xf6,0xbb,0xb5,0xb8,0xb5,0xba,0x1d,0x75,0x6b,0x77,0xeb,0x74,0x3b,0xed,0xe6,
1119
0x62,0x73,0xc6,0xed,0x9c,0x5b,0x97,0x5b,0xaf,0xdb,0x65,0xb7,0xab,0x6e,0xd7,0xdc,
1120
0x7e,0x70,0xbb,0xe1,0x66,0x24,0x35,0x91,0x0e,0x96,0x5a,0x49,0x05,0x52,0x5b,0xa9,
1121
0x58,0xea,0x28,0x1d,0x29,0x95,0x4a,0xe5,0x52,0x1f,0xa9,0x42,0x1a,0x28,0x0d,0x91,
1122
0x46,0x48,0xa3,0xa4,0xf7,0x48,0x15,0x6e,0x0f,0x48,0x1f,0x91,0x3e,0x2e,0x7d,0x4a,
1123
0xfa,0x9c,0x74,0xb4,0x74,0x8c,0x74,0x82,0x74,0xb2,0x74,0xba,0x74,0xb6,0x74,0x9e,
1124
0x74,0x81,0xf4,0x6d,0x69,0x9c,0x34,0x49,0x9a,0x2a,0x4d,0x97,0xae,0x90,0x66,0x49,
1125
0x33,0x44,0xd9,0xd2,0x3c,0x69,0xa1,0xb4,0x58,0xba,0x4d,0x5a,0x2a,0x2d,0x93,0x56,
1126
0x4a,0xab,0xa5,0xf5,0xd2,0xfd,0xd2,0x16,0x69,0xab,0xf4,0xa8,0xb4,0x5d,0x5a,0x24,
1127
0xe8,0x94,0x9e,0x96,0x9e,0x91,0x9e,0x93,0x76,0x49,0x7b,0xa5,0x97,0xa5,0x57,0xa5,
1128
0x4f,0x0b,0xae,0x49,0x7f,0x90,0xde,0x90,0x1a,0xb9,0x9b,0xb8,0x0f,0x76,0xb7,0x72,
1129
0x17,0xb8,0xdb,0xba,0x8b,0xdd,0x1d,0xdd,0x47,0xba,0x4b,0xdd,0xe5,0xee,0x3e,0xee,
1130
0x0a,0xf7,0x40,0xf7,0x10,0xf7,0x08,0xf7,0x28,0xf7,0x7b,0xdc,0x1f,0x70,0x5f,0x21,
1131
0x7d,0xc4,0xfd,0x71,0xf7,0xa7,0xdc,0x9f,0x73,0x1f,0xed,0x3e,0xc6,0x7d,0x82,0xfb,
1132
0x64,0xf7,0xc7,0xa5,0xd3,0xdd,0x67,0xbb,0xcf,0x73,0x5f,0xe0,0xfe,0xb6,0x7b,0x9c,
1133
0x7b,0x92,0x7b,0xaa,0x7b,0xba,0xfb,0x0a,0xf7,0x2c,0xf7,0x6c,0xf7,0x3c,0xf7,0x42,
1134
0xf7,0x62,0xf7,0x6d,0xee,0xa5,0xee,0x65,0xee,0x95,0xee,0xd5,0xee,0x0a,0xb7,0x7a,
1135
0xf7,0xfd,0xee,0x2d,0xee,0xad,0xee,0xcf,0xdb,0x1c,0x75,0x6f,0x77,0xef,0x74,0x3f,
1136
0xed,0x7e,0xc6,0xfd,0x9c,0x7b,0x97,0x7b,0xaf,0xfb,0x65,0xf7,0xab,0xee,0xd7,0xdc,
1137
0x7f,0x70,0x7f,0xc8,0xe1,0x86,0xbb,0x91,0x87,0x89,0xc7,0x60,0x0f,0x2b,0x0f,0x81,
1138
0x87,0xad,0x87,0xd8,0xc3,0xd1,0xe3,0x39,0xe9,0x48,0x0f,0xa9,0x87,0xdc,0xc3,0xc7,
1139
0x43,0xe1,0x11,0xe8,0x11,0xe2,0x11,0xe1,0x11,0xe5,0x71,0x8f,0xc7,0x03,0x1e,0x8f,
1140
0x78,0x3c,0xee,0x51,0x24,0x7a,0xca,0xe3,0x39,0x8f,0xd1,0x1e,0x63,0x3c,0x26,0x78,
1141
0x4c,0xf6,0x98,0xee,0x31,0xdb,0x63,0x9e,0xc7,0x02,0x8f,0xb7,0x3d,0xe2,0x3c,0x92,
1142
0x3c,0x3e,0x16,0xa6,0x7a,0xa4,0x7b,0xac,0xf0,0xc8,0xf2,0xc8,0xf6,0xc8,0xf3,0x28,
1143
0xf4,0x28,0xf6,0xd8,0xe6,0x51,0xea,0x51,0xe6,0x51,0xe9,0x51,0xed,0x51,0xef,0xb1,
1144
0xdf,0xa3,0xc5,0xe3,0x41,0x51,0xab,0xc7,0xd3,0xa2,0xa3,0x1e,0xed,0x1e,0x9d,0x1e,
1145
0xec,0x38,0x3e,0x8d,0xf0,0x0c,0x97,0x3a,0xe7,0xd1,0xe5,0xd1,0xeb,0x71,0xd9,0xe3,
1146
0xaa,0xc7,0x35,0x8f,0x1f,0x3c,0x6e,0x78,0x18,0xc9,0xae,0x0b,0x31,0x37,0xc8,0x30,
1147
0x2f,0xc8,0xb8,0x99,0x5c,0x26,0x90,0xe9,0xef,0x00,0x5b,0x99,0x58,0xe6,0x28,0x1b,
1148
0x29,0x93,0xca,0xe4,0x32,0x1f,0x99,0x42,0x16,0x28,0x0b,0x91,0x45,0xc8,0xa2,0x64,
1149
0xf7,0xc8,0x1e,0x90,0x3d,0x22,0x7b,0x5c,0xf6,0x94,0xec,0x39,0x59,0x83,0x60,0xb4,
1150
0x6c,0x8c,0x6c,0x82,0x6c,0xb2,0x6c,0xba,0x6c,0xb6,0x6c,0x9e,0x6c,0x81,0xec,0x6d,
1151
0x59,0x9c,0x2c,0x49,0x96,0x2a,0x4b,0x97,0xad,0x90,0x65,0xc9,0x5e,0x76,0xc8,0x96,
1152
0xe5,0xc9,0x0a,0x65,0xc5,0xb2,0x99,0x0e,0xdb,0x64,0xa5,0xb2,0x32,0x59,0xa5,0xac,
1153
0x5a,0x36,0xd2,0xbd,0x5e,0xb6,0x5f,0xd6,0x22,0x6b,0x95,0x1d,0x95,0xb5,0x43,0x3a,
1154
0x65,0xa7,0x65,0x67,0x64,0xe7,0x64,0x5d,0xb2,0x5e,0xd9,0x65,0xd9,0x55,0x99,0x95,
1155
0xec,0x9a,0xec,0x07,0xd9,0x0d,0x99,0x91,0xdc,0x44,0x3e,0x44,0xce,0xed,0xef,0xe5,
1156
0x42,0xb9,0x9d,0x7c,0x98,0xdc,0x49,0xee,0x22,0x77,0x97,0x7b,0xca,0xef,0x91,0xf9,
1157
0xca,0x95,0x72,0xb5,0xfc,0xb4,0x47,0xa8,0x3c,0x52,0x1e,0x2d,0xbf,0x57,0xfe,0xa0,
1158
0x7c,0x94,0xfc,0x09,0xf9,0xd3,0xf2,0xe7,0xe5,0x2f,0xc9,0xc7,0xca,0x27,0xca,0x27,
1159
0xc8,0xa6,0xc8,0x27,0xcb,0x66,0xc8,0xe7,0xc8,0xe7,0xcb,0x17,0xca,0x17,0xc9,0xcf,
1160
0x78,0x24,0xb9,0xc5,0xcb,0x93,0xe5,0xd1,0xc2,0x2c,0xe9,0x39,0xf7,0x34,0x79,0x86,
1161
0x3c,0x49,0xb6,0x52,0x9e,0x2a,0x5b,0x23,0xcf,0x91,0xe7,0xcb,0xbb,0x3c,0x8a,0xe4,
1162
0x9b,0xe5,0xdb,0xe5,0x3b,0xe5,0xe5,0xf2,0x5e,0x8f,0xbd,0xf2,0x1a,0x79,0x83,0xfc,
1163
0x1d,0xf9,0x41,0xf9,0x11,0x79,0xb5,0xec,0x98,0xfc,0x84,0x7c,0xa4,0xfb,0x29,0x79,
1164
0xab,0xec,0x43,0xf9,0xc7,0xf2,0xf3,0xf2,0x6e,0xf9,0x25,0xf9,0x19,0xd9,0x15,0xf9,
1165
0x60,0xd9,0x57,0xf2,0x73,0xb2,0x07,0xa4,0xdf,0xca,0xbb,0x64,0xd7,0xe5,0x97,0x65,
1166
0x7d,0x72,0x63,0x4f,0x53,0xcf,0x21,0x9e,0xd6,0x9e,0xd7,0x64,0x37,0x3c,0x84,0x9e,
1167
0x3f,0xc8,0xec,0x3c,0x6f,0xc8,0x86,0x79,0xbe,0x64,0xe3,0xe4,0xe9,0xea,0x29,0xf3,
1168
0xf4,0xf1,0x54,0x78,0x06,0x7a,0x86,0x78,0x46,0x7a,0xc6,0x78,0xde,0xef,0xf9,0xb0,
1169
0xe7,0xdd,0xdc,0xff,0x3e,0xe6,0xf9,0xa4,0xe7,0xd3,0x9e,0xcf,0x79,0x8e,0xf6,0x1c,
1170
0x03,0xf9,0xb5,0x52,0xe3,0x3d,0x27,0x7b,0xce,0xf0,0x9c,0xeb,0xf9,0xc6,0x2d,0x25,
1171
0xde,0xf6,0xd4,0xe9,0xe2,0x3d,0x53,0x3c,0xdf,0xb2,0x4a,0xb2,0x4a,0xf3,0x4c,0xf7,
1172
0x5c,0xee,0xb9,0xca,0x73,0x8d,0x67,0xb6,0x67,0xac,0x55,0xae,0x67,0xa1,0xe7,0x66,
1173
0xcf,0x52,0xcf,0x3d,0x9e,0xd5,0x9e,0x0d,0x9e,0xcd,0x9e,0x87,0x3d,0x8f,0x7a,0x9e,
1174
0xf0,0x7c,0xdf,0xf3,0x23,0xd4,0x3e,0xe7,0xd9,0xed,0xf9,0x99,0xe7,0x97,0x9e,0xd7,
1175
0x90,0xbe,0x0e,0x74,0x9e,0x83,0xbc,0xfa,0x74,0x83,0xbd,0xac,0x11,0x8a,0xbc,0x1c,
1176
0xbc,0x1c,0xbd,0x5c,0xbc,0x3c,0xbc,0xbc,0xbd,0x14,0x5e,0x6a,0xaf,0x30,0x2f,0xad,
1177
0xd7,0x3d,0x90,0xfb,0x0d,0xf2,0x90,0x41,0x46,0x19,0xe4,0x71,0x83,0xfc,0xc3,0x20,
1178
0xcf,0x18,0xe4,0x79,0x83,0x8c,0x36,0xc8,0x2b,0x06,0x19,0x67,0x90,0x89,0x06,0x99,
1179
0x6c,0x90,0x69,0x90,0x99,0x90,0x39,0x90,0x79,0x90,0x37,0x20,0x6f,0x42,0x16,0x19,
1180
0x24,0xce,0x20,0x89,0x06,0x49,0x31,0x48,0x1a,0x24,0xdd,0x20,0xcb,0x21,0xab,0x0c,
1181
0xb2,0xc6,0x20,0xd9,0x90,0x5c,0xc8,0x9f,0x7f,0xda,0x14,0x78,0xe9,0xa5,0x08,0x52,
1182
0x0c,0xd9,0x0a,0x39,0x63,0x52,0xe2,0x55,0xe2,0xb5,0x13,0x52,0x06,0xd9,0x63,0x90,
1183
0x7d,0x90,0x1a,0x48,0x23,0xe4,0x00,0xa4,0x15,0x72,0x0c,0xd2,0x01,0xf9,0x80,0x93,
1184
0x33,0x9c,0x9c,0x37,0x48,0x97,0xd7,0x25,0xaf,0x2f,0x70,0xfc,0x8d,0xd7,0x0f,0x5e,
1185
0x7d,0x5e,0x3c,0x6f,0x73,0x6f,0x2b,0x6f,0xa1,0xb7,0xbd,0xf7,0x08,0xef,0x91,0xde,
1186
0xee,0xde,0x5e,0xde,0xfe,0xde,0x81,0xde,0xa1,0xde,0x1a,0xef,0x58,0xef,0x07,0xbc,
1187
0x47,0x79,0x3f,0xe9,0xfd,0xac,0xf7,0x68,0xef,0xb1,0xde,0x93,0xbc,0xa7,0x79,0xcf,
1188
0xf6,0x9e,0xef,0xfd,0xa6,0x37,0xe3,0x9d,0xe4,0x9d,0xe6,0x9d,0xe9,0xbd,0xda,0x3b,
1189
0xdb,0x3b,0xdf,0x7b,0xa3,0xf7,0x56,0xef,0x52,0xef,0x72,0xef,0x7d,0xde,0x75,0xde,
1190
0xfb,0xbd,0x0f,0x7a,0xbf,0xeb,0x7d,0xdc,0xbb,0xd3,0xfb,0x43,0xef,0x4f,0xbc,0x2f,
1191
0x78,0xf7,0x7a,0x5f,0xf1,0xfe,0xda,0xfb,0x7b,0xef,0x1b,0xde,0xc6,0x3e,0x66,0x3e,
1192
0x96,0x3e,0x02,0x1f,0x3b,0x9f,0xe1,0x3e,0xce,0x3e,0x52,0x1f,0x4f,0x1f,0x3f,0x9f,
1193
0x00,0x9f,0x10,0x9f,0x48,0x9f,0x18,0x9f,0xfb,0x7d,0x1e,0xf1,0x79,0xc2,0xe7,0x19,
1194
0x9f,0x17,0x7d,0xc6,0xf8,0x4c,0xf4,0x99,0xea,0x33,0xcb,0x67,0x9e,0xcf,0x42,0x9f,
1195
0xc5,0x3e,0x89,0x3e,0xa9,0x3e,0x19,0x3e,0xab,0x7c,0xd6,0xf9,0xe4,0xf9,0x14,0xf9,
1196
0x6c,0xf1,0xd9,0xe1,0x53,0xe6,0xb3,0xd7,0xa7,0xce,0xe7,0x1d,0x9f,0xc3,0x3e,0xc7,
1197
0x7c,0x4e,0xfa,0x7c,0xe8,0xf3,0x89,0xcf,0x17,0x5e,0x17,0x7c,0xd8,0x9e,0xf4,0xfa,
1198
0x5c,0xf1,0x31,0xf7,0xfe,0xda,0x87,0xed,0xc9,0xf7,0x3e,0x37,0x7c,0xdc,0xbd,0x8d,
1199
0x7d,0xd9,0x9e,0x98,0xf9,0x5a,0xfa,0x86,0x7a,0x0b,0x7c,0xd9,0xde,0xb0,0x56,0xe9,
1200
0x2d,0xea,0xb7,0x45,0x6f,0x85,0x9d,0xef,0xfd,0x3e,0xc3,0x7d,0x9d,0x7d,0x27,0xfa,
1201
0x48,0x7d,0x59,0xed,0x65,0x3e,0x9e,0xbe,0x7e,0xbe,0xeb,0x7c,0x02,0x7c,0x59,0xbd,
1202
0xac,0xb7,0x42,0x7c,0xbf,0xf0,0x8a,0xf4,0xed,0xf7,0x56,0x8c,0x6f,0xbf,0xaf,0xee,
1203
0x47,0xdb,0x37,0x7d,0x74,0xab,0x87,0x1e,0xf1,0xbd,0xd5,0x47,0xbf,0xf4,0x10,0xeb,
1204
0x9d,0x9b,0x7e,0xe9,0xf7,0xc9,0x13,0xbe,0xfd,0x1e,0xe9,0xf7,0xc6,0x33,0xbe,0xac,
1205
0x2f,0x5e,0xf4,0xed,0xf7,0xc4,0x18,0xce,0x12,0xd6,0x06,0xbd,0xf6,0x89,0xbe,0x6f,
1206
0x7a,0x4f,0xf5,0x9d,0xe5,0x3b,0xcf,0x97,0x6d,0xc7,0x93,0xab,0xc1,0x96,0x5a,0xe8,
1207
0x1b,0xe7,0xbb,0xc4,0x37,0xd3,0x77,0xb5,0x6f,0xb6,0x6f,0xbe,0xef,0x46,0xdf,0xad,
1208
0xbe,0xa5,0xbe,0xe5,0xbe,0xfb,0x7c,0xeb,0x7c,0xf7,0xfb,0x1e,0xf4,0x7d,0xd7,0xf7,
1209
0xb8,0x6f,0xa7,0xef,0x87,0xbe,0x9f,0xf8,0x5e,0xf0,0xed,0xf5,0xbd,0xe2,0xfb,0xb5,
1210
0xef,0xf7,0xbe,0x37,0xd0,0x8a,0xb1,0x9f,0x99,0x9f,0xa5,0x9f,0xc0,0xef,0x8f,0xd6,
1211
0xeb,0x3f,0x9e,0x0a,0x7b,0x36,0x1a,0xbc,0xa1,0xcf,0x63,0x47,0x89,0x9d,0x9f,0x9d,
1212
0xdf,0xef,0x19,0xf9,0xc3,0xfd,0x5c,0x20,0x72,0x3f,0x7f,0xbf,0x20,0xbf,0x48,0xbf,
1213
0x7b,0xfc,0x1e,0x86,0x3c,0xe9,0xf7,0xbc,0xdf,0x18,0xbf,0x57,0xfd,0x66,0xfa,0xcd,
1214
0x87,0xbc,0xed,0x97,0x08,0x59,0x0a,0x59,0xe9,0x97,0x0d,0xd9,0xe0,0xb7,0x05,0xb2,
1215
0x13,0x52,0xe9,0x57,0x07,0x69,0x86,0x1c,0xf1,0x6b,0xf7,0xfb,0xc0,0xef,0x13,0x48,
1216
0xb7,0xdf,0x65,0xbf,0x6f,0xfc,0x7e,0xf4,0x33,0xf6,0x37,0xf6,0x1f,0xec,0x3f,0xd4,
1217
0xdf,0xde,0xdf,0xc9,0x5f,0xea,0x8f,0xc1,0xe1,0xaf,0x82,0x84,0x42,0xa2,0xfc,0xef,
1218
0xf7,0x7f,0xd4,0xff,0x69,0xff,0xd1,0xfe,0xe3,0xfd,0xa7,0xfa,0xb3,0x36,0xcc,0xf1,
1219
0x5f,0xe0,0xcf,0xf8,0xa7,0xf8,0x67,0xf8,0x67,0x41,0x72,0xfd,0x37,0xfa,0x6f,0xf7,
1220
0x2f,0x83,0x54,0xf9,0x37,0xfa,0x1f,0xf4,0x3f,0xea,0x7f,0xd2,0xff,0x9f,0xfe,0xe7,
1221
0xfd,0x7b,0xfd,0xbf,0xf4,0xff,0xce,0xbf,0xcf,0xdf,0x44,0x61,0xa9,0x10,0x29,0x86,
1222
0x29,0x46,0x2a,0x64,0x0a,0x3f,0x85,0x5a,0x11,0xa1,0x88,0x55,0x3c,0xa4,0x18,0x0c,
1223
0x4d,0x4f,0x28,0x9e,0x53,0xbc,0xa2,0x98,0xa4,0x98,0xa1,0x98,0x07,0x5e,0x51,0xbc,
1224
0xa5,0x48,0x50,0xa4,0x29,0x56,0x28,0xd6,0xe1,0xf8,0x03,0x58,0x5f,0xa0,0xd8,0xac,
1225
0xf8,0xe3,0xdf,0x84,0xde,0x59,0x4a,0x15,0x7b,0x14,0xb5,0x8a,0x03,0x8a,0xa3,0x8a,
1226
0x53,0x8a,0x4f,0x14,0x3d,0x8a,0xab,0x8a,0xeb,0x0a,0x23,0xa5,0xab,0x52,0xa5,0xbc,
1227
0xfd,0x37,0xfd,0xee,0xfc,0x09,0x57,0x46,0x2a,0xfb,0x74,0xd1,0x4a,0x9d,0x71,0xac,
1228
0xf2,0x5e,0xe5,0xfd,0xca,0x87,0x95,0xff,0xde,0x37,0x08,0x78,0xc2,0x28,0xff,0xa1,
1229
0x7c,0x16,0xc2,0xfe,0x3e,0xc3,0xf3,0xca,0x17,0x95,0x2f,0x29,0xc7,0x2a,0x27,0x2a,
1230
0xa7,0x28,0x67,0x28,0xe7,0x28,0xd9,0xef,0x8a,0xe7,0x2b,0x17,0x2a,0x17,0x29,0xe3,
1231
0x39,0x7b,0x92,0x95,0x4b,0x94,0x23,0xac,0xf4,0xf2,0x2c,0x57,0x4b,0xaf,0x1f,0x7a,
1232
0x8c,0xa3,0xa1,0x3f,0x56,0xf9,0xd8,0xcf,0xda,0x49,0x53,0x2e,0x53,0x66,0x28,0x63,
1233
0xad,0x96,0x2b,0x57,0x2a,0x57,0x2b,0x1f,0xb4,0xea,0xd3,0xad,0x51,0xae,0x53,0xe6,
1234
0x28,0x73,0x07,0xac,0xcc,0x57,0x16,0x29,0xb7,0xa0,0xed,0x12,0xe4,0xec,0x52,0x56,
1235
0x28,0xab,0x94,0x75,0xca,0xfd,0xca,0x16,0xe5,0x11,0xe5,0x31,0x65,0x87,0xf2,0x7d,
1236
0xe5,0x47,0xca,0x4f,0x20,0xe7,0x21,0x5d,0x90,0x1e,0xc8,0x67,0x06,0xb9,0x02,0xb9,
1237
0x6a,0x90,0x6f,0x20,0xdf,0x19,0xe4,0xba,0x41,0x6e,0x18,0x84,0x54,0x7a,0xe1,0x19,
1238
0xc4,0x14,0x32,0x18,0x62,0x09,0xe1,0x43,0x84,0x06,0xb1,0x35,0x88,0x83,0x41,0x86,
1239
0x1b,0xc4,0xc9,0x20,0x23,0x0d,0xe2,0x66,0x10,0x0f,0x83,0x78,0x1a,0xc4,0xc7,0x20,
1240
0xfe,0x06,0xe9,0xff,0xa8,0x0d,0x12,0x62,0x90,0x70,0x83,0x68,0x20,0xec,0xd3,0x20,
1241
0x5a,0xa5,0x97,0x7b,0x20,0x0f,0x42,0x1e,0x85,0xfc,0x03,0xa2,0xff,0x4d,0x95,0x3e,
1242
0x5d,0xac,0xf2,0x39,0x55,0x1a,0xe7,0xb5,0x65,0xca,0x17,0x54,0xac,0x77,0x59,0x8f,
1243
0x86,0x2b,0x97,0x2b,0x27,0xda,0x8c,0x56,0xdd,0xe9,0xf7,0x53,0xd8,0xd1,0xb0,0x12,
1244
0xde,0x5e,0x8d,0x2b,0x92,0xab,0xfc,0x23,0xdf,0x50,0x27,0x2b,0xd7,0xe0,0x4a,0xbf,
1245
0xac,0x7a,0x56,0xf9,0xae,0xe5,0x1f,0xa9,0xff,0xbc,0x72,0x8c,0xea,0x45,0xe5,0x38,
1246
0xd5,0x04,0xd5,0x64,0xd5,0x44,0x1b,0x76,0x04,0x45,0x2a,0xa7,0xab,0x7e,0x10,0xcf,
1247
0x56,0xcd,0x53,0x2d,0x50,0xbd,0xad,0x8a,0x53,0x25,0xa9,0x52,0x55,0xe9,0xaa,0x15,
1248
0xaa,0x2c,0xd5,0x5f,0xf5,0x06,0x2d,0x5b,0x95,0xa7,0x2a,0x54,0x11,0xfd,0x99,0xf7,
1249
0xcb,0xfa,0x31,0x7a,0xeb,0x5b,0x66,0xf6,0xf8,0xd6,0x37,0xcd,0xec,0xf1,0xad,0x6f,
1250
0x9b,0xd9,0x63,0xfd,0x1b,0x67,0x7d,0xdd,0x62,0xd5,0x56,0x55,0x89,0x2a,0x8c,0x76,
1251
0xaa,0xca,0x54,0x7b,0x70,0x4d,0xab,0x54,0x75,0xaa,0x26,0xd5,0x01,0xd5,0x61,0xd5,
1252
0x7b,0xaa,0xe3,0xaa,0xdf,0x9e,0x1f,0x4e,0xaa,0x4e,0xab,0x3e,0x56,0x7d,0xaa,0xea,
1253
0x51,0x5d,0x56,0x7d,0xa5,0xfa,0x4e,0xf5,0x93,0xca,0x28,0xc0,0x34,0xc0,0x22,0x60,
1254
0x68,0x80,0x6d,0xc0,0xb0,0x00,0x49,0x80,0x5b,0x80,0x3c,0xc0,0x37,0x40,0x15,0x10,
1255
0x1c,0x10,0x11,0x10,0x1d,0x70,0x5f,0xc0,0xc3,0x01,0x8f,0x07,0x3c,0x1d,0xf0,0x42,
1256
0xc0,0x2b,0x01,0x13,0x02,0xa6,0x04,0xcc,0x0c,0x78,0x2d,0x60,0x41,0xc0,0xa2,0x80,
1257
0x84,0x80,0x25,0x01,0xe9,0x01,0x2b,0x03,0xd6,0x06,0xfc,0xa7,0x7f,0x9f,0xfa,0xb7,
1258
0xbe,0x03,0xcd,0x0d,0x28,0x0c,0xd8,0x1c,0x50,0x12,0xb0,0x3b,0xa0,0x32,0xa0,0x26,
1259
0xa0,0x31,0xe0,0x40,0x40,0x6b,0xc0,0xb1,0x80,0x8e,0x80,0x0f,0x02,0xce,0x04,0x9c,
1260
0x0f,0xb8,0x18,0xf0,0x79,0xc0,0xd5,0x80,0x6f,0x03,0x7e,0x0c,0xa0,0x40,0x93,0xc0,
1261
0x21,0x81,0xfc,0x40,0x9b,0x40,0x71,0xa0,0x53,0xa0,0x6b,0xa0,0x2c,0xd0,0x27,0x50,
1262
0x19,0x18,0x14,0x18,0x1e,0x18,0x15,0x78,0x6f,0xe0,0x43,0x81,0x77,0xfb,0x5b,0x8a,
1263
0xbf,0xaa,0xbd,0xdb,0x67,0xe7,0xc7,0x02,0x9f,0x0a,0x7c,0x3e,0xf0,0xe5,0xc0,0xf1,
1264
0x81,0x93,0x03,0x67,0x04,0xce,0x0d,0x7c,0x23,0xf0,0xed,0xc0,0x78,0xf4,0x26,0x25,
1265
0x70,0x59,0xe0,0x8a,0xc0,0x35,0x81,0xeb,0x03,0x37,0x04,0x16,0x07,0x6e,0x0f,0xdc,
1266
0x15,0xb8,0x27,0xb0,0x3a,0xb0,0x21,0xb0,0x39,0xf0,0x70,0xe0,0x51,0x9c,0x3f,0x11,
1267
0xf8,0x7e,0xe0,0x47,0x81,0xe7,0x02,0xbb,0x03,0x3f,0x0b,0xfc,0x12,0xc7,0xd7,0x02,
1268
0xaf,0x07,0xf6,0xfd,0xe6,0xf7,0xc1,0xbf,0xef,0x7c,0xdf,0xcf,0x7e,0x63,0x4f,0x17,
1269
0x68,0xac,0x7e,0x8d,0x4c,0xd4,0x8b,0x8d,0xfa,0x74,0xe6,0x6a,0x0b,0x35,0x5f,0x2d,
1270
0x54,0xb3,0x7f,0x03,0x6f,0xab,0x16,0xab,0x47,0xa8,0x25,0xea,0x19,0x2e,0x2e,0xea,
1271
0x8d,0x46,0x52,0xf5,0x35,0x92,0xa9,0xbd,0xd4,0xbe,0x6a,0x85,0x3a,0x40,0xad,0x70,
1272
0x09,0x52,0x87,0xab,0xb5,0xea,0x18,0xf5,0xfd,0xea,0x87,0xd4,0x5b,0xe8,0x31,0xf5,
1273
0x6a,0x97,0x91,0xf4,0xa4,0xfa,0x69,0xb5,0x60,0xe8,0x0b,0xea,0x03,0x46,0x2f,0xa9,
1274
0xc7,0xa8,0xc7,0xab,0x5f,0x55,0x1f,0x37,0x9a,0xaa,0xee,0xd3,0xcd,0x54,0xcf,0x51,
1275
0xcf,0x53,0xbf,0xa1,0x7e,0x53,0xbd,0x48,0x1d,0xa7,0x4e,0x54,0xa7,0xaa,0x83,0x5c,
1276
0x32,0xd4,0x2b,0xd4,0x01,0x2e,0xab,0xd5,0xd9,0xea,0x7c,0xf5,0x46,0xf5,0x56,0x75,
1277
0xa9,0xba,0x5c,0xbd,0x4f,0x5d,0xa7,0xde,0xaf,0x3e,0xa8,0x7e,0x57,0x7d,0x5c,0xdd,
1278
0xa9,0xfe,0x50,0xfd,0x89,0xfa,0x82,0xba,0x57,0x7d,0x45,0xfd,0xb5,0xfa,0x7b,0xf5,
1279
0x0d,0xb5,0x71,0x90,0x59,0x90,0x65,0x90,0x20,0xc8,0x2e,0x68,0x78,0x90,0x73,0x90,
1280
0x34,0xc8,0x33,0xc8,0x2f,0x28,0x20,0x28,0x24,0x28,0x32,0x28,0x26,0xe8,0xfe,0xa0,
1281
0x47,0x82,0x9e,0x08,0x7a,0x26,0xe8,0xc5,0xa0,0x31,0x41,0x13,0x83,0xa6,0x06,0xcd,
1282
0x0a,0x9a,0x17,0xb4,0x30,0x68,0x71,0x50,0x62,0x50,0x6a,0x50,0x46,0xd0,0xaa,0xa0,
1283
0x3f,0xfe,0x0d,0xfc,0xba,0xa0,0xbc,0xa0,0xa2,0xa0,0x2d,0x41,0x3b,0x82,0xca,0x82,
1284
0xf6,0x06,0xd5,0x06,0x35,0x05,0xb5,0x04,0x1d,0x09,0x6a,0x0b,0x3a,0x19,0x74,0x3a,
1285
0xe8,0xe3,0xa0,0x4f,0x83,0x7a,0x82,0x2e,0x07,0x7d,0x15,0xf4,0x5d,0xd0,0x4f,0x41,
1286
0x46,0xc1,0x7f,0x64,0x44,0xfd,0xd9,0xf5,0x85,0x69,0xb0,0x45,0xf0,0xd0,0x60,0xdb,
1287
0xe0,0x61,0xc1,0x92,0x60,0xb7,0x60,0x79,0xb0,0x6f,0xb0,0x2a,0x38,0x38,0x38,0x22,
1288
0x38,0x3a,0xf8,0xbe,0xe0,0x87,0x83,0x1f,0x0f,0x7e,0x3a,0xf8,0x85,0xe0,0x57,0x82,
1289
0x27,0x04,0x4f,0x09,0x9e,0x19,0xfc,0x5a,0xf0,0x82,0xe0,0x45,0xc1,0x09,0xc1,0x4b,
1290
0x82,0xd3,0x83,0x57,0x06,0xaf,0x0d,0xce,0x0d,0x2e,0x0c,0xde,0x1c,0x5c,0x12,0xbc,
1291
0x3b,0xb8,0x32,0xb8,0x26,0xb8,0x31,0xf8,0x40,0x70,0x6b,0xf0,0xb1,0xe0,0x8e,0xe0,
1292
0x0f,0x82,0xcf,0x04,0x9f,0x0f,0xbe,0x18,0xfc,0x79,0xf0,0xd5,0xe0,0x6f,0x83,0x7f,
1293
0x0c,0xa6,0x10,0x93,0x90,0x21,0x21,0xfc,0x10,0x9b,0x10,0x71,0x88,0x53,0x88,0x6b,
1294
0x88,0x2c,0xc4,0x27,0x44,0x19,0x12,0x14,0x12,0x1e,0x12,0x15,0xf2,0x3f,0xf7,0x97,
1295
0x1c,0x7a,0xb9,0x37,0xe4,0xa1,0x90,0xc7,0x42,0x9e,0x0a,0x79,0x3e,0xe4,0xe5,0x90,
1296
0xf1,0x21,0x93,0x43,0x66,0x84,0xcc,0x0d,0x79,0x23,0xe4,0xed,0x90,0xf8,0x90,0x94,
1297
0x90,0x65,0x21,0x2b,0x42,0xd6,0x84,0xac,0x0f,0xd9,0x10,0x52,0x1c,0xb2,0x3d,0x64,
1298
0x57,0xc8,0x9e,0x90,0xea,0x90,0x86,0x90,0xbf,0xe2,0xbb,0xce,0xe6,0x90,0x23,0x21,
1299
0xed,0x21,0x1f,0x84,0xdc,0xf9,0x8a,0xea,0xfe,0xad,0xdf,0x00,0xf9,0xed,0xf1,0x79,
1300
0x6b,0xfe,0x2f,0x7f,0xfb,0xf5,0xee,0xfc,0xfd,0xd9,0x9d,0xff,0xa6,0xe2,0x8f,0xfc,
1301
0x2e,0xdc,0x2f,0xd7,0x2f,0x3f,0xff,0x8d,0xe1,0x3f,0xfe,0xf9,0x24,0xa4,0x27,0xe4,
1302
0x6a,0x48,0x5f,0x88,0x45,0xa8,0x43,0xa8,0x34,0xf4,0xf7,0xfd,0x3d,0xcd,0xaf,0xff,
1303
0x55,0xcd,0x7f,0xf2,0xa3,0x0c,0x0d,0x0b,0x8d,0x0d,0x7d,0x3c,0xf4,0xa5,0xd0,0xa9,
1304
0xa1,0xff,0xb3,0x96,0xfc,0xa7,0x7e,0x27,0xf2,0xcf,0xd7,0xe9,0xd3,0xfd,0xef,0xb2,
1305
0xad,0x4f,0xc7,0xd6,0x61,0xc7,0xb0,0x15,0x17,0xb2,0x75,0xd8,0xb8,0xbf,0x0e,0xfb,
1306
0xcd,0xc7,0x9d,0xf5,0xf4,0xe9,0x2c,0xc0,0xcf,0xf5,0xf4,0xe9,0xfe,0xe7,0x7d,0xdd,
1307
0xa7,0xbb,0xe9,0x6b,0x7d,0x7f,0x6e,0xad,0x73,0x7b,0x7f,0xfa,0x74,0x77,0x43,0xcf,
1308
0xcd,0x3a,0x7d,0x3a,0x47,0xea,0xff,0xc6,0xe8,0xee,0xe8,0xf9,0xbb,0xce,0xdf,0x75,
1309
0xfe,0x53,0x75,0xde,0x08,0x7d,0x33,0x74,0x51,0x68,0xdf,0xef,0xf8,0x6f,0x35,0x41,
1310
0xbc,0x9f,0xff,0xb7,0x9a,0xb8,0xd0,0xdf,0xae,0xf3,0xe8,0x6d,0x75,0x92,0x42,0x7d,
1311
0x51,0x2e,0x14,0xc7,0x0f,0xe3,0xfc,0xdf,0x3a,0xff,0x6f,0xe9,0x9c,0x0b,0x61,0xe7,
1312
0xc1,0x3b,0xad,0x9d,0xee,0x76,0x5e,0xea,0x6d,0xeb,0x8f,0x0c,0x1c,0xaf,0xe2,0xf2,
1313
0xd6,0x19,0xce,0xe4,0xfd,0x5b,0x2b,0x94,0x22,0x94,0xde,0x02,0x76,0x80,0x32,0x43,
1314
0xcd,0xbd,0x88,0x6b,0x41,0x13,0x68,0x01,0x47,0x40,0x1b,0x38,0x19,0xfa,0xdb,0x7b,
1315
0xa0,0x9b,0x9f,0x45,0xa1,0x3a,0x5d,0xdf,0x7f,0x50,0x4e,0x87,0x7e,0x1c,0xfa,0x69,
1316
0xe8,0x66,0xa3,0x9e,0xd0,0x02,0xe3,0x93,0x64,0x67,0xec,0x64,0x94,0x65,0xfc,0x79,
1317
0xe8,0xd5,0xd0,0x12,0xe3,0x6f,0x43,0xaf,0x87,0xce,0x32,0x5e,0xeb,0xa2,0x0b,0x35,
1318
0x0e,0x33,0x09,0x1b,0x12,0xc6,0x0f,0x13,0x86,0xd9,0x85,0x0d,0x0f,0x73,0x0e,0x73,
1319
0x0d,0xf3,0x08,0xf3,0x0a,0xf3,0x0b,0x53,0x85,0xa9,0xc3,0x42,0xc2,0xc2,0xc3,0x34,
1320
0x61,0xd1,0x61,0xf7,0x84,0xdd,0x1f,0xc6,0x5e,0xe3,0x87,0xc2,0x1e,0x0d,0x7b,0x32,
1321
0xec,0x99,0xb0,0xb1,0x2e,0x4b,0x8d,0x76,0x19,0xed,0x37,0x7a,0x21,0xec,0xa8,0xd1,
1322
0x4b,0x61,0xff,0xde,0x4e,0xfe,0xce,0x6f,0x5d,0xfa,0x7e,0x51,0xf7,0x66,0x2f,0x7e,
1323
0xf9,0xff,0xa3,0xf4,0xff,0x3d,0xea,0xce,0xff,0x3b,0x6a,0x24,0xf7,0x5f,0xa3,0x1c,
1324
0x47,0x7e,0x30,0xa8,0x9c,0x57,0xc5,0xfb,0x72,0x50,0xf6,0xa0,0x3d,0x83,0xee,0xdc,
1325
0x02,0x5b,0x9f,0xf7,0xb3,0xba,0xec,0x7f,0x9d,0x9a,0x86,0x7a,0xbb,0x78,0x47,0x79,
1326
0xab,0x06,0xb5,0x3b,0xe7,0x0e,0xfa,0x3d,0x5e,0x1e,0x17,0xf6,0x6a,0xd8,0xf4,0xb0,
1327
0x39,0x61,0xaf,0x87,0xbd,0x15,0x16,0x17,0x96,0x1c,0xb6,0x34,0x6c,0x79,0x58,0x56,
1328
0x58,0x4e,0x58,0x41,0xd8,0xa6,0xb0,0x6d,0x61,0x3b,0xc3,0x2a,0xc2,0xaa,0xc2,0xea,
1329
0xc3,0xde,0x09,0x3b,0x14,0xf6,0x5e,0x58,0x7b,0xd8,0xa9,0xb0,0x7f,0x86,0x9d,0x0d,
1330
0xeb,0x0a,0xbb,0x14,0xf6,0x45,0xd8,0x37,0x61,0x3f,0x84,0xf5,0x85,0xf1,0xc2,0xcd,
1331
0xc3,0xff,0xcc,0xfa,0x97,0x7d,0xc7,0x7c,0x43,0x69,0xaa,0xea,0xd3,0x69,0x54,0x7c,
1332
0x15,0xa9,0x9c,0x54,0xd1,0xdc,0xbb,0x5d,0xf6,0x7d,0xae,0x50,0xe5,0xa6,0xf2,0x54,
1333
0x39,0xa8,0x7c,0x54,0x96,0x2a,0x5b,0x15,0xfb,0xe6,0x99,0xa7,0x1a,0xac,0x1a,0xae,
1334
0x1a,0xa9,0xf2,0x50,0x59,0x85,0xa7,0x79,0x0d,0x0d,0x17,0x85,0xf7,0xe9,0xd8,0xfa,
1335
0x7d,0xba,0x70,0xfd,0xfb,0x5c,0x84,0x77,0xaa,0xdf,0xa7,0xeb,0xaf,0x8f,0xf5,0x21,
1336
0xf0,0xf8,0xd9,0x9b,0xc1,0x1b,0x03,0x6f,0xcb,0xf5,0xf5,0xfb,0x74,0x2a,0xa0,0xaf,
1337
0xdf,0xa7,0xeb,0xaf,0xcf,0x9e,0xbf,0xb5,0x7e,0x1a,0xfb,0x8d,0xed,0x2f,0xf4,0xeb,
1338
0xed,0xc7,0xdc,0xf1,0x2f,0xf4,0xeb,0xed,0xef,0xd3,0x0d,0x05,0xfd,0xfd,0x67,0xdf,
1339
0x57,0xf7,0xf7,0x9f,0xd5,0xff,0x5b,0xfd,0xbf,0x69,0xfd,0x2f,0xfd,0xf7,0xef,0xd5,
1340
0xb7,0x0b,0x17,0x87,0x8f,0x08,0x97,0x84,0xbb,0x84,0x4b,0xc3,0x65,0xe1,0x5e,0xe1,
1341
0xbe,0xe1,0x8a,0x5b,0xae,0xe8,0x1f,0xf9,0x3b,0xaf,0x80,0x70,0x13,0x3c,0xa1,0x4b,
1342
0x25,0xe1,0xe1,0x7f,0x6c,0x7f,0xa3,0x09,0x4f,0x95,0x44,0x87,0x2f,0x0a,0xbd,0x27,
1343
0xfc,0x81,0x3f,0x34,0xb6,0x1e,0x0e,0x7f,0x34,0xfc,0x89,0xf0,0xbb,0xb3,0x3f,0x7b,
1344
0x2a,0xfc,0xee,0xbc,0x27,0xf9,0x35,0x79,0x36,0xfc,0xe5,0xf0,0xc9,0xe2,0x5f,0x3f,
1345
0x3f,0x44,0x38,0x31,0x7c,0x4a,0xf8,0x8c,0x70,0x77,0xc1,0x9c,0xf0,0xf9,0xe1,0xce,
1346
0x76,0x0b,0xc3,0x17,0x85,0xc7,0x87,0x57,0xbb,0x27,0x87,0xa7,0x85,0x67,0x84,0xaf,
1347
0x0c,0x5f,0x13,0x9e,0x13,0x9e,0x23,0xcc,0x0f,0x2f,0x0a,0xdf,0x1c,0xbe,0x3d,0x7c,
1348
0x67,0x78,0x79,0xb8,0xb5,0x80,0xec,0xf6,0x86,0x17,0x38,0x58,0xda,0x6d,0x74,0xa8,
1349
0x09,0x5f,0x28,0x6a,0x08,0x7f,0x27,0xfc,0x60,0xf8,0x91,0xf0,0x63,0xe1,0x2f,0x38,
1350
0x28,0x85,0x27,0xc2,0x4f,0x85,0x7f,0x18,0xfe,0x71,0x78,0x7f,0xfb,0xe7,0xc3,0x3f,
1351
0x0f,0xff,0x36,0x9c,0x22,0x86,0x44,0xd8,0x44,0x38,0x45,0xc8,0x22,0x94,0x11,0x3f,
1352
0xd7,0x1f,0x1e,0xa1,0x8d,0xf8,0xbd,0xef,0x2f,0xfe,0xea,0xf7,0x1f,0x7f,0xe4,0x73,
1353
0xe7,0xf7,0x1f,0x37,0xf5,0xc7,0x46,0xdc,0x1f,0xf1,0x70,0xc4,0x63,0x11,0x4f,0x45,
1354
0xf8,0xc8,0x9e,0x8b,0x18,0x1d,0x31,0x26,0x62,0x42,0x84,0x42,0x36,0x39,0x62,0x7a,
1355
0xc4,0xec,0x88,0x40,0xd9,0xfc,0x88,0x85,0x11,0x8b,0x22,0xe2,0x23,0x52,0x22,0x96,
1356
0x46,0x64,0x84,0x67,0x46,0xac,0x8e,0x58,0x17,0x91,0x1b,0xb1,0x21,0x42,0x28,0xdf,
1357
0x14,0x31,0x4a,0xb0,0x2d,0xa2,0x34,0xa2,0x2c,0xa2,0x32,0xe2,0x54,0x78,0x75,0x44,
1358
0x7d,0x84,0xbb,0x9c,0xfd,0x2d,0x1f,0x4f,0xf9,0xfe,0x88,0x96,0x88,0x31,0xd2,0xd6,
1359
0x88,0x28,0xd9,0xd1,0x88,0xf6,0x88,0xce,0x88,0xd3,0x9c,0x9c,0x89,0x38,0x1f,0xd1,
1360
0x1d,0x71,0x29,0xe2,0x4a,0xc4,0xd7,0x11,0xdf,0x45,0xfc,0x18,0xa1,0x8b,0xe0,0x45,
1361
0x9a,0x45,0x5a,0x44,0xf2,0x23,0x45,0x91,0xf6,0x91,0xc3,0x23,0x25,0x91,0xae,0x10,
1362
0xa5,0xdc,0x23,0xd2,0x2b,0xd2,0x2f,0x52,0x15,0xf9,0x80,0x2c,0x28,0x32,0x2c,0x52,
1363
0x13,0xb9,0xcd,0x23,0x26,0xf2,0xbe,0xc8,0x87,0x22,0x1f,0x8d,0x7c,0x32,0xf2,0x99,
1364
0xc8,0x17,0x22,0x5f,0x8e,0x1c,0x17,0xf9,0x6a,0xe4,0xb4,0xc8,0x59,0x91,0x73,0xc2,
1365
0x5f,0x8b,0x7c,0x23,0xf2,0xad,0xc8,0xb8,0xc8,0xe4,0xc8,0xb4,0xc8,0x8c,0xc8,0x95,
1366
0x91,0x6b,0x22,0x73,0x22,0xf3,0x23,0x8b,0x22,0x37,0x43,0xb6,0x47,0xee,0x8a,0xac,
1367
0x88,0x7c,0x5c,0xba,0x2f,0xb2,0x36,0xb2,0x29,0xf2,0x40,0xe4,0xe1,0xc8,0xbd,0x82,
1368
0xf7,0x22,0x8f,0x47,0x36,0x08,0x4e,0x46,0x7e,0x10,0xf9,0x51,0xe4,0xb9,0xc8,0xae,
1369
0xc8,0x4b,0x91,0x57,0x22,0xbf,0x8a,0xfc,0x36,0xf2,0x7a,0x64,0x5f,0xa4,0xb1,0xc6,
1370
0x54,0x33,0x44,0x63,0xad,0x11,0x6a,0xec,0x34,0xc3,0x35,0x12,0x8d,0xab,0xc6,0x43,
1371
0x13,0xe7,0xe6,0xa5,0xe9,0x16,0xf8,0x6b,0xfc,0x35,0x81,0x9a,0x10,0x48,0x84,0x26,
1372
0x4a,0x73,0xaf,0xe6,0x21,0xcd,0xa3,0x9a,0x27,0x35,0xcf,0x68,0x5e,0xd0,0xbc,0xac,
1373
0x19,0xa7,0x99,0xa4,0x99,0xaa,0x99,0xa9,0x19,0x2d,0x9b,0xab,0x79,0x43,0xf3,0x96,
1374
0x86,0xd1,0x8c,0x95,0x33,0x9a,0x44,0xcd,0x04,0xd9,0x12,0xcd,0x32,0xcd,0x72,0xcd,
1375
0x6a,0xcd,0x64,0x99,0xad,0xdb,0x3a,0x4d,0xae,0x66,0x83,0x66,0x93,0x66,0xab,0x66,
1376
0x87,0x66,0xb7,0xa6,0x52,0x53,0xad,0xa9,0xd7,0xec,0xd7,0xb4,0x68,0x5a,0x35,0xc7,
1377
0x34,0x27,0x34,0xa7,0x34,0x1f,0x6a,0x3e,0xd6,0x9c,0xd7,0x74,0x6b,0x2e,0x69,0xae,
1378
0x68,0xa6,0xcb,0xbe,0xd2,0x7c,0xab,0xf9,0x51,0xa3,0xd3,0xf0,0xb4,0x66,0xda,0x79,
1379
0x32,0x0b,0x2d,0x5f,0x2b,0xd2,0xda,0x6b,0x87,0x6b,0x25,0x5a,0x57,0xad,0x87,0x96,
1380
0xfd,0x5d,0x24,0x2f,0xad,0x9f,0x56,0xa5,0x0d,0xd2,0x86,0x6b,0xb5,0xda,0x58,0xed,
1381
0xfd,0xda,0x05,0xb2,0x87,0xb5,0x8f,0x6b,0x9f,0xd2,0x3e,0xa7,0xf5,0xf1,0x1c,0xad,
1382
0x1d,0xa3,0x9d,0xa0,0x9d,0xac,0x9d,0xae,0x9d,0xa3,0x9d,0xaf,0x5d,0xa8,0x5d,0xa4,
1383
0x4d,0xd0,0xa6,0x68,0x97,0x6a,0x33,0xb5,0x59,0xd2,0x55,0xda,0xb5,0xda,0x5c,0x6d,
1384
0xa1,0x76,0xb3,0x76,0xbb,0x76,0x97,0xb6,0x42,0xbb,0x4f,0x5b,0xab,0x6d,0xd4,0xbe,
1385
0x2d,0x3b,0xe7,0xde,0xac,0x3d,0xa4,0x7d,0x57,0xdb,0xa6,0x3d,0xa9,0xfd,0x40,0xfb,
1386
0x91,0xf6,0xac,0x36,0x43,0x7e,0x41,0xdb,0xa3,0xbd,0xac,0xbd,0xaa,0xbd,0xa6,0xbd,
1387
0xae,0xd5,0x69,0x79,0x51,0x2b,0xe5,0x66,0x51,0x16,0x51,0xfc,0x28,0x51,0x94,0x7d,
1388
0xd4,0xf0,0x28,0x49,0x94,0x5b,0x94,0x2c,0xca,0x27,0x4a,0x11,0xa5,0x8e,0xca,0x91,
1389
0x87,0x46,0x45,0x46,0xc5,0x44,0xdd,0x17,0xf5,0x50,0xd4,0x63,0x51,0x4f,0x45,0x3d,
1390
0x17,0x35,0x3a,0x6a,0x4c,0xd4,0x04,0xc8,0xe4,0xa8,0xe9,0x51,0x45,0xf2,0xd9,0x51,
1391
0xf3,0xa2,0x16,0x44,0xbd,0x1d,0x15,0x17,0x95,0x1c,0x95,0x16,0x35,0x5a,0x9a,0x19,
1392
0xb5,0x3a,0x6a,0x5d,0x54,0x5e,0x54,0x51,0xd4,0x96,0xa8,0x92,0xa8,0x1a,0xf9,0xae,
1393
0xa8,0x3d,0x51,0xd5,0x51,0x0d,0x51,0xcd,0x51,0x87,0x20,0x0d,0xf2,0x40,0xcf,0x77,
1394
0xa3,0xda,0xa2,0x3a,0xa2,0xde,0x8f,0xfa,0x28,0xaa,0xd5,0xed,0xa0,0xfc,0x6c,0xd4,
1395
0x85,0xa8,0x62,0x59,0x6f,0xd4,0x95,0xa8,0x1f,0x3c,0xbe,0x8e,0xfa,0x2e,0xaa,0x4c,
1396
0xf6,0x63,0x94,0x2e,0x8a,0x17,0x6d,0x0e,0xb1,0x8a,0x16,0x44,0xdb,0x46,0x0f,0x8b,
1397
0x76,0x8a,0x76,0x89,0x76,0x8f,0xf6,0x8a,0xf6,0x8b,0x56,0x45,0x07,0x45,0x87,0x45,
1398
0x6b,0xa2,0x63,0xa3,0xef,0x8f,0x7e,0x38,0xfa,0xb1,0xe8,0x7f,0x44,0x3f,0x1b,0xfd,
1399
0x62,0xf4,0x98,0xe8,0x89,0xd1,0x53,0xa2,0x67,0x46,0xcf,0x8d,0x7e,0x23,0xfa,0xad,
1400
0xe8,0x56,0x19,0x13,0x9d,0x14,0x9d,0x16,0x9d,0x11,0xbd,0x2a,0x7a,0x6d,0x74,0x6e,
1401
0xf4,0x86,0xe8,0x4d,0xd1,0x5b,0xa3,0x77,0x44,0xef,0x8e,0xde,0x13,0x5d,0x1d,0xdd,
1402
0x10,0xdd,0x1c,0x1d,0xa8,0x39,0x1c,0xfd,0x5e,0xf4,0xf1,0xe8,0x93,0xd1,0x1f,0x44,
1403
0x7f,0x14,0x7d,0x36,0xfa,0x42,0x74,0x4f,0xf4,0xe7,0xd1,0x5f,0x46,0x7f,0x13,0x5d,
1404
0x28,0xfd,0x21,0xfa,0x46,0xb4,0x51,0x8c,0x49,0xcc,0xe0,0x18,0xab,0x98,0x4e,0x99,
1405
0x20,0xc6,0x36,0x46,0x1c,0xe3,0x18,0x33,0x32,0xc6,0x3d,0xc6,0x2b,0xc6,0x3f,0x26,
1406
0x20,0x26,0x38,0x26,0x3c,0x46,0x1b,0x73,0x4f,0xcc,0x03,0x31,0xa3,0x62,0x9e,0x88,
1407
0x79,0x3a,0xe6,0x85,0x98,0x57,0x62,0xc6,0xc7,0x54,0xba,0xbd,0x1a,0x33,0x2d,0x66,
1408
0x56,0xcc,0x6b,0x31,0x6f,0xc4,0xbc,0x15,0x73,0x5e,0xce,0xc4,0x24,0xc6,0x2c,0x89,
1409
0x59,0x16,0xb3,0x3c,0x66,0x75,0xcc,0xba,0x98,0xdc,0x98,0x51,0xa2,0x0d,0x31,0xc5,
1410
0x31,0xdb,0x62,0x4a,0x63,0xca,0x62,0x2a,0x63,0xaa,0x63,0x1a,0x62,0x9a,0x63,0x0e,
1411
0xc5,0xbc,0x1b,0xf3,0xad,0xfc,0xba,0x7c,0x8a,0xa8,0x2d,0xe6,0x64,0xcc,0x07,0x31,
1412
0x1f,0xc5,0x9c,0x8d,0xb9,0x10,0xd3,0x1b,0x73,0x25,0xe6,0xab,0x98,0x6f,0x63,0xae,
1413
0xc7,0xe8,0x62,0xfa,0xe4,0xbc,0x58,0xf3,0x58,0xab,0x58,0x41,0xac,0x6d,0xac,0x38,
1414
0xd6,0x29,0xd6,0x25,0xd6,0x3d,0xd6,0x33,0xd6,0x37,0x56,0x19,0xab,0x8e,0x0d,0x8d,
1415
0xd5,0xc4,0xc6,0xc4,0xde,0x17,0xfb,0x50,0xec,0x63,0xb1,0xff,0x88,0x7d,0x36,0xf6,
1416
0xc5,0xd8,0x57,0x62,0x27,0xc4,0x4e,0x89,0x9d,0x11,0x3b,0x27,0x76,0x7e,0xec,0x9b,
1417
0xb1,0x8b,0x63,0xed,0x3c,0xed,0x3c,0x13,0x63,0x97,0xc4,0xa6,0xc7,0xae,0x88,0xcd,
1418
0x8a,0xcd,0x8e,0xcd,0x8b,0x2d,0x8c,0x2d,0x8e,0xdd,0x16,0x3b,0xcc,0x73,0x67,0x6c,
1419
0x79,0xec,0xde,0xd8,0x9a,0xd8,0x86,0xd8,0x77,0x62,0x0f,0xc5,0xbe,0x1b,0x7b,0x3c,
1420
0xb6,0x33,0xd6,0xd3,0xe6,0xc3,0xd8,0x50,0x9b,0x8f,0x63,0xcf,0xc7,0x76,0xc7,0x5e,
1421
0x8a,0x1d,0x65,0x73,0x25,0xf6,0x6e,0xac,0x72,0x6f,0x7b,0x1f,0xca,0xfe,0x77,0x9a,
1422
0x14,0x09,0x35,0xe9,0x74,0x5f,0xf4,0xbf,0x64,0xe5,0x42,0x8d,0xe1,0xe8,0xe2,0xad,
1423
0x73,0x1b,0x8f,0x7e,0x96,0xab,0xd1,0x2d,0x46,0xf8,0xa8,0x8e,0xfb,0xcf,0x52,0xcc,
1424
0x40,0xa9,0x1f,0xd9,0xff,0x21,0x51,0xf0,0x83,0x4e,0x77,0xa3,0xe5,0xeb,0x2b,0x8d,
1425
0x38,0xba,0x71,0xf9,0xeb,0xc6,0x30,0x23,0x6a,0xd3,0xf1,0xfa,0xae,0x70,0xf9,0x97,
1426
0xbf,0xfe,0xfc,0x50,0xc4,0x29,0x87,0x43,0xba,0xe6,0x43,0x11,0x71,0xac,0x6e,0x33,
1427
0xdd,0x27,0x37,0x90,0xaf,0xfb,0xfa,0x93,0x88,0x57,0x82,0xda,0xd8,0xb6,0xb8,0xe3,
1428
0x2f,0xd8,0xe3,0x59,0x6d,0x3a,0x6b,0xe2,0x8e,0x59,0xe3,0x6e,0x7c,0xa9,0x6b,0x63,
1429
0x57,0x71,0xba,0xc5,0x3f,0x41,0x93,0xdf,0xe2,0xc4,0x97,0x75,0x4d,0xba,0x11,0xac,
1430
0x5d,0x7c,0xae,0x5f,0x9f,0xe8,0xcc,0xb8,0x38,0x62,0x71,0x04,0x57,0x81,0x0b,0xd9,
1431
0x83,0xc5,0x06,0xeb,0x22,0x74,0xb7,0xf4,0x41,0x62,0xf0,0x00,0xfb,0x5c,0x90,0xdc,
1432
0xfa,0x92,0x14,0x9d,0x83,0x11,0x8b,0x89,0x6d,0x56,0xf7,0x09,0xfb,0x9f,0x81,0xd0,
1433
0x5b,0x9e,0xbe,0xac,0x6e,0xe0,0x3f,0x69,0x69,0xd8,0xfc,0xc5,0x3a,0xbe,0x8e,0x7f,
1434
0x95,0x3b,0x94,0xe8,0xfd,0xc3,0xe7,0x5a,0x3d,0x64,0x28,0xd4,0x66,0x88,0x59,0x03,
1435
0x0a,0xb8,0x36,0x34,0x37,0xdf,0xc5,0x1a,0xbc,0x6d,0xf8,0xf0,0xbf,0x34,0x24,0xbe,
1436
0xd7,0x7d,0xda,0xff,0x22,0x5b,0xaf,0x51,0xdf,0xb2,0xfe,0xff,0x8c,0xe3,0x32,0xd0,
1437
0xad,0x4d,0x37,0x3a,0x73,0xcd,0xd3,0x62,0xc3,0xa7,0xdf,0x38,0x3e,0xf7,0x2d,0xc1,
1438
0xcd,0x0f,0x67,0xad,0xa1,0x97,0x8b,0x6f,0x7d,0x23,0xce,0x1f,0x18,0x0f,0xfa,0x58,
1439
0xa2,0xe3,0x69,0x9a,0x0c,0x7d,0xd5,0xf1,0x19,0x2e,0xa7,0x51,0xd7,0x6c,0xe8,0x83,
1440
0xbe,0xb6,0x46,0xf7,0xb5,0xfe,0x7f,0x48,0xd0,0xf7,0xec,0xf1,0xa2,0x45,0x8b,0xe8,
1441
0xa6,0x66,0x7d,0x5d,0x3e,0xfb,0xbf,0xb6,0xbf,0xef,0xd7,0x60,0x18,0x77,0x5f,0x70,
1442
0x8d,0xec,0x43,0x19,0xcd,0x2d,0xe3,0xd0,0x2c,0x85,0x8b,0x32,0xd9,0x93,0x12,0xa3,
1443
0x9b,0x23,0x54,0x73,0xd3,0x62,0xae,0xef,0xdc,0xdf,0x80,0xf3,0xcf,0x0e,0x5c,0x03,
1444
0x36,0x6c,0xd4,0xbb,0x5c,0x73,0xb3,0x16,0xdd,0xec,0x18,0xd7,0x6b,0xe4,0x6b,0xb8,
1445
0xe1,0xd3,0xb8,0xc2,0x50,0x9c,0xeb,0x04,0x33,0x70,0x2f,0x04,0x7d,0xaf,0x57,0xae,
1446
0x4b,0xd0,0x7b,0x77,0xc0,0x2e,0x5c,0x8f,0x9f,0xb8,0xc4,0xcc,0x2f,0xbf,0x80,0x2b,
1447
0x35,0x29,0x18,0x19,0x46,0xb7,0x7e,0xc7,0xc0,0x35,0xf4,0x7d,0xbf,0x37,0x35,0x7d,
1448
0x7a,0x93,0x59,0xb3,0x78,0x4e,0xd4,0x87,0xf3,0x46,0xb7,0xde,0x6f,0x66,0x3f,0x19,
1449
0xec,0x83,0x7f,0x7f,0xf6,0xdd,0x84,0xde,0x73,0x61,0x3c,0xfa,0xa9,0x6f,0xe0,0x48,
1450
0x7f,0x95,0xfb,0xad,0xe1,0xae,0x11,0xeb,0x77,0xb6,0x09,0x4d,0xff,0xcd,0xf6,0x89,
1451
0x19,0x71,0xa3,0x95,0x37,0x70,0xeb,0xd2,0xcd,0xab,0xcb,0xbe,0x61,0xd6,0xdf,0x8d,
1452
0x86,0x66,0xf0,0x59,0x5c,0x0f,0x07,0xf4,0xff,0x47,0x2a,0x33,0x1d,0x4f,0x7f,0x9f,
1453
0x5e,0xfe,0xb1,0x20,0x24,0xee,0x6c,0x9b,0x04,0xe5,0x1f,0xe2,0xfc,0xa4,0x2b,0xfe,
1454
0xae,0xd1,0xc8,0x54,0xaf,0xf9,0x0b,0xb6,0x2e,0x6b,0xf3,0xcd,0x7e,0x68,0xf4,0xc3,
1455
0x09,0x1f,0xd4,0xe0,0x41,0x0d,0x0d,0xcc,0x26,0x3c,0xfd,0xc5,0xe6,0xee,0x2f,0x3e,
1456
0x6b,0xc9,0xcf,0xe6,0x1b,0xc3,0xdf,0xf0,0x9b,0x31,0x8b,0xbf,0x9a,0xc9,0xea,0xf9,
1457
0x61,0x31,0x0d,0x98,0x46,0x06,0x57,0xff,0x24,0xd1,0xeb,0x1b,0xf8,0x70,0x7d,0x34,
1458
0xbb,0xc5,0x5f,0x86,0xf6,0x78,0xac,0xee,0x1b,0xfa,0x5b,0xeb,0xe6,0xd8,0x46,0x23,
1459
0x7d,0xb8,0x17,0xb8,0x6e,0x2f,0xde,0xc3,0xda,0xdd,0xc8,0x96,0x59,0xfc,0x63,0xbf,
1460
0x97,0xf8,0x3a,0x1e,0xaf,0xdf,0x26,0x23,0x9d,0xbe,0x81,0x43,0x3f,0xd7,0x60,0xb8,
1461
0xcf,0x74,0x3c,0x86,0x4f,0xfd,0xd7,0xfa,0xd6,0xfb,0xd4,0xec,0x96,0x5c,0x0d,0x0d,
1462
0xdc,0xdf,0xcd,0x03,0x05,0x16,0x73,0xba,0x34,0x1a,0xac,0x04,0x75,0x3f,0xc2,0x94,
1463
0xb3,0xba,0x81,0xb1,0xa6,0xbf,0x15,0x74,0x29,0x86,0x92,0xcc,0xcd,0xef,0xaa,0x24,
1464
0xb4,0xb8,0xbf,0xa7,0x8c,0x7e,0xc4,0xb3,0xe5,0xfb,0xe7,0xdc,0x5b,0xcc,0xa3,0x2f,
1465
0x66,0x12,0x76,0x30,0x5f,0x1a,0x0d,0x5c,0x47,0xc3,0x3d,0xc2,0x47,0xe7,0x1d,0xcf,
1466
0x0e,0xcc,0xde,0x9a,0x9b,0x37,0x9e,0xe6,0x67,0xf7,0x04,0x9f,0x0c,0x63,0xc4,0x08,
1467
0xc9,0xef,0xfb,0xf4,0xbd,0x93,0x70,0x05,0x99,0x5b,0xae,0x97,0x04,0x2d,0x34,0xdf,
1468
0x3a,0x4a,0x07,0xbc,0x90,0x40,0x3f,0x9f,0x89,0x52,0xf4,0xa3,0x56,0x3f,0xaa,0x17,
1469
0xcf,0xd4,0x2d,0x2e,0x30,0x5c,0x79,0x78,0xbb,0xf9,0xd6,0xff,0xd8,0xa3,0xff,0x48,
1470
0xfa,0x53,0xfa,0x9b,0x96,0xfb,0xbf,0x6d,0xb0,0x69,0x71,0xff,0x0a,0x5d,0x9f,0xdd,
1471
0xa4,0x2f,0xf3,0x35,0xec,0x90,0x70,0xd7,0x8d,0x7f,0x73,0x04,0xb1,0xd7,0x75,0xe0,
1472
0x5e,0xd7,0xe8,0xf8,0x3c,0xc3,0x9d,0xc6,0xe5,0x68,0x74,0x92,0xc5,0x57,0x31,0x88,
1473
0x33,0xd9,0x1b,0xf1,0x3b,0xdd,0x2d,0xf3,0xef,0xcd,0x99,0xc4,0x30,0x87,0xd3,0x18,
1474
0x1a,0x4b,0xe3,0x68,0x3c,0x4d,0xa0,0x89,0x34,0x89,0x5e,0xa5,0xc9,0x34,0x85,0xa6,
1475
0xd2,0x34,0x9a,0x4e,0x33,0x68,0x26,0xcd,0xa2,0xd9,0x34,0x87,0xe6,0xd2,0x6b,0x34,
1476
0x8f,0xe6,0xd3,0xeb,0xf4,0x06,0x2d,0xa0,0x85,0xe4,0x4c,0xce,0xef,0x2d,0x01,0x89,
1477
0xc4,0xfe,0x2e,0x9a,0xf3,0x7b,0x71,0x74,0xac,0x0e,0xd1,0x16,0xec,0x25,0x15,0xe7,
1478
0xe3,0x12,0x03,0xb8,0x10,0xa7,0xb8,0x74,0xf3,0x06,0x6a,0x2e,0xa4,0xe6,0x22,0x6a,
1479
0xde,0x48,0xcd,0x9b,0xa8,0xb9,0x98,0x9a,0x37,0x53,0xf3,0x16,0x6a,0xde,0x4a,0xcd,
1480
0xdb,0xa8,0x79,0x3b,0x35,0x97,0x50,0xf3,0x0e,0x6a,0x2e,0xa5,0xe6,0x9d,0xd4,0xbc,
1481
0x8b,0x9a,0x77,0x53,0x73,0x19,0x35,0x97,0x53,0x73,0x05,0x35,0xef,0xa1,0xe6,0x4a,
1482
0x6a,0xde,0x4b,0xcd,0x55,0xd4,0x5c,0x4d,0xcd,0x35,0xd4,0x5c,0x4b,0xcd,0x75,0xd4,
1483
0x5c,0x4f,0xcd,0x0d,0x74,0x20,0x8e,0x0e,0x24,0xd0,0x81,0x24,0x3a,0x90,0x42,0x07,
1484
0x52,0xe9,0xc0,0x52,0x3a,0x90,0x4e,0x07,0x32,0xe9,0xc0,0x0a,0x3a,0xb0,0x8a,0x0e,
1485
0x64,0xd1,0x81,0xb5,0x74,0x20,0x9b,0x0e,0xac,0xa7,0x03,0x79,0x74,0xa0,0x80,0x0e,
1486
0x14,0xd2,0x81,0x8d,0x74,0xa0,0x98,0x0e,0x6c,0xa1,0x03,0xdb,0xe8,0x40,0x09,0x1d,
1487
0x28,0xa5,0x03,0xbb,0x68,0xf2,0x7b,0x29,0x34,0x79,0x0a,0x1d,0xa8,0xa4,0x03,0xfb,
1488
0xe8,0x40,0x0d,0x1d,0xa8,0xa3,0x03,0x0d,0x34,0xed,0x9d,0x7d,0xd4,0x12,0x4f,0x2d,
1489
0x89,0xd4,0x92,0x4c,0x2d,0x4b,0xe8,0x48,0xdd,0x0c,0x6a,0x59,0x4a,0x2d,0xe9,0xd4,
1490
0x92,0x49,0x2d,0x2b,0xa8,0x65,0x15,0xb5,0x64,0x51,0xcb,0x5a,0x6a,0xc9,0xa6,0x96,
1491
0xf5,0xd4,0x92,0x47,0x2d,0x05,0xd4,0x52,0x48,0x2d,0x1b,0xa9,0xa5,0x98,0x5a,0xb6,
1492
0x50,0xcb,0x36,0x6a,0x29,0xa1,0x96,0x52,0x6a,0xd9,0x45,0x2d,0x65,0xd4,0x52,0x41,
1493
0x2d,0x95,0xd4,0xb2,0x8f,0x9a,0x1b,0xa9,0xa5,0x86,0x5a,0xea,0xa8,0xa5,0x81,0x5a,
1494
0x57,0xd1,0xc1,0x04,0x3a,0x98,0x44,0xad,0xab,0xe9,0xe0,0x12,0x6a,0x5d,0x43,0xad,
1495
0x6b,0xe9,0xe0,0x32,0x3a,0x94,0x47,0xad,0xd9,0xd4,0xba,0x9e,0x0e,0xae,0xa4,0xd6,
1496
0x0d,0xd4,0xba,0x91,0x5a,0xb7,0x51,0xeb,0x56,0x3a,0x88,0xcc,0x5d,0xd4,0x5a,0x4e,
1497
0xad,0x95,0x74,0xb0,0x90,0x0e,0x6e,0xa4,0x83,0xc5,0x74,0x84,0xa1,0x83,0x5b,0xe9,
1498
0x08,0xda,0x29,0xa5,0x23,0x4b,0xe8,0xe0,0x6e,0x3a,0x92,0x46,0x47,0x96,0xd2,0xc1,
1499
0x3d,0x74,0x70,0x2f,0x1d,0x59,0x49,0x07,0xab,0xe9,0x60,0x3d,0x8d,0x87,0xbe,0x69,
1500
0x53,0x68,0xc6,0x14,0x3a,0x94,0x41,0x87,0x96,0xd3,0xa1,0x95,0x74,0x68,0x35,0x1d,
1501
0x5a,0x43,0x87,0xd6,0xd1,0xa1,0x1c,0x3a,0x94,0x4b,0x87,0x0a,0xe8,0x50,0x21,0x1d,
1502
0xda,0x48,0x87,0x8a,0xe9,0xd0,0x16,0x3a,0xb4,0x8d,0x0e,0x95,0xd0,0xa1,0x52,0x3a,
1503
0xb4,0x8b,0xc6,0x2f,0xa4,0x43,0x50,0x99,0x45,0x07,0x1b,0xe9,0x50,0x35,0x1d,0xaa,
1504
0xa5,0x43,0xf5,0x74,0xa8,0x91,0x0e,0xc7,0xd1,0xe1,0x04,0x3a,0x9c,0x44,0x87,0x53,
1505
0xe8,0x70,0x2a,0x1d,0x5e,0x4a,0x87,0xd3,0xe9,0x70,0x26,0x1d,0x5e,0x41,0x87,0x57,
1506
0xd1,0xe1,0x2c,0x3a,0xbc,0x96,0x0e,0x67,0xd3,0xe1,0xf5,0x74,0x38,0x8f,0x0e,0x17,
1507
0xd0,0xc1,0x7c,0x3a,0xbc,0x91,0x0e,0x17,0xd3,0xe1,0x2d,0x74,0x78,0x1b,0x1d,0x2e,
1508
0xa1,0xc3,0xa5,0x74,0x78,0x17,0x1d,0x2e,0xa3,0xc3,0x15,0x74,0xbe,0x0c,0x27,0xea,
1509
0xe8,0x60,0x0e,0x52,0x9b,0xa9,0x35,0x9e,0x0e,0x32,0x74,0x24,0x95,0x8e,0x2c,0xa3,
1510
0xd6,0x14,0x6a,0x4d,0xa5,0xd6,0xa5,0xd4,0x9a,0x4e,0xad,0x99,0xd4,0x8a,0xb3,0xd5,
1511
0xd4,0x5a,0x4b,0x47,0xe2,0x30,0xf0,0x92,0x41,0x0a,0x48,0x03,0x5b,0x41,0x02,0x58,
1512
0x4a,0x47,0xb2,0xe8,0x3d,0x86,0x30,0x38,0xdf,0x5b,0x45,0xef,0x2d,0x61,0x07,0x69,
1513
0x35,0x1d,0x2d,0xa3,0xa3,0x15,0x74,0x04,0x89,0x7d,0xe4,0x8c,0xe3,0x30,0x6a,0xab,
1514
0x60,0x07,0x33,0x7b,0x76,0x07,0xe1,0x8a,0x1f,0x2b,0xa5,0x63,0x3b,0xe9,0xd8,0x2e,
1515
0x6a,0x5b,0x46,0x6d,0xe9,0xd4,0x96,0x41,0xc7,0xca,0xe8,0x58,0x39,0x1d,0xab,0xa0,
1516
0x63,0x7b,0xe8,0x58,0x25,0x1d,0xdb,0x4b,0xc7,0x50,0xac,0x8a,0x8e,0xd5,0xd0,0xb1,
1517
0x5a,0x3a,0x56,0x4f,0xc7,0x1a,0xe8,0x58,0x23,0xb5,0x31,0xd4,0x16,0x47,0x6d,0x09,
1518
0xd4,0x96,0x48,0x6d,0x49,0xd4,0x96,0x4c,0x6d,0x29,0xd4,0xb6,0x84,0xda,0x52,0xa9,
1519
0x2d,0x8d,0xda,0x96,0x52,0xdb,0x5a,0x6a,0xcb,0xa6,0xb6,0xf5,0xd4,0x96,0x47,0x6d,
1520
0x05,0xd4,0x56,0x48,0x6d,0x1b,0xa9,0xad,0x98,0xda,0xb6,0x50,0xdb,0x36,0x6a,0x2b,
1521
0xa1,0xb6,0x52,0x6a,0x83,0xde,0x2a,0x6a,0xab,0xa5,0xa3,0xf8,0xa9,0xa3,0xa3,0xf5,
1522
0xd4,0xbe,0x9c,0xda,0x57,0x50,0xfb,0x4a,0x6a,0x5f,0x45,0xed,0xab,0xa9,0x3d,0x8b,
1523
0xda,0xd7,0x50,0xfb,0x5a,0x6a,0x5f,0x47,0xed,0xd9,0xd4,0x9e,0x43,0xed,0xeb,0xa9,
1524
0x3d,0x97,0xda,0xf3,0xa8,0x3d,0x9f,0xda,0x0b,0xe8,0xf8,0x6e,0x3a,0x5e,0x46,0xc7,
1525
0xcb,0xe9,0x78,0x05,0x1d,0xdf,0x43,0xc7,0x2b,0xe9,0xf8,0x5e,0x3a,0xbe,0x8f,0x8e,
1526
0x57,0xd1,0xf1,0x6a,0x3a,0x5e,0x43,0xc7,0x6b,0xe9,0x78,0x1d,0x1d,0xaf,0xa7,0xe3,
1527
0x0d,0x74,0xbc,0x91,0xda,0x19,0x6a,0x8f,0xa3,0xf6,0x78,0x6a,0x4f,0xa0,0xf6,0x44,
1528
0x6a,0x4f,0xa2,0xf6,0x64,0x6a,0x4f,0xa1,0xf6,0x25,0xd4,0x9e,0x4a,0xed,0x69,0xd4,
1529
0xbe,0x94,0xda,0x97,0x51,0x7b,0x3a,0xb5,0x67,0x50,0x7b,0x26,0xb5,0x17,0x52,0xfb,
1530
0x46,0x6a,0x2f,0xa6,0xf6,0x2d,0xd4,0xbe,0x8d,0xda,0x4b,0xa8,0xbd,0x94,0xda,0x77,
1531
0x51,0x7b,0x19,0xb5,0x57,0x50,0x7b,0x25,0xb5,0xef,0xa3,0xf6,0x6a,0x6a,0xaf,0xa5,
1532
0x76,0x18,0xdf,0x48,0x27,0xe2,0xe8,0xc4,0x52,0x3a,0x91,0x4e,0x27,0x32,0xe9,0xc4,
1533
0x0a,0x3a,0xb1,0x8a,0x4e,0x64,0xd1,0x89,0xb5,0x74,0x22,0x9b,0x4e,0xac,0xa7,0x13,
1534
0x79,0x74,0xa2,0x80,0x4e,0x14,0xd2,0x89,0x8d,0x74,0xa2,0x98,0x4e,0x6c,0xa1,0x13,
1535
0xdb,0xe8,0x44,0x09,0x9d,0x28,0xa5,0x13,0xbb,0xe8,0x44,0x19,0x9d,0xa8,0xa0,0x13,
1536
0x95,0x74,0x62,0x1f,0x9d,0xa8,0xa6,0x13,0xb5,0x74,0xa2,0x9e,0x4e,0x34,0x52,0x47,
1537
0x26,0x75,0xc4,0x53,0x47,0x22,0x75,0x24,0x53,0xc7,0x12,0xea,0x48,0xa3,0x8e,0x65,
1538
0xd4,0x91,0x41,0x1d,0x2b,0xa8,0x63,0x15,0x75,0x64,0x51,0xc7,0x5a,0xea,0xc8,0xa6,
1539
0x8e,0xf5,0xd4,0x91,0x47,0x1d,0x05,0xd4,0x51,0x48,0x1d,0x1b,0xa9,0xa3,0x98,0x3a,
1540
0xb6,0x50,0xc7,0x36,0xea,0x28,0xa1,0x8e,0x52,0xea,0xd8,0x45,0x1d,0x65,0xd4,0x51,
1541
0x41,0x1d,0x95,0xd4,0xb1,0x8f,0x3a,0xaa,0xa9,0xa3,0x96,0x3a,0xea,0xa9,0xa3,0x91,
1542
0x4e,0xc6,0xd1,0xc9,0x04,0x3a,0x99,0x44,0x27,0x53,0xe8,0x64,0x2a,0x9d,0x5c,0x4a,
1543
0x27,0xd3,0xe9,0x64,0x26,0x9d,0x5c,0x41,0x27,0x57,0xd1,0xc9,0x2c,0x3a,0xb9,0x96,
1544
0x4e,0x66,0xd3,0xc9,0xf5,0x74,0x32,0x8f,0x4e,0x16,0xd0,0xc9,0x42,0x3a,0xb9,0x91,
1545
0x4e,0x16,0xd3,0xc9,0x2d,0x74,0x72,0x1b,0x9d,0x2c,0xa1,0x93,0xa5,0x74,0x72,0x17,
1546
0x75,0x16,0x52,0x67,0x11,0x75,0x6e,0xa4,0xce,0x4d,0xd4,0x59,0x4c,0x9d,0x9b,0xa9,
1547
0x73,0x0b,0x75,0x6e,0xa5,0xce,0x6d,0xd4,0xb9,0x9d,0x3a,0x4b,0xa8,0x73,0x07,0x75,
1548
0x96,0x52,0xe7,0x4e,0xea,0x44,0xe1,0xdd,0xd4,0x59,0x46,0x9d,0xe5,0xd4,0x59,0x41,
1549
0x9d,0x7b,0xa8,0xb3,0x92,0x3a,0xf7,0x52,0xe7,0x3e,0xea,0xac,0xa2,0xce,0x6a,0xea,
1550
0xac,0xa1,0xce,0x5a,0xea,0xac,0xa3,0xce,0x7a,0xea,0x6c,0xa0,0xce,0x46,0x3a,0xc5,
1551
0xd0,0xa9,0x38,0x3a,0x15,0x4f,0xa7,0x12,0xe8,0x54,0x22,0x9d,0x4a,0xa2,0x53,0xc9,
1552
0xd0,0x82,0x8c,0x0f,0xb6,0x9c,0xde,0x43,0xa7,0x97,0x20,0xf8,0x67,0x0a,0x9b,0x4a,
1553
0x43,0x70,0x76,0x53,0xd6,0xd9,0x4d,0x75,0x88,0xd6,0xe8,0xa3,0xb5,0xfa,0x28,0x57,
1554
0x1f,0x15,0xea,0xa3,0x22,0x7d,0x54,0xa2,0x8f,0x76,0x71,0xd1,0xe6,0xc2,0xb3,0x9b,
1555
0xd9,0xa8,0x48,0x1f,0xed,0xe2,0xa2,0xad,0xe5,0x67,0xb7,0xb2,0x51,0x95,0x3e,0x5a,
1556
0xa3,0x8f,0xd6,0xea,0xa3,0x5c,0x7d,0x54,0xc2,0x45,0x3b,0x0a,0xcf,0xee,0x60,0xa3,
1557
0x22,0x2e,0xaa,0x4e,0x3f,0x5b,0x55,0x4e,0x67,0x6b,0xd3,0xcf,0xd6,0x20,0xaa,0x29,
1558
0x39,0x5b,0x93,0xad,0x8f,0x0a,0xe9,0x6c,0xdd,0x52,0x3a,0x5b,0x1f,0x7f,0xb6,0x61,
1559
0x1f,0xa2,0x65,0xfa,0x68,0x85,0x3e,0x5a,0xa3,0x8f,0xd6,0xeb,0x23,0xe6,0x6c,0x43,
1560
0x25,0xa2,0xb2,0xb3,0xf5,0xe5,0xfa,0x08,0x9d,0x6b,0x28,0x3f,0xdb,0xc0,0x70,0x11,
1561
0x32,0xb8,0x54,0x45,0x7f,0x64,0xc8,0xe8,0xcf,0x5f,0xc9,0x35,0xd2,0x90,0xab,0x8f,
1562
0x0a,0xf5,0xd1,0x66,0x7d,0x54,0xa2,0x8f,0x96,0xb3,0x0a,0xce,0xef,0x61,0x40,0x1c,
1563
0x88,0x07,0x09,0x20,0x11,0x24,0x81,0x64,0x90,0x02,0x96,0x80,0x54,0x90,0x06,0x96,
1564
0x82,0x65,0x20,0x1d,0x64,0x80,0x4c,0xb0,0x1c,0xac,0x00,0x2b,0xc1,0x2a,0xb0,0x1a,
1565
0x64,0x81,0x35,0x60,0x2d,0x58,0x07,0xb2,0x01,0xa6,0xba,0x3d,0xeb,0x41,0x2e,0xc8,
1566
0x03,0xf9,0xa0,0x00,0x6c,0x00,0x85,0xa0,0x08,0x6c,0x04,0x9b,0x40,0x31,0xd8,0x02,
1567
0x4a,0xe9,0x5c,0x42,0x2e,0x9d,0xcb,0xdc,0x0d,0xca,0x40,0x39,0xa8,0x00,0x7b,0x40,
1568
0x25,0x5d,0xca,0x5e,0x4a,0xe7,0xca,0xd3,0x50,0x66,0x39,0x58,0x01,0x56,0x82,0x55,
1569
0x60,0x35,0xc8,0x02,0x6b,0xc0,0x5a,0xb0,0x0e,0x64,0x83,0x1c,0xb0,0x1e,0xe4,0x81,
1570
0x7c,0x50,0x00,0x36,0x80,0x42,0x50,0x04,0x36,0x82,0x4d,0xa0,0x18,0x6c,0x06,0x5b,
1571
0xc0,0x56,0xb0,0x0d,0x6c,0x07,0x25,0x60,0x07,0x60,0xed,0xda,0x09,0x76,0x01,0xd8,
1572
0x96,0x00,0xdb,0x12,0x60,0x5b,0x02,0x6c,0x4b,0x80,0x6d,0x09,0x95,0x60,0x2f,0xd8,
1573
0x07,0xaa,0x40,0x35,0xa8,0x01,0xf5,0xa0,0x01,0x34,0x52,0xeb,0x72,0x6a,0x85,0xc5,
1574
0xf0,0x7a,0x2b,0x3a,0x08,0x67,0x9d,0x83,0xb3,0xce,0xc1,0x31,0xe7,0xd0,0xf9,0x56,
1575
0x3c,0x0b,0xb3,0xa8,0xb5,0x80,0x5a,0x0b,0xa9,0x15,0x87,0x50,0x5d,0x89,0x27,0x00,
1576
0x1e,0x95,0x50,0xbc,0x37,0x89,0x8e,0xe0,0x4c,0x19,0xb5,0xee,0xa6,0xd6,0x0a,0x6a,
1577
0xdd,0x43,0xad,0x55,0x74,0x04,0x4f,0x10,0x18,0x07,0xe7,0x1e,0x59,0x4e,0x47,0xd0,
1578
0x70,0x55,0x1c,0x48,0x00,0x49,0x20,0x05,0xa4,0x02,0xb8,0xab,0x2a,0x1d,0x64,0x02,
1579
0xb6,0x0c,0x5c,0x55,0x05,0x37,0x55,0x41,0x73,0x15,0xdc,0x53,0x05,0xd7,0x54,0xc1,
1580
0x82,0x2a,0xb8,0xa5,0x0a,0x2e,0xa9,0x82,0x3b,0xaa,0xe0,0x8a,0x2a,0xb8,0xa1,0x0a,
1581
0x2e,0xa8,0x82,0x86,0x2a,0x58,0x50,0x85,0x6e,0x57,0xa1,0xcb,0x55,0xe8,0x6e,0x15,
1582
0xba,0x5a,0x85,0x6e,0x56,0xa1,0x8b,0x55,0xb5,0x00,0x5d,0xac,0x6a,0xa4,0x73,0xd5,
1583
0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,
1584
0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,
1585
0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,
1586
0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,
1587
0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0xd5,0xd0,0x5f,0x0d,0xfd,0x35,
1588
0xd0,0x5f,0x03,0xfd,0x35,0xd0,0x5f,0x03,0xfd,0x35,0xd0,0x5f,0x03,0xfd,0x35,0xd0,
1589
0x5f,0x03,0xfd,0x35,0xd0,0x5f,0x03,0xfd,0x35,0x59,0x34,0xe6,0x48,0x03,0x35,0x43,
1590
0x25,0x6e,0xce,0x73,0x35,0x50,0x59,0x03,0x95,0x35,0x50,0x59,0x03,0x95,0x35,0x50,
1591
0x59,0x03,0x95,0x35,0x50,0x59,0x03,0x95,0x35,0x50,0x59,0x03,0x95,0x35,0x50,0x59,
1592
0x03,0x95,0x35,0x50,0x59,0x03,0x95,0x35,0x50,0x59,0x0b,0x95,0xb5,0x50,0x59,0x0b,
1593
0x95,0xb5,0x50,0x59,0x0b,0x95,0xb5,0x50,0x59,0x0b,0x95,0xb5,0x50,0x59,0x0b,0x95,
1594
0xb5,0x50,0x59,0x8b,0x2e,0xd7,0xa2,0xcb,0xb5,0xe8,0x72,0x2d,0xba,0x5c,0x8b,0x2e,
1595
0xd7,0x42,0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x2d,0xf4,0xd7,
1596
0x42,0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x2d,0xf4,0xd7,0x42,
1597
0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x2d,0xf4,0xd7,0x42,0x7f,0x1d,0x03,0x60,0x43,0x5d,
1598
0x3c,0x80,0x1d,0x75,0x89,0x00,0xb6,0xd4,0x25,0x03,0xd8,0x53,0x87,0xbb,0xa4,0x0e,
1599
0x36,0xd4,0xe1,0x2e,0xa9,0x83,0x1d,0x75,0xb8,0x4b,0xea,0x60,0x4b,0x1d,0xee,0x80,
1600
0x3a,0xe8,0xae,0xc3,0x1d,0x50,0x07,0xfd,0x75,0xb8,0x03,0xea,0x60,0x43,0x1d,0xee,
1601
0x80,0x3a,0xd8,0x51,0x87,0x11,0x5e,0x07,0xdd,0x75,0x18,0xe1,0x75,0xd0,0x5f,0x87,
1602
0x11,0x5e,0x07,0x1b,0xea,0x30,0xc2,0xeb,0x60,0x47,0x3d,0xf4,0xd6,0x43,0x6f,0x3d,
1603
0xf4,0xd6,0x43,0x6f,0x3d,0xf4,0xd6,0x43,0x6f,0x3d,0x74,0xd5,0x43,0x4f,0x3d,0x74,
1604
0xd4,0xa3,0xbf,0xf5,0xd0,0x53,0x0f,0x3d,0xf5,0xd0,0x53,0x0f,0x3d,0xf5,0xd0,0x53,
1605
0x0f,0x3d,0xf5,0xd0,0x53,0xcf,0xea,0x61,0xb0,0x4e,0x41,0x0f,0xb8,0x30,0x9e,0x0b,
1606
0x13,0xb8,0x30,0x91,0x0b,0x93,0xb8,0x30,0x99,0x0b,0x53,0xb8,0x70,0x03,0x17,0x16,
1607
0x72,0x61,0x11,0x17,0x6e,0xe4,0xc2,0x4d,0x5c,0x58,0xcc,0x85,0x9b,0xb9,0x70,0x0b,
1608
0x1b,0xd6,0x73,0xe5,0xeb,0xb9,0xf2,0xf5,0x5c,0xf9,0x7a,0xae,0x7c,0x3d,0x57,0xbe,
1609
0x9e,0x2b,0x5f,0xcf,0x95,0xaf,0xd7,0x97,0xdf,0x8d,0xf0,0x58,0x19,0x1b,0xec,0x60,
1610
0x8f,0x1b,0xf6,0x72,0x21,0xbc,0xd1,0x50,0xc6,0x9e,0xc5,0x72,0x6a,0x15,0x39,0x1f,
1611
0x8d,0x67,0x97,0x55,0x47,0xd9,0xbe,0xef,0x61,0x8b,0xee,0x63,0x83,0x9d,0x6c,0xc9,
1612
0x46,0xce,0x56,0xcc,0xde,0x38,0xc3,0x96,0xc5,0x1a,0x8d,0x0d,0xd9,0x75,0xdc,0x2a,
1613
0x94,0x3f,0x86,0xcb,0xd1,0xc8,0xc2,0xba,0x69,0x2f,0x32,0x57,0x73,0x05,0x56,0x73,
1614
0x05,0x56,0xb3,0x05,0xa0,0xa9,0x11,0x3e,0x6b,0x64,0x7d,0x86,0xd9,0xa3,0xb1,0x98,
1615
0x5b,0xc0,0x31,0xf4,0x0a,0x8e,0xeb,0xd0,0x76,0x5b,0x2a,0x1b,0x64,0x70,0xba,0x38,
1616
0xdb,0xea,0xab,0xd8,0x33,0x6c,0x75,0x3a,0xcf,0x2c,0x47,0x8c,0x85,0x26,0x53,0x8e,
1617
0x1f,0x43,0xa4,0x4f,0x55,0xe2,0xc7,0x10,0xb1,0xa9,0x91,0x23,0x51,0x30,0x89,0xd8,
1618
0x2d,0xec,0x48,0x1a,0xa9,0xb9,0x59,0x94,0x2d,0xed,0x4f,0x01,0x14,0x48,0x6a,0x0a,
1619
0xa2,0x60,0x0a,0x21,0x2f,0x3a,0xbf,0x64,0x25,0x45,0x90,0x8c,0xe4,0x34,0x67,0x2e,
1620
0x8d,0xf1,0x1b,0x07,0xe6,0xd2,0x3b,0xbb,0xc7,0xd1,0x38,0xbf,0x99,0x60,0x1e,0xd2,
1621
0x13,0x69,0xc6,0x4c,0x9a,0x3b,0x9d,0x5e,0x9b,0x30,0x8d,0x5e,0x9b,0x4e,0xe7,0x93,
1622
0x32,0xe8,0xfd,0xe5,0xf4,0xfe,0x0a,0x7a,0x7f,0x25,0xbd,0xbf,0x8a,0x26,0x8e,0x79,
1623
0x03,0xad,0xac,0xe0,0x76,0x4e,0x41,0x5c,0x18,0xc2,0x85,0x0a,0x7f,0x2e,0x52,0x91,
1624
0x92,0x0b,0xd9,0x74,0x20,0x97,0x0e,0xe4,0xb6,0x57,0x81,0x14,0xc0,0x85,0x6c,0xbe,
1625
0x9a,0x02,0xb9,0x90,0x4d,0x07,0x73,0x67,0x83,0xb9,0x9c,0x60,0x0a,0xe2,0x42,0x36,
1626
0x9f,0x26,0x4f,0xc6,0x0f,0x98,0x4f,0xf3,0x27,0xe3,0x87,0x03,0x87,0x6f,0xd0,0x1b,
1627
0x93,0xf1,0x33,0x99,0xce,0x27,0x27,0x92,0x3f,0xa7,0xea,0xfc,0x92,0x12,0xfc,0x18,
1628
0x22,0x7d,0x6a,0x27,0x7e,0x0c,0x11,0x9b,0xfa,0x94,0x59,0x02,0x52,0x89,0xb5,0x11,
1629
0x3b,0x3f,0x25,0x29,0x60,0x20,0x36,0x7f,0x30,0x07,0x56,0xa0,0x17,0xd0,0x19,0x42,
1630
0x4a,0x7f,0x92,0x29,0xe4,0x24,0x53,0x02,0x15,0x08,0x00,0x81,0x40,0x0d,0x82,0x40,
1631
0x30,0x08,0x01,0x0a,0x7f,0x36,0x60,0x4b,0x2a,0xd8,0xa2,0x0a,0xb6,0xac,0x82,0x2d,
1632
0xac,0x60,0x4b,0x2b,0xd8,0xe2,0x0a,0xb6,0xbc,0x82,0xad,0xa0,0x60,0x6b,0x28,0xd9,
1633
0x1a,0x63,0xc0,0x58,0x30,0x0e,0x8c,0x07,0x13,0xc0,0x44,0x30,0x09,0xbc,0x0a,0x26,
1634
0x83,0x29,0x60,0x2a,0x98,0x06,0xa6,0x83,0x19,0x60,0x26,0x98,0x05,0x66,0x83,0x39,
1635
0x60,0x2e,0x78,0x0d,0xcc,0x03,0xf3,0xc1,0xeb,0xe0,0x0d,0xb0,0x00,0x2c,0x94,0xdf,
1636
0x74,0x03,0xeb,0x89,0xd0,0xd0,0x08,0x8a,0x60,0x7f,0x22,0xe8,0x7c,0x49,0xde,0x7b,
1637
0x55,0x74,0x7e,0xf7,0x6e,0x50,0x06,0x30,0x92,0x76,0x63,0x78,0xed,0xde,0x03,0x30,
1638
0x9c,0x76,0xef,0x05,0xfb,0x00,0x5b,0xa6,0x1a,0xd4,0x80,0x5a,0x50,0x07,0xea,0x41,
1639
0x03,0x68,0xc4,0x6e,0x07,0xcb,0x8d,0x32,0x2c,0x37,0xca,0xb0,0xdc,0x28,0xc3,0x72,
1640
0xa3,0x0c,0xcb,0x8d,0x32,0x2c,0x37,0xca,0xb0,0xdc,0x28,0xc3,0x72,0xa3,0x0c,0xcb,
1641
0x8d,0x32,0x2c,0x37,0xca,0xb0,0xdc,0x28,0xc3,0x72,0xa3,0x0c,0xcb,0x8d,0x32,0x2c,
1642
0x37,0xca,0xb0,0xdc,0x28,0xc3,0x72,0xa3,0x0c,0xcb,0x8d,0x32,0x2c,0x37,0xca,0xb0,
1643
0xdc,0x28,0xc3,0x72,0xa3,0x0c,0x43,0xbd,0x0c,0xcb,0x8d,0x32,0x2c,0x37,0xca,0xb0,
1644
0xdc,0x28,0xc3,0x72,0xa3,0x0c,0xcb,0x8d,0x32,0x76,0x67,0x85,0xe5,0x46,0x19,0x96,
1645
0x1b,0x65,0x58,0x6e,0x94,0x61,0xb9,0x51,0x86,0xe5,0x46,0x19,0x9e,0xa8,0x98,0x53,
1646
0x2b,0xeb,0xa9,0x15,0x56,0x95,0x6d,0x05,0xdb,0xc1,0x0e,0xc0,0xee,0xca,0xf6,0xd2,
1647
0x61,0x3c,0x9b,0x61,0x63,0x39,0x6c,0x2c,0x87,0x7d,0xe5,0xb0,0xad,0x1c,0x76,0x95,
1648
0xc3,0xa6,0x72,0xd8,0x53,0x0e,0x5b,0xca,0x61,0x47,0x39,0x6c,0x28,0x87,0xfe,0x72,
1649
0xe8,0x2e,0x87,0xde,0x72,0xe8,0x2c,0x87,0xbe,0x72,0xe8,0x2a,0x87,0x9e,0x72,0x2c,
1650
0x69,0xca,0xb1,0x9c,0x29,0xc7,0x52,0xa6,0x1c,0x4b,0x99,0xf2,0x6d,0x00,0x43,0xab,
1651
0xbc,0x14,0xec,0x02,0xf0,0x61,0x39,0x34,0x96,0xc3,0x77,0xe5,0xf0,0x5b,0x39,0x7c,
1652
0x56,0x0e,0x7f,0x95,0xc3,0xaa,0x72,0xf8,0xa9,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0xfa,
1653
0x2b,0xa0,0xbf,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0xfa,0x2b,
1654
0xa0,0xbf,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0xfa,0x2b,0xa0,
1655
0xbf,0x02,0xfa,0x2b,0xa0,0xbf,0x02,0x3d,0xab,0xc0,0x58,0xae,0x80,0xae,0xca,0x42,
1656
0xea,0xde,0x95,0x4e,0xbd,0x0d,0x05,0x74,0xa1,0x8a,0x01,0x5b,0xc1,0x5e,0xd0,0x48,
1657
0x17,0xf0,0xfc,0xbd,0x80,0x67,0xe5,0x85,0x9a,0x65,0x60,0x03,0xa8,0xa1,0xae,0xc4,
1658
0x46,0xea,0x4a,0x2a,0x06,0x25,0xd4,0x95,0x1c,0x0f,0xd6,0x00,0xa4,0x53,0x36,0x80,
1659
0x4a,0xea,0x5a,0xc2,0x50,0x57,0xda,0x7a,0xea,0x5a,0x5a,0x4d,0x5d,0xcb,0xb2,0x40,
1660
0x0e,0xa8,0xa2,0xae,0xf4,0x38,0x90,0x0b,0xb6,0x51,0x57,0x06,0xea,0x65,0xec,0xa5,
1661
0xae,0xcc,0x25,0x60,0x23,0x75,0xad,0x5f,0x4b,0x5d,0xb9,0x05,0xd4,0xb5,0x11,0xed,
1662
0x6c,0xc2,0xb9,0x4d,0x69,0x00,0x75,0x37,0x6d,0xa1,0xae,0xe2,0x0a,0xea,0x2a,0x5d,
1663
0x4e,0x5d,0x3b,0xd1,0xee,0x2e,0xb4,0xb3,0x3b,0x13,0x14,0x01,0xa4,0xcb,0x76,0x82,
1664
0x32,0xea,0xda,0x07,0x7d,0xfb,0x60,0xd3,0x3e,0x36,0xdd,0x40,0x5d,0xd5,0xe5,0x00,
1665
0xb6,0xe2,0x99,0xdf,0x55,0xbb,0x07,0x20,0x0f,0x2b,0xec,0x2e,0x3c,0xe0,0xba,0xea,
1666
0xd1,0x16,0x1e,0x38,0x5d,0xf5,0x68,0xb7,0x31,0x81,0xba,0x97,0x2c,0x01,0x7b,0xa9,
1667
0x3b,0x75,0x29,0x75,0xaf,0xde,0x05,0xf6,0x50,0xf7,0x9a,0x14,0xb0,0x16,0x6c,0x02,
1668
0xd5,0xd4,0xbd,0x76,0x03,0x28,0xa6,0xee,0xf5,0xbb,0xa9,0x3b,0x17,0xe5,0x73,0xb7,
1669
0x52,0xf7,0x0e,0xe4,0x95,0x16,0x01,0x9c,0xdf,0x59,0x01,0x1f,0xa2,0xfe,0xae,0xd5,
1670
0x60,0x3d,0x75,0xc3,0xc6,0xee,0xdd,0x48,0xe3,0x3e,0xb8,0x18,0x57,0x42,0x17,0x97,
1671
0x6c,0x07,0x7b,0x41,0x2d,0x68,0xa4,0x8b,0xa9,0x29,0x20,0x1b,0xac,0xa7,0x8b,0x69,
1672
0x3b,0xe8,0x62,0x46,0x22,0x48,0xa5,0x8b,0xab,0x72,0xc1,0x66,0xba,0xb8,0x7a,0x1d,
1673
0x28,0x00,0x5b,0xc1,0x6e,0xba,0xb8,0x66,0x29,0x58,0x49,0x17,0xb3,0xd1,0x46,0x76,
1674
0x3d,0x5d,0xcc,0xd9,0x09,0xd0,0xce,0x7a,0xc4,0x05,0x68,0xa3,0xa0,0x08,0x54,0xd0,
1675
0xc5,0x4d,0x35,0x74,0x71,0x73,0x15,0x68,0xa0,0x8b,0xdb,0xa0,0xbb,0x04,0xf5,0x4a,
1676
0xaa,0xe9,0x22,0x46,0xf1,0xc5,0x0a,0xe4,0xe3,0xe1,0x7c,0x11,0x0f,0xe0,0x8b,0x0d,
1677
0x69,0xa0,0x9e,0x7a,0x98,0x38,0xb0,0x0c,0xac,0x04,0x15,0xd4,0x13,0xd7,0x48,0x3d,
1678
0xf1,0xa9,0xd4,0x93,0xb2,0x11,0x6c,0x07,0xc8,0x4b,0xa9,0xa3,0x9e,0x25,0x28,0xb3,
1679
0x64,0x3d,0x28,0xa0,0x9e,0xd4,0x9d,0xa0,0x1c,0x54,0x51,0x4f,0x76,0x3a,0x28,0xa1,
1680
0x9e,0x42,0x06,0xa0,0x4c,0x21,0xea,0x15,0x37,0x50,0xcf,0xe6,0xa5,0xd4,0xb3,0x05,
1681
0x6d,0x6e,0x45,0x3e,0xee,0xff,0x1e,0xdc,0xc7,0x3d,0xb8,0x1f,0x7b,0xca,0x50,0x07,
1682
0xf7,0x42,0x4f,0xe5,0x26,0xb0,0x9b,0x7a,0xf6,0xa2,0x7d,0x2c,0xa6,0x7a,0x6a,0xd3,
1683
0xa8,0xa7,0x01,0xed,0xe3,0x31,0xda,0x83,0xed,0x47,0x6f,0xfc,0x0a,0xea,0x4d,0x4a,
1684
0xa5,0xde,0x94,0x64,0xb0,0x0c,0xe0,0x38,0x6b,0x1f,0xf5,0xae,0x61,0xa8,0x77,0x5d,
1685
0x2e,0xf5,0xe6,0xec,0x05,0xd5,0xd4,0xbb,0x7e,0x2b,0xf5,0xe6,0xe1,0x5c,0x5e,0x3e,
1686
0x28,0x02,0xdb,0xa8,0xb7,0x60,0x29,0x28,0x05,0x15,0xd4,0xbb,0x21,0x8e,0x7a,0x8b,
1687
0x50,0x66,0xe3,0x7a,0x50,0x40,0xbd,0x9b,0xd7,0x80,0x6c,0xb0,0x83,0x7a,0xb7,0x23,
1688
0xbf,0x64,0x1d,0x40,0xfe,0x8e,0x62,0xb0,0x0b,0x94,0x83,0x3a,0xea,0x2d,0xcd,0xa1,
1689
0xde,0x0a,0xe4,0x61,0x1d,0xd9,0x8b,0x31,0xd4,0x8b,0xc5,0x5f,0x2f,0x16,0x75,0xbd,
1690
0x58,0xc8,0xf5,0x62,0xe1,0xd6,0x8b,0x45,0x5b,0x2f,0x16,0x5a,0xbd,0x58,0x64,0xf5,
1691
0xd6,0x65,0x80,0x55,0x60,0x03,0x40,0x99,0xfa,0x34,0xb0,0x12,0xf7,0x13,0x7b,0x4f,
1692
0xc1,0xd6,0x86,0x0d,0xe4,0x8b,0xe7,0xc4,0x4a,0x8c,0xfc,0x44,0x90,0x44,0xce,0x9f,
1693
0xc6,0x67,0xb3,0x41,0x0e,0x7d,0x1a,0xbf,0xe4,0xd3,0xf8,0x34,0x44,0x15,0x9f,0x26,
1694
0x2c,0xa1,0x73,0x89,0x58,0x32,0x25,0x62,0xc9,0x94,0x8c,0x95,0x7d,0x22,0x96,0x0e,
1695
0xc9,0xd8,0x54,0x24,0x63,0x99,0x97,0x88,0xe5,0x53,0x22,0x96,0x4f,0x89,0x58,0x3e,
1696
0x25,0xe3,0xf1,0x9f,0x8c,0x85,0x46,0x32,0x16,0x10,0xc9,0x58,0x76,0x25,0x63,0xd9,
1697
0x95,0x8c,0x65,0x57,0x22,0x36,0x31,0x89,0x58,0xd2,0x25,0x62,0x49,0x97,0xc8,0xb6,
1698
0x85,0xe5,0x41,0x22,0x96,0x9a,0x89,0xd8,0x08,0x25,0x62,0xb9,0x99,0xb8,0x0c,0x60,
1699
0xc9,0x99,0x98,0x01,0xb0,0xec,0x4c,0xc4,0x1a,0x23,0x11,0x6b,0x8c,0x44,0x2c,0xfb,
1700
0x92,0x50,0x36,0x09,0xcb,0xaf,0x24,0x2c,0xbf,0x92,0xb0,0xfc,0xc2,0xdd,0x7d,0x2e,
1701
0x09,0xcb,0xaf,0x24,0x2c,0xbf,0x92,0xb0,0xd1,0x49,0xc2,0x92,0x33,0x09,0x36,0xe1,
1702
0x8e,0x3f,0x97,0x04,0x9b,0x92,0x60,0x53,0x12,0x36,0x3a,0x49,0x58,0x7e,0x26,0xc1,
1703
0x9e,0x24,0xd8,0x93,0x04,0x7b,0x92,0x60,0x4f,0x12,0xec,0x49,0x62,0xed,0xc1,0x32,
1704
0x32,0x11,0x4b,0xbc,0x14,0xd8,0x93,0x02,0x7b,0x70,0x15,0xcf,0xa5,0x40,0x77,0x0a,
1705
0x96,0x7e,0x29,0x58,0xf6,0xa5,0x60,0x99,0x9b,0x88,0x3d,0x4e,0x0a,0x96,0xb9,0x29,
1706
0x58,0xe6,0x26,0x22,0x4e,0xc4,0xe6,0x2b,0x11,0x4b,0x9b,0x44,0xd8,0x92,0x08,0x5b,
1707
0x12,0xa1,0x3f,0x11,0xba,0x13,0xa1,0x37,0x11,0x7a,0x13,0x59,0x5f,0x40,0x6f,0x22,
1708
0xf4,0x26,0x42,0x5f,0x22,0x96,0x9a,0x49,0xf0,0x59,0x12,0x74,0x24,0xb1,0xed,0xc3,
1709
0x8e,0x14,0xd6,0x0e,0xb4,0x9f,0x84,0xcd,0x5d,0x12,0x74,0xe0,0x79,0x7e,0x2e,0x99,
1710
0xf5,0x1b,0x6c,0x48,0x46,0x7f,0x93,0xd1,0xdf,0x64,0xd8,0x96,0x0c,0x5d,0xc9,0x85,
1711
0x98,0xe5,0x52,0x31,0xfb,0xac,0x47,0x9c,0x06,0x4a,0x01,0xee,0x98,0xd5,0xe5,0x88,
1712
0x31,0xf3,0x61,0xb7,0xd4,0xb5,0x09,0xb3,0x55,0xee,0x6e,0x92,0xe1,0xe2,0xc8,0xd9,
1713
0x30,0x9e,0x0b,0x13,0xb8,0x30,0x89,0x0b,0x93,0xb9,0x30,0x85,0x0b,0x53,0xb9,0x70,
1714
0x29,0x17,0x2e,0xe3,0xc2,0x0c,0x2e,0xcc,0xe4,0xc2,0xe5,0x5c,0xb8,0x82,0x0b,0x57,
1715
0x22,0xbc,0xb4,0x9b,0x6d,0xf3,0xb3,0xf8,0x75,0x6c,0xb8,0x74,0x13,0x1b,0xe6,0xd5,
1716
0xb1,0xe1,0x96,0x25,0x6c,0xb8,0x7b,0x35,0xc2,0xcf,0xe3,0x77,0xb0,0x61,0x56,0x22,
1717
0x1b,0xe6,0xb3,0x2d,0x7c,0xbe,0x7b,0x2b,0x1b,0x56,0xef,0x41,0x78,0x39,0x81,0x6d,
1718
0xe1,0xf2,0x32,0x56,0xd7,0xe5,0x2c,0xb6,0x9d,0xcf,0x37,0xb2,0x2d,0x7c,0xbe,0x6e,
1719
0xd3,0xe7,0x1b,0x12,0xf5,0x89,0xcb,0xeb,0xd9,0x04,0xa6,0x76,0x36,0xac,0x59,0xc6,
1720
0xa5,0x59,0x3b,0xd1,0x6d,0x2e,0x87,0xd5,0xd2,0x95,0x54,0xca,0xe5,0x27,0x70,0xe9,
1721
0x12,0x36,0x5d,0x9d,0xc7,0xa6,0xd3,0xe3,0x10,0x62,0xca,0x43,0x88,0x89,0x8c,0x4d,
1722
0xef,0xde,0xc3,0xe5,0xb0,0x36,0xe0,0xb6,0x64,0xcb,0xe4,0x16,0xb0,0x39,0x6b,0x8b,
1723
0xd9,0x70,0xc3,0x76,0xee,0x2c,0xdb,0xfe,0xc5,0x4d,0x0d,0xec,0xd9,0xe5,0xe9,0x6c,
1724
0x3a,0xb5,0x1a,0x61,0x4f,0x79,0x21,0x9b,0x2e,0xe6,0x5a,0x4e,0x63,0xdb,0xb9,0x50,
1725
0xbb,0x91,0x4d,0xaf,0x60,0x6d,0xee,0x2a,0xdd,0xcc,0x9e,0x5d,0xcf,0xe6,0x5c,0xa8,
1726
0x63,0xf5,0xf6,0x54,0xa4,0x70,0x36,0xac,0xe6,0x6a,0x71,0x16,0xd6,0xb1,0x1a,0x31,
1727
0x35,0x71,0x61,0x85,0x9c,0xba,0xb2,0xf0,0x34,0xa8,0xae,0xa3,0x8b,0x3b,0x33,0x69,
1728
0xd6,0x6b,0x13,0x48,0xa9,0x20,0xa5,0x92,0x94,0x58,0x2f,0x06,0x90,0x12,0x2b,0x45,
1729
0x35,0x29,0x83,0x48,0x19,0x4c,0xca,0x10,0x52,0xf9,0x93,0x4a,0x41,0x2a,0x25,0xa9,
1730
0x54,0xa4,0x0a,0x20,0x55,0x20,0xc1,0xff,0x04,0xef,0x13,0x7c,0x4f,0xf0,0x3c,0xc1,
1731
0xef,0x04,0xaf,0x13,0x7c,0x4e,0xf0,0x38,0xc1,0xdf,0x04,0x6f,0x13,0x7c,0x4d,0xf0,
1732
0x34,0xc1,0xcf,0x04,0x2f,0x23,0xaf,0xea,0x52,0xc5,0x06,0x82,0xab,0x3f,0xcf,0xc3,
1733
0x51,0xce,0x6e,0x3c,0x18,0x57,0xe3,0x81,0xc8,0x0e,0x9f,0x04,0x3c,0x34,0xf3,0x08,
1734
0x7e,0xc0,0x43,0x02,0x13,0xfa,0x26,0x3c,0x78,0x96,0xa7,0x63,0xa2,0xaf,0xc6,0xc4,
1735
0x57,0x48,0xe8,0x3b,0x1e,0x8e,0x98,0x98,0xb7,0xb0,0x13,0x3c,0x26,0xb4,0x38,0x0c,
1736
0xaf,0xc4,0xed,0x98,0x16,0xf0,0x60,0xa9,0xc0,0x84,0xb4,0x01,0x0f,0x5b,0xec,0xc6,
1737
0xba,0x92,0xb3,0xf1,0x60,0xc1,0x83,0x71,0xdf,0x66,0x3c,0x20,0xf1,0xa0,0x5a,0x56,
1738
0x8b,0x07,0x20,0x1e,0x92,0xa5,0x78,0x38,0xac,0xdf,0x88,0x32,0x98,0xb8,0xb1,0x00,
1739
0x80,0x6f,0x30,0x44,0x73,0x49,0xa5,0x26,0x55,0x10,0xa9,0xb0,0xec,0x0d,0xa1,0x00,
1740
0xac,0xce,0x15,0x14,0xa0,0xa4,0x00,0x15,0x05,0x04,0x50,0x00,0xd6,0xc8,0x6a,0x0a,
1741
0x08,0xa2,0x80,0x60,0x0a,0x08,0xa1,0x40,0x2c,0x56,0xd9,0x47,0x98,0x92,0x0d,0x54,
1742
0x6c,0x10,0xc0,0x06,0x81,0x6c,0xa0,0x66,0x83,0x20,0x36,0x08,0x66,0x83,0x10,0x36,
1743
0x50,0xf8,0x73,0x21,0x57,0x47,0xc1,0x55,0x7a,0x75,0x12,0x4d,0x98,0x03,0xe6,0xd3,
1744
0xb4,0xd7,0xc6,0x63,0xee,0x2a,0x02,0x9b,0xc0,0x66,0xb0,0x15,0x6c,0x07,0x25,0xa0,
1745
0x14,0xec,0x02,0x65,0xec,0xfc,0x06,0x2a,0xc1,0x3e,0x50,0x0d,0x6a,0x41,0x3d,0x68,
1746
0xa4,0x4f,0x13,0xe2,0x40,0x22,0x48,0x26,0x76,0x12,0xfc,0x34,0x01,0xf3,0x61,0xc2,
1747
0x52,0xb0,0x0c,0xa4,0x83,0x0c,0x90,0x09,0x56,0x82,0x2c,0xb0,0x0e,0xac,0x07,0xf9,
1748
0xa0,0x00,0x6c,0x00,0x85,0x00,0x76,0x24,0xc0,0x8e,0x04,0xd8,0x91,0x00,0x3b,0x12,
1749
0xb6,0x01,0xd8,0x92,0x00,0x5b,0x12,0x76,0x00,0xd8,0x93,0x00,0x7b,0x12,0x76,0x03,
1750
0xd8,0x94,0x80,0x9b,0xbc,0x76,0x53,0xd7,0xca,0x65,0x6c,0x17,0x3e,0x4d,0x58,0xf1,
1751
0x69,0x42,0x1d,0xa7,0x9f,0x3d,0x28,0x81,0xa6,0x4f,0xe3,0x0b,0xf5,0x07,0x98,0x9b,
1752
0x73,0xf4,0xbd,0x2c,0xe2,0xca,0xb0,0x7d,0xdb,0x04,0x13,0xd9,0x33,0xf1,0xbb,0xf5,
1753
0x07,0x15,0x5c,0x37,0xe2,0x37,0x7f,0x1a,0xbf,0x0d,0x07,0xac,0x23,0xd0,0x4f,0x74,
1754
0x9f,0xab,0x90,0xca,0x1d,0x23,0x15,0x8f,0x76,0xeb,0x58,0x0f,0x71,0x55,0xab,0xf5,
1755
0xa9,0x3a,0xae,0x07,0x38,0xc5,0xb6,0xc3,0xf9,0x0e,0xa6,0x7f,0x9a,0x90,0xa0,0x37,
1756
0x06,0x07,0xa5,0xc8,0xd6,0xd7,0xdb,0xc1,0x1d,0x54,0xe8,0x53,0x15,0x9c,0x07,0xe2,
1757
0x77,0xe2,0x80,0x8b,0x58,0x83,0xd8,0x42,0x28,0x51,0x3c,0x50,0x63,0x27,0xd7,0x17,
1758
0x66,0xe0,0x4c,0xa9,0x21,0x82,0xe1,0x9c,0x96,0x0d,0xfd,0xc7,0x09,0x85,0xfa,0xfe,
1759
0xeb,0xbb,0xa7,0xcf,0xda,0x35,0x60,0xc5,0xcd,0xc2,0x86,0x14,0x57,0x92,0x35,0x64,
1760
0x17,0xab,0x20,0xbe,0x8e,0x33,0xbe,0x54,0x7f,0x5c,0xca,0xb5,0x94,0xce,0x5e,0x79,
1761
0xae,0xd3,0xd5,0xfa,0xe7,0x5b,0x09,0x77,0x65,0xd9,0x14,0xce,0xe6,0xb1,0xe3,0x81,
1762
0xad,0xc4,0x35,0xc0,0x1d,0x70,0x3e,0x1c,0x70,0xc7,0x3e,0xae,0x0b,0x06,0x07,0xd7,
1763
0x0e,0x38,0x58,0x9f,0x62,0x47,0x09,0xd3,0xdf,0x76,0x42,0x0a,0x37,0xac,0x12,0x52,
1764
0xf5,0x57,0x5a,0x6f,0x57,0x42,0x9a,0x7e,0xdc,0x64,0xf4,0x77,0x21,0x21,0x93,0x33,
1765
0x91,0x1d,0x67,0xdc,0x95,0xbe,0xa5,0x25,0xfd,0x95,0x67,0xcf,0x2c,0xe7,0x52,0x3b,
1766
0xf4,0x0d,0xad,0x66,0xaf,0x37,0x2e,0xa2,0xc1,0x27,0xec,0xf1,0xae,0x81,0x14,0xab,
1767
0x62,0x95,0xfe,0x88,0x1d,0x28,0xfd,0x57,0x2c,0x55,0x7f,0xbc,0xb1,0x7f,0x2c,0x25,
1768
0xac,0x61,0xb3,0xd1,0x99,0xf8,0x2d,0xfd,0x85,0x13,0xf4,0x03,0x24,0x61,0x1d,0xdb,
1769
0x5c,0x7c,0x63,0xff,0x88,0x62,0x87,0x58,0x3d,0x17,0xb1,0xd7,0x71,0x25,0x57,0x80,
1770
0x75,0x59,0xa2,0x3e,0x4f,0x3f,0x5c,0xd8,0x14,0x4c,0xaf,0x42,0x2a,0x9b,0x4b,0xb1,
1771
0xb7,0x4f,0x5e,0xff,0x00,0x64,0xf5,0xe5,0x72,0x95,0xd8,0xd4,0x7a,0xbd,0x9a,0x3c,
1772
0xee,0x54,0xaa,0x3e,0xc3,0xa0,0x4a,0x9f,0x62,0xcf,0xe6,0xf7,0x5f,0x82,0xd2,0xfe,
1773
0x03,0xae,0x40,0x3e,0xd7,0x99,0x4c,0x7d,0xaa,0x84,0xbb,0x8b,0xd9,0x54,0x05,0x77,
1774
0x59,0xb6,0xe8,0xab,0x16,0xf4,0x5f,0x6b,0xfd,0x01,0x77,0xa7,0x15,0x70,0x17,0x6d,
1775
0xf9,0x80,0xa2,0x42,0x6e,0x6c,0x72,0xd1,0xc0,0x85,0xb9,0x75,0x9c,0x25,0x6c,0xea,
1776
0xbf,0x3f,0x0c,0x29,0x36,0x6f,0xb3,0xfe,0xa6,0x23,0xae,0xad,0x84,0x81,0xa2,0xdb,
1777
0xf5,0x37,0x74,0x09,0xeb,0x7e,0x76,0x34,0xb3,0xa9,0x3a,0xce,0xc1,0xdc,0xfd,0xad,
1778
0x9f,0x06,0xf4,0xb7,0x05,0xd6,0x54,0xe5,0xfa,0x16,0xfa,0x47,0xb0,0xff,0x45,0xb8,
1779
0x4f,0xc1,0x06,0x4a,0x36,0x50,0xb1,0x41,0x00,0x1b,0x04,0xb2,0x81,0x9a,0x0d,0x82,
1780
0xd8,0x20,0x98,0x0d,0x42,0xb8,0xc2,0xfa,0x2a,0x5c,0x1d,0x05,0x57,0x49,0xc1,0xd5,
1781
0x52,0x70,0xd5,0x14,0x5c,0x3d,0x05,0x57,0x51,0xc1,0xd5,0x54,0x70,0x55,0x15,0x5c,
1782
0x5d,0x25,0x57,0x57,0xa9,0xd7,0xc7,0xd5,0x55,0x72,0x75,0x95,0x5c,0xdd,0x57,0x67,
1783
0x8d,0xa1,0xf1,0x63,0x68,0xcc,0x3c,0x1a,0x3b,0x66,0x0e,0xcd,0x9c,0x4f,0xb3,0xc6,
1784
0xd1,0xf8,0xe9,0xf8,0x51,0x02,0x15,0x4d,0x9e,0x87,0xe7,0x59,0x45,0xf7,0x92,0xe5,
1785
0xd4,0xbd,0xae,0x94,0x9d,0x9d,0xb0,0x07,0x62,0x9f,0x04,0xdd,0xeb,0x32,0xba,0xb1,
1786
0x13,0xc4,0x83,0xa5,0xab,0x2e,0xf3,0x42,0x5d,0x0e,0xfb,0x64,0x41,0x4b,0x33,0xc6,
1787
0xd0,0xb1,0xba,0x31,0x34,0x7d,0x0c,0x4d,0xc5,0xcf,0x58,0x9a,0x3e,0x96,0x26,0x8d,
1788
0xa5,0x71,0x63,0xa6,0xd1,0x54,0x36,0x98,0x35,0x91,0x66,0x4c,0x44,0x09,0x96,0x49,
1789
0x34,0x7d,0x12,0x4d,0x9d,0x44,0xaf,0x2e,0xa4,0xa9,0x60,0x3a,0x98,0x04,0x5e,0x03,
1790
0xc7,0xea,0xa6,0xd1,0xf4,0x69,0x34,0x1e,0xb5,0xa6,0xd1,0xc4,0xe9,0x34,0x63,0x3a,
1791
0xb2,0xa6,0xd3,0xf4,0xe9,0x34,0x6e,0x3a,0x4d,0x65,0x13,0x4a,0xa4,0x94,0x84,0x9f,
1792
0xa9,0x6c,0x04,0x3b,0xc7,0x01,0xfc,0x4c,0x65,0xa3,0xf3,0x4b,0xb2,0xe6,0xea,0x43,
1793
0x9c,0x87,0x51,0xd3,0xc1,0x24,0x30,0x67,0xcc,0x78,0x16,0xee,0xb4,0x21,0x56,0xd2,
1794
0xac,0xb9,0x34,0x63,0x2e,0x9a,0x47,0x8d,0xb9,0x34,0x6b,0x3e,0xcd,0x98,0x8f,0x83,
1795
0xf9,0x34,0x7d,0x3e,0x4d,0x85,0x2f,0x5e,0xa7,0x19,0xaf,0xe3,0xf8,0x75,0x9a,0xfe,
1796
0x3a,0x4d,0xc5,0x4f,0x5b,0x2a,0x4d,0x07,0x63,0x67,0xd3,0xb8,0x71,0x34,0x6e,0x3c,
1797
0x8d,0x43,0x23,0xe8,0xc3,0x78,0x74,0x73,0x01,0xbd,0x3a,0x06,0xde,0xa4,0xc9,0x33,
1798
0x68,0xea,0x54,0x9a,0xfa,0x1a,0x4d,0x9b,0x4e,0xd3,0x66,0xd0,0xb4,0x99,0x93,0x68,
1799
0xda,0x1b,0x34,0x7d,0x32,0xba,0x34,0x13,0x1e,0x78,0x95,0x66,0xcd,0x9a,0x4e,0xb3,
1800
0xe6,0xd0,0x5c,0xfc,0xcc,0xa7,0xd7,0xc7,0xd2,0x7c,0xb4,0x31,0x9d,0xc6,0x70,0xa1,
1801
0x82,0xdd,0xd6,0x29,0xd9,0x40,0xc5,0x06,0x01,0x6c,0x10,0xc8,0x06,0x6a,0x36,0x08,
1802
0x62,0x83,0x60,0x36,0x08,0x61,0x03,0x3c,0x0b,0xd9,0x90,0xab,0xa3,0xe0,0x2a,0x29,
1803
0xb8,0x5a,0x0a,0xae,0x9a,0x82,0xab,0xa7,0xe0,0x2a,0x2a,0xb8,0x9a,0x0a,0xae,0xaa,
1804
0x82,0xab,0xab,0xe4,0xea,0x2a,0xf5,0xfa,0xb8,0xba,0x4a,0xae,0xae,0x92,0xab,0xab,
1805
0xe4,0xea,0x2a,0xb9,0xba,0x4a,0xae,0xae,0x92,0xab,0xab,0xe4,0xea,0xaa,0xb8,0xba,
1806
0x2a,0xae,0xee,0x24,0x5c,0xd5,0x4b,0xd9,0x71,0x20,0x01,0x24,0x81,0x14,0x90,0x0a,
1807
0xd2,0x41,0x26,0x58,0x01,0x56,0x81,0x2c,0xb0,0x16,0x64,0x83,0xf5,0x20,0x0f,0x14,
1808
0x80,0x42,0xb0,0x11,0x14,0x83,0x2d,0x60,0x1b,0x28,0x01,0xa5,0x74,0x29,0x07,0xed,
1809
0xe6,0xa0,0xdd,0x1c,0xb4,0x9b,0x83,0x76,0x73,0xd0,0x6e,0xce,0x52,0x80,0xb6,0x73,
1810
0xd0,0x76,0x0e,0xda,0xce,0x41,0xdb,0x39,0x68,0x3b,0x07,0x6d,0xe7,0xa0,0xed,0x1c,
1811
0xb4,0x9d,0x8b,0xf6,0x72,0xd1,0x5e,0x2e,0xda,0xcb,0x45,0x7b,0xb9,0x68,0x2f,0x17,
1812
0xed,0xe5,0xee,0x02,0x15,0xa0,0x12,0xec,0x03,0xd5,0xa0,0x16,0xd4,0x83,0x46,0xba,
1813
0x94,0x07,0x7d,0x79,0xd0,0x97,0x07,0x7d,0x79,0xd0,0x97,0x07,0x7d,0x79,0xd0,0x97,
1814
0x07,0x7d,0x79,0xd0,0x87,0xad,0xdd,0xa5,0x3c,0xe8,0xcb,0x83,0xbe,0x3c,0xe8,0xcb,
1815
0x83,0xbe,0x3c,0xe8,0xcb,0x43,0x5f,0xf2,0xd0,0x97,0x3c,0xf4,0x25,0x0f,0xba,0xf3,
1816
0xa0,0x3b,0x0f,0xba,0xb1,0xfd,0xbb,0x94,0x07,0xdd,0x79,0xd0,0x9d,0x07,0xdd,0x79,
1817
0x35,0xa0,0x8e,0xce,0x55,0x42,0x6f,0x1e,0xf4,0xe5,0x43,0x5f,0x3e,0xf4,0xe5,0x43,
1818
0x5f,0x3e,0xf4,0xe5,0x2f,0x03,0xd0,0x91,0x0f,0x1d,0xf9,0x68,0x3f,0x1f,0xed,0xe7,
1819
0xa3,0xfd,0x7c,0xb4,0x9f,0x8f,0xf6,0xf3,0xd1,0x7e,0x3e,0xda,0xcf,0x47,0xfb,0xf9,
1820
0x68,0x3f,0x7f,0x1b,0xb5,0xee,0xa0,0x23,0xf9,0x74,0x04,0x95,0x4b,0xd9,0x4a,0xe8,
1821
0x58,0x3e,0x3a,0x96,0x0f,0x05,0xf9,0xe8,0x58,0x3e,0x3a,0x96,0x0f,0x45,0x05,0x50,
1822
0x54,0xc0,0x2a,0xc2,0x4e,0x63,0x6f,0x06,0xd2,0x4b,0x40,0x1a,0xb5,0x6e,0x42,0x84,
1823
0xbe,0x15,0xa0,0x6f,0x05,0xd0,0x5b,0x80,0x26,0x0a,0xd0,0xb7,0x02,0xe8,0x2e,0x80,
1824
0x6e,0x6c,0xe5,0x0f,0xae,0xa7,0xd6,0x7d,0xd4,0x5a,0x87,0x83,0xbd,0x74,0x69,0x07,
1825
0xda,0x2e,0x5d,0x49,0x47,0x50,0xa7,0x14,0x7e,0x29,0xc5,0x26,0x27,0x03,0x1b,0xa4,
1826
0x0c,0x6c,0xd8,0x32,0xb0,0x49,0xca,0xc0,0x26,0x29,0x03,0x1b,0xb6,0x0c,0x6c,0xd8,
1827
0x32,0xb0,0x61,0xcb,0xc0,0x86,0x29,0x03,0x1b,0xb6,0x0c,0x6c,0x9a,0x32,0xb0,0x61,
1828
0xcb,0xc0,0xc6,0x29,0x03,0x1b,0xa7,0x0c,0x6c,0x9c,0x32,0xb0,0x71,0xca,0xc0,0xc6,
1829
0x29,0x03,0x1b,0xb6,0x0c,0x6c,0x94,0x32,0xb0,0x51,0xca,0xc0,0x86,0x2d,0x03,0x1b,
1830
0xb6,0x0c,0x6c,0xd8,0x32,0xb0,0x99,0xca,0xd8,0x07,0xaa,0x40,0x35,0xa8,0x01,0xb5,
1831
0x00,0xfe,0xcb,0xa8,0x07,0x0d,0xa0,0x91,0xce,0x65,0x62,0xc3,0x95,0x89,0x4d,0x6a,
1832
0x26,0x36,0xa8,0x99,0xd8,0x98,0x66,0x62,0x83,0x95,0x89,0x0d,0x56,0x26,0x36,0x9f,
1833
0x99,0xd8,0x88,0x65,0x62,0xa3,0x95,0x89,0x8d,0x67,0x26,0x36,0x9e,0x99,0xd8,0x78,
1834
0x66,0xc2,0xe6,0x4c,0x6c,0x3c,0x33,0xb1,0xf9,0xcb,0xc4,0xc6,0x33,0x13,0x1b,0xcf,
1835
0x4c,0x6c,0xc4,0x32,0xb1,0x11,0xcb,0xc4,0x66,0x30,0x13,0x2e,0xca,0xc4,0x46,0x31,
1836
0x73,0x0d,0xc0,0xc6,0x2d,0x13,0x1b,0xb7,0x4c,0x6c,0xdc,0x32,0xb1,0xa1,0xcd,0x5c,
1837
0x0f,0xd8,0x6f,0xfa,0xb0,0x39,0xcc,0xc4,0x86,0x2d,0x13,0x1b,0xc5,0x4c,0xf4,0x3f,
1838
0x13,0xfd,0xcf,0x44,0xff,0x33,0xd1,0xff,0x4c,0xf4,0x3f,0x13,0xfd,0xcf,0x44,0xff,
1839
0x33,0xd1,0xff,0x4c,0xf4,0x3f,0x13,0xfd,0xcf,0x44,0xff,0x33,0xd1,0xff,0x4c,0xf4,
1840
0x3f,0x13,0xfd,0xcf,0x44,0xff,0x33,0x77,0x51,0x4f,0xd9,0x12,0xea,0x5e,0xbf,0x07,
1841
0xab,0x67,0xc4,0xd8,0xc6,0x5f,0xa8,0x2a,0xc7,0x0a,0xbb,0x98,0xba,0x8a,0xb1,0xea,
1842
0x5e,0x83,0x15,0x75,0x31,0xf2,0x53,0xd8,0xd7,0x2c,0xdb,0xe8,0x62,0x43,0x12,0xf5,
1843
0xac,0x6b,0xa4,0x9e,0xfc,0x1a,0xea,0xd9,0x58,0x45,0xbd,0xf1,0x99,0xd4,0xbd,0x35,
1844
0x9e,0xba,0xf7,0xac,0xa7,0x8b,0x09,0xd9,0x74,0x11,0x36,0xf5,0x2c,0xaf,0xa7,0x5e,
1845
0x6c,0x8e,0x7b,0xb7,0x94,0x61,0x17,0x10,0x8f,0x15,0x79,0x25,0x75,0xef,0x48,0xa4,
1846
0x8b,0xec,0xeb,0x92,0x75,0xa5,0xd4,0x5b,0x95,0x4f,0x5d,0x95,0x98,0xcd,0x1b,0x4b,
1847
0xa8,0x67,0x6d,0x3a,0xf5,0x14,0x6f,0xa2,0xee,0xa5,0xec,0x2b,0x96,0x75,0xd4,0xb3,
1848
0xa1,0x80,0xba,0x6a,0xd3,0xb0,0x53,0x58,0x4b,0xdd,0x95,0xdb,0xe9,0xe2,0xd2,0x3a,
1849
0xea,0xc5,0xba,0xe5,0x42,0x43,0x32,0x76,0x00,0xfb,0xa8,0x6b,0x69,0x3e,0x75,0xaf,
1850
0x4a,0xa4,0xee,0x92,0x55,0x68,0x6f,0x39,0x56,0xfe,0x5b,0xd0,0x66,0x32,0xf5,0x64,
1851
0xe7,0x52,0xcf,0xbe,0x5d,0xd4,0x9b,0x5b,0x4e,0xbd,0xa5,0x88,0xf7,0xd5,0xd0,0xc5,
1852
0xa2,0x65,0xd8,0x5d,0x34,0xd2,0xc5,0xbd,0x1b,0xa8,0x07,0xfe,0xef,0x5d,0x96,0x48,
1853
0x3d,0x25,0x6b,0xa8,0x6b,0x23,0x74,0xd4,0xc1,0x9e,0x32,0xe4,0xc7,0x35,0x60,0x27,
1854
0x52,0x44,0x17,0x37,0xa6,0xa1,0xff,0xf1,0xd4,0xbb,0x1e,0x3a,0x36,0xae,0xa3,0xae,
1855
0xb2,0x22,0xf4,0x6b,0x15,0x75,0xef,0xcb,0xa1,0xee,0xba,0x4c,0xba,0xb8,0x67,0x17,
1856
0x5d,0xac,0xc2,0xee,0x24,0x7b,0x29,0x6c,0x58,0x49,0x3d,0xf1,0x88,0x53,0x72,0x01,
1857
0x74,0x6c,0xcd,0x85,0x8e,0x06,0xe8,0x28,0xc3,0xf9,0x4a,0xea,0xd9,0xc9,0xa0,0x3f,
1858
0x99,0xd0,0xd5,0x00,0x5f,0x56,0x53,0xd7,0xae,0x2d,0xd4,0xcd,0xac,0xa4,0x8b,0x19,
1859
0x29,0x74,0x31,0x6b,0x37,0x76,0x2e,0x6b,0xa1,0xaf,0x16,0x7d,0x6a,0xa4,0xae,0x86,
1860
0x6d,0x28,0x93,0x8e,0x9d,0xce,0x32,0xea,0xce,0xaa,0x82,0x9e,0x22,0xf8,0x3e,0x81,
1861
0xba,0x0a,0xf3,0xe9,0x62,0x2e,0x76,0x34,0x2b,0xe0,0x97,0xed,0xd8,0x39,0xed,0xac,
1862
0xa1,0xee,0x72,0x5c,0x87,0xa5,0xd0,0xb3,0xb4,0x98,0xba,0x31,0xe6,0x2f,0x66,0x15,
1863
0xc3,0xbf,0x3b,0xb1,0xcb,0xc2,0x8e,0x29,0x25,0x95,0xba,0x8b,0xe2,0xe8,0x62,0x05,
1864
0xfc,0x91,0x8a,0x6b,0x5a,0xb2,0x92,0x7a,0x53,0xb0,0x11,0x5c,0x5a,0x49,0x5d,0x2b,
1865
0x70,0x0d,0x6a,0x77,0x50,0xf7,0xda,0x24,0xf8,0x1c,0xfd,0xdd,0x84,0x6b,0xb3,0x06,
1866
0xd7,0x61,0x1b,0xe2,0x9a,0xb5,0xd4,0x5b,0x9b,0x81,0xeb,0x9f,0x8c,0xdd,0xd5,0x3e,
1867
0xea,0xa9,0x87,0x7e,0xec,0xed,0xba,0x93,0x71,0x7d,0x96,0xa0,0x1f,0x2b,0xd9,0xfe,
1868
0x6f,0xa4,0x8b,0x49,0xd8,0xb9,0xad,0x04,0x5b,0xd2,0xe8,0xe2,0xff,0x63,0xd7,0x6d,
1869
0x80,0x9a,0xba,0xd6,0xfd,0xff,0x85,0x82,0x12,0x0b,0x05,0x94,0x28,0x58,0xb0,0xa0,
1870
0x44,0xc5,0x12,0x48,0x4e,0x93,0x96,0x60,0x68,0x45,0x41,0x09,0x24,0xbc,0xa3,0xa0,
1871
0xa0,0xd2,0x02,0x26,0x90,0x28,0x81,0x04,0x08,0x24,0x90,0x57,0x48,0x42,0xc2,0x4b,
1872
0x05,0x0a,0x15,0x5a,0x50,0x50,0xb0,0x60,0x45,0x88,0x82,0x05,0x2b,0x77,0x64,0xae,
1873
0xf4,0x27,0x33,0x32,0x23,0xb7,0xd2,0xca,0x8c,0x9c,0x12,0x24,0x77,0x64,0x06,0x7e,
1874
0x23,0xff,0x29,0xff,0x91,0x99,0xff,0xb3,0x42,0xdb,0x7f,0xcf,0xb9,0xe7,0xdc,0xf3,
1875
0xd6,0xd3,0x7b,0x7b,0x4a,0x3e,0xac,0xef,0x5e,0x7b,0xad,0xbd,0xd7,0x5e,0xeb,0x79,
1876
0x9e,0xb5,0xf6,0xde,0x24,0xb7,0x20,0x56,0x14,0x70,0x8d,0xc1,0xcb,0x68,0xee,0xfc,
1877
0x35,0x64,0x91,0x5f,0x42,0x16,0xa3,0x1e,0x99,0xb5,0xf0,0x36,0xa6,0x87,0x37,0xb4,
1878
0x0f,0x86,0x20,0x16,0xb4,0x10,0x1f,0xf8,0xba,0x3a,0x64,0xfe,0x02,0xfc,0x6f,0x84,
1879
0x1b,0xf5,0xb5,0x6b,0xe8,0xd9,0x75,0xb8,0x3e,0xc4,0x03,0xbc,0x67,0x20,0xf3,0x05,
1880
0xb0,0xcd,0x4d,0x18,0x97,0x1c,0xec,0x07,0x73,0xef,0x59,0x0d,0x8e,0xaf,0x8f,0xa0,
1881
0xed,0x32,0x64,0xd1,0xf6,0x81,0x2f,0x6e,0x22,0x4b,0xb3,0x16,0xde,0x00,0x1b,0xc0,
1882
0x56,0x15,0xe8,0xd9,0x65,0xb8,0x56,0x19,0x94,0x7f,0xd4,0x8f,0x66,0xe1,0xfd,0x66,
1883
0xe6,0x36,0xc4,0x84,0xea,0x23,0xb0,0x2f,0xd8,0xe0,0xfa,0x17,0x68,0xb6,0x1e,0xe2,
1884
0xaf,0xbc,0x12,0xe2,0x54,0x09,0xfd,0x82,0xb8,0x51,0x0c,0xa2,0xd9,0x8f,0xe0,0xfc,
1885
0x06,0xa8,0xd7,0x83,0x7d,0x9a,0xa1,0x0f,0x9f,0xf4,0x42,0x5c,0x29,0xd0,0xec,0x6d,
1886
0xb8,0x66,0x35,0x8c,0xa7,0x0e,0xce,0x69,0xfd,0x14,0xec,0x5e,0x8d,0x2c,0x60,0xf3,
1887
0x59,0x2d,0x5c,0xa3,0xb1,0x1f,0x99,0xe5,0x9f,0x22,0x73,0x1f,0xbc,0x71,0xde,0xba,
1888
0x0a,0xe3,0x84,0xb7,0x51,0xb8,0xfe,0xac,0x06,0xe2,0xae,0x05,0xec,0xf5,0x11,0x5c,
1889
0x57,0x0b,0x36,0xaf,0x06,0xfb,0xf6,0x80,0x2f,0x1a,0x20,0x4e,0x9a,0xc1,0x86,0x17,
1890
0x3b,0xc0,0x8f,0xed,0xd0,0x6e,0x19,0x7a,0xf6,0x21,0xc4,0xd4,0x10,0xbc,0xe1,0x5e,
1891
0x82,0x38,0xb8,0xd4,0x0a,0x63,0x01,0xbb,0x1a,0xa0,0x8f,0xf8,0xdf,0xc5,0xd5,0xcd,
1892
0xd0,0x4f,0x88,0xdd,0x0f,0x20,0xde,0x3f,0xbc,0x0d,0xed,0x81,0xfd,0x7a,0xa0,0xdd,
1893
0xdb,0x9f,0xa0,0x59,0x58,0x73,0x67,0x6f,0x55,0xc0,0x5c,0xe8,0x40,0xcf,0xba,0xc0,
1894
0xc7,0x37,0x20,0x6e,0x2a,0xe4,0xe8,0x99,0xb2,0x11,0xcd,0x75,0x83,0x1d,0x3e,0x97,
1895
0xa3,0x39,0xc3,0x4d,0xb8,0x3e,0xb4,0xa3,0x85,0xb9,0x79,0xfb,0x32,0xc4,0x04,0xcc,
1896
0x85,0x5e,0x88,0xeb,0x6b,0xe0,0xdf,0x3e,0x18,0xc3,0x47,0xe0,0x1f,0xfc,0x6f,0x37,
1897
0xb8,0xff,0x99,0x3f,0x3f,0x0f,0xf1,0x21,0x47,0xe6,0x0f,0x21,0xb5,0x82,0x2f,0x1b,
1898
0xfb,0x20,0x56,0x20,0xb6,0x0c,0x30,0xb7,0x2e,0x80,0x2f,0xdb,0x06,0x61,0x8e,0xc0,
1899
0x7e,0x3b,0xf4,0xfb,0x72,0x15,0xd8,0xbb,0x1e,0xae,0x09,0x31,0xd6,0x00,0x31,0xfe,
1900
0x29,0xcc,0x6f,0x39,0x24,0x15,0xcc,0xe7,0x4b,0x30,0xa7,0x2e,0x81,0x4d,0xdb,0xe0,
1901
0x8d,0xfc,0x26,0xf8,0x00,0xde,0xb4,0x2c,0x1f,0xdd,0x02,0xbf,0x80,0x6d,0x55,0x57,
1902
0xe0,0x1a,0x70,0x2d,0x98,0xc3,0xe6,0x0a,0xf0,0xab,0x11,0xaf,0x1b,0xf0,0x56,0x0f,
1903
0xf3,0xd2,0xdc,0xd8,0x01,0xd7,0x85,0x6b,0x83,0x6d,0xcc,0x3d,0x30,0xcf,0x95,0xb5,
1904
0x60,0x47,0xb0,0x53,0x19,0xd8,0xab,0xfc,0x06,0xc4,0x3c,0xac,0x1f,0x60,0xab,0x59,
1905
0xb8,0x8f,0xce,0x5e,0x84,0xfe,0x9b,0x6e,0xa1,0xd9,0x7e,0x1c,0x73,0x60,0x3f,0x0d,
1906
0xc4,0x8b,0x16,0x7c,0x53,0x0d,0xf9,0x8b,0x35,0xd0,0x47,0xf0,0x17,0xac,0x45,0xcf,
1907
0xda,0xc1,0x76,0xed,0xd0,0xcf,0xcb,0x46,0x48,0xe0,0xef,0x4e,0xb0,0xcf,0x55,0x88,
1908
0xfd,0xcf,0x60,0xdb,0x0f,0xc7,0x0c,0x40,0x7e,0xe8,0x06,0x9a,0x93,0xc3,0x5a,0x55,
1909
0xde,0x0d,0xf3,0x01,0xfc,0x50,0xf3,0x21,0x9a,0x6b,0xab,0x46,0x73,0x97,0xeb,0xd1,
1910
0x5c,0x17,0xcc,0xab,0x2e,0x28,0xeb,0x3d,0x8f,0xe6,0xfa,0x20,0x4e,0xef,0x40,0x9c,
1911
0x5d,0x00,0x1f,0x7c,0xf2,0x05,0xc4,0x1a,0xc4,0x88,0xc2,0x84,0x16,0xda,0x2a,0xae,
1912
0xa1,0x39,0x2d,0x18,0xbc,0xff,0x32,0x2c,0x3c,0x30,0x89,0xa0,0xd3,0x33,0x77,0x60,
1913
0x20,0x1a,0x0d,0xec,0xc3,0xb6,0x02,0x8c,0x5f,0x01,0x4e,0xa8,0xab,0x83,0xc1,0x36,
1914
0x82,0x81,0xc1,0xc1,0x17,0x7b,0x61,0xb1,0x54,0x43,0xaa,0x45,0xe6,0x4e,0xd8,0xef,
1915
0x82,0x41,0x7f,0xfe,0x01,0x24,0xa8,0x1f,0x82,0x80,0xb9,0xd3,0x0d,0x81,0xdb,0x00,
1916
0x06,0x80,0xc1,0xab,0x61,0x32,0x6b,0x5a,0x20,0xe0,0x60,0xb2,0xc1,0x0d,0x63,0xb6,
1917
0xba,0x09,0xcd,0xd6,0x7c,0x00,0x06,0xa9,0x87,0xc5,0xef,0x02,0x04,0x14,0x6c,0x3f,
1918
0x87,0xed,0xe7,0x10,0xf8,0x72,0x70,0x10,0xdc,0x6c,0x9f,0x69,0x4d,0xe8,0x99,0x1e,
1919
0x16,0xa2,0x9a,0x1e,0xf4,0xac,0x16,0x82,0xac,0xf6,0x73,0xf4,0xac,0x01,0x82,0xa9,
1920
0xe1,0x13,0x70,0x26,0x2c,0xc0,0xb0,0x88,0x3f,0x6b,0x06,0xa7,0x36,0x83,0x21,0x2e,
1921
0xc1,0xc2,0x74,0x15,0x8e,0xeb,0x81,0x63,0x4c,0x50,0x37,0x08,0x4e,0x35,0x82,0x53,
1922
0xf1,0x82,0xdf,0x0c,0x83,0x6f,0x07,0x23,0x5c,0x86,0x85,0xf3,0x2a,0x2c,0xe6,0x9f,
1923
0x42,0xc0,0x7d,0x0a,0x86,0xba,0x06,0x8b,0xe0,0x20,0x38,0x5c,0x01,0x8b,0x68,0x59,
1924
0x23,0xb2,0xe8,0xc0,0x30,0x8d,0xe0,0x74,0xb8,0x09,0x5b,0x5a,0x2a,0x90,0xa5,0xeb,
1925
0x03,0xb4,0x70,0xb1,0x55,0x8f,0x45,0x8d,0x16,0x2e,0xc1,0x3d,0xea,0xdb,0x6b,0xcd,
1926
0x68,0x46,0x0e,0x66,0x92,0x0f,0xa0,0x85,0x76,0x9d,0x0e,0xa4,0xb7,0x1a,0x2d,0x5c,
1927
0x81,0xb0,0xb3,0x0c,0xa9,0x90,0xe5,0x4e,0x25,0xca,0xcc,0x44,0x99,0x3c,0x94,0x09,
1928
0x4f,0xd1,0x78,0x03,0xdb,0x3c,0x11,0x9a,0xe8,0xc3,0x3f,0x65,0xea,0xc3,0x3f,0x81,
1929
0xea,0xc3,0xbf,0x7a,0xba,0xb3,0xba,0xdb,0x8d,0xbe,0x6a,0xfc,0x8f,0x3e,0xf4,0xd5,
1930
0x8d,0xff,0xb8,0x85,0xbe,0xba,0x88,0xbe,0xaa,0x45,0x5f,0x5d,0x40,0x5f,0x35,0xa1,
1931
0xaf,0x9a,0xd1,0x57,0x1d,0xe8,0xab,0xab,0xe8,0xab,0xce,0xaf,0x14,0x58,0x94,0x20,
1932
0xff,0x31,0x68,0xcd,0xc3,0x06,0xf6,0xaa,0xf1,0x19,0xd5,0xff,0xd1,0x8f,0x65,0x10,
1933
0x7d,0x55,0x83,0xe5,0x03,0x2c,0xe7,0xb1,0xd4,0x62,0xa9,0xc3,0x52,0x8f,0xa5,0x01,
1934
0x4b,0x23,0x96,0x8f,0xb0,0x5c,0xc0,0xd2,0x84,0xe5,0x63,0x2c,0x2d,0x58,0x5a,0xb1,
1935
0x5c,0xc2,0xd2,0x86,0xe5,0x32,0x96,0x2b,0x58,0x3a,0xb0,0x74,0x62,0xb9,0xba,0xda,
1936
0xe8,0x00,0xbe,0xda,0x17,0xb8,0x95,0x2f,0xf0,0xc1,0x20,0xd5,0xd0,0xe3,0xc9,0x1e,
1937
0x34,0xf9,0x39,0x9a,0xbc,0x83,0xbe,0x96,0xa3,0xc9,0xdb,0x68,0xf2,0x0b,0x34,0x39,
1938
0x80,0xbe,0x6e,0x43,0x5f,0x5f,0x46,0x5f,0xab,0xd1,0xd7,0x2a,0xf4,0x75,0x19,0xfa,
1939
0xba,0x1c,0x7d,0x6d,0x44,0x5f,0x1b,0xd0,0xd7,0x95,0xe8,0x6b,0x2d,0xfa,0xba,0x01,
1940
0x7d,0x5d,0x83,0xbe,0xee,0x44,0x5f,0x7f,0x86,0xbe,0xee,0x45,0x5f,0xf7,0xa0,0xaf,
1941
0x6f,0xa3,0xaf,0x3f,0x47,0xdf,0xc8,0xd1,0x37,0x0a,0xf4,0xf5,0x1d,0xf4,0xcd,0x07,
1942
0xe8,0x9b,0xf3,0xe8,0xeb,0x6e,0xf4,0x4d,0x39,0xfa,0xa6,0x0c,0x7d,0xa3,0x45,0xdf,
1943
0x54,0xa0,0x6f,0x34,0xe8,0x1b,0x1d,0xfa,0xa6,0x1a,0x4d,0xea,0xd0,0xe3,0xcb,0x8f,
1944
0xaf,0x80,0x7c,0x53,0x07,0x32,0xa9,0xc5,0xb9,0x72,0x2c,0x65,0x58,0xac,0xbb,0xd5,
1945
0xb8,0x02,0x8e,0x36,0xe0,0x43,0xbb,0xb0,0x74,0xe3,0x12,0x0d,0x16,0x3d,0x7a,0xdc,
1946
0x81,0xcb,0x3a,0x70,0x59,0xc7,0xe3,0x6b,0x20,0xb8,0xa2,0x03,0xb7,0xdb,0x81,0x6b,
1947
0xaf,0xe2,0xda,0xab,0xb8,0xf6,0x2a,0xae,0xbd,0x8a,0x6b,0xaf,0xe2,0xda,0xab,0xb8,
1948
0xf6,0x53,0x5c,0xfb,0x29,0x2e,0xfb,0x14,0x97,0x7d,0x8a,0xcb,0xba,0xf0,0xc1,0x5d,
1949
0xb8,0xac,0x1b,0xd7,0x76,0xe3,0xdc,0x35,0x9c,0xbb,0x86,0x2b,0xae,0xe1,0xdd,0x5e,
1950
0xbc,0xdb,0x8b,0x77,0x7b,0x71,0xa3,0xbd,0xb8,0xcc,0x84,0x77,0x4d,0x38,0x77,0x13,
1951
0xd7,0xde,0xc4,0xbb,0x37,0x71,0xed,0x4d,0x5c,0x76,0x0b,0xef,0xde,0xc2,0xb9,0x7e,
1952
0x2c,0x03,0xf8,0x90,0x01,0x9c,0xbb,0x8d,0x73,0xb7,0x21,0x37,0xa9,0x80,0x1c,0x48,
1953
0x37,0x96,0x6b,0x20,0xd6,0x32,0xe8,0x15,0x88,0x1e,0x4d,0x2a,0x71,0x85,0x12,0x97,
1954
0x29,0x71,0x99,0x12,0x97,0xa9,0xc0,0x70,0x20,0x5d,0x58,0xba,0xb1,0xc0,0x69,0xaa,
1955
0x49,0x35,0x16,0x0d,0x16,0x1d,0x16,0x38,0x4e,0x8d,0x0f,0x51,0xe3,0x43,0xd4,0xf8,
1956
0x10,0x35,0xae,0x55,0xe3,0x5a,0x35,0xae,0xd5,0xe0,0x5a,0x0d,0xae,0xd5,0xe0,0x5a,
1957
0x0d,0xae,0xd5,0xe0,0x5a,0x0d,0xae,0x2d,0xc3,0xb5,0x65,0xb8,0xb6,0x0c,0xd7,0x96,
1958
0xe1,0xda,0x32,0x5c,0x5b,0x86,0x6b,0xcb,0x71,0x6d,0x39,0x2e,0x2b,0xc7,0x65,0xe5,
1959
0xb8,0x4c,0x8f,0xcb,0xf4,0xf8,0x0c,0x3d,0x3e,0x43,0x8f,0x6b,0xf5,0xb8,0x56,0x8f,
1960
0xad,0x7b,0x7d,0xf2,0x3a,0x7a,0xdc,0x03,0x32,0xa9,0x03,0xf1,0x9a,0x34,0x4c,0xd6,
1961
0x80,0x1a,0xad,0x5a,0x69,0xd5,0x2a,0xab,0x56,0x5b,0xb5,0x06,0x1f,0x7d,0xf9,0x71,
1962
0x0f,0x96,0x1b,0xd8,0xdf,0x65,0xd8,0xcb,0x3d,0x58,0x6e,0x60,0x07,0x97,0x61,0xb7,
1963
0xf6,0x60,0xb9,0x81,0x3d,0x5a,0x86,0x3d,0xda,0x83,0xe5,0x06,0x76,0x66,0x19,0x1e,
1964
0xd2,0x15,0xdc,0xf3,0x1e,0x2c,0x37,0x70,0xa7,0xcb,0x70,0xb7,0x7a,0xb0,0xdc,0xc0,
1965
0x3d,0xc2,0x51,0x86,0x9d,0x74,0x79,0xb2,0x1c,0xb7,0x57,0x8e,0x5b,0x29,0xc7,0xce,
1966
0xb4,0xda,0xa9,0x1c,0x9f,0x51,0x8e,0xc7,0x75,0x1d,0x1f,0x5c,0x8e,0x1b,0x2d,0xc7,
1967
0xfe,0x06,0xe9,0xc3,0xde,0xeb,0xc3,0xb5,0x72,0x6b,0xc7,0x61,0x53,0xb5,0xba,0xc1,
1968
0x5d,0x07,0x5f,0xeb,0xb0,0xe8,0xb1,0x9b,0x75,0x58,0xf4,0xd8,0xcd,0x3a,0x2c,0x7a,
1969
0xdc,0x82,0x0e,0x8b,0x1e,0xb7,0xa0,0xc3,0xa2,0xc7,0x81,0xa6,0xc3,0x82,0x23,0x10,
1970
0xe7,0xba,0x70,0xee,0x1a,0xce,0x5d,0xc3,0x39,0x13,0xce,0x99,0x70,0xee,0x26,0xce,
1971
0xdd,0xb4,0x9e,0x8b,0x63,0xa7,0x0f,0x47,0x56,0x1f,0x1e,0x43,0x1f,0x1e,0x7a,0x2f,
1972
0x16,0x13,0x96,0x9b,0x58,0xae,0x4c,0x56,0x58,0xe7,0x80,0x35,0xec,0x57,0x03,0xfa,
1973
0xea,0x6a,0x48,0x5f,0x5d,0x0d,0xe5,0xab,0x56,0xff,0x5b,0x37,0xdd,0xab,0x9b,0x6b,
1974
0xd6,0xe8,0xc7,0x7b,0xdd,0xd6,0x10,0xb0,0x6e,0x74,0xd6,0x78,0x5f,0x0d,0xfb,0xae,
1975
0xd5,0xc0,0xef,0x5a,0x1d,0x83,0xf5,0xc8,0xde,0xd5,0x56,0x7a,0xad,0xd1,0x83,0xa7,
1976
0xc2,0xf7,0x93,0xc1,0x6a,0xa3,0xd5,0xeb,0xf5,0xad,0x8e,0xa8,0x6f,0xf5,0x0a,0x7d,
1977
0xab,0x75,0x37,0x57,0x47,0x7d,0x73,0xb5,0x2f,0xb7,0x56,0x1b,0xbb,0xb5,0x5a,0x77,
1978
0x6b,0xf5,0xea,0x03,0xab,0x9d,0x1f,0x58,0x2d,0x1c,0x58,0xed,0xcb,0xed,0xd5,0xbd,
1979
0xdb,0xab,0x87,0xdc,0x5e,0x8d,0x57,0x85,0xb5,0x15,0x3c,0x49,0xbe,0x9f,0x2b,0xd6,
1980
0x38,0xb7,0x5e,0xdd,0xba,0xd1,0xaf,0x6e,0x74,0xd6,0x09,0xb1,0x3a,0x25,0xae,0xad,
1981
0x4e,0x85,0xef,0xa3,0xbf,0xfb,0xfb,0x99,0x60,0x9d,0x01,0xab,0x27,0x68,0xac,0xa3,
1982
0xc5,0x9b,0xd5,0xc2,0x6b,0xab,0x87,0x5c,0x5b,0xdd,0xeb,0xc2,0x61,0x52,0xbe,0x3a,
1983
0x83,0xca,0x57,0xaf,0x57,0xb6,0x7a,0x7a,0xd9,0xea,0x85,0xca,0x56,0xcf,0x2b,0xb3,
1984
0x1a,0x0b,0x4f,0x1e,0xeb,0x94,0x5a,0xed,0xae,0x7e,0x75,0x0c,0x1d,0xab,0xfe,0xbd,
1985
0xba,0x6a,0x9e,0xab,0xab,0x66,0xbd,0xfa,0x43,0xe1,0xb5,0xd5,0xa5,0xca,0x3a,0xcc,
1986
0xab,0xab,0x63,0xef,0x5a,0xdd,0xeb,0x5a,0x35,0x5d,0xd7,0x0f,0xce,0xb1,0x1e,0x69,
1987
0x5a,0x0d,0xa0,0xbe,0xd5,0xcd,0xcd,0x1f,0x06,0xdd,0x65,0xdd,0xac,0x5e,0x5d,0xbf,
1988
0x5a,0xa8,0x5f,0x2d,0xd4,0xaf,0x16,0x6a,0x56,0x37,0xca,0x1f,0xe6,0x7c,0xf7,0x6a,
1989
0xe0,0x5a,0xf7,0x54,0x3f,0x2e,0x04,0xdf,0xaf,0x11,0x3f,0xb4,0xa9,0x59,0xad,0xd3,
1990
0xac,0xf6,0x45,0x6f,0x5d,0x2f,0xbf,0xb7,0x19,0xde,0x28,0x56,0xfb,0xd9,0xb1,0x5a,
1991
0xd7,0xbb,0x7a,0x5e,0xd9,0xea,0x30,0x4d,0x93,0x6a,0xb8,0x2f,0xc0,0xf5,0xf0,0x06,
1992
0x82,0x54,0x6d,0x9d,0x6c,0x90,0x51,0x59,0xa7,0xf7,0xaa,0x13,0x1e,0x7f,0x66,0x3d,
1993
0x70,0x75,0x9d,0xec,0x81,0xe0,0xd2,0xc2,0xda,0x06,0x7b,0x6a,0xeb,0x54,0x9c,0xd4,
1994
0x42,0x89,0xda,0x1a,0x6e,0xd6,0xc5,0x6c,0x75,0xe3,0xf5,0x43,0x63,0x5e,0x3f,0x1c,
1995
0xe8,0xf5,0xff,0x1f,0xd8,0x35,0xa9,0xf6,0xc2,0x62,0x3d,0x06,0x2e,0xd7,0xf3,0x8d,
1996
0x01,0x67,0x91,0x1f,0xfa,0x56,0xae,0x40,0x41,0xc8,0x1b,0xbd,0x0b,0xb9,0x7a,0x48,
1997
0x1f,0xa2,0xdf,0xcb,0xf1,0x8f,0xac,0xce,0xa3,0x53,0xa8,0x18,0xc9,0xa0,0xa4,0x16,
1998
0x12,0x3c,0x38,0xc8,0xab,0x21,0xd5,0x40,0xd2,0x43,0xaa,0x80,0x64,0x80,0x64,0x84,
1999
0x54,0x09,0xa9,0x0a,0x9d,0x40,0xa9,0x68,0x17,0xda,0x8d,0xf6,0x21,0x32,0x62,0xa2,
2000
0x77,0x50,0x0a,0xf2,0x41,0x24,0x74,0x00,0x56,0xb2,0x0a,0xbc,0x32,0x54,0xe0,0x05,
2001
0x0f,0x2f,0x77,0x78,0xb1,0xb3,0x2e,0x1c,0x78,0xbd,0xb3,0x2e,0x1d,0x78,0xc9,0xb3,
2002
0x2e,0x1e,0x78,0xd5,0xc3,0x19,0xbc,0xfc,0x7d,0x80,0x33,0x60,0xa0,0x56,0xf4,0xf8,
2003
0x22,0x7a,0x7c,0x09,0x3d,0x6e,0x43,0x8f,0xdb,0x61,0xb1,0x42,0xf8,0x8e,0xd9,0x81,
2004
0x1e,0x77,0x42,0x50,0xc0,0x9a,0x84,0xac,0xf7,0x29,0x84,0xe7,0x15,0x98,0x0c,0xaf,
2005
0xaf,0x08,0x2f,0x80,0xbd,0x10,0x08,0x60,0x16,0x88,0x03,0x98,0x4c,0x70,0xe3,0x01,
2006
0xdb,0xc1,0x5c,0x01,0xc7,0x80,0xe1,0xc1,0x75,0x08,0xdf,0x29,0x70,0x70,0x22,0xab,
2007
0x35,0xd1,0xaa,0x5b,0x2f,0x62,0xb9,0x84,0xa5,0x1d,0xcb,0x15,0xb4,0x13,0xed,0x41,
2008
0x01,0xe8,0x24,0x92,0xa2,0x12,0xf4,0xfb,0xcb,0x1a,0x48,0xf8,0xfb,0x1d,0xfc,0xbd,
2009
0x0f,0xfe,0x5a,0xe5,0x12,0xa4,0x76,0x48,0x57,0x20,0xe1,0x7f,0xeb,0xc2,0xbe,0x0a,
2010
0xf6,0xe1,0xd9,0xfa,0x5b,0x95,0x0a,0xad,0xfe,0x83,0x17,0x7f,0xbd,0xd0,0x88,0xf0,
2011
0xd7,0xe4,0xff,0x76,0x11,0xfd,0xdb,0x25,0xf4,0x6f,0x5d,0xe8,0xdf,0x2e,0xa3,0x7f,
2012
0x6b,0x47,0xbf,0x87,0x53,0x7e,0x5f,0xab,0x44,0xbf,0x87,0xd7,0xb6,0xdf,0x97,0xd5,
2013
0x40,0xfa,0x00,0xd2,0x79,0xf4,0xfb,0xfa,0x16,0xf4,0xfb,0x0f,0x2b,0xd0,0x42,0x75,
2014
0x75,0x07,0x96,0x4e,0x2c,0x57,0xb1,0x7c,0x8a,0xa5,0x0b,0x4b,0x37,0x96,0x6b,0x58,
2015
0x3e,0xc3,0x72,0x1d,0x4b,0x0f,0x96,0x1b,0x58,0x7a,0xb1,0xf4,0x61,0x31,0x61,0xb9,
2016
0x89,0xe5,0x16,0x96,0x7e,0x2c,0x03,0x58,0x6e,0x63,0xf9,0x1c,0xcb,0x20,0x96,0x21,
2017
0x2c,0x77,0xb0,0x7c,0x01,0x52,0x23,0xc7,0xa2,0xc0,0xa2,0xc4,0xa2,0xc2,0xa2,0xc6,
2018
0xa2,0xc1,0x52,0x86,0xa5,0x1c,0x8b,0x16,0x8b,0x0e,0x8b,0x1e,0x0b,0xee,0x73,0x8d,
2019
0x01,0x8b,0x11,0x4b,0x25,0x96,0x2a,0x90,0xf3,0x0d,0x58,0x1a,0xb1,0x7c,0x84,0xe5,
2020
0x02,0x96,0x26,0x2c,0xcd,0x58,0x3e,0xc6,0xf2,0x09,0x96,0x16,0x2c,0xad,0x58,0x2e,
2021
0x62,0xb9,0x84,0xa5,0x0d,0x4b,0x3b,0x96,0xcb,0x58,0xae,0x60,0xc1,0x76,0x39,0x8f,
2022
0xed,0x72,0x1e,0xdb,0xe5,0x3c,0xb6,0xcb,0x79,0x6c,0x97,0xf3,0xd8,0x2e,0xe7,0xb1,
2023
0x5d,0xce,0x63,0xbb,0x9c,0xc7,0x76,0x39,0x8f,0xed,0x72,0x1e,0xdb,0xe5,0x3c,0xb6,
2024
0xcb,0x79,0x6c,0x97,0xf3,0xd8,0x2e,0xe7,0xb1,0x5d,0xce,0x63,0xbb,0x9c,0xc7,0x76,
2025
0x39,0x8f,0xed,0x72,0x1e,0xdb,0xe5,0x3c,0xb6,0x4b,0xfd,0x87,0x58,0x70,0xc7,0xeb,
2026
0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,
2027
0xc7,0xeb,0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,0xc7,0xeb,0x71,0x9f,0xeb,0x71,0x9f,
2028
0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,
2029
0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,
2030
0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x9f,0xeb,0x71,0x77,0xeb,0x71,0x77,0xeb,0x71,0x77,
2031
0xeb,0x71,0x77,0xeb,0x71,0x77,0xeb,0x71,0x77,0xeb,0x71,0x77,0xeb,0xad,0x3d,0x1d,
2032
0x44,0xff,0xa7,0x1a,0xfd,0x9f,0x1a,0xf4,0x65,0x23,0xfa,0xf2,0x12,0xfa,0xcf,0xee,
2033
0xcb,0xe8,0xcb,0x76,0xf4,0x65,0x1b,0x9a,0xbe,0x59,0x83,0x46,0x1b,0xd0,0xe8,0xc7,
2034
0xe8,0xcb,0x4e,0x34,0x7a,0x11,0x7d,0x79,0x01,0x7d,0xd9,0x84,0x46,0xaf,0xa0,0x2f,
2035
0xd5,0xe8,0xcb,0xab,0xe8,0x4b,0xe8,0x42,0xf3,0xa0,0x1a,0xfd,0xe7,0xc7,0x95,0x68,
2036
0xf4,0x1a,0xce,0x6b,0xd0,0x97,0x95,0x78,0x5b,0x86,0x46,0x6f,0xa2,0xd1,0xdb,0x38,
2037
0xab,0x45,0xa3,0x77,0xd0,0x97,0x1d,0xe8,0xcb,0xcb,0xd0,0x30,0x9c,0x79,0x05,0xfd,
2038
0xbe,0xa7,0x07,0x7d,0x59,0x85,0xbe,0x6c,0x45,0x5f,0x42,0x93,0x0d,0xe8,0xdf,0xe5,
2039
0xe8,0xdf,0x15,0xe8,0xdf,0x95,0xf8,0x68,0x3d,0x16,0xb8,0x5c,0x3d,0xfa,0xf2,0x43,
2040
0x9c,0xc5,0x01,0xd1,0x8b,0x83,0xa9,0x17,0x07,0x53,0x2f,0x0e,0xa6,0x5e,0x1c,0x4c,
2041
0xbd,0x38,0x98,0x7a,0x71,0x30,0xf5,0xe2,0x60,0xea,0xc5,0xc1,0xd4,0x8b,0x83,0xa9,
2042
0x17,0x07,0x53,0x2f,0x0e,0xa6,0x5e,0xeb,0xb9,0x38,0x98,0x7a,0x71,0x30,0xf5,0xe2,
2043
0x60,0xea,0xc5,0xc1,0x84,0x5f,0x55,0xaa,0x7b,0x6b,0xb0,0x7c,0x80,0xe5,0x3c,0x96,
2044
0x5a,0x2c,0x75,0x58,0xea,0xb1,0x60,0xdf,0xf5,0x62,0xdf,0xf5,0x62,0xdf,0xf5,0x62,
2045
0xdf,0xf5,0x62,0xdf,0xf5,0x62,0xdf,0xf5,0x62,0xdf,0xf5,0x62,0xdf,0xf5,0x62,0xdf,
2046
0xf5,0x62,0xdf,0xf5,0x62,0xdf,0xf5,0xe2,0xa0,0xeb,0xc5,0x0e,0xec,0xc5,0x0e,0xec,
2047
0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,
2048
0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x0e,
2049
0xec,0xc5,0x0e,0xec,0xc5,0x0e,0xec,0xc5,0x41,0x67,0xc2,0xbb,0x26,0xbc,0x6b,0xb2,
2050
0xee,0x62,0xa7,0x9a,0xb0,0x53,0x4d,0xd8,0xa9,0x26,0xec,0x54,0x13,0x76,0xaa,0x09,
2051
0x3b,0xd5,0x84,0x9d,0x6a,0xc2,0x31,0x68,0xc2,0x9e,0x35,0xe1,0xb9,0x69,0xc2,0x73,
2052
0xd3,0x84,0xe7,0xa6,0x09,0xcf,0xcd,0x9b,0xd8,0x9c,0x37,0xb1,0x39,0x6f,0x62,0x73,
2053
0xde,0xc4,0xe6,0xbc,0x89,0xcd,0x79,0x13,0xcc,0x59,0x73,0x49,0x8e,0x45,0x81,0x45,
2054
0x89,0x45,0x85,0x45,0x8d,0xc5,0x5a,0x5b,0x86,0xa5,0x1c,0x8b,0x16,0x8b,0x0e,0x8b,
2055
0x1e,0x4b,0x05,0x16,0x03,0x16,0x23,0x96,0x4a,0x2c,0x55,0x58,0xaa,0xb1,0xd4,0x60,
2056
0xf9,0x00,0xcb,0x79,0x2c,0xb5,0x58,0xea,0xb0,0xd4,0x63,0xf9,0x10,0x4b,0x03,0x96,
2057
0x46,0x2c,0x1f,0x61,0xb9,0x80,0xa5,0x09,0x4b,0x33,0x96,0x8f,0xb1,0x80,0xb1,0xeb,
2058
0x07,0x5a,0xb0,0xb4,0x62,0xb9,0x88,0xe5,0x12,0x96,0x36,0x2c,0xed,0x58,0x2e,0x63,
2059
0xb9,0x82,0xa5,0x03,0x4b,0x27,0x96,0xab,0x58,0x3e,0xc5,0xd2,0x85,0xa5,0x1b,0xcb,
2060
0x35,0x2c,0x9f,0x61,0xb9,0x8e,0xa5,0x07,0xcb,0x0d,0x2c,0xbd,0x58,0xfa,0xb0,0x98,
2061
0xb0,0xdc,0xc4,0x72,0x0b,0x4b,0x3f,0x96,0x01,0x2c,0xb7,0xb1,0x7c,0x8e,0x65,0x10,
2062
0xcb,0x10,0x96,0x3b,0x58,0xc0,0xba,0xf5,0xb7,0x71,0xc5,0x6d,0x5c,0x71,0x1b,0x57,
2063
0xdc,0xc6,0x15,0xb7,0x71,0xc5,0xe7,0x72,0x2c,0x0a,0x2c,0x4a,0x2c,0x2a,0x2c,0x6a,
2064
0x2c,0x1a,0x2c,0x65,0x58,0xca,0xb1,0x68,0xb1,0xe8,0xb0,0xe8,0xb1,0x54,0x60,0x31,
2065
0x60,0x31,0x62,0xa9,0xc4,0x52,0x85,0xa5,0x1a,0x4b,0x0d,0x96,0x0f,0xb0,0x9c,0x47,
2066
0xdf,0x2a,0xce,0x7f,0xab,0xe8,0xb0,0x7e,0xf5,0x8b,0x7f,0x73,0x80,0xbf,0x30,0xc4,
2067
0xb7,0x9a,0x0e,0xfc,0x9d,0xe4,0x42,0xb3,0xe6,0x43,0x48,0xed,0x38,0xd3,0xf0,0x07,
2068
0x19,0x48,0xd7,0x7e,0xba,0xf3,0xd9,0x4f,0x77,0xae,0xff,0x74,0xa7,0xe7,0xa7,0x3b,
2069
0x60,0xac,0xe6,0xb2,0x81,0xef,0x5b,0x2a,0xbb,0xfd,0x43,0x66,0xe0,0x27,0x4d,0xae,
2070
0x96,0xfe,0xb0,0x33,0xf0,0x93,0xf6,0x7f,0xac,0xf9,0x0c,0xdd,0xeb,0x41,0xf7,0x6f,
2071
0xa1,0xbc,0x3c,0xf4,0x7b,0x6d,0x39,0x24,0xbc,0x08,0x0c,0x29,0xb0,0xe8,0xb0,0x54,
2072
0x60,0xc1,0x2b,0xca,0xd0,0x07,0x58,0x3a,0xb1,0xe0,0x45,0x67,0xa8,0x1b,0x0b,0x6e,
2073
0x6a,0xa8,0x17,0x8b,0x09,0xcb,0x2d,0x2c,0x03,0x58,0x3e,0xc7,0x32,0x84,0xe5,0x0b,
2074
0x2c,0x78,0x25,0x19,0x6a,0xc0,0xd2,0x88,0xa6,0xfb,0xac,0x99,0x6a,0xbc,0xb8,0xdc,
2075
0x41,0xd3,0x78,0x46,0x34,0x0f,0x7e,0x81,0xee,0xf7,0xa3,0xfb,0xf8,0xd4,0x41,0xeb,
2076
0x92,0x06,0xcb,0x60,0x19,0x2c,0x7e,0xf8,0xc8,0xc1,0x2e,0x2c,0x4d,0xe8,0xcb,0xf3,
2077
0x50,0xf0,0x11,0x9c,0xae,0x81,0x24,0x87,0x54,0x8e,0x46,0xbf,0x40,0x5f,0xc2,0x82,
2078
0x77,0x0d,0x7d,0xf9,0x19,0xba,0xdf,0x8a,0xee,0xf7,0xa1,0xfb,0x26,0x74,0xff,0x26,
2079
0x1c,0x87,0xbf,0x5d,0xa9,0x83,0x6d,0x39,0x24,0x3d,0xfa,0xb2,0x05,0x37,0x01,0xe3,
2080
0xf9,0xb8,0xed,0x22,0x96,0x4b,0x58,0xda,0xb0,0xb4,0x63,0xb9,0x8c,0xe5,0x0a,0x96,
2081
0x0e,0x2c,0x9d,0x58,0xae,0x62,0xf9,0x14,0x4b,0x17,0x96,0x6e,0x2c,0xd7,0xb0,0x7c,
2082
0x86,0xe5,0x3a,0x96,0x1e,0x2c,0x37,0xb0,0xf4,0x62,0xe9,0xc3,0x62,0xc2,0x72,0x13,
2083
0xcb,0x2d,0x2c,0xfd,0x58,0x06,0xb0,0xdc,0xc6,0xf2,0x39,0x96,0x41,0x2c,0x43,0x58,
2084
0xee,0x60,0x81,0xe1,0x7f,0xdc,0x2e,0xc7,0xa2,0xc0,0xa2,0xc4,0x02,0x4f,0x36,0xd7,
2085
0xd0,0xd7,0xad,0x68,0xf2,0x33,0x44,0xf1,0x43,0x54,0x3f,0xf4,0x3b,0x3f,0xf4,0xa6,
2086
0x1f,0xa2,0xf9,0x21,0xba,0x1f,0x7a,0xcb,0x0f,0xbd,0xed,0x87,0x02,0xfd,0x10,0x03,
2087
0x3f,0xf5,0xd5,0xe6,0xe1,0xa7,0xba,0x82,0x22,0xc4,0xcd,0x47,0x79,0xe9,0x28,0x27,
2088
0x27,0x1f,0x15,0xbc,0x8f,0x04,0xf0,0x97,0x8e,0x04,0xb9,0x28,0x3d,0x0b,0x82,0xf2,
2089
0xf3,0x6f,0x15,0x15,0xd6,0xdf,0x3b,0x28,0xf1,0xef,0x57,0x3f,0x44,0xe6,0x2a,0xfc,
2090
0x83,0x96,0x72,0x64,0x6e,0xfb,0x08,0xcd,0x5d,0xb9,0x84,0x66,0x6e,0xb7,0xa1,0xd9,
2091
0x86,0x16,0xf4,0x4c,0xdd,0x8a,0xcc,0x3a,0x23,0x32,0xdf,0x31,0x20,0x73,0x99,0x11,
2092
0xcd,0xc2,0x8d,0xcc,0xac,0x6d,0x46,0xcf,0x4c,0x4a,0x34,0x77,0xa3,0x13,0x99,0x2f,
2093
0xc1,0x3e,0x3c,0x7b,0xcc,0x0e,0xd6,0xa2,0x59,0x7d,0x1d,0x9a,0x35,0xd6,0x21,0x8b,
2094
0x42,0x8f,0x66,0x0d,0xe5,0x68,0x56,0x77,0x1e,0x3d,0xbb,0xac,0x40,0xcf,0x3a,0xf1,
2095
0x3f,0x5a,0xb5,0x68,0xf6,0xb6,0x1c,0x3d,0xab,0x85,0xeb,0xe9,0x6e,0x20,0x33,0xdc,
2096
0xf7,0x2c,0x1a,0xfc,0x8c,0x59,0x3b,0xdb,0xd4,0xb5,0xfa,0x14,0x5a,0x3b,0xd3,0xaf,
2097
0xfb,0x21,0x77,0xdb,0xf0,0x7d,0xce,0x7c,0xed,0x87,0xb2,0x67,0xca,0x81,0xef,0x73,
2098
0xd0,0xf0,0x0f,0x65,0x17,0x3e,0xfc,0xe1,0xb8,0x8a,0xe6,0x1f,0x6a,0xeb,0xac,0x65,
2099
0xe6,0x3b,0x78,0x54,0x9f,0xa1,0x99,0xfe,0x21,0x48,0xfd,0x68,0x66,0x00,0x8c,0xd9,
2100
0xa2,0xbe,0x88,0x66,0x86,0x5a,0xd0,0xcc,0x9d,0xcf,0x91,0x59,0xae,0x44,0x66,0x05,
2101
0x74,0x0d,0x9e,0xe3,0xcc,0xf8,0xf7,0x04,0x1f,0xc0,0x7a,0xd6,0xd2,0x00,0x05,0x1a,
2102
0xfc,0x73,0xa9,0x36,0x48,0xe0,0xb0,0x96,0xda,0x26,0xa8,0x19,0x80,0x1d,0x88,0x86,
2103
0x96,0xba,0x0a,0xb0,0x02,0xb4,0x5b,0xd6,0x86,0x66,0x3e,0xc7,0x16,0x81,0x48,0xe8,
2104
0x2c,0xff,0x04,0x4c,0x02,0xcf,0x85,0xe7,0xf1,0x16,0xda,0xd5,0x95,0x41,0xba,0x85,
2105
0xbe,0xad,0xc5,0x3f,0x2f,0xd6,0x40,0x82,0x7d,0xa3,0x0e,0xd2,0x47,0x90,0x60,0xf8,
2106
0xc6,0x21,0x48,0xe0,0xe3,0x96,0x8e,0x2e,0xf4,0x4c,0x01,0xf6,0xab,0xd2,0x43,0x82,
2107
0x75,0xb4,0x05,0xff,0xa6,0xaa,0xea,0x53,0x48,0x3d,0x60,0x30,0x38,0x0b,0x7a,0x64,
2108
0x86,0xa7,0x3b,0x33,0x3c,0x91,0x99,0x6b,0x3a,0x60,0xff,0x22,0x32,0xc3,0xf3,0x8d,
2109
0xb9,0xb6,0x1a,0x99,0xeb,0xce,0x43,0x82,0xe3,0xeb,0xd5,0x90,0xe0,0x1c,0x78,0xae,
2110
0x30,0x7f,0x08,0x23,0x6a,0xaa,0x87,0x04,0x5d,0x6c,0xac,0x81,0xd4,0x07,0x0e,0xba,
2111
0x86,0xcc,0x9f,0x54,0x42,0x82,0x7c,0x0b,0x38,0xf2,0x63,0x18,0x42,0x0b,0x38,0xa0,
2112
0x05,0xae,0x71,0x11,0xba,0xdf,0x0a,0x8f,0x62,0xe6,0x4b,0x50,0x70,0xe9,0x16,0x78,
2113
0x1f,0x2e,0x0a,0xf3,0xc1,0xdc,0x0e,0x73,0xa2,0xf5,0x23,0x08,0xfd,0xd6,0x0b,0x57,
2114
0x91,0xf9,0x4a,0x17,0x32,0x77,0x5c,0x80,0x74,0x05,0xf2,0x0d,0xc8,0xdc,0x79,0x19,
2115
0x7d,0x7b,0xe1,0x1a,0xa4,0x41,0x64,0xee,0x82,0xae,0x75,0x41,0xd4,0xb6,0x5e,0x81,
2116
0xcc,0x67,0x2a,0x48,0x70,0xc0,0x67,0x10,0xfd,0xad,0x5d,0x38,0xf3,0x05,0x32,0x5f,
2117
0x87,0x36,0x87,0x60,0x21,0xfc,0x58,0x81,0xcc,0x3d,0x2d,0xc8,0x0c,0x4f,0x0e,0xe6,
2118
0x1b,0xb0,0x6c,0xb6,0xde,0x82,0x0b,0x9b,0x54,0x38,0x73,0x19,0x32,0xd0,0x4d,0x13,
2119
0x0c,0x03,0x6e,0x8e,0xe6,0x5b,0x10,0x73,0xb7,0x2e,0xa2,0x6f,0x5b,0x3e,0x83,0x2d,
2120
0x18,0xab,0x1f,0x86,0x0e,0x5e,0x34,0xc3,0x9d,0xe3,0xdb,0x56,0xe8,0xd9,0xc5,0x32,
2121
0xb0,0x76,0x2b,0x1c,0x78,0x1b,0x8c,0x77,0x1b,0xc6,0x7d,0x1b,0xa6,0xd7,0xd5,0x4a,
2122
0xfc,0x1f,0x51,0x43,0x0f,0x9a,0xd3,0xc2,0x85,0x06,0xe1,0x74,0x7c,0x4b,0xbc,0xa4,
2123
0x87,0xf9,0x76,0xb9,0x1c,0x2c,0x8f,0xbf,0x4d,0x81,0x65,0xea,0xdb,0x4b,0x60,0xb3,
2124
0x3b,0xb0,0xff,0x05,0xd8,0xe2,0x0b,0xb0,0xd3,0x17,0x10,0xbc,0x4a,0x05,0xfa,0x16,
2125
0xa6,0xe3,0xb7,0x6d,0x70,0x6f,0xbb,0x78,0x01,0x22,0x19,0x66,0xc2,0xac,0x06,0xff,
2126
0x57,0xd8,0x00,0xe9,0x36,0x9a,0x2d,0xbb,0x01,0x09,0x66,0x44,0xd9,0x67,0x68,0xb6,
2127
0x1c,0x7f,0x35,0x81,0xbf,0x92,0xb9,0x00,0x11,0xde,0x0c,0x51,0xdf,0x83,0x66,0x2b,
2128
0xe0,0x1c,0x23,0x2c,0x5f,0x17,0xbb,0xe0,0x04,0xc3,0x10,0x14,0x0c,0x42,0x41,0x07,
2129
0x9a,0xad,0x54,0xa1,0xd9,0x2a,0x58,0x56,0x2e,0x7e,0x06,0x47,0x55,0x5f,0x84,0x1d,
2130
0x0d,0x14,0xc2,0x38,0x3a,0xae,0xa1,0xd9,0x9a,0x4e,0x48,0x77,0xd0,0xec,0x07,0xd0,
2131
0x4a,0x0d,0x04,0x4c,0x67,0x17,0x9a,0xad,0x03,0x97,0x5c,0x82,0x17,0xb1,0xd9,0x0f,
2132
0x2f,0xa1,0xd9,0x0b,0xfd,0x68,0xb6,0x51,0x87,0xbe,0xed,0x82,0x37,0x0d,0x30,0xf4,
2133
0xb7,0x9f,0x82,0xc5,0xe0,0x75,0xc2,0x5c,0x06,0x13,0xad,0x49,0x8e,0x66,0x3f,0x6a,
2134
0x42,0x73,0x70,0x57,0x99,0xa9,0x6a,0x84,0xfd,0x56,0x34,0xdb,0x0c,0x5d,0x6b,0x3e,
2135
0x8f,0xff,0x1d,0x0c,0x06,0xea,0xd6,0xa1,0xd9,0x4f,0xa0,0xef,0x1f,0xc3,0x15,0x5b,
2136
0xc1,0x36,0x97,0x6a,0xba,0xd1,0xec,0xc5,0x4a,0x34,0xdb,0xf2,0x09,0x9a,0x6d,0x83,
2137
0x0e,0xc3,0xc2,0x32,0x7b,0x19,0xae,0x72,0xe5,0x2a,0x9a,0xbd,0x0a,0xbe,0xbe,0xf4,
2138
0x11,0xec,0x7c,0x7a,0x01,0x7d,0x7b,0xbd,0x01,0xcd,0x76,0xc1,0xdd,0xfc,0xd2,0xc5,
2139
0x2b,0x68,0xb6,0x1b,0x5e,0x12,0x7b,0xe0,0xac,0x6e,0x30,0xc1,0x35,0x38,0xf3,0x1a,
2140
0xac,0x58,0x97,0xae,0x62,0xff,0xf5,0xc1,0x8d,0xe0,0xd2,0xa7,0x70,0x05,0xa8,0x5e,
2141
0xb8,0x74,0x03,0x46,0x7c,0xe3,0x0b,0x34,0x0b,0xcf,0x75,0xb3,0x3d,0x70,0x5e,0x5f,
2142
0x3d,0x24,0x18,0x9c,0x09,0x06,0x09,0x4f,0x41,0xb3,0xf8,0x41,0xe6,0x12,0xfe,0x4a,
2143
0xa4,0xaf,0x0f,0xcd,0xf6,0x83,0x1d,0xe1,0x76,0xff,0x6d,0x5f,0x2f,0x9a,0xc5,0x37,
2144
0xd8,0x4b,0x70,0xcf,0x9c,0xbd,0x05,0x9e,0x18,0x82,0x05,0xf5,0xd2,0x10,0x4c,0xc4,
2145
0x4b,0x77,0xe0,0x9a,0x5f,0x94,0xa1,0x67,0xf2,0x01,0x48,0xd0,0xa9,0x9b,0xf5,0x30,
2146
0x59,0xf4,0x90,0x86,0x20,0xdd,0x42,0xcf,0x60,0xdc,0x30,0x39,0xdb,0xd1,0x33,0x0d,
2147
0x34,0xdc,0xa6,0xbb,0x84,0x9e,0x95,0x81,0xf7,0xda,0x2a,0xf1,0xef,0xd9,0x3b,0xd0,
2148
0x33,0x1d,0x78,0xa3,0xad,0x41,0x8b,0x9e,0xe9,0x61,0xd1,0x81,0x85,0x69,0xa1,0xad,
2149
0x09,0x7f,0x95,0xd0,0x52,0x8b,0x9e,0x19,0x6f,0xa3,0x67,0x95,0xb0,0xfa,0xdd,0xc6,
2150
0x3f,0x6d,0x87,0xf7,0xba,0xdb,0xfd,0xe8,0x19,0xbc,0xf8,0x3c,0xab,0x69,0x42,0xcf,
2151
0x3e,0xd0,0xa0,0x67,0xe7,0xe1,0x35,0x78,0xf0,0x02,0x2c,0x55,0xe0,0xb7,0xb6,0xeb,
2152
0x37,0x21,0x03,0xf1,0xdd,0x76,0x03,0x87,0x57,0xd9,0x27,0xe8,0x59,0x03,0x6e,0xf9,
2153
0x4e,0x2b,0x16,0x88,0xad,0x76,0x85,0x1a,0x7d,0xfb,0xc5,0x20,0x9a,0x91,0xc3,0x23,
2154
0x42,0x3b,0xbc,0x16,0x82,0xc0,0x0d,0xa0,0x5d,0xdd,0x88,0xa5,0x17,0x3d,0x6b,0xc2,
2155
0xdf,0x1e,0xc2,0x69,0x30,0xef,0x66,0x14,0x65,0x68,0x46,0x09,0x4f,0x57,0xed,0xf8,
2156
0x6b,0xa7,0xd6,0x4a,0x34,0x03,0xaf,0x96,0x0b,0xed,0x0d,0x70,0xb3,0x69,0xff,0x08,
2157
0x1e,0xb0,0xda,0x2f,0xc0,0xd5,0xaf,0x7c,0x8a,0x66,0xd4,0x9f,0xc1,0xa2,0x09,0x63,
2158
0xed,0x84,0x67,0x8a,0xf6,0x76,0xb8,0x3b,0xb4,0x5f,0xbd,0x82,0x9e,0x7d,0x7a,0x0d,
2159
0xcd,0xe0,0x7b,0x71,0xfb,0x35,0x18,0xe3,0x67,0x60,0x9a,0xcf,0x74,0x50,0x00,0xcb,
2160
0x52,0xfb,0x0d,0x18,0x23,0x3c,0x36,0xcf,0xe8,0x61,0xc1,0x86,0x07,0xda,0x67,0xf0,
2161
0xb4,0xfb,0x0c,0xee,0x87,0x0b,0xed,0x77,0xe0,0x28,0x13,0xac,0xe6,0x06,0x58,0x85,
2162
0x6f,0xc1,0x10,0xfb,0x95,0xe8,0xd9,0x80,0x06,0xf6,0xe1,0xce,0x74,0x19,0xcc,0xb4,
2163
0x70,0x59,0x57,0x8e,0x66,0x8c,0xd0,0xd7,0xcb,0x15,0x8d,0xe8,0xd9,0x10,0xdc,0x92,
2164
0x2e,0x1b,0xee,0xa0,0x67,0x77,0xea,0xd0,0xb3,0x2f,0xf0,0x0e,0x7e,0xb3,0xbb,0x5c,
2165
0x7b,0x09,0xcd,0x29,0xe0,0x7e,0x79,0x19,0xde,0x76,0xe6,0x60,0xc1,0x5a,0xb8,0x64,
2166
0xfc,0x04,0x82,0xae,0x0e,0x82,0xef,0x06,0x9a,0x53,0xab,0xd0,0x4c,0x75,0x05,0x6c,
2167
0xef,0x20,0xf3,0x55,0xb0,0xf1,0xe5,0x8f,0xaf,0x60,0x81,0xdc,0xa5,0x4a,0x1c,0x8b,
2168
0x95,0x10,0xa4,0x5a,0x35,0x9a,0xbb,0xf3,0x31,0x9a,0xa9,0xf9,0x14,0xcd,0xe9,0x6b,
2169
0x20,0xc1,0xf1,0x7a,0xfc,0x63,0xd3,0x5e,0xd8,0xc2,0x94,0xb5,0x6e,0x87,0xd0,0x5c,
2170
0x05,0x98,0xe2,0x72,0xd7,0x20,0x9a,0x33,0x34,0xa3,0x39,0x23,0x5c,0xb6,0xb2,0x1b,
2171
0xf2,0x78,0x0b,0x95,0x55,0x57,0xa0,0xec,0x3c,0x6c,0xf5,0x90,0x0c,0x90,0xc0,0xdf,
2172
0x97,0xc1,0x3f,0x0b,0x97,0x61,0xe1,0x58,0xb8,0x0c,0x2f,0x0a,0x33,0xb5,0xd0,0x3e,
2173
0xbc,0x19,0xce,0xc1,0x3b,0xe1,0x5c,0x2d,0x18,0xfa,0x0a,0x3e,0xb6,0x0e,0xfc,0x78,
2174
0x19,0x1e,0x19,0x66,0xea,0x9a,0x21,0x81,0xe3,0x2e,0xdf,0x81,0xfb,0xf4,0x15,0x15,
2175
0x18,0xac,0x0e,0x8e,0x6f,0xac,0x86,0x04,0x4d,0x37,0x76,0xa2,0xb9,0x8f,0x70,0xd2,
2176
0xa2,0xb9,0xa6,0x4a,0x34,0x77,0xe1,0x22,0x6c,0x61,0xc0,0xcd,0x70,0xcc,0xc7,0xe0,
2177
0xb8,0x0f,0x3f,0x44,0x73,0x9f,0xb4,0xa2,0xb9,0x16,0x05,0xe4,0x07,0xd0,0x5c,0x2b,
2178
0x58,0xe4,0x0a,0x3e,0x11,0x1e,0x95,0xe7,0xe0,0x59,0x78,0xa6,0xc1,0x04,0x5b,0x58,
2179
0x45,0x3e,0x80,0x19,0x72,0xe5,0x22,0x04,0xf2,0x95,0xf6,0xcb,0x68,0xe6,0xa3,0x3b,
2180
0x68,0xe6,0x42,0x39,0x9a,0xbb,0x8a,0x0f,0xbf,0x01,0xed,0xdd,0x80,0xf6,0xe0,0xc5,
2181
0x69,0xae,0xef,0x02,0x9a,0xc3,0xef,0x08,0x57,0x06,0xe1,0xf9,0xa1,0xa5,0x05,0x2c,
2182
0x84,0xbf,0x6c,0xbc,0x09,0x83,0xbf,0x05,0x26,0x6e,0x81,0x16,0xe7,0x3e,0x87,0x67,
2183
0xf2,0x8e,0x0f,0x3f,0xc0,0xd2,0x8d,0x2c,0xca,0x5a,0x64,0x51,0xf5,0x20,0x8b,0x1a,
2184
0x9e,0x2f,0x3b,0x9a,0xae,0x41,0xe6,0x02,0xb2,0x68,0xfb,0x91,0xa5,0xe2,0x43,0x48,
2185
0x0d,0xc8,0xa2,0x1b,0x44,0x96,0xaa,0x01,0x64,0xa9,0x86,0x70,0xef,0xf8,0xec,0x36,
2186
0xb2,0xd4,0x43,0xcc,0x5d,0x86,0x1b,0x32,0x7e,0xbf,0xec,0x80,0x6b,0xcd,0x5c,0xb9,
2187
0x8c,0x2c,0x17,0x60,0x91,0xbe,0x79,0x03,0x59,0x9a,0x20,0xf6,0x3a,0xf1,0xe4,0xe9,
2188
0xd4,0x7e,0x84,0x66,0x3a,0x21,0xb8,0x3a,0xe1,0x9e,0xfc,0x09,0x74,0xb3,0xb3,0x5a,
2189
0x8f,0x66,0xae,0x42,0x14,0x77,0x7e,0x50,0x8f,0x2c,0x2d,0xf0,0xf0,0xd3,0x89,0x6f,
2190
0xd7,0x97,0xe0,0xde,0xd9,0xd5,0x8b,0x2c,0xf0,0x34,0x64,0xb9,0x7c,0x05,0x59,0xae,
2191
0x28,0x21,0xc1,0xe8,0x3e,0x83,0xe9,0xdf,0xd9,0x75,0x1d,0x59,0x7a,0xe4,0xc8,0xd2,
2192
0x0b,0x77,0x5b,0x78,0xab,0x9b,0x81,0xd7,0x27,0x8b,0x09,0x02,0xe1,0x2a,0xfe,0xc5,
2193
0x40,0x2f,0x4c,0x94,0xab,0x6a,0xb8,0xd4,0x55,0x2d,0x1c,0x7b,0x15,0x22,0x60,0xc6,
2194
0x04,0x2d,0x7f,0x7e,0x07,0x59,0xe0,0xed,0xd4,0x32,0x58,0x05,0x09,0xbc,0x75,0xb5,
2195
0x41,0x8e,0x90,0xcd,0xba,0xf5,0xb6,0x76,0x1b,0x36,0x6e,0xb4,0x27,0x6c,0x7a,0xc5,
2196
0xc1,0xf1,0x55,0xa7,0x8d,0x3f,0x7e,0x9c,0x37,0xba,0x6c,0xde,0xe2,0x4a,0xdc,0xba,
2197
0xcd,0xcd,0xba,0xeb,0xbe,0x71,0xfb,0x6b,0x1e,0x9e,0x3b,0x5e,0xf7,0xf2,0xde,0xf8,
2198
0x8b,0x7f,0x76,0xee,0x02,0xf1,0xf9,0x59,0x9b,0x24,0xed,0xde,0xb3,0xd7,0x77,0xdf,
2199
0x1b,0xd6,0xbc,0xdf,0x46,0xf2,0x0f,0xc5,0xfe,0x01,0x1b,0x29,0xd4,0xdf,0x41,0xe6,
2200
0xcd,0x9f,0xe9,0x3a,0xb4,0x9f,0xe4,0xe9,0x3f,0x43,0x7b,0x6f,0xfd,0xf9,0xaa,0xb7,
2201
0xb1,0x04,0x6e,0xdc,0xc8,0x08,0xda,0xcf,0xfc,0xbe,0x28,0xf8,0x9d,0x3f,0x38,0xe2,
2202
0xdd,0x8d,0x1b,0x0f,0x84,0xfc,0xb0,0x73,0x70,0xe3,0x6f,0xf8,0x73,0x28,0x34,0x6c,
2203
0xe3,0xda,0x67,0xed,0xb3,0xf6,0x59,0xfb,0xac,0x7d,0xd6,0x3e,0x6b,0x9f,0xb5,0xcf,
2204
0xda,0x67,0xed,0xb3,0xf6,0x59,0xfb,0xac,0x7d,0x7e,0x3b,0x1f,0x64,0xbb,0xc6,0x3f,
2205
0x84,0x1d,0xb2,0xff,0x03,0x08,0xc8,0x19,0xb9,0x20,0xd7,0xef,0x21,0x22,0x0f,0xc0,
2206
0x13,0x79,0x23,0x12,0x22,0x23,0x0a,0x40,0x45,0x0c,0x14,0x8c,0x0e,0xa0,0x10,0xc4,
2207
0x41,0xc9,0x28,0x1d,0xe0,0x23,0x11,0x92,0x22,0x35,0x32,0xa0,0x5a,0xa0,0x09,0xb5,
2208
0xa1,0x2e,0xd4,0x87,0x06,0xd1,0x3d,0xf4,0x00,0x3d,0x42,0x4f,0x80,0x19,0xf4,0x1c,
2209
0xbd,0x40,0x2f,0x91,0xad,0x8d,0x83,0x15,0x57,0x1b,0x0f,0x1b,0x1f,0x1b,0x3f,0x1b,
2210
0x9a,0x15,0xa6,0x4d,0xa8,0x0d,0xdb,0x26,0xc1,0x26,0xc5,0x26,0x1d,0xe0,0xdb,0x88,
2211
0x6c,0xa4,0x36,0x6a,0x1b,0x83,0x4d,0xad,0x4d,0x93,0x4d,0x9b,0x4d,0x17,0xd0,0x67,
2212
0x33,0x68,0x73,0xcf,0xe6,0x81,0xcd,0x23,0x9b,0x27,0x56,0x66,0x6c,0x9e,0xdb,0xbc,
2213
0xb0,0x79,0x69,0x63,0xbb,0xce,0x76,0x9d,0x03,0xe0,0xba,0xce,0x63,0x9d,0xcf,0x3a,
2214
0xbf,0x75,0xb4,0x75,0xcc,0x75,0xa1,0xeb,0xd8,0xeb,0x12,0xd6,0xa5,0xac,0x4b,0x5f,
2215
0xc7,0x5f,0x27,0x5a,0x27,0x5d,0xa7,0x5e,0x67,0xb0,0x52,0xbb,0xae,0x69,0x5d,0xdb,
2216
0xba,0xae,0x75,0x7d,0xeb,0x06,0xd7,0xdd,0x5b,0xf7,0x60,0xdd,0xa3,0x75,0x4f,0xd6,
2217
0xcd,0xac,0x7b,0xbe,0xee,0xc5,0xba,0x97,0xeb,0x6c,0xd7,0x3b,0xac,0x77,0x5d,0xef,
2218
0xb1,0xde,0x67,0xbd,0x9f,0x15,0xda,0x7a,0xe6,0xfa,0xd0,0xf5,0xec,0xf5,0x09,0xeb,
2219
0x53,0xd6,0xa7,0xaf,0xe7,0xaf,0x17,0xad,0x17,0xaf,0x97,0xad,0x57,0xaf,0x37,0xac,
2220
0xaf,0x5d,0xdf,0xb4,0xbe,0x0d,0xe8,0x5a,0xdf,0xb7,0x7e,0x70,0xfd,0xbd,0xf5,0x0f,
2221
0xd6,0x4f,0xac,0x9f,0x5a,0x3f,0x63,0xe5,0xf9,0xfa,0x17,0xeb,0x5f,0xae,0xb7,0xb5,
2222
0x75,0xb0,0x25,0xda,0x7a,0x58,0xf1,0xb1,0xf5,0xb3,0xa5,0xd9,0x32,0x6d,0x43,0x6d,
2223
0xd9,0x56,0x12,0x6c,0x53,0x6c,0xd3,0x6d,0xf9,0xb6,0x22,0x5b,0xa9,0xad,0xda,0xd6,
2224
0x60,0x5b,0x6b,0xdb,0x64,0xdb,0x66,0xdb,0x65,0xdb,0x67,0x3b,0x68,0x7b,0xcf,0xf6,
2225
0x81,0xed,0x23,0xdb,0x27,0x56,0x66,0x6c,0x9f,0xdb,0xbe,0xb0,0x7d,0x69,0x6b,0x6b,
2226
0xe7,0x60,0xe7,0x6a,0xe7,0x61,0xe7,0x63,0xe7,0x67,0x47,0xb3,0x63,0xda,0x85,0xda,
2227
0xb1,0xed,0x12,0xec,0x52,0xec,0xd2,0xed,0xf8,0x76,0x22,0x3b,0xa9,0x9d,0xda,0xce,
2228
0x60,0x57,0x67,0xd7,0xf0,0x0f,0xd3,0x62,0xd7,0xf1,0xdf,0x70,0xdd,0xae,0xff,0xaf,
2229
0x62,0xc0,0x6e,0xc4,0x6e,0xdc,0x6e,0xca,0xce,0x6c,0x37,0x6f,0xb7,0x64,0xb7,0x62,
2230
0x67,0xb7,0xc1,0x61,0x83,0xeb,0x06,0x8f,0x0d,0x3e,0x1b,0xfc,0x36,0xd0,0x36,0x30,
2231
0x37,0x84,0x6e,0x60,0x6f,0x48,0xda,0x90,0xbe,0x21,0x67,0x83,0x74,0x83,0x76,0x43,
2232
0xed,0x86,0x96,0x0d,0x5d,0x40,0xff,0x86,0x7b,0x1b,0x1e,0x6e,0x78,0xb2,0x61,0x66,
2233
0xc3,0x73,0x2b,0x2f,0x36,0xbc,0xdc,0x60,0xbb,0xd1,0x61,0xa3,0xeb,0x46,0x8f,0x8d,
2234
0x7b,0x37,0xd2,0x36,0x32,0x37,0x86,0x6e,0xe4,0x6c,0x4c,0xdc,0x98,0xba,0x31,0x7d,
2235
0x23,0x7f,0xa3,0xc8,0x8a,0x74,0xa3,0x7a,0x63,0xf5,0xc6,0xa6,0x8d,0x6d,0x1b,0xbb,
2236
0x36,0xf6,0x6d,0x1c,0x04,0xee,0x6d,0x7c,0xb0,0xf1,0xd1,0xc6,0x27,0x1b,0x67,0x36,
2237
0x3e,0xdf,0xf8,0x62,0xe3,0xcb,0x8d,0xb6,0xf6,0x0e,0xf6,0xae,0xf6,0x1e,0xf6,0x3e,
2238
0xf6,0x7e,0xf6,0x34,0x7b,0xa6,0x7d,0xa8,0x3d,0xdb,0x3e,0xc1,0x3e,0xc5,0x3e,0xdd,
2239
0x9e,0x6f,0x2f,0xb2,0x97,0xda,0xab,0xed,0x0d,0xf6,0xb5,0xf6,0x4d,0x56,0xda,0xec,
2240
0xbb,0xfe,0x80,0x3e,0xfb,0x41,0xfb,0x7b,0xf6,0x0f,0xec,0x1f,0xdb,0xcf,0xd8,0x2f,
2241
0xd8,0xbf,0xb4,0xb7,0x25,0x38,0x10,0xdc,0x08,0x3e,0x04,0x3f,0x02,0xed,0x37,0x0a,
2242
0x9d,0xc0,0x20,0x04,0x13,0x42,0x08,0x61,0x04,0x16,0x81,0x43,0x88,0x25,0x24,0x12,
2243
0x92,0xfe,0x21,0x92,0x09,0x69,0x04,0x1e,0x41,0x48,0x90,0x10,0x14,0x04,0x2d,0xa0,
2244
0x23,0x18,0x09,0x35,0x84,0x3a,0x42,0x23,0xa1,0xe9,0x57,0x4b,0x0b,0xa1,0x0d,0xe8,
2245
0x20,0x5c,0xff,0x27,0xd3,0xf7,0x23,0x26,0xc2,0xe0,0xf7,0xdc,0xfd,0x91,0x61,0xc2,
2246
0x97,0x84,0x87,0x84,0xc7,0x84,0x27,0x84,0x19,0xc2,0x73,0xc2,0x0b,0xe0,0x25,0x60,
2247
0xbb,0xc9,0x61,0x93,0xdb,0xdf,0x81,0xd7,0xa6,0xbd,0x9b,0x28,0x9b,0x02,0x37,0x1d,
2248
0xd8,0x14,0xbe,0x29,0xe1,0xef,0x20,0x65,0x53,0xfa,0x26,0xfe,0x26,0xd1,0x26,0xe9,
2249
0x26,0xd9,0x26,0xc5,0x26,0xcd,0x26,0xfd,0xa6,0x0f,0x36,0x35,0x6e,0x6a,0xde,0xd4,
2250
0xf2,0x37,0xd3,0xba,0xa9,0x7d,0x53,0xe7,0xa6,0xae,0x4d,0xdd,0x9b,0x7a,0x36,0xf5,
2251
0x59,0x31,0x6d,0xea,0xff,0x23,0xee,0x6e,0xba,0x0f,0x3c,0xfc,0x9e,0xc7,0x3f,0xf2,
2252
0x74,0xd3,0xdc,0xa6,0x85,0x3f,0xc9,0x77,0xff,0x20,0xe8,0x95,0xbf,0x05,0xfb,0x57,
2253
0x9c,0x01,0xb7,0xef,0xf1,0xfa,0x91,0xbd,0xaf,0x50,0x5e,0x09,0xfc,0x1b,0x39,0xf0,
2254
0x4a,0xf8,0xff,0x42,0x62,0x5e,0x49,0xfa,0x6f,0x38,0xfd,0x0a,0xf7,0x95,0x9c,0x57,
2255
0x0a,0xad,0xc8,0x5f,0xd1,0x5a,0xa9,0x7e,0xa5,0xe1,0x95,0x96,0x57,0x3a,0x5e,0xb9,
2256
0xfe,0x4a,0xbf,0x95,0xbb,0xaf,0xdc,0x7f,0xe5,0xe1,0x2b,0x8f,0x5f,0x79,0xfa,0xca,
2257
0x9c,0x95,0x85,0x57,0xbe,0x7b,0x05,0x39,0xd8,0x3b,0x38,0x3b,0xb8,0x39,0x78,0x39,
2258
0xec,0x75,0xa0,0x38,0x04,0x3a,0x1c,0x70,0x08,0xb7,0x12,0xe3,0x90,0xf4,0xab,0x26,
2259
0xd9,0x21,0xe5,0x9f,0x48,0xaa,0x43,0xba,0x95,0x0c,0x07,0x9e,0x03,0x7f,0x8d,0xbf,
2260
0x01,0x91,0x83,0xd4,0x41,0xed,0x60,0x70,0xa8,0xfd,0x5f,0x4c,0x9d,0x43,0xb3,0x43,
2261
0xbb,0x43,0xb7,0x43,0xdf,0xff,0x32,0x06,0x81,0x7b,0x7f,0x91,0x07,0xff,0x34,0xd0,
2262
0xda,0xe7,0x37,0xfe,0xf9,0x67,0x44,0xd5,0xa3,0x3f,0xe2,0x89,0x95,0x99,0x9f,0x89,
2263
0xe7,0x0e,0x2f,0x1c,0x5e,0x3a,0xd8,0x3a,0x3a,0x38,0xba,0x3a,0x7a,0x38,0xfa,0xfc,
2264
0x8b,0xe2,0xe7,0x48,0xfb,0x0b,0x30,0x1d,0x43,0x01,0xf6,0xaf,0x86,0x04,0x2b,0x29,
2265
0x3f,0x0b,0xe9,0x8e,0x7c,0x47,0x91,0x15,0xe9,0x1a,0xff,0x82,0xa8,0xad,0x18,0x1c,
2266
0x6b,0xff,0x02,0x4d,0x8e,0x6d,0xbf,0x28,0x5d,0xbf,0x20,0x7d,0x8e,0x83,0x8e,0xf7,
2267
0x7e,0xb3,0x3c,0xf8,0x8d,0xf1,0xe8,0x0f,0x78,0xe2,0x38,0x03,0x3c,0x77,0xfc,0xee,
2268
0x37,0x0e,0x7a,0xd5,0xfe,0x55,0xe7,0x35,0xfe,0x2c,0x6e,0x80,0xd7,0xab,0x7e,0xaf,
2269
0xd2,0x7e,0x35,0xd0,0x5f,0x65,0xfe,0xa6,0x09,0x7e,0x35,0xf4,0x67,0x26,0xec,0x55,
2270
0xce,0xab,0x09,0xff,0x54,0x12,0x5f,0x4d,0xfa,0x45,0x39,0xfd,0x27,0xe0,0xfe,0x48,
2271
0xce,0x8f,0x14,0xfe,0x88,0xfc,0xcf,0xa2,0xfd,0x13,0x54,0x03,0x0d,0xaf,0xb6,0xbe,
2272
0xda,0xf5,0xaa,0xe9,0xd5,0xbb,0x7f,0xc4,0xfd,0xbf,0x82,0x87,0x7f,0x82,0xc7,0x3f,
2273
0xf2,0xf4,0x47,0xe6,0x7e,0x64,0xe1,0xcf,0xf2,0xdd,0xbf,0x30,0xc8,0x69,0x8d,0x5f,
2274
0x07,0x36,0x4e,0xb6,0x7f,0x12,0x07,0xc0,0x15,0xf0,0x00,0x7c,0x00,0xbf,0xef,0xa1,
2275
0xfd,0xec,0x30,0x81,0x50,0x2b,0x6c,0xa7,0x04,0x20,0x65,0x8d,0x7f,0x31,0x52,0x9d,
2276
0xd2,0x9c,0x32,0x9c,0xb8,0x4e,0x3c,0x27,0x81,0x93,0xd0,0x49,0xec,0x24,0x71,0x92,
2277
0x39,0x29,0x9c,0x34,0x4e,0x3a,0x27,0xa3,0x53,0x8d,0x53,0xad,0x53,0x9d,0x53,0xa3,
2278
0x53,0xb3,0x53,0xab,0x53,0xbb,0x53,0xa7,0x53,0xb7,0x53,0x8f,0x93,0xc9,0x69,0xc0,
2279
0x69,0xc8,0x69,0xd8,0x69,0xc4,0x69,0xd4,0x69,0xcc,0x69,0xdc,0x69,0xc2,0x69,0xd2,
2280
0xe9,0x89,0xd3,0x94,0xd3,0xb4,0x93,0xd9,0xc9,0xe2,0x34,0xef,0xb4,0xe8,0xb4,0xe4,
2281
0xb4,0xec,0xb4,0xe2,0x64,0xe3,0x6c,0xe7,0x4c,0x70,0x76,0x74,0x76,0x71,0x26,0x3a,
2282
0xbb,0x3b,0x7b,0x3a,0x7b,0x3b,0x93,0x9c,0x7d,0x9d,0xc9,0xce,0x54,0x67,0xba,0x33,
2283
0xc3,0x39,0xd8,0x39,0xc4,0x39,0xcc,0x99,0xe5,0xcc,0xfe,0xb3,0x70,0x9c,0x63,0x7e,
2284
0x06,0x62,0x9d,0x13,0x9d,0x93,0x9d,0x53,0x9d,0xd3,0x9c,0x33,0x9c,0x79,0xce,0x02,
2285
0x67,0xa1,0xb3,0xd8,0x59,0xe2,0x2c,0x73,0x56,0x38,0x6b,0x9c,0x75,0xce,0x46,0xe7,
2286
0x1a,0xe7,0x3a,0xe7,0x46,0xe7,0x66,0xe7,0x56,0xe7,0x76,0xe7,0x4e,0xe7,0x6e,0xe7,
2287
0x1e,0x67,0x93,0xf3,0x80,0xf3,0x90,0xf3,0xb0,0xf3,0x88,0xf3,0xa8,0xf3,0x98,0xf3,
2288
0xb8,0xf3,0x84,0xf3,0xa4,0xf3,0x94,0xf3,0xb4,0xf3,0xcc,0xff,0x02,0x9e,0x3b,0xbf,
2289
0x70,0x7e,0xe9,0x6c,0xeb,0xe2,0xe0,0xe2,0xea,0xe2,0xe1,0xe2,0xe3,0x42,0x71,0x61,
2290
0xba,0x84,0xba,0xb0,0x5d,0x12,0x5c,0x52,0x5c,0xd2,0x5d,0xf8,0x2e,0x22,0x17,0xa9,
2291
0x8b,0xda,0xc5,0xe0,0xd2,0xe0,0xd2,0xe6,0x72,0xdd,0x65,0xd0,0xe5,0x9e,0xcb,0x03,
2292
0x97,0x47,0x2e,0x4f,0x5c,0xe6,0x5c,0x5e,0xb8,0xbc,0x74,0xb1,0xdd,0xec,0xb0,0xd9,
2293
0x75,0xb3,0xc7,0x66,0x9f,0xcd,0x7e,0x9b,0x69,0x9b,0x99,0x9b,0x43,0x37,0xb3,0x37,
2294
0x27,0x6c,0x4e,0xd9,0x9c,0xbe,0x99,0xbf,0x59,0xb4,0x59,0xbe,0xd9,0xb0,0xb9,0x76,
2295
0x73,0xd3,0xe6,0xb6,0xcd,0x5d,0x9b,0xfb,0x36,0x0f,0x6e,0xbe,0xb7,0xf9,0xc1,0xe6,
2296
0xc7,0x9b,0x67,0x36,0x3f,0xdf,0xfc,0x62,0xf3,0xcb,0xcd,0xb6,0x5b,0x1c,0xb6,0xb8,
2297
0x6e,0xf1,0xd8,0xe2,0xb3,0xc5,0x6f,0x0b,0x6d,0x0b,0x73,0x4b,0xe8,0x16,0xf6,0x96,
2298
0x84,0x2d,0x29,0x5b,0xd2,0xb7,0xf0,0xb7,0x88,0xb6,0xc8,0xb7,0x18,0xb6,0x34,0x6c,
2299
0x69,0xdb,0x72,0x7d,0xcb,0xe0,0x96,0xfb,0x5b,0x1e,0x6d,0x79,0xb2,0x65,0x66,0xcb,
2300
0xf3,0x2d,0x2f,0xb6,0xbc,0xdc,0x62,0xeb,0xea,0xe0,0xea,0xea,0xea,0xe5,0xea,0xe7,
2301
0x4a,0x73,0x65,0xba,0x86,0xba,0xb2,0x5d,0x13,0x5c,0x53,0x5c,0xb9,0xae,0x22,0x57,
2302
0xb9,0xab,0xc1,0xb5,0xc1,0xb5,0xcd,0xb5,0xcb,0xb5,0xcf,0x75,0xd0,0xf5,0x9e,0xeb,
2303
0x03,0xd7,0x47,0xae,0x4f,0x5c,0x67,0x5c,0x9f,0xbb,0xbe,0x70,0x7d,0xe9,0x6a,0x4b,
2304
0x74,0x20,0xba,0x12,0xbd,0x88,0x7e,0xc4,0x40,0x62,0x28,0x91,0x4d,0x4c,0x20,0xa6,
2305
0x10,0xd3,0x89,0x7c,0xa2,0x88,0x28,0x25,0xaa,0x89,0x06,0x62,0x2d,0xb1,0x89,0xd8,
2306
0x46,0xec,0x22,0xf6,0x11,0x07,0x89,0xf7,0x88,0x0f,0x88,0x8f,0x88,0x4f,0x88,0x33,
2307
0xc4,0xe7,0xc4,0x17,0xc4,0x97,0x44,0xdb,0xad,0x0e,0x5b,0x5d,0xb7,0x7a,0x6c,0xf5,
2308
0xd9,0xea,0xb7,0x95,0xbe,0xf5,0x9d,0xad,0xa1,0x3f,0xc2,0xde,0x9a,0xb0,0x35,0x65,
2309
0x6b,0xfa,0xd6,0x9c,0xad,0xd2,0xad,0xda,0xad,0xb5,0x5b,0x5b,0xb6,0x76,0x6d,0xed,
2310
0xdf,0x7a,0x6f,0xeb,0xc3,0xad,0x4f,0xb6,0xce,0x6d,0x7d,0xb1,0x15,0x6d,0x73,0xd8,
2311
0xe6,0xb6,0xcd,0x67,0x1b,0x65,0x1b,0x73,0x5b,0xf8,0xb6,0x84,0x6d,0x29,0xdb,0xd2,
2312
0xb7,0xf1,0xb7,0x89,0xb6,0x49,0xb7,0xa9,0xb7,0x55,0x6f,0x6b,0xda,0xd6,0xb1,0xad,
2313
0x6f,0xdb,0xdd,0x6d,0x0f,0xb6,0x3d,0xde,0x36,0xb3,0x6d,0x61,0xdb,0xcb,0x6d,0xb6,
2314
0x6e,0x0e,0x6e,0xae,0x6e,0x1e,0x6e,0x3e,0x6e,0x7e,0x6e,0x34,0x37,0xa6,0x5b,0xb8,
2315
0x5b,0x82,0xdb,0x69,0x37,0xbe,0x5b,0xa1,0x9b,0xda,0xad,0xda,0xad,0xc9,0xad,0xc3,
2316
0xad,0xcf,0xed,0xae,0xdb,0x03,0xb7,0xc7,0x6e,0x33,0x6e,0x0b,0x6e,0x2f,0xdd,0xec,
2317
0xdd,0x5d,0xdd,0xbd,0xdc,0xfd,0xdc,0x69,0xee,0x4c,0xf7,0x50,0x77,0xb6,0x7b,0x92,
2318
0x7b,0xba,0x7b,0x8e,0xbb,0xd4,0x5d,0xeb,0x5e,0xeb,0xde,0xe2,0xde,0xe5,0xde,0xef,
2319
0x7e,0xcf,0xfd,0x81,0xfb,0x23,0xf7,0x27,0xee,0x33,0xee,0xcf,0xdd,0x5f,0xb8,0xbf,
2320
0x74,0xb7,0xdd,0xfe,0x87,0x38,0x6c,0x77,0xdd,0xee,0xb5,0xdd,0x6f,0x7b,0xe0,0xf6,
2321
0xd0,0xed,0x31,0xdb,0x53,0xb6,0xa7,0x6f,0xe7,0x6f,0x2f,0xdc,0xae,0xde,0x5e,0xbd,
2322
0xbd,0x69,0x7b,0xc7,0xf6,0xbe,0xed,0x83,0xdb,0xef,0x6d,0x7f,0xb8,0xfd,0xc9,0xf6,
2323
0xb9,0xed,0x2f,0xac,0xbc,0xdc,0x6e,0xfb,0x9a,0xf3,0x6b,0x1e,0xaf,0xed,0x7d,0x8d,
2324
0x66,0x85,0xf9,0x5a,0xe8,0x6b,0x31,0xaf,0xa5,0xbc,0xc6,0x7d,0x4d,0xf4,0x9a,0xfc,
2325
0x35,0xc3,0x6b,0xb5,0xaf,0x35,0xbd,0xd6,0xf1,0x5a,0xdf,0x6b,0x77,0x5f,0x7b,0xf0,
2326
0xda,0xe3,0xd7,0x66,0x5e,0x7b,0xfe,0xda,0x8b,0xd7,0x90,0x87,0x83,0x87,0x9b,0x87,
2327
0x8f,0x07,0xc5,0x83,0xe9,0x11,0xea,0xc1,0xf6,0x48,0xf2,0x48,0xf7,0xc8,0xf1,0x90,
2328
0x7a,0x68,0x3d,0x6a,0x3d,0x9a,0x3c,0xda,0x3c,0xae,0x7b,0x0c,0x7a,0xdc,0xf7,0x78,
2329
0x64,0xe5,0x89,0xc7,0x8c,0xc7,0x82,0xc7,0x4b,0x0f,0x7b,0x4f,0x57,0x2b,0x1e,0x9e,
2330
0x3e,0x9e,0x14,0x4f,0xa6,0x67,0xb8,0x67,0x82,0xe7,0x69,0x4f,0x3e,0x20,0x02,0xe4,
2331
0x80,0x01,0x68,0xf0,0x6c,0xf1,0xec,0xf0,0xec,0xf3,0xbc,0xeb,0xf9,0xc0,0xf3,0xb1,
2332
0xe7,0x8c,0xe7,0x82,0xe7,0x77,0x9e,0x68,0x87,0xc3,0x0e,0xb7,0x1d,0x3e,0x3b,0x28,
2333
0x3b,0x98,0x3b,0xc2,0x77,0xc4,0xec,0x48,0xda,0x71,0x7a,0x07,0x77,0x47,0xce,0x8e,
2334
0xc2,0x1d,0xf2,0x1d,0xda,0x1d,0xd5,0x3b,0x1a,0x76,0xb4,0xec,0xe8,0xd8,0x71,0x7d,
2335
0x47,0xbf,0x95,0x7b,0x3b,0x1e,0xee,0x78,0xba,0x63,0x61,0x07,0x7a,0xdd,0xf9,0x75,
2336
0xaf,0xd7,0x29,0xaf,0x33,0x5f,0x0f,0x7f,0x3d,0xe9,0x75,0xee,0xeb,0x85,0xaf,0x6b,
2337
0x5f,0x6f,0x78,0xbd,0xe3,0xf5,0xbe,0xd7,0xef,0xbe,0xfe,0xf0,0xf5,0xa7,0xaf,0x2f,
2338
0xbc,0x8e,0xbc,0x9c,0xbd,0xbc,0xbc,0xfc,0xbc,0x02,0xbd,0xc2,0xbd,0x92,0xbc,0xb8,
2339
0x5e,0x85,0x5e,0x5a,0xaf,0x06,0xaf,0x36,0xaf,0xeb,0x5e,0x77,0xbd,0x1e,0x7a,0x3d,
2340
0xf5,0x5a,0xf0,0x42,0xde,0xce,0xde,0x1e,0xde,0x7b,0xbd,0x03,0xbd,0xc3,0xbd,0x93,
2341
0xbc,0xb9,0xde,0x85,0xde,0x5a,0xef,0x6a,0xef,0x06,0xef,0x36,0xef,0x2e,0xef,0x7e,
2342
0xe0,0xae,0xf7,0x03,0xef,0x47,0xde,0x4f,0xbc,0x67,0xbc,0x9f,0x7b,0x2f,0x79,0xbf,
2343
0xf4,0xb6,0xd9,0x49,0xd8,0xb9,0x79,0xa7,0xdb,0x4e,0x9f,0x9d,0x7e,0x3b,0x03,0x81,
2344
0x03,0x3b,0xd9,0x3b,0x13,0x76,0xa6,0xec,0x4c,0xdf,0xc9,0xdf,0x99,0xbf,0xb3,0x64,
2345
0x67,0xd9,0x4e,0xc3,0xce,0xda,0x9d,0x4d,0x3b,0x3b,0x76,0xf6,0x59,0x19,0xdc,0x79,
2346
0x7f,0xe7,0xc3,0x9d,0x8f,0x77,0x3e,0xdd,0x39,0xb7,0xf3,0x3f,0x77,0xfe,0xdf,0x9d,
2347
0xff,0xef,0x4e,0xb4,0xcb,0x7e,0x97,0xf3,0x2e,0x8f,0x5d,0x7b,0x77,0x51,0x76,0x05,
2348
0xee,0x3a,0xb0,0x8b,0xbd,0x2b,0x61,0x57,0xca,0xae,0xf4,0x5d,0xfc,0x5d,0xf9,0xbb,
2349
0x4a,0x76,0xa9,0x77,0x69,0xad,0xd4,0xee,0x6a,0xda,0xd5,0x01,0x5c,0xdf,0x35,0xb8,
2350
0xeb,0xde,0xae,0x07,0xbb,0x1e,0xed,0x7a,0xb2,0x6b,0x76,0x97,0x65,0xd7,0xc2,0xae,
2351
0xff,0x0b,0xfc,0x3f,0xbb,0x96,0x77,0xad,0xec,0xb2,0xf1,0xb1,0xf3,0x21,0xf8,0x38,
2352
0xfa,0xb8,0xf8,0x10,0x7d,0xdc,0x7d,0x3c,0x7e,0x82,0xa7,0x8f,0xd7,0x8f,0x78,0xfb,
2353
0xec,0xfd,0x33,0xf8,0xfa,0x90,0x7d,0xe8,0x3e,0x07,0xfe,0x88,0x10,0x9f,0x50,0x2b,
2354
0x61,0x3e,0x1c,0x9f,0x24,0x9f,0x64,0x9f,0x34,0x1f,0xfe,0xf7,0x08,0x7c,0x44,0x3e,
2355
0x62,0x1f,0xe9,0x1f,0x21,0xf3,0xd1,0xf8,0x18,0x7d,0x6a,0xff,0x2c,0x75,0x3e,0x6d,
2356
0x7f,0x40,0xbb,0x4f,0xc7,0x5f,0xa0,0xd3,0xa7,0xdb,0xe7,0x3a,0xd0,0xe3,0x63,0xf2,
2357
0x19,0xf0,0x19,0xf2,0x19,0xf6,0x19,0xf1,0x19,0xf5,0x19,0xf3,0x19,0xf7,0x99,0xf0,
2358
0x99,0xf4,0x99,0xf2,0x99,0xf6,0x31,0xfb,0x58,0x7c,0xe6,0x7d,0x16,0x7d,0x96,0x7c,
2359
0x96,0x7d,0x56,0x7c,0x6c,0x48,0x76,0x24,0x02,0xc9,0x91,0xe4,0x42,0x22,0x92,0xdc,
2360
0x49,0x1e,0x24,0x4f,0x92,0x37,0x89,0x44,0xf2,0x25,0x91,0x49,0x54,0x12,0x9d,0xc4,
2361
0x20,0x05,0x93,0x42,0x48,0x61,0x24,0x16,0x89,0x43,0x8a,0x25,0x25,0x92,0x92,0x49,
2362
0x29,0x7f,0x44,0x2a,0x29,0xfd,0x57,0x45,0x06,0x20,0x24,0xc9,0x48,0x0a,0x92,0x96,
2363
0xa4,0x23,0xd5,0x91,0x5a,0x49,0x6d,0xa4,0x76,0x52,0x37,0xa9,0x87,0x64,0x22,0x0d,
2364
0x90,0x86,0x48,0xc3,0xa4,0x11,0xd2,0x28,0x69,0x8c,0x34,0x4e,0x7a,0x44,0x9a,0x20,
2365
0x4d,0x92,0x9e,0x02,0xd3,0x24,0x33,0xc9,0x42,0x9a,0x27,0x2d,0x92,0x5e,0x00,0x4b,
2366
0xa4,0x15,0x12,0x61,0xb7,0xf3,0x6e,0x97,0xdd,0xae,0x80,0xdb,0x6e,0xf7,0xdd,0x1e,
2367
0x80,0xd7,0x6e,0xdf,0xdd,0xe4,0xdd,0x94,0xdd,0xd4,0xdd,0xf4,0xdd,0x8c,0xdd,0xcc,
2368
0xdd,0xc1,0xbb,0x43,0x76,0x87,0xed,0x66,0xed,0xe6,0xec,0x8e,0xdd,0x9d,0xb8,0x3b,
2369
0x69,0x77,0xf2,0xee,0x8c,0xdd,0xbc,0xdd,0x82,0xdd,0xc2,0xdd,0xe2,0xdd,0x85,0xdf,
2370
0x23,0xd9,0x2d,0xdb,0xad,0xd8,0xad,0xd9,0xad,0xdb,0x6d,0xf8,0x09,0xc6,0xdd,0x8d,
2371
0xbb,0xdb,0x77,0x9b,0x76,0x0f,0xef,0x1e,0xdb,0x3d,0xb9,0xdb,0xbc,0x7b,0x71,0xf7,
2372
0xca,0x6e,0xc2,0x1e,0xe2,0x1e,0xef,0x3d,0xe4,0x3d,0x8c,0x3d,0x61,0x7b,0x38,0x7b,
2373
0x62,0xf7,0x24,0xef,0xc9,0xd8,0x23,0xd8,0x23,0xdc,0x23,0xd9,0xa3,0xd9,0x53,0xb7,
2374
0xa7,0x79,0x4f,0xeb,0x9e,0xce,0x3d,0xa6,0x3d,0x03,0x7b,0x86,0xf6,0x0c,0xef,0x19,
2375
0xd9,0x33,0xba,0x67,0x7c,0xcf,0xd4,0x1e,0xf3,0x1e,0xcb,0x9e,0xc5,0x3d,0x2b,0x7b,
2376
0x1c,0xf7,0x12,0xf7,0xba,0xef,0xf5,0xde,0x4b,0xde,0x4b,0xdd,0x4b,0xdf,0xcb,0xd8,
2377
0xcb,0xfc,0x2f,0x04,0xef,0x0d,0xff,0x8b,0xc4,0xec,0x4d,0xfa,0xab,0x38,0xfd,0x0f,
2378
0xc1,0xdd,0x9b,0xb3,0xb7,0xf0,0x17,0x44,0xfe,0x23,0x5a,0x2b,0xd5,0x7f,0x23,0x0d,
2379
0x40,0xcb,0x8f,0xb4,0xee,0xed,0xdc,0xdb,0xb7,0xd7,0xb4,0x77,0x68,0xef,0xfd,0xbf,
2380
0xc8,0x43,0x2b,0x8f,0xad,0x3c,0x05,0xe6,0xfe,0x26,0x16,0x80,0xef,0xfe,0x24,0xc8,
2381
0xd7,0xde,0xd7,0xd9,0xd7,0xcd,0xd7,0xcb,0xca,0x5e,0x5f,0x8a,0x95,0x40,0xdf,0x03,
2382
0x7f,0x40,0xb8,0x6f,0x8c,0x95,0x24,0xdf,0xd3,0x56,0xb8,0xbe,0x39,0x3f,0x0b,0x85,
2383
0xbe,0x72,0x5f,0xad,0x6f,0xf5,0x3f,0x9d,0x06,0xdf,0x16,0xdf,0x0e,0xdf,0xeb,0x7f,
2384
0x40,0xbf,0xef,0x5d,0xdf,0xfb,0xbe,0x0f,0xff,0xc7,0x78,0xe4,0xfb,0x78,0x8d,0x35,
2385
0x7e,0x21,0x26,0x7d,0xa7,0x7c,0xa7,0x7d,0xcd,0xbe,0x16,0xdf,0x79,0xdf,0x45,0xdf,
2386
0x25,0xdf,0x65,0xdf,0x15,0x5f,0xbb,0x7d,0x8e,0xfb,0x88,0xfb,0x3c,0xf7,0x91,0xf6,
2387
0x91,0xf7,0xd1,0xf7,0x05,0xef,0x0b,0xdb,0xc7,0xd9,0x97,0xb8,0x2f,0x6d,0x9f,0x60,
2388
0x9f,0x64,0x9f,0x66,0x5f,0xcd,0xbe,0xe6,0x7d,0x9d,0xfb,0x4c,0xfb,0x86,0xf7,0x8d,
2389
0xef,0x9b,0xde,0xb7,0xb8,0xcf,0xe6,0x0d,0x97,0x37,0xbc,0xdf,0xa0,0xbe,0x11,0xf2,
2390
0x46,0xec,0x1b,0x69,0x6f,0x08,0xdf,0x90,0xbc,0xa1,0x78,0x43,0xf7,0x46,0xcd,0x1b,
2391
0x8d,0x6f,0xb4,0xbe,0xd1,0xf9,0x46,0xcf,0x1b,0x03,0x6f,0x8c,0xbc,0x31,0xfe,0xc6,
2392
0xd4,0x1b,0x96,0x37,0x96,0xde,0xb0,0xf1,0x73,0xf4,0x73,0xf7,0x23,0xf9,0x51,0xfd,
2393
0x82,0xfd,0x58,0x7e,0x89,0x7e,0x69,0x7e,0x02,0x3f,0x89,0x9f,0xc6,0xaf,0xc6,0xaf,
2394
0xd9,0xaf,0xd3,0xcf,0xe4,0x37,0xec,0x37,0xe6,0x37,0xe9,0x67,0xf6,0x5b,0xf4,0x5b,
2395
0xf1,0x23,0x90,0x89,0x64,0x6f,0x32,0x99,0xcc,0x20,0x87,0x91,0x63,0xc9,0xa9,0x64,
2396
0x1e,0x59,0x4c,0x96,0x90,0x65,0x64,0x05,0x59,0x43,0xd6,0x91,0x8d,0xe4,0x1a,0x72,
2397
0x1d,0xb9,0x91,0xdc,0x4c,0x6e,0x25,0xb7,0x93,0x3b,0xc9,0xdd,0xe4,0x1e,0xb2,0x89,
2398
0x3c,0x40,0x1e,0x22,0x0f,0x93,0x47,0xc8,0xa3,0xe4,0x31,0xf2,0x38,0x79,0x82,0x3c,
2399
0x49,0x9e,0x22,0x4f,0x93,0xcd,0x64,0x0b,0x79,0x9e,0xbc,0x48,0x5e,0x22,0x2f,0x93,
2400
0x57,0xc8,0x36,0xfe,0x76,0xfe,0x04,0x7f,0x47,0x7f,0x17,0x7f,0xa2,0xbf,0xbb,0xbf,
2401
0xa7,0xbf,0xb7,0x3f,0xc9,0xdf,0xd7,0x9f,0xec,0x4f,0xf5,0xa7,0xfb,0x33,0xfc,0x83,
2402
0xfd,0x43,0xfc,0xc3,0xfc,0xc3,0x7f,0x06,0x58,0xfe,0x49,0xff,0x52,0x24,0xfb,0x67,
2403
0xf8,0x0b,0xfc,0x0b,0xff,0x85,0x90,0xaf,0xf1,0x0f,0xa1,0xf0,0xd7,0xf8,0x6b,0xd7,
2404
0xf8,0x97,0x47,0xe7,0x6f,0x58,0x63,0x8d,0x7f,0x22,0x46,0xff,0xea,0x5f,0x05,0x35,
2405
0xfe,0xb5,0x7f,0x86,0x3a,0xa0,0xd1,0xbf,0xd9,0xbf,0xd5,0xbf,0xdd,0xbf,0xd3,0xbf,
2406
0xdb,0xbf,0xc7,0xdf,0xe4,0x3f,0xe0,0x3f,0xe4,0x3f,0xec,0x3f,0xe2,0x3f,0xea,0x3f,
2407
0xe6,0x3f,0xee,0x3f,0xe1,0x3f,0xe9,0x3f,0xe5,0x3f,0xed,0x6f,0xf6,0xb7,0xf8,0xcf,
2408
0xfb,0x2f,0xfa,0x2f,0xf9,0x2f,0xfb,0xaf,0xf8,0xdb,0x04,0xd8,0x05,0x10,0x02,0x1c,
2409
0x03,0x5c,0x02,0x88,0x01,0xee,0x01,0x9e,0x01,0xde,0x01,0xa4,0x00,0xdf,0x00,0x72,
2410
0x00,0x35,0x80,0x1e,0xc0,0x08,0x08,0x0e,0x08,0x09,0x08,0x0b,0x60,0x05,0x70,0x02,
2411
0x62,0x03,0x12,0x03,0x92,0x03,0x52,0x03,0xd2,0x02,0x32,0x02,0x78,0x01,0x82,0x00,
2412
0x61,0x80,0x38,0x40,0x12,0x20,0x0b,0x50,0x04,0x68,0x02,0x74,0x01,0xc6,0x80,0x9a,
2413
0x80,0xba,0x80,0xc6,0x80,0xe6,0x80,0xd6,0x80,0xf6,0x80,0xce,0x80,0xee,0x80,0x9e,
2414
0x00,0x53,0xc0,0x40,0xc0,0x50,0xc0,0x70,0xc0,0x48,0xc0,0x68,0xc0,0x58,0xc0,0x78,
2415
0xc0,0x44,0xc0,0x64,0xc0,0x54,0xc0,0x74,0x80,0x39,0xc0,0x12,0x30,0x1f,0xb0,0x18,
2416
0xb0,0x14,0xb0,0x1c,0xb0,0x12,0x60,0x43,0xb1,0xa3,0x10,0x28,0x8e,0x14,0x17,0x0a,
2417
0x91,0xe2,0x4e,0xf1,0xa4,0x78,0x53,0x48,0xf0,0xa2,0x47,0xa6,0x50,0x29,0x74,0x0a,
2418
0x83,0x12,0x4c,0x09,0xa1,0x84,0x51,0x58,0x14,0x0e,0x25,0x96,0x92,0x48,0x49,0xa6,
2419
0xa4,0x52,0xd2,0x28,0x19,0x14,0x1e,0x45,0x40,0x11,0x52,0xc4,0x14,0x09,0x45,0x46,
2420
0x51,0x50,0x34,0x14,0x1d,0xc5,0x48,0xa9,0xa1,0xd4,0x51,0x1a,0x29,0xcd,0x94,0x56,
2421
0x4a,0x3b,0xa5,0x93,0xd2,0x4d,0xe9,0xa1,0x98,0x28,0x03,0x94,0x21,0xca,0x30,0x65,
2422
0x84,0x32,0x4a,0x19,0xa3,0x8c,0x53,0x26,0x28,0x93,0x94,0x29,0xca,0x34,0xc5,0x4c,
2423
0xb1,0x50,0xe6,0x29,0x8b,0x94,0x25,0xca,0x32,0x65,0x85,0x62,0x43,0xb5,0xa3,0x12,
2424
0xa8,0x8e,0x54,0x17,0x2a,0x91,0xea,0x4e,0xf5,0xa4,0x7a,0x53,0x49,0x54,0x5f,0x2a,
2425
0x99,0x4a,0xa5,0xd2,0xa9,0x0c,0x6a,0x30,0x35,0x84,0x1a,0x46,0x65,0x51,0x39,0xd4,
2426
0x58,0x6a,0x22,0x35,0x99,0x9a,0x4a,0x4d,0xa3,0x66,0x50,0x79,0x54,0x01,0x55,0x48,
2427
0x15,0x53,0x25,0x54,0x19,0x55,0x41,0xd5,0x50,0x75,0x54,0x23,0xb5,0x86,0x5a,0x47,
2428
0x6d,0xa4,0x36,0x53,0x5b,0xa9,0xed,0xd4,0x4e,0x6a,0x37,0xb5,0x87,0x6a,0xa2,0x0e,
2429
0x50,0x87,0xa8,0xc3,0xd4,0x11,0xea,0x28,0x75,0x8c,0x3a,0x4e,0x9d,0xa0,0x4e,0x52,
2430
0xa7,0xa8,0xd3,0x54,0x33,0xd5,0x42,0x7d,0xfe,0x4f,0x60,0x1e,0x58,0xf8,0xc5,0x58,
2431
0xa4,0xbe,0xa0,0x2e,0x51,0x97,0xa9,0x2b,0x54,0xf4,0xbb,0xbf,0x8c,0x3d,0xe0,0x0c,
2432
0xb8,0x01,0x5e,0xc0,0x5e,0x80,0x02,0x04,0x02,0x07,0x80,0x70,0x20,0x06,0x48,0x02,
2433
0x4e,0x5b,0xe1,0x02,0x39,0x40,0xe1,0x1f,0x20,0xff,0x9d,0x16,0xa8,0xfe,0x5d,0x03,
2434
0xd0,0xf2,0xbb,0x0e,0xe0,0xfa,0xef,0xfa,0x81,0xbb,0xbf,0xbb,0xff,0x37,0xf1,0xf0,
2435
0x27,0x8c,0xff,0x6e,0xf2,0x77,0x4f,0x01,0xcb,0xef,0x16,0xfe,0x2c,0xdf,0x01,0xe8,
2436
0x4d,0xf4,0xa6,0x3d,0xe0,0x0c,0xb8,0x01,0x5e,0xc0,0x5e,0x80,0x02,0x04,0x02,0x07,
2437
0x80,0x70,0x20,0xc6,0x4a,0x12,0x70,0x1a,0xe0,0xfe,0x01,0x39,0x6f,0x16,0x02,0xf2,
2438
0x37,0xb5,0x40,0xf5,0x9b,0x0d,0x40,0xcb,0x9b,0x1d,0xc0,0xf5,0x37,0xfb,0xff,0x26,
2439
0xee,0x5a,0xb9,0xff,0xe6,0xc3,0x37,0x1f,0xbf,0xf9,0xf4,0x7b,0x2c,0x6f,0x2e,0xfc,
2440
0x02,0x2c,0xbe,0xb9,0xf4,0xe6,0xf2,0x9b,0x2b,0x6f,0xda,0xd0,0xec,0x68,0x04,0x9a,
2441
0x23,0xcd,0x85,0x46,0xa4,0xb9,0xd3,0x3c,0x69,0xde,0x34,0x12,0xcd,0x97,0x46,0xa6,
2442
0x51,0x69,0x74,0x1a,0x83,0x16,0x4c,0x0b,0xa1,0x85,0xd1,0x58,0x34,0x0e,0x2d,0x96,
2443
0x96,0x48,0x4b,0xa6,0xa5,0xd2,0xd2,0x68,0x19,0x34,0x1e,0x4d,0x40,0x13,0xd2,0xc4,
2444
0x34,0x09,0x4d,0x46,0x53,0xd0,0x34,0x34,0x1d,0xcd,0x48,0xab,0xa1,0xd5,0xd1,0x1a,
2445
0x69,0xcd,0xb4,0x56,0x5a,0x3b,0xad,0x93,0xd6,0x4d,0xeb,0xa1,0x99,0x68,0x03,0xb4,
2446
0x21,0xda,0x30,0x6d,0x84,0x36,0x4a,0x1b,0xa3,0x8d,0xd3,0x26,0x68,0x93,0xb4,0x29,
2447
0xda,0x34,0xcd,0x4c,0xb3,0xd0,0xe6,0x69,0x8b,0xb4,0x25,0xda,0x32,0x6d,0x85,0x66,
2448
0x43,0xb7,0xa3,0x13,0xe8,0x8e,0x74,0x17,0x3a,0x91,0xee,0x4e,0xf7,0xa4,0x7b,0xd3,
2449
0x49,0x74,0x5f,0x3a,0x99,0x4e,0xa5,0xd3,0xe9,0x0c,0x7a,0x30,0x3d,0x84,0x1e,0x46,
2450
0x67,0xd1,0x39,0xf4,0x58,0x7a,0x22,0x3d,0x99,0x9e,0x4a,0x4f,0xa3,0x67,0xd0,0xb9,
2451
0x56,0x78,0x74,0x01,0x5d,0x48,0x17,0xd3,0x25,0x74,0x19,0x5d,0x41,0xd7,0xd0,0x75,
2452
0x74,0x23,0xbd,0x86,0x5e,0x47,0x6f,0xa4,0x37,0xd3,0x5b,0x7e,0xe5,0xb4,0x02,0xdd,
2453
0xf4,0x01,0xfa,0x08,0x7d,0x9c,0x3e,0x45,0xb7,0xd0,0x97,0xe8,0x36,0x6f,0x39,0xbe,
2454
0xe5,0xfe,0x16,0xe9,0x2d,0xea,0x5b,0xc1,0x6f,0xb1,0xde,0x4a,0x7e,0x8b,0xf7,0x96,
2455
0xe4,0x2d,0xdd,0x5b,0x8d,0x6f,0x75,0xbe,0x35,0xf0,0xd6,0xe8,0x5b,0x93,0x6f,0x59,
2456
0xde,0x5a,0x7e,0x8b,0xf0,0xb6,0xfb,0xdb,0xbe,0x6f,0x33,0xde,0x4e,0x7c,0x9b,0xff,
2457
0xb6,0xe0,0x6d,0xc9,0xdb,0x9a,0xb7,0x6b,0xde,0x6e,0x7e,0xbb,0xf3,0x6d,0xd3,0xdb,
2458
0xc3,0x6f,0x8f,0xbd,0x3d,0xf9,0xb6,0xf9,0xed,0xc5,0xb7,0x57,0xde,0x26,0x04,0x12,
2459
0x03,0xbd,0x03,0xc9,0x81,0x8c,0xc0,0xb0,0xc0,0xd8,0xc0,0xd4,0x40,0x5e,0xa0,0x38,
2460
0x50,0x11,0x68,0x0c,0x6c,0x0c,0x6c,0x0f,0xec,0x09,0x1c,0x0a,0x1c,0x0d,0x9c,0x08,
2461
0x9c,0x0e,0x9c,0x0f,0x5c,0x0e,0xb4,0x63,0xb8,0x30,0x3c,0x19,0xde,0x0c,0x12,0xc3,
2462
0x97,0xe1,0xf7,0x47,0x90,0x19,0x0c,0x46,0x08,0x83,0xc5,0x88,0x65,0x24,0x33,0xd2,
2463
0x18,0x3c,0x86,0x90,0x21,0x61,0x28,0x18,0x3a,0x46,0x0d,0xa3,0x91,0xd1,0xca,0xe8,
2464
0x64,0xf4,0x30,0x4c,0x8c,0x01,0xc6,0x10,0x63,0x98,0x31,0xc2,0x18,0x65,0x8c,0x31,
2465
0xc6,0x19,0x13,0x8c,0x49,0xc6,0x14,0x63,0x9a,0x61,0x66,0x58,0x18,0x8b,0x8c,0x65,
2466
0x86,0x4d,0x10,0x21,0xc8,0x25,0xc8,0x3d,0xc8,0x3b,0xc8,0x37,0x88,0x1a,0xc4,0x08,
2467
0x0a,0x09,0x62,0x05,0xc5,0x06,0x25,0x07,0x09,0x82,0x64,0x41,0xea,0x20,0x4d,0x90,
2468
0x2e,0xc8,0x18,0x54,0x13,0x54,0x17,0xd4,0x18,0xd4,0x1c,0xd4,0x1a,0xd4,0x1e,0xd4,
2469
0x19,0xd4,0x1d,0xd4,0x13,0x64,0x0a,0x1a,0x08,0x1a,0x0a,0x1a,0x0e,0x1a,0x09,0x1a,
2470
0x0d,0x1a,0x0b,0x1a,0x0f,0x9a,0x08,0x9a,0x0c,0x9a,0x0a,0x9a,0x0e,0x32,0x07,0x59,
2471
0x82,0xe6,0x83,0x16,0x83,0x96,0x82,0x96,0x83,0x56,0x82,0x6c,0xf6,0xdb,0xed,0x27,
2472
0xec,0x77,0xdc,0xef,0xb2,0x9f,0xb8,0xdf,0x7d,0xbf,0xe7,0x7e,0xef,0xfd,0xa4,0xfd,
2473
0xbe,0xfb,0xc9,0xfb,0xa9,0xfb,0xe9,0xfb,0x19,0xfb,0x83,0xf7,0x87,0xec,0x0f,0xdb,
2474
0xcf,0xda,0x1f,0xbb,0x3f,0x79,0x7f,0xda,0x7e,0xde,0x7e,0xe1,0x7e,0xc9,0x7e,0xc5,
2475
0x7e,0xdd,0xfe,0x9a,0xfd,0x8d,0xfb,0x5b,0xf7,0x77,0xee,0xef,0xd9,0x3f,0xb0,0x7f,
2476
0x78,0xff,0xe8,0xfe,0xf1,0xfd,0x93,0xfb,0xa7,0xf7,0x5b,0xf6,0x2f,0xee,0x5f,0xde,
2477
0x6f,0xc3,0x24,0x30,0x89,0x4c,0x6f,0x26,0x99,0x49,0x67,0x86,0x30,0x59,0xcc,0x44,
2478
0x66,0x32,0x33,0x95,0x99,0xc6,0xcc,0x60,0xf2,0x98,0x02,0xa6,0x90,0x29,0x66,0x4a,
2479
0x98,0x32,0xa6,0x82,0xa9,0x61,0xea,0x98,0x46,0x66,0x0d,0xb3,0x8e,0xd9,0xc8,0x6c,
2480
0x66,0xb6,0x32,0xdb,0x99,0x9d,0xcc,0x6e,0x66,0x0f,0xd3,0xc4,0x1c,0x60,0x0e,0x31,
2481
0x87,0x99,0x23,0xcc,0x51,0xe6,0x18,0x73,0x9c,0x39,0xc1,0x9c,0x64,0x4e,0x31,0xa7,
2482
0x99,0x66,0xa6,0x85,0x39,0xcf,0x5c,0x64,0x2e,0x31,0x97,0x99,0x2b,0x4c,0x9b,0x60,
2483
0xbb,0x60,0x42,0xb0,0x63,0xb0,0x4b,0xb0,0x3b,0x40,0x0e,0x0e,0x0e,0x8e,0x0d,0x4e,
2484
0x0d,0x16,0x06,0xcb,0x82,0x75,0xc1,0xad,0xc1,0x3d,0xc1,0x43,0xc1,0xa3,0xc1,0x13,
2485
0xc1,0xe6,0xe0,0xa5,0x60,0xbb,0x77,0x88,0xef,0x90,0xde,0xa1,0xbf,0x13,0xf6,0x4e,
2486
0xea,0x3b,0x19,0xef,0xc8,0xde,0xa9,0x7b,0xa7,0xf3,0x9d,0x81,0x77,0xc6,0xdf,0xb1,
2487
0xbc,0xb3,0xfc,0x8e,0xdd,0xbb,0x2e,0xef,0x7a,0xbf,0x4b,0x7d,0x37,0xec,0xdd,0xe4,
2488
0x77,0x33,0xde,0x15,0xbe,0xab,0x78,0xd7,0xf8,0x6e,0xe3,0xbb,0xad,0xef,0x76,0xbe,
2489
0x6b,0x7a,0x77,0xf8,0xdd,0xc9,0x77,0x2d,0xef,0xae,0xbc,0x4b,0x3c,0x40,0x3a,0x40,
2490
0x3d,0x10,0x7c,0x20,0xf1,0x40,0xc6,0x01,0xd9,0x01,0xdd,0x81,0xe6,0x03,0x9d,0x07,
2491
0x06,0x0e,0x8c,0x1c,0x98,0x38,0x60,0x39,0xb0,0x7c,0xc0,0x31,0xc4,0x33,0x84,0x14,
2492
0xc2,0x08,0x09,0x0b,0x89,0x0d,0x49,0x0b,0x11,0x84,0x48,0x42,0x34,0x21,0x8d,0x21,
2493
0x9d,0x21,0x3d,0x21,0xa3,0x21,0x13,0x21,0x96,0x90,0xe5,0x10,0xc2,0x41,0xe2,0x41,
2494
0xef,0x83,0xd4,0x83,0x8c,0x83,0xac,0x83,0xa9,0x07,0x33,0x0e,0xca,0x0e,0xea,0x0e,
2495
0xd6,0x1c,0x6c,0x3c,0xd8,0x7a,0xb0,0xf3,0x60,0xcf,0xc1,0x81,0x83,0xc3,0x07,0x47,
2496
0x0f,0x8e,0x1f,0x9c,0x3c,0x68,0x3e,0xb8,0x78,0x70,0xe5,0x20,0xe1,0x10,0xf1,0x90,
2497
0xf7,0x21,0xf2,0x21,0xc6,0xa1,0xb0,0x43,0xb1,0x87,0x52,0x0f,0xf1,0x0e,0x89,0x0f,
2498
0x29,0x0e,0x19,0x0f,0x35,0x1e,0x6a,0x3d,0xd4,0x79,0xc8,0x74,0x68,0xe8,0xd0,0xc8,
2499
0xa1,0xb1,0x43,0x93,0x87,0xcc,0x87,0xe6,0x0f,0x2d,0x1d,0x5a,0x39,0x64,0x17,0xea,
2500
0x18,0xea,0x19,0x4a,0x0a,0x25,0x87,0xd2,0x43,0x83,0x43,0xc3,0x42,0x39,0xa1,0x89,
2501
0xa1,0xa9,0xa1,0xbc,0x50,0x49,0xa8,0x22,0x54,0x17,0x5a,0x13,0xda,0x18,0xda,0x1a,
2502
0xda,0x19,0xda,0x13,0x3a,0x14,0x3a,0x1a,0x3a,0x11,0x3a,0x1d,0x6a,0x09,0x5d,0x0c,
2503
0x5d,0x0e,0xb5,0x09,0x23,0x84,0xb9,0x84,0xb9,0x87,0x79,0x87,0xf9,0x86,0x51,0xc3,
2504
0x82,0xc3,0x58,0x61,0xb1,0x61,0xa9,0x61,0xbc,0x30,0x71,0x98,0x2c,0x4c,0x17,0x56,
2505
0x17,0xd6,0x1e,0xd6,0x1d,0x36,0x10,0x36,0x12,0x36,0x1e,0x36,0x15,0xb6,0x18,0x46,
2506
0x38,0xec,0x72,0xd8,0xfd,0xb0,0xf7,0x61,0xdf,0xc3,0xd4,0xc3,0x8c,0xc3,0x21,0x87,
2507
0x59,0x87,0x63,0x0f,0x27,0x1f,0x4e,0x3b,0xcc,0x3b,0x2c,0x3c,0x2c,0x39,0xac,0x38,
2508
0xac,0x3b,0x5c,0x73,0xb8,0xf1,0x70,0xe7,0xe1,0x9e,0xc3,0x03,0x87,0x87,0x0f,0x8f,
2509
0x1f,0x9e,0x3a,0x6c,0x3e,0x3c,0x7f,0x78,0xe9,0xf0,0xca,0x61,0xbb,0x23,0x8e,0x47,
2510
0x88,0x47,0x3c,0x8f,0x90,0x8e,0x90,0x8f,0x30,0x8e,0x84,0x1c,0x61,0x1d,0x49,0x3c,
2511
0x92,0x76,0x84,0x77,0x44,0x72,0x44,0x73,0xc4,0x78,0xa4,0xee,0x48,0xf3,0x91,0xf6,
2512
0x23,0x3d,0x47,0x86,0x8e,0x8c,0x1c,0x19,0x3b,0x32,0x71,0x64,0xea,0x88,0xf9,0xc8,
2513
0xfc,0x91,0xa5,0x23,0x2b,0x47,0xec,0xc2,0x5d,0xc2,0x3d,0xc3,0x7d,0xc3,0xe9,0xe1,
2514
0x21,0xe1,0x9c,0xf0,0xe4,0xf0,0x8c,0x70,0x61,0xb8,0x2c,0x5c,0x17,0x5e,0x17,0xde,
2515
0x1a,0xde,0x1d,0x3e,0x10,0x3e,0x12,0x3e,0x1e,0x3e,0x15,0x6e,0x09,0x5f,0x0a,0xb7,
2516
0x61,0x39,0xb2,0xdc,0xd6,0xf8,0x3b,0x71,0x67,0x79,0xb2,0xbc,0xd6,0xf8,0x15,0xe0,
2517
0xcd,0xf2,0xf9,0x8d,0x43,0x62,0xf9,0xb2,0xc8,0x2c,0x2a,0x8b,0x66,0x85,0xce,0x62,
2518
0xb0,0x98,0xff,0x12,0x04,0xb3,0x42,0x58,0x61,0x2c,0x16,0x8b,0xfd,0x5f,0xe0,0xb0,
2519
0x62,0xd6,0xf8,0x9b,0x48,0x60,0x25,0xb1,0x52,0x58,0xa7,0x59,0xe9,0x2c,0x2e,0x8b,
2520
0xcf,0xca,0x61,0x89,0x58,0x85,0x2c,0x29,0x4b,0xce,0x52,0xb3,0xb4,0x2c,0x03,0xab,
2521
0x9a,0x55,0xcb,0x6a,0x60,0x35,0xb1,0x5a,0x58,0x6d,0xac,0x0e,0x56,0x17,0xeb,0x3a,
2522
0xab,0x8f,0xd5,0xcf,0x1a,0x64,0xdd,0x65,0xdd,0x63,0xdd,0x67,0x3d,0x60,0x3d,0x64,
2523
0x3d,0x62,0x3d,0x66,0x3d,0x61,0x3d,0x65,0xcd,0xb0,0xe6,0x58,0xcf,0x59,0x0b,0xac,
2524
0x17,0xac,0xef,0x58,0x2f,0x59,0x28,0xc2,0x36,0xc2,0x3e,0xc2,0x21,0xc2,0x39,0xc2,
2525
0x35,0xc2,0x2d,0xc2,0x23,0xc2,0x2b,0xc2,0x27,0x62,0x6f,0x84,0x5f,0x04,0x25,0x82,
2526
0x16,0x11,0x18,0xc1,0x8c,0x38,0x10,0x11,0x1a,0x11,0x1e,0xc1,0x8e,0x88,0x89,0x48,
2527
0x88,0x48,0x8a,0x48,0x89,0x38,0x1d,0x91,0x1e,0xc1,0x8d,0xe0,0x47,0xe4,0x44,0x88,
2528
0x22,0x0a,0x23,0xa4,0x11,0xf2,0x08,0x75,0x84,0x36,0xc2,0x10,0x51,0x1d,0x51,0x1b,
2529
0xd1,0x10,0xd1,0x14,0xd1,0x12,0xd1,0x16,0xd1,0x11,0xd1,0x15,0x71,0x3d,0xa2,0x2f,
2530
0xa2,0x3f,0x62,0x30,0xe2,0x6e,0xc4,0xbd,0x88,0xfb,0x11,0x0f,0x22,0x1e,0x46,0x3c,
2531
0x8a,0x78,0x1c,0xf1,0x24,0xe2,0x69,0xc4,0x4c,0xc4,0x5c,0xc4,0xf3,0x88,0x85,0x88,
2532
0x17,0x11,0xdf,0x45,0xbc,0x8c,0x40,0x91,0xb6,0x91,0xf6,0x91,0x0e,0x91,0xce,0x91,
2533
0xae,0x91,0x6e,0x91,0x1e,0x91,0x5e,0x91,0x3e,0x91,0x7b,0x23,0xfd,0x22,0x29,0x91,
2534
0xb4,0xc8,0xc0,0x48,0x66,0xe4,0x81,0xc8,0xd0,0xc8,0xf0,0x48,0x76,0x64,0x4c,0x64,
2535
0x42,0x64,0x52,0x64,0x4a,0xe4,0xe9,0xc8,0xf4,0x48,0x6e,0x24,0x3f,0x32,0x27,0x52,
2536
0x14,0x59,0x18,0x29,0x8d,0x94,0x47,0xaa,0x23,0xb5,0x91,0x86,0xc8,0xea,0xc8,0xda,
2537
0xc8,0x86,0xc8,0xa6,0xc8,0x96,0xc8,0xb6,0xc8,0x8e,0xc8,0xae,0xc8,0xeb,0x91,0x7d,
2538
0x91,0xfd,0x91,0x83,0x91,0x77,0x23,0xef,0x45,0xde,0x8f,0x7c,0x10,0xf9,0x30,0xf2,
2539
0x51,0xe4,0xe3,0xc8,0x27,0x91,0x4f,0x23,0x67,0x22,0xe7,0x22,0x9f,0x47,0x2e,0x44,
2540
0xbe,0x88,0xfc,0x2e,0xf2,0x65,0x24,0x62,0xdb,0xb2,0xed,0xd9,0x0e,0x6c,0x67,0xb6,
2541
0x2b,0xdb,0x8d,0xed,0xc1,0xf6,0x62,0xfb,0xb0,0xf7,0xb2,0xfd,0xd8,0x14,0x36,0x8d,
2542
0x1d,0xc8,0x66,0xb2,0x0f,0xb0,0x43,0xd9,0xe1,0x6c,0x36,0x3b,0x86,0x9d,0xc0,0x4e,
2543
0x62,0xa7,0xb0,0x4f,0xb3,0xd3,0xd9,0x5c,0x36,0x9f,0x9d,0xc3,0x16,0xb1,0x0b,0xd9,
2544
0x52,0xb6,0x9c,0xad,0x66,0x6b,0xd9,0x06,0x76,0x35,0xbb,0x96,0xdd,0xc0,0x6e,0x62,
2545
0xb7,0xb0,0xdb,0xd8,0x1d,0xec,0x2e,0xf6,0x75,0x76,0x1f,0xbb,0x9f,0x3d,0xc8,0xbe,
2546
0xcb,0xbe,0xc7,0xbe,0xcf,0x7e,0xc0,0x7e,0xc8,0x7e,0xc4,0x7e,0xcc,0x7e,0xc2,0x7e,
2547
0xca,0x9e,0x61,0xcf,0xb1,0x9f,0xb3,0x17,0xd8,0x2f,0xd8,0xdf,0xb1,0x5f,0xb2,0x11,
2548
0xc7,0x96,0x63,0xcf,0x71,0xe0,0x38,0x73,0x5c,0x39,0x6e,0x1c,0x0f,0x8e,0x17,0xc7,
2549
0x87,0xb3,0x97,0xe3,0xc7,0xa1,0x70,0x68,0x9c,0x40,0x0e,0x93,0x73,0x80,0x13,0xca,
2550
0x09,0xe7,0xb0,0x39,0x31,0x40,0x02,0x27,0x89,0x93,0xc2,0x39,0xcd,0x49,0xe7,0x70,
2551
0x39,0x7c,0x4e,0x0e,0x47,0xc4,0x29,0xe4,0x48,0x39,0x72,0x8e,0x9a,0xa3,0xb5,0x62,
2552
0x00,0xaa,0xad,0xd4,0x72,0x1a,0x38,0x4d,0x9c,0x16,0x4e,0x1b,0xa7,0x83,0xd3,0xc5,
2553
0xb9,0xce,0xe9,0xe3,0xf4,0x03,0x83,0xc0,0x5d,0x2b,0xf7,0x38,0xf7,0xbf,0xe7,0x01,
2554
0xe7,0x21,0xe7,0x11,0xe7,0x31,0xe7,0x09,0xe7,0x29,0x67,0x86,0x33,0xc7,0x79,0xce,
2555
0x59,0xe0,0xbc,0xe0,0x7c,0xc7,0x79,0xc9,0x41,0x51,0xb6,0x51,0xf6,0x51,0x0e,0x51,
2556
0xce,0x51,0xae,0x51,0x6e,0x51,0x1e,0x51,0x5e,0x51,0x3e,0x51,0x7b,0xa3,0xfc,0xa2,
2557
0x28,0x51,0xb4,0xa8,0xc0,0x28,0x66,0xd4,0x81,0xa8,0xd0,0xa8,0xf0,0x28,0x76,0x54,
2558
0x4c,0x54,0x42,0x54,0x52,0x54,0x4a,0xd4,0xe9,0xa8,0xf4,0x28,0x6e,0x14,0x3f,0x2a,
2559
0x27,0x4a,0x14,0x55,0x18,0x25,0x8d,0x92,0x47,0xa9,0xa3,0xb4,0x51,0x86,0xa8,0xea,
2560
0xa8,0xda,0xa8,0x86,0xa8,0xa6,0xa8,0x96,0xa8,0xb6,0xa8,0x8e,0xa8,0xae,0xa8,0xeb,
2561
0x51,0x7d,0x51,0xfd,0x51,0x83,0x51,0x77,0xa3,0xee,0x45,0xdd,0x8f,0x7a,0x10,0xf5,
2562
0x30,0xea,0x51,0xd4,0x63,0x2b,0x4f,0xa2,0x9e,0x46,0xcd,0x44,0xcd,0x45,0x3d,0x8f,
2563
0x5a,0x88,0x7a,0x11,0xf5,0x5d,0xd4,0xcb,0x28,0x14,0x6d,0x1b,0x6d,0x1f,0xed,0x10,
2564
0xed,0x1c,0xed,0x1a,0xed,0x16,0xed,0x11,0xed,0x15,0xed,0x13,0xbd,0x37,0xda,0x2f,
2565
0x9a,0x12,0x4d,0x8b,0x0e,0x8c,0x66,0x46,0x1f,0x88,0x0e,0x8d,0x0e,0x8f,0x66,0x47,
2566
0xc7,0x44,0x27,0x44,0x27,0x45,0xa7,0x44,0x9f,0x8e,0x4e,0x8f,0xe6,0x46,0xf3,0xa3,
2567
0x73,0xa2,0x45,0xd1,0x85,0xd1,0xd2,0x68,0x79,0xb4,0x3a,0x5a,0x1b,0x6d,0x88,0xae,
2568
0x8e,0xae,0x8d,0x6e,0x88,0x6e,0x8a,0x6e,0x89,0x6e,0x8b,0xee,0x88,0xee,0x8a,0xbe,
2569
0x1e,0xdd,0x17,0xdd,0x1f,0x3d,0x18,0x7d,0x37,0xfa,0x5e,0xf4,0xfd,0xe8,0x07,0xd1,
2570
0x0f,0xa3,0x1f,0x45,0x3f,0x8e,0x7e,0x12,0xfd,0x34,0x7a,0x26,0x7a,0x2e,0xfa,0x79,
2571
0xf4,0x42,0xf4,0x8b,0xe8,0xef,0xa2,0x5f,0x46,0xa3,0x18,0xdb,0x18,0xfb,0x18,0x87,
2572
0x18,0xe7,0x18,0xd7,0x18,0xb7,0x18,0x8f,0x18,0xaf,0x18,0x9f,0x98,0xbd,0x31,0x7e,
2573
0x31,0x94,0x18,0x5a,0x4c,0x60,0x0c,0x33,0xe6,0x40,0x4c,0x68,0x4c,0x78,0x0c,0x3b,
2574
0x26,0x26,0x26,0x21,0x26,0x29,0x26,0x25,0xe6,0x74,0x4c,0x7a,0x0c,0x37,0x86,0x1f,
2575
0x93,0x13,0x23,0x8a,0x29,0x8c,0x91,0xc6,0xc8,0x7f,0x46,0x14,0x80,0x2e,0xa6,0x26,
2576
0xa6,0x31,0xa6,0x3d,0xa6,0x27,0x66,0x20,0xe6,0xee,0x9f,0x61,0x38,0x66,0x34,0x66,
2577
0x3c,0x66,0x32,0x66,0x3a,0x66,0xee,0x27,0x2c,0x00,0xcb,0x31,0x2b,0x31,0x36,0xb1,
2578
0x76,0xb1,0x84,0x58,0xc7,0x58,0x97,0x58,0x62,0xac,0x7b,0xac,0x67,0xac,0x57,0xec,
2579
0xde,0x58,0x4a,0x2c,0x33,0x36,0x3c,0x36,0x26,0x36,0x29,0xf6,0x74,0x2c,0x37,0x36,
2580
0x27,0xb6,0x30,0x56,0x1e,0xab,0x8d,0xad,0x06,0x1a,0x62,0x5b,0x62,0x3b,0x62,0xaf,
2581
0xc7,0xf6,0x03,0x77,0x81,0xfb,0xb1,0x0f,0x81,0xc7,0xb1,0x4f,0x81,0xb9,0xd8,0x85,
2582
0xd8,0xef,0x62,0x51,0x9c,0x7d,0x9c,0x73,0x9c,0x5b,0x9c,0x57,0x9c,0x6f,0x1c,0x35,
2583
0x8e,0x1e,0xc7,0x88,0x0b,0x8e,0x0b,0x89,0x0b,0x8b,0x63,0xc5,0x71,0xe2,0x62,0xe3,
2584
0x12,0xe3,0x92,0xe3,0x52,0xe3,0xd2,0xe2,0x32,0xe2,0x78,0x71,0x82,0x38,0x61,0x9c,
2585
0x38,0x4e,0x12,0x27,0x8b,0x53,0xc4,0x69,0xe2,0x74,0x71,0xc6,0xb8,0x9a,0xb8,0xba,
2586
0xb8,0xc6,0xb8,0xe6,0xb8,0xd6,0xb8,0xf6,0xb8,0xce,0xb8,0xee,0xb8,0x9e,0x38,0x53,
2587
0xdc,0x40,0xdc,0x50,0xdc,0x70,0xdc,0x48,0xdc,0x68,0xdc,0x58,0xdc,0x78,0xdc,0x44,
2588
0xdc,0x64,0xdc,0x54,0xdc,0x74,0x9c,0x39,0xce,0x12,0x37,0x1f,0xb7,0x18,0xb7,0x14,
2589
0xb7,0x1c,0xb7,0x12,0x67,0x13,0x6f,0x17,0x4f,0x88,0x77,0x8c,0x77,0x89,0x27,0xc6,
2590
0xbb,0xc7,0x7b,0xc6,0x7b,0xc7,0x93,0xe2,0x7d,0xe3,0xc9,0xf1,0xd4,0x78,0x7a,0x3c,
2591
0x23,0x3e,0x38,0x3e,0x24,0x3e,0x2c,0x9e,0x15,0xcf,0x89,0x8f,0x8d,0x4f,0x8c,0x4f,
2592
0x8e,0x4f,0x8d,0x4f,0x8b,0xcf,0x88,0xe7,0xc5,0x0b,0xe2,0x85,0xf1,0xe2,0x78,0x49,
2593
0xbc,0x2c,0x5e,0x11,0xaf,0x8b,0xaf,0x89,0xaf,0x8b,0x6f,0x8c,0x6f,0x8e,0x6f,0x8d,
2594
0x6f,0x8f,0xef,0x8c,0xef,0x8e,0xef,0x89,0x37,0xc5,0x0f,0xc4,0x0f,0xc7,0xdf,0xff,
2595
0x87,0x19,0x8d,0x1f,0x8b,0x1f,0x8f,0x9f,0x88,0x9f,0x8c,0x9f,0x8a,0x9f,0x8e,0x37,
2596
0xc7,0x5b,0xe2,0xe7,0xe3,0x17,0xe3,0x97,0xe3,0x57,0xe2,0x6d,0x12,0xec,0x12,0x08,
2597
0x09,0x8e,0x09,0x2e,0x09,0xc4,0x04,0xf7,0x04,0xcf,0x04,0xef,0x04,0x52,0x82,0x6f,
2598
0x02,0x3d,0x21,0x24,0x81,0x93,0x90,0x9c,0x90,0x91,0x20,0x4c,0x90,0x25,0xe8,0x12,
2599
0xea,0x12,0x5a,0x13,0xba,0x13,0x06,0x12,0x46,0x12,0xc6,0x13,0xa6,0x12,0x2c,0x09,
2600
0x4b,0x09,0x36,0x89,0x76,0x89,0x84,0x44,0xc7,0x44,0x17,0xc0,0x33,0xd1,0x37,0x91,
2601
0x9e,0x18,0x92,0xc8,0x49,0x4c,0x4c,0x4c,0x4d,0xcc,0x48,0x14,0x24,0x8a,0x13,0x65,
2602
0x89,0x9a,0x44,0x63,0x62,0x5d,0x62,0x73,0x62,0x7b,0x62,0x77,0xa2,0x29,0x71,0x28,
2603
0x71,0x24,0x71,0x2c,0x71,0x22,0x71,0x2a,0xd1,0x9c,0x38,0x9f,0xb8,0x94,0xb8,0x92,
2604
0x68,0x77,0xd4,0xf1,0x28,0xf1,0xa8,0xe7,0x51,0xd2,0x51,0xf2,0x51,0xfa,0xd1,0xe0,
2605
0xa3,0x61,0x47,0x39,0x47,0x13,0x8f,0xa6,0x1e,0xcd,0x38,0x2a,0x38,0x2a,0x3e,0x2a,
2606
0x3b,0xaa,0x39,0x6a,0x3c,0x5a,0x77,0xb4,0xf9,0x68,0xfb,0xd1,0xee,0xa3,0xa6,0xa3,
2607
0x43,0x47,0x47,0x8e,0x8e,0x1d,0x9d,0x38,0x3a,0x75,0xd4,0x7c,0x74,0xfe,0xe8,0xd2,
2608
0xd1,0x95,0xa3,0x76,0xc7,0x1c,0x8f,0x11,0x8f,0x79,0x1e,0x23,0x1d,0x23,0x1f,0xa3,
2609
0x1f,0x0b,0x3e,0x16,0x76,0x8c,0x73,0x2c,0xf1,0x58,0xea,0xb1,0x8c,0x63,0x82,0x63,
2610
0xe2,0x63,0xb2,0x63,0x9a,0x63,0xc6,0x63,0x75,0xc7,0x9a,0x8f,0xb5,0x1f,0xeb,0x3e,
2611
0x66,0x3a,0x36,0x74,0x6c,0xe4,0xd8,0xd8,0xb1,0x89,0x63,0x53,0xc7,0xcc,0xc7,0xe6,
2612
0x8f,0x2d,0x1d,0x5b,0x39,0x66,0x97,0xe4,0x98,0x44,0x4c,0xf2,0x4e,0x22,0x27,0x31,
2613
0x92,0xc2,0x92,0x62,0x93,0x52,0x93,0x78,0x49,0xe2,0x24,0x45,0x92,0x31,0xa9,0x31,
2614
0xa9,0x3d,0xa9,0x3b,0xc9,0x94,0x34,0x94,0x34,0x92,0x34,0x96,0x34,0x91,0x34,0x95,
2615
0x64,0x4e,0x9a,0x4f,0x5a,0x4a,0x5a,0x49,0xb2,0x4b,0x76,0x4c,0x26,0x26,0x7b,0x26,
2616
0x93,0x92,0xc9,0xc9,0xf4,0xe4,0xe0,0xe4,0xb0,0x64,0x4e,0x72,0x62,0x72,0x6a,0x72,
2617
0x46,0xb2,0x20,0x59,0x9c,0x2c,0x4b,0xd6,0x24,0x1b,0x93,0xeb,0x92,0x9b,0x93,0xdb,
2618
0x93,0xbb,0x93,0x4d,0xc9,0x43,0xc9,0x23,0xc9,0x63,0xc9,0x13,0xc9,0x53,0xc9,0xe6,
2619
0xe4,0xf9,0xe4,0xa5,0xe4,0x95,0x64,0xbb,0xe3,0x8e,0xc7,0xdd,0x8f,0x93,0x8e,0x53,
2620
0x8f,0x07,0x1f,0x67,0x1d,0x8f,0x3d,0x9e,0x7c,0x3c,0xed,0x38,0xef,0xb8,0xf0,0xb8,
2621
0xe4,0xb8,0xe2,0xb8,0xee,0x78,0xcd,0xf1,0xc6,0xe3,0xad,0xc7,0x3b,0x8f,0xf7,0x1c,
2622
0x1f,0x38,0x3e,0x7c,0x7c,0xf4,0xf8,0xf8,0xf1,0xc9,0xe3,0xd3,0xc7,0x2d,0xc7,0x17,
2623
0x8f,0x2f,0x1f,0xb7,0x39,0x41,0x38,0xe1,0x72,0xc2,0xfd,0x84,0xf7,0x09,0xdf,0x13,
2624
0xd4,0x13,0x8c,0x13,0x21,0x27,0x58,0x27,0x62,0x4f,0x24,0x9f,0x48,0x3b,0xc1,0x3b,
2625
0x21,0x3c,0x21,0x39,0xa1,0x38,0xa1,0x3b,0x51,0x73,0xa2,0xf1,0x44,0xeb,0x89,0xce,
2626
0x13,0x3d,0x27,0x06,0x4e,0x0c,0x9f,0x18,0x3d,0x31,0x7e,0x62,0xf2,0xc4,0xf4,0x09,
2627
0xcb,0x89,0xc5,0x13,0xcb,0x27,0x6c,0x52,0x08,0x29,0x2e,0x29,0xee,0x29,0xde,0x29,
2628
0xbe,0x29,0xd4,0x14,0x46,0x4a,0x48,0x0a,0x2b,0x25,0x36,0x25,0x39,0x25,0x2d,0x45,
2629
0x90,0x22,0x49,0x51,0xa4,0xe8,0x52,0x6a,0x52,0x1a,0x53,0x5a,0x53,0x3a,0x53,0x7a,
2630
0x52,0x06,0x52,0x86,0x53,0x46,0x53,0xc6,0x53,0x26,0x53,0xa6,0x53,0x2c,0x29,0x8b,
2631
0x29,0xcb,0x29,0x36,0xa9,0x8e,0xa9,0xee,0xa9,0xa4,0x54,0x72,0x2a,0x3d,0x35,0x38,
2632
0x35,0x2c,0x95,0x93,0x9a,0x98,0x9a,0x9a,0x9a,0x91,0x2a,0x48,0x15,0xa7,0xca,0x00,
2633
0x4d,0xaa,0x31,0xb5,0x2e,0xb5,0x39,0xb5,0x3d,0xb5,0x3b,0xd5,0x94,0x3a,0x94,0x3a,
2634
0x92,0x3a,0x96,0x3a,0x91,0x3a,0x95,0x6a,0x4e,0x9d,0x4f,0x5d,0x4a,0x5d,0x49,0xb5,
2635
0x3b,0xe9,0x78,0x92,0x78,0xd2,0xf3,0x24,0xe9,0x24,0xf9,0x24,0xfd,0x64,0xf0,0xc9,
2636
0xb0,0x93,0x9c,0x93,0x89,0x27,0x53,0x4f,0x66,0x9c,0x14,0x9c,0x14,0x9f,0x94,0x9d,
2637
0xd4,0x9c,0x34,0x9e,0xac,0x3b,0xd9,0x7c,0xb2,0xfd,0x64,0xf7,0x49,0xd3,0xc9,0xa1,
2638
0x93,0x23,0x27,0xc7,0x4e,0x4e,0x9c,0x9c,0x3a,0x69,0x3e,0x39,0x7f,0x72,0xe9,0xe4,
2639
0xca,0x49,0xbb,0x53,0x8e,0xa7,0x88,0xa7,0x3c,0x4f,0x91,0x4e,0x91,0x4f,0xd1,0x4f,
2640
0x05,0x9f,0x0a,0x3b,0xc5,0x39,0x95,0x78,0x2a,0xf5,0x54,0xc6,0x29,0xfe,0x5f,0x81,
2641
0xe0,0x94,0xe4,0x94,0xe6,0x54,0xcd,0xa9,0xe6,0x53,0x9d,0xa7,0x4c,0xa7,0x86,0x4f,
2642
0x8d,0x9d,0x9a,0x3c,0x65,0x3e,0xb5,0x78,0x6a,0xe5,0x14,0xe1,0x34,0xf1,0xb4,0xf7,
2643
0x69,0xf2,0x69,0xc6,0xe9,0xb0,0xd3,0xb1,0xa7,0x53,0x4f,0xf3,0x4e,0x8b,0x4f,0x2b,
2644
0x4e,0x1b,0x4f,0x37,0x9e,0x6e,0x3f,0xdd,0x73,0x7a,0xe8,0xf4,0xe8,0xe9,0x89,0xd3,
2645
0xd3,0xa7,0xe7,0x4f,0x2f,0x9f,0xb6,0x4b,0x73,0x49,0xf3,0x4c,0xf3,0x4d,0xa3,0xa7,
2646
0x85,0xa4,0x71,0xd2,0x92,0xd3,0x32,0xd2,0x84,0x69,0xb2,0x34,0x5d,0x5a,0x5d,0x5a,
2647
0x6b,0x5a,0x77,0xda,0x40,0xda,0x48,0xda,0x78,0xda,0x54,0x9a,0x25,0x6d,0x29,0xcd,
2648
0xe6,0x3d,0xc7,0xf7,0xdc,0xdf,0x23,0xbd,0x47,0x7d,0x2f,0xf8,0x3d,0xd6,0x7b,0x89,
2649
0xef,0xa5,0xbd,0xc7,0x07,0x04,0xef,0x49,0xde,0xd3,0xbc,0x57,0xf3,0x5e,0xf3,0x7b,
2650
0x9d,0xef,0x99,0xde,0x1b,0x7e,0x6f,0xec,0xbd,0xc9,0xf7,0xcc,0xef,0x2d,0xbe,0xb7,
2651
0xf2,0x1e,0xe1,0x7d,0xe2,0xfb,0xde,0xef,0x93,0xdf,0x67,0xbc,0x1f,0xf6,0x7e,0xec,
2652
0xfb,0xa9,0xef,0xf3,0xde,0x17,0xbf,0xaf,0x78,0xdf,0xf8,0x7e,0xe3,0xfb,0xed,0xef,
2653
0xf7,0xbc,0x3f,0xf4,0xfe,0xe8,0xfb,0x13,0xef,0x4f,0xbf,0x3f,0xff,0xfe,0xf2,0xfb,
2654
0x76,0xe9,0x2e,0xe9,0x9e,0xe9,0xbe,0xe9,0xf4,0xf4,0x90,0x74,0x4e,0x7a,0x72,0x7a,
2655
0x46,0xba,0x30,0x5d,0x96,0xae,0x4b,0xaf,0x4b,0x6f,0x4d,0xef,0x4e,0x1f,0x48,0x1f,
2656
0x49,0x1f,0x4f,0x9f,0x4a,0xb7,0xa4,0xbf,0xf8,0x99,0x59,0x4a,0xb7,0xc9,0x70,0xcc,
2657
0xf0,0xcc,0x20,0x67,0x04,0x67,0x70,0x32,0x52,0x33,0x04,0x19,0xb2,0x0c,0x5d,0xc6,
2658
0x78,0xc6,0x62,0x06,0xca,0xfc,0xeb,0xb0,0xc9,0xb4,0xcb,0x24,0x64,0x3a,0x66,0xba,
2659
0x64,0x12,0x33,0xdd,0x33,0x3d,0x33,0xbd,0x33,0x49,0x99,0x94,0xbf,0x01,0x6a,0x26,
2660
0x23,0x33,0x38,0x33,0x24,0x33,0x2c,0x93,0x95,0xc9,0xc9,0x8c,0xcd,0x4c,0xcc,0x4c,
2661
0xce,0x4c,0xcd,0x4c,0xcb,0xcc,0xc8,0xe4,0x65,0x0a,0x32,0x85,0x99,0xe2,0x4c,0x49,
2662
0xa6,0x2c,0x53,0x91,0xa9,0xc9,0xd4,0x02,0xba,0x4c,0x63,0x66,0x4d,0x66,0x63,0x66,
2663
0x6b,0x66,0x67,0x66,0x4f,0xa6,0x29,0x73,0x20,0x73,0x28,0x73,0x38,0x73,0x24,0xf3,
2664
0x7e,0xe6,0x68,0xe6,0x58,0xe6,0x78,0xe6,0x44,0xe6,0x64,0xe6,0x54,0xe6,0x74,0xa6,
2665
0x39,0xd3,0x92,0x39,0x9f,0xb9,0x98,0xb9,0x94,0xb9,0x9c,0xb9,0x92,0x69,0x73,0xc6,
2666
0xee,0x0c,0xe1,0x8c,0xe3,0x19,0x97,0x33,0xae,0x67,0x88,0x67,0xdc,0xcf,0x78,0x9e,
2667
0xf1,0x3e,0xe3,0xf3,0x3d,0xa4,0x33,0xe4,0x33,0xf4,0x33,0xcc,0x33,0xc1,0x67,0x42,
2668
0xcf,0x84,0x9d,0xe1,0x9c,0x49,0x3c,0x93,0x7a,0x26,0xe3,0x8c,0xe0,0x8c,0xf8,0x8c,
2669
0xec,0x8c,0xe6,0x8c,0xf1,0x4c,0xdd,0x99,0xc6,0x33,0xad,0x67,0x3a,0xcf,0xf4,0x9c,
2670
0x19,0x38,0x33,0x7c,0x66,0xf4,0xcc,0xf8,0x99,0xc9,0x33,0xd3,0x67,0x2c,0x67,0x16,
2671
0xcf,0x2c,0x9f,0x59,0x39,0x63,0xc3,0xb5,0xe3,0x12,0xb8,0x8e,0x5c,0x17,0x2e,0x91,
2672
0xeb,0xce,0xf5,0xe4,0x7a,0x73,0x49,0x5c,0x5f,0x2e,0x99,0x4b,0xe5,0xd2,0xb9,0x0c,
2673
0x6e,0x30,0x37,0x84,0x1b,0xc6,0x65,0x71,0x39,0xdc,0x58,0x6e,0x22,0x37,0x99,0x9b,
2674
0xca,0x4d,0xe3,0x66,0x70,0x79,0x5c,0x01,0x57,0xc8,0x15,0x73,0x25,0x5c,0x19,0x57,
2675
0xc1,0xd5,0x70,0x75,0x5c,0x23,0xb7,0x86,0x5b,0xc7,0x6d,0xe4,0x36,0x73,0x5b,0xb9,
2676
0xed,0xdc,0x4e,0x6e,0x37,0xb7,0x87,0x6b,0xe2,0x0e,0x70,0x87,0xb8,0xc3,0xdc,0x11,
2677
0xee,0x28,0x77,0x8c,0x3b,0xce,0x9d,0xe0,0x4e,0x72,0xa7,0xb8,0xd3,0x5c,0x33,0xd7,
2678
0xc2,0x9d,0xe7,0x2e,0x72,0x97,0xb8,0xcb,0xdc,0x15,0xae,0x0d,0xcf,0x8e,0x47,0xe0,
2679
0x39,0xf2,0x5c,0x78,0x44,0x9e,0x3b,0xcf,0x93,0xe7,0xcd,0x23,0xf1,0x7c,0x79,0x64,
2680
0x1e,0x95,0x47,0xe7,0x31,0x78,0xc1,0xbc,0x10,0x5e,0x18,0x8f,0xc5,0xe3,0xf0,0x62,
2681
0x79,0x89,0xbc,0x64,0x5e,0x2a,0x2f,0x8d,0x97,0xc1,0xe3,0xf1,0x04,0x3c,0x21,0x4f,
2682
0xcc,0x93,0xf0,0x64,0x3c,0x05,0x4f,0xc3,0xd3,0xf1,0x8c,0xbc,0x1a,0x5e,0x1d,0xaf,
2683
0x91,0xd7,0xce,0xeb,0xe1,0x0d,0xf1,0x46,0x79,0x13,0xbc,0x69,0x9e,0x85,0xb7,0xf0,
2684
0x23,0x8b,0xbc,0x25,0xde,0x32,0x6f,0x85,0x67,0x93,0x65,0x97,0x45,0xc8,0x72,0xcc,
2685
0x72,0xc9,0x22,0x66,0xb9,0x67,0x79,0x66,0x79,0x67,0x91,0xb2,0x7c,0xb3,0xc8,0x59,
2686
0xd4,0x2c,0x7a,0x16,0x23,0x2b,0x38,0x2b,0x24,0x2b,0x2c,0x8b,0x95,0xc5,0xc9,0x8a,
2687
0xcd,0x4a,0xcc,0x4a,0xce,0x4a,0xcd,0x4a,0xcb,0xca,0xc8,0xe2,0x65,0x09,0xb2,0x84,
2688
0x59,0xe2,0x2c,0x49,0x96,0x2c,0x4b,0x91,0xa5,0xc9,0xd2,0x65,0x19,0xb3,0x6a,0xb2,
2689
0xea,0xb2,0x1a,0xb3,0x9a,0xb3,0x5a,0xb3,0xda,0xb3,0x3a,0xb3,0xba,0xb3,0x7a,0xb2,
2690
0x4c,0x59,0x03,0x59,0x43,0x59,0xc3,0x59,0x23,0x59,0xa3,0x59,0x63,0x59,0xe3,0x59,
2691
0x13,0x59,0x93,0x59,0x53,0x59,0xd3,0x59,0xe6,0x2c,0x4b,0xd6,0x7c,0xd6,0x62,0xd6,
2692
0x52,0xd6,0x72,0xd6,0x4a,0x96,0x4d,0xb6,0x5d,0x36,0x21,0xdb,0x31,0xdb,0x25,0x9b,
2693
0x98,0xed,0x9e,0xed,0x99,0xed,0x9d,0x4d,0xca,0xf6,0xcd,0x26,0x67,0x53,0xb3,0xe9,
2694
0xd9,0x8c,0xec,0xe0,0xec,0x90,0xec,0xb0,0x6c,0x56,0x36,0x27,0x3b,0x36,0x3b,0x31,
2695
0x3b,0x39,0x3b,0x35,0x3b,0x2d,0x3b,0x23,0x9b,0x97,0x2d,0xc8,0x16,0x66,0x8b,0xb3,
2696
0x25,0xd9,0xb2,0x6c,0x45,0xb6,0x26,0x5b,0x97,0x6d,0xcc,0xae,0xc9,0xae,0xcb,0x6e,
2697
0xcc,0x6e,0xce,0x6e,0xcd,0x6e,0xcf,0xee,0xcc,0xee,0xce,0xee,0xc9,0x36,0x65,0x0f,
2698
0x64,0x0f,0x65,0x0f,0x67,0x8f,0x64,0x8f,0x66,0x8f,0x65,0x8f,0x67,0x4f,0x64,0x4f,
2699
0x66,0x4f,0x65,0x4f,0x67,0x9b,0xb3,0x2d,0xd9,0xf3,0xd9,0x8b,0xd9,0x4b,0xd9,0xcb,
2700
0xd9,0x2b,0xd9,0x36,0x7c,0x3b,0x3e,0x81,0xef,0xc8,0x77,0xe1,0x13,0xf9,0xee,0x7c,
2701
0x4f,0xbe,0x37,0x9f,0xc4,0xf7,0xe5,0x93,0xf9,0x54,0x3e,0x9d,0xcf,0xe0,0x07,0xf3,
2702
0x43,0xf8,0x61,0x7c,0x16,0x9f,0xc3,0x8f,0xe5,0x27,0xf2,0x93,0xf9,0xa9,0xfc,0x34,
2703
0x7e,0x06,0x9f,0xc7,0x17,0xf0,0x85,0x7c,0x31,0x5f,0xc2,0x97,0xf1,0x15,0x7c,0x0d,
2704
0x5f,0xc7,0x37,0xf2,0x6b,0xf8,0x75,0xfc,0x46,0x7e,0x33,0xbf,0x95,0xdf,0xce,0xef,
2705
0xe4,0x77,0xf3,0x7b,0xf8,0x26,0xfe,0x00,0x7f,0x88,0x3f,0xcc,0x1f,0xe1,0x8f,0xf2,
2706
0xc7,0xf8,0xe3,0xfc,0x09,0xfe,0x24,0x7f,0x8a,0x3f,0xcd,0x37,0xf3,0xe7,0xac,0x58,
2707
0xf8,0xf3,0xfc,0x45,0xfe,0x12,0x7f,0x99,0xbf,0xc2,0x47,0x02,0x24,0xb0,0x11,0xd8,
2708
0x09,0x08,0x02,0x47,0x81,0x8b,0x80,0x28,0x70,0x03,0xdc,0x05,0x9e,0x02,0x6f,0x01,
2709
0x49,0xe0,0x2b,0x20,0x0b,0x28,0x00,0x55,0x40,0x17,0x30,0x04,0x4c,0x2b,0xc1,0x82,
2710
0x10,0x41,0x98,0x80,0x25,0x88,0x15,0x24,0x0a,0x92,0x05,0x29,0x82,0x54,0x41,0x9a,
2711
0x20,0x43,0xc0,0x13,0x08,0x04,0x42,0x81,0x58,0x50,0xb8,0xc6,0xaf,0x12,0xf9,0xdf,
2712
0x85,0x76,0x8d,0xbf,0x13,0x9d,0xc0,0x28,0xa8,0x11,0xd4,0x09,0x1a,0x05,0x4d,0x82,
2713
0x66,0x41,0xab,0xa0,0x5d,0xd0,0x29,0xe8,0x16,0xf4,0x08,0x4c,0x82,0x01,0xc1,0x90,
2714
0x60,0x58,0x30,0x22,0x18,0x15,0x8c,0x09,0xc6,0x05,0x13,0x82,0x49,0xc1,0x94,0x60,
2715
0x5a,0x60,0x16,0x58,0x04,0xf3,0x82,0x45,0xc1,0x92,0x60,0x59,0xb0,0x22,0xb0,0x39,
2716
0x6b,0x77,0x96,0x70,0xd6,0xf1,0xac,0xcb,0x59,0xe2,0x59,0xf7,0xb3,0x9e,0x67,0xbd,
2717
0xcf,0x92,0xce,0xfa,0x9e,0x25,0x9f,0xa5,0x9e,0xa5,0x9f,0x65,0x9c,0x0d,0x3e,0x1b,
2718
0x72,0x36,0xf4,0x6c,0xd8,0x59,0xd6,0x59,0xce,0xd9,0xd8,0xb3,0x89,0x67,0x93,0xcf,
2719
0xa6,0x9e,0x4d,0x3b,0x9b,0x71,0x96,0x77,0x56,0x70,0x56,0x78,0x56,0x7c,0x56,0x72,
2720
0x56,0xba,0xc6,0xaf,0x12,0x35,0x60,0xf8,0x6f,0xa9,0x5d,0xc3,0x4a,0xd3,0xd9,0xb6,
2721
0x35,0xd6,0xf8,0xbb,0xe8,0x3a,0xdb,0xf7,0x8b,0x32,0x08,0xdc,0xfb,0x2f,0x3c,0xb0,
2722
0xf2,0xe8,0x17,0xe2,0x09,0x30,0x73,0xf6,0xf9,0x1a,0xbf,0x09,0x5e,0x9c,0x7d,0x09,
2723
0xd8,0x9e,0x5b,0xe3,0xb7,0x89,0xc3,0x39,0xd7,0xdf,0x30,0x1e,0x6b,0xfc,0xcb,0xe1,
2724
0x73,0xce,0xef,0x1c,0xed,0x1c,0xf3,0x5c,0xe8,0xb9,0x98,0x73,0x29,0xe7,0xb8,0x6b,
2725
0xac,0xf1,0x3f,0x4a,0xce,0xb9,0xc2,0x73,0xea,0x35,0x7e,0x61,0x34,0xe7,0x8c,0xe7,
2726
0xea,0xce,0x35,0x9f,0x6b,0x5b,0x63,0x8d,0x35,0xfe,0x69,0xb4,0x9f,0xeb,0x3c,0xd7,
2727
0x7d,0xae,0xe7,0x9c,0xe9,0xdc,0xc0,0xb9,0xa1,0x73,0xc3,0xe7,0x46,0xce,0x8d,0x9e,
2728
0x1b,0x3b,0x37,0x7e,0x6e,0xe2,0xdc,0xe4,0xb9,0xa9,0x73,0xd3,0xe7,0xcc,0xe7,0x2c,
2729
0xe7,0xe6,0xcf,0x2d,0x9e,0x5b,0x3a,0xb7,0x7c,0x6e,0xe5,0x9c,0x4d,0x8e,0x5d,0x0e,
2730
0x21,0xc7,0x31,0xc7,0x25,0x87,0x98,0xe3,0x9e,0xe3,0x99,0xe3,0x9d,0x43,0xca,0xf1,
2731
0xcd,0x21,0xe7,0x50,0x73,0x68,0xff,0x42,0x30,0x73,0x42,0x73,0x62,0x72,0x52,0x72,
2732
0xb8,0x39,0xa2,0x1c,0xf9,0xaf,0x0a,0x6d,0x4e,0x75,0x4e,0x53,0x4e,0x47,0x4e,0x5f,
2733
0xce,0xdd,0xff,0x61,0x86,0x73,0x46,0x72,0x46,0x73,0xc6,0x72,0xc6,0x73,0x26,0x72,
2734
0x26,0x73,0xa6,0x72,0xa6,0x73,0xcc,0x39,0x96,0x9c,0xf9,0x9c,0xc5,0x9c,0xa5,0x9c,
2735
0xe5,0x9c,0x95,0x1c,0x1b,0xa1,0x9d,0x90,0x20,0x74,0x14,0xba,0x08,0x89,0x42,0x77,
2736
0xa1,0xa7,0xd0,0x5b,0x48,0x12,0xfa,0x0a,0xc9,0x42,0xaa,0x90,0x2e,0x64,0x08,0x83,
2737
0x85,0x21,0xc2,0x30,0x21,0x4b,0xc8,0x11,0xc6,0x0a,0x13,0x85,0xc9,0xc2,0x54,0x61,
2738
0x9a,0x30,0x43,0xc8,0x13,0x0a,0x84,0x42,0xa1,0x58,0x28,0x11,0xca,0x84,0x0a,0xa1,
2739
0x46,0xa8,0x13,0x1a,0x85,0x35,0xc2,0x3a,0x61,0xa3,0xb0,0x59,0xd8,0x2a,0x6c,0x17,
2740
0x76,0x0a,0xbb,0x85,0x3d,0x42,0x93,0x70,0x40,0x38,0x24,0x1c,0x16,0x8e,0x08,0x47,
2741
0x85,0x63,0xc2,0x71,0xe1,0x84,0x70,0x52,0x38,0x25,0x9c,0x16,0x9a,0x85,0x16,0xe1,
2742
0xbc,0x70,0x51,0xb8,0x24,0x5c,0x16,0xae,0x08,0x6d,0x72,0xed,0x72,0x09,0xb9,0x8e,
2743
0xb9,0x2e,0xb9,0xae,0xb9,0xc4,0x5c,0xf7,0x5c,0xcf,0x5c,0xef,0x5c,0x52,0xae,0x6f,
2744
0x2e,0x39,0x97,0x9a,0x4b,0xcf,0x65,0xe4,0x06,0xe7,0x86,0xe4,0x86,0xe5,0xb2,0x72,
2745
0x39,0xb9,0xb1,0xb9,0x89,0xb9,0xc9,0xb9,0xa9,0xb9,0x69,0xb9,0x19,0xb9,0xbc,0x5c,
2746
0x41,0xae,0x30,0x57,0x9c,0x2b,0xc9,0x95,0xe5,0x2a,0x72,0x35,0xb9,0xba,0x5c,0x63,
2747
0x6e,0x4d,0x6e,0x5d,0x6e,0x63,0x6e,0x73,0x6e,0x6b,0x6e,0x7b,0x6e,0x67,0x6e,0x77,
2748
0x6e,0x4f,0xae,0x29,0x77,0x20,0x77,0x28,0x77,0x38,0x77,0x24,0x77,0x34,0x77,0x2c,
2749
0x77,0x3c,0x77,0x22,0x77,0x32,0x77,0x2a,0x77,0x3a,0xd7,0x9c,0x6b,0xc9,0x9d,0xcf,
2750
0x5d,0xcc,0x5d,0xca,0x5d,0xce,0x5d,0xc9,0xb5,0xc9,0xb3,0xcb,0x23,0xe4,0x39,0xe6,
2751
0xb9,0xe4,0x11,0xf3,0xdc,0xf3,0x3c,0xf3,0xbc,0xf3,0x48,0x79,0xbe,0x79,0xe4,0x3c,
2752
0x4a,0x1e,0x35,0x8f,0x9e,0x17,0x08,0x30,0xf2,0x98,0x40,0x70,0x5e,0x48,0x5e,0x28,
2753
0x10,0x96,0xc7,0xca,0xe3,0xe4,0xc5,0xe6,0x25,0xe4,0x25,0xe6,0x25,0xe7,0xa5,0xe6,
2754
0xa5,0xe5,0x65,0xe4,0xf1,0xf2,0x04,0x79,0xc2,0x3c,0x71,0x9e,0x24,0x4f,0x96,0xa7,
2755
0xc8,0x53,0xe7,0x69,0xf2,0xb4,0x79,0xba,0x3c,0x63,0x5e,0x4d,0x5e,0x5d,0x5e,0x63,
2756
0x5e,0x73,0x5e,0x6b,0x5e,0x5b,0x5e,0x7b,0x5e,0x67,0x5e,0x77,0x5e,0x4f,0x9e,0x29,
2757
0x6f,0x20,0x6f,0x28,0x6f,0x38,0x6f,0x24,0x6f,0x34,0x6f,0x2c,0x6f,0x3c,0x6f,0x22,
2758
0x6f,0x32,0x6f,0x2a,0x6f,0x3a,0xcf,0x9c,0x67,0xc9,0x9b,0xcf,0x5b,0xcc,0x5b,0xca,
2759
0x5b,0xce,0x5b,0xc9,0xb3,0x11,0xd9,0x89,0x08,0x22,0x47,0x91,0x8b,0x88,0x28,0x72,
2760
0x17,0x79,0x8a,0xbc,0x45,0x24,0x91,0xaf,0x88,0x2c,0xa2,0x8a,0xe8,0x22,0x86,0x28,
2761
0x58,0x14,0x22,0x0a,0x13,0xb1,0x44,0x1c,0x51,0xac,0x28,0x51,0x94,0x2c,0x4a,0x15,
2762
0xa5,0x89,0x32,0x44,0x3c,0x91,0x40,0x24,0x14,0x89,0x45,0x12,0x91,0x4c,0xa4,0x10,
2763
0x69,0x44,0x3a,0x91,0x51,0x54,0x03,0xd4,0x89,0x1a,0x45,0xcd,0xa2,0x56,0x51,0xbb,
2764
0xa8,0x43,0xd4,0x29,0xea,0x16,0xf5,0x88,0x4c,0xa2,0x7e,0x60,0x40,0x34,0x24,0x1a,
2765
0x16,0x8d,0x88,0x46,0x45,0x63,0xa2,0x71,0xd1,0x84,0xe8,0xb1,0x68,0x52,0x34,0x25,
2766
0x9a,0x16,0x99,0x45,0x16,0xd1,0xbc,0x68,0x51,0xf4,0x42,0xb4,0x24,0x5a,0x16,0xad,
2767
0x88,0x6c,0xc4,0x76,0x62,0x82,0xd8,0x51,0xec,0x22,0x26,0x8a,0xdd,0xc5,0x9e,0x62,
2768
0x6f,0x31,0x49,0xec,0x2b,0x26,0x8b,0xa9,0x62,0xba,0x98,0x21,0x0e,0x16,0x87,0x88,
2769
0xc3,0xc4,0x2c,0x31,0x47,0x1c,0x2b,0x4e,0x14,0x27,0x8b,0x53,0xc5,0x69,0xe2,0x74,
2770
0x71,0x86,0x98,0x27,0x16,0x88,0x85,0x62,0x91,0x58,0x2c,0x96,0x88,0x65,0x62,0x85,
2771
0x58,0x23,0xd6,0x8a,0x75,0x62,0x83,0x15,0xa3,0xb8,0x46,0x5c,0x27,0x6e,0x14,0x37,
2772
0x8b,0x5b,0xc5,0xed,0xe2,0x0e,0x71,0xa7,0xb8,0x5b,0xdc,0x23,0x36,0x89,0x07,0xc4,
2773
0x43,0xe2,0x61,0xf1,0x88,0x78,0x54,0x3c,0x26,0x1e,0x17,0x4f,0x88,0x27,0xc5,0x53,
2774
0xe2,0x69,0xb1,0x59,0x6c,0x11,0xcf,0x8b,0x17,0xc5,0x4b,0xe2,0x65,0xf1,0x8a,0xd8,
2775
0x26,0xdf,0x2e,0x9f,0x90,0xef,0x98,0xef,0x92,0x4f,0xcc,0x77,0xcf,0xf7,0xcc,0xf7,
2776
0xce,0x27,0xe5,0xfb,0xe6,0x93,0xf3,0xa9,0xf9,0xf4,0x7c,0x46,0x7e,0x70,0x7e,0x48,
2777
0x7e,0x58,0x3e,0x2b,0x9f,0x93,0x1f,0x9b,0x9f,0x98,0x9f,0x9c,0x9f,0x9a,0x9f,0x96,
2778
0x9f,0x91,0xcf,0xcb,0x17,0xe4,0x0b,0xf3,0xc5,0xf9,0x92,0x7c,0x59,0xbe,0x22,0x5f,
2779
0x93,0xaf,0xcb,0x37,0xe6,0xd7,0xe4,0xd7,0xe5,0x37,0xe6,0x37,0xe7,0xb7,0xe6,0xb7,
2780
0xe7,0x77,0xe6,0x77,0xe7,0xf7,0xe4,0x9b,0xf2,0x07,0xf2,0x87,0xf2,0x87,0xf3,0x47,
2781
0xf2,0x47,0xf3,0xc7,0xf2,0xc7,0xf3,0x27,0xf2,0x27,0xf3,0xa7,0xf2,0xa7,0xf3,0xcd,
2782
0xf9,0x96,0xfc,0xf9,0xfc,0xc5,0xfc,0xa5,0xfc,0xe5,0xfc,0x95,0x7c,0x9b,0x02,0xbb,
2783
0x02,0x42,0x81,0x63,0x81,0x4b,0x01,0xb1,0xc0,0xbd,0xc0,0xb3,0xc0,0xbb,0x80,0x54,
2784
0xe0,0x5b,0x40,0x2e,0xa0,0x16,0xd0,0x0b,0x18,0x05,0xc1,0x05,0x21,0x05,0x61,0x05,
2785
0xac,0x02,0x4e,0x41,0x6c,0x41,0x62,0x41,0x72,0x41,0x6a,0x41,0x5a,0x41,0x46,0x01,
2786
0xaf,0x40,0x50,0x20,0x2c,0x10,0x17,0x48,0x0a,0x64,0x05,0x8a,0x02,0x4d,0x81,0xae,
2787
0xc0,0x58,0x50,0x53,0x50,0x57,0xd0,0x58,0xd0,0x5c,0xd0,0x5a,0xd0,0x5e,0xd0,0x59,
2788
0xd0,0x5d,0xd0,0x53,0x60,0x2a,0x18,0x28,0x18,0x2a,0x18,0x2e,0x18,0x29,0x18,0x2d,
2789
0x18,0x2b,0x18,0x2f,0x98,0x28,0x98,0x2c,0x98,0x2a,0x98,0x2e,0x30,0x17,0x58,0x0a,
2790
0xe6,0x0b,0x16,0x0b,0x96,0x0a,0x96,0x0b,0x56,0x0a,0x6c,0x0a,0xed,0x0a,0x09,0x85,
2791
0x8e,0x85,0x2e,0x85,0xc4,0x42,0xf7,0x42,0xcf,0x42,0xef,0x42,0x52,0xa1,0x6f,0x21,
2792
0xb9,0x90,0x5a,0x48,0x2f,0x64,0x14,0x06,0x17,0x86,0x14,0x86,0x15,0xb2,0x0a,0x39,
2793
0x85,0xb1,0x85,0x89,0x85,0xc9,0x85,0xa9,0x85,0x69,0x40,0x46,0x21,0xaf,0x50,0x50,
2794
0x28,0x2c,0x14,0x17,0x4a,0x0a,0x65,0x85,0x8a,0x42,0x4d,0xa1,0xae,0xd0,0x58,0x58,
2795
0x53,0x58,0x57,0xd8,0x58,0xd8,0x5c,0xd8,0x5a,0xd8,0x5e,0xd8,0x59,0xd8,0x5d,0xd8,
2796
0x53,0x68,0x2a,0x1c,0x28,0x1c,0x2a,0x1c,0x2e,0x1c,0x29,0x1c,0x2d,0x1c,0x2b,0x1c,
2797
0x2f,0x9c,0x28,0x9c,0x2c,0x9c,0x2a,0x9c,0x2e,0x34,0x17,0x5a,0x0a,0xe7,0x0b,0x17,
2798
0x0b,0x97,0x0a,0x97,0x0b,0x57,0x0a,0x6d,0x24,0x76,0x12,0x82,0xc4,0x51,0xe2,0x22,
2799
0x21,0x4a,0xdc,0x25,0x9e,0x12,0x6f,0x09,0x49,0xe2,0x2b,0x21,0x4b,0xa8,0x12,0xba,
2800
0x84,0x21,0x09,0x96,0x84,0x48,0xc2,0x24,0x2c,0x09,0x47,0x12,0x2b,0x49,0x94,0x24,
2801
0x4b,0x52,0x25,0x69,0x92,0x0c,0x09,0x4f,0x22,0x90,0x08,0x25,0x62,0x89,0x44,0x22,
2802
0x93,0x28,0x24,0x1a,0x89,0x4e,0x62,0x94,0xd4,0x48,0xea,0x24,0x8d,0x92,0x66,0x49,
2803
0xab,0xa4,0x5d,0xd2,0x29,0xe9,0x96,0xf4,0x48,0x4c,0x92,0x01,0xc9,0x90,0x64,0x58,
2804
0x32,0x22,0x19,0x95,0x8c,0x49,0xc6,0x25,0x13,0x92,0x49,0xc9,0x94,0x64,0x5a,0x62,
2805
0x96,0x58,0x24,0xf3,0x92,0x45,0xc9,0x92,0x64,0x59,0xb2,0x22,0xb1,0x29,0xb2,0x2b,
2806
0x22,0x14,0x39,0x16,0xb9,0x14,0x11,0x8b,0xdc,0x8b,0x3c,0x8b,0xbc,0x8b,0x48,0x45,
2807
0xbe,0x45,0xe4,0x22,0x6a,0x11,0xbd,0x88,0x51,0x14,0x5c,0x14,0x52,0x14,0x56,0xc4,
2808
0x2a,0xe2,0x14,0xc5,0x16,0x25,0x16,0x25,0x17,0xa5,0x16,0xa5,0x15,0x65,0x14,0xf1,
2809
0x8a,0x04,0x45,0xc2,0x22,0x71,0x91,0xa4,0x48,0x56,0xa4,0x28,0xd2,0x14,0xe9,0x8a,
2810
0x8c,0x45,0x35,0x45,0x75,0x45,0x8d,0x45,0xcd,0x45,0xad,0x45,0xed,0x45,0x9d,0x45,
2811
0xdd,0x45,0x3d,0x45,0xa6,0xa2,0x81,0xa2,0xa1,0xa2,0xe1,0xa2,0x91,0xa2,0xd1,0xa2,
2812
0xb1,0xa2,0xf1,0xa2,0x89,0xa2,0xc9,0xa2,0xa9,0xa2,0xe9,0x22,0x73,0x91,0xa5,0x68,
2813
0xbe,0x68,0xb1,0x68,0xa9,0x68,0xb9,0xe8,0x65,0xd1,0x4a,0x91,0x4d,0xb1,0x5d,0x31,
2814
0xa1,0xd8,0xb1,0xd8,0xa5,0x98,0x58,0xec,0x5e,0xec,0x59,0xec,0x5d,0x4c,0x2a,0xf6,
2815
0x2d,0x26,0x17,0x53,0x8b,0xe9,0xc5,0x8c,0xe2,0xe0,0xe2,0x90,0xe2,0xb0,0x62,0x56,
2816
0x31,0xa7,0x38,0xb6,0x38,0xb1,0x38,0xb9,0x38,0xb5,0x38,0xad,0x38,0xa3,0x98,0x57,
2817
0x2c,0x28,0x16,0x16,0x8b,0x8b,0x25,0xc5,0xb2,0x62,0x45,0xb1,0xa6,0x58,0x57,0x6c,
2818
0x2c,0xae,0x29,0xae,0x2b,0x6e,0x2c,0x6e,0x2e,0x6e,0x2d,0x6e,0x2f,0xee,0x2c,0xee,
2819
0x2e,0xee,0x29,0x36,0x15,0x0f,0x14,0x0f,0x15,0x0f,0x17,0x8f,0x14,0x8f,0x16,0x8f,
2820
0x15,0x8f,0x17,0x4f,0x14,0x4f,0x16,0x4f,0x15,0x4f,0x17,0x9b,0x8b,0x2d,0xc5,0xf3,
2821
0xc5,0x8b,0xc5,0x4b,0xc5,0xcb,0xc5,0x2b,0xc5,0x36,0x52,0x3b,0x29,0x41,0xea,0x28,
2822
0x75,0x91,0x12,0xa5,0xee,0x52,0x4f,0xa9,0xb7,0x94,0x24,0xf5,0x95,0x92,0xa5,0x54,
2823
0x29,0x5d,0xca,0x90,0x06,0x4b,0x43,0xa4,0x61,0x52,0x96,0x94,0x23,0x8d,0x95,0x26,
2824
0x4a,0x93,0xa5,0xa9,0x40,0x9a,0x34,0x43,0xca,0x93,0x0a,0xa4,0x42,0xa9,0x58,0x2a,
2825
0x91,0xca,0xa4,0x0a,0xa9,0x46,0xaa,0x93,0x1a,0xa5,0x35,0xd2,0x3a,0x69,0xa3,0xb4,
2826
0x59,0xda,0x2a,0x6d,0x97,0x76,0x4a,0xbb,0xa5,0x3d,0x52,0x93,0x74,0x40,0x3a,0x24,
2827
0x1d,0x96,0x8e,0x48,0x47,0xa5,0x63,0xd2,0x71,0xe9,0x84,0x74,0x52,0x3a,0x25,0x9d,
2828
0x96,0x9a,0xa5,0x16,0xe9,0xbc,0x74,0x51,0xba,0x24,0x5d,0x96,0xae,0x48,0x6d,0x64,
2829
0x76,0x32,0x82,0xcc,0x51,0xe6,0x22,0x23,0xca,0xdc,0x65,0x9e,0x32,0x6f,0x19,0x49,
2830
0xe6,0x2b,0x23,0xcb,0xa8,0x32,0xba,0x8c,0x21,0x0b,0x96,0x85,0xc8,0xc2,0x64,0x2c,
2831
0x19,0x47,0x16,0x2b,0x4b,0x94,0x25,0xcb,0x52,0x65,0x69,0xb2,0x0c,0x19,0x4f,0x26,
2832
0x90,0x09,0x65,0x62,0x99,0x44,0x26,0x93,0x29,0x64,0x1a,0x99,0x4e,0x66,0x94,0xd5,
2833
0xc8,0xea,0x64,0x8d,0xb2,0x66,0x59,0xab,0xac,0x5d,0xd6,0x29,0xeb,0x96,0xf5,0xc8,
2834
0x4c,0xb2,0x01,0xd9,0x90,0x6c,0x58,0x36,0x22,0x1b,0x95,0x8d,0xc9,0xc6,0x65,0x13,
2835
0xb2,0x49,0xd9,0x94,0x6c,0x5a,0x66,0x96,0x59,0x64,0xf3,0xb2,0x45,0xd9,0x92,0x6c,
2836
0x59,0xb6,0x22,0xb3,0x29,0xb1,0x2b,0x21,0x94,0x38,0x96,0xb8,0x94,0x10,0x4b,0xdc,
2837
0x4b,0x3c,0x4b,0xbc,0x4b,0x48,0x25,0xbe,0x25,0xe4,0x12,0x6a,0x09,0xbd,0x84,0x51,
2838
0x12,0x5c,0x12,0x52,0x12,0x56,0xc2,0x2a,0xe1,0x94,0xc4,0x96,0x24,0x96,0x24,0x97,
2839
0xa4,0x96,0xa4,0x95,0x64,0x94,0xf0,0x4a,0x04,0x25,0xc2,0x12,0x71,0x89,0xa4,0x44,
2840
0x56,0xa2,0x28,0xd1,0x94,0xe8,0x4a,0x8c,0x25,0x35,0x25,0x75,0x25,0x8d,0x25,0xcd,
2841
0x25,0xad,0x25,0xed,0x25,0x9d,0x25,0xdd,0x25,0x3d,0x25,0xa6,0x92,0x81,0x92,0xa1,
2842
0x92,0xe1,0x92,0x91,0x92,0xd1,0x92,0xb1,0x92,0xf1,0x92,0x89,0x92,0xc9,0x92,0xa9,
2843
0x92,0xe9,0x12,0x73,0x89,0xa5,0x64,0xbe,0x64,0xb1,0x64,0xa9,0x64,0xb9,0x64,0xa5,
2844
0xc4,0xa6,0xd4,0xae,0x94,0x50,0xea,0x58,0xea,0x52,0x4a,0x2c,0x75,0x2f,0xf5,0x2c,
2845
0xf5,0x2e,0x25,0x95,0xfa,0x96,0x92,0x4b,0xa9,0xa5,0xf4,0x52,0x46,0x69,0x70,0x69,
2846
0x48,0x69,0x58,0x29,0xab,0x94,0x53,0x1a,0x5b,0x9a,0x58,0x9a,0x5c,0x9a,0x5a,0x9a,
2847
0x56,0x9a,0x51,0xca,0x2b,0x15,0x94,0x0a,0x4b,0xc5,0xa5,0x92,0x52,0x59,0xa9,0xa2,
2848
0x54,0x53,0xaa,0x2b,0x35,0x00,0xc6,0xd2,0x9a,0xd2,0xba,0xd2,0xc6,0xd2,0xe6,0xd2,
2849
0xd6,0xd2,0xf6,0xd2,0xce,0xd2,0xee,0xd2,0x9e,0x52,0x53,0xe9,0x40,0xe9,0x50,0xe9,
2850
0x70,0xe9,0x48,0xe9,0x68,0xe9,0x58,0xe9,0x78,0xe9,0x44,0xe9,0x64,0xe9,0x54,0xe9,
2851
0x74,0xa9,0xb9,0xd4,0x52,0x3a,0x5f,0xba,0x58,0xba,0x54,0xba,0x5c,0xba,0x52,0x6a,
2852
0x23,0xb7,0x93,0x13,0xe4,0x8e,0x72,0x17,0x39,0x51,0xee,0x2e,0xf7,0x94,0x7b,0xcb,
2853
0x49,0x72,0x5f,0x39,0x59,0x4e,0x95,0xd3,0xe5,0x0c,0x79,0xb0,0x3c,0x44,0x1e,0x26,
2854
0x67,0xc9,0x39,0xf2,0x58,0x79,0xc2,0x1a,0x7f,0x35,0x89,0xf2,0xa4,0x5f,0x94,0x64,
2855
0x79,0xaa,0x3c,0x4d,0x9e,0x21,0xe7,0xc9,0x05,0x72,0xa1,0x5c,0x2c,0x97,0xc8,0x65,
2856
0x72,0x85,0x5c,0x23,0xd7,0xc9,0x8d,0xf2,0x1a,0x79,0x9d,0xbc,0x51,0xde,0x2c,0x6f,
2857
0x95,0xb7,0xcb,0x3b,0xe5,0xdd,0xf2,0x1e,0xb9,0x49,0x3e,0x20,0x1f,0x92,0x0f,0xcb,
2858
0x47,0xe4,0xa3,0xf2,0x31,0xf9,0xb8,0x7c,0x42,0x3e,0x29,0x9f,0x92,0x4f,0xcb,0xcd,
2859
0x72,0x8b,0x7c,0x5e,0xbe,0x28,0x5f,0x92,0x2f,0xcb,0x57,0xe4,0x36,0x0a,0x3b,0x05,
2860
0x41,0xe1,0xa8,0x70,0x51,0x10,0x15,0xee,0x0a,0x4f,0x85,0xb7,0xc2,0xe7,0x9f,0x0e,
2861
0x49,0xe1,0xab,0x20,0x2b,0xa8,0x0a,0xba,0x82,0xa1,0x08,0x56,0x84,0x28,0xc2,0x14,
2862
0x2c,0x05,0x47,0x11,0xab,0x48,0x54,0x24,0x2b,0x52,0x15,0x69,0x8a,0x0c,0x05,0x4f,
2863
0x21,0x50,0x08,0x15,0x62,0x85,0x44,0x21,0x53,0x28,0x14,0x1a,0x85,0x4e,0x61,0x54,
2864
0xd4,0x28,0xea,0x14,0x8d,0x8a,0x66,0x45,0xab,0xa2,0x5d,0xd1,0xa9,0xe8,0x56,0xf4,
2865
0x28,0x4c,0x8a,0x01,0xc5,0x90,0x62,0x58,0x31,0xa2,0x18,0x55,0x8c,0x29,0xc6,0x15,
2866
0x13,0x8a,0x49,0xc5,0x94,0x62,0x5a,0x61,0x56,0x58,0x14,0xf3,0x8a,0x45,0xc5,0x92,
2867
0x62,0x59,0xb1,0xa2,0xb0,0x51,0xda,0x29,0x09,0x4a,0x47,0xa5,0x8b,0x92,0xa8,0x74,
2868
0x57,0x7a,0xac,0xf1,0x57,0xe0,0xa9,0xf4,0x56,0x92,0x94,0xbe,0x4a,0x3f,0x25,0x59,
2869
0x49,0x55,0xd2,0x95,0x0c,0x65,0xb0,0x32,0x44,0x19,0xa6,0x64,0x29,0x39,0xca,0x58,
2870
0x65,0xa2,0x32,0x59,0x99,0xaa,0x4c,0x53,0x66,0x28,0x79,0x4a,0x81,0x52,0xa8,0x14,
2871
0x2b,0x25,0x4a,0x99,0x52,0xa1,0xd4,0x28,0x75,0x4a,0xa3,0xb2,0x46,0x59,0xa7,0x6c,
2872
0x50,0x36,0x2a,0x9b,0x95,0x2d,0xca,0x56,0x65,0x1b,0xd0,0xae,0xec,0x50,0x76,0x2a,
2873
0xbb,0x95,0x3d,0x4a,0x93,0x72,0x40,0x39,0xa4,0x1c,0x56,0x8e,0x28,0x47,0x95,0x63,
2874
0xca,0x87,0xca,0x71,0xe5,0x84,0x72,0x52,0x39,0xa5,0x7c,0xaa,0x9c,0x56,0xce,0x28,
2875
0xcd,0xca,0xb9,0x9f,0x60,0x51,0x3e,0xff,0x9e,0x79,0xe5,0x82,0x72,0x51,0xf9,0x42,
2876
0xb9,0xa4,0xfc,0x4e,0xb9,0xac,0x5c,0x51,0xda,0xa8,0x6c,0x55,0x76,0x2a,0x82,0xca,
2877
0x41,0xe5,0xa8,0x72,0x06,0x5c,0x54,0xae,0x2a,0xa2,0xca,0x4d,0xe5,0xae,0xf2,0x50,
2878
0x79,0xaa,0xbc,0x54,0xde,0x2a,0x1f,0x15,0x49,0xe5,0xab,0xf2,0x53,0x91,0x55,0x14,
2879
0x80,0xaa,0xa2,0xab,0x18,0xaa,0x60,0xd5,0x01,0x55,0x88,0x2a,0x4c,0xc5,0x52,0x71,
2880
0x54,0xb1,0xaa,0x44,0x55,0xb2,0x2a,0x45,0x95,0xaa,0x4a,0x53,0x65,0xa8,0x78,0x2a,
2881
0xbe,0x4a,0xa0,0x12,0xaa,0xc4,0x2a,0x89,0x4a,0xaa,0x92,0xa9,0xe4,0x2a,0x85,0x4a,
2882
0xa3,0xd2,0xa9,0x8c,0xaa,0x1a,0x55,0x9d,0xaa,0x51,0xd5,0xac,0x6a,0x55,0xb5,0xab,
2883
0x3a,0x54,0x9d,0xaa,0x6e,0x55,0x8f,0xca,0xa4,0x1a,0x50,0x0d,0xa9,0x86,0x55,0x23,
2884
0xaa,0x51,0xd5,0x98,0x6a,0x5c,0x35,0xa1,0x9a,0x54,0x4d,0xa9,0xa6,0x55,0x66,0x95,
2885
0x45,0xf5,0xfc,0x47,0xe6,0x55,0x8b,0xaa,0x25,0xd5,0x77,0xaa,0x65,0xd5,0x8a,0xca,
2886
0x46,0x6d,0xa7,0x26,0xa8,0x1d,0xd4,0x8e,0x6a,0x17,0x35,0x51,0xed,0xae,0xf6,0x54,
2887
0x7b,0xab,0x49,0x6a,0x5f,0x35,0x59,0x4d,0x55,0xd3,0xd5,0x0c,0x75,0xb0,0x3a,0x44,
2888
0x1d,0xa6,0x66,0xa9,0x39,0xea,0x98,0xff,0x35,0xc4,0xaa,0x93,0xd5,0x69,0x6a,0x9e,
2889
0x5a,0xa8,0x96,0xa8,0x15,0x6a,0x9d,0xba,0x46,0xdd,0xa8,0x6e,0x55,0x77,0xfc,0x48,
2890
0xa7,0xda,0xa4,0x1e,0x56,0x8f,0xa9,0x27,0xd5,0x66,0xf5,0xa2,0x7a,0x45,0x4d,0xd0,
2891
0x10,0x35,0xde,0x1a,0xb2,0x86,0xa1,0x09,0xd3,0xc4,0x6a,0x52,0x35,0x3c,0x8d,0x58,
2892
0xa3,0xd0,0x18,0x35,0x8d,0x9a,0x76,0x4d,0x8f,0x66,0x48,0x33,0xaa,0x99,0xd0,0x4c,
2893
0x6b,0xe6,0x35,0x8b,0x9a,0x25,0xcd,0x8a,0xc6,0xb6,0xcc,0xae,0x8c,0x50,0xe6,0x58,
2894
0xe6,0x52,0x46,0x2c,0x73,0x2f,0xf3,0x2c,0xf3,0x2e,0x23,0x95,0xf9,0x96,0x91,0xcb,
2895
0xa8,0x65,0xf4,0x32,0x46,0x59,0x70,0x59,0x48,0x59,0x58,0x19,0xab,0x8c,0x53,0x16,
2896
0x5b,0x96,0x58,0x96,0x5c,0x96,0x5a,0x96,0x56,0x96,0x51,0xc6,0x2b,0x13,0x94,0x89,
2897
0xcb,0x64,0x65,0x9a,0x32,0x63,0x59,0x63,0x59,0xcb,0xdf,0x41,0x6b,0x59,0x67,0x59,
2898
0x4f,0x59,0xff,0xcf,0xc2,0x40,0xd9,0xdd,0x7f,0x69,0x86,0x81,0xd1,0xb2,0xf1,0xb2,
2899
0x47,0x7f,0x96,0x89,0xb2,0xc9,0xb2,0xa9,0xb2,0xe9,0x32,0x4b,0xd9,0x7c,0xd9,0x62,
2900
0xd9,0x52,0xd9,0x72,0xd9,0x4a,0x99,0x4d,0xb9,0x5d,0x39,0xa1,0xdc,0xb1,0xdc,0xa5,
2901
0x9c,0x58,0xee,0x5e,0xee,0x59,0xee,0x5d,0x4e,0x2a,0xf7,0x2d,0x27,0x97,0x53,0xcb,
2902
0xe9,0xe5,0x8c,0xf2,0xe0,0xf2,0x90,0xf2,0xb0,0x72,0x56,0x39,0xa7,0x3c,0xb6,0x3c,
2903
0xb1,0x3c,0xb9,0x3c,0xb5,0x3c,0xad,0x3c,0xa3,0x9c,0x57,0x2e,0x28,0x17,0x96,0x8b,
2904
0xcb,0x25,0xe5,0xb2,0x72,0x45,0xb9,0xa6,0x5c,0xfb,0x3d,0xba,0xf2,0xba,0xf2,0xd6,
2905
0xf2,0xee,0xf2,0x81,0xf2,0x91,0xf2,0xf1,0xf2,0xa9,0x72,0x4b,0xf9,0x8b,0x3f,0x60,
2906
0xa9,0x7c,0xb9,0xfc,0xe5,0x1a,0x6b,0xac,0xf1,0x77,0xb2,0x52,0x6e,0xa3,0xb5,0xd3,
2907
0x12,0xb4,0x8e,0x5a,0x17,0x2d,0x51,0xeb,0xae,0xf5,0xd4,0x7a,0x6b,0x7d,0xfe,0x88,
2908
0xbd,0x5a,0x3f,0x2d,0x45,0x4b,0xd3,0x06,0x6a,0x99,0xda,0x03,0xda,0x50,0x6d,0xb8,
2909
0x96,0xad,0x8d,0xd1,0x26,0x68,0x93,0xb4,0x29,0xda,0xd3,0xda,0x74,0x2d,0x57,0xcb,
2910
0xd7,0xe6,0x68,0x45,0xda,0x42,0xad,0x54,0x2b,0xd7,0xaa,0xb5,0x5a,0xad,0x41,0x5b,
2911
0xad,0xad,0xd5,0x36,0x68,0x9b,0xb4,0x2d,0xda,0x36,0x6d,0x87,0xb6,0x4b,0x7b,0x5d,
2912
0xdb,0xa7,0xed,0xd7,0x0e,0x6a,0xef,0x6a,0xef,0x69,0xef,0x6b,0x1f,0x68,0x1f,0x6a,
2913
0x1f,0x69,0x1f,0x6b,0x9f,0x68,0x9f,0x6a,0x67,0xb4,0x73,0xda,0xe7,0xda,0x05,0xed,
2914
0x0b,0xed,0x77,0xda,0x97,0x5a,0xa4,0xb3,0xd5,0xd9,0xeb,0x1c,0x74,0xce,0x3a,0x57,
2915
0x9d,0x9b,0xce,0x43,0xe7,0xa5,0xf3,0xd1,0xed,0xd5,0xf9,0xe9,0x28,0x3a,0x9a,0x2e,
2916
0x50,0xc7,0xd4,0x1d,0xd0,0x85,0xea,0xc2,0x75,0x6c,0x5d,0x8c,0x2e,0x41,0x97,0xa4,
2917
0x4b,0xd1,0x9d,0xd6,0xa5,0xeb,0xb8,0x3a,0xbe,0x2e,0x47,0x27,0xd2,0x15,0xea,0xa4,
2918
0x3a,0xb9,0x4e,0xad,0xd3,0xea,0x0c,0xba,0x6a,0x5d,0xad,0xae,0x41,0xd7,0xa4,0x6b,
2919
0xd1,0xb5,0xe9,0x3a,0x74,0x5d,0xba,0xeb,0xba,0x3e,0x5d,0xbf,0x6e,0x50,0x77,0x57,
2920
0x77,0x4f,0x77,0x5f,0xf7,0x40,0xf7,0x50,0xf7,0x48,0xf7,0x58,0xf7,0x44,0xf7,0x54,
2921
0x37,0xa3,0x9b,0xd3,0x3d,0xd7,0x2d,0xe8,0x5e,0xe8,0xbe,0xd3,0xbd,0xd4,0x21,0xbd,
2922
0xad,0xde,0x5e,0xef,0xa0,0x77,0xd6,0xbb,0xea,0xdd,0xf4,0x1e,0x7a,0x2f,0xbd,0x8f,
2923
0x7e,0xaf,0xde,0x4f,0x4f,0xd1,0xd3,0xf4,0x81,0x7a,0xa6,0xfe,0x80,0x3e,0x54,0x1f,
2924
0xae,0x67,0xeb,0x63,0xf4,0x09,0xfa,0x24,0x7d,0x8a,0xfe,0xb4,0x3e,0x5d,0xcf,0xd5,
2925
0xf3,0xf5,0x39,0x7a,0x91,0xbe,0x50,0x2f,0xd5,0xcb,0xf5,0x6a,0xbd,0x56,0x6f,0xd0,
2926
0x57,0xeb,0x6b,0xf5,0x0d,0xfa,0x26,0x7d,0x8b,0xbe,0x4d,0xdf,0xa1,0xef,0xd2,0x5f,
2927
0xd7,0xf7,0xe9,0xfb,0xf5,0x83,0xfa,0xbb,0xfa,0x7b,0xfa,0xfb,0xfa,0x07,0xfa,0x87,
2928
0xfa,0x47,0xfa,0xc7,0xfa,0x27,0xfa,0xa7,0xfa,0x19,0xfd,0x9c,0xfe,0xb9,0x7e,0x41,
2929
0xff,0x42,0xff,0x9d,0xfe,0xa5,0x1e,0x55,0xd8,0x56,0xd8,0x57,0x38,0x54,0x38,0x57,
2930
0xb8,0x56,0xb8,0x55,0x78,0x54,0x78,0x55,0xf8,0x54,0xec,0xad,0xf0,0xab,0xa0,0x54,
2931
0xd0,0x2a,0x02,0x2b,0x98,0x15,0x07,0x2a,0x42,0x2b,0xc2,0x2b,0xd8,0x15,0x31,0x15,
2932
0x09,0x15,0x49,0x15,0x29,0x15,0xa7,0x2b,0xd2,0x2b,0xb8,0x15,0xfc,0x8a,0x9c,0x0a,
2933
0x51,0x45,0x61,0x85,0xb4,0x42,0x5e,0xa1,0xae,0xd0,0x56,0x18,0x2a,0xaa,0x2b,0x6a,
2934
0x2b,0x1a,0x2a,0x9a,0x2a,0x5a,0x2a,0xda,0x2a,0x3a,0x2a,0xba,0x2a,0xae,0x57,0xf4,
2935
0x55,0xf4,0x57,0x0c,0x56,0xdc,0xad,0xb8,0x57,0x71,0xbf,0xe2,0x41,0xc5,0xc3,0x8a,
2936
0x47,0x15,0x8f,0x2b,0x9e,0x54,0x3c,0xad,0x98,0xa9,0x98,0xab,0x78,0x5e,0xb1,0x50,
2937
0xf1,0xa2,0xe2,0xbb,0x8a,0x97,0x15,0xc8,0x60,0x6b,0xb0,0x37,0x38,0x18,0x9c,0x0d,
2938
0xae,0x06,0x37,0x83,0x87,0xc1,0xcb,0xe0,0x03,0xec,0x35,0xf8,0x19,0x28,0x06,0x9a,
2939
0x21,0xd0,0xc0,0x34,0x1c,0x30,0x84,0x1a,0xc2,0x0d,0x6c,0x43,0x8c,0x21,0xc1,0x90,
2940
0x64,0x48,0x31,0x9c,0x36,0xa4,0x1b,0xb8,0x06,0xbe,0x21,0xc7,0x20,0x32,0x14,0x1a,
2941
0xa4,0x06,0xb9,0x41,0x6d,0xd0,0x1a,0x0c,0x86,0x6a,0x43,0xad,0xa1,0xc1,0xd0,0x64,
2942
0x68,0x31,0xb4,0x19,0x3a,0x0c,0x5d,0x86,0xeb,0x86,0x3e,0x43,0xbf,0x61,0xd0,0x70,
2943
0xd7,0x70,0xcf,0x70,0xdf,0xf0,0xc0,0xf0,0xd0,0xf0,0xc8,0xf0,0xd8,0xf0,0xc4,0xf0,
2944
0xd4,0x30,0x63,0x98,0x33,0x3c,0x37,0x2c,0x18,0x5e,0x18,0xbe,0x33,0xbc,0x34,0x20,
2945
0xa3,0xad,0xd1,0xde,0xe8,0x60,0x74,0x36,0xba,0x1a,0xdd,0x8c,0x1e,0x46,0x2f,0xa3,
2946
0x8f,0x71,0xaf,0xd1,0xcf,0x48,0x31,0xd2,0x8c,0x81,0x46,0xa6,0xf1,0x80,0x31,0xd4,
2947
0x18,0x6e,0x64,0x1b,0x63,0x8c,0x09,0xc6,0x24,0x63,0x8a,0xf1,0xb4,0x31,0xdd,0xc8,
2948
0x35,0xf2,0x8d,0x39,0x46,0x91,0xb1,0xd0,0x28,0x35,0xca,0x8d,0x6a,0xa3,0xd6,0x68,
2949
0x30,0x56,0x1b,0x6b,0x8d,0x0d,0xc6,0x26,0x63,0x8b,0xb1,0xcd,0xd8,0x61,0xec,0x32,
2950
0x5e,0x37,0xf6,0x19,0xfb,0x8d,0x83,0xc6,0xbb,0xc6,0x7b,0xc6,0xfb,0xc6,0x07,0xc6,
2951
0x87,0xc6,0x47,0xc6,0xc7,0xc6,0x27,0xc6,0xa7,0xc6,0x19,0xe3,0x9c,0xf1,0xb9,0x71,
2952
0xc1,0xf8,0xc2,0xf8,0x9d,0xf1,0xa5,0x11,0x55,0xda,0x56,0xda,0x57,0x3a,0x54,0x3a,
2953
0x57,0xba,0x56,0xba,0x55,0x7a,0x54,0x7a,0x55,0xfa,0x54,0xee,0xad,0xf4,0xab,0xa4,
2954
0x54,0xd2,0x2a,0x03,0x2b,0x99,0x95,0x07,0x2a,0x43,0x2b,0xc3,0x2b,0xd9,0x95,0x31,
2955
0x95,0x09,0x95,0x49,0x95,0x29,0x95,0xa7,0x2b,0xd3,0x2b,0xb9,0x95,0xfc,0xca,0x9c,
2956
0x4a,0x51,0x65,0x61,0xa5,0xb4,0x52,0x5e,0xa9,0xae,0xd4,0x56,0x1a,0x2a,0xab,0x2b,
2957
0x6b,0x2b,0x1b,0x2a,0x9b,0x2a,0x5b,0x2a,0xdb,0x2a,0x3b,0x2a,0xbb,0x2a,0xaf,0x57,
2958
0xf6,0x55,0xf6,0x57,0x0e,0x56,0xde,0xad,0xbc,0x57,0x79,0xbf,0xf2,0x41,0xe5,0xc3,
2959
0xca,0x47,0x95,0x8f,0x2b,0x9f,0x54,0x3e,0xad,0x9c,0xa9,0x9c,0xab,0x7c,0x5e,0xb9,
2960
0x50,0xf9,0xa2,0xf2,0xbb,0xca,0x97,0x95,0xa8,0xca,0xb6,0xca,0xbe,0xca,0xa1,0xca,
2961
0xb9,0xca,0xb5,0xca,0xad,0xca,0xa3,0xca,0xab,0xca,0xa7,0x6a,0x6f,0x95,0x5f,0x15,
2962
0xa5,0x8a,0x56,0x15,0x58,0xc5,0xac,0x3a,0x50,0x15,0x5a,0x15,0x5e,0xc5,0xae,0x8a,
2963
0xa9,0x4a,0xa8,0x4a,0xaa,0x4a,0xa9,0x3a,0x5d,0x95,0x5e,0xc5,0xad,0xe2,0x57,0xe5,
2964
0x54,0x89,0xaa,0x0a,0xab,0xa4,0x55,0xf2,0x2a,0x75,0x95,0xb6,0xca,0x50,0x55,0x5d,
2965
0x55,0x5b,0xd5,0x50,0xd5,0x54,0xd5,0x52,0xd5,0x56,0xd5,0x51,0xd5,0x55,0x75,0xbd,
2966
0xaa,0xaf,0xaa,0xbf,0xea,0xff,0x63,0xef,0x4c,0x00,0x74,0xaa,0x1a,0x3e,0x7e,0x9f,
2967
0x67,0xe6,0x99,0x31,0x28,0x84,0x4a,0xb2,0x4e,0x96,0x30,0x63,0x76,0xc6,0x3a,0x86,
2968
0xc7,0x18,0xc2,0xc8,0x96,0xb4,0x18,0xb2,0x65,0xdf,0x97,0x54,0x96,0x44,0xab,0x51,
2969
0xa9,0xb4,0xd2,0x4a,0x2a,0x5b,0x92,0xb2,0x57,0x88,0x94,0x68,0x51,0xa6,0x08,0x49,
2970
0x24,0xa4,0xde,0x37,0xa5,0xfa,0x7e,0x67,0xee,0xff,0xe6,0x78,0x3e,0xde,0xf4,0xd6,
2971
0xdb,0x3a,0xcf,0xf1,0xf3,0x3f,0xe7,0xdc,0x73,0xcf,0x7e,0xce,0x3d,0x77,0x9d,0xa5,
2972
0x53,0x56,0x4e,0x79,0x65,0xca,0xba,0x29,0xaf,0x4f,0xd9,0x34,0xe5,0xed,0x29,0x5b,
2973
0xa7,0xe4,0x4e,0xd9,0x31,0x65,0xf7,0x94,0xbd,0x53,0x3e,0x9f,0x72,0x68,0xca,0x57,
2974
0x53,0xbe,0x99,0x72,0x6c,0x8a,0x93,0x13,0x9e,0x53,0x20,0xa7,0x70,0x4e,0xd1,0x9c,
2975
0x12,0x39,0xe7,0xe6,0x9c,0x9f,0x53,0x3e,0xe7,0x02,0x4c,0xd5,0x9c,0x1a,0x39,0x71,
2976
0x39,0x49,0x39,0xb5,0x73,0xea,0xe5,0xa4,0xe5,0x34,0xc9,0x69,0x96,0x73,0x51,0x4e,
2977
0x56,0x4e,0xbb,0x9c,0x4b,0x72,0x2e,0xcb,0xe9,0x92,0x73,0x55,0x4e,0xaf,0x9c,0xbe,
2978
0x39,0x03,0x73,0x86,0xe6,0x8c,0xcc,0x19,0x93,0x33,0x36,0xe7,0x86,0x9c,0xc9,0x39,
2979
0xb7,0xe6,0xe4,0xe4,0xdc,0x95,0x73,0x6f,0xce,0x03,0xf9,0xe6,0x6f,0x60,0xcc,0xdf,
2980
0x1f,0x2f,0x2f,0x0a,0x84,0x39,0x4e,0xb6,0xec,0xe1,0xd8,0x13,0xd0,0x44,0xb9,0x7d,
2981
0xb8,0x97,0x86,0xb9,0xf6,0x2a,0x68,0x3c,0x3a,0xc0,0x71,0xb5,0x09,0x9e,0x49,0x96,
2982
0xdd,0xdb,0xcf,0xf3,0x6f,0x64,0x12,0x09,0x73,0xd5,0x27,0xf5,0x4b,0xc3,0xa4,0x05,
2983
0xa4,0x05,0xd1,0xc6,0x4a,0x23,0xa8,0xfd,0x82,0xda,0x2f,0xa8,0xfd,0x82,0x0a,0x9f,
2984
0xa9,0xed,0x99,0xda,0x9e,0xa9,0xed,0x99,0xda,0xde,0x4a,0xf1,0xb7,0x56,0xb8,0xd6,
2985
0x0a,0xd7,0x5a,0xe1,0x5a,0x5b,0xdb,0x4d,0xf8,0xf6,0x0a,0xd7,0x5e,0xe1,0xda,0x2b,
2986
0x5c,0x7b,0x6d,0xef,0x24,0xff,0x6c,0x85,0xcb,0xb6,0xdc,0x7e,0x69,0x98,0xd4,0xab,
2987
0x4b,0x53,0x9e,0x6e,0x2a,0x4f,0x77,0xed,0xd7,0x5d,0xfb,0x75,0xd7,0x7e,0xdd,0x15,
2988
0xbe,0xb7,0xb6,0xf7,0xd6,0xf6,0xde,0xda,0xde,0x5b,0xdb,0xfb,0x2b,0xfe,0x01,0x0a,
2989
0x37,0x40,0xe1,0x06,0x28,0xdc,0x00,0x6b,0xbb,0x09,0x3f,0x4c,0xe1,0x86,0x29,0xdc,
2990
0x30,0x85,0x1b,0xa6,0xed,0xa3,0xe4,0x3f,0xca,0xaa,0xff,0x70,0xe5,0x3b,0x5c,0xee,
2991
0x08,0xb9,0x23,0xe4,0xae,0x2a,0x77,0x55,0xb5,0x93,0x4f,0xe5,0xf3,0xc9,0xed,0x97,
2992
0xdb,0x2f,0x77,0xa4,0xdc,0x91,0x72,0x17,0x96,0xdb,0x68,0x13,0xe9,0x55,0xd2,0xa0,
2993
0xd2,0xed,0x2e,0x0d,0x2a,0xdd,0xee,0xd2,0xa0,0xe2,0xe9,0x2e,0x0d,0x2a,0x1f,0xdd,
2994
0xa5,0x41,0xc5,0xd3,0x5d,0x9a,0xa1,0x7c,0xf4,0x94,0x66,0x28,0x9e,0x9e,0xd2,0x0c,
2995
0xc5,0xd3,0x53,0x9a,0xa1,0x76,0xea,0x29,0x6d,0xa6,0xfd,0x7a,0x59,0xfd,0x2a,0x4c,
2996
0xed,0x11,0x26,0x77,0xb8,0xdc,0xe1,0x72,0x47,0xc8,0x1d,0x21,0x77,0x55,0xb9,0xab,
2997
0xca,0x1d,0x29,0x6d,0xee,0xb8,0xfe,0x57,0xcb,0x6e,0xe2,0xbf,0x5a,0xda,0x42,0xe9,
2998
0xf7,0x91,0x5e,0xa4,0xfa,0xed,0x2b,0xbd,0x48,0xfe,0x7d,0xad,0xed,0x85,0xe5,0x2e,
2999
0x2c,0xf7,0x62,0xc7,0x75,0x1b,0x6d,0xa5,0xfd,0xfa,0x4b,0x5b,0x69,0xbf,0xfe,0xd2,
3000
0x56,0xda,0xaf,0xbf,0x74,0xa9,0xdf,0xb5,0xb7,0x56,0xb9,0x06,0x48,0x5b,0xab,0x5c,
3001
0x03,0xa4,0xc6,0x5d,0x48,0x6e,0xa3,0x17,0x2b,0xfe,0xc1,0xd2,0x8b,0x15,0xff,0x60,
3002
0xe9,0xc5,0x8a,0x7f,0xb0,0xb4,0xad,0xc2,0x0d,0x91,0xb6,0x55,0xf9,0x87,0x48,0xdb,
3003
0x6a,0xbf,0x21,0xd2,0xb6,0xda,0x6f,0x88,0xb4,0x9d,0xfc,0x87,0x4a,0xdb,0xc9,0x7f,
3004
0xa8,0xb4,0xbd,0xda,0x69,0x98,0xb4,0xbd,0xca,0x31,0x4c,0xda,0x5e,0xe5,0x18,0x26,
3005
0x6d,0xaf,0xf1,0x3a,0x4c,0xda,0x5e,0xe5,0x1a,0x26,0x6d,0xaf,0x76,0x1c,0x26,0xed,
3006
0xa8,0x7c,0x8e,0x90,0x76,0x92,0x8e,0xb2,0xdc,0x66,0x5c,0x5d,0xaa,0xf2,0x8d,0x96,
3007
0x5e,0xaa,0x7e,0x30,0x5a,0x7a,0xa9,0xf2,0x3b,0xda,0x2a,0x9f,0xa9,0xdb,0xd2,0xaa,
3008
0xdb,0xd2,0x4a,0xbb,0xb4,0xd2,0x2e,0xad,0xb1,0x73,0xa9,0x35,0x8e,0x46,0x5b,0x63,
3009
0x69,0xb4,0xd5,0x0f,0x4c,0xdf,0xba,0x48,0xfd,0xac,0xaf,0xb4,0x95,0xfc,0x5b,0xc9,
3010
0xdd,0x5f,0xda,0x48,0xfb,0x65,0x4b,0x33,0xa5,0xbd,0xa5,0xad,0xa5,0x03,0xac,0xfa,
3011
0x2d,0xac,0x3c,0x15,0xb6,0xe6,0xc9,0x70,0x6b,0x8e,0x09,0xb7,0xfc,0x7d,0x96,0xbf,
3012
0xcf,0xf2,0x2f,0x6c,0xf9,0xdb,0xf1,0x38,0x96,0xbf,0x63,0x1d,0x27,0xc2,0xad,0x39,
3013
0xd6,0x9b,0xa7,0x22,0x2d,0x7f,0xcf,0xbe,0x46,0xed,0xbc,0x47,0x9a,0xa1,0x7c,0xf6,
3014
0x94,0xb6,0x90,0xf6,0xb1,0xca,0x57,0x55,0xe5,0xab,0x6a,0xb9,0xc3,0x2d,0x3f,0x63,
3015
0x5f,0xec,0x73,0xc3,0xdf,0xe1,0x77,0xf5,0x6a,0xab,0x1d,0x4c,0x9b,0x78,0xed,0xe1,
3016
0xb5,0x45,0x86,0xda,0xbd,0xa7,0x35,0xfe,0x1c,0x8d,0x37,0xc7,0x3a,0xee,0xf9,0xac,
3017
0x63,0x86,0x4f,0xf9,0xf7,0x29,0xff,0x46,0xb7,0x4a,0xbf,0xb1,0x8e,0xa3,0x45,0xb4,
3018
0x4f,0x11,0xb9,0x8b,0xc9,0x5d,0x4c,0xf3,0x61,0x11,0xcd,0x87,0x45,0xe4,0x2e,0x26,
3019
0x77,0x31,0xb5,0x6f,0x11,0xb5,0x6f,0x11,0xb9,0x8b,0xc9,0x5d,0x4c,0xe5,0x2f,0xa2,
3020
0xb2,0x17,0x91,0xbb,0x98,0xdc,0xc5,0x34,0x9e,0x8b,0x68,0x3c,0x17,0x91,0xbb,0x98,
3021
0xdc,0xc5,0xd4,0x8e,0x45,0xd4,0x86,0x45,0xe4,0x2e,0x26,0x77,0x31,0x8d,0xe7,0xca,
3022
0xea,0xef,0x95,0x35,0x7e,0x2b,0x6b,0xfc,0x56,0xd6,0xfc,0x5b,0x58,0xf3,0x6f,0x61,
3023
0xab,0x9d,0xb3,0xad,0xf9,0xdf,0x3b,0xae,0x56,0xb1,0x8e,0xe3,0xe1,0xd6,0x31,0x30,
3024
0xdc,0x3a,0xce,0x87,0x5b,0xc7,0x48,0xcf,0x3f,0x52,0x7e,0x91,0x96,0x3b,0xdc,0xf2,
3025
0x0b,0xd7,0x38,0x0e,0xd7,0xb8,0x0e,0x57,0x7e,0x7a,0xf8,0xdd,0x76,0x37,0x65,0x1d,
3026
0x85,0xfd,0x1a,0x18,0xe7,0x77,0xe7,0x82,0x51,0x5a,0x33,0x45,0x68,0xbd,0x14,0x29,
3027
0x2d,0x28,0xad,0x2a,0x0d,0x93,0x9a,0xb9,0xa5,0x9b,0xdf,0x1d,0x9f,0xa6,0x2e,0x46,
3028
0xc2,0x34,0xbf,0xdb,0x37,0x4c,0x3b,0x17,0x0f,0x3b,0x3e,0x66,0x96,0xf8,0xdd,0x7d,
3029
0x82,0xd8,0xeb,0x5a,0x6b,0xb3,0x59,0xd2,0xa9,0x0a,0x67,0xe6,0xfd,0x69,0xb2,0xdf,
3030
0x23,0x9d,0x2e,0x7d,0x58,0xfa,0xb8,0x74,0xb6,0x17,0xb7,0x95,0xce,0x74,0xd9,0x1f,
3031
0x97,0xce,0x97,0xff,0x22,0x2f,0x7e,0x6b,0x1f,0xa3,0xaf,0xda,0x79,0x94,0xdd,0xf3,
3032
0x5b,0x61,0x85,0x31,0xfa,0x9a,0x74,0x01,0xbc,0xa0,0x34,0x36,0xcb,0x6f,0xb3,0xf6,
3033
0x59,0x03,0x2b,0xe1,0x45,0x58,0x05,0xab,0xe1,0x5e,0xa5,0xff,0x28,0x94,0x0c,0x77,
3034
0xeb,0xc7,0xa8,0x09,0x5f,0x3c,0xdc,0xdd,0x3f,0x42,0xee,0xf3,0xe4,0x3e,0x57,0xe1,
3035
0xa2,0xc3,0xdd,0xf6,0x38,0x57,0x5a,0x5b,0x9a,0xac,0xed,0xc9,0xda,0x2f,0x51,0xfb,
3036
0x75,0x90,0xbb,0x8e,0xdc,0xb5,0x15,0xae,0xb1,0xf6,0x1b,0x1a,0xae,0xbe,0x2d,0x3d,
3037
0x5b,0xfe,0x29,0xd2,0xa2,0xd2,0x38,0xcb,0x5d,0x40,0xee,0x02,0xca,0xb7,0x97,0xbe,
3038
0xd1,0xad,0xf2,0x7f,0x5f,0x7a,0xb6,0x34,0x45,0x7a,0x8e,0xb4,0x96,0xd4,0x94,0x23,
3039
0x5c,0xf9,0x0a,0x97,0xbb,0x80,0xdc,0x46,0xcb,0x4a,0x1b,0x48,0xf7,0x4a,0x3f,0x93,
3040
0xc6,0x48,0x5b,0x4a,0xa3,0x15,0x4f,0x63,0x69,0xb4,0xfc,0x1b,0x5b,0xdb,0x0b,0xc9,
3041
0x6d,0xb4,0x8a,0xfc,0x33,0xa4,0xd5,0xa5,0x2d,0xa4,0x3d,0x03,0x8c,0x4b,0x18,0x0f,
3042
0x7d,0x60,0x18,0x54,0x89,0x60,0xcc,0x47,0xb8,0xda,0x0e,0x9a,0x49,0x8d,0xbb,0x3d,
3043
0x34,0xb7,0xdc,0x43,0xb5,0xdd,0xe8,0x5a,0x69,0x73,0xe9,0x3b,0x0a,0xb7,0x4a,0xba,
3044
0x59,0x5a,0x35,0xca,0x71,0xea,0x41,0x9c,0x34,0x51,0x5a,0x52,0x7a,0xb6,0xf4,0x1c,
3045
0xe9,0xf9,0xd2,0x0a,0xd2,0x8a,0xd2,0xea,0xd2,0x9a,0xd2,0xb5,0xb0,0x5c,0xfa,0x1e,
3046
0xcc,0x84,0xa5,0xf0,0x88,0x74,0xae,0x34,0xa1,0x20,0xe1,0xa1,0xb6,0xf4,0x6c,0xe9,
3047
0x39,0xd2,0xf3,0xa5,0xd5,0xa5,0x19,0x85,0xe8,0x67,0x85,0x5c,0x6d,0x20,0xed,0x08,
3048
0x15,0xa0,0x1e,0x54,0x94,0xde,0x01,0xef,0xc1,0x1a,0x58,0x0e,0x6b,0xa5,0x6b,0xe4,
3049
0xdf,0xb4,0x30,0xf1,0xc0,0x0a,0x78,0x07,0xd6,0x58,0xfa,0xae,0x74,0xb5,0xa5,0x66,
3050
0x5b,0xd3,0x33,0x48,0x13,0x32,0xa4,0xc6,0xdd,0x11,0xde,0x87,0xf5,0xd2,0x37,0x2d,
3051
0xf5,0xfc,0xb6,0x43,0xcb,0x33,0x29,0x2b,0x6c,0x84,0x05,0x30,0x07,0xa6,0x4b,0x67,
3052
0x42,0xa1,0x22,0x8e,0x93,0x0e,0x8b,0xe1,0x22,0x69,0x1b,0x69,0x07,0x69,0x67,0x69,
3053
0x1a,0x2c,0x82,0x41,0x30,0x58,0x3a,0x14,0x16,0xc0,0x58,0xe9,0x20,0xd9,0x17,0x5a,
3054
0xea,0xf9,0x79,0x7a,0x87,0xe2,0x7b,0x40,0x3a,0x53,0xfa,0x84,0x74,0x8e,0x34,0x47,
3055
0xe9,0x55,0x2a,0xea,0x38,0xb1,0x90,0x0b,0x81,0xd2,0x8c,0x43,0x88,0x94,0x46,0x49,
3056
0x0b,0x49,0xcf,0x90,0x16,0x93,0xd6,0x91,0xd6,0x93,0x36,0x90,0x36,0x94,0xa6,0x4b,
3057
0xcd,0xf1,0xca,0x1c,0xc3,0xd3,0xb5,0x26,0x30,0xc7,0xab,0xdb,0x7d,0xee,0x7a,0xc0,
3058
0x1c,0xdb,0xbc,0xf3,0x80,0x16,0x5a,0xa3,0xb5,0xd4,0x9a,0xcc,0x1c,0x87,0x2a,0x32,
3059
0xcf,0x67,0x39,0xee,0x31,0xd5,0x1c,0x17,0xcd,0xb1,0xd3,0xac,0x37,0xcd,0xb1,0x2f,
3060
0x8b,0x6d,0x6d,0xc0,0x5f,0xc6,0x71,0xba,0x6a,0x9d,0x61,0x8e,0x81,0x9d,0xf0,0xeb,
3061
0x0c,0x97,0xf9,0xdd,0xb5,0x86,0x59,0xd7,0xf4,0x33,0xf1,0xfb,0xdc,0xe3,0x59,0x3b,
3062
0xfc,0xcf,0x66,0x9f,0x73,0x60,0xa0,0xe3,0x1e,0x67,0xcd,0xb1,0xb8,0x0c,0xee,0x01,
3063
0x6c,0x1b,0x8e,0xbd,0x52,0x19,0x77,0x5e,0x5e,0x08,0xcf,0x69,0x1e,0x5e,0xab,0x35,
3064
0xc1,0x60,0x85,0x37,0xe1,0xbc,0x30,0xab,0xac,0x30,0xf5,0x19,0xfb,0x17,0xfb,0xdd,
3065
0xf3,0xbb,0xf6,0xe8,0x21,0xc7,0xcd,0x4b,0x0f,0xf4,0x4a,0x34,0x1b,0xba,0x43,0x2f,
3066
0xe8,0x6d,0x8e,0x9f,0xe6,0xb8,0x49,0x7a,0x0f,0xa2,0xfd,0x60,0x22,0xf6,0x87,0xd1,
3067
0x41,0x30,0x10,0x06,0xc3,0x10,0x18,0x0a,0xc3,0x60,0x24,0x8c,0x87,0x09,0x30,0x87,
3068
0x32,0xdd,0x84,0xde,0x0c,0xe7,0xb3,0xdf,0x2d,0xe8,0xad,0x7e,0x77,0xbd,0x95,0x83,
3069
0x4e,0xf5,0xbb,0xeb,0xb3,0x17,0xb4,0x6e,0xa8,0xa4,0x75,0x83,0xd1,0x74,0x1d,0x93,
3070
0xbb,0x4a,0x8d,0x3b,0x5a,0xee,0x68,0xb9,0xe3,0xe5,0x8e,0xb7,0xae,0x47,0xf8,0xac,
3071
0x73,0x79,0x9f,0xd6,0x7b,0x91,0x5a,0x73,0x47,0xca,0x1d,0x2d,0x77,0xb4,0xdc,0xf1,
3072
0x72,0xc7,0xcb,0x5d,0x45,0xee,0x2a,0x72,0xc7,0xc8,0x1d,0x63,0x9d,0xff,0x3a,0xd6,
3073
0x39,0xb0,0x63,0xf9,0xfb,0x2c,0x7f,0xef,0x7a,0x48,0x8c,0xfc,0xbc,0xfd,0xe3,0xe4,
3074
0x8e,0xb3,0xd6,0x47,0x11,0xd6,0x1a,0xc9,0xd8,0x9b,0x2a,0xbf,0x3d,0xac,0xf3,0xde,
3075
0x70,0xad,0x4f,0xc3,0xb5,0xee,0x8a,0xd4,0x3a,0x27,0x52,0xee,0x68,0xb9,0xa3,0xe5,
3076
0x2e,0x20,0x77,0x01,0xb9,0xab,0xc8,0xed,0x9d,0x37,0xc7,0xca,0x1d,0xab,0x75,0x65,
3077
0x9c,0xfa,0x50,0x9c,0x75,0x7d,0xc6,0x67,0x5d,0xdb,0xf0,0x69,0x3d,0xee,0xd3,0x7a,
3078
0xdc,0x73,0x47,0xcb,0x1d,0x2d,0x77,0xbc,0xdc,0xf1,0x3a,0xbf,0x89,0xd6,0x79,0x6f,
3079
0xb4,0xe5,0x0e,0xb7,0xfc,0xc2,0xe5,0x1f,0x2f,0x3f,0x6f,0xbf,0x18,0xb9,0x8d,0xb6,
3080
0x54,0x7a,0xfd,0xa4,0x2d,0x55,0xee,0x7e,0xd2,0x96,0x8a,0xab,0x9f,0xb4,0x95,0xfc,
3081
0xfb,0x4b,0x5b,0xc9,0xbf,0xbf,0xb5,0x3d,0x5e,0xee,0x78,0xb9,0x63,0xe4,0x8e,0xb1,
3082
0xd6,0xa3,0x3e,0x6b,0x3d,0xea,0xb3,0xfc,0x0b,0x58,0xfe,0x05,0xc2,0x8e,0x9f,0x87,
3083
0x3b,0xd6,0xb9,0xb8,0x63,0xf9,0xfb,0x2c,0x7f,0x63,0xcf,0x52,0x39,0x06,0x3a,0xc7,
3084
0xdd,0x91,0x72,0x47,0x6a,0x9d,0x1e,0xa9,0x75,0xba,0xe7,0x8e,0x96,0x3b,0xda,0x72,
3085
0x87,0x5b,0x7e,0xe1,0xf2,0x8f,0x97,0x5f,0xbc,0xd6,0xef,0x91,0x5a,0xbf,0x47,0xca,
3086
0x1d,0x2d,0x77,0xb4,0x75,0x7e,0x1f,0x69,0x9d,0xe3,0x47,0x5a,0xe7,0xf1,0x91,0xd6,
3087
0xb9,0xbc,0xbd,0x7f,0xa4,0x15,0x47,0xa4,0xce,0x0b,0x22,0x75,0x5e,0xe0,0xb9,0xa3,
3088
0xe5,0x8e,0x96,0x3b,0x5e,0xee,0x78,0xb9,0x63,0xe4,0x8e,0xd1,0x79,0xc7,0x05,0x3a,
3089
0xef,0xb8,0x40,0xee,0x38,0xb9,0xe3,0xe4,0x8e,0x91,0x3b,0xc6,0xba,0x6e,0xe0,0xb3,
3090
0xae,0x1d,0xf8,0xac,0xeb,0x07,0x05,0xac,0x6b,0x08,0xc6,0xde,0x41,0x61,0x86,0x4b,
3091
0x3b,0x28,0x5f,0xc3,0xa5,0x1d,0x75,0x9e,0x37,0x42,0xda,0x51,0x75,0x31,0x42,0xda,
3092
0x51,0x63,0x60,0x84,0xb4,0xa3,0xca,0x39,0x42,0xda,0x51,0xf1,0x8c,0x90,0x5e,0x22,
3093
0xff,0x91,0xd2,0x4b,0xb4,0xdf,0x48,0xeb,0x3a,0x65,0xa4,0xce,0x57,0xbc,0xeb,0x0b,
3094
0x7e,0x5d,0x5f,0xf0,0xcb,0x1d,0x2d,0x77,0xb4,0xdc,0xf1,0x72,0xc7,0x6b,0xdc,0x7a,
3095
0xf5,0xe9,0xe5,0xab,0xa0,0xe2,0x2b,0xa8,0x79,0x74,0x39,0x73,0xeb,0xf5,0x3e,0x37,
3096
0xfe,0x46,0x8a,0x27,0x5b,0x6a,0xdc,0x51,0x72,0x47,0x59,0xd7,0x7b,0xed,0x6b,0xa5,
3097
0xf6,0x75,0x60,0xc7,0xf2,0x77,0x2c,0xff,0x28,0xcb,0xdf,0x8e,0x27,0xcc,0xf2,0x0f,
3098
0xb3,0xd2,0xf7,0x5b,0x79,0xf0,0x5b,0xd7,0x2f,0x7d,0xd6,0x35,0x4c,0x9f,0xe5,0xef,
3099
0x58,0xfe,0x8e,0xe5,0x1f,0x65,0xf9,0x47,0x59,0xfe,0x61,0x96,0xbf,0x9d,0x6e,0x84,
3100
0x95,0xae,0x77,0x9d,0x32,0x5a,0x73,0x6e,0xb4,0xdc,0x51,0x72,0x47,0xc9,0x1d,0x26,
3101
0x77,0x98,0x75,0x5d,0xdb,0xbe,0x26,0x6c,0x5f,0xef,0x76,0x2c,0x7f,0xc7,0xf2,0x8f,
3102
0xb2,0xfc,0xa3,0x2c,0xff,0x30,0xcb,0x3f,0xcc,0xca,0x8f,0xdf,0xca,0x93,0x77,0x3d,
3103
0x33,0x4a,0x73,0x70,0x94,0xdc,0xd1,0x72,0x47,0x6b,0x7e,0x89,0xd6,0xdc,0xe2,0xb9,
3104
0xa3,0xe4,0x8e,0xb2,0xae,0xa3,0xdb,0xd7,0xa0,0xed,0xeb,0xeb,0x8e,0xe5,0xef,0x58,
3105
0xfe,0x51,0x96,0xbf,0x1d,0x4f,0x98,0xe5,0x1f,0x66,0xa5,0xef,0xb7,0xf2,0xe0,0x5d,
3106
0xb7,0x2f,0x6d,0xa5,0x5b,0xda,0x4a,0xb7,0xb4,0x95,0x6e,0x69,0x2b,0xdd,0xd2,0x56,
3107
0xba,0xa5,0xad,0x74,0x4b,0x5b,0xe9,0x96,0xb6,0xd2,0x35,0xf6,0x68,0xcb,0x3f,0x5a,
3108
0xe3,0x3f,0x5a,0x63,0xdf,0x73,0x47,0xc9,0x1d,0x65,0x5d,0xa3,0xf3,0x59,0xd7,0xe9,
3109
0x7c,0x96,0xbf,0x63,0xf9,0x3b,0x96,0x7f,0x94,0xe5,0x6f,0xc7,0x13,0x66,0xf9,0x87,
3110
0x59,0xfe,0xd1,0x96,0x7f,0xb4,0xc6,0xbb,0xa3,0xf1,0xe9,0xc8,0x1d,0x2d,0xb7,0xb7,
3111
0x3d,0x4a,0xee,0x28,0xb9,0xc3,0xe4,0x0e,0xd3,0xb9,0x7d,0x71,0x69,0x09,0xcb,0xed,
3112
0x58,0x7e,0x8e,0xe5,0xef,0xb3,0xfc,0x7d,0x96,0x7f,0xba,0xe5,0x9f,0xae,0x6b,0x11,
3113
0xc5,0xa5,0x25,0x2c,0xb7,0x63,0xf9,0x39,0x96,0xbf,0xcf,0xf2,0xf7,0x59,0xfe,0xe9,
3114
0x96,0x7f,0xba,0xae,0x01,0x14,0x97,0x96,0xb0,0xdc,0x8e,0xe5,0xe7,0x58,0xfe,0x3e,
3115
0xcb,0xdf,0xd8,0xa7,0xc9,0x7f,0x9a,0xfc,0xa6,0x59,0xfb,0x4f,0xb3,0xf6,0x9f,0x66,
3116
0xed,0x3f,0xcd,0xda,0x7f,0xb1,0xfc,0x17,0xcb,0x6f,0xb1,0xb5,0xff,0x62,0x6b,0xff,
3117
0xc5,0xd6,0xfe,0x8b,0x4f,0xb2,0x7f,0xba,0xe5,0x9f,0xae,0xeb,0x34,0xc5,0xa5,0x25,
3118
0x2c,0xb7,0x63,0xf9,0x39,0x96,0xbf,0xcf,0xf2,0xf7,0x59,0xfe,0xe9,0x96,0x7f,0xba,
3119
0xae,0xc7,0x14,0x97,0x96,0xb0,0xdc,0x8e,0xe5,0xe7,0x58,0xfe,0x3e,0xcb,0xdf,0x67,
3120
0xf9,0xa7,0x5b,0xfe,0xe9,0xba,0x46,0x54,0x5c,0x5a,0xc2,0x72,0x3b,0x96,0x9f,0x63,
3121
0xf9,0xfb,0x2c,0x7f,0x9f,0xe5,0x9f,0x6e,0xf9,0xa7,0xeb,0x7a,0x51,0x71,0x69,0x09,
3122
0xcb,0xed,0x58,0x7e,0x8e,0xe5,0xef,0xb3,0xfc,0xbd,0xeb,0x5b,0xc5,0xa5,0x25,0x2c,
3123
0xb7,0x63,0xf9,0x39,0x96,0xbf,0xcf,0xf2,0xf7,0xae,0x53,0x15,0x97,0x96,0xb0,0xdc,
3124
0x8e,0xe5,0xe7,0x58,0xfe,0x3e,0xcb,0xdf,0xde,0x3f,0xdd,0xf2,0x4f,0xd7,0x75,0xae,
3125
0x12,0x96,0x3a,0x96,0xdd,0x67,0xd9,0xd3,0x75,0x8d,0xac,0xb8,0xb4,0x84,0xe5,0x76,
3126
0x2c,0x3f,0xc7,0xf2,0xf7,0x59,0xfe,0x3e,0xcb,0x3f,0xdd,0xf2,0x4f,0xd7,0xb5,0xbe,
3127
0xe2,0xd2,0x12,0x96,0xdb,0xb1,0xfc,0x1c,0xcb,0xdf,0x67,0xf9,0xfb,0x2c,0xff,0x74,
3128
0xcb,0xdf,0x1b,0xf7,0x4e,0xc8,0x75,0x42,0x27,0xe4,0x7a,0xa1,0x13,0x72,0xdd,0xd0,
3129
0xb1,0xae,0x1f,0xae,0xb0,0xda,0xd4,0xab,0x43,0x27,0xe4,0x9a,0xa1,0x63,0x5d,0x3b,
3130
0xf4,0xe6,0x9c,0xa0,0x35,0xe7,0x04,0x43,0xe6,0xae,0x60,0xc8,0xfc,0x15,0x0c,0x99,
3131
0xc3,0x82,0x21,0xf3,0x58,0x30,0x64,0x2e,0x0b,0x86,0xcc,0x67,0x41,0x6b,0x4e,0x0a,
3132
0x5a,0x73,0x52,0x30,0x64,0x6e,0x0b,0x86,0xcc,0x6f,0xc1,0x90,0x39,0x2e,0x18,0x32,
3133
0xcf,0x05,0x43,0xe6,0xba,0x60,0xc8,0x7c,0x17,0xb4,0xe6,0x8c,0xa0,0x35,0x67,0x04,
3134
0x43,0xe6,0x9e,0x60,0xc8,0xfc,0x13,0x0c,0x99,0x83,0x82,0x21,0xf3,0x50,0x30,0x64,
3135
0x2e,0x0a,0x86,0xcc,0x47,0x41,0x6b,0x4e,0x09,0x5a,0x73,0x4a,0x30,0x64,0x6e,0x0a,
3136
0x86,0xcc,0x4f,0xc1,0x90,0x39,0x2a,0x18,0x32,0x4f,0x05,0x43,0xe6,0xaa,0x60,0xc8,
3137
0x7c,0x15,0xb4,0xfa,0x6f,0xd0,0xea,0xbf,0xc1,0x90,0x71,0x10,0x0c,0x19,0x0b,0xc1,
3138
0x90,0xf1,0x10,0x0c,0x19,0x13,0xc1,0x90,0x71,0x11,0x0c,0x19,0x1b,0x41,0xab,0x7f,
3139
0x07,0xad,0xfe,0x1d,0x0c,0x19,0x27,0xc1,0x90,0xb1,0x12,0x0c,0x19,0x2f,0xc1,0x90,
3140
0x31,0x13,0x0c,0x19,0x37,0xc1,0x90,0xb1,0xe3,0xf5,0xb3,0x08,0x69,0xb8,0x35,0x9e,
3141
0xbc,0x6d,0x41,0x6b,0x6c,0x79,0xf6,0x74,0x4b,0xbd,0x3e,0x13,0x21,0x0d,0x97,0x3a,
3142
0xd6,0x3d,0x81,0xa9,0x0a,0x67,0xee,0x19,0x78,0xc7,0x03,0xcf,0x6e,0x34,0x5d,0xf7,
3143
0x11,0xd2,0xad,0xf1,0xea,0xf5,0x89,0xa0,0x35,0x76,0x3d,0x7b,0xba,0xa5,0x41,0x1d,
3144
0x23,0xbd,0xe3,0xa6,0x77,0x3c,0x72,0xac,0xfb,0x0f,0xf7,0x28,0xdc,0x8a,0x72,0x1a,
3145
0xeb,0xe5,0x34,0xf6,0xcb,0x1d,0x3f,0xb6,0x44,0x48,0xc3,0xad,0xfb,0x08,0x4e,0xc8,
3146
0xbd,0x89,0x25,0xd6,0xb1,0xa8,0x80,0x75,0xfc,0x88,0x90,0x86,0x4b,0x1d,0xeb,0x9e,
3147
0xc7,0x0f,0x4a,0xf3,0x87,0x72,0xc7,0xdd,0xde,0xfc,0x1c,0x21,0x0d,0xb7,0xee,0x59,
3148
0x38,0x21,0xf7,0x34,0x56,0xa9,0xfd,0x56,0x59,0xc7,0x84,0x74,0x2b,0x8c,0x37,0xbf,
3149
0x47,0x48,0xc3,0xa5,0x8e,0x75,0x9f,0x65,0xa6,0xf6,0x9d,0xa5,0x75,0x9a,0x77,0xcf,
3150
0xa6,0x8b,0x73,0x7c,0x7e,0xf3,0xfa,0x64,0xd0,0x9a,0xeb,0x3c,0x7b,0xba,0xa5,0x41,
3151
0x1d,0xb3,0x1c,0xeb,0x7e,0xce,0x6c,0x6b,0xee,0xf6,0xdc,0x26,0xdc,0x73,0xba,0x4f,
3152
0x64,0xd2,0xf6,0x63,0x09,0x2b,0x7f,0xfc,0x99,0x9f,0xff,0x44,0x51,0x85,0x4b,0x64,
3153
0xbf,0x58,0xe7,0xe4,0x98,0xed,0x09,0xe5,0xff,0x3f,0xc9,0x27,0xa1,0x82,0xe3,0x62,
3154
0xf6,0x09,0x10,0x67,0x43,0xe7,0x38,0xde,0xb6,0x86,0x27,0x89,0xcf,0x84,0x8f,0xd3,
3155
0xf3,0x12,0xe6,0x79,0xa2,0x64,0x48,0x81,0x5a,0x50,0x1b,0x52,0xa1,0x3a,0x9c,0x55,
3156
0xd1,0x71,0xea,0x9b,0xfb,0x6b,0x70,0xa1,0xee,0x6b,0xc7,0xe9,0xb9,0x24,0xef,0x99,
3157
0xa4,0x5f,0xb2,0x7f,0xb6,0xae,0xab,0x0e,0xd0,0x3d,0x39,0x73,0x7d,0xb5,0x97,0xae,
3158
0xab,0xf6,0xd5,0xb5,0x55,0x93,0xc6,0x40,0xdd,0xb7,0x33,0xe7,0xcb,0xde,0xfd,0xbf,
3159
0xd1,0xba,0x76,0x3b,0x44,0xf1,0xd4,0x74,0xdc,0x6b,0x87,0x9e,0xdd,0xf8,0x9b,0xeb,
3160
0x8a,0xf3,0xa4,0xdd,0xe4,0x3f,0xc0,0xb2,0x9b,0x35,0x7e,0x8e,0xcf,0x0d,0x63,0xae,
3161
0xd9,0xf5,0xd4,0x75,0x63,0x8f,0xbc,0xeb,0x6d,0x3e,0xf7,0xbc,0x2d,0x53,0xd7,0x90,
3162
0xfb,0xea,0x1a,0x72,0x2b,0xc5,0x65,0xae,0xfd,0xb4,0x51,0x5e,0x3c,0xda,0xea,0x5a,
3163
0x73,0x3b,0x5d,0x93,0xbe,0x48,0xf6,0x96,0xba,0x7f,0x3d,0x5b,0xd7,0x04,0x5a,0x38,
3164
0xc7,0xef,0x4d,0xa7,0x2b,0x9f,0xdd,0xb5,0x4f,0x53,0x85,0x37,0x69,0x6c,0x0a,0x38,
3165
0xce,0x5b,0xb0,0x19,0xb6,0x04,0xdc,0x76,0x6a,0xaa,0x7d,0xcd,0xb5,0x89,0x95,0xba,
3166
0x56,0x7c,0x27,0xcc,0x80,0x62,0x15,0xdd,0x6b,0x9f,0xde,0x75,0x6b,0xef,0x39,0x18,
3167
0xef,0xf9,0xb1,0x5a,0x96,0x3d,0xd5,0xb2,0xc7,0x5b,0xed,0x69,0xdc,0x89,0x6a,0x57,
3168
0xcf,0xee,0xf9,0x27,0x5b,0xfe,0xc9,0xd6,0xb3,0x68,0xc9,0x6a,0x7f,0xcf,0xee,0x85,
3169
0x4f,0x51,0x9f,0xf0,0xec,0x9e,0x7f,0x6d,0x6b,0xdf,0xda,0x56,0x98,0xda,0xea,0x3b,
3170
0x9e,0xdd,0x0b,0xef,0xb5,0xc3,0xc9,0xe8,0x60,0x91,0x69,0x69,0xa8,0xdd,0xe3,0x12,
3171
0x8b,0x4c,0x4b,0xbd,0x76,0x6e,0xac,0x7b,0x0a,0x2d,0x55,0x7f,0xa7,0x62,0xb8,0x45,
3172
0x6f,0x4b,0x43,0xed,0x1e,0x23,0x2d,0x7a,0x5b,0xda,0x5b,0x7d,0xab,0x9b,0xda,0xad,
3173
0x9f,0xda,0xc2,0xab,0xfb,0x1c,0x06,0x6f,0x6d,0xf3,0x4c,0x84,0xf4,0x2e,0xe9,0x26,
3174
0xe9,0xdb,0xd2,0xcd,0xd2,0xb0,0x8a,0xae,0x16,0x90,0x16,0x92,0x46,0x4b,0x2b,0x49,
3175
0xab,0x57,0xfc,0xff,0xc4,0x9e,0x84,0x7a,0x0a,0xdf,0x58,0x1a,0x94,0x36,0x93,0x9a,
3176
0x71,0x6d,0x34,0x5b,0xee,0x96,0xd2,0x7a,0xf2,0x6f,0x20,0xbd,0x4a,0xfe,0xdd,0xa5,
3177
0x83,0xa5,0x43,0xa4,0xc3,0xa5,0x23,0xa4,0xa3,0xa5,0xd7,0x48,0xc7,0x4b,0x27,0x48,
3178
0x6f,0x94,0x4e,0x92,0x3e,0x22,0x9d,0x25,0x9d,0x2d,0x9d,0x23,0x1d,0x23,0xbd,0x56,
3179
0x3a,0x55,0x7a,0x87,0x74,0x81,0x74,0xa1,0xf4,0x39,0xe9,0x22,0xaf,0x3e,0x69,0x94,
3180
0xa8,0xb8,0xd3,0x9b,0xf3,0xec,0xf1,0x14,0x6f,0xcd,0x93,0xf1,0xce,0xf1,0xf1,0xe4,
3181
0x3d,0xd7,0xe9,0x8d,0x17,0x6f,0x7c,0x78,0x63,0xd4,0xeb,0xff,0xa9,0xda,0x37,0x4e,
3182
0xf3,0x67,0xbc,0xe6,0xd0,0xaa,0xf2,0xf7,0xec,0x89,0x96,0x3d,0xc9,0xb2,0x27,0x5b,
3183
0xf6,0x14,0xcb,0x5e,0xcb,0xb2,0xd7,0xb6,0xec,0xa9,0x96,0xdd,0x2b,0x87,0xed,0x8e,
3184
0x0f,0x71,0x27,0x84,0xb8,0x13,0x43,0xdc,0x49,0x21,0xee,0xe4,0x10,0x77,0x4a,0x88,
3185
0xbb,0x56,0x88,0xbb,0x76,0x88,0x3b,0x35,0xa4,0xfc,0x5e,0xfe,0xe2,0x75,0xdc,0x4c,
3186
0x90,0x26,0x4a,0x93,0xa4,0xc9,0xd2,0x14,0x69,0x2d,0x69,0x6d,0x69,0xaa,0xd4,0x2b,
3187
0x73,0xac,0x55,0xde,0x58,0xab,0xac,0xb1,0x56,0x39,0x63,0xad,0x32,0xc6,0x5a,0xe5,
3188
0x8b,0xb5,0xca,0x16,0x6b,0x95,0x2b,0xd6,0x2a,0x53,0xac,0x55,0x9e,0x58,0xab,0x2c,
3189
0xb1,0x2a,0x5b,0xb6,0x55,0xce,0xae,0x96,0xbd,0x9b,0x65,0xbf,0xca,0xb2,0x77,0xb7,
3190
0xec,0x3d,0x2c,0x7b,0x4f,0xcb,0xde,0xcb,0xb2,0xf7,0xb6,0xec,0x57,0x5b,0xf6,0x3e,
3191
0x96,0xbd,0xaf,0x65,0xef,0x67,0xd9,0xfb,0x5b,0xf6,0x01,0x96,0x7d,0xa0,0x65,0x1f,
3192
0x64,0xd9,0x07,0x5b,0xf6,0x21,0x96,0x7d,0xa8,0x65,0x1f,0x66,0xd9,0x87,0x5b,0xf6,
3193
0x11,0x96,0x7d,0xa4,0x65,0x1f,0x65,0xd9,0x47,0xcb,0xde,0xc8,0x39,0x7e,0x3c,0x6d,
3194
0x62,0x1d,0x4f,0x4f,0xe7,0xbe,0xb0,0x7d,0x3c,0x6f,0x6b,0xdd,0x1b,0xee,0xa0,0xfb,
3195
0xc3,0xe6,0x38,0xd1,0x49,0xc7,0xf1,0x6c,0xb5,0x49,0x37,0xeb,0x58,0xdb,0x43,0x75,
3196
0xdd,0xcb,0x3a,0xee,0x86,0xae,0x67,0x06,0xa8,0x8e,0x06,0xa9,0x4e,0x86,0x58,0xf7,
3197
0x8a,0x87,0xab,0xac,0x23,0xad,0x75,0x8e,0xe9,0x0f,0xa1,0x73,0x74,0x1d,0xc7,0xa5,
3198
0xfe,0x29,0xf8,0xb0,0x9a,0x3b,0x5f,0x5d,0xad,0xbc,0x67,0xc7,0x38,0xce,0x46,0x32,
3199
0xf2,0xf0,0xc3,0x6e,0x61,0xab,0x42,0x0a,0x34,0x84,0x4e,0x30,0x11,0x6e,0x85,0x19,
3200
0xf0,0xa2,0xf1,0xa7,0x12,0xba,0x43,0x1f,0x18,0x0f,0x77,0xc3,0x1c,0xd8,0x01,0x5f,
3201
0xab,0x82,0xee,0x87,0xa3,0x50,0x92,0x8a,0x3a,0x0f,0x6a,0x43,0x23,0xb8,0x0c,0x7a,
3202
0xc3,0x78,0x78,0x1e,0xd6,0xc1,0x2e,0x78,0x8f,0x8c,0x94,0xa3,0x12,0xf7,0x53,0x89,
3203
0x7e,0x2a,0xb1,0x20,0x94,0x84,0x2a,0x30,0x04,0xb2,0x3a,0x3b,0xce,0x58,0xf8,0x06,
3204
0x8a,0x5c,0xe6,0x38,0x15,0xa1,0x36,0xf4,0x87,0x41,0xb0,0xed,0x72,0xc7,0xf9,0x04,
3205
0x0e,0xc3,0x0f,0x30,0xf8,0x0a,0xea,0x07,0xae,0x87,0xaf,0xe0,0x07,0x28,0x74,0x25,
3206
0xe7,0x11,0x90,0x05,0xd9,0x30,0x04,0x5e,0x86,0x02,0x34,0x54,0x0a,0xb4,0x80,0x9a,
3207
0x34,0x54,0x12,0x4c,0x82,0x7b,0xe0,0x31,0x58,0x02,0x3b,0xe0,0x13,0x38,0x44,0x23,
3208
0x16,0xa0,0x11,0xab,0x42,0x79,0xea,0xac,0x2b,0x8c,0x82,0x85,0xb0,0x01,0xde,0x86,
3209
0x6d,0x50,0x84,0x46,0x2d,0x01,0x49,0xd0,0x87,0x06,0xad,0x46,0x63,0xa6,0x40,0x5d,
3210
0x68,0x08,0x19,0xd0,0x09,0x3a,0xc3,0xd3,0x70,0x03,0x0d,0x7d,0x13,0xe4,0xd2,0xd8,
3211
0x7b,0xe0,0x5c,0x1a,0xbc,0x1c,0x54,0x85,0x38,0xb8,0x05,0xee,0x80,0xe1,0x74,0x82,
3212
0x6b,0xe1,0x59,0x58,0x01,0x5f,0xc0,0x36,0x3a,0xc5,0x4e,0x38,0x02,0x75,0xe8,0x18,
3213
0x2f,0xc0,0x72,0x18,0x4a,0x07,0xd9,0x00,0x47,0x61,0xc8,0x18,0xea,0x0e,0x52,0xae,
3214
0xa7,0x0f,0xc3,0xcd,0xb0,0x0c,0x7c,0x63,0x1d,0xa7,0x30,0x9c,0x05,0x89,0x70,0x3d,
3215
0xdc,0x04,0xbb,0xc6,0x39,0xce,0x3e,0x38,0x02,0xc7,0xa0,0xf0,0x78,0xc7,0x29,0x0d,
3216
0xe5,0xa0,0x3f,0x0c,0x86,0x91,0xd0,0xf2,0x46,0xca,0x07,0x69,0x93,0x19,0x2f,0xd0,
3217
0x0d,0xae,0xbb,0x89,0xfc,0xc2,0x66,0x70,0x6e,0x66,0x5e,0xbb,0x95,0x31,0x06,0xed,
3218
0x61,0x24,0x3c,0x08,0x57,0xdd,0x46,0x3f,0x87,0x85,0x30,0xe7,0x76,0xc7,0x59,0x0f,
3219
0xf7,0x4f,0x61,0xbd,0x0d,0x8b,0x60,0x6a,0x0e,0x63,0x71,0xaa,0xe3,0xac,0x81,0xd7,
3220
0xe1,0x2d,0x18,0x31,0x8d,0x3e,0x00,0xe7,0xdf,0x4d,0xdf,0x81,0x25,0xb0,0x17,0xda,
3221
0xdc,0xe3,0x38,0x57,0x40,0x57,0xe8,0x0d,0x1b,0xe0,0x00,0x1c,0x01,0xdf,0xbd,0x1c,
3222
0xef,0x61,0x1b,0x6c,0x87,0xbb,0xa7,0x73,0x5e,0x0a,0x4f,0xc3,0xac,0xfb,0x1c,0x67,
3223
0x2b,0x6c,0x87,0x4a,0xf7,0xd3,0xf6,0x90,0x00,0xf5,0xe0,0x52,0xf8,0xe4,0x01,0xc6,
3224
0xdd,0x43,0xd4,0x09,0x3c,0x0e,0x2f,0xc1,0xcb,0xb0,0x11,0xde,0x82,0xa3,0xf0,0x3d,
3225
0x9c,0xc9,0xb8,0x29,0x0e,0xe5,0xa1,0x2e,0x34,0x87,0x8b,0xe1,0x36,0x78,0x00,0x66,
3226
0x3c,0xec,0x9e,0x47,0x9d,0x15,0xe7,0x8e,0x81,0x26,0x10,0x84,0x16,0xb8,0xa7,0x43,
3227
0x4b,0x69,0x6b,0x69,0x1b,0x69,0x5b,0x69,0x7b,0x69,0x47,0x69,0x27,0x69,0x67,0xe9,
3228
0xe5,0xd2,0x2b,0xa5,0xd9,0xd2,0xab,0xa4,0x3d,0xa4,0xbd,0xa4,0x03,0x2c,0xbd,0x0f,
3229
0x06,0xcb,0x3d,0x58,0xee,0x61,0x72,0x0f,0x93,0x7b,0xa4,0xdc,0x23,0xe5,0xbe,0x46,
3230
0xee,0x6b,0xe4,0x6e,0x2a,0xb7,0x29,0xa3,0xa7,0xc6,0xff,0x41,0xf9,0x4f,0x86,0x9b,
3231
0x61,0x8e,0xdc,0xcf,0x48,0xe7,0x4a,0xe7,0x4b,0x17,0x4a,0x17,0x49,0x17,0x4b,0x97,
3232
0x48,0x5f,0x92,0x2e,0x93,0xae,0x90,0xae,0x92,0xbe,0x22,0x5d,0x23,0x5d,0x27,0x7d,
3233
0xd3,0x52,0x93,0xaf,0xcd,0x72,0x6f,0x96,0xfb,0x1d,0xb9,0xdf,0x91,0x7b,0xab,0xdc,
3234
0x5b,0xe5,0xde,0x26,0xf7,0x36,0xb9,0x9f,0x90,0xfb,0xa0,0xf4,0x90,0xf4,0xb0,0xf4,
3235
0x4b,0xe9,0xf7,0x56,0xb9,0x4c,0x5e,0x9c,0x62,0xf4,0x47,0x78,0x0a,0xfc,0xf0,0x34,
3236
0x3c,0x03,0x61,0x10,0x0e,0x01,0x98,0x07,0xf3,0x61,0x01,0x2c,0x84,0xe7,0x60,0x11,
3237
0x9c,0x07,0x11,0x10,0x09,0x05,0xa0,0x02,0x44,0x41,0x41,0x28,0x04,0x85,0xe1,0x0c,
3238
0x38,0x13,0x8a,0x40,0x51,0x28,0x06,0x67,0x41,0x36,0x74,0x85,0x6e,0x70,0x15,0x74,
3239
0x87,0x1e,0xd0,0x13,0x7a,0x41,0x6f,0xb8,0x1a,0xfa,0x40,0x5f,0xe8,0x07,0xfd,0x61,
3240
0x00,0x0c,0x84,0x41,0x30,0x18,0x86,0xc0,0x50,0x18,0x06,0x5d,0xa0,0x04,0x94,0x84,
3241
0xb5,0xb0,0x0e,0x5e,0x87,0x37,0x60,0x0b,0xbc,0x07,0xef,0xc3,0xf9,0xf0,0x21,0x6c,
3242
0x87,0x32,0x50,0x16,0xca,0x43,0x45,0x88,0x86,0x2a,0x70,0x21,0x54,0x87,0x1a,0x10,
3243
0x03,0xb1,0x50,0x13,0x12,0x20,0x05,0xd2,0x20,0x03,0x2e,0x82,0xc3,0xf0,0x25,0x74,
3244
0x84,0x4b,0xa0,0x13,0xdc,0x00,0x13,0x61,0x32,0x4c,0x85,0x3b,0xe0,0x2e,0x78,0x08,
3245
0x66,0x16,0x73,0x8f,0x69,0xe6,0xf8,0x15,0x05,0xdb,0x38,0xce,0x14,0x44,0x63,0xa0,
3246
0x10,0x24,0x0c,0x73,0x8f,0x71,0xa5,0xc0,0x07,0x17,0x72,0xac,0x89,0xeb,0xe8,0x1e,
3247
0xe7,0xcc,0xba,0xc1,0xb4,0x99,0xb7,0x86,0xf0,0x5b,0xf6,0x30,0xcb,0x1e,0xb0,0xec,
3248
0x11,0x96,0x3d,0xd2,0xb2,0x47,0x59,0xf6,0x42,0x96,0xbd,0xb0,0x65,0x3f,0xd3,0xb2,
3249
0x17,0xb1,0xec,0x45,0x2d,0x7b,0x31,0xcb,0x7e,0x96,0x65,0x77,0xd4,0xce,0x76,0x5e,
3250
0xb3,0x43,0xf2,0x9b,0x1d,0x92,0xe7,0xec,0x90,0x7c,0x67,0x87,0xe4,0x3d,0x3b,0x24,
3251
0xff,0xd9,0x21,0x65,0xc8,0x0e,0x29,0x47,0x76,0x48,0x59,0xb2,0x43,0xca,0x93,0x1d,
3252
0x52,0xa6,0xec,0x90,0x72,0x65,0x87,0x94,0x2d,0x34,0xfe,0xfe,0x21,0xe9,0xf7,0x56,
3253
0xbf,0x37,0xfd,0x79,0xce,0x49,0xb6,0x9d,0x15,0xb2,0x8f,0xe9,0x07,0x9e,0xfd,0x56,
3254
0xcb,0x1e,0x65,0xd9,0x4d,0xff,0xf0,0xec,0x77,0x59,0xfe,0xfd,0xda,0x58,0x75,0x69,
3255
0xf9,0xf7,0xb1,0xfc,0x2f,0xb7,0xfc,0xcd,0x3c,0xef,0xd9,0xcd,0x7a,0xe1,0xa7,0xf0,
3256
0x03,0xad,0x73,0xb0,0xbe,0xc7,0xed,0x55,0xad,0x30,0xe6,0x58,0xe7,0xd9,0xcd,0x9a,
3257
0xc8,0xb3,0x9b,0xf5,0x87,0x67,0xaf,0xd6,0xcb,0xca,0xbf,0xb5,0x6f,0x83,0x51,0xc7,
3258
0xed,0x67,0xb4,0xb3,0xd6,0xc2,0x83,0x8f,0xdb,0x67,0xde,0x6a,0xe5,0xd9,0x0a,0xff,
3259
0xdc,0xc5,0xc7,0xed,0xbb,0xac,0xb2,0x8c,0xb1,0xe2,0xe9,0xd1,0xd9,0x0a,0x33,0xfc,
3260
0xb8,0xdd,0xd7,0xfa,0xb8,0x7d,0xad,0x15,0x7f,0x3b,0xab,0x1e,0xfa,0x59,0x69,0x15,
3261
0xb3,0xc2,0x9b,0x75,0x86,0x67,0x3f,0x22,0x7b,0x6b,0x16,0xd6,0x63,0xae,0x70,0xd7,
3262
0x61,0x53,0xae,0x71,0xd7,0xde,0xde,0x35,0xb3,0x04,0xeb,0x5c,0x2b,0xc1,0x3a,0xd7,
3263
0x4e,0xd0,0x79,0x56,0x82,0x73,0xfc,0x3a,0x54,0x8a,0xb4,0x96,0xb4,0xb6,0x34,0x55,
3264
0xfb,0xc4,0x59,0xe7,0xdb,0x89,0x56,0x5c,0x89,0xd6,0xf9,0x7b,0xa2,0xe2,0x73,0x34,
3265
0x6f,0x87,0x69,0xae,0xf6,0xe6,0xe3,0x28,0x6b,0x0e,0x3e,0xd9,0xfc,0xeb,0x8d,0x4d,
3266
0x6f,0x4c,0x7a,0x63,0xd1,0x1b,0x83,0xde,0xd8,0xf3,0xc6,0x9c,0x37,0xd6,0xbc,0x31,
3267
0xe6,0x8d,0x2d,0x6f,0x4c,0x79,0x63,0xc9,0x1b,0x43,0xde,0xd8,0x39,0x2b,0x24,0xdc,
3268
0x62,0xa5,0xed,0x8d,0x93,0xfe,0x8a,0x73,0xa8,0xb4,0xff,0x49,0xe6,0x46,0xd3,0xe7,
3269
0x4d,0x5f,0x37,0x7d,0xdc,0xf4,0x6d,0xd3,0xa7,0x4d,0x5f,0x36,0x7d,0xd8,0xf4,0x5d,
3270
0xd3,0x67,0x4d,0x5f,0x35,0x7d,0xd4,0xf4,0x4d,0xd3,0x27,0x4d,0x5f,0x34,0x7d,0xd0,
3271
0xf4,0x3d,0xd3,0xe7,0x4c,0x5f,0x33,0x7d,0xcc,0xf4,0x2d,0xd3,0xa7,0xb6,0xa2,0xb5,
3272
0x86,0xb9,0xeb,0xf8,0xde,0xac,0xeb,0xaa,0x11,0xef,0x40,0xe2,0xdc,0x4b,0x5c,0x81,
3273
0x7b,0xdd,0xbe,0x30,0x1d,0xbf,0x6e,0x7d,0x4e,0x9c,0x9b,0xf7,0xb0,0x8e,0x3f,0x42,
3274
0xb8,0xba,0x70,0x4f,0x67,0xb7,0xef,0x99,0x3e,0x67,0xfa,0x9a,0xe9,0x63,0xa6,0x6f,
3275
0x9d,0xdf,0xc9,0x6d,0x9f,0x14,0xb5,0x53,0x2d,0xa9,0x77,0xfd,0x30,0x55,0x6d,0x18,
3276
0x67,0x5d,0x4f,0x49,0xb2,0xfa,0x8a,0xd7,0xc6,0x49,0xd6,0xb5,0x9a,0x24,0xc5,0x97,
3277
0xa4,0xf8,0x92,0x14,0x5f,0x92,0xe2,0x4b,0xb6,0xae,0xdd,0x98,0x7a,0x49,0x90,0x26,
3278
0x4a,0x93,0xa4,0xc9,0xd2,0x14,0x69,0x2d,0x69,0x6d,0x69,0xaa,0xd4,0xbb,0x9e,0xe0,
3279
0xd9,0xe3,0x2d,0xbb,0x17,0x77,0x33,0x9d,0x3b,0x76,0xd7,0x79,0xa1,0x67,0xef,0x60,
3280
0x5d,0x43,0x36,0xe7,0xb3,0x8f,0x10,0xd1,0x63,0x5a,0xa3,0xcc,0x82,0xa7,0xb4,0xee,
3281
0x7a,0x46,0xeb,0xad,0xf9,0x5a,0x8f,0x2c,0xd2,0xfa,0x6a,0x89,0xd6,0x55,0xcb,0xb4,
3282
0x9e,0x5a,0xa5,0x75,0xd4,0x1a,0xad,0x59,0xd6,0xc3,0x06,0x78,0x1d,0x36,0xc2,0x1b,
3283
0x5a,0x47,0x6d,0xd6,0x7a,0x69,0xab,0xd6,0x45,0x1f,0xc1,0x76,0xd8,0x01,0x1f,0xc3,
3284
0x4e,0xd8,0x0d,0x7b,0x60,0x2f,0x7c,0x06,0xfb,0x60,0x3f,0x7c,0x0e,0x07,0xb4,0x7e,
3285
0x3a,0xa4,0x75,0x93,0x59,0x33,0xed,0x36,0x7d,0xb1,0x9d,0x5b,0x06,0x6f,0xad,0x76,
3286
0x4c,0xf9,0x78,0x44,0xfb,0x9a,0x34,0x67,0xca,0x7d,0xc4,0x5a,0xa3,0x3d,0x22,0x8e,
3287
0x29,0xdc,0x63,0xca,0xf7,0x11,0x6b,0x9d,0xf9,0x98,0xdc,0xab,0x54,0x3f,0xb3,0xe5,
3288
0x9e,0xa5,0x7a,0x98,0x6b,0xa5,0x37,0x5d,0xfe,0xc7,0x54,0x7f,0xc7,0x54,0x97,0x47,
3289
0x14,0xf6,0x29,0xf9,0xed,0xd0,0xf6,0xc7,0x54,0xbe,0x39,0x2a,0xeb,0xcb,0x8a,0x67,
3290
0x8e,0xca,0xba,0xcf,0x8a,0x6b,0xba,0xfc,0x8e,0x58,0xee,0x23,0xaa,0x43,0x6f,0x6d,
3291
0x1c,0xba,0x56,0xde,0xa0,0xfd,0x8d,0xfb,0x13,0x2b,0x3e,0x6f,0xfb,0x7e,0x6b,0x3d,
3292
0xec,0xf9,0x1f,0xb0,0xd4,0xab,0x83,0xcf,0x94,0x67,0xcf,0xff,0x63,0xab,0xcc,0xfb,
3293
0x2d,0xff,0x83,0x56,0x19,0x42,0xf7,0x0d,0x75,0xaf,0xb3,0xea,0x79,0xbf,0xb5,0x4e,
3294
0x7f,0xcc,0x4a,0xfb,0x80,0xd2,0xd9,0xa8,0x3e,0x78,0x4c,0xf5,0xb8,0x50,0xfb,0xac,
3295
0x97,0xfd,0x98,0xb5,0xce,0x5e,0xa4,0x38,0xbc,0x78,0x17,0x59,0xed,0xe7,0xd5,0xfd,
3296
0x62,0xd5,0x85,0xdd,0xce,0x2f,0x59,0xe1,0x3c,0xfb,0xba,0x90,0xfa,0x59,0x62,0x9d,
3297
0x27,0x2c,0xb6,0xda,0x7c,0xbf,0x55,0x9e,0xf5,0xea,0xef,0x6f,0x58,0x75,0xf1,0xa6,
3298
0xf2,0xf4,0x4a,0x48,0x1f,0xb5,0xd3,0xb1,0xfd,0x5f,0xb1,0xce,0x3f,0x8e,0xa9,0xef,
3299
0xef,0xb7,0xce,0x3d,0x1e,0x51,0x5e,0xd6,0x85,0xf8,0xcf,0x0d,0x71,0x2f,0xb4,0xce,
3300
0x5b,0xec,0x71,0x60,0xf7,0x35,0xef,0x1c,0xe6,0x51,0xab,0x4d,0xbd,0x73,0x9b,0x97,
3301
0x55,0xce,0x27,0xad,0xfd,0x3f,0xb3,0xc6,0xd0,0x5c,0xd5,0x8f,0x37,0x7e,0xbc,0x71,
3302
0xb5,0xcc,0xb2,0x6f,0x50,0x1e,0xb6,0x2a,0xcc,0x2b,0xd6,0x36,0x6f,0x5c,0x6c,0xb5,
3303
0xca,0xbe,0xd8,0x3a,0x8f,0xf2,0xca,0xbf,0xc2,0x6a,0xdf,0xc7,0xac,0x3a,0xdb,0x16,
3304
0x52,0xff,0xdb,0xb4,0x6d,0x9b,0x15,0xff,0x3a,0xeb,0x3c,0xcc,0xcb,0xa7,0x67,0xf7,
3305
0xc6,0xcf,0x63,0x56,0x7f,0xf3,0xdc,0xfb,0x65,0x7f,0x59,0x6d,0xf1,0x91,0xfc,0xe6,
3306
0xca,0x7e,0x44,0x79,0xfd,0x54,0xf6,0xed,0x56,0x1c,0x9e,0x7b,0x9f,0xa5,0x76,0x7b,
3307
0xee,0xd7,0x18,0xf2,0xc6,0xab,0x6d,0xf7,0xfa,0x51,0xe8,0x18,0xdb,0x1d,0x32,0xcf,
3308
0xec,0xb6,0xe2,0xda,0x63,0xcd,0x6d,0xfb,0xac,0xb6,0xdd,0x2f,0xf7,0x67,0x21,0xfd,
3309
0xc2,0xdb,0xef,0x98,0xd5,0xd6,0xde,0x1c,0xbb,0x43,0xea,0xd5,0xdd,0x7c,0x6b,0xae,
3310
0xb1,0xc7,0xb7,0x39,0xf6,0x2c,0x19,0xe8,0x1e,0x6f,0x8c,0x26,0x48,0x13,0xa5,0x49,
3311
0xd2,0x64,0x69,0x8a,0xb4,0x96,0xb4,0xb6,0x34,0xd5,0x8a,0xc7,0x8e,0x33,0xde,0xb2,
3312
0x27,0x58,0xf6,0x44,0xcb,0x9e,0x64,0xd9,0x93,0x2d,0x7b,0x8a,0x65,0xaf,0x65,0xd9,
3313
0x6b,0x5b,0xf6,0x54,0x2b,0xdf,0x71,0x96,0xdd,0x2e,0x4f,0x82,0x65,0x4f,0xb4,0xec,
3314
0x5e,0xba,0xbd,0x74,0x7d,0x37,0x5b,0xd7,0x6b,0xb3,0x75,0xad,0xb8,0xbd,0xae,0xe3,
3315
0x66,0xeb,0xb8,0x3b,0x40,0xc7,0xdc,0x81,0x21,0xf7,0xe3,0x3c,0x4d,0xb0,0xec,0x89,
3316
0xba,0x9e,0x6c,0xe2,0x18,0xc2,0x5a,0xb6,0x28,0x11,0xc5,0xf4,0x70,0x8f,0x71,0xe6,
3317
0xba,0xa6,0x59,0xef,0x9c,0x89,0xfb,0xa5,0xbe,0xee,0x1a,0xaa,0xc8,0x95,0x9c,0xe7,
3318
0xb7,0x76,0xd7,0x51,0x03,0x95,0x7e,0x7f,0xe9,0x52,0x3d,0xf3,0xdc,0x4f,0xee,0x3e,
3319
0xd2,0x16,0xba,0x9e,0xdd,0x52,0x9a,0x21,0xf5,0xee,0x77,0xf7,0x55,0x58,0xdb,0x3d,
3320
0x50,0xd7,0xbc,0xfb,0x4b,0x97,0x86,0x1d,0xd7,0x9e,0x4a,0xc3,0x7b,0x87,0xc9,0xbb,
3321
0xef,0x3d,0x5a,0x6e,0xcf,0xde,0xd2,0xb2,0x67,0x58,0xf6,0x76,0x96,0x7d,0x69,0xd8,
3322
0xf1,0x6b,0xdb,0x7d,0x55,0x2f,0x7d,0xad,0x6b,0xde,0x3d,0xac,0xeb,0xde,0xfd,0x14,
3323
0xbe,0x9f,0x73,0x9c,0x6e,0xd2,0x3e,0xce,0x89,0xfe,0x09,0xd6,0xb6,0x04,0x4b,0xfb,
3324
0x84,0xf8,0x79,0x6d,0xd0,0xcd,0xb2,0x7b,0xda,0x27,0xc4,0xaf,0x64,0x45,0xf7,0x5a,
3325
0xbb,0x6d,0x4f,0xb0,0xfa,0x44,0x1f,0xcb,0xde,0xd2,0xb2,0x67,0x58,0xf6,0xc1,0x56,
3326
0xff,0xb1,0xed,0x5e,0x7c,0x27,0xf3,0x4b,0xb0,0x9e,0x61,0xe8,0x2f,0x5d,0x1a,0x76,
3327
0x3c,0x2f,0x43,0xb4,0xbd,0x83,0xb6,0x77,0xd0,0xf6,0x0e,0xda,0xde,0x41,0x79,0xeb,
3328
0xa0,0x7c,0x79,0x7d,0xb3,0xa3,0xc2,0x77,0x54,0xf8,0x8e,0x0a,0xdf,0x51,0xe1,0x3b,
3329
0x2a,0xbc,0xe7,0x9e,0xad,0x77,0x6d,0x66,0xeb,0x79,0xfa,0x58,0x85,0x8f,0x55,0x7f,
3330
0x1a,0xa4,0x7a,0xec,0x66,0xf5,0xfb,0xc6,0x2a,0x87,0xd7,0x4f,0x1a,0x6b,0x7c,0xc4,
3331
0x6a,0xbb,0xd7,0x1f,0x47,0xe9,0x9e,0x47,0xb6,0xfa,0x46,0x96,0xee,0x7f,0xf4,0x57,
3332
0xff,0xf5,0x68,0xa9,0xbc,0x0c,0x75,0x4e,0xec,0x37,0xfd,0xa5,0x03,0x94,0x4e,0x5f,
3333
0xdd,0x03,0xe9,0xa7,0xb1,0xd9,0xcf,0xba,0x47,0xde,0x4f,0xe1,0xfa,0x2a,0x9d,0x66,
3334
0xaa,0x0f,0xbb,0x3c,0x59,0xc2,0x6b,0x47,0xef,0x59,0x91,0xc1,0xba,0xaf,0x33,0x5c,
3335
0xf5,0xd2,0x55,0xf5,0x69,0xca,0xe8,0x8d,0x3b,0xcf,0x1e,0xaf,0xf3,0xf1,0x04,0x69,
3336
0xa2,0x34,0x49,0x9a,0x2c,0x4d,0x91,0xd6,0x92,0xd6,0x96,0xa6,0x4a,0xbd,0xb9,0xd2,
3337
0xb3,0xc7,0x5b,0xf6,0x04,0xcb,0x9e,0x68,0xd9,0x93,0x2c,0x7b,0xb2,0x65,0x4f,0xb1,
3338
0xec,0xb5,0x2c,0x7b,0x6d,0xcb,0x9e,0x6a,0xe5,0x3b,0xce,0xb2,0xdb,0xe5,0x49,0xb0,
3339
0xec,0x89,0x96,0x3d,0xc9,0xb2,0x27,0x5b,0xf6,0x14,0xcb,0x5e,0xcb,0xb2,0xd7,0xb6,
3340
0xec,0xa9,0x56,0x3d,0xc5,0x59,0x76,0x2f,0xdd,0x9e,0xd6,0xfc,0xd4,0x3c,0x9c,0x73,
3341
0x1a,0x18,0xf0,0xa4,0xdb,0x1e,0x8d,0x35,0x4f,0x99,0x5b,0x4b,0x95,0x7d,0xf8,0x41,
3342
0x15,0xb6,0xd5,0x9a,0x43,0x7f,0xf1,0xd3,0x7e,0xe8,0x6d,0x68,0x33,0xce,0x09,0xbf,
3343
0xea,0xe1,0xde,0x4b,0x58,0x87,0xfd,0x2d,0x3a,0x4e,0x02,0xe7,0x14,0x9f,0xb4,0x75,
3344
0xaf,0xc3,0x1b,0xda,0x74,0x72,0xcf,0x5d,0x27,0x31,0x29,0x37,0xc3,0xfe,0x2f,0x12,
3345
0xed,0x4d,0x83,0x4f,0xbc,0xde,0x71,0x1a,0xde,0xe8,0x38,0x2f,0x4e,0x72,0x9c,0x6f,
3346
0x26,0x3b,0xce,0x14,0xce,0x53,0xfd,0x57,0x3b,0x4e,0x69,0x1a,0xfb,0x7d,0x3a,0xd0,
3347
0x47,0x74,0x90,0xfa,0x37,0x38,0xce,0xd5,0xec,0x7b,0x78,0xba,0xe3,0x8c,0x27,0xde,
3348
0x61,0xc4,0x1b,0x4e,0x87,0x2d,0x4d,0xc7,0x89,0x61,0xdf,0xb2,0x0f,0xd1,0x9f,0x38,
3349
0x67,0xdd,0x4f,0x07,0xdc,0x38,0x91,0x31,0x70,0x93,0xe3,0xbc,0x46,0x27,0xda,0x3a,
3350
0x8e,0x73,0x65,0xe2,0x5c,0xcf,0x31,0xe0,0x1c,0x0a,0x7a,0x35,0x71,0x1e,0x63,0x9f,
3351
0x37,0x48,0xe3,0x46,0xe6,0xfb,0xc5,0x14,0xec,0x23,0x3a,0xe1,0x2b,0x0c,0x9a,0x2d,
3352
0xa4,0x59,0x94,0x6d,0x9f,0x0e,0x77,0xef,0xcd,0x44,0x10,0xef,0x65,0x70,0xf0,0x36,
3353
0xca,0x72,0x0f,0x75,0x72,0xbf,0xe3,0x7c,0xfb,0x20,0xc7,0x10,0x06,0xc0,0xf5,0x0c,
3354
0xac,0x19,0xd7,0x92,0xc6,0x04,0xf2,0x71,0xa7,0x7b,0x9f,0xe2,0xdd,0x9b,0x59,0xa7,
3355
0x5c,0x82,0x9b,0x63,0x49,0x97,0x31,0x8e,0x73,0x1d,0x71,0x74,0x25,0xbe,0xf5,0x84,
3356
0x5f,0x4d,0x9d,0xfc,0xfb,0x6e,0xf2,0xc3,0xf6,0xae,0x97,0x39,0x4e,0x71,0xd2,0xfa,
3357
0x80,0xbc,0x14,0x21,0xbf,0x35,0x89,0xa7,0xd6,0x75,0x8c,0x43,0xb6,0x6f,0x26,0x2f,
3358
0xb7,0xb0,0x5f,0x2e,0xf9,0x7a,0x1d,0xce,0x67,0x32,0x5f,0xce,0xf6,0xc3,0xa4,0x33,
3359
0x8c,0xed,0x63,0x6f,0x61,0x0d,0xd4,0xd5,0xad,0x9f,0x1f,0x48,0x2f,0x95,0xba,0xf8,
3360
0x94,0x73,0xf3,0xb3,0xba,0x50,0xaf,0xd4,0xd3,0x40,0xce,0xf5,0xcf,0xa1,0x6e,0xbe,
3361
0x23,0xcd,0x15,0x94,0x6f,0x36,0x79,0x39,0x83,0x30,0xaf,0xd3,0xb8,0x23,0x69,0xeb,
3362
0x8a,0xc4,0xf5,0x32,0xdb,0xaf,0x20,0x1f,0xbe,0x11,0x1c,0x23,0xa9,0xd7,0xa7,0x88,
3363
0xe7,0xc5,0x3e,0xee,0xfd,0x9f,0xc9,0x84,0xfb,0x81,0xf8,0x3f,0x19,0x4f,0xf9,0x98,
3364
0x6c,0xba,0x13,0xdf,0xb3,0xec,0xdf,0x9b,0xbc,0xbc,0x06,0xe3,0x98,0x4c,0x3e,0xa5,
3365
0x6c,0x03,0xd8,0xbe,0x99,0xfd,0xde,0xa4,0x4d,0xbe,0x26,0xcf,0xe9,0xed,0xdc,0x6b,
3366
0x0c,0x9f,0x53,0xcf,0xaf,0x92,0xce,0x0f,0x94,0xab,0x1a,0x75,0xf4,0xcc,0x34,0xea,
3367
0xfc,0x3e,0xc7,0xb9,0x87,0xfa,0x79,0xe3,0x21,0xf7,0xde,0xe4,0x1a,0xfa,0xc9,0x08,
3368
0x73,0xff,0x8e,0xf4,0x86,0x12,0x3e,0x47,0x37,0x6c,0xef,0xa3,0x0d,0xa2,0xd9,0x2f,
3369
0x93,0x09,0xef,0x26,0x26,0xa2,0xf5,0xec,0xff,0x15,0xf9,0x1d,0x40,0x7d,0x54,0x26,
3370
0xec,0x17,0xe4,0x35,0x9a,0x76,0x6b,0x4e,0x7d,0x9f,0x43,0x3c,0x8f,0xc2,0x32,0xd2,
3371
0x5d,0x47,0x1f,0x59,0x3d,0xd9,0x2d,0xc7,0x6b,0xc4,0xf7,0x35,0x65,0xbe,0x86,0xbc,
3372
0x3f,0x4b,0x1a,0x0d,0xc8,0xeb,0xb0,0x21,0xee,0xf9,0xed,0xd1,0x0e,0x6e,0x5d,0xbd,
3373
0x48,0x3f,0x39,0x9f,0xfa,0x5a,0x80,0x7f,0x6f,0xd2,0xb9,0x8f,0xfe,0xd7,0x94,0x34,
3374
0x92,0xee,0xa0,0x4f,0x52,0xc7,0xcd,0x68,0xeb,0x73,0xef,0xa5,0x1d,0xa8,0xbf,0x67,
3375
0xcd,0x75,0x14,0xca,0xf8,0x02,0xfe,0x1f,0xb3,0xcf,0x8d,0xc4,0xf3,0x01,0x13,0xd7,
3376
0x17,0xc4,0xd3,0x90,0x76,0x9c,0xde,0xdd,0x6d,0x8b,0x37,0xc8,0x73,0x3a,0xfd,0xe6,
3377
0x18,0x79,0x1c,0x93,0xe3,0xde,0x7f,0x9a,0x4c,0x39,0x63,0xd9,0xef,0x26,0xf2,0x79,
3378
0x0d,0x7d,0xef,0x08,0x34,0xa2,0xcd,0x1f,0x60,0x6c,0x44,0x91,0x6e,0x27,0xea,0xb6,
3379
0x0f,0xed,0x54,0x94,0x32,0x5e,0x71,0xaf,0x7b,0xed,0x27,0x96,0x7a,0x18,0xc9,0x3e,
3380
0xd5,0x49,0xa3,0x14,0xf9,0xdc,0x47,0xf8,0x6a,0x94,0xfd,0x16,0xca,0xd4,0x84,0x7a,
3381
0x3a,0xa7,0x97,0xdb,0xce,0x37,0x12,0xe6,0x42,0xe2,0x2d,0x42,0xf9,0xbb,0x9b,0xfe,
3382
0x44,0x5a,0xad,0x88,0x7f,0x16,0xdb,0x3f,0xa1,0x0d,0x23,0x88,0x7f,0x27,0xf1,0x8f,
3383
0xa2,0x6c,0x6f,0x52,0x37,0x1f,0x4f,0x76,0xef,0xe5,0xed,0x64,0xbf,0x86,0xb4,0xff,
3384
0x8b,0xe4,0xa1,0x0c,0xfb,0x6e,0x22,0xdf,0xf7,0x12,0xf6,0x5b,0xc6,0xcc,0xa3,0x6c,
3385
0xeb,0xf8,0x80,0xe3,0x3c,0x4c,0x3b,0xdd,0x43,0x5c,0x1b,0x48,0x7b,0xef,0x38,0xf7,
3386
0x3e,0x66,0xf9,0x6b,0x1c,0xe7,0x0e,0xea,0x72,0x25,0xfd,0x79,0x3a,0xf5,0x7d,0x09,
3387
0xfd,0x70,0xa5,0xb9,0x57,0x4d,0xbf,0xac,0x43,0x3e,0x22,0xe1,0x09,0xea,0x7e,0x0b,
3388
0xf9,0x7f,0x97,0x70,0x13,0xa9,0x9f,0xb2,0xec,0xff,0x1c,0xf9,0xaa,0x3b,0xc5,0xbd,
3389
0x3f,0xd9,0xf2,0x6e,0xf7,0xde,0xe4,0x16,0xc2,0xa5,0x51,0xd6,0x95,0xcc,0x03,0x97,
3390
0xd2,0x0f,0x87,0x12,0xe6,0x23,0xdc,0xd5,0x28,0xd7,0x7a,0xea,0xb0,0x1e,0x75,0x7e,
3391
0x05,0x74,0x87,0x29,0xd0,0x81,0xf6,0x58,0x3e,0xc6,0xbd,0x67,0x7a,0x16,0xe3,0xf1,
3392
0x1b,0xda,0xb9,0x36,0x75,0xfc,0x3d,0x1c,0xa4,0xde,0x8e,0x41,0x55,0xe6,0x85,0xe7,
3393
0x18,0x9b,0x1f,0xe1,0xb7,0x98,0x74,0x9e,0xa5,0xed,0x3e,0xa5,0x0e,0x5b,0x9a,0x7e,
3394
0x4b,0xde,0x76,0x43,0x1b,0xca,0xfd,0x20,0x69,0x46,0xd0,0x0f,0x7a,0x41,0x1a,0x69,
3395
0xcf,0x82,0xab,0x74,0x2f,0xfb,0x2e,0xda,0xb7,0x17,0x75,0x7c,0x3b,0x7c,0x09,0xad,
3396
0x69,0xdb,0x9d,0x30,0x95,0xfc,0x4d,0xa4,0x5e,0x47,0x50,0x9e,0xf3,0xa8,0xb7,0x8a,
3397
0xf4,0xd1,0xfe,0xd4,0x5b,0x75,0xea,0xa2,0x22,0x75,0x37,0x75,0xa4,0xbb,0x6e,0xcc,
3398
0x84,0x66,0x90,0x65,0xf2,0x3c,0xca,0xbd,0x06,0x77,0x1b,0xdc,0x0e,0x69,0xd4,0xe1,
3399
0x38,0x58,0x79,0x8d,0xdb,0xa7,0xa3,0x18,0xef,0x8d,0x60,0x30,0x65,0x0a,0xd0,0xf7,
3400
0x0e,0x50,0xcf,0xa3,0xc6,0xbb,0x74,0xa4,0x0f,0x15,0xa5,0x9e,0xee,0x06,0x1f,0xf5,
3401
0x9c,0x0a,0x5b,0x98,0x3f,0x0a,0x30,0x0f,0x3d,0x3f,0xc5,0x2d,0xfb,0x2e,0xca,0xf8,
3402
0x23,0xf5,0x52,0x97,0xb2,0x0f,0x23,0xdf,0x5f,0xa4,0xfb,0x9d,0x73,0xd9,0xb7,0x32,
3403
0x6d,0xb2,0x88,0x32,0xf7,0x82,0xb1,0xd4,0x41,0xd0,0x28,0xac,0xa5,0xfc,0xdf,0x5e,
3404
0xec,0x96,0xbf,0x3d,0x4c,0x87,0x9d,0xaa,0xff,0x85,0xd0,0x84,0xb1,0xdb,0x0e,0xba,
3405
0x5e,0x4a,0x5d,0xd2,0x76,0x9b,0x69,0xa3,0xf7,0xa1,0x37,0xfd,0xee,0x19,0xd8,0x4a,
3406
0x1a,0xad,0xa8,0x93,0x02,0xaa,0x9f,0x2e,0xaa,0xa3,0x24,0xda,0xfb,0x15,0xc6,0xda,
3407
0xf9,0x8c,0xdd,0x8b,0xa1,0x43,0x77,0xb7,0x3d,0xcd,0x5c,0x5b,0x1a,0x3a,0xf4,0x74,
3408
0xef,0xd1,0x9b,0xf9,0xc5,0xf4,0xfd,0x6d,0xd4,0xdf,0x06,0xd5,0x61,0xd9,0x81,0x6e,
3409
0x3d,0x3e,0xc9,0x3c,0x94,0x4c,0x5d,0xce,0x1d,0xec,0xf6,0x81,0x41,0xd4,0x69,0x04,
3410
0x7d,0xb7,0x2e,0x94,0xa1,0x3f,0x94,0x1b,0xee,0xf6,0x8b,0x6d,0xf0,0x15,0x34,0x27,
3411
0x7c,0x1a,0xbc,0x4e,0xbd,0xcf,0x57,0x9d,0x5e,0x43,0xff,0xe8,0x7c,0xad,0x5b,0xb7,
3412
0x0d,0x54,0xa7,0x17,0xd3,0x37,0x0f,0xc2,0x28,0x8e,0x2b,0x8d,0xa8,0xcb,0x1b,0x55,
3413
0xa7,0x2b,0x6e,0x76,0xfb,0xd0,0x86,0x9b,0xdd,0xfa,0x35,0xf3,0xe8,0x81,0x9b,0xdd,
3414
0x7a,0xbe,0xf9,0x16,0xb7,0x9e,0x6b,0x53,0xcf,0x83,0xa9,0xe7,0xe9,0x8c,0x99,0xe1,
3415
0xcc,0x0b,0x63,0xee,0x76,0xeb,0xdc,0xf4,0xc5,0x6d,0xf7,0xb8,0x75,0x5f,0xe8,0x5e,
3416
0xb7,0xfe,0xcf,0xba,0xdf,0x3d,0xbe,0x35,0xaf,0xea,0x77,0x9a,0xc0,0x3b,0x89,0x7e,
3417
0xe7,0xc1,0xba,0xcc,0x21,0x69,0xc4,0x09,0x99,0x17,0xfb,0x9d,0x4d,0x97,0xf9,0x9d,
3418
0x2d,0xd7,0xf9,0x9d,0xc6,0x84,0xbb,0xfd,0x61,0x77,0xfd,0xed,0xd1,0x5b,0xda,0xf7,
3419
0x24,0x7e,0x9e,0xbf,0xf7,0x2c,0x8a,0xa7,0x43,0x03,0xe4,0x2b,0xe0,0x6a,0x77,0xa9,
3420
0xf9,0xde,0xc8,0x75,0x96,0x7f,0x3f,0x78,0x1f,0x9e,0x83,0x2f,0x61,0x31,0xec,0x0c,
3421
0xb8,0xcf,0xad,0x9a,0xe7,0x55,0xdf,0x86,0x6d,0x90,0x0b,0x1f,0xc2,0x5e,0xd8,0x17,
3422
0x70,0x9f,0x09,0xfe,0x0c,0x5d,0x15,0x70,0x75,0xb5,0x74,0xa9,0xe5,0xb7,0x54,0xfe,
3423
0x9b,0x14,0xaf,0xd1,0x17,0xa4,0x4b,0xf5,0x5c,0xec,0x52,0x3d,0x1b,0xbb,0x54,0xe9,
3424
0x2d,0x55,0x9a,0x46,0xdf,0x91,0xbe,0x2b,0xdd,0x2a,0x7d,0x5f,0xfa,0x81,0x74,0x9b,
3425
0x34,0x57,0xfa,0x91,0x74,0x87,0xf4,0x63,0xe9,0x2e,0xe9,0x6e,0xe9,0x1e,0xe9,0xa7,
3426
0xd2,0xbd,0x52,0x2f,0xef,0xfb,0xac,0x7c,0x2c,0x51,0x7e,0x57,0x28,0xbd,0x15,0x8a,
3427
0x67,0x85,0xca,0x63,0xd2,0x1e,0x14,0xe1,0x72,0x4d,0x08,0xd7,0x85,0x30,0x36,0x84,
3428
0xd1,0x21,0x5c,0x1f,0xc2,0xa8,0x10,0x1e,0x0b,0xe1,0x89,0x10,0x6e,0x08,0x61,0x42,
3429
0x08,0x37,0x86,0x30,0x29,0x84,0xdb,0xc4,0xad,0xe2,0x76,0x31,0x59,0xdc,0x2b,0xa6,
3430
0x8a,0xd9,0x21,0xcc,0x0d,0x61,0x61,0x08,0xf3,0x43,0x78,0x51,0xbc,0x14,0x82,0xf7,
3431
0x2d,0x1b,0xfb,0x9b,0x36,0x36,0xcb,0x43,0xd8,0x6c,0x61,0x7f,0xfb,0xe6,0x99,0x10,
3432
0xd6,0x8a,0x35,0x62,0x9d,0xf0,0xbe,0xa5,0xb3,0x41,0xbc,0x2a,0x5e,0x13,0x9b,0x42,
3433
0xc8,0x14,0xf6,0xb7,0x79,0x4e,0x66,0x7f,0xe7,0x14,0xf6,0x66,0xa7,0xb0,0xaf,0x3d,
3434
0x85,0x7d,0xcd,0x29,0xec,0xeb,0x4e,0x61,0xdf,0x74,0x1a,0xf6,0xcc,0xff,0x60,0x7f,
3435
0x3d,0x04,0x6f,0x5b,0x0d,0xcb,0x1e,0x63,0xd9,0x83,0xa7,0x88,0xcb,0x68,0x55,0xed,
3436
0x57,0x55,0xfb,0x18,0x8d,0x95,0x06,0xa5,0x99,0x52,0x13,0xbe,0x9a,0xc2,0x57,0x53,
3437
0xf8,0x6a,0x0a,0x5f,0x4d,0xe1,0xab,0x29,0x7c,0x35,0x85,0xaf,0xae,0xf0,0xd5,0xb5,
3438
0xbd,0xba,0xb6,0x57,0xd7,0xf6,0x1a,0x8a,0xa7,0x86,0xb6,0xc7,0x58,0x7e,0x41,0xc5,
3439
0x5d,0x43,0x1a,0x23,0x35,0xfe,0x89,0xf2,0x4f,0x94,0x7f,0xa2,0xb6,0x25,0x6a,0x7b,
3440
0xb2,0xfc,0x93,0xe5,0x4e,0x51,0xf8,0x14,0xf9,0xa7,0x28,0x7c,0x8a,0xb6,0xd7,0x92,
3441
0x7f,0x2d,0xb9,0x6b,0x4b,0x53,0xb5,0x5f,0xaa,0xdc,0x75,0xe4,0xae,0x23,0x77,0x23,
3442
0xb9,0x1b,0x69,0xff,0x46,0x8a,0xb7,0x91,0xb5,0x3d,0x53,0x6a,0xca,0x9b,0xae,0x70,
3443
0xe9,0xda,0x9e,0xae,0xed,0xe9,0xda,0xde,0x58,0x7d,0xb4,0xb1,0xe2,0x6d,0xac,0xf0,
3444
0x8d,0x15,0xaf,0xd1,0x26,0xd2,0xa0,0x34,0x53,0xda,0x5c,0xdb,0x6a,0x48,0x63,0xa4,
3445
0xb1,0xd2,0xa0,0x34,0x53,0xda,0x5c,0x7e,0x76,0xdd,0x07,0xad,0x3a,0xf6,0xc8,0xb4,
3446
0xfa,0x50,0x53,0x85,0x6f,0xaa,0xf0,0x4d,0x15,0xbe,0xa9,0xc2,0x34,0x55,0xf8,0xa6,
3447
0x0a,0x9f,0xa1,0xf0,0x19,0xda,0x9e,0xa1,0xed,0x19,0xda,0xde,0xdc,0xea,0xb7,0x5e,
3448
0x9f,0x8d,0xb5,0xf2,0xd6,0xdc,0xea,0xb3,0x86,0x38,0x18,0x08,0xf1,0xd2,0x4c,0xa9,
3449
0x79,0x76,0xea,0x22,0xb4,0x8d,0xec,0x2d,0x2d,0x7b,0x2b,0xcb,0xde,0xda,0xb2,0x67,
3450
0x59,0xf6,0x36,0x8a,0xc7,0x1b,0x1b,0xf1,0x96,0x3d,0xe1,0x14,0x63,0xa9,0xe9,0xcf,
3451
0x8c,0xab,0x78,0x69,0x42,0xc8,0x78,0x6a,0x7a,0x8a,0x71,0x15,0x2f,0x4d,0x08,0x19,
3452
0x4f,0x4d,0x4f,0x31,0xae,0xe2,0xa5,0x09,0x21,0xe3,0xab,0xe9,0x49,0xc6,0xd9,0xc9,
3453
0xfa,0xe1,0xa9,0xfa,0xdd,0xcf,0xf5,0xaf,0x53,0xf5,0xa3,0x2a,0x56,0x9f,0x69,0xaa,
3454
0xfc,0x35,0x55,0xfe,0xec,0xfe,0xd1,0xf4,0x24,0xfd,0x24,0xd3,0xaa,0x7f,0xaf,0xee,
3455
0x13,0x42,0xfa,0x41,0xd3,0x93,0xf4,0x87,0x9f,0x9b,0xfb,0x62,0x4f,0xd1,0x76,0x19,
3456
0xa7,0x39,0xf7,0x65,0x9c,0xe6,0x9c,0x97,0x61,0xb5,0xc1,0x2f,0x99,0xd3,0x7e,0xe9,
3457
0x5c,0x16,0xfb,0x5f,0xcc,0x69,0xbf,0xd5,0x5c,0x16,0x3a,0x77,0x9d,0xee,0x1c,0x75,
3458
0x3a,0x73,0x52,0xc6,0x69,0xcc,0x45,0xa7,0x33,0xf7,0x64,0x9c,0x62,0xce,0x19,0x78,
3459
0x9a,0x73,0x4d,0xc6,0xcf,0xf4,0x97,0xd0,0x7e,0x71,0xb2,0xf6,0xaf,0x2e,0x77,0xa2,
3460
0xd5,0xbe,0xc6,0x9d,0x24,0x77,0x92,0xdc,0x27,0xab,0xa7,0xe0,0x49,0xca,0x13,0x9a,
3461
0xbf,0xb4,0x88,0xe3,0x73,0x9a,0xb1,0xb7,0xb6,0xec,0xde,0x9c,0x56,0x4b,0xe3,0xa4,
3462
0x96,0xf6,0x4b,0x95,0x3b,0x55,0xee,0x3a,0x72,0xd7,0x91,0x3b,0x51,0xee,0x44,0xb9,
3463
0x93,0xe4,0x4e,0xb2,0xea,0x2b,0xd3,0xaa,0xb7,0x1a,0x72,0xd7,0xb0,0xea,0x31,0xd3,
3464
0xaa,0xcf,0x64,0xb9,0x93,0xe5,0x4e,0x91,0x3b,0xc5,0x8a,0xbf,0x86,0x34,0x46,0x1a,
3465
0x1b,0x52,0x47,0xf1,0xca,0x4f,0xbc,0xe2,0x89,0xd7,0xfe,0xf1,0xff,0x80,0xf2,0xfd,
3466
0xdc,0xfe,0x76,0x9f,0xca,0xb0,0xd6,0x2d,0xa7,0x9a,0x4b,0x4e,0x15,0x5f,0xe8,0x7a,
3467
0xc7,0xcc,0xe1,0x2d,0x2c,0xad,0x66,0x8d,0xc9,0x6a,0xd6,0x5c,0x76,0x32,0x7b,0xd0,
3468
0x9a,0x1b,0x83,0xd6,0xf8,0xa8,0x61,0xd9,0x63,0x2c,0x7b,0xec,0x49,0xe6,0x48,0xcf,
3469
0x1e,0x63,0xf5,0xf9,0x18,0x6b,0x1d,0x92,0x68,0x85,0x4d,0xb4,0xe6,0xd5,0x44,0xab,
3470
0xcd,0x12,0xad,0x78,0x4e,0x66,0xaf,0x61,0xd9,0x83,0x21,0xf6,0x64,0x2b,0xfd,0x50,
3471
0x7b,0xd0,0x6a,0xbb,0x98,0x53,0xd8,0x6b,0x58,0xed,0x1f,0x0c,0x69,0x33,0xdb,0x1e,
3472
0x0c,0xb1,0xa7,0x58,0x7d,0x30,0xc5,0xaa,0x43,0xdb,0x5e,0xcb,0x2a,0xcb,0xc9,0xec,
3473
0x76,0x98,0xe6,0xd6,0x7c,0x1f,0xb4,0xe6,0xfc,0x53,0xd9,0x33,0xad,0xe3,0x40,0xd0,
3474
0xb2,0x37,0xb7,0xec,0x99,0xd6,0x31,0x21,0x18,0x62,0x4f,0xb7,0xf2,0x93,0x6e,0xc5,
3475
0xd3,0xc4,0xaa,0x9f,0x26,0xd6,0xf8,0x6a,0x62,0x95,0xd7,0x3b,0x3e,0xd4,0x38,0x89,
3476
0x3d,0xd6,0xda,0x37,0x36,0x64,0x9e,0x8c,0x09,0xb1,0x9f,0xac,0x1f,0x05,0x2d,0x7b,
3477
0xf3,0x90,0xe3,0xb3,0x7d,0xbc,0x09,0xed,0x8f,0xf6,0x71,0xc7,0x3b,0x56,0xdb,0xc7,
3478
0xa8,0x8c,0x90,0xe3,0x52,0x4c,0x88,0x3d,0xd3,0x3a,0x5e,0x05,0x4f,0x61,0xcf,0xb4,
3479
0xe6,0xfa,0xe6,0x96,0x3d,0xd3,0xca,0x6b,0x30,0xc4,0x5e,0xd5,0x9a,0x83,0xaa,0x59,
3480
0xfd,0xad,0x9a,0x15,0x67,0xb5,0x90,0x30,0xb1,0x96,0x7f,0xd0,0xf2,0x0f,0x5a,0x73,
3481
0x5c,0x30,0xe4,0x7c,0xcc,0xf6,0xcf,0xb4,0xe6,0x91,0x4c,0x6b,0x5c,0x34,0xb7,0xfa,
3482
0x7f,0x73,0xab,0x0f,0xdb,0xe7,0x21,0xf6,0x9a,0xb1,0x79,0xc8,0xb1,0xd7,0x3e,0x1e,
3483
0x37,0x3f,0x49,0x59,0x9b,0x5b,0x7d,0xa9,0xb9,0x55,0xb7,0xcd,0x43,0xfa,0x9b,0xdd,
3484
0xc7,0x52,0xad,0xf0,0x8d,0x4f,0x72,0xde,0x62,0xaf,0x2b,0xec,0x7c,0x06,0xad,0xf0,
3485
0xc1,0x10,0xff,0xa6,0x21,0x6b,0xba,0x18,0xab,0x1c,0x35,0x42,0xfa,0x55,0x73,0x6b,
3486
0xbd,0xd4,0xdc,0x5a,0x5b,0x36,0x0f,0x89,0xdf,0x1e,0x9b,0xc9,0x21,0x73,0x51,0x6c,
3487
0x48,0x9e,0xbd,0xe3,0x4d,0x13,0x5d,0x3b,0x49,0xb7,0xec,0x55,0x64,0xf7,0xd6,0x50,
3488
0xde,0x1a,0xde,0x3b,0xff,0xb0,0xc7,0x41,0x4d,0x2b,0x1e,0xaf,0x9e,0xbc,0x63,0x50,
3489
0x33,0xcb,0xbf,0x89,0xb5,0xd6,0x68,0xa6,0xed,0x4d,0xac,0xbc,0x36,0xb1,0xfa,0x81,
3490
0x67,0xcf,0xfb,0x1b,0x2b,0x21,0x79,0x31,0x7e,0xa1,0xf1,0x19,0xbf,0xd0,0x38,0xbd,
3491
0xb1,0x6e,0xb6,0x79,0xf6,0x2a,0x56,0x3c,0xf1,0xba,0xce,0xe1,0xf9,0xd5,0x30,0xcf,
3492
0x4d,0xc7,0x39,0x8e,0x3f,0xce,0x7d,0x5f,0xaf,0xae,0xf5,0x1d,0x86,0xb3,0xf1,0x3b,
3493
0x27,0xee,0xe4,0xdf,0x7d,0x28,0x41,0x02,0xc5,0xe1,0x4a,0xc7,0xc5,0xfb,0x66,0xc2,
3494
0x35,0x70,0xad,0xd9,0xce,0x7e,0x25,0xa1,0x28,0x14,0x83,0x82,0x50,0x28,0xee,0xf8,
3495
0xfb,0xc9,0x85,0xe1,0x0c,0x38,0x13,0x8a,0x98,0xf7,0x88,0xcc,0x73,0xe0,0xd6,0xb7,
3496
0x21,0x4e,0xa5,0x5e,0x7a,0x06,0x2f,0xef,0xb1,0xca,0x77,0x1d,0xeb,0x5b,0x12,0x26,
3497
0x7f,0xa7,0xca,0x53,0xb4,0xb9,0x87,0x6b,0x9e,0x5f,0xd7,0x77,0x1f,0x62,0x1c,0xf7,
3498
0x3d,0xf0,0x06,0x7a,0x37,0xf1,0x32,0xf3,0x9d,0x48,0xf3,0xad,0x58,0x48,0x53,0x9e,
3499
0x5a,0x68,0x4d,0xd8,0xc2,0x3a,0x3f,0xf6,0xce,0x8d,0xbd,0xf3,0x62,0x6f,0x2d,0xe9,
3500
0x9d,0x1b,0x7b,0xeb,0x49,0xef,0xfc,0xd8,0x5b,0x53,0x7a,0xe7,0xc8,0x69,0xd6,0x39,
3501
0xf3,0xc5,0x72,0x1b,0xad,0x10,0x71,0xe2,0xb7,0xb2,0xed,0x6f,0x66,0x87,0x7e,0x3b,
3502
0x3b,0xf4,0x1b,0xda,0xa1,0xdf,0xd2,0x3e,0x95,0x56,0x11,0x55,0x43,0xb8,0x50,0x54,
3503
0x0b,0xa1,0x7a,0x08,0x35,0x42,0x88,0x09,0x21,0x36,0x84,0x9a,0x22,0x4e,0xc4,0x8b,
3504
0x04,0x91,0x18,0x42,0x52,0x08,0xc9,0x21,0xa4,0x84,0x50,0x2b,0x84,0xda,0x21,0xa4,
3505
0x86,0x50,0x27,0x84,0x46,0x21,0xa4,0x87,0xd0,0x38,0x84,0x26,0x21,0x04,0x43,0x68,
3506
0x1a,0x42,0x46,0x08,0xcd,0x44,0xe6,0x49,0xce,0xc1,0x9b,0x5b,0xe3,0xb6,0xed,0x29,
3507
0xec,0xed,0x4e,0x61,0x6f,0x7f,0x0a,0xbb,0xa7,0x66,0x6c,0x54,0x74,0xdc,0x31,0xe0,
3508
0xf5,0x71,0x33,0x16,0xaa,0x58,0x63,0xd8,0x1b,0x17,0x35,0x34,0x36,0x62,0xf5,0x3d,
3509
0x92,0xd3,0xfd,0x96,0x8a,0x37,0x8f,0xd4,0xd3,0x78,0x6a,0xa0,0x71,0x99,0xf6,0x3b,
3510
0xbe,0xfb,0xdc,0x59,0xe3,0xd8,0xcc,0x29,0x57,0x68,0xbe,0xe8,0xf2,0x3b,0xbe,0x13,
3511
0x6d,0xe6,0x9c,0x31,0x9a,0x77,0xae,0x83,0x89,0x54,0xec,0x8d,0x17,0xba,0xf3,0xac,
3512
0x37,0xf7,0x99,0xb9,0xeb,0x3b,0x3d,0x77,0x3e,0x53,0xcf,0xcc,0x3e,0xae,0xe7,0x63,
3513
0xcd,0x73,0xe1,0xbb,0xf4,0x9c,0xf5,0xa7,0x7a,0x4e,0xf2,0x58,0xdc,0x5f,0xef,0xd9,
3514
0xfa,0x23,0x7a,0xde,0xd3,0x3c,0x27,0xda,0xa5,0xd8,0xdf,0xeb,0xfd,0xc3,0x47,0x28,
3515
0xce,0xa3,0xf0,0xb4,0xf5,0x37,0xd3,0x9e,0x40,0x1f,0x37,0xcf,0xb0,0xe1,0xe1,0xaf,
3516
0xe4,0x7e,0x17,0x65,0x6a,0x05,0xf7,0xbb,0x28,0x77,0xc2,0x0c,0xfc,0x36,0x54,0x32,
3517
0xf7,0x03,0x7d,0x79,0xdf,0xce,0xfd,0x40,0xba,0xc9,0xef,0x38,0x6f,0xf9,0xdd,0xbf,
3518
0xf5,0x32,0x1d,0x6d,0x0b,0x8f,0x9a,0x6f,0xa7,0xcf,0x21,0x3e,0xf4,0x31,0xe8,0x00,
3519
0x1d,0xcd,0xb7,0xcd,0xcb,0xd0,0xd7,0xd1,0x2b,0x60,0x36,0x5c,0x05,0x5d,0xa1,0x0b,
3520
0xdc,0xef,0x77,0xbf,0x09,0xf4,0x80,0xf9,0x06,0x3c,0xdc,0x00,0x4f,0x99,0xef,0xa5,
3521
0x9b,0xbf,0x2f,0x02,0xe1,0xdb,0x7d,0xce,0xed,0x4f,0x52,0x36,0xec,0x01,0x63,0x47,
3522
0x23,0x50,0xf3,0x37,0x65,0x86,0x9b,0xbf,0x5f,0xe2,0x77,0xfb,0xf8,0x68,0xb4,0x00,
3523
0xfe,0xd7,0xa2,0xd7,0xc1,0x58,0x98,0x05,0x4f,0x98,0x78,0xc9,0xd3,0x93,0xe8,0x64,
3524
0x13,0x96,0x49,0x62,0x0a,0x3a,0x13,0x1e,0x81,0x7b,0x61,0x25,0xe9,0xaf,0x82,0xd5,
3525
0x50,0x90,0x38,0xca,0xc2,0x24,0xfc,0xef,0x86,0x7b,0xe0,0x21,0x28,0x84,0xdf,0xf4,
3526
0xa2,0x3e,0xe7,0x45,0xb8,0x5f,0xfa,0xb8,0x34,0xbe,0x98,0xcf,0xa9,0x02,0x09,0xd2,
3527
0x8c,0xe2,0x3e,0xa7,0x41,0x71,0x57,0x3b,0xc2,0x78,0x78,0x0d,0x6e,0x80,0x97,0xe0,
3528
0x16,0x58,0x0d,0x39,0xf2,0x5f,0x6d,0xf1,0x82,0xd4,0xf8,0x2f,0x29,0x41,0xfc,0x25,
3529
0x5c,0x9d,0x27,0x5d,0x06,0x2f,0x94,0xf4,0x39,0x73,0x61,0x89,0x34,0xb9,0x94,0xcf,
3530
0x89,0x83,0xb2,0xd9,0xc7,0xb9,0x50,0x5a,0x4e,0xf6,0x72,0x72,0x97,0xb7,0xc2,0x94,
3531
0xb3,0xc2,0x96,0xb3,0xfc,0x4d,0x98,0x9e,0xfd,0x5c,0xba,0x85,0xa8,0xa1,0xad,0xde,
3532
0x8b,0x5e,0xa7,0x71,0xbc,0x4e,0xe3,0x73,0xaf,0xc6,0xd4,0xef,0x35,0x67,0x9e,0xee,
3533
0xfc,0xde,0xf1,0x2d,0x9f,0xd3,0x1d,0x2e,0x09,0xd1,0xfe,0x96,0x7d,0x80,0x65,0x1f,
3534
0x68,0xd9,0x07,0x59,0xf6,0xc1,0xb0,0x44,0xf6,0x17,0xa5,0x4b,0xac,0xb8,0x5e,0xb4,
3535
0xec,0x4b,0xac,0x78,0x5f,0xb4,0xec,0x7f,0xb7,0x6f,0x69,0xfc,0x19,0xca,0xf3,0x77,
3536
0x2a,0xcb,0x6f,0xdd,0x36,0x5e,0x59,0x32,0xac,0xbc,0x87,0xe6,0xf9,0x97,0xe6,0xb7,
3537
0xc7,0xcf,0xe4,0xf3,0x9f,0x5e,0xe7,0xe9,0x27,0x29,0xcb,0xcf,0x95,0xe1,0x3f,0xe5,
3538
0xff,0x8f,0xce,0xfb,0xc9,0xda,0xa0,0xf5,0x9f,0x2c,0xcf,0xf9,0xf3,0x69,0x7e,0x79,
3539
0xf2,0xcb,0x93,0x5f,0x9e,0xbf,0x5b,0x79,0xe2,0x39,0x27,0xa9,0xc5,0xf9,0xc7,0x76,
3540
0xc7,0xfd,0x1e,0xf2,0x1d,0xfa,0x2e,0xe9,0x5d,0xfa,0x6e,0xf1,0xdd,0xfa,0x4e,0xf1,
3541
0xbd,0xfa,0x76,0xf0,0x7d,0x70,0x3f,0x3c,0x00,0x0f,0xc2,0x43,0xfa,0xde,0xee,0x0c,
3542
0x7d,0xcf,0xf7,0x5e,0xfd,0x3d,0xc2,0xc7,0xf4,0x9d,0xdf,0x27,0xe0,0x49,0xf3,0x7d,
3543
0x47,0x7d,0x7f,0x37,0xb2,0xa2,0xfb,0x8d,0x66,0xfb,0x6f,0x6a,0x99,0x6f,0xa2,0x3f,
3544
0xaf,0x6f,0x27,0xbf,0xa0,0xef,0x18,0x9b,0xbf,0x73,0xf8,0x92,0xfe,0xc6,0xf6,0x32,
3545
0x58,0xae,0x6f,0xa1,0xaf,0xb4,0xfe,0xfe,0xe1,0xcb,0xf0,0x8a,0xbe,0x39,0xec,0xfd,
3546
0xcd,0xad,0x75,0xfa,0x26,0xb0,0xbf,0xa2,0x1b,0xef,0x0b,0x8a,0x6b,0x8d,0xf6,0x5b,
3547
0x19,0x96,0x5f,0xce,0xfc,0x72,0xe6,0x97,0xf3,0xcf,0x5c,0xce,0x5c,0xf8,0x30,0xec,
3548
0xf4,0xcf,0xbf,0xff,0xec,0xe1,0xcc,0xdc,0xda,0x71,0x3b,0xe7,0xf9,0xd0,0x09,0xcc,
3549
0xdf,0xb6,0x3d,0xb7,0x8c,0xe3,0x8c,0x65,0xee,0x2d,0x06,0x9f,0x40,0x3a,0xdc,0x07,
3550
0x59,0x6c,0x6f,0x00,0x99,0xe6,0xef,0x49,0x11,0xa6,0x21,0xf6,0x87,0xf0,0x1f,0x83,
3551
0xbb,0x36,0xa4,0x42,0x75,0xfc,0x4a,0xc1,0x8d,0xe6,0xfa,0x12,0x61,0x6a,0x60,0x3f,
3552
0x1f,0xee,0xc4,0x7d,0x1f,0xee,0x40,0x19,0xf3,0x47,0x0c,0x69,0x4b,0xb8,0xde,0xfc,
3553
0x1d,0x41,0x78,0x16,0xe6,0x42,0x05,0x48,0x82,0x64,0x48,0xf1,0x1f,0x6f,0x8f,0x71,
3554
0x84,0x9d,0xf6,0xa4,0xe3,0x4c,0x42,0x6f,0x86,0xdb,0x61,0x32,0xe9,0x4e,0x87,0xc7,
3555
0x61,0x06,0x61,0x9f,0x41,0xa3,0x48,0xc7,0xfc,0xcd,0xd6,0x78,0x48,0x08,0x77,0xff,
3556
0x3e,0x6c,0x52,0xb8,0xfb,0x77,0x5b,0xcd,0xdf,0x66,0x35,0x7f,0x8f,0xd5,0xfc,0xcd,
3557
0x55,0xf3,0x77,0x62,0xeb,0x42,0xbd,0x70,0xf7,0x6f,0xae,0x36,0x84,0x34,0x68,0x04,
3558
0xe9,0xe1,0xee,0xdf,0x4d,0x6d,0x02,0x41,0x68,0x1a,0xee,0xfe,0xdd,0xd4,0x66,0xe1,
3559
0xee,0xdf,0x4b,0x35,0x7f,0x83,0xb5,0x15,0xdc,0xf4,0x84,0xfb,0xf7,0x5f,0xcd,0xdf,
3560
0x9e,0xbd,0x24,0xdc,0xfd,0x5b,0xad,0x73,0xe1,0xcd,0x70,0xe7,0x17,0xe5,0xc1,0x4b,
3561
0xbf,0xd1,0x7f,0x48,0xb7,0xb9,0xd2,0x9e,0xaa,0xf4,0xda,0xc3,0x95,0x30,0x07,0xda,
3562
0x90,0x8f,0xf9,0xe1,0xc7,0xef,0x0f,0xd5,0xd0,0xbd,0x9b,0x66,0xba,0x57,0x13,0x63,
3563
0x3d,0x2b,0xd4,0x38,0xe4,0x59,0xab,0x44,0xdd,0x5f,0x69,0xa4,0xfb,0x34,0xe9,0xd6,
3564
0x33,0x38,0xde,0x7d,0xa4,0x58,0xdd,0x03,0x4a,0xd1,0xbd,0x19,0x73,0xff,0xa5,0xbf,
3565
0x9e,0x8f,0x9f,0x09,0x03,0xac,0x74,0x33,0x42,0xee,0xf9,0xfe,0x5c,0x5a,0xa1,0xe9,
3566
0xa4,0x58,0xcf,0xe6,0xd9,0xf7,0xd3,0xed,0xfd,0xed,0x7d,0xed,0x7d,0x5e,0x3c,0x45,
3567
0x5e,0x6a,0x85,0xdc,0x83,0xfe,0x25,0x79,0xb1,0xcb,0x3b,0x33,0xe2,0xff,0xd7,0x71,
3568
0xc6,0x29,0xea,0xf9,0xb7,0xa8,0xe3,0x9f,0x6b,0xcb,0xdf,0x22,0x0d,0xef,0xdb,0xc0,
3569
0x71,0xba,0x7f,0x14,0x2f,0x4d,0x90,0x26,0x4a,0x93,0xa4,0xc9,0xd2,0x14,0x69,0x2d,
3570
0x69,0x6d,0x69,0xaa,0xb4,0xaa,0xd6,0xa2,0xde,0x37,0xba,0xd2,0x2d,0x7b,0x63,0xcb,
3571
0xde,0xc4,0xb2,0x07,0x2d,0x7b,0x53,0xcb,0x9e,0x61,0xd9,0x9b,0x59,0xf6,0x4c,0xcb,
3572
0xde,0xdc,0xb2,0xb7,0xb0,0xec,0x17,0x59,0xf6,0x96,0x96,0xbd,0x95,0x65,0x6f,0x6d,
3573
0xd9,0xb3,0x2c,0x7b,0x1b,0xcb,0x7e,0xb1,0x65,0x6f,0x6b,0xd9,0xdb,0x59,0xf6,0xf6,
3574
0x96,0xbd,0x83,0x65,0xef,0x68,0xd9,0x2f,0xb1,0xec,0x9d,0x2c,0xfb,0xa5,0xb2,0x9b,
3575
0x7b,0xde,0x26,0x7e,0x73,0xdf,0xbb,0xb1,0xd2,0xf5,0xd6,0xf2,0x1d,0x15,0xee,0xf7,
3576
0x5a,0xe3,0x37,0x0b,0xf9,0x46,0x40,0x5b,0xa5,0xd7,0x56,0x78,0xef,0xc4,0x7b,0xfb,
3577
0x36,0x56,0x58,0x4f,0xbd,0xef,0xdd,0x5f,0x2c,0xbb,0xc9,0x93,0xf9,0xfe,0x67,0x0b,
3578
0xdd,0xf3,0xf2,0xee,0x7b,0x99,0x6f,0xe8,0x76,0xec,0xec,0x38,0xaf,0xb7,0x3d,0xfe,
3579
0x7d,0x1d,0xf3,0x7d,0xb1,0xf3,0xc8,0xc8,0xae,0x9b,0xdc,0xef,0x2b,0x3e,0x86,0xbb,
3580
0x3c,0x27,0x18,0x15,0x06,0xb9,0xef,0xae,0xb6,0x24,0xd2,0x5b,0xaf,0x74,0x9c,0xdb,
3581
0x28,0xcc,0x3c,0xdc,0x65,0xcc,0xbb,0xbc,0xd7,0xba,0xdf,0xbf,0x9d,0x7d,0xab,0xe3,
3582
0x1c,0xa2,0x20,0xa9,0x14,0xae,0x04,0x27,0x1c,0xd3,0x88,0xbf,0x7d,0x37,0xb7,0x12,
3583
0xcc,0x37,0xcb,0x9a,0xe7,0xb8,0xdf,0x09,0x33,0xdf,0x0c,0x33,0xdf,0x0a,0x8b,0xec,
3584
0xe6,0x7e,0x57,0xb6,0x2d,0xe1,0xc6,0x71,0xe2,0x31,0x9a,0x13,0x8f,0x02,0xec,0x3b,
3585
0xb6,0xbf,0xfb,0x8d,0xb2,0xbc,0xef,0x74,0x11,0xef,0x60,0xd2,0x78,0x9e,0xca,0x6a,
3586
0x39,0xd5,0x6d,0xa7,0x1a,0x3d,0xdd,0x76,0x32,0x76,0x13,0xaf,0x67,0xbf,0xd5,0xb2,
3587
0xdf,0xd4,0xf9,0xb8,0xdd,0x7c,0x33,0xc4,0xb3,0x9b,0xb4,0x3c,0xfb,0x7b,0xc3,0x8f,
3588
0xdb,0x3f,0xbc,0xf8,0xb8,0xbd,0x63,0x77,0xd7,0x7e,0x0f,0xe5,0x3c,0xd8,0xf6,0xf4,
3589
0x8f,0xe7,0xf5,0x49,0xbf,0xb6,0xf9,0x06,0x1b,0x54,0xf4,0xf9,0x9d,0x2e,0xad,0xdd,
3590
0xf7,0x4a,0x5f,0x02,0x3f,0x0d,0x36,0x1a,0xa6,0x67,0xb9,0xef,0x99,0xbe,0x09,0x0f,
3591
0x25,0x99,0xb9,0xc0,0x9f,0xf7,0xce,0x69,0x3b,0xb8,0x0a,0x46,0x98,0x77,0xb8,0x03,
3592
0x7e,0x67,0x09,0xdb,0x7a,0xb6,0x71,0xeb,0xb9,0x05,0xee,0x7b,0xd0,0xc7,0xcc,0x3b,
3593
0xde,0xc4,0xfd,0x74,0x1b,0xf7,0x9d,0xcd,0xed,0x53,0xfd,0x79,0xdf,0x70,0x0e,0x23,
3594
0xef,0xdb,0x09,0x5f,0x17,0x6d,0x7a,0xb1,0x5b,0x5f,0x23,0x4c,0x79,0x92,0xdd,0xf7,
3595
0x38,0xbd,0xf7,0x59,0xcd,0xfb,0x9c,0x01,0xca,0x13,0xd1,0xd6,0x7d,0xe7,0x3b,0xb3,
3596
0xad,0xfb,0x8e,0xeb,0xa5,0x30,0x04,0xae,0x85,0xeb,0x2d,0x6a,0x14,0xf4,0x3b,0x03,
3597
0xa9,0xbb,0xf5,0xd8,0xb7,0x43,0xb7,0x42,0x7e,0x67,0x3f,0x7a,0xd8,0xc4,0x41,0x3b,
3598
0x3d,0x04,0xb5,0xa1,0x19,0xf4,0x32,0xdf,0x02,0x83,0x7f,0x41,0x51,0xda,0xaa,0x2d,
3599
0x74,0x83,0x1b,0x84,0x79,0x7f,0x74,0x0e,0x2c,0x84,0xd5,0x70,0x76,0x47,0xf7,0xbd,
3600
0xda,0x73,0xd0,0x36,0xe8,0xd0,0x0e,0xee,0x3b,0xc1,0x5f,0xd0,0x7f,0xde,0xc0,0xef,
3601
0x2b,0x38,0x03,0xfb,0x2d,0x68,0x02,0x1a,0x0f,0x4f,0xc3,0xee,0x12,0x7e,0xe7,0x4b,
3602
0xf4,0xdf,0x10,0xd1,0xc9,0xed,0xab,0x15,0xcd,0x7b,0xa8,0x30,0xeb,0x6c,0xbf,0xb3,
3603
0x0f,0x3e,0xc7,0x5e,0x9a,0x81,0x54,0x05,0xb6,0x62,0xef,0x81,0x7e,0x41,0x63,0x1d,
3604
0x83,0x02,0xf4,0x8b,0x06,0x62,0x5d,0x29,0xbf,0xf3,0x32,0xba,0xb5,0xb3,0xfb,0x9e,
3605
0xf7,0x11,0x38,0xb7,0xb4,0xdf,0xf9,0x11,0x8d,0xb8,0x8c,0x32,0x5c,0xe9,0x7e,0xbb,
3606
0x7a,0x1c,0x8d,0xdc,0x45,0xef,0xfc,0xae,0x84,0xdb,0x60,0x77,0x19,0xbf,0xd3,0x98,
3607
0xbe,0xbc,0x07,0xed,0x8f,0xf6,0x81,0x31,0xf0,0x31,0xec,0x84,0x9a,0x74,0x8a,0xef,
3608
0xd1,0xaa,0x57,0xd0,0x2f,0xcc,0x7b,0xb1,0xd0,0x15,0xbf,0x09,0x2c,0xb4,0xc6,0xa0,
3609
0xf3,0x70,0x2f,0x84,0xe7,0xaf,0x70,0xbf,0x35,0x70,0xc7,0xa3,0xfe,0xbc,0xef,0x5e,
3610
0xc7,0x47,0xfb,0xf3,0xf0,0x8d,0x27,0xed,0x2b,0x5d,0xd6,0x12,0xfe,0x85,0x04,0xbf,
3611
0xf3,0x41,0xb6,0xdf,0xe9,0x8a,0xbb,0x0f,0xec,0xc2,0xef,0x3e,0x74,0x23,0xbc,0x07,
3612
0x47,0x61,0x5c,0x17,0xfa,0x13,0x1d,0xf1,0xfc,0x54,0xf7,0xdd,0xe4,0xb7,0x2b,0xfb,
3613
0x9d,0xb5,0x68,0xb3,0x6c,0xe6,0xa3,0x6c,0xf7,0x7d,0x5c,0xa3,0xa3,0xf5,0x4e,0xee,
3614
0x02,0x78,0x0c,0xe6,0xc2,0x47,0x7a,0x3f,0xd7,0x7c,0x63,0xc1,0x7c,0xfb,0xa6,0x34,
3615
0x5c,0x0e,0xf3,0xe1,0x6d,0xc8,0x62,0xac,0x16,0xae,0xee,0x77,0xea,0xa3,0xc7,0x70,
3616
0xf7,0x42,0x27,0xc0,0x6e,0x38,0x8c,0x7f,0xc5,0xab,0x58,0xcf,0x63,0x9f,0x0d,0xb1,
3617
0x75,0x28,0x2f,0xee,0xeb,0xe0,0x41,0x18,0x01,0x7d,0xeb,0xb8,0xef,0x47,0xf7,0xed,
3618
0x6e,0x9e,0x71,0xf2,0x3b,0xbb,0xd0,0x6f,0x98,0x57,0x32,0xa1,0x54,0x5d,0xf7,0x9d,
3619
0xe9,0x02,0xe8,0x6e,0xc2,0xdd,0x41,0x9f,0x9e,0xd6,0xc6,0xbd,0xa8,0xf1,0x00,0xfe,
3620
0xcf,0x8c,0x65,0xbd,0xd7,0xf8,0xf8,0x3b,0xc2,0x15,0xe0,0x0a,0x68,0x0b,0x2f,0x27,
3621
0xfa,0x9d,0x4c,0xf6,0xfb,0x16,0xfb,0x44,0xb8,0xb8,0x97,0xfb,0xee,0x75,0x3f,0x16,
3622
0xb3,0xb7,0xa3,0xe5,0xa0,0x44,0x6f,0x27,0xef,0xfd,0xda,0x74,0xf4,0x51,0xd8,0x07,
3623
0xb3,0xae,0xc6,0xce,0x42,0x77,0x1b,0x7a,0x6e,0x3d,0xe2,0xec,0xc3,0xf9,0x0e,0x0b,
3624
0xe9,0x76,0x68,0x2b,0xdc,0x83,0xcd,0x37,0xd6,0xf5,0x1e,0xf2,0x4b,0x70,0x5b,0x1d,
3625
0xbf,0x53,0x88,0xb6,0xfe,0x16,0x6d,0xd5,0x97,0xf3,0x9b,0x7a,0x7e,0x67,0x05,0xba,
3626
0x11,0x7a,0xc2,0xd9,0xfd,0xe8,0x53,0xfd,0xdc,0x77,0xbe,0xcd,0x7b,0xcb,0xbd,0x61,
3627
0x24,0x4c,0x84,0xb2,0xf5,0xfd,0x4e,0x12,0x5a,0x93,0x79,0xad,0x3f,0x24,0xd6,0x77,
3628
0xdf,0x69,0x5e,0x0b,0x6f,0x35,0xf0,0x3b,0x47,0xd9,0xd6,0x9f,0xf9,0xf2,0x8a,0x86,
3629
0xe4,0x19,0xd6,0x60,0x4f,0x1d,0xe8,0xbe,0xef,0x5c,0x1a,0xee,0x26,0x7c,0x73,0xf4,
3630
0x5a,0x18,0x01,0xcf,0x40,0x25,0xe6,0x84,0x20,0x73,0x72,0xb7,0x74,0xbf,0xf3,0x00,
3631
0x3a,0xa7,0xb1,0xdf,0xa9,0x3a,0xd8,0x7d,0x2f,0x3a,0x0b,0x0a,0x34,0xf5,0x3b,0x63,
3632
0xd1,0x69,0xc6,0x2f,0xc3,0xef,0x94,0x68,0xe6,0x77,0x46,0x0f,0x61,0x3c,0xc1,0xd3,
3633
0x0d,0x58,0xbb,0xa3,0x2f,0x34,0x70,0xc9,0x18,0xea,0x38,0x97,0x0d,0x75,0xdf,0xa3,
3634
0x9e,0x68,0xbe,0xa3,0x00,0xa5,0x1b,0x3a,0xce,0x05,0xcc,0xbd,0x29,0x17,0xf9,0x9d,
3635
0x06,0xe6,0x7b,0xe6,0xa8,0xf9,0x56,0xc4,0xc3,0xf4,0xdf,0xa2,0xcc,0x9b,0x33,0x5b,
3636
0xfb,0x9d,0x17,0xa0,0x49,0x96,0xdf,0x39,0x46,0xd8,0x02,0x69,0xee,0xbb,0xd6,0x47,
3637
0x70,0x7f,0x09,0xa5,0xda,0xf8,0x9d,0x44,0x28,0x3b,0x82,0x36,0x10,0xe6,0x3d,0x6c,
3638
0xf3,0x7e,0xf3,0x2d,0x68,0x53,0xf4,0xee,0x34,0xf3,0x4d,0x01,0xea,0x73,0xa4,0xfb,
3639
0x8d,0x0c,0xf3,0x7e,0xf6,0x2e,0xfc,0x2a,0x77,0xf0,0xe7,0xbd,0x0f,0x7f,0x1f,0xfa,
3640
0x2a,0x98,0x77,0xfa,0xf7,0x43,0xcd,0x46,0xee,0x7b,0xf1,0xcd,0xa1,0x35,0x8c,0xe9,
3641
0xe4,0x77,0x9e,0xbc,0xd4,0xe5,0x0b,0xdc,0x7e,0x0e,0xce,0x73,0x3a,0x53,0x7f,0xd7,
3642
0x30,0xe7,0x41,0x15,0xdc,0x63,0x2f,0xf3,0x3b,0x9b,0xc7,0x70,0x9e,0x82,0x7d,0x2f,
3643
0xba,0x4b,0x0f,0x9b,0xdc,0x78,0xa5,0xdf,0xe9,0x86,0xfa,0xe8,0x57,0x6b,0x51,0xff,
3644
0x75,0x1c,0xcf,0x21,0x09,0x77,0xd5,0xae,0x7e,0x27,0x03,0x3a,0x61,0x7f,0x1f,0x1d,
3645
0x7d,0x3d,0x6d,0xcb,0xc9,0xd9,0x34,0xf4,0x5b,0xbd,0x2b,0xfe,0xc1,0x55,0x7e,0x27,
3646
0xba,0x3b,0x73,0x3c,0xf6,0x59,0xe8,0x40,0xf4,0x4a,0xfa,0xe2,0x3b,0xec,0xb3,0x00,
3647
0x7b,0xd8,0x38,0xc7,0x29,0xc4,0xc1,0xb7,0x01,0xba,0x88,0xf9,0xe7,0xc9,0x9e,0x7e,
3648
0x67,0x11,0xdc,0x49,0x98,0x07,0x12,0xdd,0xf1,0x1d,0x0e,0x0f,0x4d,0x61,0x3c,0x13,
3649
0x6e,0x2a,0xf6,0x5b,0xe0,0x41,0x58,0xc8,0x3c,0x38,0xdf,0x28,0x2c,0x83,0x3d,0x50,
3650
0xaf,0x8f,0x3f,0xef,0x1b,0x1b,0x65,0x26,0xd0,0xe6,0xf0,0x0c,0x44,0xc3,0x32,0xf8,
3651
0x74,0x82,0xfb,0x0d,0x80,0xb6,0xe8,0x7a,0x78,0x1d,0x72,0x21,0xa5,0xaf,0xdf,0xe9,
3652
0xd3,0x8f,0x3c,0xa1,0xd5,0x59,0xac,0x1c,0x26,0xcc,0x11,0x38,0x7b,0x22,0xe1,0x86,
3653
0xf8,0x9d,0xab,0xd0,0x1a,0x03,0xfc,0xce,0xe5,0x6c,0xcb,0x86,0xf9,0xd8,0x37,0x0f,
3654
0x64,0x1f,0xec,0x59,0xfa,0x96,0x49,0x4f,0xe8,0x0d,0xb3,0x61,0x32,0x9c,0x39,0x89,
3655
0xf9,0xed,0x46,0xf7,0x1d,0xf9,0xaa,0xd0,0x07,0x6e,0x84,0xf7,0xd8,0xe7,0x63,0xd4,
3656
0x37,0x99,0xb9,0x08,0x7b,0x17,0x7d,0x5f,0xbe,0xe7,0x70,0xbf,0xf3,0x1e,0xfa,0x11,
3657
0x24,0xb3,0x58,0xfa,0x16,0x7d,0x89,0x63,0xd5,0xb3,0x23,0xfd,0x4e,0x8f,0x51,0x7e,
3658
0x67,0x39,0x7e,0x6b,0x61,0x86,0xde,0xa9,0x37,0xef,0xd3,0x9b,0x6f,0xcf,0xcf,0xe2,
3659
0xc4,0x76,0x0e,0xba,0x0a,0x4a,0xb3,0x46,0x18,0x01,0x35,0x39,0x69,0x0d,0x2f,0xe0,
3660
0x77,0x36,0x60,0x5f,0x0a,0x87,0xe0,0x23,0xdc,0x6f,0xdf,0xee,0xbe,0x7f,0xbf,0x99,
3661
0x13,0xda,0x03,0x70,0x17,0xeb,0x8c,0xc3,0x50,0x8c,0xf5,0x42,0xec,0x24,0xbf,0x53,
3662
0x1a,0xad,0x7d,0x07,0x79,0x84,0xad,0xe6,0xdd,0x7c,0x38,0x7a,0x27,0xc7,0xc7,0xbb,
3663
0xc8,0xcf,0x2d,0x7e,0xe7,0x96,0x69,0x8c,0x13,0x16,0x6f,0x8b,0xa7,0x99,0x74,0xfc,
3664
0xce,0x1e,0xec,0x2f,0xdf,0x4d,0x3b,0x32,0x7f,0x47,0xdf,0x43,0xbf,0xe0,0x38,0x7b,
3665
0xde,0x1d,0xcc,0xf3,0x2c,0xa4,0x86,0xc3,0x0e,0xfc,0x0a,0xde,0xe5,0x77,0x16,0x60,
3666
0xbf,0x1b,0x35,0xef,0xf5,0x1b,0x2e,0x84,0xe7,0xa7,0xf9,0x9d,0x9d,0x68,0x22,0x8b,
3667
0xc0,0x0b,0xa7,0xd3,0xee,0xb0,0x1a,0x7e,0x80,0x37,0xf0,0x8b,0xbb,0xdf,0x9f,0xf7,
3668
0xfe,0x7f,0xda,0x03,0x1c,0x1f,0xe0,0x0d,0x16,0x8a,0x07,0xa0,0xe7,0x83,0xd8,0x39,
3669
0x99,0xfe,0x06,0x7b,0x60,0xa6,0xdf,0x39,0xf3,0x11,0xbf,0x33,0x15,0xcc,0x77,0xec,
3670
0x3b,0xb4,0x74,0xbf,0x5f,0xff,0x03,0x04,0x1e,0x76,0x9c,0x22,0x70,0xb6,0xbe,0x5f,
3671
0x9f,0xf7,0xa0,0x09,0xd5,0xee,0x0f,0x0b,0x0f,0x44,0x44,0x16,0x88,0x2a,0x58,0xa8,
3672
0xf0,0x19,0x67,0x12,0x24,0xef,0xb3,0xcd,0x67,0x15,0x2f,0x51,0xf2,0x6c,0xe6,0x4d,
3673
0xe7,0xf8,0xef,0xdc,0x52,0x1c,0x33,0x9d,0x3f,0xe2,0x57,0xda,0x39,0xbf,0x4c,0xd9,
3674
0x72,0xbf,0x71,0xa4,0xee,0x5f,0x4b,0xab,0x18,0x7d,0x81,0xeb,0xac,0xc4,0xe4,0x51,
3675
0xa5,0xea,0x85,0xd5,0xaa,0xd7,0x88,0x89,0xad,0x19,0x17,0x9f,0x90,0xe8,0x24,0x25,
3676
0xe7,0x2d,0xd3,0x7e,0xdd,0xaf,0x96,0x67,0xa9,0xed,0x3d,0xb6,0xf7,0x9b,0xfd,0xea,
3677
0x9e,0xcc,0xb3,0x5e,0xfd,0x13,0x9c,0x0d,0x52,0x1b,0x3a,0x69,0x8d,0xd2,0x9d,0xc6,
3678
0x4d,0x9c,0xfc,0x5f,0xfe,0x2f,0xff,0x97,0xff,0xcb,0xff,0xe5,0xff,0xf2,0x7f,0xf9,
3679
0xbf,0xfc,0x5f,0xfe,0x2f,0xff,0x97,0xff,0xcb,0xff,0xe5,0xff,0xf2,0x7f,0xff,0xd0,
3680
0xdf,0x9e,0x93,0xfd,0xf6,0xe6,0xf2,0xdb,0xbb,0xd5,0xfc,0x9f,0xbb,0x7e,0xfd,0xf1,
3681
0xff,0xf5,0xf3,0x99,0x9f,0xb1,0x78,0xe1,0x0f,0xed,0x71,0x1d,0xb9,0xb9,0x4e,0xde,
3682
0xff,0x38,0x88,0x62,0xcf,0x67,0xfb,0xf6,0x99,0x7f,0x27,0x44,0x9d,0x5f,0xe3,0x27,
3683
0x6f,0x82,0xfc,0x6a,0xd0,0x2f,0xaf,0x53,0x99,0xff,0x3e,0x52,0xf7,0x72,0xfb,0x5c,
3684
0x9e,0xdf,0x47,0xbb,0xf7,0xe4,0x5d,0xa3,0x2c,0x62,0x2e,0x4f,0xe6,0x5d,0x9f,0x3c,
3685
0xc7,0x5c,0x94,0xdc,0x93,0xeb,0x9c,0x55,0xb0,0xe4,0x6f,0x3b,0x1e,0xca,0x96,0x2b,
3686
0xff,0x4b,0x77,0x2d,0x6d,0xae,0x51,0x96,0xaf,0x50,0xd1,0x64,0x79,0x8f,0x4a,0x91,
3687
0x1b,0x1a,0x28,0xfa,0xf7,0x1c,0xd5,0xae,0x25,0x37,0x4f,0x9d,0x93,0xe5,0xe6,0x24,
3688
0xbf,0x0b,0x7e,0x26,0x66,0xb7,0x25,0x4c,0x8b,0x98,0x7f,0x79,0xd1,0xbb,0x66,0xcf,
3689
0x5f,0x64,0xaa,0xcb,0x3d,0x9e,0xd1,0xdc,0xff,0x14,0xf4,0xf8,0xd4,0xe8,0xfc,0xe4,
3690
0xfa,0x25,0xfd,0x38,0x37,0xf7,0x57,0xe5,0x55,0xd3,0xeb,0x2f,0x2c,0x5e,0xae,0x3d,
3691
0x2d,0x2b,0xf7,0x6a,0x31,0x77,0x2b,0x9d,0x54,0x3d,0x33,0xf7,0x57,0xcf,0x3b,0x91,
3692
0xa1,0x1e,0x51,0xea,0x20,0xbf,0x53,0x83,0x9e,0x34,0xfd,0x5f,0x56,0xcd,0x7f,0x70,
3693
0xfa,0x4e,0x7e,0xfa,0xbf,0xe5,0xef,0xcf,0x52,0xfe,0x76,0x9d,0xff,0x09,0xf5,0x1f,
3694
0x15,0xf5,0xa7,0x6a,0xff,0xdf,0x37,0xf1,0x9e,0x3d,0x4f,0x4c,0xaf,0x0f,0xbf,0xdf,
3695
0x33,0xfd,0xe1,0xc3,0x4f,0x4c,0x7f,0xf4,0x68,0xf3,0x04,0xdc,0x6f,0xb8,0x0c,0xfb,
3696
0x4f,0x47,0xaf,0x5c,0xcc,0xd6,0xff,0x32,0xe2,0x71,0xe3,0x9d,0x1b,0xf2,0x2c,0xe3,
3697
0xf9,0xf1,0x3f,0xc7,0xad,0x28,0xe7,0xd7,0x1e,0x32,0x72,0x7f,0xef,0xce,0x16,0x79,
3698
0x92,0xde,0xff,0x1b,0x54,0xfa,0xdf,0xef,0xcc,0xe6,0xaf,0x98,0xed,0x9f,0x6b,0xda,
3699
0xa8,0x3f,0x77,0xee,0x7f,0xab,0xe5,0xcd,0x9f,0xeb,0xb7,0xfb,0x4f,0x96,0x9f,0x8f,
3700
0xf6,0xfc,0xdd,0x46,0xeb,0x89,0xa7,0x79,0xff,0xcb,0xa3,0xf2,0xf1,0x8b,0x41,0xbf,
3701
0x38,0x99,0x13,0x2f,0x09,0x38,0xb9,0xb9,0xf6,0xd9,0x76,0xe8,0x2f,0xf7,0x04,0xcb,
3702
0xbe,0xbc,0xa0,0xff,0x83,0x75,0x57,0xd4,0xe9,0xd6,0xe9,0xaf,0xba,0x06,0xf6,0x6b,
3703
0x0e,0x38,0x91,0xbf,0x51,0x3c,0xa7,0x5e,0x7a,0xfe,0x99,0x0e,0x39,0x3e,0xaf,0x7b,
3704
0x98,0xff,0x1d,0x9f,0xfb,0xb3,0x8e,0xaf,0x7b,0xf2,0xc2,0xfd,0x5d,0x0e,0xb1,0xb9,
3705
0xc7,0xfb,0xf8,0xbe,0x77,0x73,0xd7,0xef,0x39,0x9d,0xdf,0xde,0xdd,0xbb,0x73,0x3f,
3706
0xd8,0xf3,0x59,0xee,0xdf,0x6f,0x0e,0xdb,0xb3,0xc7,0xe7,0x33,0x25,0xf4,0x19,0xf1,
3707
0x1a,0x1b,0x7b,0xee,0x1e,0x5d,0xb2,0x76,0xfe,0xd1,0xbf,0x3f,0xdb,0x8a,0x2c,0xea,
3708
0x77,0x28,0xf0,0x7f,0xfc,0x9d,0x7e,0x4c,0x1f,0xec,0xde,0xfb,0xd1,0x8e,0x1d,0xbf,
3709
0x5b,0xcd,0x14,0x28,0xf0,0xb7,0xec,0x7f,0x27,0xb6,0xc9,0xcf,0xb7,0xde,0x6f,0xdf,
3710
0x1f,0xfe,0xfb,0x6e,0xf8,0x67,0x5d,0xf7,0x47,0xfd,0xa2,0xfe,0xff,0x2b,0x2e,0x09,
3711
0xe4,0xfe,0x29,0xaa,0x29,0xf2,0xaf,0x73,0x2e,0xf6,0xbf,0x18,0x40,0x79,0xb7,0x71,
3712
0xd4,0x8c,0xe6,0xbe,0xc4,0x9f,0x72,0xda,0xfd,0xeb,0x0d,0x94,0x93,0xfe,0xce,0x73,
3713
0xfe,0xe9,0xbf,0x3d,0xf6,0x4d,0xd8,0xdc,0xfc,0xfb,0xd4,0x7f,0xab,0x5f,0x6e,0x7e,
3714
0x11,0xff,0xc0,0x51,0xf5,0x67,0xac,0xac,0xd3,0xce,0xd4,0x1e,0x5f,0xee,0x5f,0xe7,
3715
0x40,0xf2,0x2b,0x4f,0x73,0x7f,0x93,0xc6,0xca,0x7f,0xca,0xe7,0x7f,0xb3,0x74,0xb7,
3716
0x5b,0xf9,0x34,0x8e,0x4f,0x79,0x0f,0xae,0xe8,0x61,0x88,0x5f,0xf9,0x8c,0xc6,0x09,
3717
0xb1,0xba,0x0f,0xc2,0xfc,0x37,0x11,0xee,0xf9,0x1b,0x5c,0x85,0x89,0xfa,0x6f,0x43,
3718
0xfe,0xf7,0xf3,0x47,0x54,0xe4,0x6f,0xd4,0xa9,0x7e,0xf1,0xa0,0xfc,0xb5,0x17,0x50,
3719
0x23,0xff,0x37,0x35,0xff,0x3b,0x5e,0x92,0x8d,0x8a,0xfc,0xeb,0x75,0xd1,0xc8,0xdf,
3720
0xfc,0x50,0x15,0x79,0xfa,0xcf,0x5f,0x1c,0x3f,0xf5,0xfe,0xdf,0x1e,0x06,0xa2,0xa2,
3721
0xa2,0xfe,0x90,0xb1,0x1f,0x79,0xca,0xb3,0xd5,0xfc,0xce,0xf8,0xb7,0x2e,0x7c,0xd4,
3722
0x3f,0xa8,0xd8,0x51,0x4e,0xfe,0x2f,0x7f,0xd8,0xfd,0xff,0x95,0xc0,0x9f,0xba,0x22,
3723
0xa2,0x7e,0x9f,0x38,0xa3,0xfe,0xa1,0xa3,0x2d,0x7f,0x4e,0xf8,0xdf,0x3c,0x0a,0x17,
3724
0xf5,0x17,0x9b,0x03,0xfe,0x31,0x33,0x5e,0x7e,0x7f,0xff,0x6b,0xff,0x7e,0x7a,0x16,
3725
0xe6,0xbf,0x3f,0x5f,0xce,0xbf,0x90,0xf5,0x17,0xfe,0x45,0x44,0xfc,0xa5,0x7a,0xeb,
3726
0x9f,0x25,0x23,0xbf,0xee,0x42,0xe1,0xd6,0xad,0xee,0xa0,0xdb,0xb9,0xd5,0xfc,0x8e,
3727
0xc7,0xe9,0xfe,0x7e,0x7a,0xa8,0xf1,0xe7,0x47,0xde,0x9f,0xb1,0x8d,0x4e,0xcc,0x96,
3728
0x55,0x3e,0x53,0xe4,0xad,0x3f,0x5f,0x35,0x7f,0x78,0xee,0x4f,0x7c,0xd9,0x6f,0xcf,
3729
0x09,0xef,0x4e,0xba,0x9b,0x7e,0xbf,0x8b,0xf7,0xf9,0x13,0xeb,0xff,0xb0,0x7a,0xfe,
3730
0xe9,0x07,0xae,0xbd,0x7b,0xff,0xf1,0x8f,0x3f,0xe6,0xfe,0x33,0x07,0xcd,0x9e,0x9f,
3731
0x46,0xc0,0xdf,0x7d,0x96,0xf9,0xe9,0x98,0xfa,0xbb,0x1f,0x43,0xfe,0xa2,0xd7,0xc3,
3732
0xdc,0xaf,0xbf,0x06,0x02,0x91,0x81,0x02,0x51,0x05,0x03,0x81,0x42,0x81,0x9f,0x7e,
3733
0x85,0x03,0x81,0x33,0xce,0x0c,0x14,0x29,0x1a,0xb0,0x7f,0xc5,0x02,0x7f,0xc3,0xdf,
3734
0x59,0xc7,0xad,0xc5,0x4b,0x04,0x4a,0x9e,0x7d,0x0e,0x96,0x73,0x7f,0xa3,0xb8,0x4b,
3735
0x59,0xf6,0xf3,0x02,0xf9,0xbf,0xfc,0x5f,0xfe,0x2f,0xff,0x97,0xff,0xcb,0xff,0xe5,
3736
0xff,0xf2,0x7f,0xf9,0xbf,0xfc,0x5f,0xfe,0x2f,0xff,0x97,0xff,0xcb,0xff,0xe5,0xff,
3737
0xfe,0x80,0x9f,0xcf,0xf9,0xa3,0x4c,0x98,0x13,0x70,0x22,0xf3,0x4c,0x15,0x27,0xc6,
3738
0xa9,0xe5,0x34,0x76,0xba,0x3b,0x3d,0x9d,0x61,0xce,0x04,0x67,0xa6,0xf3,0xa8,0xf3,
3739
0x8c,0xb3,0xc4,0x59,0xe1,0xbc,0xe5,0x1c,0x76,0xbe,0xc6,0x04,0x7c,0xc5,0x7d,0x15,
3740
0x7c,0x19,0xbe,0x16,0xbe,0x8e,0xbe,0xce,0xbe,0x7e,0xbe,0x51,0x27,0x98,0xe9,0xbe,
3741
0x87,0x7d,0xb3,0x7d,0x8b,0x7c,0xef,0xf9,0xde,0xf7,0x7d,0xea,0xfb,0xb7,0xaf,0xb8,
3742
0xff,0x1c,0x7f,0x05,0x7f,0x8c,0x3f,0xd1,0x1f,0xf4,0x77,0xf7,0xf7,0xc6,0x8c,0xf2,
3743
0x4f,0xf2,0xdf,0xe3,0x5f,0xe6,0x5f,0xe5,0x7f,0xd3,0xbf,0xc5,0xff,0xa9,0xff,0xc8,
3744
0xff,0xd0,0x1c,0xfd,0x2f,0x8c,0x2f,0xcc,0x17,0x16,0x16,0x16,0x08,0x8b,0x0a,0x2b,
3745
0x94,0x67,0x8a,0xff,0x64,0x4a,0xfe,0x64,0xca,0x84,0x45,0x87,0x55,0xc2,0x54,0x91,
3746
0xa9,0x69,0x99,0x5a,0x98,0xd4,0xb0,0xba,0x61,0x0d,0xc3,0x1a,0xe5,0x99,0xcc,0x9f,
3747
0x4c,0x8b,0x9f,0x4c,0xdb,0xb0,0x4e,0x61,0x9d,0x31,0x97,0xcb,0x74,0x3f,0xc1,0xf4,
3748
0x0b,0x1b,0xf6,0x1f,0xcd,0xa8,0xb0,0x6b,0x7f,0x77,0x33,0x2e,0x6c,0xe2,0x29,0xcd,
3749
0xa4,0xb0,0x9b,0x7e,0x32,0xb7,0x84,0xdd,0x76,0x82,0x99,0x12,0x36,0x35,0xec,0xce,
3750
0xb0,0x69,0xa7,0x69,0xee,0xf9,0xd5,0x66,0x66,0xd8,0x9c,0xff,0x60,0x16,0x85,0xad,
3751
0x38,0xc1,0xac,0xfa,0x5d,0xcc,0xcb,0x61,0xaf,0xfe,0x41,0x66,0x6d,0xd8,0x6b,0x61,
3752
0x1b,0xc2,0x36,0xfe,0x64,0xde,0x0c,0x7b,0xeb,0x6f,0x61,0xb6,0xe4,0x9b,0x7f,0xb4,
3753
0xf9,0x58,0xe6,0x33,0xcc,0x11,0x8c,0x2f,0xfc,0xb8,0x89,0xc2,0x14,0x92,0x39,0x47,
3754
0xa6,0x42,0x9e,0x89,0xc6,0x54,0xca,0x33,0xc9,0x32,0xf5,0x31,0x99,0x98,0x4e,0x96,
3755
0xc9,0xc6,0x74,0x97,0x19,0x26,0x33,0x2e,0x7c,0x52,0xf8,0x6d,0x79,0x66,0x8a,0xcc,
3756
0x9d,0xbf,0x9b,0x99,0x76,0x12,0x33,0x3d,0xcf,0xdc,0x8f,0x99,0x19,0xfe,0x78,0xf8,
3757
0x93,0xe1,0x73,0x31,0xf3,0x65,0x16,0xfe,0x64,0x5e,0x92,0x59,0x26,0xb3,0x02,0xb3,
3758
0x2a,0xcf,0xbc,0x9a,0x67,0xd6,0x62,0x36,0x86,0xbf,0x15,0xbe,0x25,0x7c,0x1b,0xe6,
3759
0x43,0x99,0xed,0x3f,0x99,0x4f,0x65,0x3e,0x93,0xd9,0x8f,0x39,0xf0,0xff,0xcc,0xc1,
3760
0x5f,0x61,0x0e,0x87,0x1f,0xf9,0x5b,0x98,0xaf,0xc3,0xff,0xfd,0x1f,0xcd,0xd1,0xf0,
3761
0xef,0x7e,0x91,0xc9,0x7f,0xba,0xe2,0x9f,0xfe,0xfb,0x2e,0xfc,0xb7,0x35,0xbe,0xc0,
3762
0xaf,0x35,0x2c,0x89,0xff,0x61,0xe7,0x63,0x91,0x3f,0x6b,0xa2,0xf2,0x4c,0xa1,0xbf,
3763
0x88,0x39,0x23,0xc4,0x14,0xc9,0x33,0xc5,0xf2,0xcd,0x69,0x99,0x92,0xff,0x78,0x53,
3764
0xfa,0x4f,0x69,0xca,0xfc,0x4e,0xa6,0x42,0x20,0xfa,0x1f,0x6e,0x2a,0xfd,0xe3,0x4c,
3765
0x95,0x13,0x4c,0x8c,0x4c,0xcd,0x7f,0xac,0x49,0x0c,0x24,0xe7,0x9b,0x9f,0x35,0x75,
3766
0xf3,0x4c,0xfd,0x3f,0xa1,0x69,0x98,0x6f,0xfe,0xe2,0xa6,0x11,0xa6,0x31,0x26,0x88,
3767
0xc9,0xc0,0x64,0xca,0xb4,0xf8,0xcd,0x4d,0x4b,0x4c,0x6b,0x4c,0x9b,0x40,0xdb,0x3c,
3768
0xd3,0x3e,0xdf,0xfc,0x43,0x4c,0xc7,0x40,0xa7,0xdf,0xc4,0x74,0x0e,0x5c,0x7e,0x82,
3769
0xb9,0x32,0x90,0xfd,0x87,0x99,0xee,0x81,0xde,0xbf,0xc8,0xf4,0x09,0xf4,0x3b,0x2d,
3770
0x33,0x20,0x30,0xe8,0x77,0x32,0xa3,0x02,0xe3,0x02,0x13,0x02,0x13,0x03,0x93,0x02,
3771
0x37,0x05,0x6e,0x09,0xdc,0x16,0x98,0x16,0x78,0x30,0xf0,0x70,0x60,0x66,0xe0,0xd1,
3772
0xc0,0xe3,0x81,0x27,0x03,0xb3,0x03,0xcf,0x04,0xe6,0x9f,0x60,0x16,0x05,0x96,0x9c,
3773
0x60,0x56,0x05,0x5e,0x0b,0x6c,0x08,0x6c,0x0c,0xbc,0x19,0x78,0x2b,0xb0,0x25,0xf0,
3774
0x4e,0xe0,0xc3,0xc0,0x27,0x81,0x4f,0x03,0x9f,0x05,0xf6,0x07,0x0e,0x04,0x0e,0x06,
3775
0x0e,0x07,0xfe,0x1d,0xf8,0xfe,0x04,0x13,0x16,0x11,0x75,0x82,0x39,0x23,0xa2,0xd8,
3776
0x09,0xa6,0x64,0x44,0xa9,0x13,0x4c,0xb9,0x88,0x4a,0x21,0xa6,0xfa,0x09,0x26,0x31,
3777
0xa2,0x6e,0x44,0xfd,0x88,0x86,0x11,0x8d,0x22,0x1a,0x47,0x04,0x23,0x32,0x22,0x5a,
3778
0x47,0x74,0x8c,0xe8,0x14,0xd1,0x39,0xe2,0xf2,0x88,0x2b,0x23,0xb2,0x23,0xba,0x45,
3779
0x74,0x97,0xe9,0x19,0x62,0x7a,0xff,0x01,0xa6,0xcf,0xff,0x33,0x83,0x4e,0x30,0x43,
3780
0xfe,0xc7,0x66,0x58,0x88,0xb9,0x26,0xdf,0x9c,0x86,0xb9,0x16,0x73,0x3d,0x66,0xdc,
3781
0x1f,0x64,0x26,0x60,0x26,0x62,0x26,0xfd,0x8f,0xcd,0x4d,0x3f,0x99,0x5b,0xf2,0xcc,
3782
0x6d,0xbf,0xd0,0x4c,0xc1,0x4c,0xfd,0x45,0xe6,0xce,0x13,0xcc,0x34,0xcc,0x3d,0x79,
3783
0x66,0xfa,0x4f,0xe6,0xfe,0xd3,0x34,0x0f,0xe6,0x99,0x87,0x23,0x66,0x9e,0xd2,0x3c,
3784
0x1a,0xf1,0x78,0x9e,0x79,0x32,0x62,0x76,0x9e,0x99,0x13,0xf1,0x4c,0xc4,0xdc,0x88,
3785
0xf9,0x3f,0x99,0x85,0x11,0x8b,0xf2,0xcc,0xe2,0x88,0x25,0x27,0x31,0x2f,0x45,0x2c,
3786
0xfb,0x19,0xb3,0xc2,0x32,0xab,0x22,0x5e,0xc6,0xbc,0x7a,0x82,0x59,0x1b,0xf1,0x5a,
3787
0xc4,0x86,0x88,0x8d,0xf9,0xe6,0x67,0xcd,0x9b,0x3f,0x99,0xb7,0x30,0x5b,0x30,0xef,
3788
0x60,0xde,0xc3,0xbc,0x8f,0xd9,0x86,0xf9,0x10,0xb3,0x1d,0xf3,0x31,0x66,0x17,0xe6,
3789
0x13,0xcc,0xa7,0x79,0xe6,0x33,0xcc,0x7e,0xcc,0x81,0x13,0xcc,0xe1,0x3c,0xf3,0x75,
3790
0x9e,0x39,0x9a,0x67,0xbe,0xcf,0x33,0xbe,0xc8,0x5f,0x6f,0xc2,0xfe,0x9f,0x39,0x7e,
3791
0x21,0xd7,0xfc,0xa2,0x30,0x85,0x30,0x67,0x60,0x8a,0x60,0x8a,0x61,0x8a,0x63,0x4a,
3792
0x62,0xce,0xc1,0x94,0xc2,0x94,0xc6,0x94,0xc9,0x33,0xe5,0x30,0x15,0x30,0xd1,0x27,
3793
0x98,0x2a,0x79,0xa6,0x7a,0x9e,0xa9,0x99,0x67,0x12,0xf3,0x4c,0xad,0xd3,0x34,0xa9,
3794
0x91,0x75,0x23,0xeb,0x47,0x36,0x3c,0xa9,0x69,0x94,0x6f,0xfe,0x32,0xa6,0x71,0x88,
3795
0x09,0xe6,0x9b,0x3f,0xd4,0x64,0x60,0x32,0x4f,0x62,0x5a,0xe4,0x9b,0x53,0x98,0x96,
3796
0x91,0xad,0xf3,0x4d,0xbe,0x39,0x4d,0xd3,0xf6,0x0f,0x31,0xed,0x31,0x1d,0x4f,0x30,
3797
0x9d,0x7e,0x32,0x9d,0x7f,0x07,0x93,0x9d,0x6f,0xfe,0x51,0xa6,0x67,0xbe,0xf9,0x47,
3798
0x9b,0xde,0x91,0x7d,0xfe,0xb1,0xa6,0x5f,0xbe,0xf9,0xdb,0x99,0x61,0x79,0x66,0x54,
3799
0xe4,0x35,0x27,0x98,0x6b,0xf3,0x4d,0xbe,0xf9,0xdd,0xcd,0xf5,0x32,0xe3,0x30,0x13,
3800
0xf2,0xcd,0x2f,0x30,0xee,0xf3,0xa2,0xb5,0xc3,0x1c,0xa7,0x7f,0x45,0x57,0xbb,0x48,
3801
0x07,0xa0,0x0e,0xba,0xd2,0x7c,0x5a,0x07,0x5d,0x85,0xfa,0xd1,0xd5,0xc6,0x1b,0x7d,
3802
0x19,0x0d,0x0f,0x73,0x3f,0x6d,0x18,0x81,0xfa,0xd1,0x48,0xb4,0xb2,0xdf,0x71,0x0a,
3803
0xa0,0xaf,0x98,0x8f,0xac,0xa2,0x8f,0x94,0x75,0x9c,0x82,0xe8,0xab,0xb8,0x0b,0xa3,
3804
0x1b,0x09,0x57,0xc4,0xec,0x47,0xb8,0x62,0x66,0x3f,0x34,0x1a,0x9d,0x41,0xb8,0x4a,
3805
0xc6,0x1f,0xad,0x8a,0x86,0x2b,0x3e,0x7f,0x59,0x77,0x7b,0x38,0x1a,0x8f,0x46,0x94,
3806
0x75,0xf3,0x13,0xe1,0x73,0xf3,0x53,0x40,0xe1,0x0a,0xfa,0xdc,0xf8,0x0b,0xa3,0x55,
3807
0xd0,0xb5,0x8e,0xfc,0xcb,0xba,0xfe,0x67,0xfa,0xdc,0x78,0x0a,0x97,0x75,0xb7,0x17,
3808
0x45,0x63,0xd0,0xb3,0x14,0xef,0x99,0x65,0xdd,0xf2,0xae,0x53,0x79,0x5f,0x53,0x79,
3809
0xd7,0xab,0xbc,0x4b,0xcb,0xba,0xe5,0x3d,0x4b,0xe5,0x2d,0xa1,0x74,0xcf,0xf6,0xb9,
3810
0xe5,0xdd,0xa0,0xf2,0xbe,0xa8,0xf4,0xce,0x53,0x39,0xc3,0x55,0xce,0x08,0x95,0xf3,
3811
0x05,0xa5,0x5f,0xd5,0xef,0x96,0xf3,0x5c,0x9f,0x9b,0x8f,0x73,0xf1,0x8f,0x33,0xfb,
3812
0x95,0x75,0xe3,0x2d,0xab,0x72,0x7e,0xa5,0x72,0x9e,0xef,0x73,0xd3,0x2f,0x5f,0xd6,
3813
0x4d,0xbf,0xac,0xd2,0x2f,0xaf,0x72,0xef,0x51,0xb9,0x2b,0x2a,0xfc,0x05,0xda,0x5e,
3814
0xb1,0xac,0x9b,0xbf,0xca,0xca,0x57,0x59,0xe5,0xe3,0x02,0x2f,0x1f,0x68,0x2c,0x5a,
3815
0x4d,0xe5,0x7f,0x5d,0xe5,0xdf,0xa8,0xf2,0xbf,0xa1,0xf2,0x57,0x55,0xfa,0xd5,0x54,
3816
0xfe,0x1a,0x8a,0x3f,0x4e,0xe5,0x7f,0x53,0xe5,0x5f,0xa7,0x74,0xde,0x54,0xf9,0x0b,
3817
0xa8,0xfc,0x05,0x95,0xee,0x7a,0xb5,0x6f,0xac,0xcf,0x2d,0x6f,0x8d,0xb2,0x6e,0x3a,
3818
0x49,0x3e,0x37,0xdd,0x38,0xed,0xbf,0x57,0xed,0x95,0xa0,0x7c,0xa6,0xf8,0xdc,0x76,
3819
0x4a,0x52,0xbd,0xa4,0xaa,0xdc,0xf5,0x15,0x2e,0x45,0xe1,0xea,0xaa,0x3e,0xeb,0xa9,
3820
0x5d,0xeb,0x28,0x7c,0x03,0xd5,0x6b,0x9a,0xfa,0x53,0xba,0xca,0xfb,0x8d,0xd2,0x6d,
3821
0xec,0x73,0xcb,0xf9,0x96,0xfa,0x4d,0x13,0xe5,0x23,0x43,0xf1,0x37,0x55,0xfc,0x41,
3822
0xc5,0xdf,0x5c,0xf1,0x37,0x53,0x3c,0x9b,0x55,0x6f,0x5b,0x54,0x6f,0x6f,0xab,0xde,
3823
0xde,0xd1,0x38,0xb9,0x48,0xf5,0xd6,0x4a,0xf5,0x16,0xab,0x71,0xf2,0xae,0xea,0xed,
3824
0x0d,0xe2,0x29,0x84,0x66,0xa9,0x5c,0x6f,0xa9,0xfe,0x0a,0xab,0xfe,0xce,0x44,0x4b,
3825
0x9b,0x71,0xa2,0xfc,0xbc,0xae,0x7a,0xdc,0xa7,0xfc,0xb7,0x53,0xf9,0x3a,0xa8,0xbc,
3826
0xed,0x94,0xce,0x25,0x2a,0xc7,0x25,0x8a,0xaf,0xa8,0xe2,0x3b,0x4b,0xed,0x71,0xa9,
3827
0xca,0xd5,0x41,0xf5,0x7b,0x85,0xf6,0xbf,0x54,0xfd,0xe8,0x32,0xc5,0xd3,0x45,0xf1,
3828
0x74,0x51,0xfa,0x5d,0x71,0x57,0x36,0xfd,0xd6,0xef,0xee,0x7f,0x85,0xc2,0x5d,0xad,
3829
0x70,0x57,0x29,0x5c,0x5f,0x85,0x3b,0x4f,0xe1,0xba,0xaa,0xfe,0x06,0xaa,0xfe,0xfa,
3830
0xab,0xfe,0xde,0x57,0xfd,0x7d,0xa0,0xfa,0xdb,0xa6,0xfa,0xeb,0xa5,0x7e,0x77,0xb5,
3831
0xea,0xaf,0xaf,0xfa,0x5b,0xae,0xea,0x6d,0x8f,0xe6,0x97,0xfe,0x3e,0xb7,0xfe,0x06,
3832
0xaa,0xfe,0xb6,0xa8,0xbc,0x25,0x54,0xde,0xb3,0x55,0x7f,0x73,0x95,0xaf,0xdd,0xec,
3833
0x77,0x01,0x3a,0x58,0xf5,0x38,0x58,0xf9,0x1a,0xae,0x71,0x38,0xb4,0xac,0x9b,0xfe,
3834
0x18,0xf5,0x97,0xeb,0x94,0xcf,0xb1,0xaa,0x9f,0xf1,0xea,0xb7,0x43,0x55,0xee,0x1b,
3835
0x35,0xce,0x6e,0x50,0xf8,0xc9,0x6a,0x8f,0x9b,0xe5,0x7f,0xab,0xf6,0xff,0x52,0xfb,
3836
0x7f,0xa8,0x72,0x0e,0x57,0xbf,0xfb,0x46,0xf3,0x4b,0x82,0xdf,0xdd,0xef,0x76,0xed,
3837
0x37,0xd2,0xe7,0x96,0xf3,0x5f,0x8a,0xf7,0x2b,0xed,0x3f,0x4a,0xed,0x93,0xa3,0x74,
3838
0xae,0x51,0xb9,0xaf,0x55,0xf9,0xee,0x50,0xfd,0xde,0xa5,0x74,0x77,0xa8,0x7e,0x3f,
3839
0x56,0xba,0x3b,0x55,0xbf,0xbb,0xd4,0x3f,0x7d,0xaa,0xdf,0x30,0x95,0xa7,0x8a,0xfa,
3840
0xe7,0x6e,0xd5,0xf3,0xa3,0xaa,0xe7,0x4f,0x34,0x8f,0xbf,0xa1,0xfa,0xf5,0xa9,0x7e,
3841
0xc3,0xd4,0x9f,0x66,0x6a,0x1e,0xf7,0xa9,0x5e,0x03,0x8a,0x2f,0x4c,0xf9,0x0f,0x28,
3842
0x5f,0x91,0x2a,0x47,0xa4,0xca,0x11,0xa5,0x70,0x85,0x54,0x8e,0x33,0x34,0x9f,0x7d,
3843
0xaa,0xf1,0x58,0x48,0xfd,0xaa,0x88,0xca,0x77,0x86,0xfa,0x6d,0x31,0xcd,0xe3,0xc5,
3844
0x15,0x6f,0x11,0x95,0x77,0xaf,0xca,0xfb,0x99,0xca,0xbb,0x4f,0xe5,0x5d,0xa6,0x7a,
3845
0x2e,0xae,0xf2,0x96,0x54,0xba,0xe7,0xa8,0x5f,0xed,0x57,0x79,0x5f,0x52,0x7a,0xa5,
3846
0x55,0xce,0x80,0xca,0x19,0xa9,0x72,0x2e,0x51,0xfa,0x17,0x6a,0x1e,0x2f,0xa5,0xfe,
3847
0x53,0x4a,0xfd,0xa7,0xb4,0xda,0xa5,0x9c,0xca,0xf9,0xb5,0xca,0x59,0x46,0xfd,0xb9,
3848
0x82,0xe6,0xf1,0x72,0x4a,0xbf,0x82,0xca,0xfd,0xa9,0xca,0x1d,0xad,0xf0,0x95,0xb4,
3849
0x3d,0x5a,0xfd,0xa1,0x8a,0xf2,0x55,0x4e,0xf9,0xa8,0xe4,0xe5,0x43,0xf3,0x78,0x75,
3850
0xd5,0xc3,0xdd,0xaa,0x87,0xcf,0x55,0x0f,0x07,0x54,0x0f,0x5f,0xa8,0x1e,0x2e,0x54,
3851
0x3e,0xaa,0xab,0x1e,0x62,0x54,0xfe,0x83,0x2a,0xff,0x6b,0x4a,0x67,0x93,0xca,0x1f,
3852
0xa5,0xf2,0x17,0x52,0xba,0x1b,0xd4,0xbe,0x35,0x35,0x8f,0xc7,0x68,0x3c,0x24,0xab,
3853
0x1c,0x87,0x34,0x2f,0xc5,0x2b,0x9e,0xcf,0xd4,0x6e,0x89,0xca,0x6f,0x2d,0xcd,0x37,
3854
0xc9,0xaa,0x9f,0x3a,0xda,0xaf,0x81,0xc2,0xd5,0x52,0xb8,0x7a,0xaa,0xd7,0xfa,0x2a,
3855
0x57,0x5d,0x85,0x6f,0xa8,0xfa,0x6d,0xa4,0x7e,0xd5,0x58,0xe5,0x3d,0xaa,0x74,0x9b,
3856
0x68,0x5c,0x1d,0x56,0xff,0x09,0x2a,0x1f,0xcd,0x14,0x7f,0x86,0xe2,0x6f,0xaa,0xf8,
3857
0x5b,0x28,0xfe,0x4c,0x6f,0x9c,0xaa,0xde,0x8e,0xa8,0xde,0xbe,0x52,0xbd,0x7d,0xad,
3858
0xf1,0xd2,0x52,0xf5,0xd6,0x5a,0xed,0x53,0x53,0xe3,0xe5,0x5f,0xaa,0xbf,0x37,0x35,
3859
0x9f,0xb7,0x51,0xb9,0x36,0xab,0x1e,0xcf,0x50,0x3d,0x16,0xd1,0x7c,0x34,0x53,0xf9,
3860
0xd9,0xa8,0xfa,0xdc,0xaf,0xfc,0xb7,0x57,0xf9,0x3a,0xaa,0xbc,0xed,0x95,0x4e,0x27,
3861
0x95,0xa3,0x93,0xe2,0x2b,0xa6,0xf8,0x8a,0xab,0x5d,0x3a,0xab,0x5c,0x1d,0x55,0xbf,
3862
0x57,0x6a,0xff,0xce,0xea,0x4f,0x97,0x2b,0x9e,0x6c,0xc5,0x93,0xad,0xf4,0xbb,0x69,
3863
0x9e,0x2e,0xa5,0x79,0xfa,0x4a,0x85,0xeb,0xa3,0x7e,0x77,0x8f,0xc2,0x77,0x57,0xf8,
3864
0x7e,0x0a,0x5f,0x5a,0xe1,0xbb,0xa9,0x1e,0x07,0xa9,0x1e,0x07,0x78,0xed,0xa1,0x7a,
3865
0xfc,0x56,0xf5,0xf8,0x9d,0xea,0xb1,0xb7,0xfa,0x5f,0x1f,0xd5,0x63,0x3f,0xf5,0xbf,
3866
0x63,0xaa,0xbf,0x4f,0x35,0xdf,0x0c,0xd0,0xbc,0x3e,0x48,0xf5,0xf8,0xb6,0xca,0x5d,
3867
0x52,0xe5,0x3e,0x47,0xf5,0x38,0x4f,0xf9,0xfa,0x44,0xf3,0xfa,0x10,0xd5,0xe7,0x10,
3868
0xe5,0x6b,0x84,0xc6,0xe5,0x30,0xcd,0xeb,0xd7,0xaa,0xdf,0x5c,0xaf,0x7c,0x8e,0x53,
3869
0x3d,0x4d,0x50,0x3f,0x1e,0xa6,0xf2,0x4f,0x52,0xf9,0x27,0x2a,0x3f,0xf7,0x6a,0xbf,
3870
0x9b,0xd4,0x3e,0xb7,0x68,0xfb,0x6d,0x8a,0xe7,0x88,0xe2,0xf9,0x5e,0xe5,0x1d,0xa1,
3871
0x7e,0x78,0x54,0xf3,0x4e,0xa2,0xe6,0xf7,0x29,0xda,0xef,0x47,0x95,0xf7,0xdf,0x8a,
3872
0x7f,0xba,0xe2,0xff,0x5a,0xf1,0x8c,0x56,0xbb,0x4d,0x55,0x7a,0x63,0x54,0x0f,0xd7,
3873
0xa9,0xbc,0x77,0xaa,0xbe,0xa7,0x29,0xfd,0x03,0xe5,0xdc,0xfd,0x26,0x9a,0x35,0x8e,
3874
0x59,0xb7,0x97,0x73,0xfd,0x9f,0x50,0x7c,0x8f,0xa9,0xfc,0x4f,0x95,0x75,0xd3,0x9d,
3875
0xa5,0x7c,0x7d,0xa4,0x7e,0xf7,0xad,0xf4,0x98,0xda,0x67,0xa7,0xdc,0x05,0x14,0xff,
3876
0x4a,0xc5,0xb3,0x5c,0xf1,0xbc,0xa2,0x78,0x56,0xcb,0x3f,0xd6,0x5b,0x0f,0xc9,0xbd,
3877
0x49,0xe1,0xde,0x55,0xb8,0xb7,0xe5,0x7f,0x91,0xd2,0xad,0xa1,0x71,0xd3,0x4a,0xee,
3878
0x6a,0x7e,0x77,0xfb,0x0f,0x3e,0x37,0x9e,0x6d,0x4a,0xff,0x3d,0xe5,0xe7,0x1d,0x95,
3879
0xff,0x7d,0x6d,0x7f,0x52,0xf1,0x3d,0xae,0x74,0xe6,0x28,0x9d,0xd9,0x8a,0x6f,0xbb,
3880
0xf6,0xff,0x4e,0xfa,0xbd,0xe2,0xd9,0x25,0x77,0x94,0xf2,0xbb,0x4a,0xf1,0xac,0x50,
3881
0x3c,0xaf,0x2a,0x9e,0x97,0xe5,0x5f,0x53,0xe1,0xb6,0xc8,0xfd,0x96,0xc2,0xbd,0xa7,
3882
0x70,0xef,0xc8,0xbf,0xa5,0xd2,0x8d,0x51,0xb9,0x5a,0xcb,0x5d,0x5d,0xe5,0xfa,0x51,
3883
0xf9,0xce,0x55,0xfa,0x5b,0x95,0x9f,0x77,0x55,0xae,0x0f,0xb4,0x7d,0x9e,0xe2,0x7b,
3884
0x56,0xe9,0x3c,0xa7,0x74,0x16,0x28,0x1f,0xf3,0xb5,0x7d,0xae,0xb6,0x2f,0xd2,0xf6,
3885
0x85,0xda,0x5e,0x42,0xdb,0xcf,0x96,0xbb,0xa4,0xdc,0xe7,0xc8,0x9d,0x25,0xf7,0xc5,
3886
0x72,0xb7,0x91,0xbb,0xad,0xfa,0xd9,0x55,0xd2,0xee,0xd2,0x1e,0xd2,0x9e,0x0a,0x37,
3887
0xd2,0x5b,0x87,0xa8,0x1f,0x8f,0x96,0x5e,0xa3,0x70,0xf7,0x2b,0xde,0x5c,0x85,0xfb,
3888
0x40,0xf9,0xdc,0xa1,0x7c,0x7e,0xa4,0x7e,0xbe,0x53,0xe1,0x3e,0x54,0xb8,0x6d,0x0a,
3889
0xf7,0xb1,0xc2,0x6d,0x57,0xb8,0x5d,0x0a,0xb7,0x4f,0xe1,0xf6,0x2a,0xdc,0x17,0x0a,
3890
0xf7,0xb9,0xc2,0x1d,0x52,0xb8,0xfd,0x0a,0xf7,0x99,0xc2,0x1d,0x54,0xb8,0x03,0x0a,
3891
0x77,0x58,0xf3,0xd9,0x17,0xaa,0xff,0xcf,0xa5,0x07,0xa4,0x3b,0xa4,0x1f,0x6b,0x7e,
3892
0x3a,0x5f,0xc7,0xeb,0x32,0x6a,0xcf,0x38,0xbf,0xab,0xf1,0x7e,0x37,0x9e,0x83,0x6a,
3893
0xb7,0x17,0x35,0xfe,0x6e,0x0c,0x73,0xb7,0x2f,0x29,0xe7,0xee,0xf7,0x02,0x5a,0xdc,
3894
0x8c,0x23,0xb4,0x84,0xe9,0x77,0x68,0xd0,0x9c,0x57,0x6a,0x7c,0xae,0xd3,0x7e,0x93,
3895
0xc3,0xdc,0x70,0xe7,0x2a,0x5c,0x29,0x6d,0x5f,0xaf,0xed,0x37,0x69,0x7b,0x55,0x6d,
3896
0xbf,0x50,0xf1,0xbc,0xae,0x70,0x1f,0x28,0xdc,0xcd,0x4a,0xff,0x7d,0xa5,0xbf,0xb5,
3897
0x9c,0xdb,0x3e,0x4f,0x69,0xff,0xda,0xda,0x3f,0x55,0xfb,0x7d,0xa3,0xfd,0x6e,0xd5,
3898
0xf6,0x66,0xda,0x9e,0x29,0xfd,0x5c,0xe1,0xf6,0x29,0xdc,0xed,0x8a,0xff,0x33,0xc5,
3899
0xbf,0x57,0xf1,0xcf,0x09,0x73,0xc3,0x77,0x52,0xf8,0x6f,0x15,0x7e,0x8a,0xe2,0xed,
3900
0xa5,0xf8,0x7a,0x2b,0xdf,0xc7,0xa4,0xcf,0x49,0x5f,0xd1,0x7e,0x03,0xb5,0xdf,0xd3,
3901
0x4a,0x67,0xbe,0xd2,0x99,0xa7,0x7a,0x74,0x14,0x8f,0xaf,0x9c,0x3b,0xcf,0x3d,0xaf,
3902
0xfd,0x17,0x6a,0xff,0xc1,0xda,0xff,0x19,0xa5,0x5b,0x54,0xe1,0x8b,0x69,0xfb,0x50,
3903
0x6d,0x7f,0x56,0xdb,0xcb,0x6b,0x7b,0x05,0xc5,0xb7,0x46,0xf1,0xbd,0xac,0xf0,0xc3,
3904
0x15,0x7e,0xae,0xf2,0xf3,0x96,0xf2,0xb3,0x49,0xe5,0x5e,0xaf,0x78,0xe2,0x14,0x4f,
3905
0xbc,0xe2,0x79,0x57,0xfb,0x8f,0xd4,0xfe,0xaf,0x2b,0x5c,0x9a,0xc2,0x35,0x52,0x79,
3906
0x76,0xcb,0xfd,0x89,0xc2,0x8f,0x56,0xf8,0x8d,0x4a,0xef,0x63,0xa5,0xb7,0x43,0xe9,
3907
0x6d,0x50,0x3c,0x59,0xda,0xaf,0x8d,0xd2,0xdb,0xa3,0xfd,0xc7,0x68,0xff,0x37,0x14,
3908
0xae,0x8b,0xc2,0x65,0x2b,0xdc,0xbf,0x54,0xbe,0x23,0x0a,0xbf,0x59,0xe1,0x73,0x74,
3909
0xdc,0x78,0x4f,0xfe,0x3b,0xe5,0x3f,0x4f,0xfe,0x9f,0x6a,0xbf,0xaf,0xe4,0xbf,0x25,
3910
0xcc,0xcd,0xcf,0xdb,0xd2,0xc8,0x70,0xd5,0x4b,0xb8,0xeb,0xde,0x1c,0xee,0x86,0x0b,
3911
0x0b,0x77,0xe3,0x73,0xb4,0xfd,0x5d,0x6d,0xf7,0xc9,0xbd,0x4a,0xee,0x5c,0xe9,0x47,
3912
0x0a,0x7f,0x46,0xb8,0x8e,0x43,0x0a,0x57,0x4a,0xdb,0x77,0x2b,0xde,0xc2,0x72,0xef,
3913
0x51,0xb8,0x2f,0x14,0xee,0x4c,0xf9,0x1f,0x0a,0x77,0xd7,0x0f,0x5f,0xca,0xfd,0x95,
3914
0xf4,0x1b,0xe9,0xe7,0x0a,0xff,0x96,0xdc,0x5b,0x14,0x6f,0x5b,0xa5,0x9f,0xa5,0xed,
3915
0xef,0x69,0x7b,0x1b,0xb9,0x57,0xcb,0xfd,0xa1,0x74,0xbb,0xc2,0x5f,0xae,0x7c,0xec,
3916
0x52,0xb8,0x54,0x6d,0xff,0x44,0xf1,0x5e,0x26,0xf7,0xa7,0x0a,0x77,0x50,0xe1,0xae,
3917
0x90,0xff,0x61,0xe5,0xf7,0x88,0xdc,0x5f,0x4b,0x8f,0x4a,0x0f,0x48,0x3b,0x86,0xbb,
3918
0xeb,0xa0,0xe1,0xd2,0x11,0xf2,0xff,0x40,0xba,0x4d,0xba,0x4f,0xba,0x1f,0x6d,0x1b,
3919
0xe1,0x38,0x15,0xa1,0x1d,0x44,0x43,0x7b,0xa8,0x24,0xf7,0x05,0xd2,0xca,0xd2,0xd5,
3920
0xd2,0x2d,0xd2,0x95,0x50,0x2f,0x8a,0xf9,0x26,0xca,0xd5,0x78,0x69,0x12,0x2c,0x87,
3921
0x0d,0xf0,0x1e,0xbc,0x0e,0x0d,0x0a,0xb1,0x9e,0x86,0x0e,0xd0,0x0c,0x3a,0xc2,0x45,
3922
0xf0,0x1e,0xdc,0x05,0xcb,0x61,0xbd,0xdc,0xaf,0xcb,0xbd,0xc1,0x84,0x2f,0x4c,0x78,
3923
0x78,0x07,0x56,0xc2,0x6a,0x58,0x2f,0xf7,0x5a,0x78,0x17,0xd6,0xc9,0xbd,0x01,0x1a,
3924
0x9c,0xe1,0x38,0xcd,0xa1,0x23,0x5c,0x74,0x86,0xeb,0x6e,0x01,0xeb,0xe1,0x03,0x78,
3925
0x13,0x72,0x61,0x3b,0x7c,0x24,0xff,0x0f,0x21,0xb6,0x28,0xe5,0x84,0xe4,0xd2,0xd4,
3926
0x7d,0x69,0x57,0x0b,0x48,0x0b,0x4a,0x0b,0x4b,0xcf,0x94,0x9e,0x25,0xad,0x2b,0xad,
3927
0x2f,0x4d,0x93,0x36,0x92,0x36,0x2e,0xed,0xb6,0x6b,0x6d,0x1d,0x27,0x52,0xa5,0x97,
3928
0x49,0x2f,0xd7,0xf1,0xb1,0x97,0xb4,0xb7,0xd6,0x9b,0x4f,0xeb,0xf8,0xf2,0xbc,0xdc,
3929
0xcf,0xc8,0xbd,0x58,0xee,0x35,0xd2,0xb5,0xd2,0xad,0xd2,0xf7,0x75,0xbc,0xf3,0x6b,
3930
0x3c,0x86,0x6b,0x7c,0x47,0x68,0x9c,0x8e,0xd5,0x38,0x0e,0xd3,0xf6,0x80,0xb6,0x47,
3931
0x6a,0xfb,0x38,0xe9,0x78,0xe9,0x04,0xe9,0x0d,0xd2,0x89,0xd2,0x1b,0xa5,0x93,0x14,
3932
0x5f,0x41,0xc5,0x57,0x58,0xf1,0x9d,0xa9,0xed,0x93,0xb5,0xbd,0x90,0xb6,0x9f,0xa1,
3933
0xed,0x45,0xb4,0xfd,0x26,0xe9,0xcd,0xd2,0x5b,0xa4,0xb7,0x4a,0x6f,0x93,0xde,0x2e,
3934
0x9d,0xa2,0xf8,0xce,0x52,0x7c,0x25,0xe4,0x2e,0x2e,0x77,0x49,0xb9,0xcf,0x93,0xfb,
3935
0x7c,0xb9,0x4b,0xcb,0x5d,0x46,0xee,0x8a,0x72,0x5f,0xa0,0xfc,0x54,0x56,0xfc,0x39,
3936
0xda,0x1e,0xad,0xed,0x95,0xb4,0xbd,0x8a,0xb6,0x4f,0x95,0xde,0x21,0xbd,0x53,0x7a,
3937
0x97,0x74,0x9a,0xf4,0x6e,0xe9,0x3d,0x8a,0xaf,0x9a,0xe2,0xab,0xa1,0xf8,0x62,0xb5,
3938
0xfd,0x5e,0x6d,0xaf,0xae,0xed,0x31,0xda,0x5e,0x53,0xdb,0xa7,0x4b,0xef,0x93,0xde,
3939
0x2f,0x7d,0x40,0xfa,0xa0,0xf4,0x21,0xe9,0xc3,0x8a,0x2f,0x41,0xf1,0x25,0x29,0xbe,
3940
0x14,0xf9,0x27,0xca,0x3f,0x59,0xfe,0xb5,0xe4,0x5f,0x47,0xfe,0xf5,0xe4,0xdf,0x40,
3941
0xfe,0x75,0xe5,0x5f,0x5f,0xfe,0x0d,0xe5,0x9f,0x2e,0xff,0x26,0x72,0x37,0x96,0x3b,
3942
0x28,0x77,0x73,0xb9,0x2f,0x92,0xbb,0x85,0xdc,0x2d,0xe5,0xbe,0x58,0xee,0x76,0x8a,
3943
0xb7,0x83,0xfc,0xdb,0xca,0xbf,0xbd,0xfc,0x3b,0xca,0xbf,0xb3,0xfc,0x2f,0x97,0xff,
3944
0x95,0xf2,0xef,0x2a,0xff,0xab,0xe4,0xdf,0x43,0xf5,0x30,0x43,0xdb,0xbb,0x69,0x7b,
3945
0x77,0x6d,0xef,0xa9,0xed,0x33,0xa5,0x8f,0x48,0x1f,0x95,0x3e,0x26,0x7d,0x5c,0xfa,
3946
0x84,0xf4,0x49,0xc5,0x77,0xb5,0xe2,0xeb,0xab,0xf8,0xfa,0x6b,0xfb,0x2c,0x6d,0xef,
3947
0xa3,0xed,0xfd,0xb4,0x7d,0x80,0xb6,0xcf,0x96,0x3e,0x25,0x9d,0x23,0x7d,0x5a,0xfa,
3948
0x8c,0xf4,0x59,0xe9,0x5c,0xe9,0x02,0xe9,0x6a,0xe9,0x97,0xd2,0xc5,0x4a,0x6f,0xa3,
3949
0x77,0x5c,0x57,0x7a,0x6f,0x6a,0xfb,0x5a,0xe9,0xbf,0x15,0xee,0x43,0x85,0xfb,0x48,
3950
0xe1,0xb6,0x97,0x73,0xef,0xeb,0xdc,0x57,0xc1,0xd5,0xfb,0xa5,0xcf,0x4a,0x37,0x4a,
3951
0xdf,0x94,0xbe,0x21,0x0d,0xd7,0xfd,0xa0,0x28,0x69,0x61,0xe9,0x05,0xd2,0xca,0xd2,
3952
0x46,0xd2,0x26,0xd2,0x0c,0x69,0xa6,0xb4,0x9f,0xb4,0xab,0x74,0xa0,0x74,0x90,0x74,
3953
0xa8,0x74,0x98,0x74,0xa4,0x74,0x94,0x74,0xac,0x74,0x9c,0x74,0x87,0xf4,0x63,0xe9,
3954
0x0d,0xd2,0x89,0xd2,0xc9,0xd2,0x9b,0xa4,0x3b,0xa5,0xbb,0xa4,0x4f,0x4b,0x9f,0x91,
3955
0x3e,0x2b,0x9d,0x2b,0xdd,0x27,0xdd,0x2f,0xfd,0x5c,0x7a,0x00,0x9d,0x1e,0xc7,0xf8,
3956
0x8f,0x73,0xf5,0x22,0x69,0x2b,0x69,0x96,0xf4,0x62,0x69,0x3b,0x69,0x07,0xe9,0x25,
3957
0xd2,0x4b,0xa5,0x97,0x49,0xaf,0x90,0x76,0x91,0x76,0x95,0x76,0x97,0xf6,0x94,0xf6,
3958
0x96,0x0e,0x84,0xfb,0x60,0x90,0xdc,0x43,0xe4,0x1e,0x2a,0xf7,0x70,0xb9,0x47,0xc8,
3959
0x3d,0x4a,0xee,0xd1,0x72,0x8f,0x91,0xfb,0x5a,0xb9,0x1f,0x92,0x7e,0x25,0x7d,0x5a,
3960
0xfa,0xac,0x74,0x9e,0x74,0x81,0xf4,0x39,0xe9,0xf3,0xd2,0x17,0xa4,0x2f,0x4a,0x97,
3961
0x4a,0x97,0x4b,0x57,0x4a,0x57,0x4b,0x5f,0x95,0xae,0x95,0xbe,0x26,0xdd,0xa4,0x7c,
3962
0xbd,0x25,0xf7,0x16,0xb9,0xdf,0x96,0xfb,0x5d,0xb9,0xdf,0x93,0xfb,0x7d,0xb9,0x3f,
3963
0x90,0x3b,0x57,0xee,0x0f,0xe5,0xfe,0xb7,0xf4,0x1b,0xe9,0x51,0xe9,0xb7,0xd2,0x1f,
3964
0xe2,0xdc,0xe3,0xf0,0x6b,0x01,0x5f,0x9e,0xee,0x46,0x5f,0x2c,0xea,0x73,0xee,0x2b,
3965
0xea,0xea,0x03,0xd2,0x39,0x50,0xa5,0x98,0xcf,0x89,0x2d,0xe6,0x6a,0x4d,0x68,0x50,
3966
0xdc,0xe7,0xb4,0x80,0x8e,0x70,0x11,0xbc,0x06,0x13,0xe0,0x25,0x98,0x08,0xab,0xe1,
3967
0x76,0xf9,0x4f,0x85,0x17,0x60,0xad,0xfc,0x5f,0x95,0xff,0x3a,0x98,0x57,0xc2,0xe7,
3968
0x2c,0x85,0x17,0xe1,0x25,0x58,0x06,0xcb,0x61,0x6e,0x49,0xfc,0x4a,0xba,0xfa,0x12,
3969
0xc4,0x95,0xf2,0x39,0xb5,0xa1,0x6c,0xb6,0xcf,0xa9,0x00,0xe5,0x20,0x1a,0xca,0x43,
3970
0x25,0xb8,0x10,0x2a,0xca,0xbf,0xb2,0xfc,0xab,0xca,0x5d,0x45,0x7a,0x01,0xf4,0xec,
3971
0xe7,0x73,0x7a,0xf7,0x73,0xb5,0x97,0xf4,0x6a,0xa0,0x2a,0x9c,0x54,0x68,0x04,0x97,
3972
0xc2,0x95,0x22,0x1b,0x46,0xc3,0x53,0x62,0x91,0x58,0x2c,0x5e,0x14,0xe6,0x5e,0xb1,
3973
0xb9,0x9f,0x65,0xfe,0x14,0x9a,0xb9,0x0e,0xfa,0x8d,0xf1,0xe7,0xbc,0xf8,0x25,0xb1,
3974
0x14,0x56,0xc0,0x4a,0x78,0x19,0x5e,0x81,0x3b,0x39,0x7f,0xbe,0x0b,0xa6,0xc1,0xdd,
3975
0x30,0x17,0xe6,0xc1,0x2a,0x58,0x03,0x6f,0xc1,0x0e,0xd8,0x0d,0x9f,0x8b,0x2f,0x84,
3976
0x99,0xe7,0x06,0x98,0xb9,0xc4,0x5c,0xe7,0x33,0x73,0x88,0x18,0x6e,0xd6,0xc3,0xe6,
3977
0x1c,0x4a,0x5c,0x63,0xae,0xf7,0x99,0x6b,0x7d,0xe2,0x46,0x31,0x49,0x4c,0xd6,0xf9,
3978
0xf2,0xad,0xc2,0x9c,0xdb,0xce,0x34,0xc7,0x08,0xb3,0xfe,0x36,0x73,0xaa,0x99,0x77,
3979
0x58,0x3f,0x4f,0x80,0x49,0x70,0x33,0xd4,0x0c,0xb0,0x06,0x86,0x0e,0x70,0x09,0x74,
3980
0x82,0x2e,0x30,0x19,0x6e,0x81,0x5b,0x61,0x2a,0x2c,0x83,0x15,0x62,0x15,0xac,0x86,
3981
0x57,0xe0,0x55,0x58,0x1b,0x30,0xfd,0x8e,0x3e,0x0f,0xfb,0xe0,0x20,0x7c,0x09,0x45,
3982
0x59,0x6b,0x9f,0x07,0xe5,0xa1,0x21,0xa4,0x89,0x46,0xd0,0x1c,0x5a,0xc0,0x95,0xd0,
3983
0x05,0x7a,0x43,0x7f,0x18,0x00,0x03,0xc5,0x20,0xad,0xdb,0xdf,0x11,0xef,0x42,0x2e,
3984
0x6c,0x87,0xdd,0xf0,0x09,0xec,0x81,0x4f,0x61,0x2f,0xec,0x83,0x03,0xf0,0x05,0x1c,
3985
0x84,0x43,0x70,0x14,0xbe,0x85,0x63,0xf0,0xa3,0x28,0x1a,0xe9,0x52,0x4c,0x9c,0x05,
3986
0x35,0x21,0x0e,0x9a,0x43,0x4b,0x78,0x1c,0x9e,0x80,0x79,0x30,0x5f,0xac,0x84,0xd7,
3987
0x60,0x3d,0xec,0x83,0xfd,0x70,0x04,0xbe,0x82,0xaf,0xe1,0x5b,0xf1,0xbd,0x70,0x0a,
3988
0xb0,0xae,0x83,0xb3,0xa1,0x14,0x9c,0x27,0x4a,0x43,0x34,0x5c,0x20,0x2a,0x41,0x15,
3989
0xa8,0x2a,0x2e,0x84,0x18,0x48,0x83,0x4b,0xa0,0x13,0x74,0x86,0x2e,0x70,0x35,0x0c,
3990
0x84,0x49,0x70,0x13,0x4c,0x81,0x7b,0xe0,0x61,0x98,0x01,0xeb,0xe0,0x35,0xb1,0x1e,
3991
0x3e,0x86,0x5d,0xe0,0xe7,0x7c,0x26,0x4c,0x84,0x43,0x2a,0xd4,0x11,0x75,0x45,0x3d,
3992
0x51,0x5f,0x34,0x80,0x34,0x68,0x04,0xcd,0x20,0x13,0x2e,0x82,0x96,0xa2,0x15,0xb4,
3993
0x86,0x2c,0xd1,0x06,0x3a,0xc2,0x25,0x90,0x0d,0x5d,0xa1,0x1b,0xf4,0x80,0x01,0x30,
3994
0x48,0x0c,0x86,0xb1,0x30,0x4e,0x8c,0x87,0x09,0x30,0x11,0x6e,0x85,0x29,0x90,0x03,
3995
0x77,0xc2,0x2c,0x78,0x0a,0xe6,0xc1,0x02,0xf1,0x3c,0x2c,0x81,0xa5,0x62,0x99,0x30,
3996
0xe7,0x6f,0x2b,0x61,0x15,0xbc,0x02,0x6b,0x61,0x9d,0xce,0xe9,0xcc,0xf9,0xdc,0x46,
3997
0xf1,0x86,0x78,0x4f,0xe4,0xc2,0x87,0xb0,0x1d,0x3e,0x86,0x9d,0xb0,0x0b,0xf6,0xc0,
3998
0x41,0x38,0x04,0x87,0xe1,0x98,0xf8,0x41,0xf8,0x0a,0x52,0xaf,0x10,0x26,0x02,0x50,
3999
0x10,0x8a,0x40,0x51,0x28,0x0e,0x55,0xa1,0x1a,0xc4,0x41,0x02,0x24,0x42,0x32,0xa4,
4000
0x40,0x6d,0x48,0x85,0x7a,0xa2,0x01,0xa4,0x41,0x23,0x48,0x87,0x0c,0x68,0x06,0x2d,
4001
0xa0,0x25,0xb4,0x11,0x9d,0xe0,0x32,0xb8,0x42,0xf4,0x80,0x01,0x30,0x10,0x06,0xc1,
4002
0x60,0x18,0x0a,0xc3,0xc4,0x38,0x18,0x0f,0x13,0xc4,0x44,0xb8,0x0d,0xa6,0xc0,0x54,
4003
0xb8,0x13,0x66,0xc1,0x53,0x30,0x0f,0x16,0xc0,0x42,0x58,0x04,0x4b,0x60,0xa9,0x58,
4004
0x26,0x96,0xc3,0x4a,0x58,0x05,0xaf,0xc2,0x5a,0x58,0x07,0xaf,0x89,0x0d,0xf0,0x3a,
4005
0x6c,0x14,0x9b,0xc4,0x0e,0xf8,0x18,0x76,0xc2,0x2e,0xd8,0x03,0x07,0xe1,0xa8,0xf8,
4006
0x16,0x7e,0x04,0x5f,0x21,0x17,0x3f,0x84,0x41,0x00,0x0a,0x43,0x11,0x28,0x0a,0xc5,
4007
0xa1,0x2a,0x54,0x83,0x38,0x48,0x80,0x44,0x48,0x86,0x54,0xa8,0x27,0xea,0x8b,0x06,
4008
0xa2,0xa1,0x48,0x13,0x8d,0xa0,0x09,0x64,0xe8,0xfc,0xbe,0x85,0xce,0xef,0x5b,0x8a,
4009
0xb6,0x3a,0xf7,0xef,0x28,0x2e,0x83,0xcb,0xe1,0x4a,0xc8,0x86,0xae,0xd0,0x0d,0x7a,
4010
0xc0,0x00,0x18,0x24,0xc6,0x8b,0x09,0x62,0x22,0xdc,0x0c,0xb7,0x43,0x0e,0xdc,0x01,
4011
0xd3,0x60,0x3a,0xdc,0x07,0x0f,0x88,0x87,0xe0,0x61,0x78,0x14,0x1e,0x83,0x59,0xf0,
4012
0x14,0x3c,0x0b,0x4b,0x74,0x7d,0x61,0x05,0xac,0x14,0xab,0x60,0x35,0xac,0x81,0x75,
4013
0xba,0x16,0x61,0xae,0x43,0x6c,0x14,0x9b,0xc4,0x7b,0x62,0x0f,0x1c,0x2c,0x64,0x6e,
4014
0x7c,0xbb,0xf8,0x20,0x0c,0xc2,0x45,0x00,0x0a,0xc3,0x99,0x50,0x14,0xce,0x82,0xaa,
4015
0x50,0x0d,0x52,0xa1,0x9e,0xa8,0x2f,0x1a,0x40,0x1a,0x34,0x82,0x26,0xd0,0x54,0xd7,
4016
0x3d,0x9a,0x43,0x4b,0x68,0x5f,0xd8,0xbd,0x16,0x72,0x09,0x5c,0x0a,0x97,0xc1,0xe5,
4017
0xd0,0x05,0xb2,0xa1,0x2b,0x74,0x83,0x1e,0x30,0x00,0xc6,0x8a,0x71,0x62,0x3c,0x4c,
4018
0x80,0x89,0x70,0x2b,0xdc,0x0e,0x39,0x70,0x07,0xcc,0x82,0xa7,0x60,0x21,0x2c,0x82,
4019
0x25,0xb0,0x54,0x2c,0x13,0xcb,0xc5,0x0a,0x61,0xae,0xc5,0xbc,0x02,0x6b,0xc4,0x5a,
4020
0x5d,0x87,0x59,0xaf,0xeb,0x30,0xaf,0xc3,0x46,0x5d,0x97,0x31,0xd7,0x68,0x72,0xe1,
4021
0x23,0xd8,0x01,0x1f,0xc3,0x4e,0xd8,0x05,0x7b,0xe0,0x20,0x1c,0x86,0x2f,0xe1,0x88,
4022
0x70,0xce,0xa0,0x4e,0xc1,0x0f,0x61,0x10,0x0e,0x85,0xe1,0x4c,0x28,0x0a,0x67,0x41,
4023
0x1d,0xa8,0x0b,0xf5,0xa0,0xbe,0x30,0xd7,0x7b,0xd2,0xa0,0x11,0x34,0x81,0xa6,0xd0,
4024
0x4c,0xd7,0x84,0xcc,0xf5,0xa0,0x96,0xa2,0x95,0x68,0x07,0x1d,0x74,0xbd,0xc8,0x70,
4025
0x25,0x64,0x43,0x57,0xe8,0x06,0x3d,0x60,0x00,0x8c,0x86,0xeb,0x61,0x9c,0x18,0x0f,
4026
0x13,0x60,0x22,0xdc,0x0d,0xf7,0xc1,0x7c,0x58,0x08,0x2f,0xc1,0x32,0xb1,0x12,0xd6,
4027
0xe8,0x3a,0xd3,0x7a,0x5d,0x7f,0x7a,0x0b,0x36,0xc3,0xdb,0xf0,0xae,0xd8,0xaa,0x6b,
4028
0x52,0x7b,0xe0,0x20,0x7c,0x09,0x47,0x4c,0x1d,0x9c,0xc9,0xb8,0x84,0x78,0x91,0x00,
4029
0x89,0x90,0x04,0x75,0x20,0x0d,0x82,0xd0,0x54,0x64,0x40,0x2b,0xc8,0x82,0x4e,0x30,
4030
0x0e,0xc6,0xc3,0x0d,0xe2,0x46,0xb8,0x19,0x6e,0x85,0x47,0xe1,0x71,0xf1,0x24,0xcc,
4031
0x83,0xf9,0x62,0x01,0x2c,0x84,0xe7,0x60,0x29,0x2c,0x13,0x2b,0xe1,0x15,0x58,0x23,
4032
0xd6,0xc1,0x1b,0xb0,0x09,0xde,0x87,0x5c,0xd8,0x0e,0x4e,0x11,0x97,0x73,0xa1,0x14,
4033
0x94,0x87,0x0b,0x21,0x59,0xd4,0x12,0xa9,0xa2,0x01,0x34,0x84,0x34,0xc8,0x80,0x4c,
4034
0xe8,0x0b,0x83,0xe0,0x3a,0xb8,0x5e,0x8c,0x85,0x1b,0xe0,0x46,0x98,0x04,0x93,0xe1,
4035
0x56,0xb8,0x0d,0xee,0x81,0xe9,0xb0,0x14,0xd6,0x08,0xa7,0x28,0x63,0x0e,0xaa,0x43,
4036
0x0d,0x88,0x81,0x38,0x88,0x17,0x09,0x50,0x0b,0x6a,0x8b,0x54,0xa8,0x03,0x75,0xa1,
4037
0x1e,0xd4,0x87,0x06,0xd0,0x50,0xa4,0x41,0x26,0x64,0x41,0x7b,0xe8,0x00,0x1d,0xe1,
4038
0x12,0xe8,0x04,0x97,0xc2,0xe5,0x70,0x05,0x74,0x81,0x6c,0xd1,0x15,0xae,0x82,0xee,
4039
0xd0,0x03,0x7a,0x42,0x3f,0xe8,0x0f,0x03,0x61,0x10,0x0c,0x85,0x61,0x30,0x0e,0xc6,
4040
0x8b,0x09,0x70,0x03,0x4c,0x84,0x1b,0x61,0x12,0xdc,0x0a,0xb7,0x89,0xdb,0xc5,0x14,
4041
0x91,0x03,0xd3,0xe1,0x3e,0x78,0x00,0x1e,0x14,0x33,0xe0,0x55,0x58,0x2b,0x36,0x8a,
4042
0x4d,0xf0,0x2d,0x1c,0x13,0xdf,0xc3,0x8f,0xe0,0x14,0x63,0xdc,0x9c,0xc5,0xb8,0x81,
4043
0x96,0x90,0x05,0x1d,0xe0,0x12,0x71,0x29,0x5c,0x0e,0x5d,0x60,0x32,0xdc,0x0c,0xb7,
4044
0x41,0x0e,0xcc,0x83,0x05,0xb0,0x08,0x5e,0x80,0xe5,0xb0,0x52,0xac,0x86,0x57,0x61,
4045
0x1d,0xbc,0x0b,0x5b,0xa1,0x68,0x71,0xc6,0x33,0x94,0x84,0x73,0xe1,0x52,0xb8,0x1c,
4046
0xae,0x84,0xde,0x30,0x08,0xc6,0xc2,0x14,0x98,0x01,0x5f,0xc3,0x37,0xf0,0x3d,0xf8,
4047
0x4a,0xd0,0x4f,0xce,0x66,0x8c,0xc2,0xf5,0x30,0x0e,0xee,0x83,0x19,0xb0,0x0f,0xbe,
4048
0x80,0x43,0x70,0x18,0xbe,0x01,0xe7,0x1c,0x8a,0x06,0x67,0x41,0x09,0x28,0x29,0xca,
4049
0x41,0x3c,0x24,0x40,0x22,0x24,0x89,0x34,0x68,0x03,0x17,0x43,0x5b,0xe8,0x02,0x7d,
4050
0xa1,0x3f,0x0c,0x84,0xc1,0x30,0x04,0xc6,0xc2,0x42,0x78,0x0e,0x16,0xc1,0xf3,0x62,
4051
0x31,0x2c,0x83,0xe5,0xf0,0x2a,0xac,0x11,0x6b,0x61,0x1d,0xbc,0x06,0x5b,0xe0,0x3d,
4052
0x91,0x2b,0x3e,0x14,0x3b,0xe0,0x33,0x28,0x74,0x2e,0x53,0x22,0x14,0x11,0x45,0xa1,
4053
0x14,0x94,0x87,0x74,0x68,0x2c,0x9a,0xc0,0x48,0x18,0x0b,0x37,0xc0,0x44,0xb8,0x11,
4054
0x26,0xc1,0x2c,0x98,0x2d,0x9e,0x12,0xf3,0xe0,0x6b,0x70,0x4a,0x39,0x4e,0x59,0x28,
4055
0x0f,0x15,0x21,0x1a,0x2a,0x43,0x15,0xa8,0x0a,0x17,0x42,0x75,0x88,0x83,0x78,0x48,
4056
0x10,0x89,0x50,0x1b,0x52,0xa1,0x2e,0x34,0x85,0xd6,0x90,0x05,0xfd,0x60,0x20,0x0c,
4057
0x85,0xb1,0x30,0x07,0xe6,0xc1,0x6b,0xb0,0x09,0xde,0x87,0x0f,0x84,0x73,0x1e,0x6b,
4058
0x7b,0x38,0x07,0xce,0x85,0x52,0x70,0x1e,0x94,0x16,0xe5,0xa1,0x1d,0xb4,0x17,0x1d,
4059
0x44,0x47,0x71,0x09,0x5c,0x01,0x5d,0x44,0xb6,0xe8,0x2a,0xba,0xc1,0x55,0xd0,0x1d,
4060
0xfa,0x42,0x3f,0x18,0x0c,0x43,0x60,0x0c,0x5c,0x2f,0xc6,0xc2,0x4d,0x90,0x03,0xd3,
4061
0xe1,0x49,0x31,0x0f,0x96,0xc1,0x0a,0x38,0x04,0x4e,0x69,0x8e,0x4b,0xe6,0xba,0xbe,
4062
0x08,0x40,0x22,0x24,0x89,0x64,0x91,0x02,0x75,0x74,0x8f,0xc0,0x50,0x4f,0xd4,0xd7,
4063
0xfd,0x81,0x74,0x61,0xee,0x11,0x34,0x81,0x20,0x5c,0x04,0x59,0xd0,0x09,0xfa,0xc0,
4064
0x10,0x18,0x0b,0xe3,0x60,0xbc,0x98,0x00,0x33,0x60,0xa6,0x78,0x04,0x1e,0x87,0x27,
4065
0xe0,0x49,0x98,0x05,0xb3,0xe1,0x29,0x31,0x07,0x9e,0x81,0x67,0x61,0x2e,0xcc,0x83,
4066
0x25,0xf0,0x22,0x7c,0x02,0x7b,0xc4,0xa7,0x62,0x2f,0x7c,0x06,0xfb,0xe0,0x73,0x38,
4067
0x20,0xbe,0x10,0x07,0xe1,0x30,0x7c,0x09,0x47,0xc0,0x39,0x9f,0x3e,0x03,0x17,0x40,
4068
0x75,0xa8,0x01,0x89,0x90,0x04,0xc9,0x90,0x02,0xb5,0x20,0x0d,0x32,0xa1,0x25,0xb4,
4069
0x86,0x2c,0xe8,0x04,0x97,0xc2,0x08,0x18,0x09,0xd7,0xc2,0x58,0xb8,0x19,0x72,0xe0,
4070
0x45,0x58,0x06,0x2b,0x60,0x13,0x6c,0x86,0xb7,0x61,0x07,0x7c,0x2c,0x76,0xc2,0x5e,
4071
0xf8,0x0c,0x3e,0x87,0x03,0xe2,0x0b,0x38,0x02,0x5f,0x89,0xaf,0xe1,0x5f,0xf0,0x6f,
4072
0xf1,0x0d,0x1c,0x85,0x6f,0x85,0x53,0x86,0xfc,0x43,0x0d,0xb8,0x1a,0xfa,0xc0,0x08,
4073
0x18,0x29,0x46,0xc1,0x7d,0x70,0x3f,0xac,0x80,0x95,0xf0,0x63,0x19,0xf7,0x19,0x75,
4074
0x73,0xdf,0xc1,0xdc,0xa3,0x37,0xf7,0x17,0xcc,0xbd,0x63,0x73,0x1d,0xdc,0xdc,0x33,
4075
0x37,0xd7,0xbb,0xcd,0x3d,0x59,0x73,0x1d,0xbb,0x93,0xe8,0x2c,0x2e,0x17,0xe6,0x5a,
4076
0xf6,0xb5,0xe5,0xdc,0x7b,0x33,0xe6,0xbe,0xb7,0xb9,0x77,0x6d,0x9e,0x03,0x58,0x2e,
4077
0xcc,0xb5,0x5f,0x73,0x1f,0xdc,0xdc,0x83,0x36,0xf7,0xf5,0xcd,0x3d,0xe6,0x2d,0xe5,
4078
0xdc,0x7b,0xc9,0xdb,0xca,0xb9,0xf7,0x80,0xcd,0xfd,0x78,0x73,0x6d,0xd8,0xdc,0x87,
4079
0x35,0xf7,0x72,0xcd,0x7d,0xf4,0xc2,0xe5,0x99,0x37,0xa0,0x21,0xa4,0x41,0x3b,0x31,
4080
0x48,0x5c,0x2f,0xa6,0xc0,0xc3,0xb0,0x09,0x72,0xe1,0x63,0xf1,0x09,0x1c,0x02,0x7f,
4081
0x05,0x97,0x48,0x51,0x10,0x8a,0x43,0x49,0x71,0xae,0x28,0x05,0x65,0xe0,0x02,0x51,
4082
0x59,0x54,0x15,0xd5,0x20,0x06,0x62,0x45,0x4d,0x48,0x82,0x64,0x73,0x6d,0x19,0x52,
4083
0x45,0x3d,0x68,0x08,0x41,0xc8,0x84,0x56,0xa2,0x0b,0x8c,0x87,0x09,0x70,0x03,0x4c,
4084
0x84,0xc9,0xe0,0xd4,0x70,0x9c,0x6b,0x60,0x0c,0x5c,0x0b,0xd7,0xc1,0x6e,0xd8,0x0f,
4085
0x5f,0xc0,0x41,0x38,0x0c,0x5f,0xc2,0x11,0x70,0x62,0x1c,0xa7,0x12,0x54,0x11,0x31,
4086
0x22,0x0e,0x7a,0xc2,0x00,0x71,0xbd,0x18,0x0b,0x77,0xc3,0x0c,0x78,0x02,0x66,0xc1,
4087
0xb3,0x30,0x0f,0x9e,0x87,0x17,0x60,0x39,0xac,0x84,0x35,0xb0,0x0e,0xde,0x80,0x4d,
4088
0xf0,0x2e,0x6c,0x85,0x8f,0x60,0x07,0xfc,0x08,0x81,0x38,0x97,0x08,0x11,0x29,0x2a,
4089
0xc0,0x85,0x50,0x0d,0x62,0x20,0x16,0x6a,0x42,0x3c,0x24,0x43,0x6d,0xa8,0x03,0x75,
4090
0x45,0x3d,0xd1,0x08,0xee,0xd6,0xf5,0x4b,0x73,0xad,0xf3,0x7e,0x78,0x00,0x1e,0xd4,
4091
0x75,0xdc,0x87,0xc5,0x4c,0x5d,0xe7,0xfc,0x4e,0x1c,0xd3,0xf5,0xce,0x1f,0x45,0x20,
4092
0x9e,0xf4,0x20,0x1e,0x6e,0x87,0x19,0xb0,0x02,0x0e,0xc1,0x8f,0xe0,0x24,0xe1,0x6e,
4093
0x89,0xb6,0xe2,0xf8,0x39,0x83,0xb6,0x17,0x67,0xc3,0xad,0x8f,0x51,0x5e,0xf8,0x37,
4094
0x7c,0x03,0xdf,0x83,0xf3,0x38,0xc7,0xae,0x27,0xe8,0x87,0xa2,0x28,0x94,0x83,0xf2,
4095
0x70,0x21,0x54,0x83,0xea,0x90,0x06,0xfd,0xa0,0xbf,0x18,0x20,0x86,0xc2,0xb5,0x70,
4096
0xbd,0x18,0x0b,0xf7,0xc3,0x03,0xf0,0x20,0x3c,0x04,0x0f,0xc3,0x0c,0xf8,0x04,0xf6,
4097
0xc0,0x41,0x38,0x04,0x87,0xe1,0x9c,0x27,0x49,0x0f,0x2a,0xc2,0x00,0x18,0x28,0x06,
4098
0xc1,0x24,0x98,0x2c,0x6e,0x81,0xdb,0x61,0x8a,0xc8,0x81,0x0f,0x61,0xa7,0x38,0x0c,
4099
0x5f,0xc1,0xd7,0xf0,0x2f,0xf8,0xb7,0xf8,0x06,0x8e,0xc2,0xb7,0xe2,0x3b,0xf0,0xcd,
4100
0x62,0xac,0x88,0x30,0x08,0x40,0x84,0x88,0x84,0x82,0x50,0x48,0x14,0x86,0x8a,0x10,
4101
0x0d,0x17,0x40,0x25,0xa8,0x0c,0x55,0x44,0x0d,0x91,0x06,0x43,0x60,0x2c,0x8c,0x83,
4102
0xf1,0xb0,0x10,0x9e,0x83,0x97,0xe1,0x15,0x78,0x15,0x36,0xc1,0xfb,0xb0,0x03,0x0e,
4103
0xc3,0x97,0xf0,0x6f,0xf8,0x4e,0x7c,0x0f,0x3f,0xc0,0x8f,0xc2,0x99,0xed,0x38,0x51,
4104
0x50,0x10,0x2a,0x41,0x65,0x88,0x81,0x38,0x68,0x0a,0x19,0xd0,0x06,0x2e,0x86,0xb6,
4105
0xd0,0x05,0xc6,0xc0,0x58,0x18,0x0f,0x13,0xc4,0x0d,0xb0,0x00,0x16,0x8a,0xe7,0x60,
4106
0x11,0x3c,0x0f,0x4b,0xe0,0x45,0x78,0x09,0x96,0xc2,0x32,0x58,0x0e,0x2b,0xe1,0x4d,
4107
0xb1,0x09,0xde,0x87,0x1d,0xb0,0x1b,0x3e,0x11,0x7b,0xc4,0xa7,0x70,0x10,0x0e,0xc1,
4108
0x51,0xf8,0x16,0x7e,0x98,0xed,0x5e,0x7c,0xae,0x0a,0x17,0x42,0x2c,0xd4,0x84,0x38,
4109
0x88,0x87,0x04,0x48,0x84,0x24,0x48,0x86,0x14,0x48,0x83,0x74,0x68,0x2c,0x9a,0x40,
4110
0x0b,0xb8,0x48,0xb4,0x14,0x59,0xd0,0x09,0xba,0xc0,0x00,0x18,0x28,0x06,0xc1,0x70,
4111
0x18,0x2d,0xae,0x11,0x63,0xc4,0xb5,0xe2,0x3a,0x98,0x0b,0xf3,0xc4,0x7c,0xb1,0x00,
4112
0x9e,0x83,0x45,0xf0,0x3c,0x2c,0x86,0x17,0x60,0x09,0x2c,0x83,0xe5,0xb0,0x02,0x56,
4113
0x8a,0x55,0x62,0xb5,0xd8,0x06,0xb9,0xf0,0xa1,0xd8,0x01,0xfb,0x60,0xbf,0xf8,0x1c,
4114
0x0e,0xc0,0x17,0x70,0x10,0xbe,0x14,0x47,0xe0,0x2b,0xf8,0x5a,0xfc,0x4b,0xf8,0xe6,
4115
0xd0,0x2f,0x21,0x0a,0xce,0x84,0x62,0x70,0x36,0x94,0x87,0xca,0x50,0x15,0x62,0x21,
4116
0x0e,0x2e,0x85,0xcb,0xe0,0x4a,0xe8,0x02,0xbd,0xa0,0xb7,0xe8,0x0b,0xfd,0x60,0x20,
4117
0xac,0x80,0x95,0xb0,0x13,0x76,0xc1,0x6e,0xf8,0x44,0xec,0x81,0x4f,0x61,0xaf,0xf8,
4118
0x0c,0xf6,0xc1,0xe7,0xe2,0x80,0x38,0x04,0x47,0xc1,0x79,0x9a,0xf3,0xd4,0xf7,0xa8,
4119
0x43,0x58,0x03,0x1b,0xe0,0x3b,0x30,0x0f,0x11,0xf7,0xfb,0x96,0xf4,0xe0,0x7d,0xf3,
4120
0x20,0xf1,0x77,0x94,0x03,0x8a,0xc3,0x39,0x50,0x46,0x94,0x15,0xe5,0xa0,0x2a,0x54,
4121
0x83,0x14,0xa8,0x0d,0xf5,0xa0,0x81,0x48,0x83,0x46,0xd0,0x18,0x9a,0x40,0x53,0x98,
4122
0x0f,0x5b,0xa0,0xfe,0xf7,0xf4,0x07,0x98,0x02,0x77,0xc0,0x5a,0x38,0x04,0xdf,0x99,
4123
0x07,0x7a,0x7f,0x60,0x3d,0x0e,0xe5,0xa1,0x26,0x24,0x42,0x12,0xb4,0x84,0xd6,0x30,
4124
0x10,0x86,0xc2,0x70,0x38,0x06,0x45,0x7f,0xe4,0x18,0x09,0x15,0xa0,0x0e,0x34,0x14,
4125
0x8d,0xe0,0x52,0xe8,0x2e,0x7a,0xc0,0x00,0x18,0x28,0x06,0xc1,0x83,0xf0,0x10,0x3c,
4126
0x0c,0x33,0x60,0x39,0xac,0x86,0xb5,0xb0,0x1e,0xde,0x84,0xcd,0xf0,0x1e,0x7c,0x00,
4127
0xb9,0xe6,0x41,0x62,0xc7,0xe7,0x14,0x82,0x33,0xa0,0x32,0x54,0x85,0x3a,0x50,0x0f,
4128
0xea,0x43,0x43,0x68,0x09,0x59,0x70,0x39,0x8c,0x85,0x6f,0x21,0xcd,0xe7,0x73,0x86,
4129
0xc2,0xf7,0x62,0xac,0xdf,0xe7,0x3c,0x00,0x33,0x60,0x13,0xec,0x10,0xe6,0xe5,0x90,
4130
0x72,0x10,0x03,0x69,0xd0,0x48,0xa4,0x43,0x26,0x34,0x17,0x59,0x30,0x0c,0x86,0xc3,
4131
0x68,0x18,0x0b,0x0f,0xc2,0x0c,0x78,0x19,0xd6,0xc1,0x9b,0xf0,0x16,0xbc,0x63,0x5e,
4132
0x38,0x09,0xf7,0x39,0xad,0x21,0x0b,0x1e,0x84,0x19,0x30,0x1b,0xe6,0xc1,0x16,0xd8,
4133
0x0a,0xdf,0x99,0x17,0x02,0x03,0x3e,0xa7,0x0a,0xc4,0x41,0x37,0x18,0x08,0xa3,0x61,
4134
0x0c,0xdc,0x0c,0xb7,0xc2,0x1d,0x70,0x17,0x4c,0x83,0x7b,0x60,0x26,0x3c,0x0a,0xf3,
4135
0x61,0x21,0x2c,0x81,0x97,0x60,0x29,0xac,0x84,0x23,0xe6,0x05,0x95,0x08,0x9f,0x93,
4136
0x12,0x49,0x99,0xa0,0x3d,0x74,0x81,0x9e,0x30,0x16,0x26,0xc2,0x24,0x98,0x07,0x0b,
4137
0x60,0x85,0x79,0x61,0xa5,0x80,0xcf,0x09,0x40,0x01,0x51,0x10,0x92,0xa1,0x16,0xd4,
4138
0x86,0x7a,0xa2,0x21,0xb4,0x87,0x2e,0x30,0x1c,0xc6,0xc2,0x43,0xb0,0x03,0xbe,0x84,
4139
0xaf,0xe0,0x6b,0xf3,0x02,0x63,0x94,0xcf,0x29,0x09,0xe5,0x21,0x15,0xd2,0xa0,0x13,
4140
0x8c,0x85,0xc5,0xb0,0x1c,0x56,0x98,0x17,0x64,0x0a,0xba,0xf8,0x20,0x0c,0x02,0x10,
4141
0x01,0x85,0xa1,0x08,0x14,0x85,0xe2,0x50,0x12,0xce,0x81,0x52,0x90,0x0c,0xb5,0xa1,
4142
0x0e,0x34,0x14,0x5d,0x60,0x0c,0x8c,0x85,0x07,0x60,0x25,0xac,0x85,0xd7,0x60,0x37,
4143
0x7c,0x02,0x7b,0x4c,0x5a,0x85,0xd8,0x1f,0xd2,0xa0,0x3d,0x74,0x81,0xc1,0x30,0x16,
4144
0xa6,0xe6,0xbd,0xa8,0xe3,0x73,0x9a,0xc1,0x58,0x58,0x00,0x2b,0xe1,0x4b,0xf3,0x02,
4145
0xe6,0x19,0x3e,0x27,0x1a,0x2e,0x80,0x2a,0x10,0x07,0xa9,0x90,0x06,0x99,0xd0,0x1c,
4146
0x5a,0x42,0x2b,0xd1,0x5a,0x64,0x41,0x77,0xe8,0x0d,0xfd,0x60,0x80,0x18,0x08,0x13,
4147
0x61,0xec,0x99,0xf4,0x0b,0x98,0x03,0x4f,0xc3,0x3c,0x98,0x0f,0xab,0xe1,0x15,0x78,
4148
0x55,0xac,0x81,0xb5,0xb0,0x01,0xde,0x84,0xf7,0xe1,0x0b,0x38,0x04,0x3f,0x9a,0x17,
4149
0x41,0x8b,0xf8,0x9c,0xf3,0xa1,0x8a,0x88,0x83,0x20,0x34,0x85,0x2c,0x18,0x08,0xe3,
4150
0x60,0x3c,0x4c,0x84,0x79,0xf0,0x0a,0xec,0x80,0x7f,0x99,0x17,0x90,0x8a,0xba,0xf8,
4151
0x84,0x5f,0x84,0x41,0x2d,0xa8,0x0d,0x4d,0xa1,0x07,0x0c,0x80,0x81,0x62,0x10,0x0c,
4152
0x86,0x21,0x30,0x14,0x86,0x89,0xeb,0x61,0x1c,0x8c,0x17,0x13,0x60,0x2e,0xcc,0x83,
4153
0x05,0xb0,0x10,0x9e,0x87,0xc5,0xf0,0x02,0x2c,0xd1,0x3d,0xe9,0xd5,0x62,0x13,0xec,
4154
0x85,0x43,0x70,0xd4,0xe4,0xad,0x18,0xf9,0x81,0x30,0xa8,0xac,0xfb,0xd5,0xd5,0xa1,
4155
0x86,0x88,0x81,0x24,0x48,0x81,0x86,0xd0,0x44,0x04,0xa1,0x29,0x64,0x88,0x2c,0x18,
4156
0x0c,0x43,0xc4,0x70,0x31,0x16,0xc6,0xc1,0x78,0x31,0x01,0x16,0xc0,0x42,0x58,0x04,
4157
0xcf,0xc3,0x72,0x58,0x01,0x2b,0x61,0x15,0xbc,0x02,0xaf,0xc1,0xeb,0xf0,0x86,0x78,
4158
0x53,0x6c,0x82,0xf7,0xe1,0x03,0x91,0x2b,0xcc,0xcb,0xb6,0xc5,0xa0,0x38,0x54,0x87,
4159
0x1a,0x10,0x0b,0x35,0x21,0x1e,0x12,0x20,0x11,0x92,0x44,0xb2,0x48,0x81,0x5a,0xd0,
4160
0x40,0x34,0x84,0x34,0x68,0x24,0xc6,0xc2,0x8d,0x30,0x59,0xdc,0x0c,0xb7,0xc1,0x14,
4161
0x78,0x10,0x1e,0x86,0x59,0x30,0x0f,0x3e,0x82,0xed,0x62,0x07,0xec,0x84,0x5d,0xb0,
4162
0x0f,0x0e,0xc1,0x51,0xf3,0x42,0x70,0x71,0xfa,0x01,0xf8,0x21,0x0c,0x02,0x50,0x18,
4163
0x8a,0x40,0x51,0x28,0x0e,0x55,0xa1,0x1a,0xc4,0x41,0x02,0x24,0x42,0x32,0xa4,0x42,
4164
0x5d,0xa8,0x07,0xf5,0x85,0x79,0xae,0xa0,0x21,0xa4,0x89,0x46,0xd0,0x04,0x32,0xa0,
4165
0x99,0x9e,0x39,0x68,0x09,0x59,0xa2,0xa3,0xb8,0x1c,0xb2,0xa1,0x2b,0x74,0x83,0x1e,
4166
0xd0,0x17,0x06,0xc2,0x50,0x18,0x0b,0x37,0xc1,0x2d,0xe2,0x76,0x91,0x03,0x8b,0x60,
4167
0xb1,0x30,0xcf,0x29,0xbc,0xa8,0xe7,0x18,0x56,0xea,0x79,0x05,0xef,0x99,0x85,0x57,
4168
0xf5,0x0c,0xc3,0x7a,0x78,0x1d,0x36,0xc2,0x1b,0xe2,0x4d,0xb1,0x49,0xbc,0x25,0x36,
4169
0x8b,0x2d,0xe2,0x63,0xd8,0x69,0x5e,0xc0,0x2b,0x41,0xbb,0x41,0x32,0xd4,0x82,0xda,
4170
0xd0,0x10,0xd2,0xa0,0x11,0xa4,0x43,0x13,0x08,0x8a,0xa6,0x22,0x03,0x9a,0x43,0x16,
4171
0x74,0x82,0x2b,0xc4,0x95,0x90,0x0d,0x63,0xcd,0xb3,0x13,0x25,0xdc,0xe7,0x2a,0x16,
4172
0xc0,0x42,0x78,0x01,0x96,0x88,0x17,0xad,0x67,0x2d,0xcc,0x73,0x16,0x2b,0x60,0x25,
4173
0xac,0x12,0xab,0xe1,0x65,0x78,0x05,0x5e,0x85,0xb5,0x62,0x13,0xbc,0x6f,0xe2,0x2f,
4174
0xe9,0x73,0x9e,0xd5,0x73,0x19,0xf3,0x61,0x01,0x2c,0x82,0x17,0xf4,0x9c,0xc6,0x52,
4175
0x58,0x06,0xcb,0xc5,0x0a,0x58,0x09,0x5b,0x61,0x1b,0xe4,0xc2,0x87,0xe6,0xc5,0xc3,
4176
0xb3,0xe9,0xcb,0x10,0x07,0x09,0x90,0x08,0x75,0xa0,0x2e,0xd4,0x83,0xfa,0xa2,0x81,
4177
0x68,0x08,0x69,0xd0,0x44,0x64,0x41,0x27,0x18,0x0b,0x4f,0xc1,0x1c,0xf1,0xb4,0x78,
4178
0x46,0x3c,0x0b,0x73,0x61,0x1e,0x2c,0x82,0xe7,0xc5,0x62,0xf1,0x82,0x58,0x09,0xaf,
4179
0xc1,0x26,0xd8,0x65,0x5e,0x6c,0x3f,0xc7,0xe7,0x9c,0x07,0x65,0x44,0x59,0x51,0x4e,
4180
0x94,0x87,0x0a,0x50,0x11,0x2a,0x41,0x65,0x51,0x05,0xaa,0x43,0x1c,0xa4,0x42,0x1a,
4181
0x34,0x35,0x2f,0x58,0x9e,0x8b,0x3f,0xd4,0x80,0x58,0xa8,0x09,0xb5,0xa0,0xb6,0x48,
4182
0x85,0x3a,0x30,0x03,0xb6,0xc3,0x0e,0xf8,0x0c,0x7e,0x84,0x88,0x52,0x3e,0x27,0x4a,
4183
0x14,0x86,0xe2,0x50,0x12,0xce,0x86,0x73,0xa1,0x66,0x29,0xf7,0xf9,0x98,0x64,0xa8,
4184
0xa5,0xe7,0x64,0xea,0x42,0x3d,0xa8,0x2f,0x1a,0x88,0x86,0x22,0x4d,0x34,0x12,0xe9,
4185
0xa2,0xb1,0xc8,0x82,0x4e,0x30,0x03,0x9e,0x84,0xa7,0x60,0x13,0xbc,0x05,0x5b,0xe0,
4186
0x6d,0x78,0x0f,0x3e,0x80,0x6d,0x90,0x0b,0xdb,0x61,0x87,0xf8,0x58,0xec,0x12,0xbb,
4187
0x45,0xde,0xc7,0x01,0xc0,0x07,0x05,0xa1,0x10,0x24,0x40,0x22,0xd4,0x86,0x54,0x51,
4188
0x47,0xd4,0x85,0x06,0x90,0x21,0xb2,0x44,0x1b,0xe8,0x00,0x1d,0xe1,0x12,0xe8,0x04,
4189
0x9d,0xe1,0x32,0xb8,0x09,0x6e,0x86,0xbb,0xe1,0x1e,0x71,0x2f,0x4c,0x87,0x07,0xc5,
4190
0x3c,0xf8,0xc6,0xe4,0xa1,0xb4,0x4b,0x17,0x91,0x2d,0xba,0xc2,0x55,0xd0,0x5d,0xf4,
4191
0x10,0x3d,0xc5,0x4a,0xd8,0x01,0x87,0xe0,0xa8,0x79,0x51,0xf6,0x7c,0xd6,0x43,0x50,
4192
0x10,0x62,0xa1,0xa6,0x88,0x83,0x14,0xa8,0x0d,0xf5,0xa1,0x81,0x68,0x28,0xd2,0x44,
4193
0x16,0x74,0x82,0xc1,0x30,0x05,0xee,0x80,0x27,0x61,0xb6,0x78,0x0a,0xe6,0xc1,0x7c,
4194
0xb1,0x00,0x16,0xc2,0x73,0x62,0x11,0x3c,0x6f,0x3e,0x94,0x50,0x86,0xfe,0x02,0x05,
4195
0x20,0x0a,0x0a,0x41,0x1c,0xc4,0x43,0x0a,0xd4,0x11,0xf5,0xa0,0x3e,0x34,0x84,0x20,
4196
0x34,0x15,0x19,0x22,0x0b,0x3a,0x41,0x17,0xe8,0x0e,0x3d,0xa1,0x17,0x5c,0x0d,0x37,
4197
0xc1,0xcd,0x70,0x3b,0xe4,0xc0,0x54,0xb8,0x13,0xee,0x82,0x69,0xe2,0x6e,0x71,0x8f,
4198
0xb8,0x57,0xcc,0x80,0xd9,0x30,0x0f,0xb6,0xc2,0xfb,0xe2,0x03,0xd8,0x06,0x3b,0xe0,
4199
0x33,0x38,0x24,0x0e,0x8b,0x1d,0x65,0x59,0x5f,0xc1,0x11,0xf8,0x0a,0xbe,0x86,0x7f,
4200
0x99,0x0f,0x41,0x94,0xa3,0x2f,0x81,0x5f,0x84,0x89,0x70,0x28,0x0a,0x67,0x41,0x22,
4201
0x24,0x41,0x32,0xa4,0x40,0x1d,0x68,0x00,0x0d,0x21,0x4d,0x34,0x12,0xe9,0x22,0x0b,
4202
0x3a,0xc1,0xa5,0x62,0x9e,0x30,0x1f,0x9d,0x98,0x6e,0x5e,0x50,0xbe,0x80,0xf5,0x0d,
4203
0x0c,0x83,0xeb,0x61,0x2c,0x34,0xae,0xc4,0x7e,0x70,0x63,0x65,0xea,0xa5,0x26,0xf9,
4204
0xcf,0x7b,0x41,0x98,0x7e,0x90,0x44,0x1a,0xa2,0x11,0x34,0x85,0x0c,0x68,0x0f,0x5d,
4205
0xe0,0x5b,0xf3,0x01,0x86,0x26,0xf8,0x9b,0x17,0x72,0xb3,0x99,0x6f,0xb2,0xdd,0xe7,
4206
0xdc,0xcc,0x33,0x6d,0xd5,0xa0,0x06,0xc4,0x40,0x4d,0x88,0x83,0x54,0xf3,0xe2,0x6a,
4207
0x2f,0xfa,0xd4,0xd5,0xc4,0x09,0x57,0x40,0x17,0xe8,0x0d,0x03,0x61,0x39,0xac,0x84,
4208
0xd7,0x60,0x13,0x1c,0x80,0x43,0xf0,0x95,0xf9,0x90,0x40,0x1f,0xe2,0x81,0x38,0x48,
4209
0x81,0x34,0x68,0x0c,0x59,0xd0,0x09,0xba,0xc1,0x08,0xb8,0x16,0xa6,0x98,0xed,0xfd,
4210
0xa8,0x0f,0x68,0xac,0xe7,0xe4,0xfa,0x40,0x5f,0x18,0x08,0xa3,0x20,0xad,0x3f,0xe5,
4211
0x87,0x19,0xf0,0x02,0xbc,0x04,0x5b,0xcc,0x07,0x09,0x06,0x70,0x9c,0x82,0xd6,0x22,
4212
0x4b,0xb4,0x81,0x49,0x30,0x05,0xee,0x80,0x3b,0xe1,0x61,0xd8,0x01,0x1f,0xc3,0x2e,
4213
0xb1,0x5b,0x1c,0x82,0xc3,0xf0,0x25,0x1c,0x81,0xaf,0xe0,0x5f,0xe6,0xc5,0xd8,0x81,
4214
0xf4,0x99,0x5b,0x99,0x1f,0xa1,0xfc,0x6d,0xd4,0x3f,0x7c,0x09,0xce,0xed,0xf4,0xc7,
4215
0xa9,0xe4,0x07,0x36,0xc3,0xa1,0xb9,0xec,0x07,0x5f,0xc3,0x77,0xf0,0x3d,0xfc,0x60,
4216
0x3e,0x84,0x30,0x8f,0x75,0xc9,0x7c,0xe6,0x1e,0x91,0x05,0x17,0x43,0x7b,0x71,0x15,
4217
0xf4,0x82,0x81,0xf0,0xdd,0x02,0xf7,0x01,0xbe,0xab,0x61,0x20,0x8c,0x81,0xb1,0x30,
4218
0x19,0x72,0x60,0x3a,0x3c,0x08,0x0f,0xc1,0xa1,0xd7,0x99,0x0f,0xc0,0x7c,0x04,0x24,
4219
0x06,0xe2,0xa0,0x29,0x54,0x79,0x8b,0xf4,0xa0,0x3b,0xf4,0x80,0x9e,0xd0,0x1b,0xfa,
4220
0xc1,0x60,0xb8,0x06,0xc6,0xc3,0x44,0xb8,0x05,0x9e,0x82,0x67,0x20,0x7d,0x33,0xc7,
4221
0x3b,0xc8,0x82,0x8b,0xa1,0x33,0x5c,0x06,0x57,0x8a,0xb1,0x30,0xce,0xbc,0x60,0xfd,
4222
0xb6,0xcf,0x69,0x07,0x1d,0xe0,0x01,0x78,0x08,0x1e,0x86,0x47,0xc4,0xe3,0xf0,0x04,
4223
0xcc,0x86,0xa7,0xe1,0x59,0x58,0x02,0x2f,0x89,0x65,0xf0,0x32,0xbc,0x0a,0x81,0x77,
4224
0x7c,0x4e,0x24,0x14,0x84,0x33,0xa0,0x04,0x9c,0x0d,0xe7,0x43,0x59,0x48,0x85,0xba,
4225
0xd0,0x00,0xd2,0xa0,0x09,0x34,0x15,0xcd,0x21,0x0b,0x2e,0x86,0x27,0xde,0x65,0x2d,
4226
0x09,0x2b,0x61,0x35,0x7c,0x00,0xb9,0xf0,0x2d,0x1c,0x83,0x12,0xef,0x11,0x2f,0x24,
4227
0x41,0x0a,0xb4,0x82,0x2c,0xe8,0x0f,0x03,0x61,0x32,0xdc,0x0c,0xb3,0xe0,0x29,0x58,
4228
0x0d,0xaf,0xc0,0x06,0x78,0x03,0x7e,0x34,0x2f,0xc6,0x7e,0xc0,0xbe,0x50,0x17,0xfa,
4229
0xc2,0x30,0x71,0x83,0xb8,0x1f,0x1e,0x86,0x99,0x30,0xd7,0xbc,0x60,0xba,0x9d,0x79,
4230
0x11,0x0a,0x8a,0x42,0x70,0x3d,0x8c,0x85,0x71,0x90,0x03,0x77,0xc3,0x46,0xf8,0xd1,
4231
0xbc,0x40,0xbb,0x83,0xf9,0x14,0x0a,0xc0,0xb9,0x50,0x1a,0x2a,0x40,0x34,0x5c,0x00,
4232
0x95,0xa1,0x1a,0xc4,0x41,0x3f,0x98,0x22,0xcc,0xcb,0x93,0x35,0x20,0x0e,0x52,0xa0,
4233
0x16,0xd4,0x87,0x34,0xc8,0x84,0x56,0x22,0x67,0x27,0xed,0x0c,0xcf,0x8a,0x95,0xb0,
4234
0x1f,0x3e,0x87,0x83,0x70,0x08,0x8e,0xc2,0xa6,0xdd,0xac,0xbb,0x61,0xbf,0xf8,0x1c,
4235
0x0e,0xc2,0x21,0x38,0x0a,0x9b,0x3e,0x61,0x9c,0xc3,0x17,0x70,0x10,0x0e,0x89,0xc3,
4236
0xf0,0x2d,0xac,0xdc,0xc3,0x7a,0x1e,0x76,0xc0,0x4e,0xd8,0x25,0x76,0xc3,0x27,0xb0,
4237
0x47,0x7c,0x0a,0x07,0xe0,0x0b,0x38,0x08,0x87,0xe0,0x2b,0xf8,0x5a,0xfc,0x20,0x7e,
4238
0x14,0x3b,0x3e,0x65,0x3f,0xd8,0x0b,0xfb,0xe1,0x00,0x7c,0x01,0x87,0xe0,0x07,0xf3,
4239
0x41,0x87,0xbd,0xb4,0x19,0x6c,0x82,0x77,0xcd,0x87,0x6d,0x3e,0x63,0x2e,0x81,0x26,
4240
0xd0,0x1c,0x5a,0x88,0x2c,0xe8,0x64,0x3e,0x94,0xf0,0x05,0xf3,0xf7,0xff,0xb5,0x77,
4241
0x1e,0xf0,0x55,0x97,0x67,0x1b,0x3e,0xe7,0xe4,0xe4,0x70,0x92,0x20,0xe0,0xc0,0x2d,
4242
0x6e,0xd9,0x10,0x99,0x0a,0x08,0x41,0x51,0x1c,0x1f,0x05,0xdc,0x48,0x15,0xc4,0x8d,
4243
0x03,0x04,0xdc,0x16,0x11,0x44,0xc5,0x89,0x6d,0xb5,0x9f,0xa3,0x8a,0xf5,0x73,0xa0,
4244
0x82,0x51,0xd0,0x82,0x20,0x04,0x71,0xcb,0x12,0x5c,0x75,0x31,0xac,0x7e,0x28,0x22,
4245
0xcb,0x09,0x6a,0xbe,0xfb,0x3d,0xff,0xeb,0x21,0x0f,0x7f,0x73,0x04,0xac,0xfd,0xd5,
4246
0xfe,0xbe,0x26,0xbd,0x01,0x43,0x20,0x83,0x24,0x7d,0xf2,0x5e,0xcf,0x75,0xbf,0x4a,
4247
0xa1,0xb2,0xab,0xb2,0xbb,0xb2,0x87,0xb2,0x17,0xa9,0x4f,0x1a,0x2a,0x2d,0x94,0x56,
4248
0x4a,0x5b,0x65,0x7f,0xd2,0x9e,0x1c,0x48,0xba,0x92,0xc3,0xc8,0x11,0xa4,0x9b,0xd2,
4249
0x5d,0xe9,0xa9,0x1c,0xa9,0x1c,0x4d,0x8e,0x23,0xbd,0x48,0x6f,0x72,0x22,0xe9,0x43,
4250
0x4e,0x56,0xfa,0x29,0xa7,0x92,0x33,0x94,0xfe,0xca,0x39,0xca,0x20,0x65,0x88,0x72,
4251
0x91,0x72,0x89,0x72,0xb9,0x32,0x94,0x0c,0x53,0x46,0x29,0xd7,0x2b,0x77,0x2a,0xf7,
4252
0x2a,0xf7,0x29,0xf7,0x2b,0x63,0x95,0x47,0x94,0x29,0xca,0xca,0x75,0xfa,0x77,0x0d,
4253
0xe2,0x76,0x22,0x95,0x58,0xf8,0x40,0x2a,0x91,0x78,0x30,0x95,0xa8,0x37,0x29,0x95,
4254
0xd8,0x4d,0x19,0x37,0x27,0x95,0x28,0x57,0x16,0x2d,0x4b,0x25,0x56,0x2a,0x27,0x86,
4255
0x85,0xe0,0x6f,0x52,0x89,0x5d,0xd6,0x46,0x8b,0xc1,0x87,0x6f,0x5d,0xa0,0xef,0x8d,
4256
0x0a,0x12,0x97,0xb4,0x0a,0x32,0x62,0x41,0xa2,0xd3,0x77,0x05,0xb9,0x05,0x9b,0x15,
4257
0x8a,0xed,0x37,0xe7,0xdb,0x6b,0xfe,0x57,0xed,0x33,0xff,0xdc,0x3d,0xe6,0x4d,0xdd,
4258
0x5f,0xde,0xd4,0xbd,0xe5,0xf8,0x3e,0x72,0xbe,0x3d,0x64,0xdb,0x3b,0x8e,0xef,0x1b,
4259
0xdb,0x7e,0xb1,0xed,0x13,0xe7,0xdb,0x23,0xb6,0xfd,0x61,0xdb,0x1b,0xb6,0x7d,0x61,
4260
0xdb,0x13,0x8e,0xef,0x07,0xdb,0x5e,0xb0,0xed,0x03,0xdb,0x1e,0xb0,0xed,0xff,0xda,
4261
0xde,0x6f,0xbe,0x7d,0xdf,0xf8,0x9e,0xaf,0xed,0xf3,0xda,0xde,0xae,0xed,0xe3,0xda,
4262
0x1e,0x6e,0x7c,0xef,0x76,0x73,0xf7,0x6c,0x6d,0xbf,0xd6,0xf6,0x66,0xe3,0xfb,0xb2,
4263
0xf1,0xfd,0xd8,0x9f,0xbb,0x07,0x1b,0xdf,0x6b,0xb5,0x3d,0xd6,0xcd,0xdd,0x57,0xb5,
4264
0x3d,0xd5,0xf8,0xde,0xa9,0xed,0x99,0x6e,0xee,0x3e,0xa9,0xed,0x91,0xc6,0xf7,0x3f,
4265
0x6d,0xdf,0xf3,0x97,0xde,0xf3,0xb4,0xbd,0xcd,0x8d,0xed,0x63,0xda,0x1e,0x66,0xbe,
4266
0xfd,0x4a,0xdb,0xa7,0xdc,0xd4,0xfd,0x49,0xdb,0x9b,0x8c,0xef,0x3d,0xda,0x9e,0x63,
4267
0xbe,0x7d,0x46,0xdb,0x63,0x8c,0xef,0x27,0xda,0x5e,0xa2,0xed,0x21,0x6e,0xea,0xde,
4268
0xa1,0xed,0x0f,0xda,0xde,0x60,0x7c,0x5f,0x70,0x73,0xf7,0x03,0x6d,0x2f,0x30,0xdf,
4269
0x3e,0x60,0x7c,0xff,0x2f,0xbe,0xcf,0x67,0xfb,0x7a,0xb6,0x97,0x67,0x7b,0x75,0xb6,
4270
0x4f,0x67,0xfb,0x73,0xb6,0x37,0x67,0xfb,0x72,0xb6,0x27,0x67,0xfb,0x71,0xb6,0xf7,
4271
0xf6,0xef,0xb6,0xd7,0xf6,0x4b,0xef,0xb1,0xd9,0xde,0x9a,0xed,0xa9,0xc5,0xf7,0xd3,
4272
0x6c,0x2f,0x2d,0xbe,0x5f,0xb6,0xb9,0x7b,0x63,0xf9,0xf6,0xc5,0x36,0xb6,0xe7,0x65,
4273
0x7b,0x5d,0xb6,0xbf,0x65,0xfb,0x54,0xb6,0x2f,0x65,0xfb,0x4e,0xb6,0xcf,0x64,0xfb,
4274
0x49,0xb6,0x97,0x64,0x7b,0x45,0xb6,0x2f,0xb4,0xa9,0x7b,0x42,0xb6,0x07,0x64,0xfb,
4275
0x3f,0xb6,0xf7,0xf3,0x73,0xf7,0x7c,0x7e,0xad,0xfb,0x3d,0xf9,0xf6,0x78,0xfe,0xdd,
4276
0xf7,0x75,0x36,0x77,0x4f,0xe7,0x97,0xda,0xcf,0xd9,0xd8,0x5e,0xce,0xa6,0xee,0xe1,
4277
0x6c,0x6c,0xff,0xe6,0x5f,0xb5,0x77,0x93,0x6f,0xdf,0x26,0xdf,0x7e,0x4d,0x7c,0xaf,
4278
0xe6,0x5f,0xb5,0x4f,0x63,0x7b,0x34,0xb6,0x3f,0x63,0x7b,0x33,0xb6,0x17,0x63,0xfb,
4279
0x30,0xf9,0xf6,0x5d,0x6c,0xbf,0xc5,0xf6,0x5a,0x6c,0x8f,0xc5,0xf6,0x56,0x6c,0x0f,
4280
0xc5,0xf6,0x4f,0xe2,0x7b,0x27,0xf1,0x7d,0x13,0xdb,0x23,0xb1,0xfd,0x91,0x8d,0xed,
4281
0x89,0xd8,0x3e,0x88,0xed,0x81,0xd8,0xfe,0x87,0xed,0x7d,0xd8,0xbe,0xc7,0xc6,0xf6,
4282
0x3c,0xe2,0xfb,0x1c,0xff,0xec,0xfd,0x8d,0x7f,0x74,0xff,0xe2,0x9f,0xb5,0x77,0x11,
4283
0xdf,0xab,0xb0,0x7d,0x0a,0xdb,0xa3,0xf8,0xb5,0xec,0x4f,0xc4,0xf7,0x26,0x36,0x77,
4284
0x5f,0x62,0x73,0xf7,0x24,0xfe,0xb3,0x1f,0x51,0xfd,0x7e,0x44,0xbe,0x3d,0x88,0x8d,
4285
0xed,0x3d,0xfc,0xa3,0xfb,0x0e,0x1b,0xdb,0x6b,0xc8,0xb7,0xcf,0xb0,0xb1,0x3d,0x06,
4286
0xdb,0x5f,0xc8,0xb7,0xb7,0x60,0xfb,0x0a,0xf1,0x3d,0x05,0xdb,0x47,0xb0,0xbd,0x03,
4287
0xdb,0x37,0xb0,0xfd,0x02,0xdb,0x1b,0xb0,0x3d,0x01,0xdb,0x03,0x88,0xf3,0x7f,0xe3,
4288
0xfe,0xc6,0xf9,0x8d,0xe7,0x6f,0x8c,0xd7,0x1b,0x77,0xdf,0x5c,0xde,0xbe,0xb9,0xfc,
4289
0xdc,0xb8,0xb9,0xf1,0x70,0xe3,0xe0,0x9b,0xca,0xbb,0x8d,0x53,0x1b,0x9f,0x36,0x2e,
4290
0x6d,0x9c,0x39,0xce,0x95,0xe3,0x5c,0xd8,0x78,0xb0,0xf1,0x5d,0xe3,0xba,0xc6,0x69,
4291
0x8d,0xcf,0x1a,0x67,0x35,0xae,0x1a,0xe7,0xa2,0xc6,0x3d,0x37,0x95,0x77,0x1a,0xc7,
4292
0x34,0x7e,0x19,0xe7,0x94,0x71,0xfe,0x68,0xdc,0xd1,0x78,0xa3,0xf1,0x45,0xe3,0x89,
4293
0xc6,0x0d,0xf3,0xf1,0x41,0xe3,0x7d,0x71,0xce,0x67,0xfc,0xce,0xb8,0x5d,0x3e,0xfe,
4294
0x66,0x7c,0x2d,0x1f,0x4f,0x33,0x3e,0x96,0x8f,0x8b,0xc5,0x39,0x98,0xf1,0xae,0x38,
4295
0xe7,0xfa,0x47,0x39,0x95,0xf1,0xa9,0x7c,0x5c,0x2a,0xce,0x9d,0x8c,0x37,0x19,0x67,
4296
0x32,0xbe,0x64,0x5c,0x69,0x53,0x79,0xd2,0xc6,0x38,0x92,0xf1,0xa3,0x7c,0xbc,0xe8,
4297
0xd7,0xce,0x87,0xfe,0xbf,0xf1,0x99,0xcd,0xe5,0x2c,0xc6,0x4f,0x8c,0x9b,0x18,0x2f,
4298
0x89,0x73,0x12,0xe3,0x23,0x71,0x1e,0x62,0xfc,0xc3,0xb8,0x47,0x9c,0x77,0x18,0xe7,
4299
0x30,0xbe,0x61,0x5c,0xe3,0xe7,0xf2,0x0c,0xe3,0x18,0xc6,0x2f,0xfe,0xc3,0x2d,0x22,
4300
0x6e,0xf1,0x8b,0xf1,0x8a,0xd0,0x0d,0xac,0x14,0x2b,0xa6,0x9f,0x6f,0xa1,0xd4,0x8a,
4301
0x8e,0x4a,0x42,0x05,0x66,0x42,0xdf,0xfe,0x27,0xc2,0xb7,0xd8,0x7b,0x2a,0xfb,0x28,
4302
0x8d,0xa3,0x6f,0xb7,0xc3,0xb7,0xd2,0x89,0x66,0x4a,0xe8,0x74,0x69,0xa7,0xb4,0xa7,
4303
0xd7,0xa5,0x37,0xdc,0xe3,0x32,0xe5,0x0a,0x65,0xa4,0x72,0xb5,0xa2,0x6f,0x2d,0x13,
4304
0xf7,0x2a,0x7f,0x51,0x1e,0x80,0x87,0x84,0x6f,0x09,0xc6,0x29,0xe3,0x95,0x72,0xe5,
4305
0x09,0x65,0x22,0x8c,0xe4,0x29,0x65,0x32,0x9c,0x64,0x0a,0xac,0xe4,0x2d,0x58,0xc9,
4306
0xd7,0xb0,0x92,0xc9,0x7a,0xd3,0xa6,0x28,0xcf,0x2a,0xf3,0x94,0xf9,0xb0,0x8f,0x8f,
4307
0xe0,0x1d,0x2b,0xe8,0x70,0x19,0xe8,0x78,0x47,0xe0,0x1c,0x43,0xe1,0x1b,0x57,0xb9,
4308
0x9e,0x96,0x6b,0x1d,0xdb,0x08,0x5c,0xe3,0x2b,0xb8,0xc6,0x08,0xb8,0xc6,0xbe,0xf0,
4309
0x8c,0xeb,0xe0,0x18,0x37,0x2a,0x37,0xd3,0xc1,0x32,0x8d,0xfe,0x95,0x0a,0x3a,0x58,
4310
0x66,0xd2,0xc1,0xf2,0x02,0x1d,0x2c,0xf3,0x60,0x1d,0x89,0x8c,0xfe,0xa7,0x64,0x95,
4311
0x22,0xa5,0x44,0xa9,0xa9,0x6c,0xa1,0xd4,0xca,0x44,0xbd,0x2c,0x3b,0xd1,0xbf,0x12,
4312
0xba,0x57,0xfa,0x2b,0x67,0x2b,0xe7,0xba,0xde,0x95,0xd0,0xb5,0xf2,0xbe,0xf2,0x01,
4313
0x7d,0x2b,0x1f,0xd1,0xb3,0xf2,0x09,0x3d,0x2b,0x9f,0xd3,0xaf,0x12,0x98,0x48,0x6d,
4314
0xd7,0xa3,0x52,0x0a,0x07,0x79,0xc0,0x75,0xa6,0x2c,0x83,0x81,0x7c,0xe5,0xfa,0x51,
4315
0x7e,0xa8,0x11,0xf5,0xa2,0x58,0x1f,0x8a,0xf5,0xa0,0x58,0xff,0x49,0x29,0x1c,0x24,
4316
0x74,0x9f,0x9c,0x04,0x0b,0x09,0x1c,0x64,0x34,0x7d,0x27,0x63,0xe8,0x37,0x59,0x42,
4317
0xbf,0x49,0x81,0xeb,0x32,0xb1,0x0e,0x93,0xce,0x74,0x96,0x58,0x57,0x49,0x4f,0x98,
4318
0x48,0xe8,0x25,0x39,0xd5,0x75,0x8f,0x8c,0x84,0x85,0xfc,0x01,0x06,0x62,0xec,0xc3,
4319
0xba,0x45,0x66,0xd0,0x25,0xf2,0xaa,0xeb,0x0f,0xb1,0xde,0x90,0x85,0xf4,0x85,0x84,
4320
0xae,0x90,0xd5,0xca,0x17,0xca,0x3a,0xd7,0x13,0x92,0x74,0xdd,0x20,0xb5,0x61,0x21,
4321
0x8d,0x60,0x20,0xad,0x61,0x1f,0xd6,0xfd,0xd1,0x99,0xce,0x8f,0x23,0x5c,0xcf,0x87,
4322
0xf5,0x7b,0x0c,0x84,0x87,0x84,0x3e,0x8f,0x0b,0xe9,0xf4,0xb0,0x2e,0x8f,0x9b,0x61,
4323
0x22,0x0f,0xc3,0x42,0x9e,0x74,0x7d,0x1d,0x33,0xe8,0xe7,0xb0,0x5e,0x8e,0xd9,0x8e,
4324
0x89,0x2c,0xa1,0x83,0x63,0x95,0xeb,0xdf,0xb0,0xde,0x8d,0x42,0xf8,0xc8,0xd6,0x70,
4325
0x91,0x16,0xf0,0x10,0xeb,0xd5,0xe8,0xe4,0x3a,0x34,0xba,0xd2,0x9d,0x61,0x9d,0x19,
4326
0xd6,0x95,0xd1,0x87,0x8e,0x8c,0xd3,0x5d,0x1f,0xc6,0x48,0xf8,0xc8,0xef,0xe1,0x22,
4327
0xc6,0x43,0xee,0x83,0x83,0x8c,0xa7,0xe7,0xc2,0xfa,0x2d,0x5e,0xa0,0xd7,0x62,0xb6,
4328
0xeb,0xb2,0x08,0x3d,0x16,0x6b,0x94,0x6f,0x95,0xb5,0x25,0x55,0x5d,0x16,0xd6,0x61,
4329
0x51,0x0b,0x56,0xd2,0xc8,0xf5,0x55,0x74,0xa4,0xa7,0xe2,0x10,0xfa,0x29,0x8e,0x81,
4330
0x9b,0xfc,0x16,0x5e,0xd2,0x8f,0x1e,0x8a,0x8b,0x94,0x8b,0x95,0x2b,0x5c,0x07,0xc5,
4331
0x4d,0x30,0x93,0x87,0x61,0x25,0xd6,0x31,0xf1,0x02,0xdd,0x11,0xb3,0xe8,0x8c,0x78,
4332
0x0f,0x66,0xb2,0x84,0x8e,0x88,0x55,0x7c,0xa1,0x4b,0xc1,0x4c,0xb6,0xa2,0xfb,0xe1,
4333
0x00,0xba,0x1e,0x0e,0xa1,0xe3,0xa1,0x9b,0xe3,0x26,0xfd,0xe8,0x6f,0xb0,0xbe,0x86,
4334
0x91,0xf0,0x92,0x09,0x8e,0x91,0x58,0x27,0xc3,0x7c,0xd7,0xc3,0xf0,0x31,0xfd,0x0b,
4335
0x49,0xd7,0xb9,0x10,0xfa,0x16,0x3a,0xc1,0x4f,0x42,0xc7,0x42,0x77,0xd8,0x89,0x31,
4336
0x93,0x1b,0x1c,0x27,0xb1,0xfe,0x84,0x89,0x8e,0x91,0x58,0x57,0xc2,0x3c,0x18,0x89,
4337
0x75,0x23,0xec,0x48,0x1f,0x42,0x1b,0xfa,0x10,0xf6,0xa3,0x0f,0xa1,0x1d,0x9d,0x08,
4338
0x87,0xd1,0x81,0x60,0xdd,0x07,0x23,0xe9,0x3e,0xb8,0x96,0xce,0x83,0xd0,0x77,0x30,
4339
0x8d,0xae,0x83,0x17,0x95,0x39,0xb0,0x95,0xa6,0xae,0xdf,0xc0,0x7a,0x0d,0xda,0xd3,
4340
0x67,0xd0,0x89,0xbe,0x82,0x13,0xe8,0x29,0x38,0x99,0xfe,0x81,0x0b,0x5c,0xe7,0xc0,
4341
0x48,0xba,0x06,0xac,0x63,0x20,0x74,0x08,0xdc,0xed,0x18,0x4b,0xe0,0x2b,0x87,0xc3,
4342
0x4f,0x8c,0x9b,0xf4,0x85,0x97,0x8c,0x86,0x93,0x4c,0x72,0x6c,0xe4,0x25,0x98,0xc8,
4343
0x56,0xb0,0x90,0xe0,0xf7,0xf7,0x85,0x87,0x8c,0x86,0x87,0x04,0x16,0x92,0xd8,0x26,
4344
0x62,0x21,0xc3,0x60,0x20,0x77,0xc2,0x40,0x12,0x38,0xfb,0xe6,0xea,0xb7,0x70,0x7e,
4345
0xfe,0x91,0x70,0x8f,0xf3,0xf0,0xf1,0x87,0xe1,0xe1,0x9b,0x7f,0x3f,0xcd,0x39,0xf7,
4346
0xc1,0xb7,0x7f,0x5d,0x79,0xd7,0x79,0xf6,0xc1,0xb1,0x5f,0xa9,0x24,0xb6,0x8f,0x3c,
4347
0xfb,0x5a,0xce,0xb1,0xdf,0x0d,0x26,0x32,0x12,0x16,0x32,0xd6,0x71,0x90,0x04,0xbe,
4348
0xfc,0x9e,0x78,0xf2,0x0d,0xf1,0xe3,0xcd,0x8b,0x0f,0x4e,0x7c,0x99,0xd2,0x05,0x2f,
4349
0x7e,0x20,0x7c,0xa4,0x1c,0xff,0xfd,0x03,0xf8,0xc8,0x76,0xf8,0xee,0xc1,0x73,0xaf,
4350
0xe7,0xbc,0xf6,0xe3,0x9d,0xcb,0x6e,0x0e,0xfb,0x69,0xb8,0xeb,0x83,0x9d,0xaf,0x1e,
4351
0x5c,0xf5,0x31,0x38,0xea,0x09,0x7c,0xf4,0x56,0x31,0xff,0xfc,0x37,0xb8,0xe4,0x43,
4352
0x70,0xc9,0x87,0xe3,0x8c,0x3f,0x80,0x2b,0x6e,0x8e,0xf8,0x78,0xe7,0x81,0x2f,0xc5,
4353
0xff,0x5e,0xee,0x9c,0xef,0xe0,0x7b,0x7f,0xb7,0x53,0xe4,0x77,0xb7,0xc2,0xeb,0x6e,
4354
0x0f,0x9f,0x19,0x0d,0x7f,0x09,0x8e,0xf6,0x02,0x1c,0x6d,0x73,0xb3,0x3f,0x71,0x3e,
4355
0xb6,0x79,0xd8,0xdf,0x38,0x16,0x53,0x01,0x63,0xd9,0x1e,0xb6,0x72,0x28,0x4c,0xa5,
4356
0x97,0xe3,0x28,0x7d,0xe0,0x27,0x81,0x9d,0x3c,0x03,0x37,0x99,0x0e,0x3b,0x09,0xdc,
4357
0x64,0x36,0xdc,0x24,0x30,0x93,0xf7,0x61,0x26,0xcb,0x61,0x26,0x81,0x97,0x7c,0xcf,
4358
0x70,0x54,0xa2,0xd4,0x52,0x6a,0x2b,0x75,0x94,0x06,0x4a,0x43,0xa5,0x91,0xd2,0x58,
4359
0x69,0xa2,0x34,0x55,0x9a,0x29,0xcd,0x95,0x52,0xa5,0xb5,0xd2,0x45,0x39,0x58,0xe9,
4360
0xa3,0xf4,0x55,0x4e,0x57,0xce,0x50,0xce,0x54,0xce,0x52,0xfa,0x2b,0x03,0xe1,0x31,
4361
0x43,0x94,0x4b,0x95,0xcb,0xe1,0x32,0xc3,0x94,0xeb,0x94,0x1b,0x94,0xd1,0xca,0x18,
4362
0x5c,0xeb,0x04,0x9c,0xa6,0x00,0x4e,0x93,0x85,0xd5,0x6c,0x03,0xa7,0xd9,0x16,0x46,
4363
0x53,0x0f,0x3e,0xb3,0x37,0x7c,0xa6,0x3e,0x7c,0xa6,0x21,0x8c,0xc6,0xd8,0x4c,0x3b,
4364
0x58,0x4c,0x19,0x2c,0xe6,0x70,0x38,0x4c,0x0f,0x58,0xcc,0x28,0x65,0xb4,0xb2,0xd5,
4365
0x1e,0xfa,0xff,0x23,0x65,0x1b,0xa5,0x8d,0x06,0xc5,0xcb,0x94,0x5b,0x95,0xdb,0x94,
4366
0xb2,0xbd,0xf4,0xbc,0xca,0xb5,0xca,0x5d,0xca,0xa7,0xca,0xa3,0x1a,0x24,0xc7,0x85,
4367
0x61,0xb2,0x81,0xd2,0x50,0xff,0xbf,0xc9,0x50,0xf9,0x11,0xcc,0x66,0x05,0xcc,0xe6,
4368
0x5b,0x06,0xcd,0xfa,0x8e,0xd3,0x0c,0x70,0x0e,0xf5,0x18,0xd8,0x4c,0x39,0x4c,0xa6,
4369
0x02,0x16,0x33,0x0f,0x06,0xb3,0x88,0x21,0xb5,0xaf,0x32,0x4c,0xb9,0x33,0x0c,0xac,
4370
0xcd,0xf5,0xf9,0xd9,0x3c,0x1a,0x5c,0x93,0xf0,0x99,0x2c,0x4c,0xa6,0x11,0x8e,0x74,
4371
0x29,0x6c,0xa6,0x0d,0x6c,0xe6,0x00,0x58,0xcc,0xed,0xb0,0x98,0xc0,0x61,0xc6,0xc0,
4372
0x5f,0xcc,0x7b,0x2e,0x84,0xb7,0x8c,0x56,0x2a,0x94,0x15,0xf0,0x96,0x5d,0x5a,0xe8,
4373
0xc3,0x44,0xe9,0xa1,0xf4,0x55,0x2e,0x57,0xae,0x50,0x1e,0x57,0x2a,0x94,0x59,0xca,
4374
0x3c,0xe5,0xa2,0x96,0x7a,0xbf,0x29,0x1f,0x28,0x8b,0x94,0xca,0x96,0x11,0xa7,0xa9,
4375
0x80,0xd3,0x8c,0x86,0xcb,0x6c,0x01,0x7f,0x29,0xc3,0x69,0x1e,0x8c,0xd7,0x3c,0x14,
4376
0xde,0x72,0x37,0x9c,0x25,0x38,0xcb,0xab,0xc3,0xa0,0x0d,0x5f,0x09,0x1c,0x65,0x94,
4377
0xe3,0x25,0xe6,0x13,0x9b,0x47,0x6c,0xfe,0xf0,0xde,0xb8,0xc2,0x0d,0x70,0x85,0x4b,
4378
0x95,0xfd,0x60,0x23,0x43,0x70,0x86,0x83,0x1f,0x3c,0x07,0x2f,0x78,0xb5,0x73,0x7f,
4379
0x83,0xef,0xdb,0x0c,0xcf,0x37,0x38,0xbe,0x7d,0x70,0x7b,0x47,0x38,0x8f,0xf7,0x29,
4380
0xfc,0xdd,0xa9,0x78,0xbb,0x81,0x93,0x7c,0xe0,0xfc,0xdc,0x04,0xfe,0x6d,0x73,0xbc,
4381
0xdb,0x96,0xf8,0xb6,0x65,0xce,0xb1,0xfd,0x2f,0xe7,0xd5,0xfe,0xd6,0xb9,0xb2,0xe5,
4382
0xce,0x8b,0x7d,0x12,0x1f,0x76,0x32,0x1e,0x6c,0x85,0x73,0x5f,0xdf,0xc5,0x6d,0xfd,
4383
0xdc,0x79,0xab,0x45,0xf0,0x8e,0xdd,0xe0,0x1c,0x81,0x71,0xf4,0x87,0x65,0x0c,0x74,
4384
0xbe,0xa9,0x79,0xa6,0xe6,0x95,0x06,0xa6,0x51,0x0e,0xcb,0x08,0xdf,0x9c,0x0c,0x84,
4385
0x5f,0x6c,0xed,0x9c,0xd1,0xc0,0x2d,0x1a,0xc2,0x2d,0xf6,0x73,0xac,0xe2,0x20,0x18,
4386
0x45,0x0f,0x65,0x26,0x9c,0xa2,0x23,0x9c,0x62,0x34,0x9c,0xe2,0x25,0x38,0xc5,0xf7,
4387
0xf8,0xa1,0x75,0xf0,0x43,0x4b,0x95,0x1e,0x4a,0x4f,0xe5,0x48,0xe5,0x68,0xe5,0x18,
4388
0xe5,0x58,0xa5,0x8f,0xd2,0x57,0xe9,0xa7,0x9c,0xaa,0x9c,0xa9,0x9c,0xa5,0x9c,0x8d,
4389
0x43,0x1a,0x38,0x47,0xa5,0x92,0xac,0xd4,0xc7,0x80,0x92,0x51,0x4a,0x94,0x9a,0xca,
4390
0x16,0x4a,0xad,0xca,0xc8,0x2d,0xdd,0x51,0xd9,0x09,0xbf,0xb4,0x3d,0x3c,0xa4,0x37,
4391
0x3c,0xe4,0x59,0x38,0xc7,0x7c,0xf8,0xc6,0x22,0x65,0x89,0xf2,0x91,0xb2,0x54,0xf9,
4392
0x16,0xde,0xb1,0x05,0x9c,0xa3,0x03,0x7c,0xa3,0x07,0x5c,0x23,0x5c,0x08,0x96,0x54,
4393
0x52,0x4a,0x0d,0xa5,0x6d,0x32,0xe2,0x1c,0x37,0x2a,0xa3,0x95,0x31,0xca,0x3c,0xe7,
4394
0x8b,0x8e,0xc1,0x11,0x5d,0x0c,0xf7,0x68,0x0a,0xd7,0xb8,0x10,0xae,0x71,0x0f,0x3c,
4395
0x23,0x81,0xdf,0x59,0x0e,0xb7,0x48,0xc0,0x2b,0x06,0xc0,0x29,0x6e,0x80,0x4f,0xfc,
4396
0x09,0x2e,0x31,0x01,0x1e,0x51,0x01,0x87,0x28,0x83,0x3f,0x0c,0x83,0x3b,0x3c,0x01,
4397
0x6f,0x30,0xce,0xd0,0xd6,0xb1,0x85,0xe3,0x94,0x07,0xe1,0x09,0x81,0x25,0xac,0x53,
4398
0x76,0x85,0x23,0x74,0x82,0x1f,0x4c,0x55,0xe6,0x17,0x45,0x4e,0x65,0x21,0x2e,0x65,
4399
0x1d,0xd8,0xc1,0x0e,0xb8,0x93,0xc1,0x99,0x2c,0x53,0x7a,0xc0,0x10,0x2a,0x70,0x24,
4400
0x97,0xc1,0x0c,0xf6,0x87,0x19,0x1c,0xaf,0x5c,0xac,0xdc,0xae,0x8c,0x85,0x17,0x0c,
4401
0x83,0x13,0xac,0x85,0x13,0xec,0x85,0x0f,0x59,0x06,0x2f,0x08,0xae,0xe3,0x79,0x70,
4402
0x81,0x9b,0x94,0xbe,0xb5,0x22,0x2e,0x10,0x1c,0xc7,0x71,0xb0,0x81,0xc0,0x05,0x5e,
4403
0xc6,0x67,0x9c,0x07,0x0f,0x58,0x09,0x0f,0x28,0xc5,0x5b,0xec,0x09,0x07,0x08,0xce,
4404
0xe2,0xd5,0xb0,0x80,0x45,0xb5,0xab,0x3c,0xc5,0x14,0x5e,0x62,0x57,0xe5,0x48,0xdc,
4405
0x44,0x73,0x12,0x07,0x3b,0x0f,0x71,0x38,0xbe,0xe1,0x5f,0xf1,0x0c,0xa7,0xe0,0x18,
4406
0xce,0x86,0x17,0xac,0xc4,0x2f,0x2c,0xc0,0x2b,0x34,0x9f,0xb0,0x0d,0xbc,0x20,0x78,
4407
0x82,0x43,0x70,0x04,0x87,0xe3,0x02,0x4e,0xc7,0xfd,0x9b,0xed,0x7c,0xbf,0xc5,0xf0,
4408
0x82,0xad,0xf1,0xf9,0x5a,0x38,0x87,0x2f,0xf8,0x7b,0xfb,0x39,0x77,0xcf,0x9c,0x3d,
4409
0x63,0x07,0x37,0xc3,0x0c,0xca,0x9d,0x97,0xf7,0x21,0x3e,0x5e,0x02,0x0f,0xaf,0x10,
4410
0x7e,0xb0,0x35,0xdc,0xa0,0x05,0xbc,0xa0,0x3d,0xac,0xc0,0xbc,0xba,0xae,0xf8,0x74,
4411
0x3d,0x9c,0x43,0x77,0x3a,0xce,0xdc,0x30,0xc7,0x0d,0x46,0xc3,0x0a,0xa6,0x38,0x17,
4412
0xee,0x45,0x1c,0xb8,0x39,0xce,0x7b,0x7b,0xcd,0xb9,0x6e,0x6f,0xe1,0xba,0x25,0x70,
4413
0xdb,0xca,0x70,0xda,0x0e,0x76,0x1e,0xdb,0x89,0xce,0x5d,0x1b,0x86,0xab,0x36,0xd9,
4414
0xf9,0x69,0xd3,0x9d,0x93,0xf6,0x1c,0x0e,0xda,0x30,0x9c,0xb3,0x49,0xb8,0x66,0xe6,
4415
0x98,0xcd,0xc0,0x2d,0x4b,0xe0,0x92,0xb5,0x77,0xfe,0x58,0x70,0xc7,0x3a,0xe3,0x8c,
4416
0xf5,0x85,0x49,0x3c,0xe2,0x3c,0xb1,0xf1,0xf8,0x61,0x4f,0x39,0x27,0xac,0x02,0x17,
4417
0x2c,0xe1,0xfc,0x2f,0xf3,0xbe,0xf6,0x70,0xae,0x57,0x29,0x0c,0xa3,0xb9,0xf3,0xb8,
4418
0xda,0xc3,0x33,0x02,0xcb,0x30,0x86,0x51,0x17,0x76,0xd1,0x16,0x37,0xeb,0x00,0xe7,
4419
0x63,0x05,0xdf,0xaa,0x0b,0xce,0xd5,0x18,0x18,0xc6,0xeb,0xb8,0x55,0xef,0x39,0x9f,
4420
0xca,0xbc,0xa9,0x1a,0x4a,0x11,0x2c,0xa3,0x25,0xbe,0x54,0xf0,0xa4,0x3a,0x39,0x47,
4421
0xaa,0x27,0x6e,0x54,0x2f,0xd8,0xc6,0x75,0xce,0x83,0xba,0x03,0xbe,0x91,0x70,0xce,
4422
0x53,0x3f,0xe7,0x39,0x99,0xdf,0xb4,0x12,0xde,0x51,0x8c,0xc7,0xb4,0x1f,0xee,0x52,
4423
0x70,0x95,0x06,0xe2,0x28,0x99,0x9b,0x64,0x4e,0x92,0xb9,0x48,0x09,0x18,0x48,0x09,
4424
0xee,0x91,0x39,0x47,0x9d,0x9c,0x67,0xd4,0x03,0x1e,0x72,0x06,0x1c,0x64,0x34,0x1e,
4425
0xd1,0xad,0xce,0x1d,0x32,0x67,0xa8,0x1c,0x37,0x68,0xa5,0xe3,0x20,0x6b,0xf0,0x80,
4426
0x12,0xb0,0x90,0xad,0xf0,0x7b,0x3a,0x3a,0xa7,0x27,0xb8,0x3c,0x07,0x39,0x87,0xa7,
4427
0x42,0x79,0x43,0x79,0x5f,0x59,0xac,0x54,0xee,0x1a,0x31,0x92,0xc0,0x43,0x46,0xc3,
4428
0x41,0xcc,0xd3,0xe9,0x0a,0x07,0xc9,0x5d,0xa8,0x87,0x93,0xd3,0x08,0x17,0xa7,0x14,
4429
0x16,0x52,0x86,0x7b,0x73,0x1e,0xce,0xcd,0x3c,0x5c,0x9b,0x2f,0x61,0x21,0xc1,0xb3,
4430
0x69,0x8b,0x5f,0xd3,0x1b,0x1e,0xf2,0x3b,0x38,0x48,0x19,0xbc,0x63,0x0a,0x9c,0xc3,
4431
0x3c,0x99,0x9b,0xe1,0x1c,0x81,0x71,0x2c,0x71,0x3e,0xcc,0x4a,0xb8,0x46,0x60,0x1a,
4432
0xc3,0x60,0x19,0x63,0x60,0x18,0x5f,0xc2,0x2e,0x02,0xb7,0x30,0x5e,0x61,0x9c,0x22,
4433
0x30,0x8a,0x04,0x6c,0x62,0x18,0x4c,0xe2,0x2e,0x9c,0x95,0x7b,0x94,0x31,0x81,0x4f,
4434
0xcc,0x4a,0x26,0xde,0x9c,0x15,0xf9,0x2b,0x6b,0x83,0xbf,0x32,0x5b,0x9f,0x87,0x73,
4435
0xf4,0xf9,0xac,0xbc,0x3f,0x27,0xf2,0x59,0x82,0xcb,0xd2,0x23,0x5c,0x6e,0x1b,0x2e,
4436
0x46,0x7c,0x2d,0x72,0x5a,0x1a,0xe2,0xb2,0xf4,0x57,0x06,0xe3,0xb1,0x8c,0xc0,0x63,
4437
0xb9,0x01,0x8f,0x65,0xbc,0xf2,0x89,0xb2,0x2c,0x5c,0xec,0x3a,0x3f,0x72,0x5a,0x0e,
4438
0xc6,0x69,0x09,0x3e,0xcb,0x89,0x4a,0x85,0xb2,0x28,0x78,0x2c,0x0b,0xf4,0xfe,0x5c,
4439
0x10,0xf1,0x92,0x63,0xe1,0x24,0xc6,0x47,0xc6,0xc2,0x45,0x8c,0x87,0x04,0x16,0x52,
4440
0x03,0x06,0xb2,0x2d,0xec,0xa3,0x3d,0xcc,0xc3,0x58,0x47,0xe0,0x1c,0x81,0x71,0xcc,
4441
0x80,0x71,0xbc,0x0b,0xe3,0x58,0x07,0xe3,0xa8,0x0b,0xe3,0x68,0x0d,0xe3,0xe8,0x0e,
4442
0xe3,0x18,0x00,0xe3,0x18,0x05,0xe3,0x18,0x0b,0xe3,0x98,0x09,0xe3,0x08,0xfe,0x49,
4443
0xee,0x02,0xb3,0x77,0xf4,0xef,0x8b,0x7f,0x72,0x2e,0xee,0xc9,0x85,0xb8,0x27,0x23,
4444
0xf1,0x4f,0x82,0x7b,0x92,0xbb,0xcc,0x0d,0xee,0x31,0x1b,0xaf,0x24,0x8b,0x4f,0xb2,
4445
0x27,0x1e,0x49,0xa9,0x73,0x47,0x4a,0x61,0x20,0x65,0x8e,0x7f,0x98,0x1f,0xf2,0x19,
4446
0x5e,0x48,0x25,0x1c,0xe4,0x33,0x3c,0x90,0x79,0xf8,0x1f,0x81,0x7f,0x54,0xc2,0x40,
4447
0x16,0x39,0xcf,0xc3,0xfc,0x8e,0xcf,0xe1,0x1f,0xe6,0x73,0x2c,0x82,0x77,0x2c,0x87,
4448
0x73,0x04,0xc6,0xf1,0x22,0xce,0x46,0x02,0x57,0xc3,0x1c,0x8d,0x93,0x94,0xf3,0x3f,
4449
0xd3,0xd7,0xa1,0xe5,0x11,0xf3,0x28,0x84,0x75,0xec,0xe5,0xf8,0x46,0x2b,0xc7,0x34,
4450
0x0e,0x74,0x1c,0xc3,0xf8,0x45,0x4f,0xc7,0x2c,0x7a,0x39,0x4e,0x61,0x7c,0xc2,0xb8,
4451
0xc4,0x39,0xf0,0x88,0x4b,0x1c,0x83,0xb8,0x1e,0xf6,0x70,0x3f,0xcc,0x61,0x65,0x60,
4452
0x0e,0x2b,0xf5,0xfe,0x52,0xc6,0x28,0x8f,0x2b,0x33,0x94,0xd7,0xc2,0x25,0x9c,0xab,
4453
0xf4,0xf5,0x47,0xa9,0xa3,0x34,0x57,0x4a,0x95,0xfe,0xca,0x40,0x65,0x9c,0x32,0x5e,
4454
0xf9,0x38,0xfc,0xfe,0x6a,0xbd,0x9f,0x95,0x1e,0x4a,0x5f,0x25,0xb1,0x46,0x1f,0x23,
4455
0x5f,0xe9,0xef,0x56,0x12,0x5f,0xeb,0xeb,0xb0,0xf2,0xae,0xb2,0x48,0x59,0xa9,0xd4,
4456
0xf9,0x46,0xcf,0xab,0xf4,0x55,0x46,0x2b,0xe5,0x4a,0x85,0x32,0x2f,0x5c,0xa8,0xfc,
4457
0xad,0x9e,0xbe,0x56,0x2f,0x43,0x19,0xa6,0xbc,0xa4,0xcc,0x52,0x16,0x2a,0x2b,0xc2,
4458
0x05,0x83,0xeb,0x34,0xe3,0xad,0x8b,0xfc,0x8e,0xb5,0xf8,0x1d,0x81,0x95,0x04,0x4e,
4459
0x12,0x18,0x49,0xe0,0x23,0x81,0x8d,0x04,0x38,0x10,0x98,0x48,0xe0,0x21,0xc9,0x44,
4460
0x2d,0x7d,0x3b,0x5f,0x2b,0x3a,0xa8,0x4b,0x44,0x07,0x5f,0xd9,0x3c,0x7c,0x64,0xa7,
4461
0xe8,0x78,0x61,0x3d,0x1f,0x09,0x57,0x99,0xef,0xad,0x34,0x8a,0xf1,0x91,0xe6,0xf4,
4462
0xdd,0x07,0x3e,0x52,0x86,0x13,0xd2,0x17,0x27,0x64,0xa8,0x72,0x15,0x7c,0xe4,0x1e,
4463
0xc7,0x47,0xee,0x8f,0xbe,0x95,0xca,0xf1,0x91,0x47,0xe1,0x23,0x8f,0x29,0x8f,0x2b,
4464
0x13,0x1c,0x1f,0x99,0xe4,0xf8,0xc8,0x74,0x3c,0x92,0xb7,0xf0,0x48,0x02,0x1f,0xd1,
4465
0x9b,0x9a,0x78,0x1a,0x2f,0x64,0x2e,0x5e,0xc8,0x42,0xbc,0x90,0xe5,0xf0,0x91,0xca,
4466
0x54,0xd4,0x6f,0x1f,0x9c,0x90,0x0b,0x70,0x41,0x7e,0xe7,0xf8,0xc8,0x48,0xc7,0x47,
4467
0xcc,0xff,0xb8,0x17,0xe7,0x23,0xf0,0x91,0xe1,0x69,0x7d,0x4f,0x89,0xf3,0x11,0x7c,
4468
0x8f,0x51,0xf0,0x91,0xe0,0x78,0xdc,0x04,0x1f,0x79,0x26,0xc6,0x47,0x9e,0x85,0x8f,
4469
0x3c,0x0f,0x1f,0x79,0x19,0x17,0xe4,0x0b,0xa5,0x30,0xa3,0xef,0x45,0xe1,0x23,0xc5,
4470
0x31,0x3e,0x52,0x9b,0xce,0xfa,0xc3,0xe9,0xa6,0x3f,0x0b,0x3e,0x72,0x8e,0xeb,0xa6,
4471
0x7f,0x83,0x1e,0x7a,0xe3,0x23,0x7f,0xc7,0x13,0x59,0x0a,0x1f,0x59,0x8e,0x2f,0x12,
4472
0xba,0xe7,0xb7,0x70,0x5d,0xf3,0xcd,0xe9,0x97,0xbf,0xdf,0xf5,0xca,0x7f,0x4a,0x87,
4473
0x7c,0xf0,0x43,0xbe,0x75,0x7c,0xa4,0xae,0xeb,0x8c,0xb7,0xae,0x78,0xeb,0x88,0x0f,
4474
0xdd,0xf0,0x1d,0x71,0x44,0x7a,0xc3,0x47,0xfa,0xe3,0x86,0xdc,0x42,0x17,0xfc,0xcb,
4475
0x74,0xbf,0x2f,0xa1,0xfb,0x7d,0xff,0x18,0x1f,0x29,0xa3,0xd3,0xdd,0xfa,0xdc,0x7b,
4476
0xd0,0xdd,0x7e,0x32,0x9d,0xed,0xd6,0xcf,0x3e,0x02,0x57,0x64,0x34,0x8e,0x88,0xf9,
4477
0x21,0xd6,0xbf,0x5e,0x41,0xd7,0xfa,0x4b,0xae,0x63,0xdd,0xf8,0xc8,0xfb,0xf8,0x21,
4478
0x1f,0xe2,0x87,0xac,0x51,0xd6,0xc2,0x47,0xbe,0x87,0x8f,0x58,0x7f,0x7a,0x31,0xae,
4479
0x48,0x03,0x1c,0x91,0x96,0xb8,0x21,0xd6,0x8f,0x5e,0x46,0x27,0xfa,0xa1,0xae,0x0b,
4480
0xdd,0x5c,0x91,0x01,0xf4,0x9e,0x0f,0x71,0x7c,0xc4,0xfa,0xce,0x6f,0xc4,0x19,0x79,
4481
0x08,0x57,0x64,0x82,0xeb,0x34,0xaf,0xa0,0xbf,0xdc,0xba,0xcb,0x67,0x39,0x3e,0xb2,
4482
0x98,0x8e,0xf2,0x95,0x8e,0x8f,0x58,0x37,0x79,0x01,0xfe,0x48,0x1d,0xbc,0x91,0x52,
4483
0x7c,0x11,0xeb,0x1e,0xef,0xe8,0xf8,0x48,0x17,0xba,0xc5,0xad,0x57,0xdc,0xfa,0xc4,
4484
0x4f,0xc4,0x21,0x09,0xfd,0xe1,0x17,0x39,0x3e,0x72,0x1d,0xee,0xc8,0xad,0xce,0x19,
4485
0xb9,0x07,0x4f,0xe4,0x61,0xfc,0x10,0xeb,0x00,0x7f,0x96,0xde,0xef,0x59,0x31,0x3e,
4486
0xb2,0x5a,0xf9,0x26,0xc6,0x47,0xac,0xe7,0xbb,0x26,0x2e,0x49,0x03,0xd7,0xe9,0x7d,
4487
0x00,0x3d,0xde,0x5d,0xe8,0xef,0xee,0x46,0x6f,0xf7,0x09,0xf8,0x24,0x27,0xd3,0xd3,
4488
0x3d,0x00,0x3e,0x32,0xd4,0xf5,0x74,0xdf,0x80,0x53,0xf2,0x10,0x2e,0x89,0xf5,0x70,
4489
0x3f,0x47,0xb7,0xf6,0xab,0x74,0x6a,0xbf,0x89,0x53,0xb2,0x98,0x0e,0xed,0x15,0x74,
4490
0x66,0x27,0x71,0x4a,0xea,0xe0,0x92,0x74,0xa0,0x0b,0xbb,0x0b,0x1d,0xd8,0xd6,0x7f,
4491
0xdd,0x1d,0x97,0xe4,0x14,0xd7,0x69,0x3d,0x02,0x9f,0xe4,0x71,0xe7,0x91,0x58,0x6f,
4492
0xf5,0x6b,0xae,0xab,0x7a,0x21,0xfd,0xd4,0x5f,0x6c,0x51,0xd5,0x4b,0xdd,0x92,0x2e,
4493
0xea,0x4e,0x38,0x25,0xa1,0x7f,0xba,0xb7,0xf3,0x4a,0xae,0x73,0x2e,0x89,0x75,0x4c,
4494
0x4f,0x70,0xbd,0xd2,0xe6,0x8f,0xcc,0xa1,0x43,0x3a,0xf8,0x23,0xdb,0xd1,0x1b,0xdd,
4495
0x2a,0x0f,0x1f,0x39,0x00,0xaf,0xe4,0x1c,0xd7,0x0f,0x7d,0x15,0x7c,0xe4,0x1a,0x1c,
4496
0x93,0x3f,0xd1,0x05,0xfd,0x3c,0x7c,0x64,0x96,0xf2,0x4e,0xed,0xa8,0x07,0xda,0x3a,
4497
0xa0,0xad,0xfb,0xb9,0x1d,0x7d,0xcf,0x1d,0xe9,0x73,0xee,0x85,0x87,0xd2,0x17,0xef,
4498
0x64,0x88,0xeb,0x65,0xbe,0x8a,0x2e,0x66,0xeb,0x61,0xb6,0x9e,0xe5,0xe7,0x1d,0x1f,
4499
0x39,0x14,0xbf,0xc4,0xdc,0x92,0x13,0xf1,0x49,0x6e,0xc4,0x23,0x79,0xd2,0xf9,0x23,
4500
0xcf,0xe3,0x8c,0xd4,0xc1,0x15,0x39,0x81,0xee,0xe3,0xcb,0x71,0x45,0x6e,0xc7,0x15,
4501
0xf9,0x1e,0x3e,0x12,0xfc,0x90,0x61,0xf8,0x21,0x77,0xe1,0x83,0x6c,0xe9,0xfa,0x8c,
4502
0xf7,0xa5,0xc3,0xb8,0x0d,0x4e,0xc8,0x51,0x38,0x21,0x03,0xe9,0x2a,0x9e,0xe0,0x3a,
4503
0x8a,0x9f,0x71,0xbd,0xc4,0x2f,0xd1,0x45,0xfc,0x4e,0x8c,0x8f,0x84,0xfe,0xe1,0x6f,
4504
0x95,0x62,0x3a,0x88,0x8d,0x8f,0xec,0x80,0x33,0x72,0x15,0xae,0xc8,0x43,0x8e,0x8f,
4505
0x04,0x47,0xa4,0x1e,0x5d,0xc2,0xfb,0xd0,0x21,0xdc,0xd8,0x75,0x07,0xef,0x47,0x5f,
4506
0x70,0xe0,0x23,0x07,0xe3,0x90,0x0c,0xc1,0x1d,0x79,0x99,0x4e,0xe0,0xca,0x1d,0x22,
4507
0x77,0x64,0x7b,0xd7,0x05,0x7c,0x8c,0xe3,0x23,0x27,0xc5,0xf8,0xc8,0xa9,0x74,0xfb,
4508
0x0e,0x72,0x9d,0xbe,0xa3,0xe8,0xf1,0x1d,0x47,0x6f,0x6f,0x81,0xeb,0xe9,0x0d,0x7c,
4509
0x64,0x7f,0xfc,0x93,0xfe,0xf4,0xec,0x5e,0x41,0xcf,0xee,0xbd,0xf4,0xe9,0x3e,0xe8,
4510
0x7a,0x74,0xc7,0xb9,0xae,0xdc,0xff,0xa5,0x1f,0xf7,0x33,0xc7,0x47,0x56,0xd1,0x85,
4511
0xdb,0x98,0xee,0xdb,0xd6,0x74,0xde,0x1e,0x86,0xa3,0x12,0xfc,0x94,0x17,0xe9,0xaf,
4512
0x5d,0xe0,0xfa,0x6b,0x97,0xba,0xce,0x5a,0xeb,0xaa,0xfd,0xda,0xf5,0xd2,0x4e,0xa7,
4513
0x63,0xb6,0x2e,0xee,0xc9,0xc1,0x38,0x27,0xc7,0xc5,0xf8,0xc8,0xef,0x70,0x4b,0xa6,
4514
0x3a,0x3e,0x32,0x03,0xaf,0x24,0x38,0x25,0x73,0x71,0x4a,0x82,0x4f,0xb2,0x10,0x9f,
4515
0x64,0x05,0x3e,0x49,0x70,0x49,0x7e,0x50,0x8a,0xe9,0x8b,0x35,0x3e,0x52,0x7f,0x13,
4516
0xf8,0x48,0x2b,0xe5,0x20,0xf8,0xc8,0x49,0xf0,0x91,0x53,0xab,0xe1,0x23,0x03,0x1c,
4517
0x1f,0xb9,0x44,0xb9,0x4c,0x19,0x0a,0x1f,0x19,0xa5,0x5c,0xef,0xfc,0x95,0xe7,0xe8,
4518
0x9d,0x4d,0xc2,0x47,0x32,0xf0,0x91,0x22,0x3c,0x96,0x6d,0x9c,0xc7,0x12,0xfc,0x95,
4519
0x3d,0x7f,0x82,0x8f,0x98,0xbf,0x12,0x3c,0x95,0xf6,0x78,0x2a,0x5d,0xf0,0x54,0xba,
4520
0x29,0xdd,0x95,0x3e,0x78,0x29,0xd7,0x2b,0x5b,0xee,0x51,0xc5,0x47,0x5a,0xef,0xa9,
4521
0xd9,0x4f,0xf9,0x23,0x7c,0xa4,0xe1,0x5e,0x9a,0x3b,0x94,0x6b,0x94,0x3b,0x95,0x4f,
4522
0x94,0x47,0xf6,0x89,0xf8,0x48,0x65,0x7d,0xa5,0x81,0x3e,0x8e,0x34,0x50,0x56,0x36,
4523
0x8e,0x7c,0x96,0x4f,0xf1,0x59,0x56,0xe1,0xb3,0x54,0x36,0xa9,0xf2,0x59,0x9a,0xe2,
4524
0xb0,0x0c,0x84,0x8f,0xdc,0x86,0xbb,0x32,0x1e,0x67,0x65,0x1a,0xae,0xca,0x1c,0x1c,
4525
0x95,0x0f,0xe8,0x8e,0x3d,0xb1,0x99,0xbe,0x76,0x2b,0xb7,0x2b,0x6b,0x94,0x37,0x34,
4526
0xb4,0x56,0xc2,0x47,0xd2,0xf8,0x2a,0xbb,0xe1,0xab,0x34,0xa5,0x3f,0xb6,0x14,0x6f,
4527
0xa5,0x2d,0x9e,0x4a,0x27,0x3c,0x95,0x3b,0xf0,0x54,0xee,0x81,0x8f,0x58,0x37,0x6c,
4528
0x70,0x52,0x9a,0xe3,0xa2,0x04,0x0f,0xe5,0x23,0xf8,0xc8,0xce,0x2d,0xf4,0x79,0xad,
4529
0x74,0x57,0xfa,0x28,0x97,0x29,0x43,0x95,0x72,0x65,0xba,0xf2,0xaa,0x32,0x57,0xb9,
4530
0xb0,0xa5,0xde,0x6f,0xca,0xfb,0xca,0x42,0xe5,0x07,0xf8,0x48,0x70,0x58,0x2a,0xbb,
4531
0x45,0xce,0xca,0x0b,0xff,0x13,0xb9,0x29,0xb5,0x71,0x52,0x82,0x87,0x32,0x08,0x3e,
4532
0x62,0x9d,0xaf,0x7f,0xa6,0xdf,0x75,0x05,0x7d,0xae,0x5f,0x2b,0xbb,0x3b,0xd7,0xc4,
4533
0x9c,0x12,0xeb,0x5c,0xb5,0xae,0x55,0xeb,0x58,0xdd,0xcb,0xf5,0xa9,0x36,0x86,0x8f,
4534
0xb4,0x55,0xf6,0xc7,0x1b,0xb9,0x88,0xfe,0xd4,0xe7,0xe9,0x4d,0x5d,0xe5,0xfa,0x51,
4535
0xf7,0xa6,0x0b,0xf5,0x10,0x3a,0x50,0x8f,0xc2,0x19,0x19,0xee,0xba,0x4e,0x9f,0xa4,
4536
0xdf,0x74,0x0a,0xbd,0xa6,0xb3,0xe9,0x31,0xb5,0x0e,0xd3,0xe0,0x8c,0x34,0xa0,0x9b,
4537
0xb4,0x94,0x4e,0xd2,0x56,0x74,0x91,0x5a,0x0f,0xe9,0x11,0x8e,0x8f,0xf4,0x72,0x7d,
4538
0xa2,0x8f,0x39,0x3e,0x32,0x11,0x5f,0x64,0x12,0xbe,0xc8,0xf4,0x18,0x1f,0x59,0x46,
4539
0xef,0xa7,0x75,0x7b,0x66,0xf0,0x41,0xb6,0xc5,0x03,0x69,0x86,0xe7,0x71,0x36,0x9e,
4540
0x87,0x75,0x72,0x5a,0x17,0xa7,0x75,0x6f,0x86,0xce,0xcd,0xfb,0x70,0x3d,0x82,0xe7,
4541
0x71,0x2e,0x7e,0x47,0xc6,0x79,0x1d,0xf5,0x70,0x3a,0x1a,0xe2,0x74,0x98,0xcf,0xd1,
4542
0x19,0x87,0xa3,0xbb,0xf2,0xac,0x32,0x1f,0x87,0xa3,0x3b,0x0e,0xc7,0x2d,0x38,0x1c,
4543
0x73,0x95,0xef,0x94,0xca,0xef,0xa3,0xee,0xcc,0x1d,0xe8,0xce,0xec,0x9e,0x87,0x8f,
4544
0x9c,0x04,0x1f,0x39,0x59,0x39,0x45,0x39,0x1d,0x3e,0xd2,0x1f,0x3e,0x32,0x04,0x07,
4545
0x24,0xf0,0x91,0x54,0xa5,0x3e,0x06,0x94,0xe2,0x18,0x1f,0xa9,0x4d,0xef,0x66,0xe0,
4546
0x23,0xbb,0xe1,0x8a,0x94,0xb9,0xce,0xcd,0x69,0x78,0x20,0x73,0xf1,0x3f,0x82,0xfb,
4547
0xb1,0x58,0xf9,0xbb,0xf2,0xb1,0xf2,0xb9,0xf2,0x7d,0xf8,0x3b,0xf1,0x40,0xda,0xe1,
4548
0x7f,0x74,0xc3,0xfb,0x58,0x1b,0xe3,0x23,0x2d,0x95,0x4e,0xca,0x0d,0xca,0x4d,0xca,
4549
0x5d,0xf0,0x91,0xef,0xe0,0x23,0x77,0xb9,0x1e,0xcd,0x75,0xca,0x9e,0x78,0x1f,0x17,
4550
0xd0,0x8f,0xf9,0x67,0x7c,0x8f,0xe0,0x78,0xfc,0x99,0xee,0xcb,0x05,0x38,0x1d,0xf5,
4551
0x71,0x39,0x2e,0xc5,0xe1,0xf8,0x3d,0xee,0xc6,0xbd,0x38,0x1b,0x93,0x71,0x35,0x82,
4552
0xa7,0xd1,0x06,0x3f,0xe3,0x0c,0xbc,0x8c,0x72,0x7c,0x0c,0x73,0x31,0x5a,0x3b,0xff,
4553
0xe2,0x18,0x5c,0x8b,0xc7,0x70,0x2d,0x82,0x67,0xb1,0x53,0x51,0xc4,0x47,0xf6,0xc7,
4554
0xaf,0x08,0x6e,0xc5,0x5c,0xbc,0x8a,0x02,0xba,0x26,0x6b,0xe3,0x56,0x6c,0x87,0x53,
4555
0x61,0xbd,0x92,0x87,0x2a,0xc7,0x2b,0xf7,0xe0,0x52,0x84,0xfe,0xc8,0xaf,0x8a,0x23,
4556
0x9f,0xa2,0x13,0x3e,0xc5,0x20,0x3c,0x8a,0xbb,0x94,0xc7,0x4a,0x22,0x97,0xe2,0x09,
4557
0x1c,0x8a,0xca,0x9a,0x91,0x43,0x51,0x9f,0xae,0xc8,0xc3,0x70,0x26,0xce,0x85,0x8f,
4558
0x04,0x5f,0xe2,0x66,0x65,0x28,0xce,0xc4,0xa3,0xf0,0x91,0xc7,0x71,0x24,0x5e,0xa1,
4559
0xeb,0xf1,0x6d,0x5c,0x89,0xd0,0xf3,0x58,0x1f,0x3f,0x22,0x74,0x3a,0xf6,0xc2,0x91,
4560
0x08,0x7d,0x8e,0xa3,0x94,0x57,0x5d,0x97,0x63,0x12,0x4f,0x22,0x74,0x36,0x76,0x53,
4561
0x4e,0x73,0xbd,0x8d,0x83,0x5c,0x57,0xe3,0x95,0xf4,0x31,0x3e,0x45,0x0f,0x63,0xe8,
4562
0x60,0x9c,0xe1,0xf8,0xc8,0x52,0xfa,0x17,0x53,0xf8,0x14,0xd6,0xb9,0xd8,0x0a,0x9f,
4563
0x62,0x90,0xeb,0x51,0xbc,0x92,0xae,0xc4,0xd0,0x93,0xf8,0x92,0xeb,0x45,0x0c,0x7c,
4564
0x64,0xa1,0xf2,0xc5,0x96,0x91,0x4b,0xd1,0x8c,0xae,0xc3,0x96,0x8e,0x8f,0x84,0x6e,
4565
0xc3,0x03,0xe0,0x23,0xd6,0x6b,0x68,0x7e,0xc5,0x8d,0x38,0x15,0x63,0x5d,0x77,0xe1,
4566
0x12,0xfa,0x0a,0x43,0x57,0x61,0x92,0x8e,0xc2,0x9a,0xb8,0x15,0x0d,0x70,0x2a,0x5a,
4567
0xe2,0x52,0x74,0x70,0xdd,0x83,0x5d,0xe8,0x1b,0xec,0xe6,0xf8,0xc8,0x29,0x74,0x0a,
4568
0x0e,0x71,0x6e,0xc5,0x4d,0xf8,0x14,0x4f,0xbb,0xbe,0xc0,0xe7,0xe9,0x08,0x9c,0x9d,
4569
0x87,0x8f,0xbc,0xa1,0xbc,0x4d,0x0f,0x60,0x5b,0x7a,0xff,0x3a,0xbb,0xbe,0xbf,0xc0,
4570
0x47,0x7a,0x3b,0x3e,0x72,0x32,0x5d,0x7e,0x93,0x1c,0x1f,0x99,0xe6,0x7a,0xfb,0x66,
4571
0xe2,0x62,0x84,0x7e,0xbe,0xc7,0xe9,0xe3,0x9b,0xe2,0x7a,0xf8,0x2a,0x70,0x33,0x42,
4572
0xef,0x5e,0x0b,0x7a,0xf6,0x3a,0x38,0x3e,0x62,0xbd,0x7a,0xa1,0x4f,0xef,0x1c,0xd7,
4573
0xa7,0x67,0x7c,0xe4,0x31,0xd7,0x9d,0x17,0xf8,0xc8,0x64,0xba,0xf2,0x42,0x4f,0xde,
4574
0x8e,0x31,0x3e,0xb2,0xbb,0xeb,0xc3,0x6b,0x8c,0xe3,0xd1,0xcc,0x75,0xdd,0xb5,0x83,
4575
0x8f,0xac,0x76,0x9e,0xc7,0xd6,0xb8,0x1d,0xad,0xe9,0xae,0xeb,0xe0,0xf8,0x88,0x75,
4576
0xd2,0x1d,0x42,0x1f,0xdd,0x83,0xf4,0xcf,0xbd,0x45,0xef,0x9c,0x75,0xce,0x59,0xb7,
4577
0x5c,0x46,0xc9,0xd2,0x2d,0xd7,0x82,0x4e,0xb9,0x76,0x74,0xc8,0x1d,0xe2,0xf8,0xc8,
4578
0xb1,0xf4,0xc6,0xf5,0xc6,0xfb,0xb0,0xae,0xb8,0xd0,0x11,0xf7,0x17,0xe7,0x7e,0x18,
4579
0x1f,0x39,0x35,0xc6,0x47,0x16,0xd3,0xfb,0x96,0xa5,0xe7,0xad,0x0d,0xfd,0x6e,0x07,
4580
0x2b,0xe7,0xe0,0x82,0x58,0x7f,0x9b,0xf5,0xb6,0x59,0x5f,0x5b,0xe8,0x69,0xcb,0xe0,
4581
0x87,0x94,0xba,0x5e,0xb6,0x03,0x5c,0x17,0x5b,0x57,0xfa,0xd7,0x4e,0xc3,0x13,0xb9,
4582
0x89,0x9e,0xb5,0x3f,0x56,0xc3,0x47,0xc6,0xe2,0x88,0x7c,0xe2,0xf8,0xc8,0x6a,0x7a,
4583
0xd2,0xbe,0xa9,0x17,0xf5,0xa3,0xd5,0xa1,0xff,0xac,0x9d,0xeb,0x3d,0x33,0x3e,0xd2,
4584
0xcb,0xf1,0x91,0xd7,0x95,0xf7,0x94,0x45,0xca,0xaa,0x5d,0x23,0x87,0xe4,0x20,0x5c,
4585
0x91,0xd5,0xcd,0xf5,0x67,0xe9,0x31,0x3b,0x84,0xfe,0xb2,0xe0,0x88,0x04,0x3f,0x64,
4586
0x17,0xfa,0xca,0x9a,0xd0,0x53,0x16,0x3a,0xca,0xf6,0xc3,0x11,0x39,0x0b,0x47,0xe4,
4587
0x65,0x1c,0x91,0x2f,0xe0,0x23,0xcd,0xe9,0x20,0x3b,0x98,0xee,0xb1,0x93,0x71,0x45,
4588
0x82,0x27,0x12,0xba,0xc5,0xee,0xc0,0x05,0x09,0x1e,0x88,0x75,0x89,0x5d,0x43,0x6f,
4589
0xd8,0x3d,0xf8,0x1f,0x9e,0x8f,0x04,0xef,0xe3,0x1d,0x7c,0x8f,0xe0,0x7a,0xdc,0x82,
4590
0xe3,0xb1,0x06,0xb7,0x23,0x78,0x1d,0xe6,0x74,0x98,0xcb,0x71,0x26,0xfe,0x46,0x7f,
4591
0xbc,0x8d,0x6b,0xf1,0x35,0xee,0xa2,0xcf,0x2b,0xf0,0x91,0xfb,0x94,0x37,0x66,0x25,
4592
0x13,0x2b,0xe8,0xf6,0xfa,0x4e,0x99,0x30,0x47,0x9f,0xd3,0xca,0xeb,0xca,0xf7,0x73,
4593
0xa2,0xae,0xaf,0xd0,0xf3,0x35,0x53,0xf9,0x72,0x9e,0x3e,0xfe,0xe9,0xfb,0x3a,0x9d,
4594
0x9e,0xaf,0xd0,0xf1,0x75,0x29,0x1d,0x5f,0x57,0xd1,0xf1,0x35,0x96,0x8e,0xaf,0xa5,
4595
0xca,0xa7,0x4a,0xa5,0xd2,0x99,0xbe,0xaf,0xc0,0x47,0x4e,0xa0,0xeb,0x2b,0xf4,0x7b,
4596
0x2d,0x50,0xd6,0x28,0xc7,0x2e,0x48,0x26,0x2e,0x5e,0x10,0xb9,0x24,0x77,0x39,0x87,
4597
0xe4,0x01,0xbc,0x11,0x73,0x46,0x66,0xe2,0x89,0x14,0xe3,0x87,0xec,0x8c,0x17,0xd2,
4598
0xd1,0xf9,0x20,0x3d,0x70,0x40,0x2a,0xe0,0x23,0xef,0xc0,0x47,0xd6,0xc2,0x47,0x82,
4599
0xff,0x51,0x17,0xff,0xa3,0x35,0xfe,0x47,0x77,0xfc,0x8f,0x01,0xf8,0x1f,0xa3,0xf0,
4600
0x3f,0xc6,0xe2,0x7f,0xcc,0xc4,0xff,0x08,0xdd,0x5c,0x95,0x7f,0x8b,0xba,0xb9,0xda,
4601
0xd1,0xcd,0x35,0x04,0x3e,0x32,0x02,0x3e,0x72,0x3d,0xdd,0x5c,0xa1,0x97,0x6b,0xe7,
4602
0x77,0x23,0x2f,0xe4,0x36,0x7c,0x90,0x0c,0x7d,0x5b,0xbb,0xd3,0xb3,0xd5,0xc8,0xf5,
4603
0x6b,0x35,0xa1,0x53,0xeb,0x00,0xba,0xb4,0xba,0x2f,0xae,0xea,0xd0,0x5a,0x46,0x6f,
4604
0xd6,0xb7,0xf0,0x91,0x65,0xf4,0x64,0x85,0x8e,0xac,0xe5,0x74,0x63,0xad,0x85,0x8f,
4605
0x7c,0xe0,0xba,0xb0,0xac,0x03,0x6b,0x39,0xbd,0x57,0xd6,0x79,0x15,0x9c,0x90,0x8f,
4606
0x71,0x41,0x3e,0xc7,0x01,0x09,0xfe,0xc7,0x5c,0xfa,0xac,0x0e,0x72,0x3d,0x56,0xa1,
4607
0xbf,0xaa,0x8f,0x32,0xf1,0x33,0xbd,0x6e,0xcb,0x23,0x1f,0x64,0x57,0xe7,0x81,0xd4,
4608
0xc7,0xfd,0x68,0xfb,0x13,0x7c,0xa4,0xbb,0xf3,0x3a,0xaa,0xe3,0x23,0xe6,0x6e,0xf4,
4609
0xc7,0xd7,0xb8,0xc8,0x79,0x1a,0xa3,0x70,0x33,0xee,0xc3,0xc9,0x08,0x3e,0xc6,0x2a,
4610
0xa5,0xf1,0xca,0x64,0xe2,0x0f,0xca,0x78,0x65,0xba,0x32,0x57,0xf9,0x52,0x29,0x5e,
4611
0xa5,0x99,0x46,0x69,0x06,0x1f,0x39,0x4b,0x19,0xa0,0x3c,0xea,0xf8,0x48,0x6a,0xb5,
4612
0x5e,0x4f,0xe5,0x50,0xa5,0xa7,0x72,0x9a,0xf2,0xb7,0xaf,0x92,0x89,0xcf,0x94,0xef,
4613
0x94,0xbf,0x39,0x3e,0xb2,0x4c,0x29,0xf9,0x46,0x6f,0x8f,0xd2,0x4b,0xb9,0x46,0x19,
4614
0xa7,0x4c,0x51,0x66,0x28,0x6f,0x2b,0xc7,0xad,0xd5,0xbf,0xa3,0x72,0xb9,0xf2,0x02,
4615
0x7c,0xe4,0x7d,0x65,0x99,0xb2,0x56,0xf9,0xfd,0x3a,0xbd,0xff,0xe9,0xbe,0x0a,0x7c,
4616
0x24,0xb8,0x24,0xf5,0x70,0x48,0x16,0xe1,0x8e,0x04,0x6f,0xe4,0x70,0x7c,0x91,0xe0,
4617
0x8a,0x04,0x3e,0x72,0x45,0x22,0xea,0xb7,0xfa,0xbe,0xb2,0xb6,0x52,0x27,0x91,0xdc,
4618
0xb6,0xee,0xb6,0x35,0xeb,0x26,0xf5,0x43,0xba,0x24,0x5d,0x90,0x2a,0x48,0x15,0xa6,
4619
0xd2,0x19,0x3d,0x26,0xeb,0x26,0x53,0x7a,0x8a,0x7e,0x91,0x2e,0x29,0xd4,0x4f,0x85,
4620
0x99,0xf4,0x86,0x8f,0x59,0xfd,0xc0,0xaf,0x33,0xe1,0x17,0xd9,0xdc,0x8f,0xe9,0x92,
4621
0x6c,0x0d,0x7b,0xac,0x51,0x9c,0x2e,0x2a,0x29,0x4a,0x15,0xa5,0xb3,0x45,0xd9,0xe2,
4622
0x92,0xe2,0xa2,0xf0,0x53,0xf8,0xb5,0x52,0x58,0x14,0xfe,0x4b,0x8f,0x7a,0xb6,0x74,
4623
0x0d,0xf7,0x47,0xb2,0x35,0x8a,0x8a,0x8a,0xc3,0x33,0x66,0x33,0x1b,0x3e,0x46,0x0f,
4624
0xb9,0x5f,0x65,0xa3,0x5f,0x95,0xe8,0x31,0x6b,0xbf,0x11,0x7e,0x27,0x9b,0xfb,0xaf,
4625
0xd8,0xb3,0x47,0xcf,0x9f,0xf5,0xcf,0xcb,0x73,0xac,0x7f,0xee,0xaa,0x87,0x2c,0xd1,
4626
0x1b,0x9e,0xb5,0x17,0x93,0xfb,0x8b,0xa3,0xa7,0xa7,0x79,0xe6,0x6c,0x55,0xb2,0xee,
4627
0x95,0x5a,0xff,0x77,0x65,0x79,0x59,0xfa,0xb9,0x64,0xc3,0x57,0x3d,0x53,0xf5,0x1a,
4628
0x66,0xd3,0xeb,0x7f,0x95,0xf5,0x4f,0xae,0xf6,0xed,0xce,0x6c,0xf8,0x4a,0xe6,0xde,
4629
0xf3,0x35,0x33,0xe9,0xcc,0xfa,0x97,0xec,0xfe,0x44,0x78,0x91,0xe9,0x74,0x36,0x99,
4630
0x75,0x2f,0x34,0x7a,0x86,0x74,0xee,0x9f,0x2a,0xf7,0x66,0xac,0x7f,0xb9,0xbc,0xae,
4631
0xd9,0xec,0xfa,0xe7,0x8a,0xbf,0x02,0xfe,0x3d,0x51,0xf5,0xb4,0xaa,0x87,0x74,0xf4,
4632
0xea,0xf0,0x73,0xcd,0x64,0xa6,0x46,0xba,0x66,0xdd,0xed,0xea,0xd4,0xae,0xb5,0x45,
4633
0xaa,0x24,0x9d,0xd2,0x13,0xb6,0xd9,0x72,0xab,0xad,0x93,0x85,0x99,0xc2,0x82,0x74,
4634
0x2e,0x25,0xd9,0x74,0xfc,0x63,0x49,0xaf,0xf3,0xfa,0x5f,0xa7,0x0b,0x4a,0xa2,0x9f,
4635
0xed,0x43,0x2e,0x9d,0x7b,0x85,0xd3,0xeb,0xdf,0xf3,0xbc,0x17,0xd2,0xb9,0x87,0x9a,
4636
0xf6,0xbb,0xb9,0x9f,0xab,0x3e,0x1c,0x7f,0xfc,0x22,0xf8,0x3d,0x7d,0xf4,0x45,0x6f,
4637
0x7f,0xf4,0x9c,0xf6,0x16,0xa5,0xb3,0xb9,0xd7,0x21,0xf6,0x66,0x67,0xab,0xfe,0x99,
4638
0xfd,0x7f,0xfe,0xf8,0x9d,0x93,0xc9,0xa4,0x37,0xfc,0xc8,0xcb,0xe8,0x23,0xb9,0xa0,
4639
0x46,0xee,0xa1,0x28,0x6d,0x8f,0xe1,0x65,0xa7,0x72,0x8f,0xfa,0x54,0x4b,0xeb,0x87,
4640
0xa2,0xa2,0xe4,0x86,0x9f,0x75,0xb9,0x3f,0x5a,0xa2,0xa7,0xa5,0xab,0xde,0xbb,0x99,
4641
0xe8,0x9d,0x10,0x5e,0x58,0x61,0x26,0x53,0xed,0x87,0x44,0xf4,0x12,0xab,0x1e,0xd2,
4642
0xb9,0x1f,0xf5,0x71,0x9b,0xfb,0x31,0xf7,0x6b,0x7b,0x62,0xee,0x35,0xca,0x16,0x17,
4643
0xd7,0xc8,0xea,0xbf,0x8b,0xc3,0xd3,0xf5,0xa9,0x98,0x2e,0xd2,0xe7,0x5d,0xee,0x93,
4644
0xb1,0x46,0x0d,0xde,0x39,0xd9,0x6a,0xde,0xe6,0x0d,0x3f,0x2c,0x63,0x1f,0xa3,0x3f,
4645
0xfa,0x34,0xcd,0x64,0x32,0xf6,0x39,0x97,0xcd,0xfc,0xf8,0xef,0x88,0xbf,0x8f,0x37,
4646
0x78,0x81,0xe9,0xea,0x5e,0x90,0x7f,0xf7,0x56,0xfd,0x66,0xbe,0x0f,0x5b,0xf7,0x0a,
4647
0x65,0xfd,0x4b,0xc8,0x44,0x5f,0x28,0xb2,0x1b,0xfe,0x2d,0x99,0xd8,0x2b,0x17,0xbe,
4648
0xf4,0x65,0x36,0xfc,0x04,0xca,0x64,0xaa,0x3e,0xe5,0xfd,0xdb,0x99,0xae,0xfe,0x9f,
4649
0x24,0x9b,0x49,0xea,0xe3,0x3d,0xf7,0x41,0xba,0xfe,0xe5,0x27,0xb3,0xf6,0xa1,0x97,
4650
0xb5,0x2f,0x98,0xd5,0x3d,0x54,0xf7,0x81,0x5b,0x58,0xf5,0xb6,0x65,0xd3,0xbc,0x11,
4651
0x1b,0xbc,0x87,0x4a,0xdc,0x97,0xc6,0xaa,0x37,0xbd,0x46,0xf4,0x65,0x55,0xff,0xc8,
4652
0x1b,0x7d,0x88,0x3e,0xa1,0xd2,0x85,0xe9,0xaa,0xaf,0xea,0x99,0xdc,0x53,0x32,0xe9,
4653
0x6a,0x1e,0x0a,0xab,0x5e,0xf5,0x64,0xf8,0x52,0x63,0xf7,0xac,0x8f,0x80,0x27,0x6f,
4654
0xea,0xbd,0xe6,0x76,0x8f,0xb9,0xdd,0x57,0x6e,0xf7,0x93,0xc7,0xef,0x23,0x8f,0xdf,
4655
0x43,0x6e,0xf7,0x8b,0xdb,0xbd,0xe2,0x76,0x9f,0xb8,0xdd,0x1b,0x6e,0xf7,0x84,0xdb,
4656
0xfd,0xe0,0x76,0x2f,0xb8,0xdd,0x07,0x6e,0xf7,0x80,0xdb,0xfd,0xdf,0x76,0xcf,0xb7,
4657
0xbf,0xd7,0xdb,0xbc,0xb7,0x0e,0xdc,0xd7,0xdd,0xdd,0xdd,0xc3,0x6d,0xf7,0x6f,0x1b,
4658
0xc7,0xb5,0xfb,0xb2,0xa7,0x55,0x73,0x3f,0xf6,0x6c,0x77,0x1f,0xb6,0xdd,0x7f,0xfd,
4659
0x43,0xcc,0x61,0xf3,0xf7,0x54,0xff,0xd4,0xfd,0xd4,0x76,0x0f,0xb5,0xbf,0x7f,0x7a,
4660
0x84,0xbb,0x47,0x7a,0x9a,0xbb,0x37,0xda,0x7b,0x69,0x76,0x2f,0xf4,0xda,0x18,0x6b,
4661
0xed,0xe0,0xb8,0x6a,0xfc,0xbe,0x66,0xef,0x9c,0xd9,0x7d,0xcc,0x76,0xff,0xf2,0xb4,
4662
0x6a,0xee,0x47,0x9e,0xed,0xee,0x43,0x4e,0xc0,0x44,0xed,0x5e,0xe3,0x8e,0x1b,0xb9,
4663
0xc7,0xd8,0xee,0x2b,0xbe,0x92,0x7b,0x89,0xed,0xbe,0xe1,0x69,0xee,0x5e,0x61,0xbb,
4664
0x4f,0xd8,0xdf,0x23,0x6c,0xf7,0x06,0xfb,0x7b,0x82,0x0b,0xdc,0x3d,0xc0,0x1d,0xab,
4665
0xb9,0xf7,0xb7,0x9b,0xbb,0xdf,0xd7,0xee,0xf5,0x35,0xe6,0xe9,0xef,0xe5,0xad,0xee,
4666
0x3e,0x5e,0xbb,0x87,0xd7,0xee,0xdf,0xb5,0x7b,0x77,0xed,0x9e,0x5d,0xbb,0x2f,0xd7,
4667
0xee,0xc9,0xb5,0xfb,0x70,0xed,0xde,0xdb,0x8d,0xdd,0x77,0x7b,0x7e,0xec,0x3e,0xdb,
4668
0x7c,0xf7,0xd8,0x36,0x86,0x4d,0x1e,0x0b,0x9b,0xb4,0xfb,0x65,0xed,0x5e,0x59,0xbb,
4669
0x4f,0xd6,0xee,0x91,0x1d,0x0e,0x9b,0xb4,0x7b,0x61,0xef,0x80,0x51,0xda,0xbd,0xaa,
4670
0xe6,0x52,0x99,0x47,0x65,0xf7,0x9b,0xda,0x7d,0xa6,0x13,0x61,0x81,0x76,0x0f,0x69,
4671
0xfc,0xfe,0x51,0xeb,0x87,0xb3,0xfb,0x44,0x77,0x73,0xf7,0x83,0x06,0xae,0xb7,0x9d,
4672
0xe3,0x75,0xc6,0xe9,0xfc,0x3d,0x9b,0xe5,0xee,0x1e,0x4d,0xf3,0x95,0xba,0xc4,0xee,
4673
0xbb,0x1c,0x0e,0x87,0x1b,0x07,0x73,0x0b,0x6c,0x6d,0x2f,0x98,0x9a,0xbf,0x07,0x72,
4674
0xa9,0xbb,0xef,0xf1,0x8b,0x18,0x3f,0xb3,0xfb,0x19,0xe7,0xc1,0x93,0xec,0x1e,0x40,
4675
0xbb,0xd7,0xcf,0xee,0xe3,0x6b,0x04,0x27,0xb1,0xfb,0xf3,0x06,0xc0,0x22,0xec,0xfe,
4676
0x39,0xbb,0x67,0xce,0xee,0x95,0xb3,0xfb,0xdd,0xec,0x5e,0x37,0xbb,0xcf,0x6d,0xcf,
4677
0xd8,0xbd,0x6d,0x76,0x5f,0xdb,0x44,0x18,0x83,0xdd,0xcb,0x66,0xf7,0xaf,0xd9,0x7d,
4678
0x6b,0x5d,0xe1,0x0b,0xde,0xbd,0xa8,0x70,0xf7,0xa0,0x35,0x84,0x19,0xd8,0xbd,0x65,
4679
0xc6,0x0b,0x2e,0x73,0x1e,0x45,0xb9,0xbb,0x5f,0xcc,0xee,0x15,0xb3,0xfb,0xc4,0xec,
4680
0x1e,0xb1,0x65,0xdc,0x0b,0x66,0x9c,0xe0,0x43,0x77,0xff,0x56,0x38,0xff,0xb7,0xfb,
4681
0xb2,0xe2,0xf7,0x5a,0xd9,0x3d,0x50,0x76,0xef,0x93,0xdd,0xe3,0x94,0xef,0xde,0xa1,
4682
0xf8,0xfd,0x42,0x76,0x7f,0x90,0xdd,0xff,0x63,0xf7,0xf9,0xd8,0xbd,0x3d,0x76,0x2f,
4683
0x8f,0xdd,0xc7,0x63,0xf7,0xee,0xd8,0x7d,0x3b,0x09,0xb7,0xaf,0x7e,0x88,0xbb,0x3f,
4684
0xc7,0xee,0xcd,0xb1,0x3d,0xf5,0xf2,0xd8,0x3d,0x38,0x76,0xef,0x4d,0x7d,0xce,0x5c,
4685
0xed,0x3e,0x1b,0xbb,0xbf,0xc6,0x76,0xd2,0x27,0x70,0x2f,0xcd,0xcb,0xb1,0x73,0xd7,
4686
0x26,0xb1,0x7b,0x63,0xec,0xbe,0x98,0x85,0x9c,0x9f,0x26,0x38,0x3b,0xb5,0xfb,0x5a,
4687
0x3a,0xe6,0xb9,0x97,0xc5,0xee,0x63,0xc9,0x77,0x0f,0xcb,0xa4,0x4d,0xb8,0x57,0x65,
4688
0x9e,0xbb,0x37,0xc5,0xee,0x4b,0x69,0xcd,0xb9,0xa8,0xdd,0x77,0x52,0xce,0xb9,0xe7,
4689
0x63,0xee,0xfe,0x91,0x0a,0x77,0xbf,0x48,0x29,0xe7,0x9a,0x8f,0x70,0x66,0xb9,0x0b,
4690
0xe7,0x91,0x4d,0x38,0x83,0xac,0xee,0xbe,0x8c,0x8e,0xee,0x5e,0x0c,0x3b,0x77,0x7c,
4691
0xcd,0xdd,0x73,0xb1,0xc8,0xdd,0x63,0x61,0xf7,0x57,0xf8,0xfd,0x6b,0x7f,0x4f,0x45,
4692
0x4f,0xce,0x16,0xaf,0xe3,0x4c,0xb1,0x2f,0xe7,0x86,0xcd,0xdd,0x7d,0x10,0x9d,0x62,
4693
0xf7,0x3c,0x84,0x73,0xc1,0x8d,0xdd,0xd3,0x60,0xf7,0x33,0x54,0x77,0xff,0xc2,0x9f,
4694
0xdc,0xbd,0x09,0x6b,0x62,0xf7,0x23,0xd8,0xbd,0x08,0xad,0xdc,0xfd,0x07,0x07,0xba,
4695
0xfb,0x0d,0xec,0x7e,0x02,0xbb,0x97,0xa0,0x1e,0xe7,0x78,0x76,0x6f,0x80,0xdd,0x17,
4696
0x60,0x7d,0xfe,0xf1,0x1e,0xff,0x78,0x5f,0xbf,0xf5,0xe1,0xff,0x54,0x0f,0xfe,0x2f,
4697
0xda,0x7f,0xbf,0xb9,0x3d,0xf0,0x9b,0xd8,0xeb,0x6e,0x7d,0xee,0xd6,0xe3,0x6e,0x3d,
4698
0xed,0xd6,0xcf,0x6e,0x3d,0xec,0xd6,0xbb,0x6e,0xbd,0xea,0xd6,0xa7,0x6e,0x3d,0xea,
4699
0xd6,0x9f,0x6e,0x3d,0xe8,0xd6,0x7f,0x6e,0xbd,0xdc,0x61,0x97,0x32,0xc1,0x9c,0x79,
4700
0x8b,0x9b,0x2d,0x9f,0x63,0xa6,0x0c,0xf3,0xe4,0xce,0x99,0xa8,0x8f,0x7a,0x0f,0x65,
4701
0x1f,0xa5,0xbe,0xd2,0x40,0x69,0xa8,0x34,0x52,0x9a,0x2b,0x2d,0x5d,0x4f,0xf5,0xa1,
4702
0xca,0x61,0xcc,0xa0,0xe7,0xb9,0x9e,0x86,0x0b,0x94,0x8b,0x95,0x6b,0x95,0x3b,0x94,
4703
0x0a,0x65,0x86,0x32,0x53,0x99,0xa5,0xcc,0x56,0xe6,0x28,0x73,0x95,0x79,0xca,0x7c,
4704
0xf6,0x17,0xdf,0x64,0x6e,0xfd,0x5f,0xd7,0xe7,0xb0,0x96,0x5e,0xeb,0xda,0x6e,0x67,
4705
0x31,0x74,0x3a,0xd4,0x55,0x76,0x54,0xea,0x29,0xbb,0x2a,0x0d,0x94,0x86,0x4a,0x23,
4706
0xa5,0xb1,0xd2,0x44,0x69,0xca,0x7e,0xa3,0xf5,0x3f,0xfc,0x46,0xe9,0xa5,0xfc,0x56,
4707
0x39,0x5b,0x39,0x57,0x39,0x5f,0x19,0xa4,0x0c,0x56,0x2e,0x50,0x2e,0x56,0x2e,0x65,
4708
0x2e,0x7e,0x85,0xb9,0x78,0xad,0x9b,0x89,0x77,0x62,0x16,0x6e,0x48,0x17,0x44,0x67,
4709
0xe5,0x10,0xe5,0x50,0xe5,0x30,0xe5,0x70,0xe5,0x68,0xe5,0x18,0xe5,0x58,0xe6,0xe4,
4710
0xd0,0x13,0xd1,0x4f,0x39,0x43,0x39,0x53,0x39,0x8b,0xde,0x88,0x11,0xca,0xd5,0x74,
4711
0x68,0xdf,0xc4,0xae,0xa4,0xf5,0x48,0x3c,0xac,0x8c,0x57,0x1e,0x53,0x1e,0x57,0x26,
4712
0x28,0x93,0x95,0xa7,0x99,0xb5,0xc3,0x9c,0x6d,0x33,0x76,0x67,0xf6,0x25,0x7b,0x32,
4713
0x5f,0x5f,0xc9,0x4c,0x3d,0x83,0x19,0x7a,0x89,0x9b,0x99,0x3b,0x54,0xd3,0xe9,0x30,
4714
0xd0,0xcd,0xc4,0x53,0x5d,0x3f,0x83,0xcd,0xbf,0xd6,0xc1,0xd0,0x81,0x1d,0xc2,0xce,
4715
0x6e,0xc6,0xed,0xc7,0x5c,0x5b,0xc1,0x1c,0xeb,0xe7,0xd7,0x8e,0xb1,0x6e,0x83,0x7e,
4716
0xcc,0xa9,0x61,0x3e,0x9d,0xce,0x6c,0x3a,0x8b,0x59,0x34,0xc1,0xec,0xd9,0x99,0x39,
4717
0xb3,0x1f,0xb3,0xe5,0x2b,0xae,0x53,0xc0,0xe6,0xc6,0xae,0x6e,0x56,0x7c,0x89,0x19,
4718
0xb1,0xb5,0x9b,0x0b,0xcf,0xc7,0xf1,0xbf,0xda,0xb9,0xfd,0x61,0xf6,0x6b,0x8a,0xc7,
4719
0xbf,0x3f,0xfe,0xfe,0xf1,0xcc,0x7f,0xe7,0x33,0xe7,0x8d,0x64,0xd6,0xb3,0xf9,0x6e,
4720
0x2b,0xe6,0xba,0x23,0x99,0xe7,0x26,0xe2,0xc1,0xbf,0x80,0xff,0x1e,0xe6,0xb9,0x1a,
4721
0xdb,0x47,0xfb,0x5c,0x25,0xcc,0x73,0xbb,0x55,0xe3,0xb8,0xef,0x86,0xd7,0xde,0x02,
4722
0x97,0xdd,0x66,0xba,0x63,0x9d,0x9b,0xde,0x0f,0x27,0x7d,0xb0,0x9b,0xeb,0x12,0xcc,
4723
0x73,0x6d,0xb8,0xeb,0xfc,0x40,0xe6,0xba,0x61,0x38,0xe7,0x0f,0xe1,0x9a,0x7f,0x8c,
4724
0x63,0xbe,0x1c,0xb7,0xbc,0x09,0x3e,0xf9,0x3c,0xe6,0xba,0x25,0x6e,0xa6,0xfb,0x86,
4725
0x59,0xae,0xc4,0xed,0x27,0x35,0xc2,0xc3,0xee,0x8f,0x4b,0xbd,0xa2,0x49,0xd5,0x4c,
4726
0xd7,0x88,0x59,0xce,0xee,0x10,0xbe,0x9b,0xd9,0x2d,0xe5,0xe6,0xb5,0xbd,0xdd,0xdd,
4727
0xba,0x83,0x70,0x64,0x17,0xb9,0xb9,0xac,0x2b,0xf3,0xd8,0x04,0x1c,0xd8,0xa9,0x6e,
4728
0x16,0xdb,0x17,0xc7,0xd5,0x66,0xb1,0xcb,0xdd,0xfc,0xf5,0x57,0xe6,0xae,0x19,0x38,
4729
0xab,0x61,0xce,0xfa,0x88,0x3d,0x0b,0x9b,0xb1,0x12,0xcc,0x56,0x61,0x67,0x21,0x78,
4730
0x97,0x36,0x5b,0x5d,0x58,0xb0,0xa1,0x77,0x68,0xae,0x61,0xf0,0x0b,0x9f,0x77,0xdd,
4731
0x84,0xb3,0x95,0x39,0xca,0x02,0xe5,0x2d,0xe5,0x6d,0xe5,0x7d,0xe5,0x03,0x65,0xb1,
4732
0xbb,0xb3,0x31,0xf8,0x88,0x2b,0x8a,0xa3,0xbe,0xc2,0x2b,0x95,0xe1,0xca,0x08,0xe5,
4733
0x6a,0x65,0x94,0x72,0x9d,0x72,0x83,0x72,0xa3,0x72,0x93,0x32,0x1a,0x1e,0x1f,0x5c,
4734
0xc5,0x71,0x25,0x91,0x9f,0x98,0x54,0xf6,0x70,0xf7,0x37,0x9e,0xc5,0xdc,0x16,0x1c,
4735
0xc4,0x99,0x74,0x12,0xbe,0xea,0x1c,0xc4,0xe0,0x1f,0xb6,0x54,0x5a,0x39,0x0f,0xf1,
4736
0x68,0x5c,0xc4,0x21,0xca,0x85,0xcc,0x75,0xc1,0x47,0x7c,0x42,0x99,0xa8,0x4c,0x52,
4737
0x26,0x2b,0x53,0x94,0x67,0x94,0x69,0xca,0x0c,0xe5,0x59,0xfa,0x0b,0x5f,0x56,0x5e,
4738
0x81,0xd1,0x27,0x99,0x03,0x6d,0xfe,0xbb,0x02,0x3f,0x71,0xb2,0x9b,0xf9,0xea,0xe3,
4739
0x20,0xda,0x8c,0xf7,0x14,0xb3,0x5d,0x98,0xe9,0x9a,0xc3,0xcd,0xdb,0xb8,0x99,0x6e,
4740
0x21,0xbe,0x60,0x82,0x59,0xae,0xcc,0x39,0x7f,0x53,0xe0,0xd5,0xf3,0xdc,0xec,0xb5,
4741
0x1f,0xde,0x9e,0xcd,0x5e,0x13,0xe0,0xcf,0xd3,0xf1,0xf2,0x9e,0xc0,0xc3,0x9b,0xce,
4742
0xec,0xd5,0x12,0xae,0xdc,0x89,0xd9,0x6b,0x1c,0x6e,0x9d,0xcd,0x60,0xbb,0xe2,0xcf,
4743
0x05,0x77,0xae,0xb9,0xf9,0x72,0xcc,0x5e,0x07,0x39,0xef,0x6d,0x11,0x33,0x56,0x4b,
4744
0x66,0x2b,0x9b,0xa9,0x7a,0x31,0x53,0xfd,0x37,0x33,0x55,0x3f,0x98,0x6c,0x69,0x6c,
4745
0xa6,0x7a,0x18,0x1f,0xed,0xc9,0x9d,0x7f,0xec,0x9f,0x75,0x65,0x6e,0xba,0xd5,0xcd,
4746
0x4c,0x6b,0x98,0x95,0xda,0xc0,0x46,0x6d,0x36,0x2a,0x65,0x26,0xaa,0x87,0xf7,0xb5,
4747
0x92,0x59,0xa8,0x3b,0xb3,0xcf,0xdf,0x99,0x75,0xc6,0x4c,0xad,0x72,0xa4,0xea,0xe3,
4748
0x44,0x0d,0x66,0x9e,0x79,0x98,0x39,0xa6,0x37,0x73,0x4a,0x7b,0x37,0x9b,0xac,0xf7,
4749
0x83,0xaa,0xf1,0x81,0x6c,0xee,0xb0,0x79,0xe3,0x33,0xe6,0x8c,0x0f,0xdd,0x6c,0x61,
4750
0x33,0x85,0x79,0x3a,0xde,0x15,0x09,0x33,0x45,0x38,0xbb,0x0a,0xe7,0x56,0x76,0x66,
4751
0xf5,0x2c,0xe7,0x54,0xe1,0x8c,0x6a,0x47,0x37,0x53,0xec,0x5d,0xcd,0x4c,0xd1,0x4c,
4752
0x69,0xe1,0xee,0xbf,0xe8,0xca,0x4c,0x61,0x9e,0x83,0xb9,0x0d,0x83,0x95,0x8b,0x94,
4753
0x6b,0x94,0xdb,0x95,0xe9,0xcc,0x14,0xcf,0x2a,0xaf,0x56,0x33,0x53,0xbc,0xe6,0xee,
4754
0xcc,0x78,0x8f,0x73,0xb0,0xa5,0xce,0x81,0xf8,0xae,0x9a,0x99,0x62,0x1b,0x65,0x07,
4755
0x65,0x17,0x66,0x8a,0xfa,0x79,0x66,0x8a,0x66,0xce,0x99,0x08,0x33,0xc5,0xf1,0x4a,
4756
0x6f,0xa5,0xbf,0x72,0x8e,0x32,0xd0,0xcd,0x14,0x43,0x94,0x8b,0x94,0x4b,0x94,0x2b,
4757
0x38,0x67,0x33,0xb7,0xc2,0x66,0x8a,0x1d,0x38,0x5f,0xab,0xcf,0xb9,0x5a,0x98,0x29,
4758
0x0e,0x56,0xba,0xba,0x99,0xe2,0x28,0x37,0x53,0x98,0x5f,0x11,0x66,0x8a,0xd3,0xdc,
4759
0x4c,0x11,0x5c,0x8b,0xe1,0xca,0x48,0x66,0x8a,0x1b,0xdd,0x4c,0x11,0xce,0xe7,0xc6,
4760
0x2a,0x8f,0x32,0x53,0x94,0x2b,0x4f,0x28,0x93,0x98,0x29,0x5e,0xe2,0xec,0x2e,0xe5,
4761
0xce,0xed,0x0e,0x65,0xa6,0x38,0xce,0x9d,0xd7,0x4d,0xe5,0x8c,0x6e,0xb6,0x3b,0x8b,
4762
0x4b,0x31,0x53,0xc4,0x3d,0x08,0x3b,0x6b,0x1b,0xce,0x4c,0x61,0x4e,0xc3,0x6c,0xce,
4763
0xd3,0x2a,0x63,0x33,0x45,0x17,0xe7,0x22,0x9c,0xf2,0x13,0x33,0x45,0x59,0xcc,0x07,
4764
0x38,0xa5,0x9a,0x99,0x62,0x36,0x67,0x5b,0x49,0xce,0xb2,0xba,0x30,0x53,0x9c,0xe2,
4765
0x66,0x8a,0xd7,0xdd,0x4c,0xd1,0xce,0x9d,0x41,0x4d,0xe5,0xdc,0x69,0x87,0xd8,0x4c,
4766
0x31,0x94,0xf3,0xa5,0x6b,0xdc,0x3e,0x7c,0x98,0x29,0x4a,0xd9,0x7d,0x6f,0xc7,0xb9,
4767
0x52,0x2f,0xce,0x93,0xec,0xec,0xe8,0x6a,0x37,0x53,0x84,0xf3,0xa2,0x6d,0xd8,0x29,
4768
0x3f,0x8a,0xf3,0xa1,0x27,0xd9,0x1d,0x7f,0xc1,0x9d,0x13,0xd9,0x4c,0x61,0xe7,0x44,
4769
0x17,0x57,0xb3,0x17,0xbe,0x07,0xbb,0xe0,0x2d,0x38,0x27,0xda,0xde,0xcd,0x14,0x27,
4770
0xb9,0x99,0xe2,0x1c,0x77,0x5e,0x64,0x7b,0xdb,0xad,0xe8,0xb2,0xb1,0x99,0x62,0x30,
4771
0xbb,0xda,0xf7,0xb3,0xa3,0x6d,0xe7,0x44,0x9f,0x30,0x53,0x84,0x7d,0xec,0x96,0x9c,
4772
0x17,0xcd,0x67,0xdf,0x7a,0xa9,0x9b,0x29,0xc2,0xf9,0x50,0xa5,0x9b,0x29,0x6a,0xb3,
4773
0xd3,0x7c,0x2a,0xbb,0xca,0xe1,0xbc,0xc8,0xce,0x8a,0xc2,0x19,0x51,0x53,0xce,0x86,
4774
0x06,0x71,0x26,0x74,0x8f,0x3b,0x0b,0xb2,0x99,0x62,0x1f,0x66,0x8a,0xf3,0x99,0x29,
4775
0x9e,0x77,0xe7,0x3d,0x4d,0xd9,0x23,0x1d,0xce,0x4c,0x31,0x99,0x9d,0xd1,0x30,0x53,
4776
0x34,0x63,0x37,0xb4,0x4d,0x35,0x33,0xc5,0x44,0xce,0x72,0xec,0x1c,0x67,0x79,0x9e,
4777
0x99,0xa2,0x36,0x67,0x35,0x61,0xa6,0x58,0xe7,0x66,0x8a,0x70,0x4e,0xe3,0x77,0xf5,
4778
0xec,0x5c,0xe6,0x39,0x37,0x53,0xbc,0xc2,0x4c,0x31,0x5f,0x79,0x93,0x99,0xe2,0x3d,
4779
0x66,0x8a,0x45,0x6e,0xa6,0x08,0x67,0x38,0x9f,0x57,0x33,0x53,0x8c,0x54,0xae,0x65,
4780
0xa6,0xb8,0xde,0xcd,0x14,0x37,0xbb,0x99,0xe2,0x51,0x65,0x3c,0x33,0xc5,0xee,0x6e,
4781
0xa6,0xa8,0xcf,0x59,0xd0,0xa3,0xae,0xef,0xf8,0x45,0xce,0x83,0x6c,0x6f,0xaf,0x05,
4782
0x33,0x45,0x17,0xce,0x85,0x8e,0x62,0xa6,0x18,0xac,0x5c,0xe0,0xf6,0xf8,0xc2,0x4c,
4783
0x31,0x41,0x79,0x8a,0x99,0xe2,0x69,0x65,0x2a,0x33,0xc5,0x74,0x66,0x8a,0x99,0x79,
4784
0x66,0x0a,0x3b,0x57,0x1a,0xc2,0x5e,0xdf,0x53,0xee,0x2c,0x29,0xc5,0xee,0x5e,0x2b,
4785
0x66,0x8a,0x2b,0xd9,0xd3,0x9b,0xc5,0x4c,0xb1,0x2f,0x33,0x45,0xdb,0xd8,0x4c,0xf1,
4786
0x29,0xfb,0x75,0x1d,0x98,0x29,0x6c,0x4f,0xae,0x22,0x36,0x53,0x84,0xb3,0x9c,0x4e,
4787
0xec,0xba,0xd9,0x4c,0x31,0x89,0x99,0xa2,0x82,0x33,0x9d,0x27,0xd9,0x5d,0xab,0xe0,
4788
0x2c,0xa7,0x1d,0x33,0x45,0x99,0x9b,0x29,0x9e,0x8c,0xcd,0x14,0x7b,0x73,0xbe,0xd3,
4789
0x96,0xf3,0x9d,0x0e,0x6e,0xa6,0xb0,0x5d,0xb1,0x30,0x53,0x14,0xb3,0x13,0x66,0x67,
4790
0x35,0xc7,0x72,0x4e,0x73,0x9b,0x3b,0xa7,0x39,0x95,0x99,0xc2,0x76,0xba,0x3a,0x71,
4791
0x46,0x53,0xce,0x0e,0x57,0x38,0xa7,0x89,0xef,0x6c,0x75,0xe5,0x1c,0xc6,0xcf,0x14,
4792
0x5f,0xb0,0x7b,0xd5,0x2e,0x36,0x53,0x94,0x71,0xc6,0xd2,0x90,0x33,0x96,0x70,0xbe,
4793
0x62,0x67,0x2b,0x76,0x96,0x72,0x37,0x7b,0x47,0xb6,0x57,0xd4,0x80,0xf3,0x92,0xe1,
4794
0x9c,0x8f,0x84,0xb3,0x91,0x2e,0x9c,0x85,0xb4,0x71,0x67,0x1e,0x57,0xb9,0x9d,0x9a,
4795
0xea,0x76,0x68,0xc2,0x4c,0x61,0xe7,0x18,0xe1,0xfc,0x22,0x9c,0x5d,0xac,0x70,0x33,
4796
0x85,0x9d,0x55,0xd8,0x6e,0xcb,0x11,0xcc,0x14,0xb6,0x5f,0x51,0xb8,0xfe,0x21,0x05,
4797
0xf3,0x4d,0x25,0x95,0xc2,0x54,0x61,0x3a,0x9d,0x72,0x8f,0xe9,0xf0,0x2c,0xe9,0x94,
4798
0x9e,0x5c,0xe8,0x9f,0x5c,0xe8,0x9f,0x49,0x7f,0x28,0x59,0x18,0x3d,0x9f,0xfd,0x76,
4799
0x2a,0xf7,0x67,0x93,0xa9,0xdc,0xef,0xf2,0x37,0x16,0xfe,0xf3,0x1f,0x52,0x7a,0x3d,
4800
0x52,0xb9,0xc7,0x4d,0x7a,0x48,0x56,0xf7,0x57,0x14,0x6c,0xea,0xcb,0x4a,0xa7,0xd3,
4801
0x05,0xe9,0x54,0x41,0xf4,0x5e,0x4a,0x6d,0xf8,0x5e,0xcb,0x3d,0x99,0xf7,0x5c,0x41,
4802
0x61,0xf4,0x5e,0xc8,0xfd,0xc8,0x73,0xe4,0x7e,0x28,0x28,0xfc,0xf5,0x3c,0xe4,0xde,
4803
0x63,0xff,0x07,
4804
};
4805
}  // namespace ada::idna::table_blob
4806
#endif
4807
/* end file src/table_blob.inc */
4808
4809
#include <atomic>
4810
#include <bit>
4811
#include <cstdint>
4812
#include <cstddef>
4813
#include <new>
4814
4815
namespace ada::idna {
4816
4817
// table_blob.inc is packed little-endian (see scripts/pack_tables.py). After
4818
// inflate the multi-byte sections must be converted to host endianness so
4819
// big-endian platforms (s390x) can load uint16_t/uint32_t/uint64_t natively.
4820
// CRC is checked on the raw little-endian payload before any conversion.
4821
namespace detail {
4822
4823
template <typename T>
4824
0
inline void bswap_inplace(T* data, size_t count) noexcept {
4825
0
  if constexpr (std::endian::native == std::endian::little) {
4826
0
    (void)data;
4827
0
    (void)count;
4828
0
    return;
4829
0
  }
4830
0
  for (size_t i = 0; i < count; ++i) {
4831
0
    if constexpr (sizeof(T) == 2) {
4832
0
#if defined(__GNUC__) || defined(__clang__)
4833
0
      data[i] =
4834
0
          static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(data[i])));
4835
0
#else
4836
0
      const auto v = static_cast<uint16_t>(data[i]);
4837
0
      data[i] = static_cast<T>(static_cast<uint16_t>((v >> 8) | (v << 8)));
4838
0
#endif
4839
0
    } else if constexpr (sizeof(T) == 4) {
4840
0
#if defined(__GNUC__) || defined(__clang__)
4841
0
      data[i] =
4842
0
          static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(data[i])));
4843
0
#else
4844
0
      auto v = static_cast<uint32_t>(data[i]);
4845
0
      v = ((v & 0x000000FFu) << 24) | ((v & 0x0000FF00u) << 8) |
4846
0
          ((v & 0x00FF0000u) >> 8) | ((v & 0xFF000000u) >> 24);
4847
0
      data[i] = static_cast<T>(v);
4848
0
#endif
4849
0
    } else if constexpr (sizeof(T) == 8) {
4850
0
#if defined(__GNUC__) || defined(__clang__)
4851
0
      data[i] =
4852
0
          static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(data[i])));
4853
0
#else
4854
0
      auto v = static_cast<uint64_t>(data[i]);
4855
0
      v = ((v & 0x00000000000000FFull) << 56) |
4856
0
          ((v & 0x000000000000FF00ull) << 40) |
4857
0
          ((v & 0x0000000000FF0000ull) << 24) |
4858
0
          ((v & 0x00000000FF000000ull) << 8) |
4859
0
          ((v & 0x000000FF00000000ull) >> 8) |
4860
0
          ((v & 0x0000FF0000000000ull) >> 24) |
4861
0
          ((v & 0x00FF000000000000ull) >> 40) |
4862
0
          ((v & 0xFF00000000000000ull) >> 56);
4863
0
      data[i] = static_cast<T>(v);
4864
0
#endif
4865
0
    } else {
4866
0
      static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
4867
0
    }
4868
0
  }
4869
0
}
Unexecuted instantiation: void ada::idna::detail::bswap_inplace<unsigned short>(unsigned short*, unsigned long)
Unexecuted instantiation: void ada::idna::detail::bswap_inplace<unsigned int>(unsigned int*, unsigned long)
Unexecuted instantiation: void ada::idna::detail::bswap_inplace<unsigned long>(unsigned long*, unsigned long)
4870
4871
// Convert every multi-byte section of the inflated little-endian blob to host
4872
// order. Single-byte sections are left unchanged. Safe no-op on little-endian.
4873
1
inline void convert_table_blob_to_host_endian(uint8_t* buffer) noexcept {
4874
1
  if constexpr (std::endian::native == std::endian::little) {
4875
1
    (void)buffer;
4876
1
    return;
4877
1
  }
4878
0
  auto u16 = [&](size_t off, size_t count) {
4879
1
    bswap_inplace(reinterpret_cast<uint16_t*>(buffer + off), count);
4880
1
  };
4881
1
  auto u32 = [&](size_t off, size_t count) {
4882
1
    bswap_inplace(reinterpret_cast<uint32_t*>(buffer + off), count);
4883
1
  };
4884
1
  auto u64 = [&](size_t off, size_t count) {
4885
1
    bswap_inplace(reinterpret_cast<uint64_t*>(buffer + off), count);
4886
1
  };
4887
4888
1
  u16(table_blob::off_idna_stage1, table_blob::count_idna_stage1);
4889
1
  u16(table_blob::off_idna_stage2, table_blob::count_idna_stage2);
4890
1
  u64(table_blob::off_idna_bool_blocks, table_blob::count_idna_bool_blocks);
4891
1
  u16(table_blob::off_decomposition_block,
4892
1
      table_blob::count_decomposition_block);
4893
1
  u32(table_blob::off_decomposition_data, table_blob::count_decomposition_data);
4894
1
  u16(table_blob::off_composition_block, table_blob::count_composition_block);
4895
1
  u32(table_blob::off_composition_data, table_blob::count_composition_data);
4896
1
  u32(table_blob::off_id_continue_flat, table_blob::count_id_continue_flat);
4897
1
  u32(table_blob::off_id_start_flat, table_blob::count_id_start_flat);
4898
1
  u32(table_blob::off_dir_start, table_blob::count_dir_start);
4899
1
  u32(table_blob::off_dir_final, table_blob::count_dir_final);
4900
1
  u32(table_blob::off_combining_flat, table_blob::count_combining_flat);
4901
1
  u32(table_blob::off_joining_start, table_blob::count_joining_start);
4902
1
  u32(table_blob::off_joining_final, table_blob::count_joining_final);
4903
1
}
4904
4905
}  // namespace detail
4906
4907
// --- Blob layout invariants --------------------------------------------------
4908
static_assert(table_blob::count_decomposition_index == 4352);
4909
static_assert(table_blob::count_ccc_index == 4352);
4910
static_assert(table_blob::count_composition_index == 4352);
4911
static_assert(table_blob::count_decomposition_block ==
4912
              table_blob::decomposition_block_rows *
4913
                  table_blob::decomposition_block_cols);
4914
static_assert(table_blob::count_ccc_block ==
4915
              table_blob::ccc_block_rows * table_blob::ccc_block_cols);
4916
static_assert(table_blob::count_composition_block ==
4917
              table_blob::composition_block_rows *
4918
                  table_blob::composition_block_cols);
4919
static_assert(table_blob::count_dir_start == table_blob::dir_table_count &&
4920
              table_blob::count_dir_final == table_blob::dir_table_count &&
4921
              table_blob::count_dir_value == table_blob::dir_table_count);
4922
static_assert(
4923
    table_blob::count_joining_start == table_blob::joining_table_count &&
4924
    table_blob::count_joining_final == table_blob::joining_table_count &&
4925
    table_blob::count_joining_value == table_blob::joining_table_count);
4926
static_assert(table_blob::count_id_continue_flat ==
4927
              table_blob::id_continue_count * 2);
4928
static_assert(table_blob::count_id_start_flat ==
4929
              table_blob::id_start_count * 2);
4930
static_assert(table_blob::count_combining_flat ==
4931
              table_blob::combining_range_count * 2);
4932
static_assert(table_blob::off_idna_stage1 % alignof(uint16_t) == 0);
4933
static_assert(table_blob::off_idna_stage2 % alignof(uint16_t) == 0);
4934
static_assert(table_blob::off_idna_bool_blocks % alignof(uint64_t) == 0);
4935
static_assert(table_blob::off_decomposition_block % alignof(uint16_t) == 0);
4936
static_assert(table_blob::off_decomposition_data % alignof(char32_t) == 0);
4937
static_assert(table_blob::off_composition_block % alignof(uint16_t) == 0);
4938
static_assert(table_blob::off_composition_data % alignof(char32_t) == 0);
4939
static_assert(table_blob::off_id_continue_flat % alignof(uint32_t) == 0);
4940
static_assert(table_blob::off_id_start_flat % alignof(uint32_t) == 0);
4941
static_assert(table_blob::off_dir_start % alignof(uint32_t) == 0);
4942
static_assert(table_blob::off_dir_final % alignof(uint32_t) == 0);
4943
static_assert(table_blob::off_combining_flat % alignof(uint32_t) == 0);
4944
static_assert(table_blob::off_joining_start % alignof(uint32_t) == 0);
4945
static_assert(table_blob::off_joining_final % alignof(uint32_t) == 0);
4946
static_assert(table_blob::compressed_size == sizeof(table_blob::compressed));
4947
4948
// Every section must lie entirely inside the uncompressed buffer.
4949
#define ADA_IDNA_SECTION_IN_BOUNDS(off, count, width)                       \
4950
  static_assert((off) + (count) * (width) <= table_blob::uncompressed_size, \
4951
                #off " overflows uncompressed buffer")
4952
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_idna_stage1,
4953
                           table_blob::count_idna_stage1, 2);
4954
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_idna_stage2,
4955
                           table_blob::count_idna_stage2, 2);
4956
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_idna_bool_blocks,
4957
                           table_blob::count_idna_bool_blocks, 8);
4958
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_idna_utf8_mappings,
4959
                           table_blob::count_idna_utf8_mappings, 1);
4960
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_decomposition_index,
4961
                           table_blob::count_decomposition_index, 1);
4962
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_decomposition_block,
4963
                           table_blob::count_decomposition_block, 2);
4964
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_decomposition_data,
4965
                           table_blob::count_decomposition_data, 4);
4966
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_ccc_index,
4967
                           table_blob::count_ccc_index, 1);
4968
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_ccc_block,
4969
                           table_blob::count_ccc_block, 1);
4970
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_composition_index,
4971
                           table_blob::count_composition_index, 1);
4972
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_composition_block,
4973
                           table_blob::count_composition_block, 2);
4974
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_composition_data,
4975
                           table_blob::count_composition_data, 4);
4976
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_id_continue_flat,
4977
                           table_blob::count_id_continue_flat, 4);
4978
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_id_start_flat,
4979
                           table_blob::count_id_start_flat, 4);
4980
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_dir_start,
4981
                           table_blob::count_dir_start, 4);
4982
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_dir_final,
4983
                           table_blob::count_dir_final, 4);
4984
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_dir_value,
4985
                           table_blob::count_dir_value, 1);
4986
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_combining_flat,
4987
                           table_blob::count_combining_flat, 4);
4988
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_joining_start,
4989
                           table_blob::count_joining_start, 4);
4990
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_joining_final,
4991
                           table_blob::count_joining_final, 4);
4992
ADA_IDNA_SECTION_IN_BOUNDS(table_blob::off_joining_value,
4993
                           table_blob::count_joining_value, 1);
4994
#undef ADA_IDNA_SECTION_IN_BOUNDS
4995
4996
// --- Mapping -----------------------------------------------------------------
4997
inline const uint16_t* idna_stage1 = nullptr;
4998
inline const uint16_t* idna_stage2 = nullptr;
4999
inline const uint64_t* idna_bool_blocks = nullptr;
5000
inline const uint8_t* idna_utf8_mappings = nullptr;
5001
5002
// --- Normalization (O(1) multi-stage) ----------------------------------------
5003
inline const uint8_t* decomposition_index = nullptr;
5004
inline const uint16_t* decomposition_block_flat = nullptr;
5005
inline const char32_t* decomposition_data = nullptr;
5006
inline const uint8_t* ccc_index = nullptr;
5007
inline const uint8_t* ccc_block_flat = nullptr;
5008
inline const uint8_t* composition_index = nullptr;
5009
inline const uint16_t* composition_block_flat = nullptr;
5010
inline const char32_t* composition_data = nullptr;
5011
5012
// --- Identifier --------------------------------------------------------------
5013
// Pointer-to-array alias. CF17 vs CF22 disagree on spacing inside (*)[2].
5014
// clang-format off
5015
using range_pair_ptr = const uint32_t(*)[2];
5016
// clang-format on
5017
inline range_pair_ptr id_continue = nullptr;
5018
inline range_pair_ptr id_start = nullptr;
5019
5020
// --- Validity (const SoA) ----------------------------------------------------
5021
inline const uint32_t* dir_start = nullptr;
5022
inline const uint32_t* dir_final = nullptr;
5023
inline const uint8_t* dir_value = nullptr;
5024
inline range_pair_ptr combining_ranges = nullptr;
5025
inline const uint32_t* joining_start = nullptr;
5026
inline const uint32_t* joining_final = nullptr;
5027
inline const uint8_t* joining_value = nullptr;
5028
5029
inline constexpr size_t id_continue_count = table_blob::id_continue_count;
5030
inline constexpr size_t id_start_count = table_blob::id_start_count;
5031
inline constexpr size_t dir_table_count = table_blob::dir_table_count;
5032
inline constexpr size_t joining_table_count = table_blob::joining_table_count;
5033
inline constexpr size_t combining_range_count =
5034
    table_blob::combining_range_count;
5035
inline constexpr size_t idna_utf8_mappings_size =
5036
    table_blob::count_idna_utf8_mappings;
5037
inline constexpr size_t decomposition_data_size =
5038
    table_blob::count_decomposition_data;
5039
inline constexpr size_t composition_data_size =
5040
    table_blob::count_composition_data;
5041
5042
inline constexpr size_t kDecompBlockCols =
5043
    table_blob::decomposition_block_cols;                            // 257
5044
inline constexpr size_t kCccBlockCols = table_blob::ccc_block_cols;  // 256
5045
inline constexpr size_t kCompBlockCols =
5046
    table_blob::composition_block_cols;  // 257
5047
inline constexpr size_t kDecompBlockRows = table_blob::decomposition_block_rows;
5048
inline constexpr size_t kCccBlockRows = table_blob::ccc_block_rows;
5049
inline constexpr size_t kCompBlockRows = table_blob::composition_block_rows;
5050
5051
// Init state: 0=uninit, 1=in progress, 2=ready, 3=failed.
5052
inline constexpr uint8_t kTablesUninit = 0;
5053
inline constexpr uint8_t kTablesInProgress = 1;
5054
inline constexpr uint8_t kTablesReady = 2;
5055
inline constexpr uint8_t kTablesFailed = 3;
5056
5057
inline std::atomic<uint8_t> tables_init_state{kTablesUninit};
5058
// Process-lifetime allocation published only by the winning init thread.
5059
// Never freed: shared read-only data for the process. Do not dlclose a DSO
5060
// that owns this buffer while other code may still call into ada::idna.
5061
inline uint8_t* tables_buffer = nullptr;
5062
5063
// Cap spin-wait so a stuck peer cannot hang the process forever.
5064
inline constexpr uint64_t kTablesSpinLimit = 1'000'000'000ull;
5065
5066
// ISO HDLC / zlib CRC-32 of the uncompressed table payload.
5067
[[nodiscard]] inline uint32_t crc32_ieee(const uint8_t* data,
5068
1
                                         size_t len) noexcept {
5069
1
  uint32_t c = 0xFFFFFFFFu;
5070
216k
  for (size_t i = 0; i < len; ++i) {
5071
216k
    c ^= data[i];
5072
1.94M
    for (int k = 0; k < 8; ++k) {
5073
1.72M
      const uint32_t mask = 0u - (c & 1u);
5074
1.72M
      c = (c >> 1) ^ (0xEDB88320u & mask);
5075
1.72M
    }
5076
216k
  }
5077
1
  return ~c;
5078
1
}
5079
5080
92.7k
[[nodiscard]] inline bool tables_are_ready() noexcept {
5081
92.7k
  return tables_init_state.load(std::memory_order_acquire) == kTablesReady;
5082
92.7k
}
5083
5084
// Returns true only when all table pointers are safe to use.
5085
234k
[[nodiscard]] inline bool ensure_tables() noexcept {
5086
234k
  uint8_t state = tables_init_state.load(std::memory_order_acquire);
5087
234k
  if (state == kTablesReady) {
5088
234k
    return true;
5089
234k
  }
5090
1
  if (state == kTablesFailed) {
5091
0
    return false;
5092
0
  }
5093
5094
1
  uint8_t expected = kTablesUninit;
5095
1
  if (tables_init_state.compare_exchange_strong(expected, kTablesInProgress,
5096
1
                                                std::memory_order_acq_rel,
5097
1
                                                std::memory_order_acquire)) {
5098
1
    uint8_t* buffer = new (std::nothrow) uint8_t[table_blob::uncompressed_size];
5099
1
    if (buffer == nullptr) {
5100
0
      tables_init_state.store(kTablesFailed, std::memory_order_release);
5101
0
      return false;
5102
0
    }
5103
5104
1
    const size_t n = deflate::inflate_raw(table_blob::compressed,
5105
1
                                          table_blob::compressed_size, buffer,
5106
1
                                          table_blob::uncompressed_size);
5107
1
    if (n != table_blob::uncompressed_size ||
5108
1
        crc32_ieee(buffer, n) != table_blob::uncompressed_crc32) {
5109
0
      delete[] buffer;
5110
0
      tables_init_state.store(kTablesFailed, std::memory_order_release);
5111
0
      return false;
5112
0
    }
5113
5114
    // LE payload verified; convert multi-byte fields for big-endian hosts.
5115
1
    detail::convert_table_blob_to_host_endian(buffer);
5116
5117
21
    auto at = [&](size_t off) noexcept -> const uint8_t* {
5118
21
      return buffer + off;
5119
21
    };
5120
5121
    // Publish all non-atomic pointers before READY. Waiters synchronize via
5122
    // acquire on tables_init_state and then observe these writes.
5123
1
    idna_stage1 =
5124
1
        reinterpret_cast<const uint16_t*>(at(table_blob::off_idna_stage1));
5125
1
    idna_stage2 =
5126
1
        reinterpret_cast<const uint16_t*>(at(table_blob::off_idna_stage2));
5127
1
    idna_bool_blocks =
5128
1
        reinterpret_cast<const uint64_t*>(at(table_blob::off_idna_bool_blocks));
5129
1
    idna_utf8_mappings = at(table_blob::off_idna_utf8_mappings);
5130
5131
1
    decomposition_index = at(table_blob::off_decomposition_index);
5132
1
    decomposition_block_flat = reinterpret_cast<const uint16_t*>(
5133
1
        at(table_blob::off_decomposition_block));
5134
1
    decomposition_data = reinterpret_cast<const char32_t*>(
5135
1
        at(table_blob::off_decomposition_data));
5136
1
    ccc_index = at(table_blob::off_ccc_index);
5137
1
    ccc_block_flat = at(table_blob::off_ccc_block);
5138
1
    composition_index = at(table_blob::off_composition_index);
5139
1
    composition_block_flat = reinterpret_cast<const uint16_t*>(
5140
1
        at(table_blob::off_composition_block));
5141
1
    composition_data =
5142
1
        reinterpret_cast<const char32_t*>(at(table_blob::off_composition_data));
5143
5144
1
    id_continue =
5145
1
        reinterpret_cast<range_pair_ptr>(at(table_blob::off_id_continue_flat));
5146
1
    id_start =
5147
1
        reinterpret_cast<range_pair_ptr>(at(table_blob::off_id_start_flat));
5148
5149
1
    dir_start =
5150
1
        reinterpret_cast<const uint32_t*>(at(table_blob::off_dir_start));
5151
1
    dir_final =
5152
1
        reinterpret_cast<const uint32_t*>(at(table_blob::off_dir_final));
5153
1
    dir_value = at(table_blob::off_dir_value);
5154
1
    combining_ranges =
5155
1
        reinterpret_cast<range_pair_ptr>(at(table_blob::off_combining_flat));
5156
1
    joining_start =
5157
1
        reinterpret_cast<const uint32_t*>(at(table_blob::off_joining_start));
5158
1
    joining_final =
5159
1
        reinterpret_cast<const uint32_t*>(at(table_blob::off_joining_final));
5160
1
    joining_value = at(table_blob::off_joining_value);
5161
5162
1
    tables_buffer = buffer;
5163
1
    tables_init_state.store(kTablesReady, std::memory_order_release);
5164
1
    return true;
5165
1
  }
5166
5167
  // Another thread owns init (or finished between our loads).
5168
0
  for (uint64_t spins = 0; spins < kTablesSpinLimit; ++spins) {
5169
0
    state = tables_init_state.load(std::memory_order_acquire);
5170
0
    if (state == kTablesReady) {
5171
0
      return true;
5172
0
    }
5173
0
    if (state == kTablesFailed) {
5174
0
      return false;
5175
0
    }
5176
0
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
5177
0
    defined(_M_IX86)
5178
0
#if defined(__GNUC__) || defined(__clang__)
5179
0
    __builtin_ia32_pause();
5180
0
#endif
5181
#elif defined(__aarch64__) || defined(_M_ARM64)
5182
#if defined(__GNUC__) || defined(__clang__)
5183
    asm volatile("yield" ::: "memory");
5184
#endif
5185
#endif
5186
0
  }
5187
  // Timed out waiting for a peer - treat as failure rather than hang.
5188
0
  return false;
5189
0
}
5190
5191
// O(1) multi-stage accessors. Block indices from the tables are uint8_t and
5192
// theoretically can be out of range if the blob is corrupt; clamp to a valid
5193
// empty/default row (index 0) instead of reading OOB.
5194
1.59M
inline const uint16_t* decomposition_block_row(uint8_t bi) noexcept {
5195
1.59M
  if (bi >= kDecompBlockRows) {
5196
0
    bi = 0;
5197
0
  }
5198
1.59M
  return decomposition_block_flat + static_cast<size_t>(bi) * kDecompBlockCols;
5199
1.59M
}
5200
5201
2.23M
inline const uint8_t* ccc_block_row(uint8_t bi) noexcept {
5202
2.23M
  if (bi >= kCccBlockRows) {
5203
0
    bi = 0;
5204
0
  }
5205
2.23M
  return ccc_block_flat + static_cast<size_t>(bi) * kCccBlockCols;
5206
2.23M
}
5207
5208
718k
inline const uint16_t* composition_block_row(uint8_t bi) noexcept {
5209
718k
  if (bi >= kCompBlockRows) {
5210
0
    bi = 0;
5211
0
  }
5212
718k
  return composition_block_flat + static_cast<size_t>(bi) * kCompBlockCols;
5213
718k
}
5214
5215
}  // namespace ada::idna
5216
/* end file src/table_store.hpp */
5217
/* begin file src/mapping_tables.cpp */
5218
// IDNA 18.0.0
5219
// Two-level compressed mapping table (constants only).
5220
// Array payloads are stored in the DEFLATE blob (see table_store.hpp /
5221
// scripts/pack_tables.py).
5222
// Regenerate with: python3 scripts/idna_table.py --write
5223
// Logical table size: 51037 bytes (49.8 KB)
5224
//   stage1:        8162 bytes  (4081 uint16_t entries)
5225
//   stage2:       23424 bytes  (183 mixed blocks x 64)
5226
//   bool_blocks:   1800 bytes  (225 uint64_t words)
5227
//   utf8 maps:    17651 bytes
5228
5229
// clang-format off
5230
#ifndef ADA_IDNA_MAPPING_TABLE_H
5231
#define ADA_IDNA_MAPPING_TABLE_H
5232
#include <cstdint>
5233
5234
namespace ada::idna {
5235
5236
// Block size for two-level table (2^6 = 64 code points per block).
5237
constexpr uint32_t IDNA_BLOCK_BITS = 6u;
5238
constexpr uint32_t IDNA_BLOCK_SIZE = 64u;
5239
constexpr uint32_t IDNA_BLOCK_MASK = 63u;
5240
5241
// Sentinel values stored in stage2 / returned by lookup.
5242
constexpr uint16_t IDNA_VALID      = 0xFFFF;  // code point is valid as-is
5243
constexpr uint16_t IDNA_DISALLOWED = 0xFFFE;  // code point is disallowed
5244
constexpr uint16_t IDNA_IGNORED    = 0x0000;    // ignored (index into empty UTF-8 entry)
5245
5246
// Bit 15 of a stage1 entry: set = boolean block, clear = mixed block.
5247
constexpr uint16_t IDNA_BOOL_FLAG  = 0x8000;
5248
5249
// Two-level table covers code points [0, IDNA_LOW_RANGE_END).
5250
// Derived from the highest non-disallowed code point below the high-ignored range,
5251
// rounded up to the next 64-code-point block boundary.
5252
constexpr uint32_t IDNA_LOW_RANGE_END    = 0x0003FC40;
5253
5254
// Variation selectors supplement: U+E0100..U+E01EF are all ignored.
5255
// These are handled with a simple range check; everything else above
5256
// IDNA_LOW_RANGE_END is disallowed.
5257
constexpr uint32_t IDNA_HIGH_IGNORED_START = 0x000E0100;
5258
constexpr uint32_t IDNA_HIGH_IGNORED_END   = 0x000E01F0;  // exclusive
5259
5260
// Large arrays (idna_stage1/stage2/bool_blocks/utf8_mappings) live in table_blob.
5261
5262
}  // namespace ada::idna
5263
#endif  // ADA_IDNA_MAPPING_TABLE_H
5264
/* end file src/mapping_tables.cpp */
5265
5266
namespace ada::idna {
5267
5268
// --- O(1) two-level table lookup ---------------------------------------------
5269
//
5270
// Returns one of:
5271
//   IDNA_VALID      - keep code point in output unchanged
5272
//   IDNA_DISALLOWED - code point is not allowed (map() returns error)
5273
//   IDNA_IGNORED    - code point is ignored (index 0 = empty UTF-8 entry)
5274
//   other           - byte offset into idna_utf8_mappings[] (null-terminated)
5275
//
5276
// Assumes ensure_tables() has already been called by the public entry point.
5277
1.49M
static uint16_t idna_lookup(uint32_t cp) noexcept {
5278
1.49M
  if (cp < IDNA_LOW_RANGE_END) {
5279
1.48M
    uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS];
5280
1.48M
    if (ref & IDNA_BOOL_FLAG) {
5281
717k
      uint32_t bit_idx =
5282
717k
          static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE +
5283
717k
          (cp & IDNA_BLOCK_MASK);
5284
717k
      bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u;
5285
717k
      return is_valid ? IDNA_VALID : IDNA_DISALLOWED;
5286
717k
    }
5287
769k
    return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)];
5288
1.48M
  }
5289
5290
9.12k
  if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) {
5291
3.26k
    return IDNA_IGNORED;
5292
3.26k
  }
5293
5294
5.86k
  return IDNA_DISALLOWED;
5295
9.12k
}
5296
5297
// Advances *ptr past one well-formed UTF-8 code point from the mapping table.
5298
153k
static char32_t utf8_next(const uint8_t*& ptr) noexcept {
5299
153k
  uint8_t b0 = *ptr++;
5300
153k
  if (b0 < 0x80u) return static_cast<char32_t>(b0);
5301
79.5k
  if (b0 < 0xE0u) {
5302
62.6k
    uint32_t cp = (b0 & 0x1Fu) << 6;
5303
62.6k
    cp |= (*ptr++ & 0x3Fu);
5304
62.6k
    return static_cast<char32_t>(cp);
5305
62.6k
  }
5306
16.9k
  if (b0 < 0xF0u) {
5307
15.6k
    uint32_t cp = (b0 & 0x0Fu) << 12;
5308
15.6k
    cp |= ((*ptr++ & 0x3Fu) << 6);
5309
15.6k
    cp |= (*ptr++ & 0x3Fu);
5310
15.6k
    return static_cast<char32_t>(cp);
5311
15.6k
  }
5312
1.30k
  uint32_t cp = (b0 & 0x07u) << 18;
5313
1.30k
  cp |= ((*ptr++ & 0x3Fu) << 12);
5314
1.30k
  cp |= ((*ptr++ & 0x3Fu) << 6);
5315
1.30k
  cp |= (*ptr++ & 0x3Fu);
5316
1.30k
  return static_cast<char32_t>(cp);
5317
16.9k
}
5318
5319
// Count UTF-8 code points in a null-terminated mapping string (trusted table).
5320
119k
static size_t utf8_count_codepoints(const uint8_t* ptr) noexcept {
5321
119k
  size_t n = 0;
5322
272k
  while (*ptr != 0) {
5323
153k
    ++n;
5324
153k
    if (*ptr < 0x80u) {
5325
73.7k
      ++ptr;
5326
79.5k
    } else if (*ptr < 0xE0u) {
5327
62.6k
      ptr += 2;
5328
62.6k
    } else if (*ptr < 0xF0u) {
5329
15.6k
      ptr += 3;
5330
15.6k
    } else {
5331
1.30k
      ptr += 4;
5332
1.30k
    }
5333
153k
  }
5334
119k
  return n;
5335
119k
}
5336
5337
// --- ASCII fast path ---------------------------------------------------------
5338
26.7k
void ascii_map(char* input, size_t length) {
5339
80.2k
  auto broadcast = [](uint8_t v) -> uint64_t {
5340
80.2k
    return 0x101010101010101ull * v;
5341
80.2k
  };
5342
26.7k
  uint64_t broadcast_80 = broadcast(0x80);
5343
26.7k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
5344
26.7k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
5345
26.7k
  size_t i = 0;
5346
5347
43.0k
  for (; i + 7 < length; i += 8) {
5348
16.2k
    uint64_t word{};
5349
16.2k
    std::memcpy(&word, input + i, sizeof(word));
5350
16.2k
    word ^=
5351
16.2k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
5352
16.2k
    std::memcpy(input + i, &word, sizeof(word));
5353
16.2k
  }
5354
26.7k
  if (i < length) {
5355
24.3k
    uint64_t word{};
5356
24.3k
    std::memcpy(&word, input + i, length - i);
5357
24.3k
    word ^=
5358
24.3k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
5359
24.3k
    std::memcpy(input + i, &word, length - i);
5360
24.3k
  }
5361
26.7k
}
5362
5363
// Two-pass map: first validate + exact size, then write once (no growth
5364
// realloc).
5365
94.9k
bool map(std::u32string_view input, std::u32string& out) {
5366
  //  [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap).
5367
94.9k
  out.clear();
5368
94.9k
  if (!ensure_tables()) {
5369
0
    return false;
5370
0
  }
5371
5372
  // Pass 1: validate and compute exact output length.
5373
94.9k
  size_t out_size = 0;
5374
754k
  for (char32_t x : input) {
5375
754k
    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
5376
754k
    if (status == IDNA_DISALLOWED) {
5377
6.97k
      return false;
5378
6.97k
    }
5379
747k
    if (status == IDNA_VALID) {
5380
628k
      ++out_size;
5381
628k
      continue;
5382
628k
    }
5383
119k
    if (static_cast<size_t>(status) >= idna_utf8_mappings_size) {
5384
0
      return false;
5385
0
    }
5386
119k
    out_size += utf8_count_codepoints(idna_utf8_mappings + status);
5387
119k
  }
5388
5389
  // Pass 2: write into a single allocation.
5390
88.0k
  out.resize(out_size);
5391
88.0k
  size_t w = 0;
5392
742k
  for (char32_t x : input) {
5393
742k
    uint16_t status = idna_lookup(static_cast<uint32_t>(x));
5394
742k
    if (status == IDNA_VALID) {
5395
623k
      out[w++] = x;
5396
623k
      continue;
5397
623k
    }
5398
    // IGNORED or mapped (status already validated in pass 1).
5399
119k
    const uint8_t* ptr = idna_utf8_mappings + status;
5400
272k
    while (*ptr != 0) {
5401
153k
      out[w++] = utf8_next(ptr);
5402
153k
    }
5403
119k
  }
5404
88.0k
  return true;
5405
94.9k
}
5406
5407
0
std::u32string map(std::u32string_view input) {
5408
0
  std::u32string answer;
5409
0
  if (!map(input, answer)) {
5410
0
    return {};
5411
0
  }
5412
0
  return answer;
5413
0
}
5414
5415
}  // namespace ada::idna
5416
/* end file src/mapping.cpp */
5417
/* begin file src/normalization.cpp */
5418
/* begin file include/ada/idna/normalization.h */
5419
#ifndef ADA_IDNA_NORMALIZATION_H
5420
#define ADA_IDNA_NORMALIZATION_H
5421
5422
#include <string>
5423
#include <string_view>
5424
5425
namespace ada::idna {
5426
5427
// Returns true if `input` is already in Unicode Normalization Form C.
5428
// Requires that internal tables have been loaded (call ensure via normalize
5429
// or map first, or this returns false if tables are unavailable).
5430
[[nodiscard]] bool is_already_nfc(std::u32string_view input) noexcept;
5431
5432
// Normalize the characters according to IDNA (Unicode Normalization Form C).
5433
// Returns false if the internal Unicode tables could not be loaded; in that
5434
// case `input` is left unchanged. Skips work when the string is already NFC.
5435
[[nodiscard]] bool normalize(std::u32string& input);
5436
5437
}  // namespace ada::idna
5438
#endif
5439
/* end file include/ada/idna/normalization.h */
5440
/* begin file src/normalization_tables.cpp */
5441
// Normalization table helpers.
5442
// Array payloads live in the DEFLATE blob (table_store.hpp).
5443
// Regenerate with: python3 scripts/unicode_data_table.py --write
5444
// clang-format off
5445
#ifndef ADA_IDNA_NORMALIZATION_TABLES_H
5446
#define ADA_IDNA_NORMALIZATION_TABLES_H
5447
5448
namespace ada::idna {
5449
5450
// Accessors and multi-stage tables are provided by table_store.hpp after
5451
// ensure_tables(). Lookup code matches the classic O(1) uni-algo layout.
5452
5453
}  // namespace ada::idna
5454
#endif  // ADA_IDNA_NORMALIZATION_TABLES_H
5455
/* end file src/normalization_tables.cpp */
5456
5457
#include <cstdint>
5458
5459
namespace ada::idna {
5460
5461
// See
5462
// https://github.com/uni-algo/uni-algo/blob/c612968c5ed3ace39bde4c894c24286c5f2c7fe2/include/uni_algo/impl/impl_norm.h#L467
5463
constexpr char32_t hangul_sbase = 0xAC00;
5464
constexpr char32_t hangul_tbase = 0x11A7;
5465
constexpr char32_t hangul_vbase = 0x1161;
5466
constexpr char32_t hangul_lbase = 0x1100;
5467
constexpr char32_t hangul_lcount = 19;
5468
constexpr char32_t hangul_vcount = 21;
5469
constexpr char32_t hangul_tcount = 28;
5470
constexpr char32_t hangul_ncount = hangul_vcount * hangul_tcount;
5471
constexpr char32_t hangul_scount =
5472
    hangul_lcount * hangul_vcount * hangul_tcount;
5473
5474
// Canonical decomposition length (0 if none / compatibility-only / Hangul
5475
// syllable). Length 1 means a singleton mapping (character is not NFC form).
5476
// Length >= 2 means a primary composite that is already the NFC form of its
5477
// decomposition (e.g. U+00E9 LATIN SMALL LETTER E WITH ACUTE).
5478
717k
static size_t canonical_decomp_length(char32_t current_character) noexcept {
5479
717k
  if (current_character >= hangul_sbase &&
5480
35.0k
      current_character < hangul_sbase + hangul_scount) {
5481
    // Hangul precomposed syllables are NFC.
5482
15.8k
    return 0;
5483
15.8k
  }
5484
701k
  if (current_character >= 0x110000) {
5485
0
    return 0;
5486
0
  }
5487
701k
  const uint8_t di = decomposition_index[current_character >> 8];
5488
701k
  const uint16_t* const decomposition =
5489
701k
      decomposition_block_row(di) + (current_character % 256);
5490
701k
  size_t decomposition_length =
5491
701k
      (decomposition[1] >> 2) - (decomposition[0] >> 2);
5492
701k
  if ((decomposition_length > 0) && (decomposition[0] & 1)) {
5493
0
    decomposition_length = 0;  // compatibility-only: ignored for NFC
5494
0
  }
5495
701k
  return decomposition_length;
5496
701k
}
5497
5498
std::pair<bool, size_t> compute_decomposition_length(
5499
17.1k
    const std::u32string_view input) noexcept {
5500
17.1k
  bool decomposition_needed{false};
5501
17.1k
  size_t additional_elements{0};
5502
109k
  for (char32_t current_character : input) {
5503
109k
    size_t decomposition_length{0};
5504
5505
109k
    if (current_character >= hangul_sbase &&
5506
9.82k
        current_character < hangul_sbase + hangul_scount) {
5507
      // Full NFD-style Hangul decomp for the decompose() step.
5508
3.51k
      decomposition_length = 2;
5509
3.51k
      if ((current_character - hangul_sbase) % hangul_tcount) {
5510
2.12k
        decomposition_length = 3;
5511
2.12k
      }
5512
106k
    } else if (current_character < 0x110000) {
5513
106k
      const uint8_t di = decomposition_index[current_character >> 8];
5514
106k
      const uint16_t* const decomposition =
5515
106k
          decomposition_block_row(di) + (current_character % 256);
5516
106k
      decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
5517
106k
      if ((decomposition_length > 0) && (decomposition[0] & 1)) {
5518
0
        decomposition_length = 0;
5519
0
      }
5520
106k
    }
5521
109k
    if (decomposition_length != 0) {
5522
11.4k
      decomposition_needed = true;
5523
11.4k
      additional_elements += decomposition_length - 1;
5524
11.4k
    }
5525
109k
  }
5526
17.1k
  return {decomposition_needed, additional_elements};
5527
17.1k
}
5528
5529
6.08k
void decompose(std::u32string& input, size_t additional_elements) {
5530
6.08k
  input.resize(input.size() + additional_elements);
5531
6.08k
  for (size_t descending_idx = input.size(),
5532
6.08k
              input_count = descending_idx - additional_elements;
5533
48.3k
       input_count--;) {
5534
42.2k
    if (input[input_count] >= hangul_sbase &&
5535
7.80k
        input[input_count] < hangul_sbase + hangul_scount) {
5536
      // Hangul decomposition.
5537
3.51k
      char32_t s_index = input[input_count] - hangul_sbase;
5538
3.51k
      if (s_index % hangul_tcount != 0) {
5539
2.12k
        input[--descending_idx] = hangul_tbase + s_index % hangul_tcount;
5540
2.12k
      }
5541
3.51k
      input[--descending_idx] =
5542
3.51k
          hangul_vbase + (s_index % hangul_ncount) / hangul_tcount;
5543
3.51k
      input[--descending_idx] = hangul_lbase + s_index / hangul_ncount;
5544
38.7k
    } else if (input[input_count] < 0x110000) {
5545
38.7k
      const uint16_t* decomposition =
5546
38.7k
          decomposition_block_row(
5547
38.7k
              decomposition_index[input[input_count] >> 8]) +
5548
38.7k
          (input[input_count] % 256);
5549
38.7k
      uint16_t decomposition_length =
5550
38.7k
          (decomposition[1] >> 2) - (decomposition[0] >> 2);
5551
38.7k
      if (decomposition_length > 0 && (decomposition[0] & 1)) {
5552
0
        decomposition_length = 0;
5553
0
      }
5554
38.7k
      if (decomposition_length > 0) {
5555
7.96k
        const size_t base = static_cast<size_t>(decomposition[0] >> 2);
5556
7.96k
        if (base + decomposition_length > decomposition_data_size) {
5557
0
          input[--descending_idx] = input[input_count];
5558
7.96k
        } else {
5559
24.5k
          while (decomposition_length-- > 0) {
5560
16.6k
            input[--descending_idx] =
5561
16.6k
                decomposition_data[base + decomposition_length];
5562
16.6k
          }
5563
7.96k
        }
5564
30.7k
      } else {
5565
30.7k
        input[--descending_idx] = input[input_count];
5566
30.7k
      }
5567
38.7k
    } else {
5568
0
      input[--descending_idx] = input[input_count];
5569
0
    }
5570
42.2k
  }
5571
6.08k
}
5572
5573
2.23M
uint8_t get_ccc(char32_t c) noexcept {
5574
2.23M
  if (c >= 0x110000) {
5575
0
    return 0;
5576
0
  }
5577
2.23M
  return ccc_block_row(ccc_index[c >> 8])[c % 256];
5578
2.23M
}
5579
5580
17.1k
void sort_marks(std::u32string& input) {
5581
124k
  for (size_t idx = 1; idx < input.size(); idx++) {
5582
107k
    uint8_t ccc = get_ccc(input[idx]);
5583
107k
    if (ccc == 0) {
5584
69.2k
      continue;
5585
69.2k
    }
5586
37.7k
    auto current_character = input[idx];
5587
37.7k
    size_t back_idx = idx;
5588
52.0k
    while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) {
5589
14.2k
      input[back_idx] = input[back_idx - 1];
5590
14.2k
      back_idx--;
5591
14.2k
    }
5592
37.7k
    input[back_idx] = current_character;
5593
37.7k
  }
5594
17.1k
}
5595
5596
17.1k
void decompose_nfc(std::u32string& input) {
5597
  /**
5598
   * Decompose the domain_name string to Unicode Normalization Form C.
5599
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepDecompose
5600
   */
5601
17.1k
  auto [decomposition_needed, additional_elements] =
5602
17.1k
      compute_decomposition_length(input);
5603
17.1k
  if (decomposition_needed) {
5604
6.08k
    decompose(input, additional_elements);
5605
6.08k
  }
5606
17.1k
  sort_marks(input);
5607
17.1k
}
5608
5609
// Returns true if the composition row of a starter has a pair with `second`.
5610
static bool has_composition(const uint16_t* composition,
5611
225k
                            char32_t second) noexcept {
5612
225k
  int left = composition[0];
5613
225k
  int right = composition[1];
5614
225k
  if (left < 0 || right <= left ||
5615
213k
      static_cast<size_t>(right) > composition_data_size) {
5616
11.3k
    return false;
5617
11.3k
  }
5618
653k
  while (left + 2 < right) {
5619
439k
    int middle = left + (((right - left) >> 1) & ~1);
5620
439k
    if (composition_data[static_cast<size_t>(middle)] <= second) {
5621
46.1k
      left = middle;
5622
46.1k
    }
5623
439k
    if (composition_data[static_cast<size_t>(middle)] >= second) {
5624
409k
      right = middle;
5625
409k
    }
5626
439k
  }
5627
213k
  return static_cast<size_t>(left + 1) < composition_data_size &&
5628
213k
         composition_data[static_cast<size_t>(left)] == second;
5629
225k
}
5630
5631
// Returns true if a composition step would change the string.
5632
83.1k
static bool would_compose(std::u32string_view input) noexcept {
5633
636k
  for (size_t input_count = 0; input_count < input.size();) {
5634
577k
    const char32_t current = input[input_count];
5635
577k
    if (current >= hangul_lbase && current < hangul_lbase + hangul_lcount) {
5636
10.9k
      if (input_count + 1 < input.size() &&
5637
10.6k
          input[input_count + 1] >= hangul_vbase &&
5638
8.03k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
5639
4.71k
        return true;
5640
4.71k
      }
5641
6.20k
      ++input_count;
5642
6.20k
      continue;
5643
10.9k
    }
5644
566k
    if (current >= hangul_sbase && current < hangul_sbase + hangul_scount) {
5645
11.7k
      if ((current - hangul_sbase) % hangul_tcount == 0 &&
5646
3.67k
          input_count + 1 < input.size() &&
5647
3.31k
          input[input_count + 1] > hangul_tbase &&
5648
2.23k
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
5649
168
        return true;
5650
168
      }
5651
11.5k
      ++input_count;
5652
11.5k
      continue;
5653
11.7k
    }
5654
555k
    if (current < 0x110000) {
5655
555k
      const uint16_t* composition =
5656
555k
          composition_block_row(composition_index[current >> 8]) +
5657
555k
          (current % 256);
5658
555k
      int32_t previous_ccc = -1;
5659
555k
      size_t j = input_count;
5660
565k
      for (; j + 1 < input.size(); ++j) {
5661
509k
        uint8_t ccc = get_ccc(input[j + 1]);
5662
509k
        if (composition[1] != composition[0] && previous_ccc < ccc &&
5663
208k
            has_composition(composition, input[j + 1])) {
5664
19.7k
          return true;
5665
19.7k
        }
5666
489k
        if (ccc == 0) {
5667
479k
          break;
5668
479k
        }
5669
10.1k
        previous_ccc = ccc;
5670
10.1k
      }
5671
535k
      input_count = j + 1;
5672
535k
      continue;
5673
555k
    }
5674
0
    ++input_count;
5675
0
  }
5676
58.5k
  return false;
5677
83.1k
}
5678
5679
// Trailing canonical combining class of a character: the combining class of the
5680
// last code point of its canonical decomposition, or the character's own class
5681
// when it has none. A precomposed starter such as U+00E1 (a + U+0301, class
5682
// 230) has class 0 but a nonzero trailing class, so a following mark of lower
5683
// class reorders past the hidden mark during normalization.
5684
717k
static uint8_t trailing_ccc(char32_t c) noexcept {
5685
717k
  const size_t length = canonical_decomp_length(c);
5686
717k
  if (length == 0) {
5687
691k
    return get_ccc(c);
5688
691k
  }
5689
26.3k
  const uint16_t* const decomposition =
5690
26.3k
      decomposition_block_row(decomposition_index[c >> 8]) + (c % 256);
5691
26.3k
  const size_t base = decomposition[0] >> 2;
5692
26.3k
  return get_ccc(decomposition_data[base + length - 1]);
5693
717k
}
5694
5695
void compose(std::u32string& input);
5696
5697
// A character that has a canonical decomposition is in NFC form only if that
5698
// decomposition composes back to exactly it. Singletons never do (e.g. U+212B
5699
// ANGSTROM SIGN). Composition exclusions do not either: their decomposition
5700
// composes to a different primary composite (e.g. U+1F71 -> U+03B1 U+0301 ->
5701
// U+03AC) or does not compose at all (e.g. U+0958 DEVANAGARI LETTER QA ->
5702
// U+0915 U+093C), and non-starter decompositions such as U+0344 -> U+0308
5703
// U+0301 stay decomposed. All are NFC_Quick_Check=No and must be normalized.
5704
// Since Unicode 16 the first code point of a decomposition can also compose
5705
// with the preceding character: U+16121 is U+1611E U+1611E, so U+1611E U+16121
5706
// normalizes to U+16121 U+1611E.
5707
740k
static bool decomposition_is_not_nfc(char32_t previous, char32_t c) noexcept {
5708
740k
  if (c >= hangul_sbase && c < hangul_sbase + hangul_scount) {
5709
15.8k
    return false;
5710
15.8k
  }
5711
724k
  if (c >= 0x110000) {
5712
0
    return false;
5713
0
  }
5714
724k
  const uint16_t* const decomposition =
5715
724k
      decomposition_block_row(decomposition_index[c >> 8]) + (c % 256);
5716
724k
  const size_t length = (decomposition[1] >> 2) - (decomposition[0] >> 2);
5717
724k
  if (length == 0 || (decomposition[0] & 1)) {
5718
696k
    return false;  // no canonical decomposition (or compatibility-only)
5719
696k
  }
5720
28.6k
  if (length == 1) {
5721
0
    return true;  // singleton
5722
0
  }
5723
28.6k
  const size_t base = decomposition[0] >> 2;
5724
28.6k
  if (base + length > decomposition_data_size) {
5725
0
    return false;
5726
0
  }
5727
  // Recompose the canonical decomposition; if it does not collapse back to c,
5728
  // then c is an exclusion / non-starter decomposition and is not NFC.
5729
28.6k
  std::u32string decomposed(decomposition_data + base,
5730
28.6k
                            decomposition_data + base + length);
5731
28.6k
  compose(decomposed);
5732
28.6k
  if (!(decomposed.size() == 1 && decomposed[0] == c)) {
5733
0
    return true;
5734
0
  }
5735
28.6k
  return previous < 0x110000 &&
5736
17.2k
         has_composition(
5737
17.2k
             composition_block_row(composition_index[previous >> 8]) +
5738
17.2k
                 (previous % 256),
5739
17.2k
             decomposition_data[base]);
5740
28.6k
}
5741
5742
92.7k
bool is_already_nfc(std::u32string_view input) noexcept {
5743
92.7k
  if (input.empty()) {
5744
0
    return true;
5745
0
  }
5746
92.7k
  if (!tables_are_ready() && !ensure_tables()) {
5747
0
    return false;
5748
0
  }
5749
  // 1) A character whose canonical decomposition does not compose back to it is
5750
  //    not NFC: singletons (e.g. U+212B), composition exclusions (e.g. U+0958)
5751
  //    and non-starter decompositions (e.g. U+0344), or one whose
5752
  //    decomposition starts with a code point that composes with the previous
5753
  //    character (e.g. U+1611E U+16121).
5754
92.7k
  char32_t previous = 0x110000;  // none
5755
740k
  for (char32_t c : input) {
5756
740k
    if (decomposition_is_not_nfc(previous, c)) {
5757
224
      return false;
5758
224
    }
5759
740k
    previous = c;
5760
740k
  }
5761
  // 2) Combining marks already in canonical order. prev_ccc carries the
5762
  //    trailing class of the previous character's canonical decomposition so a
5763
  //    composite starter followed by a lower-class mark is caught.
5764
92.5k
  uint8_t prev_ccc = 0;
5765
726k
  for (char32_t c : input) {
5766
726k
    uint8_t ccc = get_ccc(c);
5767
726k
    if (ccc != 0 && prev_ccc > ccc) {
5768
9.35k
      return false;
5769
9.35k
    }
5770
717k
    prev_ccc = trailing_ccc(c);
5771
717k
  }
5772
  // 3) No pairwise composition would apply (including Hangul L+V / LV+T).
5773
83.1k
  return !would_compose(input);
5774
92.5k
}
5775
5776
45.7k
void compose(std::u32string& input) {
5777
  /**
5778
   * Compose the domain_name string to Unicode Normalization Form C.
5779
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepCompose
5780
   */
5781
45.7k
  size_t input_count{0};
5782
45.7k
  size_t composition_count{0};
5783
151k
  for (; input_count < input.size(); input_count++, composition_count++) {
5784
105k
    input[composition_count] = input[input_count];
5785
105k
    if (input[input_count] >= hangul_lbase &&
5786
36.0k
        input[input_count] < hangul_lbase + hangul_lcount) {
5787
8.50k
      if (input_count + 1 < input.size() &&
5788
8.14k
          input[input_count + 1] >= hangul_vbase &&
5789
7.11k
          input[input_count + 1] < hangul_vbase + hangul_vcount) {
5790
6.06k
        input[composition_count] =
5791
6.06k
            hangul_sbase +
5792
6.06k
            ((input[input_count] - hangul_lbase) * hangul_vcount +
5793
6.06k
             input[input_count + 1] - hangul_vbase) *
5794
6.06k
                hangul_tcount;
5795
6.06k
        input_count++;
5796
6.06k
        if (input_count + 1 < input.size() &&
5797
4.69k
            input[input_count + 1] > hangul_tbase &&
5798
3.05k
            input[input_count + 1] < hangul_tbase + hangul_tcount) {
5799
2.26k
          input[composition_count] += input[++input_count] - hangul_tbase;
5800
2.26k
        }
5801
6.06k
      }
5802
96.7k
    } else if (input[input_count] >= hangul_sbase &&
5803
7.77k
               input[input_count] < hangul_sbase + hangul_scount) {
5804
0
      if ((input[input_count] - hangul_sbase) % hangul_tcount == 0 &&
5805
0
          input_count + 1 < input.size() &&
5806
0
          input[input_count + 1] > hangul_tbase &&
5807
0
          input[input_count + 1] < hangul_tbase + hangul_tcount) {
5808
0
        input[composition_count] += input[++input_count] - hangul_tbase;
5809
0
      }
5810
96.7k
    } else if (input[input_count] < 0x110000) {
5811
96.7k
      const uint16_t* composition =
5812
96.7k
          composition_block_row(composition_index[input[input_count] >> 8]) +
5813
96.7k
          (input[input_count] % 256);
5814
96.7k
      size_t initial_composition_count = composition_count;
5815
166k
      for (int32_t previous_ccc = -1; input_count + 1 < input.size();
5816
122k
           input_count++) {
5817
122k
        uint8_t ccc = get_ccc(input[input_count + 1]);
5818
5819
122k
        if (composition[1] != composition[0] && previous_ccc < ccc) {
5820
68.1k
          int left = composition[0];
5821
68.1k
          int right = composition[1];
5822
68.1k
          if (left < 0 || right < left ||
5823
68.1k
              static_cast<size_t>(right) > composition_data_size) {
5824
0
            break;
5825
0
          }
5826
166k
          while (left + 2 < right) {
5827
98.7k
            int middle = left + (((right - left) >> 1) & ~1);
5828
98.7k
            if (composition_data[static_cast<size_t>(middle)] <=
5829
98.7k
                input[input_count + 1]) {
5830
41.8k
              left = middle;
5831
41.8k
            }
5832
98.7k
            if (composition_data[static_cast<size_t>(middle)] >=
5833
98.7k
                input[input_count + 1]) {
5834
80.7k
              right = middle;
5835
80.7k
            }
5836
98.7k
          }
5837
68.1k
          if (static_cast<size_t>(left + 1) < composition_data_size &&
5838
68.1k
              composition_data[static_cast<size_t>(left)] ==
5839
68.1k
                  input[input_count + 1]) {
5840
49.4k
            char32_t composed = composition_data[static_cast<size_t>(left + 1)];
5841
49.4k
            input[initial_composition_count] = composed;
5842
49.4k
            composition =
5843
49.4k
                composition_block_row(composition_index[composed >> 8]) +
5844
49.4k
                (composed % 256);
5845
49.4k
            continue;
5846
49.4k
          }
5847
68.1k
        }
5848
5849
73.2k
        if (ccc == 0) {
5850
53.1k
          break;
5851
53.1k
        }
5852
20.1k
        previous_ccc = ccc;
5853
20.1k
        input[++composition_count] = input[input_count + 1];
5854
20.1k
      }
5855
96.7k
    }
5856
105k
  }
5857
5858
45.7k
  if (composition_count < input_count) {
5859
43.4k
    input.resize(composition_count);
5860
43.4k
  }
5861
45.7k
}
5862
5863
17.1k
bool normalize(std::u32string& input) {
5864
  /**
5865
   * Normalize the characters according to IDNA (Unicode Normalization Form C).
5866
   * @see https://www.unicode.org/reports/tr46/#ProcessingStepNormalize
5867
   */
5868
17.1k
  if (!ensure_tables() || decomposition_index == nullptr ||
5869
17.1k
      composition_index == nullptr) {
5870
0
    return false;
5871
0
  }
5872
17.1k
  if (is_already_nfc(input)) {
5873
0
    return true;
5874
0
  }
5875
17.1k
  decompose_nfc(input);
5876
17.1k
  compose(input);
5877
17.1k
  return true;
5878
17.1k
}
5879
5880
}  // namespace ada::idna
5881
/* end file src/normalization.cpp */
5882
/* begin file src/punycode.cpp */
5883
/* begin file include/ada/idna/punycode.h */
5884
#ifndef ADA_IDNA_PUNYCODE_H
5885
#define ADA_IDNA_PUNYCODE_H
5886
5887
#include <string>
5888
#include <string_view>
5889
5890
namespace ada::idna {
5891
5892
bool punycode_to_utf32(std::string_view input, std::u32string& out);
5893
bool verify_punycode(std::string_view input);
5894
bool utf32_to_punycode(std::u32string_view input, std::string& out);
5895
5896
}  // namespace ada::idna
5897
5898
#endif  // ADA_IDNA_PUNYCODE_H
5899
/* end file include/ada/idna/punycode.h */
5900
5901
#include <cstdint>
5902
5903
namespace ada::idna {
5904
5905
constexpr int32_t base = 36;
5906
constexpr int32_t tmin = 1;
5907
constexpr int32_t tmax = 26;
5908
constexpr int32_t skew = 38;
5909
constexpr int32_t damp = 700;
5910
constexpr int32_t initial_bias = 72;
5911
constexpr uint32_t initial_n = 128;
5912
5913
240k
static constexpr int32_t char_to_digit_value(char value) {
5914
240k
  if (value >= 'a' && value <= 'z') return value - 'a';
5915
94.5k
  if (value >= '0' && value <= '9') return value - '0' + 26;
5916
977
  return -1;
5917
94.5k
}
5918
5919
222k
static constexpr char digit_to_char(int32_t digit) {
5920
222k
  return digit < 26 ? char(digit + 97) : char(digit + 22);
5921
222k
}
5922
5923
173k
static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) {
5924
173k
  if (firsttime) {
5925
77.6k
    d = d / damp;
5926
96.3k
  } else {
5927
96.3k
    d = d / 2;
5928
96.3k
  }
5929
173k
  d += d / n;
5930
173k
  int32_t k = 0;
5931
230k
  while (d > ((base - tmin) * tmax) / 2) {
5932
56.9k
    d /= base - tmin;
5933
56.9k
    k += base;
5934
56.9k
  }
5935
173k
  return k + (((base - tmin + 1) * d) / (d + skew));
5936
173k
}
5937
5938
31.7k
bool punycode_to_utf32(std::string_view input, std::u32string &out) {
5939
31.7k
  int32_t written_out{0};
5940
31.7k
  out.reserve(out.size() + input.size());
5941
31.7k
  uint32_t n = initial_n;
5942
31.7k
  int32_t i = 0;
5943
31.7k
  int32_t bias = initial_bias;
5944
  // grab ascii content
5945
  // RFC 3492 section 6.2: copy the code points before the last delimiter,
5946
  // then consume the delimiter only "if more than zero code points were
5947
  // consumed". With a leading delimiter, b == 0, decoding starts at the
5948
  // delimiter itself, which is not a digit, and fails. This matches the
5949
  // reference implementation in appendix C (`in = b > 0 ? b + 1 : 0`).
5950
31.7k
  size_t end_of_ascii = input.find_last_of('-');
5951
31.7k
  if (end_of_ascii != std::string_view::npos && end_of_ascii > 0) {
5952
21.4k
    for (uint8_t c : input.substr(0, end_of_ascii)) {
5953
21.4k
      if (c >= 0x80) {
5954
0
        return false;
5955
0
      }
5956
21.4k
      out.push_back(c);
5957
21.4k
      written_out++;
5958
21.4k
    }
5959
5.34k
    input.remove_prefix(end_of_ascii + 1);
5960
5.34k
  }
5961
131k
  while (!input.empty()) {
5962
104k
    int32_t oldi = i;
5963
104k
    int32_t w = 1;
5964
242k
    for (int32_t k = base;; k += base) {
5965
242k
      if (input.empty()) {
5966
1.70k
        return false;
5967
1.70k
      }
5968
240k
      uint8_t code_point = input.front();
5969
240k
      input.remove_prefix(1);
5970
240k
      int32_t digit = char_to_digit_value(code_point);
5971
240k
      if (digit < 0) {
5972
977
        return false;
5973
977
      }
5974
240k
      if (digit > (0x7fffffff - i) / w) {
5975
87
        return false;
5976
87
      }
5977
239k
      i = i + digit * w;
5978
239k
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
5979
239k
      if (digit < t) {
5980
101k
        break;
5981
101k
      }
5982
138k
      if (w > 0x7fffffff / (base - t)) {
5983
0
        return false;
5984
0
      }
5985
138k
      w = w * (base - t);
5986
138k
    }
5987
101k
    bias = adapt(i - oldi, written_out + 1, oldi == 0);
5988
101k
    if (i / (written_out + 1) > int32_t(0x7fffffff - n)) {
5989
1.27k
      return false;
5990
1.27k
    }
5991
100k
    n = n + i / (written_out + 1);
5992
100k
    i = i % (written_out + 1);
5993
100k
    if (n < 0x80) {
5994
0
      return false;
5995
0
    }
5996
100k
    out.insert(out.begin() + i, n);
5997
100k
    written_out++;
5998
100k
    ++i;
5999
100k
  }
6000
  // See https://github.com/whatwg/url/issues/803
6001
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
6002
27.7k
  if (out.size() >= 4 && out[0] == U'x' && out[1] == U'n' && out[2] == U'-' &&
6003
1.36k
      out[3] == U'-') {
6004
144
    return false;
6005
144
  }
6006
27.5k
  return true;
6007
27.7k
}
6008
6009
0
bool verify_punycode(std::string_view input) {
6010
  // Track only the first 4 decoded code points to check for the "xn--" prefix.
6011
  // This avoids heap allocation while still detecting double-encoded ACE
6012
  // labels.
6013
0
  uint32_t first4[4]{};
6014
0
  size_t written_out{0};
6015
0
  uint32_t n = initial_n;
6016
0
  int32_t i = 0;
6017
0
  int32_t bias = initial_bias;
6018
  // grab ascii content
6019
0
  size_t end_of_ascii = input.find_last_of('-');
6020
0
  if (end_of_ascii != std::string_view::npos) {
6021
0
    for (uint8_t c : input.substr(0, end_of_ascii)) {
6022
0
      if (c >= 0x80) {
6023
0
        return false;
6024
0
      }
6025
0
      if (written_out < 4) {
6026
0
        first4[written_out] = c;
6027
0
      }
6028
0
      written_out++;
6029
0
    }
6030
0
    input.remove_prefix(end_of_ascii + 1);
6031
0
  }
6032
0
  while (!input.empty()) {
6033
0
    int32_t oldi = i;
6034
0
    int32_t w = 1;
6035
0
    for (int32_t k = base;; k += base) {
6036
0
      if (input.empty()) {
6037
0
        return false;
6038
0
      }
6039
0
      uint8_t code_point = input.front();
6040
0
      input.remove_prefix(1);
6041
0
      int32_t digit = char_to_digit_value(code_point);
6042
0
      if (digit < 0) {
6043
0
        return false;
6044
0
      }
6045
0
      if (digit > (0x7fffffff - i) / w) {
6046
0
        return false;
6047
0
      }
6048
0
      i = i + digit * w;
6049
0
      int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
6050
0
      if (digit < t) {
6051
0
        break;
6052
0
      }
6053
0
      if (w > 0x7fffffff / (base - t)) {
6054
0
        return false;
6055
0
      }
6056
0
      w = w * (base - t);
6057
0
    }
6058
0
    bias = adapt(i - oldi, int32_t(written_out + 1), oldi == 0);
6059
0
    if (i / (written_out + 1) > 0x7fffffff - n) {
6060
0
      return false;
6061
0
    }
6062
0
    n = n + i / int32_t(written_out + 1);
6063
0
    i = i % int32_t(written_out + 1);
6064
0
    if (n < 0x80) {
6065
0
      return false;
6066
0
    }
6067
    // Simulate insert at position i, maintaining only the first 4 slots.
6068
0
    size_t insert_pos = size_t(i);
6069
0
    if (insert_pos < 4) {
6070
0
      for (size_t j = 3; j > insert_pos; j--) {
6071
0
        first4[j] = first4[j - 1];
6072
0
      }
6073
0
      first4[insert_pos] = n;
6074
0
    }
6075
0
    written_out++;
6076
0
    ++i;
6077
0
  }
6078
  // See https://github.com/whatwg/url/issues/803
6079
  // Reject labels whose decoded form begins with "xn--" (double-encoded ACE).
6080
0
  if (written_out >= 4 && first4[0] == U'x' && first4[1] == U'n' &&
6081
0
      first4[2] == U'-' && first4[3] == U'-') {
6082
0
    return false;
6083
0
  }
6084
0
  return true;
6085
0
}
6086
6087
48.7k
bool utf32_to_punycode(std::u32string_view input, std::string &out) {
6088
48.7k
  out.reserve(input.size() + out.size());
6089
48.7k
  uint32_t n = initial_n;
6090
48.7k
  int32_t d = 0;
6091
48.7k
  int32_t bias = initial_bias;
6092
48.7k
  size_t h = 0;
6093
  // first push the ascii content
6094
137k
  for (uint32_t c : input) {
6095
137k
    if (c < 0x80) {
6096
64.6k
      ++h;
6097
64.6k
      out.push_back(char(c));
6098
64.6k
    }
6099
137k
    if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) {
6100
0
      return false;
6101
0
    }
6102
137k
  }
6103
48.7k
  size_t b = h;
6104
48.7k
  if (b > 0) {
6105
15.6k
    out.push_back('-');
6106
15.6k
  }
6107
119k
  while (h < input.size()) {
6108
70.9k
    uint32_t m = 0x10FFFF;
6109
266k
    for (auto code_point : input) {
6110
266k
      if (code_point >= n && code_point < m) m = code_point;
6111
266k
    }
6112
6113
70.9k
    if ((m - n) > (0x7fffffff - d) / (h + 1)) {
6114
0
      return false;
6115
0
    }
6116
70.9k
    d = d + int32_t((m - n) * (h + 1));
6117
70.9k
    n = m;
6118
266k
    for (auto c : input) {
6119
266k
      if (c < n) {
6120
154k
        if (d == 0x7fffffff) {
6121
0
          return false;
6122
0
        }
6123
154k
        ++d;
6124
154k
      }
6125
266k
      if (c == n) {
6126
72.4k
        int32_t q = d;
6127
222k
        for (int32_t k = base;; k += base) {
6128
222k
          int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
6129
6130
222k
          if (q < t) {
6131
72.4k
            break;
6132
72.4k
          }
6133
150k
          out.push_back(digit_to_char(t + ((q - t) % (base - t))));
6134
150k
          q = (q - t) / (base - t);
6135
150k
        }
6136
72.4k
        out.push_back(digit_to_char(q));
6137
72.4k
        bias = adapt(d, int32_t(h + 1), h == b);
6138
72.4k
        d = 0;
6139
72.4k
        ++h;
6140
72.4k
      }
6141
266k
    }
6142
70.9k
    ++d;
6143
70.9k
    ++n;
6144
70.9k
  }
6145
48.7k
  return true;
6146
48.7k
}
6147
6148
}  // namespace ada::idna
6149
/* end file src/punycode.cpp */
6150
/* begin file src/validity.cpp */
6151
6152
#include <algorithm>
6153
#include <span>
6154
#include <string_view>
6155
6156
namespace ada::idna {
6157
6158
// Values stored in dir_value; keep in sync with BIDI_CLASSES in
6159
// scripts/unicode_data_table.py.
6160
enum direction : uint8_t {
6161
  NONE,
6162
  BN,
6163
  CS,
6164
  ES,
6165
  ON,
6166
  EN,
6167
  L,
6168
  R,
6169
  NSM,
6170
  AL,
6171
  AN,
6172
  ET,
6173
  WS,
6174
  RLO,
6175
  LRO,
6176
  PDF,
6177
  RLE,
6178
  RLI,
6179
  FSI,
6180
  PDI,
6181
  LRI,
6182
  B,
6183
  S,
6184
  LRE
6185
};
6186
6187
// Values stored in joining_value; keep in sync with JOINING_TYPES in
6188
// scripts/unicode_data_table.py. Code points without a range are U.
6189
enum class joining_type : uint8_t { U, C, D, L, R, T };
6190
6191
// Bidi direction and Joining_Type ranges live in the compressed blob as const
6192
// SoA arrays (dir_* and joining_*). See table_store.hpp layout asserts.
6193
// Regenerate with: python3 scripts/unicode_data_table.py --write
6194
6195
// Defined in normalization.cpp.
6196
uint8_t get_ccc(char32_t c) noexcept;
6197
6198
// CheckJoiners and CheckBidi are true for URL specification.
6199
6200
// Returns the index of the range [start[i], last[i]] that contains code_point,
6201
// or count if there is none. `last` must be sorted.
6202
inline static size_t find_range(const uint32_t* start, const uint32_t* last,
6203
391k
                                size_t count, uint32_t code_point) noexcept {
6204
391k
  size_t lo = 0, hi = count;
6205
4.55M
  while (lo < hi) {
6206
4.16M
    size_t mid = lo + (hi - lo) / 2;
6207
4.16M
    if (last[mid] < code_point) {
6208
1.17M
      lo = mid + 1;
6209
2.98M
    } else {
6210
2.98M
      hi = mid;
6211
2.98M
    }
6212
4.16M
  }
6213
391k
  return lo < count && code_point >= start[lo] ? lo : count;
6214
391k
}
6215
6216
// Assumes ensure_tables() has already been called by is_label_valid().
6217
387k
inline static direction find_direction(uint32_t code_point) noexcept {
6218
387k
  size_t i = find_range(dir_start, dir_final, dir_table_count, code_point);
6219
387k
  return i == dir_table_count ? direction::NONE
6220
387k
                              : static_cast<direction>(dir_value[i]);
6221
387k
}
6222
6223
// Assumes ensure_tables() has already been called by is_label_valid().
6224
3.80k
inline static joining_type find_joining_type(uint32_t code_point) noexcept {
6225
3.80k
  size_t i =
6226
3.80k
      find_range(joining_start, joining_final, joining_table_count, code_point);
6227
3.80k
  return i == joining_table_count ? joining_type::U
6228
3.80k
                                  : static_cast<joining_type>(joining_value[i]);
6229
3.80k
}
6230
6231
// The ContextJ rules for U+200C and U+200D from RFC 5892 Appendix A.
6232
67.9k
inline static bool is_contextj_valid(std::u32string_view label) noexcept {
6233
67.9k
  constexpr uint8_t virama_ccc = 9;
6234
310k
  for (size_t i = 0; i < label.size(); i++) {
6235
245k
    if (label[i] != 0x200C && label[i] != 0x200D) {
6236
242k
      continue;
6237
242k
    }
6238
    // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True;
6239
2.77k
    if (i > 0 && get_ccc(label[i - 1]) == virama_ccc) {
6240
84
      continue;
6241
84
    }
6242
2.68k
    if (label[i] == 0x200D) {
6243
144
      return false;
6244
144
    }
6245
    // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C
6246
    //    (Joining_Type:T)*(Joining_Type:{R,D})) Then True;
6247
2.54k
    joining_type before = joining_type::U;
6248
2.69k
    for (size_t j = i; j > 0;) {
6249
2.60k
      before = find_joining_type(label[--j]);
6250
2.60k
      if (before != joining_type::T) {
6251
2.45k
        break;
6252
2.45k
      }
6253
2.60k
    }
6254
2.54k
    if (before != joining_type::L && before != joining_type::D) {
6255
1.33k
      return false;
6256
1.33k
    }
6257
1.21k
    joining_type after = joining_type::U;
6258
1.38k
    for (size_t j = i + 1; j < label.size(); j++) {
6259
1.20k
      after = find_joining_type(label[j]);
6260
1.20k
      if (after != joining_type::T) {
6261
1.04k
        break;
6262
1.04k
      }
6263
1.20k
    }
6264
1.21k
    if (after != joining_type::R && after != joining_type::D) {
6265
1.04k
      return false;
6266
1.04k
    }
6267
1.21k
  }
6268
65.3k
  return true;
6269
67.9k
}
6270
6271
inline static size_t find_last_not_of_nsm(
6272
65.3k
    const std::u32string_view label) noexcept {
6273
73.7k
  for (int i = static_cast<int>(label.size() - 1); i >= 0; i--)
6274
73.7k
    if (find_direction(label[i]) != direction::NSM) return i;
6275
6276
0
  return std::u32string_view::npos;
6277
65.3k
}
6278
6279
// An RTL label is a label that contains at least one character of type R, AL,
6280
// or AN. https://www.rfc-editor.org/rfc/rfc5893#section-2
6281
65.3k
inline static bool is_rtl_label(const std::u32string_view label) noexcept {
6282
65.3k
  const size_t mask =
6283
65.3k
      (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN);
6284
6285
65.3k
  size_t directions = 0;
6286
304k
  for (size_t i = 0; i < label.size(); i++) {
6287
239k
    directions |= 1u << find_direction(label[i]);
6288
239k
  }
6289
65.3k
  return (directions & mask) != 0;
6290
65.3k
}
6291
6292
69.0k
bool is_label_valid(const std::u32string_view label) {
6293
69.0k
  if (label.empty()) {
6294
0
    return true;
6295
0
  }
6296
69.0k
  if (!ensure_tables() || combining_ranges == nullptr || dir_start == nullptr ||
6297
69.0k
      dir_final == nullptr || dir_value == nullptr ||
6298
69.0k
      joining_start == nullptr || joining_final == nullptr ||
6299
69.0k
      joining_value == nullptr) {
6300
0
    return false;
6301
0
  }
6302
6303
  ///////////////
6304
  // We have a normalization step which ensures that we are in NFC.
6305
  // If we receive punycode, we normalize and check that the normalized
6306
  // version matches the original.
6307
  // --------------------------------------
6308
  // The label must be in Unicode Normalization Form NFC.
6309
6310
  // Current URL standard indicatest that CheckHyphens is set to false.
6311
  // ---------------------------------------
6312
  // If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character
6313
  // in both the third and fourth positions. If CheckHyphens, the label must
6314
  // neither begin nor end with a U+002D HYPHEN-MINUS character.
6315
6316
  // This is not necessary because we segment the
6317
  // labels by '.'.
6318
  // ---------------------------------------
6319
  // The label must not contain a U+002E ( . ) FULL STOP.
6320
  // if (label.find('.') != std::string_view::npos) return false;
6321
6322
  // The label must not begin with a combining mark.
6323
  // Range membership via lower_bound on range end.
6324
69.0k
  const std::span<const uint32_t[2]> comb_span{combining_ranges,
6325
69.0k
                                               combining_range_count};
6326
69.0k
  const auto comb_it = std::ranges::lower_bound(
6327
585k
      comb_span, label.front(), {}, [](const auto& range) { return range[1]; });
6328
69.0k
  if (comb_it != comb_span.end() && label.front() >= (*comb_it)[0]) {
6329
1.14k
    return false;
6330
1.14k
  }
6331
  // We verify this next step as part of the mapping:
6332
  // ---------------------------------------------
6333
  // Each code point in the label must only have certain status values
6334
  // according to Section 5, IDNA Mapping Table:
6335
  // - For Transitional Processing, each value must be valid.
6336
  // - For Nontransitional Processing, each value must be either valid or
6337
  // deviation.
6338
6339
  // If CheckJoiners, the label must satisfy the ContextJ rules from Appendix
6340
  // A, in The Unicode Code Points and Internationalized Domain Names for
6341
  // Applications (IDNA) [IDNA2008].
6342
67.9k
  if (!is_contextj_valid(label)) {
6343
2.51k
    return false;
6344
2.51k
  }
6345
6346
  // If CheckBidi, and if the domain name is a  Bidi domain name, then the label
6347
  // must satisfy all six of the numbered conditions in [IDNA2008] RFC 5893,
6348
  // Section 2.
6349
6350
  // The following rule, consisting of six conditions, applies to labels
6351
  // in Bidi domain names.  The requirements that this rule satisfies are
6352
  // described in Section 3.  All of the conditions must be satisfied for
6353
  // the rule to be satisfied.
6354
  //
6355
  //  1.  The first character must be a character with Bidi property L, R,
6356
  //     or AL.  If it has the R or AL property, it is an RTL label; if it
6357
  //     has the L property, it is an LTR label.
6358
  //
6359
  //  2.  In an RTL label, only characters with the Bidi properties R, AL,
6360
  //      AN, EN, ES, CS, ET, ON, BN, or NSM are allowed.
6361
  //
6362
  //   3.  In an RTL label, the end of the label must be a character with
6363
  //       Bidi property R, AL, EN, or AN, followed by zero or more
6364
  //       characters with Bidi property NSM.
6365
  //
6366
  //   4.  In an RTL label, if an EN is present, no AN may be present, and
6367
  //       vice versa.
6368
  //
6369
  //  5.  In an LTR label, only characters with the Bidi properties L, EN,
6370
  //       ES, CS, ET, ON, BN, or NSM are allowed.
6371
  //
6372
  //   6.  In an LTR label, the end of the label must be a character with
6373
  //       Bidi property L or EN, followed by zero or more characters with
6374
  //       Bidi property NSM.
6375
6376
65.3k
  size_t last_non_nsm_char = find_last_not_of_nsm(label);
6377
65.3k
  if (last_non_nsm_char == std::u32string_view::npos) {
6378
0
    return false;
6379
0
  }
6380
6381
  // A "Bidi domain name" is a domain name that contains at least one RTL label.
6382
  // The following rule, consisting of six conditions, applies to labels in Bidi
6383
  // domain names.
6384
65.3k
  if (is_rtl_label(label)) {
6385
    // The first character must be a character with Bidi property L, R,
6386
    // or AL. If it has the R or AL property, it is an RTL label; if it
6387
    // has the L property, it is an LTR label.
6388
6389
13.6k
    if (find_direction(label[0]) == direction::L) {
6390
      // Eval as LTR
6391
6392
      // In an LTR label, only characters with the Bidi properties L, EN,
6393
      // ES, CS, ET, ON, BN, or NSM are allowed.
6394
20.2k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
6395
20.2k
        const direction d = find_direction(label[i]);
6396
20.2k
        if (!(d == direction::L || d == direction::EN || d == direction::ES ||
6397
11.3k
              d == direction::CS || d == direction::ET || d == direction::ON ||
6398
6.99k
              d == direction::BN || d == direction::NSM)) {
6399
3.68k
          return false;
6400
3.68k
        }
6401
20.2k
      }
6402
6403
0
      const direction last_dir = find_direction(label[last_non_nsm_char]);
6404
0
      if (!(last_dir == direction::L || last_dir == direction::EN)) {
6405
0
        return false;
6406
0
      }
6407
6408
0
      return true;
6409
6410
9.98k
    } else {
6411
      // Eval as RTL
6412
6413
      // The first character must be R or AL; a leading AN (or any other
6414
      // direction) does not start a valid RTL label.
6415
9.98k
      const direction first_dir = find_direction(label[0]);
6416
9.98k
      if (first_dir != direction::R && first_dir != direction::AL) {
6417
843
        return false;
6418
843
      }
6419
6420
9.13k
      bool has_an = false;
6421
9.13k
      bool has_en = false;
6422
36.3k
      for (size_t i = 0; i <= last_non_nsm_char; i++) {
6423
30.6k
        const direction d = find_direction(label[i]);
6424
6425
        // In an RTL label, if an EN is present, no AN may be present, and vice
6426
        // versa.
6427
30.6k
        if ((d == direction::EN && ((has_en = true) && has_an)) ||
6428
30.5k
            (d == direction::AN && ((has_an = true) && has_en))) {
6429
180
          return false;
6430
180
        }
6431
6432
30.4k
        if (!(d == direction::R || d == direction::AL || d == direction::AN ||
6433
14.3k
              d == direction::EN || d == direction::ES || d == direction::CS ||
6434
9.05k
              d == direction::ET || d == direction::ON || d == direction::BN ||
6435
3.13k
              d == direction::NSM)) {
6436
1.50k
          return false;
6437
1.50k
        }
6438
6439
28.9k
        if (i == last_non_nsm_char &&
6440
7.45k
            !(d == direction::R || d == direction::AL || d == direction::AN ||
6441
2.42k
              d == direction::EN)) {
6442
1.79k
          return false;
6443
1.79k
        }
6444
28.9k
      }
6445
6446
5.65k
      return true;
6447
9.13k
    }
6448
13.6k
  }
6449
6450
51.7k
  return true;
6451
65.3k
}
6452
6453
}  // namespace ada::idna
6454
/* end file src/validity.cpp */
6455
/* begin file src/to_ascii.cpp */
6456
/* begin file include/ada/idna/to_ascii.h */
6457
#ifndef ADA_IDNA_TO_ASCII_H
6458
#define ADA_IDNA_TO_ASCII_H
6459
6460
#include <string>
6461
#include <string_view>
6462
6463
/* begin file include/ada/idna/limits.h */
6464
#ifndef ADA_IDNA_LIMITS_H
6465
#define ADA_IDNA_LIMITS_H
6466
6467
#include <cstddef>
6468
6469
namespace ada::idna {
6470
6471
// Maximum accepted UTF-8 domain length for non-ASCII to_ascii input and for
6472
// to_unicode input.
6473
// Bounds heap growth under untrusted input (DoS resistance). DNS wire limits
6474
// are smaller; this allows long Unicode labels used in URL tests/fixtures.
6475
inline constexpr size_t max_domain_input_bytes = 16384;
6476
6477
}  // namespace ada::idna
6478
6479
#endif  // ADA_IDNA_LIMITS_H
6480
/* end file include/ada/idna/limits.h */
6481
6482
namespace ada::idna {
6483
6484
// Converts a domain (e.g., www.google.com) possibly containing international
6485
// characters to an ascii domain (with punycode). It will not do percent
6486
// decoding: percent decoding should be done prior to calling this function. We
6487
// do not remove tabs and spaces, they should have been removed prior to calling
6488
// this function. We also do not trim control characters. We also assume that
6489
// the input is not empty. We return "" on error. Non-ASCII inputs longer than
6490
// max_domain_input_bytes are rejected; ASCII inputs of any length are accepted
6491
// (they are only lowercased).
6492
//
6493
// This function may accept or even produce invalid domains (WHATWG carve-outs).
6494
std::string to_ascii(std::string_view ut8_string);
6495
6496
// Same as to_ascii, but writes into `out` and returns false on error without
6497
// relying on empty-string ambiguity.
6498
[[nodiscard]] bool to_ascii(std::string_view ut8_string, std::string& out);
6499
6500
// Returns true if the string contains a forbidden code point according to the
6501
// WHATGL URL specification:
6502
// https://url.spec.whatwg.org/#forbidden-domain-code-point
6503
bool contains_forbidden_domain_code_point(std::string_view ascii_string);
6504
6505
bool constexpr is_ascii(std::u32string_view view);
6506
bool constexpr is_ascii(std::string_view view);
6507
6508
}  // namespace ada::idna
6509
6510
#endif  // ADA_IDNA_TO_ASCII_H
6511
/* end file include/ada/idna/to_ascii.h */
6512
6513
#include <algorithm>
6514
#include <cstdint>
6515
#include <cstring>
6516
#include <ranges>
6517
6518
/* begin file include/ada/idna/validity.h */
6519
#ifndef ADA_IDNA_VALIDITY_H
6520
#define ADA_IDNA_VALIDITY_H
6521
6522
#include <string>
6523
#include <string_view>
6524
6525
namespace ada::idna {
6526
6527
/**
6528
 * @see https://www.unicode.org/reports/tr46/#Validity_Criteria
6529
 */
6530
bool is_label_valid(std::u32string_view label);
6531
6532
}  // namespace ada::idna
6533
6534
#endif  // ADA_IDNA_VALIDITY_H
6535
/* end file include/ada/idna/validity.h */
6536
6537
#ifdef ADA_USE_SIMDUTF
6538
#include "simdutf.h"
6539
#endif
6540
6541
namespace ada::idna {
6542
6543
179k
bool constexpr is_ascii(std::u32string_view view) {
6544
465k
  for (uint32_t c : view) {
6545
465k
    if (c >= 0x80) {
6546
160k
      return false;
6547
160k
    }
6548
465k
  }
6549
18.9k
  return true;
6550
179k
}
6551
6552
100k
bool constexpr is_ascii(std::string_view view) {
6553
449k
  for (uint8_t c : view) {
6554
449k
    if (c >= 0x80) {
6555
73.9k
      return false;
6556
73.9k
    }
6557
449k
  }
6558
26.7k
  return true;
6559
100k
}
6560
6561
constexpr static uint8_t is_forbidden_domain_code_point_table[] = {
6562
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6563
    1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
6564
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 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, 1, 1, 1, 1, 0,
6566
    0, 0, 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, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6568
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6569
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6570
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6571
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6572
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
6573
6574
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
6575
6576
0
inline bool is_forbidden_domain_code_point(const char c) noexcept {
6577
0
  return is_forbidden_domain_code_point_table[uint8_t(c)];
6578
0
}
6579
6580
0
bool contains_forbidden_domain_code_point(std::string_view view) {
6581
0
  return std::ranges::any_of(view, is_forbidden_domain_code_point);
6582
0
}
6583
6584
// Per the WHATWG URL "domain to ASCII" algorithm, when beStrict is false and
6585
// the input domain is an ASCII string, the result is the input lowercased,
6586
// regardless of the outcome of Unicode ToASCII.
6587
//
6588
// See https://url.spec.whatwg.org/#concept-domain-to-ascii
6589
26.7k
static void from_ascii_to_ascii(std::string_view ut8_string, std::string& out) {
6590
26.7k
  out.assign(ut8_string);
6591
26.7k
  ascii_map(out.data(), out.size());
6592
26.7k
}
6593
6594
// Append ASCII code units from a UTF-32 label (all values < 0x80).
6595
39.4k
static void append_ascii_label(std::string& out, std::u32string_view label) {
6596
39.4k
  const size_t old = out.size();
6597
39.4k
  out.resize(old + label.size());
6598
39.4k
  char* dest = out.data() + old;
6599
420k
  for (char32_t c : label) {
6600
420k
    *dest++ = static_cast<char>(c);
6601
420k
  }
6602
39.4k
}
6603
6604
// True if label begins with "xn--" (already lowercased by mapping).
6605
98.6k
static bool is_ace_prefix(std::u32string_view label) noexcept {
6606
98.6k
  return label.size() >= 4 && label[0] == U'x' && label[1] == U'n' &&
6607
34.4k
         label[2] == U'-' && label[3] == U'-';
6608
98.6k
}
6609
6610
100k
[[nodiscard]] bool to_ascii(std::string_view ut8_string, std::string& out) {
6611
100k
  out.clear();
6612
  // The ASCII path is a single same-size copy, so it needs no length bound.
6613
  // Checking first would reject the (longer) ASCII output of a non-ASCII input
6614
  // that was accepted, breaking to_ascii(to_ascii(x)) == to_ascii(x).
6615
100k
  if (is_ascii(ut8_string)) {
6616
26.7k
    from_ascii_to_ascii(ut8_string, out);
6617
26.7k
    return true;
6618
26.7k
  }
6619
73.9k
  if (ut8_string.size() > max_domain_input_bytes) {
6620
0
    return false;
6621
0
  }
6622
6623
#ifdef ADA_USE_SIMDUTF
6624
  size_t utf32_length =
6625
      simdutf::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
6626
  if (utf32_length == 0 && !ut8_string.empty()) {
6627
    return false;
6628
  }
6629
  std::u32string working(utf32_length, U'\0');
6630
  size_t actual_utf32_length = simdutf::convert_utf8_to_utf32(
6631
      ut8_string.data(), ut8_string.size(), working.data());
6632
#else
6633
73.9k
  size_t utf32_length =
6634
73.9k
      ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size());
6635
73.9k
  if (utf32_length == 0 && !ut8_string.empty()) {
6636
507
    return false;
6637
507
  }
6638
73.4k
  std::u32string working(utf32_length, U'\0');
6639
73.4k
  size_t actual_utf32_length = ada::idna::utf8_to_utf32(
6640
73.4k
      ut8_string.data(), ut8_string.size(), working.data());
6641
73.4k
#endif
6642
73.4k
  if (actual_utf32_length == 0 || actual_utf32_length != utf32_length) {
6643
4.66k
    return false;
6644
4.66k
  }
6645
68.7k
  working.resize(actual_utf32_length);
6646
6647
  // Map into a second buffer with exact sizing (no growth reallocs).
6648
68.7k
  std::u32string mapped;
6649
68.7k
  if (!ada::idna::map(working, mapped)) {
6650
1.21k
    return false;
6651
1.21k
  }
6652
  // Drop UTF-32 input; reuse `working` as scratch for ACE validation below.
6653
67.5k
  working.clear();
6654
6655
  // Skip NFC when already normalized (ASCII is a fast subset of this check).
6656
67.5k
  if (!is_ascii(mapped) && !is_already_nfc(mapped)) {
6657
9.17k
    if (!normalize(mapped)) {
6658
0
      return false;
6659
0
    }
6660
9.17k
  }
6661
6662
  // Estimate ASCII output size (punycode may expand non-ASCII labels).
6663
67.5k
  out.reserve(mapped.size() + 8);
6664
6665
  // Walk labels with a single pointer scan (no repeated string::find).
6666
67.5k
  const char32_t* p = mapped.data();
6667
67.5k
  const char32_t* const end = p + mapped.size();
6668
67.5k
  std::u32string post_map;
6669
6670
135k
  while (p < end) {
6671
101k
    const char32_t* label_begin = p;
6672
733k
    while (p < end && *p != U'.') {
6673
632k
      ++p;
6674
632k
    }
6675
101k
    const size_t label_size = static_cast<size_t>(p - label_begin);
6676
101k
    std::u32string_view label_view(label_begin, label_size);
6677
101k
    const bool is_last_label = (p == end);
6678
101k
    if (p < end) {
6679
35.2k
      ++p;  // skip dot
6680
35.2k
    }
6681
6682
101k
    if (label_size == 0) {
6683
      // empty label
6684
98.6k
    } else if (is_ace_prefix(label_view)) {
6685
401k
      for (char32_t c : label_view) {
6686
401k
        if (c >= 0x80) {
6687
555
          out.clear();
6688
555
          return false;
6689
555
        }
6690
401k
      }
6691
31.7k
      append_ascii_label(out, label_view);
6692
31.7k
      std::string_view puny_segment_ascii(
6693
31.7k
          out.data() + (out.size() - label_size) + 4, label_size - 4);
6694
31.7k
      working.clear();
6695
31.7k
      if (!ada::idna::punycode_to_utf32(puny_segment_ascii, working)) {
6696
4.18k
        out.clear();
6697
4.18k
        return false;
6698
4.18k
      }
6699
27.5k
      if (is_ascii(working)) {
6700
1.38k
        out.clear();
6701
1.38k
        return false;
6702
1.38k
      }
6703
26.1k
      if (!ada::idna::map(working, post_map) || working != post_map) {
6704
8.20k
        out.clear();
6705
8.20k
        return false;
6706
8.20k
      }
6707
      // Mapping must be stable; NFC must not change the mapped form either.
6708
17.9k
      if (!is_ascii(post_map) && !is_already_nfc(post_map)) {
6709
7.92k
        if (!normalize(post_map) || post_map != working) {
6710
7.56k
          out.clear();
6711
7.56k
          return false;
6712
7.56k
        }
6713
7.92k
      }
6714
10.4k
      if (post_map.empty() || !is_label_valid(post_map)) {
6715
1.79k
        out.clear();
6716
1.79k
        return false;
6717
1.79k
      }
6718
66.2k
    } else if (is_ascii(label_view)) {
6719
7.66k
      append_ascii_label(out, label_view);
6720
58.6k
    } else {
6721
58.6k
      if (!is_label_valid(label_view)) {
6722
9.87k
        out.clear();
6723
9.87k
        return false;
6724
9.87k
      }
6725
48.7k
      out.append("xn--");
6726
48.7k
      if (!ada::idna::utf32_to_punycode(label_view, out)) {
6727
0
        out.clear();
6728
0
        return false;
6729
0
      }
6730
48.7k
    }
6731
67.5k
    if (!is_last_label) {
6732
34.0k
      out.push_back('.');
6733
34.0k
    }
6734
67.5k
  }
6735
34.0k
  return true;
6736
67.5k
}
6737
6738
100k
std::string to_ascii(std::string_view ut8_string) {
6739
100k
  std::string out;
6740
100k
  if (!to_ascii(ut8_string, out)) {
6741
39.9k
    return {};
6742
39.9k
  }
6743
60.7k
  return out;
6744
100k
}
6745
}  // namespace ada::idna
6746
/* end file src/to_ascii.cpp */
6747
/* begin file src/to_unicode.cpp */
6748
/* begin file include/ada/idna/to_unicode.h */
6749
#ifndef ADA_IDNA_TO_UNICODE_H
6750
#define ADA_IDNA_TO_UNICODE_H
6751
6752
#include <string>
6753
#include <string_view>
6754
6755
6756
namespace ada::idna {
6757
6758
// UTS #46 ToUnicode. Never fails per the standard: on step failure the original
6759
// label is kept. Inputs longer than max_domain_input_bytes are returned
6760
// unchanged as a safety measure under untrusted input.
6761
std::string to_unicode(std::string_view input);
6762
6763
// Writes into `out`. Returns false only if the input exceeds
6764
// max_domain_input_bytes (out is left empty). Otherwise always returns true
6765
// (ToUnicode does not fail).
6766
[[nodiscard]] bool to_unicode(std::string_view input, std::string& out);
6767
6768
}  // namespace ada::idna
6769
6770
#endif  // ADA_IDNA_TO_UNICODE_H
6771
/* end file include/ada/idna/to_unicode.h */
6772
6773
#include <algorithm>
6774
#include <string>
6775
6776
/* begin file include/idna.h */
6777
#ifndef ADA_IDNA_H
6778
#define ADA_IDNA_H
6779
6780
/* begin file include/ada/idna/identifier.h */
6781
#ifndef ADA_IDNA_IDENTIFIER_H
6782
#define ADA_IDNA_IDENTIFIER_H
6783
6784
#include <string>
6785
#include <string_view>
6786
6787
namespace ada::idna {
6788
6789
// Verify if it is valid name code point given a Unicode code point and a
6790
// boolean first: If first is true return the result of checking if code point
6791
// is contained in the IdentifierStart set of code points. Otherwise return the
6792
// result of checking if code point is contained in the IdentifierPart set of
6793
// code points. Returns false if the input is empty or the code point is not
6794
// valid. There is minimal Unicode error handling: the input should be valid
6795
// UTF-8. https://urlpattern.spec.whatwg.org/#is-a-valid-name-code-point
6796
bool valid_name_code_point(char32_t code_point, bool first);
6797
6798
}  // namespace ada::idna
6799
6800
#endif
6801
/* end file include/ada/idna/identifier.h */
6802
6803
#endif
6804
/* end file include/idna.h */
6805
6806
#ifdef ADA_USE_SIMDUTF
6807
#include "simdutf.h"
6808
#endif
6809
6810
namespace ada::idna {
6811
6812
0
[[nodiscard]] bool to_unicode(std::string_view input, std::string& output) {
6813
0
  output.clear();
6814
0
  if (input.size() > max_domain_input_bytes) {
6815
0
    return false;
6816
0
  }
6817
0
  output.reserve(input.size());
6818
6819
0
  size_t label_start = 0;
6820
0
  std::u32string tmp_buffer;
6821
0
  std::u32string post_map;
6822
0
  while (label_start < input.size()) {
6823
0
    size_t loc_dot = input.find('.', label_start);
6824
0
    bool is_last_label = (loc_dot == std::string_view::npos);
6825
0
    size_t label_size =
6826
0
        is_last_label ? input.size() - label_start : loc_dot - label_start;
6827
0
    auto label_view = std::string_view(input.data() + label_start, label_size);
6828
6829
0
    if (label_view.starts_with("xn--") && ada::idna::is_ascii(label_view)) {
6830
0
      label_view.remove_prefix(4);
6831
0
      tmp_buffer.clear();
6832
0
      if (ada::idna::punycode_to_utf32(label_view, tmp_buffer)) {
6833
        // Per UTS #46, the decoded label must be re-validated. Reject decodings
6834
        // that are pure ASCII (xn-- encoding of an ASCII-only label), or whose
6835
        // mapping/normalization is not stable, or that fail label validity.
6836
0
        bool accept_decoded = true;
6837
0
        if (ada::idna::is_ascii(tmp_buffer)) {
6838
0
          accept_decoded = false;
6839
0
        } else {
6840
0
          post_map.clear();
6841
0
          if (!ada::idna::map(tmp_buffer, post_map) || post_map != tmp_buffer) {
6842
0
            accept_decoded = false;
6843
0
          } else if (!ada::idna::normalize(post_map) ||
6844
0
                     post_map != tmp_buffer || post_map.empty() ||
6845
0
                     !ada::idna::is_label_valid(post_map)) {
6846
0
            accept_decoded = false;
6847
0
          }
6848
0
        }
6849
6850
0
        if (accept_decoded) {
6851
#ifdef ADA_USE_SIMDUTF
6852
          auto utf8_size = simdutf::utf8_length_from_utf32(tmp_buffer.data(),
6853
                                                           tmp_buffer.size());
6854
          size_t old_size = output.size();
6855
          output.resize(old_size + utf8_size);
6856
          size_t written = simdutf::convert_utf32_to_utf8(
6857
              tmp_buffer.data(), tmp_buffer.size(), output.data() + old_size);
6858
          if (written != utf8_size) {
6859
            output.resize(old_size);
6860
            output.append(
6861
                std::string_view(input.data() + label_start, label_size));
6862
          }
6863
#else
6864
0
          auto utf8_size = ada::idna::utf8_length_from_utf32(tmp_buffer.data(),
6865
0
                                                             tmp_buffer.size());
6866
0
          size_t old_size = output.size();
6867
0
          output.resize(old_size + utf8_size);
6868
0
          size_t written = ada::idna::utf32_to_utf8(
6869
0
              tmp_buffer.data(), tmp_buffer.size(), output.data() + old_size);
6870
0
          if (written != utf8_size) {
6871
0
            output.resize(old_size);
6872
0
            output.append(
6873
0
                std::string_view(input.data() + label_start, label_size));
6874
0
          }
6875
0
#endif
6876
0
        } else {
6877
          // ToUnicode never fails. If any step fails, return the original
6878
          // input sequence for the label.
6879
0
          output.append(
6880
0
              std::string_view(input.data() + label_start, label_size));
6881
0
        }
6882
0
      } else {
6883
0
        output.append(std::string_view(input.data() + label_start, label_size));
6884
0
      }
6885
0
    } else {
6886
0
      output.append(label_view);
6887
0
    }
6888
6889
0
    if (!is_last_label) {
6890
0
      output.push_back('.');
6891
0
    }
6892
6893
0
    label_start += label_size + 1;
6894
0
  }
6895
6896
0
  return true;
6897
0
}
6898
6899
0
std::string to_unicode(std::string_view input) {
6900
0
  std::string output;
6901
0
  if (!to_unicode(input, output)) {
6902
    // Over-limit input: return original (ToUnicode never fails in the sense of
6903
    // producing no answer for valid-length inputs).
6904
0
    return std::string(input);
6905
0
  }
6906
0
  return output;
6907
0
}
6908
}  // namespace ada::idna
6909
/* end file src/to_unicode.cpp */
6910
/* begin file src/identifier.cpp */
6911
6912
#include <algorithm>
6913
#include <array>
6914
#include <span>
6915
#include <string>
6916
6917
/* begin file src/id_tables.cpp */
6918
// IDNA  18.0.0
6919
// Identifier range tables are stored in the compressed blob (table_store.hpp).
6920
// Regenerate with: python3 scripts/derived_table.py --write
6921
//   id_continue: 1437 ranges
6922
//   id_start:    789 ranges
6923
6924
// clang-format off
6925
#ifndef ADA_IDNA_IDENTIFIER_TABLES_H
6926
#define ADA_IDNA_IDENTIFIER_TABLES_H
6927
#include <cstdint>
6928
6929
namespace ada::idna {
6930
6931
// id_continue / id_start pointers and counts are provided by table_store.hpp.
6932
6933
}  // namespace ada::idna
6934
#endif  // ADA_IDNA_IDENTIFIER_TABLES_H
6935
/* end file src/id_tables.cpp */
6936
6937
namespace ada::idna {
6938
50.8k
constexpr bool is_ascii_letter(char32_t c) noexcept {
6939
50.8k
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
6940
50.8k
}
6941
6942
8.45k
constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept {
6943
8.45k
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
6944
6.81k
         (c >= '0' && c <= '9');
6945
8.45k
}
6946
6947
60.7k
bool valid_name_code_point(char32_t code_point, bool first) {
6948
  // https://tc39.es/ecma262/#prod-IdentifierStart
6949
6950
  // Fast paths (no table needed)
6951
60.7k
  if (first && (code_point == U'$' || code_point == U'_' ||
6952
50.8k
                is_ascii_letter(code_point))) {
6953
4.57k
    return true;
6954
4.57k
  }
6955
56.1k
  if (!first && (code_point == U'$' || is_ascii_letter_or_digit(code_point))) {
6956
3.00k
    return true;
6957
3.00k
  }
6958
6959
  // Minimal error handling for invalid code point
6960
53.1k
  if (code_point > 0x10FFFF) {
6961
0
    return false;
6962
0
  }
6963
53.1k
  if (code_point >= 0xD800 && code_point <= 0xDFFF) {
6964
0
    return false;
6965
0
  }
6966
6967
53.1k
  if (!ensure_tables() || id_start == nullptr || id_continue == nullptr) {
6968
0
    return false;
6969
0
  }
6970
6971
  // Slow path: binary search through the appropriate Unicode range table.
6972
  // Each entry is a [low, high] inclusive range.
6973
53.1k
  const std::span<const uint32_t[2]> ranges =
6974
53.1k
      first ? std::span<const uint32_t[2]>{ada::idna::id_start,
6975
47.3k
                                           ada::idna::id_start_count}
6976
53.1k
            : std::span<const uint32_t[2]>{ada::idna::id_continue,
6977
5.76k
                                           ada::idna::id_continue_count};
6978
6979
53.1k
  const auto iter = std::ranges::lower_bound(
6980
53.1k
      ranges, code_point, {},
6981
535k
      [](const auto& range) { return range[1]; });  // project to range-high
6982
6983
53.1k
  return iter != ranges.end() && code_point >= (*iter)[0];
6984
53.1k
}
6985
}  // namespace ada::idna
6986
/* end file src/identifier.cpp */
6987
/* end file src/idna.cpp */
6988
/* end file src/ada_idna.cpp */
6989
ADA_POP_DISABLE_WARNINGS
6990
6991
#include <algorithm>
6992
#include <array>
6993
#include <cstdint>
6994
#include <cstring>
6995
#include <iterator>
6996
#include <optional>
6997
#include <string>
6998
#include <string_view>
6999
#include <utility>
7000
#if ADA_SSSE3
7001
#include <tmmintrin.h>
7002
#elif ADA_NEON
7003
#include <arm_neon.h>
7004
#elif ADA_SSE2
7005
#include <emmintrin.h>
7006
#elif ADA_LSX
7007
#include <lsxintrin.h>
7008
#elif ADA_RVV
7009
#include <riscv_vector.h>
7010
#endif
7011
7012
#include <ranges>
7013
7014
namespace ada::unicode {
7015
7016
8.14M
constexpr bool is_tabs_or_newline(char c) noexcept {
7017
8.14M
  return c == '\r' || c == '\n' || c == '\t';
7018
8.14M
}
7019
7020
285k
constexpr uint64_t broadcast(uint8_t v) noexcept {
7021
285k
  return 0x101010101010101ull * v;
7022
285k
}
7023
7024
95.1k
constexpr bool to_lower_ascii(char* input, size_t length) noexcept {
7025
95.1k
  uint64_t broadcast_80 = broadcast(0x80);
7026
95.1k
  uint64_t broadcast_Ap = broadcast(128 - 'A');
7027
95.1k
  uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1);
7028
95.1k
  uint64_t non_ascii = 0;
7029
95.1k
  size_t i = 0;
7030
7031
124k
  for (; i + 7 < length; i += 8) {
7032
29.0k
    uint64_t word{};
7033
29.0k
    memcpy(&word, input + i, sizeof(word));
7034
29.0k
    non_ascii |= (word & broadcast_80);
7035
29.0k
    word ^=
7036
29.0k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
7037
29.0k
    memcpy(input + i, &word, sizeof(word));
7038
29.0k
  }
7039
95.1k
  if (i < length) {
7040
90.0k
    uint64_t word{};
7041
90.0k
    memcpy(&word, input + i, length - i);
7042
90.0k
    non_ascii |= (word & broadcast_80);
7043
90.0k
    word ^=
7044
90.0k
        (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2;
7045
90.0k
    memcpy(input + i, &word, length - i);
7046
90.0k
  }
7047
95.1k
  return non_ascii == 0;
7048
95.1k
}
7049
#if ADA_SSSE3
7050
ada_really_inline bool has_tabs_or_newline(
7051
    std::string_view user_input) noexcept {
7052
  // first check for short strings in which case we do it naively.
7053
  if (user_input.size() < 16) {  // slow path
7054
    return std::ranges::any_of(user_input, is_tabs_or_newline);
7055
  }
7056
  // fast path for long strings (expected to be common)
7057
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
7058
  size_t i = 0;
7059
  // Lookup table where positions 9, 10, 13 contain their own values
7060
  // Everything else is set to 1 so it won't match
7061
  const __m128i rnt =
7062
      _mm_setr_epi8(1, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 13, 0, 0);
7063
  __m128i running = _mm_setzero_si128();
7064
  for (; i + 15 < user_input.size(); i += 16) {
7065
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
7066
    // Shuffle the lookup table using input bytes as indices
7067
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
7068
    // Compare: if shuffled value matches input, we found \t, \n, or \r
7069
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
7070
    running = _mm_or_si128(running, matches);
7071
  }
7072
  if (i < user_input.size()) {
7073
    __m128i word = _mm_loadu_si128(
7074
        (const __m128i*)(user_input.data() + user_input.length() - 16));
7075
    __m128i shuffled = _mm_shuffle_epi8(rnt, word);
7076
    __m128i matches = _mm_cmpeq_epi8(shuffled, word);
7077
    running = _mm_or_si128(running, matches);
7078
  }
7079
  return _mm_movemask_epi8(running) != 0;
7080
}
7081
#elif ADA_NEON
7082
ada_really_inline bool has_tabs_or_newline(
7083
    std::string_view user_input) noexcept {
7084
  // first check for short strings in which case we do it naively.
7085
  if (user_input.size() < 16) {  // slow path
7086
    return std::ranges::any_of(user_input, is_tabs_or_newline);
7087
  }
7088
  // fast path for long strings (expected to be common)
7089
  size_t i = 0;
7090
  /**
7091
   * The fastest way to check for `\t` (==9), '\n'(== 10) and `\r` (==13) relies
7092
   * on table lookup instruction. We notice that these are all unique numbers
7093
   * between 0..15. Let's prepare a special register, where we put '\t' in the
7094
   * 9th position, '\n' - 10th and '\r' - 13th. Then we shuffle this register by
7095
   * input register. If the input had `\t` in position X then this shuffled
7096
   * register will also have '\t' in that position. Comparing input with this
7097
   * shuffled register will mark us all interesting characters in the input.
7098
   *
7099
   * credit for algorithmic idea: @aqrit, credit for description:
7100
   * @DenisYaroshevskiy
7101
   */
7102
  static uint8_t rnt_array[16] = {1, 0, 0,  0, 0, 0,  0, 0,
7103
                                  0, 9, 10, 0, 0, 13, 0, 0};
7104
  const uint8x16_t rnt = vld1q_u8(rnt_array);
7105
  // m['0xd', '0xa', '0x9']
7106
  uint8x16_t running{0};
7107
  for (; i + 15 < user_input.size(); i += 16) {
7108
    uint8x16_t word = vld1q_u8((const uint8_t*)user_input.data() + i);
7109
7110
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
7111
  }
7112
  if (i < user_input.size()) {
7113
    uint8x16_t word =
7114
        vld1q_u8((const uint8_t*)user_input.data() + user_input.length() - 16);
7115
    running = vorrq_u8(running, vceqq_u8(vqtbl1q_u8(rnt, word), word));
7116
  }
7117
  // `running` accumulates comparison results, so every lane is 0x00 or 0xFF:
7118
  // narrowing to four bits per lane and testing against zero is cheaper than a
7119
  // horizontal maximum. The double compare is faster (no GPR transfer) but
7120
  // incorrect if flush-to-zero is enabled; ADA_NEON_SAFE_ZERO_CHECK uses an
7121
  // integer compare instead.
7122
  uint8x8_t narrowed = vshrn_n_u16(vreinterpretq_u16_u8(running), 4);
7123
#if ADA_NEON_SAFE_ZERO_CHECK
7124
  return vget_lane_u64(vreinterpret_u64_u8(narrowed), 0) != 0;
7125
#else
7126
  return vdupd_lane_f64(vreinterpret_f64_u8(narrowed), 0) != 0.0;
7127
#endif
7128
}
7129
#elif ADA_SSE2
7130
ada_really_inline bool has_tabs_or_newline(
7131
1.12M
    std::string_view user_input) noexcept {
7132
  // first check for short strings in which case we do it naively.
7133
1.12M
  if (user_input.size() < 16) {  // slow path
7134
861k
    return std::ranges::any_of(user_input, is_tabs_or_newline);
7135
861k
  }
7136
  // fast path for long strings (expected to be common)
7137
267k
  size_t i = 0;
7138
267k
  const __m128i mask1 = _mm_set1_epi8('\r');
7139
267k
  const __m128i mask2 = _mm_set1_epi8('\n');
7140
267k
  const __m128i mask3 = _mm_set1_epi8('\t');
7141
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
7142
267k
  __m128i running{0};
7143
615k
  for (; i + 15 < user_input.size(); i += 16) {
7144
348k
    __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i));
7145
348k
    running = _mm_or_si128(
7146
348k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
7147
348k
                                           _mm_cmpeq_epi8(word, mask2))),
7148
348k
        _mm_cmpeq_epi8(word, mask3));
7149
348k
  }
7150
267k
  if (i < user_input.size()) {
7151
235k
    __m128i word = _mm_loadu_si128(
7152
235k
        (const __m128i*)(user_input.data() + user_input.length() - 16));
7153
235k
    running = _mm_or_si128(
7154
235k
        _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1),
7155
235k
                                           _mm_cmpeq_epi8(word, mask2))),
7156
235k
        _mm_cmpeq_epi8(word, mask3));
7157
235k
  }
7158
267k
  return _mm_movemask_epi8(running) != 0;
7159
1.12M
}
7160
#elif ADA_LSX
7161
ada_really_inline bool has_tabs_or_newline(
7162
    std::string_view user_input) noexcept {
7163
  // first check for short strings in which case we do it naively.
7164
  if (user_input.size() < 16) {  // slow path
7165
    return std::ranges::any_of(user_input, is_tabs_or_newline);
7166
  }
7167
  // fast path for long strings (expected to be common)
7168
  size_t i = 0;
7169
  const __m128i mask1 = __lsx_vrepli_b('\r');
7170
  const __m128i mask2 = __lsx_vrepli_b('\n');
7171
  const __m128i mask3 = __lsx_vrepli_b('\t');
7172
  // If we supported SSSE3, we could use the algorithm that we use for NEON.
7173
  __m128i running{0};
7174
  for (; i + 15 < user_input.size(); i += 16) {
7175
    __m128i word = __lsx_vld((const __m128i*)(user_input.data() + i), 0);
7176
    running = __lsx_vor_v(
7177
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
7178
                                         __lsx_vseq_b(word, mask2))),
7179
        __lsx_vseq_b(word, mask3));
7180
  }
7181
  if (i < user_input.size()) {
7182
    __m128i word = __lsx_vld(
7183
        (const __m128i*)(user_input.data() + user_input.length() - 16), 0);
7184
    running = __lsx_vor_v(
7185
        __lsx_vor_v(running, __lsx_vor_v(__lsx_vseq_b(word, mask1),
7186
                                         __lsx_vseq_b(word, mask2))),
7187
        __lsx_vseq_b(word, mask3));
7188
  }
7189
  if (__lsx_bz_v(running)) return false;
7190
  return true;
7191
}
7192
#elif ADA_RVV
7193
ada_really_inline bool has_tabs_or_newline(
7194
    std::string_view user_input) noexcept {
7195
  uint8_t* src = (uint8_t*)user_input.data();
7196
  for (size_t vl, n = user_input.size(); n > 0; n -= vl, src += vl) {
7197
    vl = __riscv_vsetvl_e8m1(n);
7198
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
7199
    vbool8_t m1 = __riscv_vmseq(v, '\r', vl);
7200
    vbool8_t m2 = __riscv_vmseq(v, '\n', vl);
7201
    vbool8_t m3 = __riscv_vmseq(v, '\t', vl);
7202
    vbool8_t m = __riscv_vmor(__riscv_vmor(m1, m2, vl), m3, vl);
7203
    long idx = __riscv_vfirst(m, vl);
7204
    if (idx >= 0) return true;
7205
  }
7206
  return false;
7207
}
7208
#else
7209
ada_really_inline bool has_tabs_or_newline(
7210
    std::string_view user_input) noexcept {
7211
  auto has_zero_byte = [](uint64_t v) {
7212
    return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080);
7213
  };
7214
  size_t i = 0;
7215
  uint64_t mask1 = broadcast('\r');
7216
  uint64_t mask2 = broadcast('\n');
7217
  uint64_t mask3 = broadcast('\t');
7218
  uint64_t running{0};
7219
  for (; i + 7 < user_input.size(); i += 8) {
7220
    uint64_t word{};
7221
    memcpy(&word, user_input.data() + i, sizeof(word));
7222
    uint64_t xor1 = word ^ mask1;
7223
    uint64_t xor2 = word ^ mask2;
7224
    uint64_t xor3 = word ^ mask3;
7225
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
7226
  }
7227
  if (i < user_input.size()) {
7228
    uint64_t word{};
7229
    memcpy(&word, user_input.data() + i, user_input.size() - i);
7230
    uint64_t xor1 = word ^ mask1;
7231
    uint64_t xor2 = word ^ mask2;
7232
    uint64_t xor3 = word ^ mask3;
7233
    running |= has_zero_byte(xor1) | has_zero_byte(xor2) | has_zero_byte(xor3);
7234
  }
7235
  return running;
7236
}
7237
#endif
7238
7239
// A forbidden host code point is U+0000 NULL, U+0009 TAB, U+000A LF, U+000D CR,
7240
// U+0020 SPACE, U+0023 (#), U+002F (/), U+003A (:), U+003C (<), U+003E (>),
7241
// U+003F (?), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), or
7242
// U+007C (|).
7243
constexpr static std::array<uint8_t, 256> is_forbidden_host_code_point_table =
7244
    []() consteval {
7245
      std::array<uint8_t, 256> result{};
7246
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
7247
                        '>', '?', '@', '[', '\\', ']', '^', '|'}) {
7248
        result[c] = true;
7249
      }
7250
      return result;
7251
    }();
7252
7253
ada_really_inline constexpr bool is_forbidden_host_code_point(
7254
946
    const char c) noexcept {
7255
946
  return is_forbidden_host_code_point_table[uint8_t(c)];
7256
946
}
7257
7258
constexpr static std::array<uint8_t, 256> is_forbidden_domain_code_point_table =
7259
    []() consteval {
7260
      std::array<uint8_t, 256> result{};
7261
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
7262
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
7263
        result[c] = true;
7264
      }
7265
      for (uint8_t c = 0; c <= 32; c++) {
7266
        result[c] = true;
7267
      }
7268
      for (size_t c = 127; c < 256; c++) {
7269
        result[c] = true;
7270
      }
7271
      return result;
7272
    }();
7273
7274
static_assert(sizeof(is_forbidden_domain_code_point_table) == 256);
7275
7276
ada_really_inline constexpr bool is_forbidden_domain_code_point(
7277
438k
    const char c) noexcept {
7278
438k
  return is_forbidden_domain_code_point_table[uint8_t(c)];
7279
438k
}
7280
7281
ada_really_inline constexpr bool contains_forbidden_domain_code_point(
7282
60.6k
    const char* input, size_t length) noexcept {
7283
60.6k
  size_t i = 0;
7284
60.6k
  uint8_t accumulator{};
7285
222k
  for (; i + 4 <= length; i += 4) {
7286
161k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
7287
161k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])];
7288
161k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])];
7289
161k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])];
7290
161k
  }
7291
152k
  for (; i < length; i++) {
7292
91.5k
    accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])];
7293
91.5k
  }
7294
60.6k
  return accumulator;
7295
60.6k
}
7296
7297
constexpr static std::array<uint8_t, 256>
7298
    is_forbidden_domain_code_point_table_or_upper = []() consteval {
7299
      std::array<uint8_t, 256> result{};
7300
      for (uint8_t c : {'\0', '\x09', '\x0a', '\x0d', ' ', '#', '/', ':', '<',
7301
                        '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
7302
        result[c] = 1;
7303
      }
7304
      for (uint8_t c = 'A'; c <= 'Z'; c++) {
7305
        result[c] = 2;
7306
      }
7307
      for (uint8_t c = 0; c <= 32; c++) {
7308
        result[c] = 1;
7309
      }
7310
      for (size_t c = 127; c < 256; c++) {
7311
        result[c] = 1;
7312
      }
7313
      return result;
7314
    }();
7315
7316
ada_really_inline constexpr uint8_t
7317
contains_forbidden_domain_code_point_or_upper(const char* input,
7318
333k
                                              size_t length) noexcept {
7319
333k
  size_t i = 0;
7320
333k
  uint8_t accumulator{};
7321
920k
  for (; i + 4 <= length; i += 4) {
7322
587k
    accumulator |=
7323
587k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
7324
587k
    accumulator |=
7325
587k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])];
7326
587k
    accumulator |=
7327
587k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])];
7328
587k
    accumulator |=
7329
587k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])];
7330
587k
  }
7331
812k
  for (; i < length; i++) {
7332
479k
    accumulator |=
7333
479k
        is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])];
7334
479k
  }
7335
333k
  return accumulator;
7336
333k
}
7337
7338
// std::isalnum(c) || c == '+' || c == '-' || c == '.') is true for
7339
constexpr static std::array<bool, 256> is_alnum_plus_table = []() consteval {
7340
  std::array<bool, 256> result{};
7341
  for (size_t c = 0; c < 256; c++) {
7342
    result[c] = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
7343
                (c >= 'A' && c <= 'Z') || c == '+' || c == '-' || c == '.';
7344
  }
7345
  return result;
7346
}();
7347
7348
3.73M
ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept {
7349
3.73M
  return is_alnum_plus_table[uint8_t(c)];
7350
  // A table is almost surely much faster than the
7351
  // following under most compilers: return
7352
  // return (std::isalnum(c) || c == '+' || c == '-' || c == '.');
7353
3.73M
}
7354
7355
881k
ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept {
7356
881k
  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') ||
7357
339k
         (c >= 'a' && c <= 'f');
7358
881k
}
7359
7360
592k
ada_really_inline constexpr bool is_ascii_digit(const char c) noexcept {
7361
  // An ASCII digit is a code point in the range U+0030 (0) to U+0039 (9),
7362
  // inclusive.
7363
592k
  return (c >= '0' && c <= '9');
7364
592k
}
7365
7366
24.4k
ada_really_inline constexpr bool is_ascii(const char32_t c) noexcept {
7367
  // If code point is between U+0000 and U+007F inclusive, then return true.
7368
24.4k
  return c <= 0x7F;
7369
24.4k
}
7370
7371
1.61M
ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept {
7372
1.61M
  return (unsigned char)c <= ' ';
7373
1.61M
}
7374
7375
ada_really_inline constexpr bool is_ascii_tab_or_newline(
7376
375k
    const char c) noexcept {
7377
375k
  return c == '\t' || c == '\n' || c == '\r';
7378
375k
}
7379
7380
constexpr std::string_view table_is_double_dot_path_segment[] = {
7381
    "..", "%2e.", ".%2e", "%2e%2e"};
7382
7383
ada_really_inline constexpr bool is_double_dot_path_segment(
7384
379k
    std::string_view input) noexcept {
7385
  // This will catch most cases:
7386
  // The length must be 2,4 or 6.
7387
  // We divide by two and require
7388
  // that the result be between 1 and 3 inclusively.
7389
379k
  uint64_t half_length = uint64_t(input.size()) / 2;
7390
379k
  if (half_length - 1 > 2) {
7391
263k
    return false;
7392
263k
  }
7393
  // We have a string of length 2, 4 or 6.
7394
  // We now check the first character:
7395
115k
  if ((input[0] != '.') && (input[0] != '%')) {
7396
83.1k
    return false;
7397
83.1k
  }
7398
  // We are unlikely the get beyond this point.
7399
32.5k
  int hash_value = (input.size() + (unsigned)(input[0])) & 3;
7400
32.5k
  const std::string_view target = table_is_double_dot_path_segment[hash_value];
7401
32.5k
  if (target.size() != input.size()) {
7402
17.0k
    return false;
7403
17.0k
  }
7404
  // We almost never get here.
7405
  // Optimizing the rest is relatively unimportant.
7406
15.4k
  auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) {
7407
15.4k
    uint16_t A, B;
7408
15.4k
    memcpy(&A, a.data(), sizeof(A));
7409
15.4k
    memcpy(&B, b.data(), sizeof(B));
7410
15.4k
    return A == B;
7411
15.4k
  };
7412
15.4k
  if (!prefix_equal_unsafe(input, target)) {
7413
7.55k
    return false;
7414
7.55k
  }
7415
9.64k
  for (size_t i = 2; i < input.size(); i++) {
7416
3.90k
    char c = input[i];
7417
3.90k
    if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) {
7418
2.20k
      return false;
7419
2.20k
    }
7420
3.90k
  }
7421
5.74k
  return true;
7422
  // The above code might be a bit better than the code below. Compilers
7423
  // are not stupid and may use the fact that these strings have length 2,4 and
7424
  // 6 and other tricks.
7425
  // return input == ".." ||
7426
  //  input == ".%2e" || input == ".%2E" ||
7427
  //  input == "%2e." || input == "%2E." ||
7428
  //  input == "%2e%2e" || input == "%2E%2E" || input == "%2E%2e" || input ==
7429
  //  "%2e%2E";
7430
7.94k
}
7431
7432
ada_really_inline constexpr bool is_single_dot_path_segment(
7433
746k
    std::string_view input) noexcept {
7434
746k
  return input == "." || input == "%2e" || input == "%2E";
7435
746k
}
7436
7437
71.1k
ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept {
7438
71.1k
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
7439
71.1k
}
7440
7441
constexpr static char hex_to_binary_table[] = {
7442
    0,  1,  2,  3,  4, 5, 6, 7, 8, 9, 0, 0,  0,  0,  0,  0,  0, 10, 11,
7443
    12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0,  0,
7444
    0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
7445
854k
unsigned constexpr convert_hex_to_binary(const char c) noexcept {
7446
854k
  return hex_to_binary_table[c - '0'];
7447
854k
}
7448
7449
170k
std::string percent_decode(const std::string_view input, size_t first_percent) {
7450
  // next line is for safety only, we expect users to avoid calling
7451
  // percent_decode when first_percent is outside the range.
7452
170k
  if (first_percent == std::string_view::npos) {
7453
0
    return std::string(input);
7454
0
  }
7455
7456
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7457
170k
  const char* const src = input.data();
7458
170k
  const char* const end = src + input.size();
7459
7460
  // Decoding never grows the string, so a single pre-sized buffer written via
7461
  // bulk memcpy of the plain runs (then shrunk to the final length) avoids the
7462
  // byte-at-a-time appends of the naive version.
7463
170k
  std::string out(input.size(), '\0');
7464
170k
  char* d = out.data();
7465
170k
  char* const d0 = d;
7466
7467
170k
  std::memcpy(d, src, first_percent);
7468
170k
  d += first_percent;
7469
7470
170k
  const char* p = src + first_percent;
7471
493k
  while (p < end) {
7472
323k
    if (*p == '%') {
7473
      // Decode runs of valid %XX tightly (common for nested/encoded URLs).
7474
624k
      while (p + 2 < end && *p == '%') {
7475
446k
        if (!is_ascii_hex_digit(p[1]) || !is_ascii_hex_digit(p[2])) {
7476
19.0k
          break;
7477
19.0k
        }
7478
427k
        *d++ = static_cast<char>(convert_hex_to_binary(p[1]) * 16 +
7479
427k
                                 convert_hex_to_binary(p[2]));
7480
427k
        p += 3;
7481
427k
      }
7482
197k
      if (p < end && *p == '%') {
7483
        // Not a valid escape (too few chars left or bad hex): copy '%'
7484
        // literally and keep scanning after it.
7485
28.0k
        *d++ = *p++;
7486
28.0k
      }
7487
197k
    } else {
7488
126k
      const char* q = static_cast<const char*>(
7489
126k
          std::memchr(p, '%', static_cast<size_t>(end - p)));
7490
126k
      const char* run_end = q ? q : end;
7491
126k
      const size_t n = static_cast<size_t>(run_end - p);
7492
126k
      std::memcpy(d, p, n);
7493
126k
      d += n;
7494
126k
      p = run_end;
7495
126k
    }
7496
323k
  }
7497
7498
170k
  out.resize(static_cast<size_t>(d - d0));
7499
170k
  return out;
7500
170k
}
7501
7502
// 0..15 for hex digits, 0xFF otherwise - validate and decode with two loads.
7503
constexpr static std::array<uint8_t, 256> unhex_table = []() consteval {
7504
  std::array<uint8_t, 256> t{};
7505
  for (size_t i = 0; i < 256; ++i) {
7506
    t[i] = 0xFF;
7507
  }
7508
  for (uint8_t i = 0; i < 10; ++i) {
7509
    t[static_cast<size_t>('0') + i] = i;
7510
  }
7511
  for (uint8_t i = 0; i < 6; ++i) {
7512
    t[static_cast<size_t>('A') + i] = static_cast<uint8_t>(10 + i);
7513
    t[static_cast<size_t>('a') + i] = static_cast<uint8_t>(10 + i);
7514
  }
7515
  return t;
7516
}();
7517
7518
0
std::string form_urlencoded_decode(const std::string_view input) {
7519
0
  const size_t len = input.size();
7520
0
  if (len == 0) [[unlikely]] {
7521
0
    return {};
7522
0
  }
7523
7524
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7525
0
  const char* const src = input.data();
7526
0
  const char* const end = src + len;
7527
0
  const char* p = src;
7528
7529
  // Advance over the untransformed prefix.
7530
0
  while (p < end && *p != '+' && *p != '%') {
7531
0
    ++p;
7532
0
  }
7533
0
  if (p == end) {
7534
0
    return std::string(input);
7535
0
  }
7536
7537
  // Output is always at most as long as the input: write into a single
7538
  // pre-sized buffer, then shrink to the final length.
7539
0
  std::string out(len, '\0');
7540
0
  char* d = out.data();
7541
0
  char* const d0 = d;
7542
7543
0
  const size_t prefix = static_cast<size_t>(p - src);
7544
0
  std::memcpy(d, src, prefix);
7545
0
  d += prefix;
7546
7547
0
  while (p < end) {
7548
0
    const char c = *p;
7549
0
    if (c == '+') {
7550
0
      *d++ = ' ';
7551
0
      ++p;
7552
0
    } else if (c == '%') {
7553
      // Decode runs of valid %XX tightly (common for nested URL query values).
7554
0
      while (p + 2 < end && *p == '%') {
7555
0
        const uint8_t hi = unhex_table[static_cast<uint8_t>(p[1])];
7556
0
        const uint8_t lo = unhex_table[static_cast<uint8_t>(p[2])];
7557
0
        if ((hi | lo) >= 16) {
7558
0
          break;
7559
0
        }
7560
0
        *d++ = static_cast<char>((hi << 4) | lo);
7561
0
        p += 3;
7562
0
      }
7563
0
      if (p < end && *p == '%') {
7564
        // Invalid escape: copy '%' literally and continue.
7565
0
        *d++ = *p++;
7566
0
      }
7567
0
    } else {
7568
      // Copy a plain run until the next '+' or '%'.
7569
0
      const char* start = p;
7570
0
      ++p;
7571
0
      while (p < end && *p != '+' && *p != '%') {
7572
0
        ++p;
7573
0
      }
7574
0
      const size_t n = static_cast<size_t>(p - start);
7575
0
      std::memcpy(d, start, n);
7576
0
      d += n;
7577
0
    }
7578
0
  }
7579
7580
0
  out.resize(static_cast<size_t>(d - d0));
7581
0
  return out;
7582
0
}
7583
7584
void percent_encode_suffix(const char* p, const char* end,
7585
                           const uint8_t character_set[], std::string& out);
7586
7587
std::string percent_encode(const std::string_view input,
7588
63.2k
                           const uint8_t character_set[]) {
7589
63.2k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7590
54.3k
    return character_sets::bit_at(character_set, c);
7591
54.3k
  });
7592
  // Optimization: Don't iterate if percent encode is not required
7593
63.2k
  if (pointer == input.end()) {
7594
46.5k
    return std::string(input);
7595
46.5k
  }
7596
7597
16.7k
  std::string result;
7598
16.7k
  result.reserve(input.length());  // in the worst case, percent encoding might
7599
                                   // produce 3 characters.
7600
16.7k
  result.append(input.substr(0, std::distance(input.begin(), pointer)));
7601
16.7k
  if (static_cast<size_t>(input.end() - pointer) >= 48) {
7602
0
    percent_encode_suffix(&*pointer, input.data() + input.size(), character_set,
7603
0
                          result);
7604
16.7k
  } else {
7605
97.6k
    for (; pointer != input.end(); pointer++) {
7606
80.9k
      if (character_sets::bit_at(character_set, *pointer)) {
7607
69.4k
        result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
7608
69.4k
      } else {
7609
11.4k
        result += *pointer;
7610
11.4k
      }
7611
80.9k
    }
7612
16.7k
  }
7613
16.7k
  return result;
7614
63.2k
}
7615
7616
template <bool append>
7617
bool percent_encode(const std::string_view input, const uint8_t character_set[],
7618
271k
                    std::string& out) {
7619
271k
  ada_log("percent_encode ", input, " to output string while ",
7620
271k
          append ? "appending" : "overwriting");
7621
743k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7622
743k
    return character_sets::bit_at(character_set, c);
7623
743k
  });
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
7621
132k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7622
132k
    return character_sets::bit_at(character_set, c);
7623
132k
  });
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
7621
610k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7622
610k
    return character_sets::bit_at(character_set, c);
7623
610k
  });
7624
271k
  ada_log("percent_encode done checking, moved to ",
7625
271k
          std::distance(input.begin(), pointer));
7626
7627
  // Optimization: Don't iterate if percent encode is not required
7628
271k
  if (pointer == input.end()) {
7629
186k
    ada_log("percent_encode encoding not needed.");
7630
186k
    return false;
7631
186k
  }
7632
85.0k
  if constexpr (!append) {
7633
66.0k
    out.clear();
7634
66.0k
  }
7635
85.0k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
7636
85.0k
          " bytes");
7637
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7638
85.0k
  out.append(input.data(), std::distance(input.begin(), pointer));
7639
85.0k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
7640
85.0k
          " bytes");
7641
764k
  for (; pointer != input.end(); pointer++) {
7642
679k
    if (character_sets::bit_at(character_set, *pointer)) {
7643
477k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
7644
477k
    } else {
7645
202k
      out += *pointer;
7646
202k
    }
7647
679k
  }
7648
85.0k
  return true;
7649
271k
}
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
7618
36.0k
                    std::string& out) {
7619
36.0k
  ada_log("percent_encode ", input, " to output string while ",
7620
36.0k
          append ? "appending" : "overwriting");
7621
36.0k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7622
36.0k
    return character_sets::bit_at(character_set, c);
7623
36.0k
  });
7624
36.0k
  ada_log("percent_encode done checking, moved to ",
7625
36.0k
          std::distance(input.begin(), pointer));
7626
7627
  // Optimization: Don't iterate if percent encode is not required
7628
36.0k
  if (pointer == input.end()) {
7629
17.1k
    ada_log("percent_encode encoding not needed.");
7630
17.1k
    return false;
7631
17.1k
  }
7632
  if constexpr (!append) {
7633
    out.clear();
7634
  }
7635
18.9k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
7636
18.9k
          " bytes");
7637
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7638
18.9k
  out.append(input.data(), std::distance(input.begin(), pointer));
7639
18.9k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
7640
18.9k
          " bytes");
7641
243k
  for (; pointer != input.end(); pointer++) {
7642
224k
    if (character_sets::bit_at(character_set, *pointer)) {
7643
164k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
7644
164k
    } else {
7645
59.5k
      out += *pointer;
7646
59.5k
    }
7647
224k
  }
7648
18.9k
  return true;
7649
36.0k
}
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
7618
235k
                    std::string& out) {
7619
235k
  ada_log("percent_encode ", input, " to output string while ",
7620
235k
          append ? "appending" : "overwriting");
7621
235k
  auto pointer = std::ranges::find_if(input, [character_set](const char c) {
7622
235k
    return character_sets::bit_at(character_set, c);
7623
235k
  });
7624
235k
  ada_log("percent_encode done checking, moved to ",
7625
235k
          std::distance(input.begin(), pointer));
7626
7627
  // Optimization: Don't iterate if percent encode is not required
7628
235k
  if (pointer == input.end()) {
7629
169k
    ada_log("percent_encode encoding not needed.");
7630
169k
    return false;
7631
169k
  }
7632
66.0k
  if constexpr (!append) {
7633
66.0k
    out.clear();
7634
66.0k
  }
7635
66.0k
  ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
7636
66.0k
          " bytes");
7637
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7638
66.0k
  out.append(input.data(), std::distance(input.begin(), pointer));
7639
66.0k
  ada_log("percent_encode processing ", std::distance(pointer, input.end()),
7640
66.0k
          " bytes");
7641
521k
  for (; pointer != input.end(); pointer++) {
7642
455k
    if (character_sets::bit_at(character_set, *pointer)) {
7643
312k
      out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
7644
312k
    } else {
7645
142k
      out += *pointer;
7646
142k
    }
7647
455k
  }
7648
66.0k
  return true;
7649
235k
}
7650
7651
template bool percent_encode<true>(std::string_view input,
7652
                                   const uint8_t character_set[],
7653
                                   std::string& out);
7654
template bool percent_encode<false>(std::string_view input,
7655
                                    const uint8_t character_set[],
7656
                                    std::string& out);
7657
7658
bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
7659
100k
              size_t first_percent) {
7660
100k
  std::string percent_decoded_buffer;
7661
100k
  std::string_view input = plain;
7662
100k
  if (first_percent != std::string_view::npos) {
7663
79.9k
    percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
7664
79.9k
    input = percent_decoded_buffer;
7665
79.9k
  }
7666
  // input is a non-empty UTF-8 string, must be percent decoded
7667
100k
  std::string idna_ascii = ada::idna::to_ascii(input);
7668
100k
  if (idna_ascii.empty() || contains_forbidden_domain_code_point(
7669
65.5k
                                idna_ascii.data(), idna_ascii.size())) {
7670
65.5k
    return false;
7671
65.5k
  }
7672
35.1k
  out = std::move(idna_ascii);
7673
35.1k
  return true;
7674
100k
}
7675
7676
std::string percent_encode(const std::string_view input,
7677
1.60k
                           const uint8_t character_set[], size_t index) {
7678
1.60k
  std::string out;
7679
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
7680
1.60k
  out.append(input.data(), index);
7681
1.60k
  auto pointer = input.begin() + index;
7682
1.60k
  if (static_cast<size_t>(input.end() - pointer) >= 48) {
7683
0
    percent_encode_suffix(&*pointer, input.data() + input.size(), character_set,
7684
0
                          out);
7685
1.60k
  } else {
7686
7.88k
    for (; pointer != input.end(); pointer++) {
7687
6.27k
      if (character_sets::bit_at(character_set, *pointer)) {
7688
5.45k
        out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
7689
5.45k
      } else {
7690
815
        out += *pointer;
7691
815
      }
7692
6.27k
    }
7693
1.60k
  }
7694
1.60k
  return out;
7695
1.60k
}
7696
7697
}  // namespace ada::unicode
7698
/* end file src/unicode.cpp */
7699
#if !defined(ADA_PERCENT_ENCODE_SIMD_SEPARATE_TU)
7700
/* begin file src/unicode_percent_encode.cpp */
7701
#include <cstdint>
7702
7703
7704
7705
#include <cstring>
7706
#include <string>
7707
#if ADA_SSSE3
7708
#include <tmmintrin.h>
7709
#define ADA_UNICODE_SSSE3 1
7710
#elif ADA_NEON
7711
#include <arm_neon.h>
7712
#elif ADA_RVV
7713
#include <riscv_vector.h>
7714
#endif
7715
7716
// gcc/clang honor target("ssse3") on an SSE2 translation unit. clang-cl and
7717
// MSVC do not: they still compile the function as SSE2, then reject
7718
// always_inline _mm_shuffle_epi8. Same approach as parser.cpp.
7719
#if !ADA_UNICODE_SSSE3 && (defined(__x86_64__) || defined(__amd64__)) && \
7720
    defined(__GNUC__) && !defined(_MSC_VER)
7721
#include <tmmintrin.h>
7722
#define ADA_UNICODE_SSSE3 1
7723
#define ADA_UNICODE_NEED_SSSE3_TARGET 1
7724
#endif
7725
#ifndef ADA_UNICODE_SSSE3
7726
#define ADA_UNICODE_SSSE3 0
7727
#endif
7728
#ifdef ADA_UNICODE_NEED_SSSE3_TARGET
7729
// noinline: these functions must not be inlined into a caller that also
7730
// contains the CPU check. A target("ssse3") function can use SSSE3 in its
7731
// prologue, before any check inside it would run.
7732
#define ADA_UNICODE_SIMD __attribute__((target("ssse3"), noinline))
7733
#else
7734
#define ADA_UNICODE_SIMD ada_really_inline
7735
#endif
7736
7737
#ifdef ADA_REGULAR_VISUAL_STUDIO
7738
#include <intrin.h>
7739
#endif
7740
7741
namespace ada::unicode {
7742
namespace {
7743
7744
#if ADA_UNICODE_SSSE3 || ADA_NEON
7745
0
ada_really_inline int trailing_zeroes32(uint32_t input_num) noexcept {
7746
#ifdef ADA_REGULAR_VISUAL_STUDIO
7747
  unsigned long ret;
7748
  _BitScanForward(&ret, input_num);
7749
  return static_cast<int>(ret);
7750
#else
7751
0
  return __builtin_ctz(input_num);
7752
0
#endif
7753
0
}
7754
7755
// Append one window whose set bits mark bytes that need encoding.
7756
ada_really_inline void encode_mask_window(const char* p, uint32_t mask,
7757
0
                                          size_t width, std::string& out) {
7758
0
  uint64_t bits = mask;
7759
0
  size_t off = 0;
7760
0
  while (bits != 0) {
7761
0
    const int zero_run = trailing_zeroes32(static_cast<uint32_t>(bits));
7762
0
    if (zero_run != 0) {
7763
0
      out.append(p + off, static_cast<size_t>(zero_run));
7764
0
    }
7765
0
    off += static_cast<size_t>(zero_run);
7766
0
    out.append(character_sets::hex + uint8_t(p[off]) * 4, 3);
7767
0
    ++off;
7768
0
    bits >>= static_cast<unsigned>(zero_run + 1);
7769
0
  }
7770
0
  if (off < width) {
7771
0
    out.append(p + off, width - off);
7772
0
  }
7773
0
}
7774
#endif  // ADA_UNICODE_SSSE3 || ADA_NEON
7775
7776
ada_really_inline void percent_encode_to_scalar(const char* p, const char* end,
7777
                                                const uint8_t character_set[],
7778
0
                                                std::string& out) {
7779
0
  for (; p != end; ++p) {
7780
0
    if (character_sets::bit_at(character_set, *p)) {
7781
0
      out.append(character_sets::hex + uint8_t(*p) * 4, 3);
7782
0
    } else {
7783
0
      out += *p;
7784
0
    }
7785
0
  }
7786
0
}
7787
7788
#if ADA_UNICODE_SSSE3
7789
// Classify 16 input bytes against the 32-byte character_set bitmap:
7790
// bit_at(cs, b) == cs[b >> 3] & (1 << (b & 7)). pshufb looks up the two
7791
// 16-byte halves of that bitmap; no per-call nibble table is built.
7792
struct ssse3_percent_tables {
7793
  __m128i cs_lo;
7794
  __m128i cs_hi;
7795
  __m128i pow2;
7796
  __m128i mask_0f;
7797
  __m128i mask_07;
7798
  __m128i zero;
7799
};
7800
7801
ADA_UNICODE_SIMD ssse3_percent_tables
7802
0
load_ssse3_percent_tables(const uint8_t character_set[]) noexcept {
7803
0
  ssse3_percent_tables t{};
7804
0
  t.cs_lo = _mm_loadu_si128(reinterpret_cast<const __m128i*>(character_set));
7805
0
  t.cs_hi =
7806
0
      _mm_loadu_si128(reinterpret_cast<const __m128i*>(character_set + 16));
7807
  // 1 << (0..7), duplicated so pshufb(index & 7) works for every lane.
7808
0
  t.pow2 =
7809
0
      _mm_setr_epi8(1, 2, 4, 8, 16, 32, 64, -128, 1, 2, 4, 8, 16, 32, 64, -128);
7810
0
  t.mask_0f = _mm_set1_epi8(0x0F);
7811
0
  t.mask_07 = _mm_set1_epi8(0x07);
7812
0
  t.zero = _mm_setzero_si128();
7813
0
  return t;
7814
0
}
7815
7816
ADA_UNICODE_SIMD int ssse3_percent_mask(
7817
0
    __m128i word, const ssse3_percent_tables& tables) noexcept {
7818
0
  const __m128i idx = _mm_and_si128(_mm_srli_epi16(word, 3), tables.mask_0f);
7819
0
  const __m128i lo = _mm_shuffle_epi8(tables.cs_lo, idx);
7820
0
  const __m128i hi = _mm_shuffle_epi8(tables.cs_hi, idx);
7821
  // Bytes 0x80-0xFF are signed-negative; select the high half of the bitmap.
7822
0
  const __m128i high_byte = _mm_cmpgt_epi8(tables.zero, word);
7823
0
  const __m128i cs_byte = _mm_or_si128(_mm_and_si128(hi, high_byte),
7824
0
                                       _mm_andnot_si128(high_byte, lo));
7825
0
  const __m128i bits =
7826
0
      _mm_shuffle_epi8(tables.pow2, _mm_and_si128(word, tables.mask_07));
7827
0
  const __m128i hits = _mm_and_si128(cs_byte, bits);
7828
0
  return _mm_movemask_epi8(_mm_cmpeq_epi8(hits, tables.zero)) ^ 0xFFFF;
7829
0
}
7830
7831
ADA_UNICODE_SIMD void percent_encode_to_ssse3(
7832
    const char* p, const char* end, const uint8_t character_set[],
7833
0
    const ssse3_percent_tables& tables, std::string& out) {
7834
  // Pair 16-byte windows so a fully clean 32-byte run is one append.
7835
0
  while (p + 32 <= end) {
7836
0
    const __m128i word0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
7837
0
    const __m128i word1 =
7838
0
        _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + 16));
7839
0
    const int mask0 = ssse3_percent_mask(word0, tables);
7840
0
    const int mask1 = ssse3_percent_mask(word1, tables);
7841
0
    if ((mask0 | mask1) == 0) {
7842
0
      out.append(p, 32);
7843
0
    } else {
7844
0
      if (mask0 == 0) {
7845
0
        out.append(p, 16);
7846
0
      } else {
7847
0
        encode_mask_window(p, static_cast<uint32_t>(mask0), 16, out);
7848
0
      }
7849
0
      if (mask1 == 0) {
7850
0
        out.append(p + 16, 16);
7851
0
      } else {
7852
0
        encode_mask_window(p + 16, static_cast<uint32_t>(mask1), 16, out);
7853
0
      }
7854
0
    }
7855
0
    p += 32;
7856
0
  }
7857
0
  if (p + 16 <= end) {
7858
0
    const __m128i word = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
7859
0
    const int mask = ssse3_percent_mask(word, tables);
7860
0
    if (mask == 0) {
7861
0
      out.append(p, 16);
7862
0
    } else {
7863
0
      encode_mask_window(p, static_cast<uint32_t>(mask), 16, out);
7864
0
    }
7865
0
    p += 16;
7866
0
  }
7867
0
  percent_encode_to_scalar(p, end, character_set, out);
7868
0
}
7869
#endif  // ADA_UNICODE_SSSE3
7870
7871
#if ADA_NEON
7872
ada_really_inline uint8x16x2_t
7873
load_neon_percent_table(const uint8_t character_set[]) noexcept {
7874
  uint8x16x2_t table{};
7875
  table.val[0] = vld1q_u8(character_set);
7876
  table.val[1] = vld1q_u8(character_set + 16);
7877
  return table;
7878
}
7879
7880
ada_really_inline uint8x16_t neon_percent_hits(uint8x16_t word,
7881
                                               uint8x16x2_t table) noexcept {
7882
  const uint8x16_t cs_bytes = vqtbl2q_u8(table, vshrq_n_u8(word, 3));
7883
  const uint8x16_t bit_mask = vshlq_u8(
7884
      vdupq_n_u8(1), vreinterpretq_s8_u8(vandq_u8(word, vdupq_n_u8(7))));
7885
  return vandq_u8(cs_bytes, bit_mask);
7886
}
7887
7888
ada_really_inline uint32_t neon_percent_mask(uint8x16_t hits) noexcept {
7889
  const uint8x16_t cmp = vcgtq_u8(hits, vdupq_n_u8(0));
7890
  const uint8x16_t bit = {1, 2, 4, 8, 16, 32, 64, 128,
7891
                          1, 2, 4, 8, 16, 32, 64, 128};
7892
  const uint8x16_t masked = vandq_u8(cmp, bit);
7893
  return static_cast<uint32_t>(vaddv_u8(vget_low_u8(masked))) |
7894
         (static_cast<uint32_t>(vaddv_u8(vget_high_u8(masked))) << 8);
7895
}
7896
7897
ada_really_inline void percent_encode_to_neon(const char* p, const char* end,
7898
                                              const uint8_t character_set[],
7899
                                              uint8x16x2_t table,
7900
                                              std::string& out) {
7901
  while (p + 32 <= end) {
7902
    const uint8x16_t hits0 =
7903
        neon_percent_hits(vld1q_u8(reinterpret_cast<const uint8_t*>(p)), table);
7904
    const uint8x16_t hits1 = neon_percent_hits(
7905
        vld1q_u8(reinterpret_cast<const uint8_t*>(p + 16)), table);
7906
    const bool clean0 = vmaxvq_u32(vreinterpretq_u32_u8(hits0)) == 0;
7907
    const bool clean1 = vmaxvq_u32(vreinterpretq_u32_u8(hits1)) == 0;
7908
    if (clean0 && clean1) {
7909
      out.append(p, 32);
7910
    } else {
7911
      if (clean0) {
7912
        out.append(p, 16);
7913
      } else {
7914
        encode_mask_window(p, neon_percent_mask(hits0), 16, out);
7915
      }
7916
      if (clean1) {
7917
        out.append(p + 16, 16);
7918
      } else {
7919
        encode_mask_window(p + 16, neon_percent_mask(hits1), 16, out);
7920
      }
7921
    }
7922
    p += 32;
7923
  }
7924
  if (p + 16 <= end) {
7925
    const uint8x16_t hits =
7926
        neon_percent_hits(vld1q_u8(reinterpret_cast<const uint8_t*>(p)), table);
7927
    if (vmaxvq_u32(vreinterpretq_u32_u8(hits)) == 0) {
7928
      out.append(p, 16);
7929
    } else {
7930
      encode_mask_window(p, neon_percent_mask(hits), 16, out);
7931
    }
7932
    p += 16;
7933
  }
7934
  percent_encode_to_scalar(p, end, character_set, out);
7935
}
7936
#endif  // ADA_NEON
7937
7938
#if ADA_RVV
7939
ada_really_inline void percent_encode_to_rvv(const char* p, const char* end,
7940
                                             const uint8_t character_set[],
7941
                                             std::string& out) {
7942
  while (p < end) {
7943
    const size_t remaining = static_cast<size_t>(end - p);
7944
    const size_t vl = __riscv_vsetvl_e8m1(remaining);
7945
    const vuint8m1_t word =
7946
        __riscv_vle8_v_u8m1(reinterpret_cast<const uint8_t*>(p), vl);
7947
    const vuint8m1_t cs_bytes =
7948
        __riscv_vluxei8(character_set, __riscv_vsrl(word, 3, vl), vl);
7949
    const vuint8m1_t bit_mask = __riscv_vsll(__riscv_vmv_v_x_u8m1(1, vl),
7950
                                             __riscv_vand(word, 7, vl), vl);
7951
    const long idx = __riscv_vfirst(
7952
        __riscv_vmsne(__riscv_vand(cs_bytes, bit_mask, vl), 0, vl), vl);
7953
    if (idx < 0) {
7954
      out.append(p, vl);
7955
      p += vl;
7956
      continue;
7957
    }
7958
    if (idx > 0) {
7959
      out.append(p, static_cast<size_t>(idx));
7960
      p += idx;
7961
    }
7962
    out.append(character_sets::hex + uint8_t(*p) * 4, 3);
7963
    ++p;
7964
  }
7965
}
7966
#endif  // ADA_RVV
7967
7968
#if ADA_UNICODE_SSSE3 || ADA_NEON || ADA_RVV
7969
// Setter and existing percent_encode benches are 2-44 bytes. Table setup
7970
// plus mask walking costs more instructions than bit_at on those inputs
7971
// (especially dense USERINFO). SIMD pays off on the remaining suffix.
7972
static constexpr size_t kPercentEncodeSimdMin = 48;
7973
7974
void percent_encode_to_wide(const char* p, const char* end,
7975
0
                            const uint8_t character_set[], std::string& out) {
7976
  // Worst case every byte becomes %XX. Avoids realloc while walking windows.
7977
0
  out.reserve(out.size() + static_cast<size_t>(end - p) * 3);
7978
0
#if ADA_UNICODE_SSSE3
7979
0
  const ssse3_percent_tables tables = load_ssse3_percent_tables(character_set);
7980
0
  percent_encode_to_ssse3(p, end, character_set, tables, out);
7981
#elif ADA_NEON
7982
  percent_encode_to_neon(p, end, character_set,
7983
                         load_neon_percent_table(character_set), out);
7984
#elif ADA_RVV
7985
  percent_encode_to_rvv(p, end, character_set, out);
7986
#endif
7987
0
}
7988
#endif
7989
7990
}  // namespace
7991
7992
void percent_encode_suffix(const char* p, const char* end,
7993
0
                           const uint8_t character_set[], std::string& out) {
7994
0
#if ADA_UNICODE_SSSE3 || ADA_NEON || ADA_RVV
7995
0
#ifdef ADA_UNICODE_NEED_SSSE3_TARGET
7996
0
  static const bool ssse3_supported = __builtin_cpu_supports("ssse3") != 0;
7997
0
  const bool use_wide = ssse3_supported;
7998
#else
7999
  const bool use_wide = true;
8000
#endif
8001
0
  if (use_wide && static_cast<size_t>(end - p) >= kPercentEncodeSimdMin) {
8002
0
    percent_encode_to_wide(p, end, character_set, out);
8003
0
    return;
8004
0
  }
8005
0
#endif
8006
0
  percent_encode_to_scalar(p, end, character_set, out);
8007
0
}
8008
8009
}  // namespace ada::unicode
8010
/* end file src/unicode_percent_encode.cpp */
8011
#endif
8012
/* begin file src/serializers.cpp */
8013
8014
#include <array>
8015
#include <cstdint>
8016
#include <cstring>
8017
#include <string>
8018
8019
namespace ada::serializers {
8020
namespace {
8021
8022
// Digit pair LUT for fast decimal write: index 0..99 -> two chars.
8023
0
constexpr std::array<char, 200> make_digit_pairs() noexcept {
8024
0
  std::array<char, 200> t{};
8025
0
  for (size_t i = 0; i < 100; ++i) {
8026
0
    t[i * 2] = static_cast<char>('0' + i / 10);
8027
0
    t[i * 2 + 1] = static_cast<char>('0' + i % 10);
8028
0
  }
8029
0
  return t;
8030
0
}
8031
8032
constexpr auto digit_pairs = make_digit_pairs();
8033
8034
136k
ada_really_inline char* write_u8(char* p, uint8_t v) noexcept {
8035
136k
  if (v < 10) {
8036
105k
    *p++ = static_cast<char>('0' + v);
8037
105k
  } else if (v < 100) {
8038
10.1k
    std::memcpy(p, &digit_pairs[static_cast<size_t>(v) * 2], 2);
8039
10.1k
    p += 2;
8040
20.6k
  } else {
8041
20.6k
    *p++ = static_cast<char>('0' + v / 100);
8042
20.6k
    std::memcpy(p, &digit_pairs[static_cast<size_t>(v % 100) * 2], 2);
8043
20.6k
    p += 2;
8044
20.6k
  }
8045
136k
  return p;
8046
136k
}
8047
8048
7.26k
ada_really_inline char* write_hex_u16(char* p, uint16_t v) noexcept {
8049
7.26k
  static constexpr char kHex[] = "0123456789abcdef";
8050
7.26k
  if (v >= 0x1000) {
8051
1.01k
    *p++ = kHex[(v >> 12) & 0xf];
8052
1.01k
    *p++ = kHex[(v >> 8) & 0xf];
8053
1.01k
    *p++ = kHex[(v >> 4) & 0xf];
8054
1.01k
    *p++ = kHex[v & 0xf];
8055
6.25k
  } else if (v >= 0x100) {
8056
1.02k
    *p++ = kHex[(v >> 8) & 0xf];
8057
1.02k
    *p++ = kHex[(v >> 4) & 0xf];
8058
1.02k
    *p++ = kHex[v & 0xf];
8059
5.23k
  } else if (v >= 0x10) {
8060
801
    *p++ = kHex[(v >> 4) & 0xf];
8061
801
    *p++ = kHex[v & 0xf];
8062
4.42k
  } else {
8063
4.42k
    *p++ = kHex[v & 0xf];
8064
4.42k
  }
8065
7.26k
  return p;
8066
7.26k
}
8067
8068
}  // namespace
8069
8070
void find_longest_sequence_of_ipv6_pieces(
8071
    const std::array<uint16_t, 8>& address, size_t& compress,
8072
3.11k
    size_t& compress_length) noexcept {
8073
3.11k
  compress = 0;
8074
3.11k
  compress_length = 0;
8075
3.11k
  size_t i = 0;
8076
13.0k
  while (i < 8) {
8077
9.96k
    if (address[i] != 0) {
8078
6.08k
      ++i;
8079
6.08k
      continue;
8080
6.08k
    }
8081
3.87k
    size_t next = i + 1;
8082
18.8k
    while (next < 8 && address[next] == 0) {
8083
14.9k
      ++next;
8084
14.9k
    }
8085
3.87k
    const size_t count = next - i;
8086
3.87k
    if (count > compress_length) {
8087
3.33k
      compress_length = count;
8088
3.33k
      compress = i;
8089
3.33k
    }
8090
3.87k
    i = next;
8091
3.87k
  }
8092
3.11k
}
8093
8094
3.11k
std::string ipv6(const std::array<uint16_t, 8>& address) {
8095
3.11k
  size_t compress = 0;
8096
3.11k
  size_t compress_length = 0;
8097
3.11k
  find_longest_sequence_of_ipv6_pieces(address, compress, compress_length);
8098
8099
  // Skip compression when the longest zero run is a single piece.
8100
3.11k
  if (compress_length <= 1) {
8101
140
    compress = compress_length = 8;
8102
140
  }
8103
8104
  // Max: '[' + 8*4 hex + 7 ':' + ']' = 41
8105
3.11k
  std::string output(4 * 8 + 7 + 2, '\0');
8106
3.11k
  char* point = output.data();
8107
3.11k
  *point++ = '[';
8108
3.11k
  size_t piece_index = 0;
8109
8.19k
  while (true) {
8110
8.19k
    if (piece_index == compress) {
8111
2.97k
      *point++ = ':';
8112
      // If we skip a value initially, we need to write '::'.
8113
2.97k
      if (piece_index == 0) {
8114
1.66k
        *point++ = ':';
8115
1.66k
      }
8116
2.97k
      piece_index += compress_length;
8117
2.97k
      if (piece_index == 8) {
8118
931
        break;
8119
931
      }
8120
2.97k
    }
8121
7.26k
    point = write_hex_u16(point, address[piece_index]);
8122
7.26k
    ++piece_index;
8123
7.26k
    if (piece_index == 8) {
8124
2.18k
      break;
8125
2.18k
    }
8126
5.07k
    *point++ = ':';
8127
5.07k
  }
8128
3.11k
  *point++ = ']';
8129
3.11k
  output.resize(static_cast<size_t>(point - output.data()));
8130
3.11k
  return output;
8131
3.11k
}
8132
8133
34.1k
std::string ipv4(const uint64_t address) {
8134
34.1k
  std::string output(15, '\0');
8135
34.1k
  char* point = output.data();
8136
34.1k
  point = write_u8(point, static_cast<uint8_t>(address >> 24));
8137
34.1k
  *point++ = '.';
8138
34.1k
  point = write_u8(point, static_cast<uint8_t>(address >> 16));
8139
34.1k
  *point++ = '.';
8140
34.1k
  point = write_u8(point, static_cast<uint8_t>(address >> 8));
8141
34.1k
  *point++ = '.';
8142
34.1k
  point = write_u8(point, static_cast<uint8_t>(address));
8143
34.1k
  output.resize(static_cast<size_t>(point - output.data()));
8144
34.1k
  return output;
8145
34.1k
}
8146
8147
}  // namespace ada::serializers
8148
/* end file src/serializers.cpp */
8149
/* begin file src/implementation.cpp */
8150
8151
#include <array>
8152
#include <atomic>
8153
#include <cstdint>
8154
#include <cstring>
8155
#include <limits>
8156
#include <optional>
8157
#include <string>
8158
#include <string_view>
8159
8160
8161
namespace ada {
8162
8163
static std::atomic<uint32_t> max_input_length_{
8164
    std::numeric_limits<uint32_t>::max()};
8165
8166
0
void set_max_input_length(uint32_t length) {
8167
0
  max_input_length_.store(length, std::memory_order_relaxed);
8168
0
}
8169
8170
1.70M
uint32_t get_max_input_length() {
8171
1.70M
  return max_input_length_.load(std::memory_order_relaxed);
8172
1.70M
}
8173
8174
namespace {
8175
8176
constexpr std::array<uint8_t, 256> clean_http_host_byte = []() consteval {
8177
  std::array<uint8_t, 256> result{};
8178
  for (size_t i = 0; i < result.size(); ++i) {
8179
    const auto c = static_cast<uint8_t>(i);
8180
    result[i] =
8181
        static_cast<uint8_t>((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
8182
                             c == '-' || c == '.' || c == '_' || c == '~');
8183
  }
8184
  return result;
8185
}();
8186
8187
// SWAR: eight ASCII host bytes in [a-z0-9-._~] without 8 table lookups.
8188
// High bits must be clear first so the range subtracts cannot borrow
8189
// across bytes.
8190
// High-bit-cleared ASCII only. Subtracts cannot borrow across bytes because
8191
// each (hi|0x80) byte is >= 0x80 and each data byte is <= 0x7F. Do not use
8192
// has-zero (x-ones)&~x: a match followed by match^1 (e.g. "./" or "_^")
8193
// produces a false positive via borrow.
8194
ada_really_inline uint64_t swar_in_range(uint64_t w, uint8_t lo,
8195
0
                                         uint8_t hi) noexcept {
8196
0
  constexpr uint64_t k_ones = 0x0101010101010101ull;
8197
0
  constexpr uint64_t k_high = 0x8080808080808080ull;
8198
0
  const uint64_t ge_lo = (w | k_high) - (k_ones * lo);
8199
0
  const uint64_t le_hi = ((k_ones * hi) | k_high) - w;
8200
0
  return ge_lo & le_hi & k_high;
8201
0
}
8202
8203
ada_really_inline bool eight_clean_http_host_bytes(
8204
0
    const uint8_t* input) noexcept {
8205
0
  uint64_t w = 0;
8206
0
  std::memcpy(&w, input, 8);
8207
0
  constexpr uint64_t k_high = 0x8080808080808080ull;
8208
0
  if ((w & k_high) != 0) {
8209
0
    return false;
8210
0
  }
8211
0
  const uint64_t ok = swar_in_range(w, 'a', 'z') | swar_in_range(w, '0', '9') |
8212
0
                      swar_in_range(w, '-', '-') | swar_in_range(w, '.', '.') |
8213
0
                      swar_in_range(w, '_', '_') | swar_in_range(w, '~', '~');
8214
0
  return ok == k_high;
8215
0
}
8216
8217
// Minimal front end for the overwhelmingly common already-canonical HTTP(S)
8218
// case. It deliberately handles fewer inputs than
8219
// try_can_parse_absolute_fast: anything requiring normalization or detailed
8220
// host parsing falls through to that broader validator.
8221
#if defined(_MSC_VER) || \
8222
    (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
8223
constexpr bool k_can_parse_little_endian = true;
8224
#else
8225
constexpr bool k_can_parse_little_endian = false;
8226
#endif
8227
8228
0
std::optional<bool> try_can_parse_clean_http(std::string_view input) noexcept {
8229
0
  const auto* bytes = reinterpret_cast<const uint8_t*>(input.data());
8230
0
  const size_t length = input.size();
8231
0
  if (length < 7) {
8232
0
    return std::nullopt;
8233
0
  }
8234
8235
0
  size_t authority_start;
8236
0
  if constexpr (k_can_parse_little_endian) {
8237
0
    if (length >= 8) {
8238
0
      uint64_t first8 = 0;
8239
0
      std::memcpy(&first8, bytes, 8);
8240
0
      if (first8 == 0x2f2f3a7370747468ull) {  // "https://"
8241
0
        authority_start = 8;
8242
0
      } else if ((first8 & 0x00ffffffffffffffull) ==
8243
0
                 0x002f2f3a70747468ull) {  // "http://"
8244
0
        authority_start = 7;
8245
0
      } else {
8246
0
        return std::nullopt;
8247
0
      }
8248
0
    } else if (bytes[0] == 'h' && bytes[1] == 't' && bytes[2] == 't' &&
8249
0
               bytes[3] == 'p' && bytes[4] == ':' && bytes[5] == '/' &&
8250
0
               bytes[6] == '/') {
8251
0
      authority_start = 7;
8252
0
    } else {
8253
0
      return std::nullopt;
8254
0
    }
8255
  } else {
8256
    uint32_t first4{};
8257
    std::memcpy(&first4, bytes, 4);
8258
    if (first4 != 0x68747470u) {  // "http"
8259
      return std::nullopt;
8260
    }
8261
    if (length >= 8 && bytes[4] == 's' && bytes[5] == ':' && bytes[6] == '/' &&
8262
        bytes[7] == '/') {
8263
      authority_start = 8;
8264
    } else if (bytes[4] == ':' && bytes[5] == '/' && bytes[6] == '/') {
8265
      authority_start = 7;
8266
    } else {
8267
      return std::nullopt;
8268
    }
8269
  }
8270
8271
0
  if (authority_start >= length) {
8272
0
    return false;
8273
0
  }
8274
8275
0
  size_t cursor = authority_start;
8276
0
  while (cursor + 8 <= length && eight_clean_http_host_bytes(bytes + cursor)) {
8277
0
    cursor += 8;
8278
0
  }
8279
0
  while (cursor < length) {
8280
0
    const uint8_t c = bytes[cursor];
8281
0
    if (c == '/' || c == '?' || c == '#') {
8282
0
      break;
8283
0
    }
8284
0
    if (!clean_http_host_byte[c]) {
8285
0
      return std::nullopt;
8286
0
    }
8287
0
    ++cursor;
8288
0
  }
8289
8290
0
  const size_t host_length = cursor - authority_start;
8291
0
  if (host_length == 0) {
8292
    // Extra special-scheme slashes are normalization, not an empty host.
8293
0
    if (bytes[authority_start] == '/' || bytes[authority_start] == '\\') {
8294
0
      return std::nullopt;
8295
0
    }
8296
0
    return false;
8297
0
  }
8298
0
  if (host_length > 253 || bytes[cursor - 1] == '.') {
8299
0
    return std::nullopt;
8300
0
  }
8301
8302
0
  const std::string_view host(input.data() + authority_start, host_length);
8303
0
  if (checkers::last_label_may_be_a_number(host)) {
8304
0
    return std::nullopt;
8305
0
  }
8306
0
  if (host.find('x') != std::string_view::npos &&
8307
0
      host.find("xn-") != std::string_view::npos) {
8308
0
    return std::nullopt;
8309
0
  }
8310
8311
  // Once a special URL has a valid host, path/query/fragment bytes cannot make
8312
  // it structurally invalid: the full parser percent-encodes them as needed.
8313
0
  return true;
8314
0
}
8315
8316
// @private
8317
// Fast-path validator for can_parse.
8318
//
8319
// Validates absolute special (non-file) URLs without constructing any
8320
// url_aggregator object and without running the state machine.
8321
// Performs a single forward scan over the input bytes.
8322
//
8323
// Returns:
8324
//   true      -- URL is structurally valid
8325
//   false     -- URL is definitely invalid
8326
//   nullopt   -- edge case; fall through to the full parser
8327
//               (credentials, IDNA, IPv4/6, tabs/newlines, relative URLs, ...)
8328
std::optional<bool> try_can_parse_absolute_fast(
8329
0
    std::string_view input) noexcept {
8330
0
  const uint8_t* b = reinterpret_cast<const uint8_t*>(input.data());
8331
0
  size_t len = input.size();
8332
8333
  // -- Inline C0 whitespace trim (no allocation) --------------------------
8334
  // Note: \t (0x09), \n (0x0a), \r (0x0d) are all <= 0x20, so any
8335
  // leading/trailing tabs or newlines are correctly stripped here, matching
8336
  // the WHATWG spec's "remove leading/trailing C0 control and space" step.
8337
0
  while (len > 0 && b[0] <= 0x20) {
8338
0
    b++;
8339
0
    len--;
8340
0
  }
8341
0
  while (len > 0 && b[len - 1] <= 0x20) {
8342
0
    len--;
8343
0
  }
8344
0
  if (len == 0) return false;
8345
8346
  // -- Scheme detection -----------------------------------------------------
8347
  // Fast path for HTTP and HTTPS (covers ~90%+ of real-world URLs).
8348
  // Avoids the general scheme loop, buffer copy, and perfect hash lookup.
8349
  // We know HTTP and HTTPS are special non-file schemes, so no further
8350
  // scheme_type checks are needed on the fast path -- only `pos` matters.
8351
0
  size_t pos;
8352
8353
0
  if (len >= 7 && (b[0] | 0x20) == 'h' && (b[1] | 0x20) == 't' &&
8354
0
      (b[2] | 0x20) == 't' && (b[3] | 0x20) == 'p') {
8355
0
    if (b[4] == ':' && b[5] == '/' && b[6] == '/') {
8356
0
      pos = 7;
8357
0
      goto skip_extra_slashes;
8358
0
    }
8359
0
    if (len >= 8 && (b[4] | 0x20) == 's' && b[5] == ':' && b[6] == '/' &&
8360
0
        b[7] == '/') {
8361
0
      pos = 8;
8362
0
      goto skip_extra_slashes;
8363
0
    }
8364
    // Fall through: could be "httpe://", tabs in scheme, etc.
8365
0
  }
8366
8367
0
  {
8368
    // General scheme detection for ws, wss, ftp, and edge cases.
8369
0
    if (!checkers::is_alpha(static_cast<char>(b[0]))) return false;
8370
8371
    // Scan for ':' within the first 7 bytes. All special schemes are <= 5
8372
    // chars ("https"), so any URL whose first ':' is beyond byte 6 is either
8373
    // non-special or relative -- both require the full parser.
8374
0
    size_t colon_pos = 0;
8375
0
    for (size_t i = 1;; ++i) {
8376
0
      if (i >= 7 || i >= len) return std::nullopt;
8377
0
      const char c = static_cast<char>(b[i]);
8378
0
      if (c == ':') {
8379
0
        colon_pos = i;
8380
0
        break;
8381
0
      }
8382
      // Tabs/newlines in the scheme require the full parser to strip them.
8383
0
      if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
8384
0
      if (!unicode::is_alnum_plus(c)) return false;
8385
0
    }
8386
8387
    // Lowercase scheme bytes inline and classify via the existing perfect
8388
    // hash.
8389
0
    char scheme_buf[6];
8390
0
    scheme_buf[0] = static_cast<char>(b[0] | 0x20);
8391
0
    for (size_t i = 1; i < colon_pos; ++i)
8392
0
      scheme_buf[i] = static_cast<char>(b[i] | 0x20);
8393
8394
0
    const ada::scheme::type scheme_type =
8395
0
        ada::scheme::get_scheme_type({scheme_buf, colon_pos});
8396
8397
    // Only handle special, non-file schemes.
8398
0
    if (scheme_type == ada::scheme::NOT_SPECIAL) return std::nullopt;
8399
0
    if (scheme_type == ada::scheme::FILE) return std::nullopt;
8400
8401
    // Per WHATWG, special URLs don't require "//": "http:example.com" is valid
8402
    // (SPECIAL_AUTHORITY_IGNORE_SLASHES just skips leading slashes and
8403
    // proceeds to AUTHORITY).  Defer to the inline fallback for any input
8404
    // without "://".
8405
0
    pos = colon_pos + 1;
8406
0
    if (pos + 2 > len || b[pos] != '/' || b[pos + 1] != '/') {
8407
0
      return std::nullopt;
8408
0
    }
8409
0
    pos += 2;
8410
0
  }
8411
8412
0
skip_extra_slashes:
8413
  // SPECIAL_AUTHORITY_IGNORE_SLASHES: the full parser skips any additional
8414
  // leading '/' or '\' after the initial "//".  Mirror that here so we don't
8415
  // mis-identify the host as empty when there are extra slashes.
8416
0
  while (pos < len && (b[pos] == '/' || b[pos] == '\\')) {
8417
0
    ++pos;
8418
0
  }
8419
8420
  // Early IPv6 bail-out: if the authority starts with '[', it's an IPv6
8421
  // literal which requires the full parser.  Checking here avoids scanning
8422
  // the entire bracketed address only to bail out afterward.
8423
0
  if (pos < len && b[pos] == '[') return std::nullopt;
8424
8425
  // -- Merged authority + host scan ------------------------------------------
8426
  // A single forward pass over the authority bytes that simultaneously:
8427
  //   - finds the authority end and port colon
8428
  //   - validates host characters (forbidden domain code points)
8429
  //   - tracks IPv4 indicators (all-decimal-dots, last non-dot char)
8430
  //   - detects xn-- prefixes (IDNA punycode)
8431
  //   - detects tabs/newlines (which require the full parser to strip)
8432
  // This replaces 4 separate scans over the host bytes.
8433
0
  const size_t auth_start = pos;
8434
0
  size_t auth_end = pos;
8435
0
  size_t port_colon = SIZE_MAX;
8436
0
  bool all_dec_dots = true;
8437
8438
0
  for (; auth_end < len; ++auth_end) {
8439
0
    const uint8_t c = b[auth_end];
8440
8441
    // Non-ASCII -> needs IDNA processing -> full parser.
8442
0
    if (c >= 0x80) return std::nullopt;
8443
8444
    // Authority delimiters.
8445
0
    if (c == '/' || c == '?' || c == '#' || c == '\\') break;
8446
8447
    // Port separator.
8448
0
    if (c == ':') {
8449
0
      if (port_colon == SIZE_MAX) port_colon = auth_end;
8450
0
      continue;
8451
0
    }
8452
8453
    // Credentials or percent-encoding -> full parser.
8454
0
    if (c == '@' || c == '%') return std::nullopt;
8455
8456
    // Tabs/newlines anywhere in the authority require the full parser to
8457
    // strip them before validation.  Without this, a tab in the port (e.g.
8458
    // "http://host:8\t0/") would be mis-rejected by port validation.
8459
0
    if (c == '\t' || c == '\n' || c == '\r') return std::nullopt;
8460
8461
    // Skip remaining host-specific checks for port bytes.  Port digits are
8462
    // validated separately below, and no forbidden-domain-code-point check
8463
    // is needed on port characters.
8464
0
    if (port_colon != SIZE_MAX) continue;
8465
8466
    // -- Host byte validation (inlined) ------------------------------------
8467
    // Forbidden domain code points that are not already caught above:
8468
    //   C0 controls and space (0x00-0x20), DEL (0x7F), <, >, [, ], ^, |.
8469
    // At this stage, the input may still be userinfo or be normalized later
8470
    // (e.g., percent-encoded), so we do not reject here and defer to the
8471
    // parser. Characters already caught: >= 0x80 (non-ASCII), '/' '?' '#' '\\'
8472
    // (delimiters), ':' (port), '@' '%' (bail), '\t' '\n' '\r' (bail).
8473
0
    if (c <= 0x20 || c == 0x7F || c == '<' || c == '>' || c == '[' ||
8474
0
        c == ']' || c == '^' || c == '|') {
8475
0
      return std::nullopt;
8476
0
    }
8477
8478
    // Track whether host is all decimal digits and dots (potential IPv4).
8479
0
    if (c != '.' && (c < '0' || c > '9')) all_dec_dots = false;
8480
8481
    // Detect xn-- prefix inline (IDNA punycode -> needs full parser).
8482
    // Checking at every position mirrors the original behavior: any
8483
    // occurrence of "xn--" in the host (not just at label boundaries)
8484
    // triggers a bail-out to the full IDNA validator.
8485
0
    if ((c | 0x20) == 'x' && auth_end + 4 <= len &&
8486
0
        (b[auth_end + 1] | 0x20) == 'n' && b[auth_end + 2] == '-' &&
8487
0
        b[auth_end + 3] == '-') {
8488
0
      return std::nullopt;
8489
0
    }
8490
0
  }
8491
8492
0
  const size_t host_end = (port_colon != SIZE_MAX) ? port_colon : auth_end;
8493
8494
  // Empty host is invalid for special URLs.
8495
0
  if (auth_start == host_end) return false;
8496
8497
  // -- IPv4 handling ---------------------------------------------------------
8498
0
  const char* host_ptr = reinterpret_cast<const char*>(b + auth_start);
8499
0
  const size_t host_len = host_end - auth_start;
8500
8501
0
  if (all_dec_dots) {
8502
    // Host is all decimal digits and dots -> try the fast IPv4 parser.
8503
0
    if (checkers::try_parse_ipv4_fast({host_ptr, host_len}) !=
8504
0
        checkers::ipv4_fast_fail) {
8505
      // Valid decimal IPv4 host.  Do NOT return true yet: the port still
8506
      // needs to be validated below before we can declare the URL valid.
8507
0
      goto validate_port;
8508
0
    }
8509
    // Fast IPv4 parsing failed (e.g. host is ".", "..", "1.2.3.500").
8510
    // Such hosts may still be valid domain names; defer to the full parser.
8511
0
    return std::nullopt;
8512
0
  }
8513
8514
0
  if (checkers::last_label_may_be_a_number({host_ptr, host_len})) {
8515
0
    return std::nullopt;
8516
0
  }
8517
8518
  // -- Port validation -------------------------------------------------------
8519
0
validate_port:
8520
0
  if (port_colon != SIZE_MAX) {
8521
0
    const uint8_t* pp = b + port_colon + 1;
8522
0
    size_t pl = auth_end - port_colon - 1;
8523
0
    if (pl > 0) {
8524
      // Strip leading zeros: "0000001" == 1, "0000000000000" == 0, both valid.
8525
      // Only the significant digits count toward the 5-digit maximum.
8526
0
      while (pl > 0 && *pp == '0') {
8527
0
        ++pp;
8528
0
        --pl;
8529
0
      }
8530
0
      if (pl > 5) return false;  // significant digits > 99999
8531
0
      uint32_t pv = 0;
8532
0
      for (size_t i = 0; i < pl; ++i) {
8533
0
        if (pp[i] < '0' || pp[i] > '9') return false;
8534
0
        pv = pv * 10 + (pp[i] - '0');
8535
0
      }
8536
0
      if (pv > 65535) return false;
8537
0
    }
8538
0
  }
8539
8540
  // Path, query, and fragment are structurally always valid for can_parse --
8541
  // the parser would encode whatever is there.
8542
0
  return true;
8543
0
}
8544
8545
}  // namespace
8546
8547
template <class result_type>
8548
ada_warn_unused tl::expected<result_type, errors> parse(
8549
1.44M
    std::string_view input, const result_type* base_url) {
8550
1.44M
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
8551
1.44M
  if (!u.is_valid) {
8552
595k
    return tl::unexpected(errors::type_error);
8553
595k
  }
8554
845k
  return u;
8555
1.44M
}
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
8549
1.44M
    std::string_view input, const result_type* base_url) {
8550
1.44M
  result_type u = ada::parser::parse_url_impl<result_type>(input, base_url);
8551
1.44M
  if (!u.is_valid) {
8552
595k
    return tl::unexpected(errors::type_error);
8553
595k
  }
8554
845k
  return u;
8555
1.44M
}
8556
8557
template ada::result<url> parse<url>(std::string_view input,
8558
                                     const url* base_url = nullptr);
8559
template ada::result<url_aggregator> parse<url_aggregator>(
8560
    std::string_view input, const url_aggregator* base_url = nullptr);
8561
8562
0
std::string href_from_file(std::string_view input) {
8563
  // Match ada::parse / setters: refuse inputs that already exceed the limit.
8564
  // Path percent-encoding can still expand the result, so we also check the
8565
  // final href below.
8566
0
  const uint32_t max_length = ada::get_max_input_length();
8567
0
  if (input.size() > max_length) {
8568
0
    return {};
8569
0
  }
8570
8571
  // This is going to be much faster than constructing a URL.
8572
0
  std::string tmp_buffer;
8573
0
  std::string_view internal_input;
8574
0
  if (unicode::has_tabs_or_newline(input)) {
8575
0
    tmp_buffer = input;
8576
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
8577
0
    internal_input = tmp_buffer;
8578
0
  } else {
8579
0
    internal_input = input;
8580
0
  }
8581
0
  std::string path;
8582
0
  if (internal_input.empty()) {
8583
0
    path = "/";
8584
0
  } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
8585
0
    helpers::parse_prepared_path(internal_input.substr(1),
8586
0
                                 ada::scheme::type::FILE, path);
8587
0
  } else {
8588
0
    helpers::parse_prepared_path(internal_input, ada::scheme::type::FILE, path);
8589
0
  }
8590
0
  std::string result = "file://" + path;
8591
0
  if (result.size() > max_length) {
8592
0
    return {};
8593
0
  }
8594
0
  return result;
8595
0
}
8596
8597
0
bool can_parse(std::string_view input, const std::string_view* base_input) {
8598
  // Must match parse().has_value(), including post-normalization max length.
8599
  // Percent-encoding expands a byte by at most 3x, but IDNA expands more: a
8600
  // 3-byte UTF-8 label such as U+337F becomes the 17-byte "xn--6oqv20b1zgzxr",
8601
  // so a dotted host sustains 4.5x. When the input (plus base, if any) fits in
8602
  // max_length/5, the normalized href cannot exceed max_length, so
8603
  // validation-only parsing (store_values=false) is safe.
8604
8605
  // Hot path first: absolute special URLs, no base. Avoid loading max_length
8606
  // until we need it (common absolute-fast true/false cases).
8607
0
  if (base_input == nullptr) {
8608
0
    auto r = try_can_parse_clean_http(input);
8609
0
    if (!r.has_value()) {
8610
0
      r = try_can_parse_absolute_fast(input);
8611
0
    }
8612
0
    if (r.has_value()) {
8613
0
      if (!*r) {
8614
0
        return false;
8615
0
      }
8616
      // size <= max/5 => normalized href cannot exceed max (4.5x expansion).
8617
      // Check this first: default max is ~4GB so almost all URLs return true.
8618
0
      const uint32_t max_length = ada::get_max_input_length();
8619
0
      if (input.size() <= static_cast<size_t>(max_length) / 5) {
8620
0
        return true;
8621
0
      }
8622
0
      if (input.size() > max_length) {
8623
0
        return false;
8624
0
      }
8625
0
      return ada::parser::parse_url_impl<ada::url_aggregator, true>(input,
8626
0
                                                                    nullptr)
8627
0
          .is_valid;
8628
0
    }
8629
0
  }
8630
8631
0
  const uint32_t max_length = ada::get_max_input_length();
8632
0
  if (input.size() > max_length) {
8633
0
    return false;
8634
0
  }
8635
0
  if (base_input != nullptr && base_input->size() > max_length) {
8636
0
    return false;
8637
0
  }
8638
8639
  // Relative resolution combines base + input; bound the sum so 4.5x expansion
8640
  // of either side cannot push the final href past max_length.
8641
0
  const size_t combined =
8642
0
      input.size() + (base_input == nullptr ? 0 : base_input->size());
8643
0
  const bool size_safe = combined <= static_cast<size_t>(max_length) / 5;
8644
8645
0
  if (size_safe) {
8646
    // Validation-only: no buffer build, host still fully checked.
8647
0
    ada::url_aggregator base_agg;
8648
0
    ada::url_aggregator* base_ptr = nullptr;
8649
0
    if (base_input != nullptr) {
8650
0
      base_agg = ada::parser::parse_url_impl<ada::url_aggregator, false>(
8651
0
          *base_input, nullptr);
8652
0
      if (!base_agg.is_valid) {
8653
0
        return false;
8654
0
      }
8655
0
      base_ptr = &base_agg;
8656
0
    }
8657
0
    return ada::parser::parse_url_impl<ada::url_aggregator, false>(input,
8658
0
                                                                   base_ptr)
8659
0
        .is_valid;
8660
0
  }
8661
8662
  // Near the limit: full parse so post-normalization length matches parse().
8663
0
  if (base_input == nullptr) {
8664
0
    return ada::parser::parse_url_impl<ada::url_aggregator, true>(input,
8665
0
                                                                  nullptr)
8666
0
        .is_valid;
8667
0
  }
8668
0
  ada::url_aggregator base_agg =
8669
0
      ada::parser::parse_url_impl<ada::url_aggregator, true>(*base_input,
8670
0
                                                             nullptr);
8671
0
  if (!base_agg.is_valid) {
8672
0
    return false;
8673
0
  }
8674
0
  return ada::parser::parse_url_impl<ada::url_aggregator, true>(input,
8675
0
                                                                &base_agg)
8676
0
      .is_valid;
8677
0
}
8678
8679
0
ada_warn_unused std::string_view to_string(ada::encoding_type type) {
8680
0
  switch (type) {
8681
0
    case ada::encoding_type::UTF8:
8682
0
      return "UTF-8";
8683
0
    case ada::encoding_type::UTF_16LE:
8684
0
      return "UTF-16LE";
8685
0
    case ada::encoding_type::UTF_16BE:
8686
0
      return "UTF-16BE";
8687
0
    default:
8688
0
      unreachable();
8689
0
  }
8690
0
}
8691
8692
}  // namespace ada
8693
/* end file src/implementation.cpp */
8694
/* begin file src/helpers.cpp */
8695
#include <array>
8696
#include <cstdint>
8697
#include <cstring>
8698
#include <optional>
8699
#include <sstream>
8700
#include <string>
8701
#include <string_view>
8702
#include <utility>
8703
8704
8705
#if ADA_SSSE3
8706
#include <tmmintrin.h>
8707
#endif
8708
8709
namespace ada::helpers {
8710
8711
template <typename out_iter>
8712
0
void encode_json(std::string_view view, out_iter out) {
8713
  // trivial implementation. could be faster.
8714
0
  const char* hexvalues =
8715
0
      "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
8716
0
  for (uint8_t c : view) {
8717
0
    if (c == '\\') {
8718
0
      *out++ = '\\';
8719
0
      *out++ = '\\';
8720
0
    } else if (c == '"') {
8721
0
      *out++ = '\\';
8722
0
      *out++ = '"';
8723
0
    } else if (c <= 0x1f) {
8724
0
      *out++ = '\\';
8725
0
      *out++ = 'u';
8726
0
      *out++ = '0';
8727
0
      *out++ = '0';
8728
0
      *out++ = hexvalues[2 * c];
8729
0
      *out++ = hexvalues[2 * c + 1];
8730
0
    } else {
8731
0
      *out++ = c;
8732
0
    }
8733
0
  }
8734
0
}
8735
8736
0
ada_unused std::string get_state(ada::state s) {
8737
0
  switch (s) {
8738
0
    case ada::state::AUTHORITY:
8739
0
      return "Authority";
8740
0
    case ada::state::SCHEME_START:
8741
0
      return "Scheme Start";
8742
0
    case ada::state::SCHEME:
8743
0
      return "Scheme";
8744
0
    case ada::state::HOST:
8745
0
      return "Host";
8746
0
    case ada::state::NO_SCHEME:
8747
0
      return "No Scheme";
8748
0
    case ada::state::FRAGMENT:
8749
0
      return "Fragment";
8750
0
    case ada::state::RELATIVE_SCHEME:
8751
0
      return "Relative Scheme";
8752
0
    case ada::state::RELATIVE_SLASH:
8753
0
      return "Relative Slash";
8754
0
    case ada::state::FILE:
8755
0
      return "File";
8756
0
    case ada::state::FILE_HOST:
8757
0
      return "File Host";
8758
0
    case ada::state::FILE_SLASH:
8759
0
      return "File Slash";
8760
0
    case ada::state::PATH_OR_AUTHORITY:
8761
0
      return "Path or Authority";
8762
0
    case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES:
8763
0
      return "Special Authority Ignore Slashes";
8764
0
    case ada::state::SPECIAL_AUTHORITY_SLASHES:
8765
0
      return "Special Authority Slashes";
8766
0
    case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY:
8767
0
      return "Special Relative or Authority";
8768
0
    case ada::state::QUERY:
8769
0
      return "Query";
8770
0
    case ada::state::PATH:
8771
0
      return "Path";
8772
0
    case ada::state::PATH_START:
8773
0
      return "Path Start";
8774
0
    case ada::state::OPAQUE_PATH:
8775
0
      return "Opaque Path";
8776
0
    case ada::state::PORT:
8777
0
      return "Port";
8778
0
    default:
8779
0
      return "unknown state";
8780
0
  }
8781
0
}
8782
8783
ada_really_inline std::optional<std::string_view> prune_hash(
8784
781k
    std::string_view& input) noexcept {
8785
  // compiles down to 20--30 instructions including a class to memchr (C
8786
  // function). this function should be quite fast.
8787
781k
  size_t location_of_first = input.find('#');
8788
781k
  if (location_of_first == std::string_view::npos) {
8789
769k
    return std::nullopt;
8790
769k
  }
8791
11.8k
  std::string_view hash = input;
8792
11.8k
  hash.remove_prefix(location_of_first + 1);
8793
11.8k
  input.remove_suffix(input.size() - location_of_first);
8794
11.8k
  return hash;
8795
781k
}
8796
8797
5.74k
ada_really_inline bool shorten_path(std::string& path, ada::scheme::type type) {
8798
  // Let path be url's path.
8799
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
8800
  // Windows drive letter, then return.
8801
5.74k
  if (type == ada::scheme::type::FILE &&
8802
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
8803
0
    if (checkers::is_normalized_windows_drive_letter(
8804
0
            helpers::substring(path, 1))) {
8805
0
      return false;
8806
0
    }
8807
0
  }
8808
8809
  // Remove path's last item, if any.
8810
5.74k
  size_t last_delimiter = path.rfind('/');
8811
5.74k
  if (last_delimiter != std::string::npos) {
8812
3.61k
    path.erase(last_delimiter);
8813
3.61k
    return true;
8814
3.61k
  }
8815
8816
2.12k
  return false;
8817
5.74k
}
8818
8819
ada_really_inline bool shorten_path(std::string_view& path,
8820
0
                                    ada::scheme::type type) {
8821
  // Let path be url's path.
8822
  // If url's scheme is "file", path's size is 1, and path[0] is a normalized
8823
  // Windows drive letter, then return.
8824
0
  if (type == ada::scheme::type::FILE &&
8825
0
      path.find('/', 1) == std::string_view::npos && !path.empty()) {
8826
0
    if (checkers::is_normalized_windows_drive_letter(
8827
0
            helpers::substring(path, 1))) {
8828
0
      return false;
8829
0
    }
8830
0
  }
8831
8832
  // Remove path's last item, if any.
8833
0
  if (!path.empty()) {
8834
0
    size_t slash_loc = path.rfind('/');
8835
0
    if (slash_loc != std::string_view::npos) {
8836
0
      path.remove_suffix(path.size() - slash_loc);
8837
0
      return true;
8838
0
    }
8839
0
  }
8840
8841
0
  return false;
8842
0
}
8843
8844
19.9k
ada_really_inline void remove_ascii_tab_or_newline(std::string& input) {
8845
  // Fast path: inputs with no tab/newline (the common case) avoid the
8846
  // per-character erase_if scan. has_tabs_or_newline uses SIMD for inputs
8847
  // >= 16 bytes, making this check much cheaper than erase_if's scalar
8848
  // predicate walk when there is nothing to remove.
8849
19.9k
  if (!ada::unicode::has_tabs_or_newline(input)) {
8850
1.61k
    return;
8851
1.61k
  }
8852
18.2k
  std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
8853
18.2k
}
8854
8855
ada_really_inline constexpr std::string_view substring(std::string_view input,
8856
27.8k
                                                       size_t pos) {
8857
27.8k
  ADA_ASSERT_TRUE(pos <= input.size());
8858
  // The following is safer but unneeded if we have the above line:
8859
  // return pos > input.size() ? std::string_view() : input.substr(pos);
8860
27.8k
  return input.substr(pos);
8861
27.8k
}
8862
8863
0
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
8864
0
  ADA_ASSERT_TRUE(pos <= input.size());
8865
0
  input.remove_suffix(input.size() - pos);
8866
0
}
8867
8868
// computes the number of trailing zeroes
8869
// this is a private inline function only defined in this source file.
8870
70.0k
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
8871
#ifdef ADA_REGULAR_VISUAL_STUDIO
8872
  unsigned long ret;
8873
  // Search the mask data from least significant bit (LSB)
8874
  // to the most significant bit (MSB) for a set bit (1).
8875
  _BitScanForward(&ret, input_num);
8876
  return (int)ret;
8877
#else   // ADA_REGULAR_VISUAL_STUDIO
8878
70.0k
  return __builtin_ctzl(input_num);
8879
70.0k
#endif  // ADA_REGULAR_VISUAL_STUDIO
8880
70.0k
}
8881
8882
#if ADA_NEON
8883
// computes the number of trailing zeroes of a 64-bit word
8884
// this is a private inline function only defined in this source file.
8885
ada_really_inline int trailing_zeroes64(uint64_t input_num) noexcept {
8886
#ifdef ADA_REGULAR_VISUAL_STUDIO
8887
  unsigned long ret;
8888
  _BitScanForward64(&ret, input_num);
8889
  return (int)ret;
8890
#else   // ADA_REGULAR_VISUAL_STUDIO
8891
  return __builtin_ctzll(input_num);
8892
#endif  // ADA_REGULAR_VISUAL_STUDIO
8893
}
8894
8895
// Given a NEON register whose lanes are all either 0x00 or 0xFF (i.e., the
8896
// result of a comparison), produce a 64-bit value with four bits set per
8897
// matching input byte, and zero bits elsewhere. Narrowing by four bits per
8898
// 16-bit lane is cheaper than materializing a 16-bit bitmask, and it keeps
8899
// the value in a vector register so that the "any match?" test can be done
8900
// with a floating-point compare against zero, avoiding a transfer to a
8901
// general-purpose register on the common no-match path.
8902
//
8903
// The floating-point compare treats the nibble mask as an IEEE 754 double.
8904
// Negative zero cannot occur (each byte is 0x00, 0x0F, 0xF0 or 0xFF), but a
8905
// mask with only low bits set is a denormal: if flush-to-zero is enabled,
8906
// those compare equal to 0.0. Do not use this on arbitrary vectors.
8907
// Define ADA_NEON_SAFE_ZERO_CHECK to 1 to use an integer compare instead.
8908
ada_really_inline uint8x8_t to_nibble_mask(uint8x16_t comparison) noexcept {
8909
  return vshrn_n_u16(vreinterpretq_u16_u8(comparison), 4);
8910
}
8911
8912
ada_really_inline bool any_set(uint8x8_t nibble_mask) noexcept {
8913
#if ADA_NEON_SAFE_ZERO_CHECK
8914
  return vget_lane_u64(vreinterpret_u64_u8(nibble_mask), 0) != 0;
8915
#else
8916
  return vdupd_lane_f64(vreinterpret_f64_u8(nibble_mask), 0) != 0.0;
8917
#endif
8918
}
8919
8920
// index of the first matching byte; only meaningful when any_set is true.
8921
ada_really_inline size_t first_set(uint8x8_t nibble_mask) noexcept {
8922
  return size_t(trailing_zeroes64(
8923
             vget_lane_u64(vreinterpret_u64_u8(nibble_mask), 0))) >>
8924
         2;
8925
}
8926
#endif  // ADA_NEON
8927
8928
// starting at index location, this finds the next location of a character
8929
// :, /, \\, ? or [. If none is found, view.size() is returned.
8930
// For use within get_host_delimiter_location.
8931
#if ADA_SSSE3
8932
ada_really_inline size_t find_next_host_delimiter_special(
8933
    std::string_view view, size_t location) noexcept {
8934
  // first check for short strings in which case we do it naively.
8935
  if (view.size() - location < 16) {  // slow path
8936
    for (size_t i = location; i < view.size(); i++) {
8937
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
8938
          view[i] == '?' || view[i] == '[') {
8939
        return i;
8940
      }
8941
    }
8942
    return size_t(view.size());
8943
  }
8944
  // fast path for long strings (expected to be common)
8945
  // Using SSSE3's _mm_shuffle_epi8 for table lookup (same approach as NEON)
8946
  size_t i = location;
8947
  const __m128i low_mask =
8948
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8949
                    0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
8950
  const __m128i high_mask =
8951
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
8952
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
8953
  const __m128i fmask = _mm_set1_epi8(0xf);
8954
  const __m128i zero = _mm_setzero_si128();
8955
  for (; i + 15 < view.size(); i += 16) {
8956
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
8957
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
8958
    __m128i highpart = _mm_shuffle_epi8(
8959
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
8960
    __m128i classify = _mm_and_si128(lowpart, highpart);
8961
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
8962
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
8963
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
8964
    // avoid false positives.
8965
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
8966
    if (mask != 0) {
8967
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
8968
    }
8969
  }
8970
  if (i < view.size()) {
8971
    __m128i word =
8972
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
8973
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
8974
    __m128i highpart = _mm_shuffle_epi8(
8975
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
8976
    __m128i classify = _mm_and_si128(lowpart, highpart);
8977
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
8978
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
8979
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
8980
    // avoid false positives.
8981
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
8982
    if (mask != 0) {
8983
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
8984
    }
8985
  }
8986
  return size_t(view.size());
8987
}
8988
#elif ADA_NEON
8989
// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
8990
// support direct initialization of uint8x16_t. See
8991
// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
8992
#ifndef ada_make_uint8x16_t
8993
#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
8994
                            x13, x14, x15, x16)                                \
8995
  ([=]() {                                                                     \
8996
    static uint8_t array[16] = {x1, x2,  x3,  x4,  x5,  x6,  x7,  x8,          \
8997
                                x9, x10, x11, x12, x13, x14, x15, x16};        \
8998
    return vld1q_u8(array);                                                    \
8999
  }())
9000
#endif
9001
9002
ada_really_inline size_t find_next_host_delimiter_special(
9003
    std::string_view view, size_t location) noexcept {
9004
  // first check for short strings in which case we do it naively.
9005
  if (view.size() - location < 16) {  // slow path
9006
    for (size_t i = location; i < view.size(); i++) {
9007
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
9008
          view[i] == '?' || view[i] == '[') {
9009
        return i;
9010
      }
9011
    }
9012
    return size_t(view.size());
9013
  }
9014
  // fast path for long strings (expected to be common)
9015
  size_t i = location;
9016
  uint8x16_t low_mask =
9017
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9018
                          0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
9019
  uint8x16_t high_mask =
9020
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
9021
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
9022
  uint8x16_t fmask = vmovq_n_u8(0xf);
9023
  for (; i + 15 < view.size(); i += 16) {
9024
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
9025
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
9026
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
9027
    // vtstq_u8 gives us 0xFF where (lowpart & highpart) is non-zero and 0x00
9028
    // elsewhere: unlike the plain AND, that is a proper comparison mask, which
9029
    // is what to_nibble_mask requires.
9030
    uint8x8_t matches = to_nibble_mask(vtstq_u8(lowpart, highpart));
9031
    if (any_set(matches)) {
9032
      return i + first_set(matches);
9033
    }
9034
  }
9035
9036
  if (i < view.size()) {
9037
    uint8x16_t word =
9038
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
9039
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
9040
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
9041
    uint8x8_t matches = to_nibble_mask(vtstq_u8(lowpart, highpart));
9042
    if (any_set(matches)) {
9043
      return view.length() - 16 + first_set(matches);
9044
    }
9045
  }
9046
  return size_t(view.size());
9047
}
9048
#elif ADA_SSE2
9049
ada_really_inline size_t find_next_host_delimiter_special(
9050
738k
    std::string_view view, size_t location) noexcept {
9051
  // first check for short strings in which case we do it naively.
9052
738k
  if (view.size() - location < 16) {  // slow path
9053
1.42M
    for (size_t i = location; i < view.size(); i++) {
9054
927k
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
9055
782k
          view[i] == '?' || view[i] == '[') {
9056
165k
        return i;
9057
165k
      }
9058
927k
    }
9059
500k
    return size_t(view.size());
9060
666k
  }
9061
  // fast path for long strings (expected to be common)
9062
71.8k
  size_t i = location;
9063
71.8k
  const __m128i mask1 = _mm_set1_epi8(':');
9064
71.8k
  const __m128i mask2 = _mm_set1_epi8('/');
9065
71.8k
  const __m128i mask3 = _mm_set1_epi8('\\');
9066
71.8k
  const __m128i mask4 = _mm_set1_epi8('?');
9067
71.8k
  const __m128i mask5 = _mm_set1_epi8('[');
9068
9069
116k
  for (; i + 15 < view.size(); i += 16) {
9070
74.6k
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
9071
74.6k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
9072
74.6k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
9073
74.6k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
9074
74.6k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
9075
74.6k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
9076
74.6k
    __m128i m = _mm_or_si128(
9077
74.6k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
9078
74.6k
    int mask = _mm_movemask_epi8(m);
9079
74.6k
    if (mask != 0) {
9080
30.0k
      return i + trailing_zeroes(mask);
9081
30.0k
    }
9082
74.6k
  }
9083
41.8k
  if (i < view.size()) {
9084
41.3k
    __m128i word =
9085
41.3k
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
9086
41.3k
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
9087
41.3k
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
9088
41.3k
    __m128i m3 = _mm_cmpeq_epi8(word, mask3);
9089
41.3k
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
9090
41.3k
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
9091
41.3k
    __m128i m = _mm_or_si128(
9092
41.3k
        _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
9093
41.3k
    int mask = _mm_movemask_epi8(m);
9094
41.3k
    if (mask != 0) {
9095
39.9k
      return view.length() - 16 + trailing_zeroes(mask);
9096
39.9k
    }
9097
41.3k
  }
9098
1.88k
  return size_t(view.length());
9099
41.8k
}
9100
#elif ADA_LSX
9101
ada_really_inline size_t find_next_host_delimiter_special(
9102
    std::string_view view, size_t location) noexcept {
9103
  // first check for short strings in which case we do it naively.
9104
  if (view.size() - location < 16) {  // slow path
9105
    for (size_t i = location; i < view.size(); i++) {
9106
      if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
9107
          view[i] == '?' || view[i] == '[') {
9108
        return i;
9109
      }
9110
    }
9111
    return size_t(view.size());
9112
  }
9113
  // fast path for long strings (expected to be common)
9114
  size_t i = location;
9115
  const __m128i mask1 = __lsx_vrepli_b(':');
9116
  const __m128i mask2 = __lsx_vrepli_b('/');
9117
  const __m128i mask3 = __lsx_vrepli_b('\\');
9118
  const __m128i mask4 = __lsx_vrepli_b('?');
9119
  const __m128i mask5 = __lsx_vrepli_b('[');
9120
9121
  for (; i + 15 < view.size(); i += 16) {
9122
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
9123
    __m128i m1 = __lsx_vseq_b(word, mask1);
9124
    __m128i m2 = __lsx_vseq_b(word, mask2);
9125
    __m128i m3 = __lsx_vseq_b(word, mask3);
9126
    __m128i m4 = __lsx_vseq_b(word, mask4);
9127
    __m128i m5 = __lsx_vseq_b(word, mask5);
9128
    __m128i m =
9129
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
9130
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
9131
    if (mask != 0) {
9132
      return i + trailing_zeroes(mask);
9133
    }
9134
  }
9135
  if (i < view.size()) {
9136
    __m128i word =
9137
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
9138
    __m128i m1 = __lsx_vseq_b(word, mask1);
9139
    __m128i m2 = __lsx_vseq_b(word, mask2);
9140
    __m128i m3 = __lsx_vseq_b(word, mask3);
9141
    __m128i m4 = __lsx_vseq_b(word, mask4);
9142
    __m128i m5 = __lsx_vseq_b(word, mask5);
9143
    __m128i m =
9144
        __lsx_vor_v(__lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m3, m4)), m5);
9145
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
9146
    if (mask != 0) {
9147
      return view.length() - 16 + trailing_zeroes(mask);
9148
    }
9149
  }
9150
  return size_t(view.length());
9151
}
9152
#elif ADA_RVV
9153
ada_really_inline size_t find_next_host_delimiter_special(
9154
    std::string_view view, size_t location) noexcept {
9155
  // The LUT approach was a bit slower on the SpacemiT X60, but I could see it
9156
  // being faster on future hardware.
9157
#if 0
9158
  // LUT generated using: s=":/\\?["; list(zip([((ord(c)>>2)&0xF)for c in s],s))
9159
  static const uint8_t tbl[16] = {
9160
    0xF, 0, 0, 0, 0, 0, '[', '\\', 0, 0, 0, '/', 0, 0, ':', '?'
9161
  };
9162
  vuint8m1_t vtbl = __riscv_vle8_v_u8m1(tbl, 16);
9163
#endif
9164
  uint8_t* src = (uint8_t*)view.data() + location;
9165
  for (size_t vl, n = view.size() - location; n > 0;
9166
       n -= vl, src += vl, location += vl) {
9167
    vl = __riscv_vsetvl_e8m1(n);
9168
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
9169
#if 0
9170
    vuint8m1_t vidx = __riscv_vand(__riscv_vsrl(v, 2, vl), 0xF, vl);
9171
    vuint8m1_t vlut = __riscv_vrgather(vtbl, vidx, vl);
9172
    vbool8_t m = __riscv_vmseq(v, vlut, vl);
9173
#else
9174
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
9175
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
9176
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
9177
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
9178
    vbool8_t m5 = __riscv_vmseq(v, '\\', vl);
9179
    vbool8_t m = __riscv_vmor(
9180
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl),
9181
        m5, vl);
9182
#endif
9183
    long idx = __riscv_vfirst(m, vl);
9184
    if (idx >= 0) return location + idx;
9185
  }
9186
  return size_t(view.size());
9187
}
9188
#else
9189
// : / [ \\ ?
9190
static constexpr std::array<uint8_t, 256> special_host_delimiters =
9191
    []() consteval {
9192
      std::array<uint8_t, 256> result{};
9193
      for (int i : {':', '/', '[', '\\', '?'}) {
9194
        result[i] = 1;
9195
      }
9196
      return result;
9197
    }();
9198
// credit: @the-moisrex recommended a table-based approach
9199
ada_really_inline size_t find_next_host_delimiter_special(
9200
    std::string_view view, size_t location) noexcept {
9201
  auto const str = view.substr(location);
9202
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
9203
    if (special_host_delimiters[(uint8_t)*pos]) {
9204
      return pos - str.begin() + location;
9205
    }
9206
  }
9207
  return size_t(view.size());
9208
}
9209
#endif
9210
9211
// starting at index location, this finds the next location of a character
9212
// :, /, ? or [. If none is found, view.size() is returned.
9213
// For use within get_host_delimiter_location.
9214
#if ADA_SSSE3
9215
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9216
                                                  size_t location) noexcept {
9217
  // first check for short strings in which case we do it naively.
9218
  if (view.size() - location < 16) {  // slow path
9219
    for (size_t i = location; i < view.size(); i++) {
9220
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
9221
          view[i] == '[') {
9222
        return i;
9223
      }
9224
    }
9225
    return size_t(view.size());
9226
  }
9227
  // fast path for long strings (expected to be common)
9228
  size_t i = location;
9229
  // Lookup tables for bit classification:
9230
  // ':' (0x3A): low[0xA]=0x01, high[0x3]=0x01 -> match
9231
  // '/' (0x2F): low[0xF]=0x02, high[0x2]=0x02 -> match
9232
  // '?' (0x3F): low[0xF]=0x01, high[0x3]=0x01 -> match
9233
  // '[' (0x5B): low[0xB]=0x04, high[0x5]=0x04 -> match
9234
  const __m128i low_mask =
9235
      _mm_setr_epi8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9236
                    0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
9237
  const __m128i high_mask =
9238
      _mm_setr_epi8(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
9239
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
9240
  const __m128i fmask = _mm_set1_epi8(0xf);
9241
  const __m128i zero = _mm_setzero_si128();
9242
9243
  for (; i + 15 < view.size(); i += 16) {
9244
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
9245
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
9246
    __m128i highpart = _mm_shuffle_epi8(
9247
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
9248
    __m128i classify = _mm_and_si128(lowpart, highpart);
9249
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
9250
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
9251
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
9252
    // avoid false positives.
9253
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
9254
    if (mask != 0) {
9255
      return i + trailing_zeroes(static_cast<uint32_t>(mask));
9256
    }
9257
  }
9258
9259
  if (i < view.size()) {
9260
    __m128i word =
9261
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
9262
    __m128i lowpart = _mm_shuffle_epi8(low_mask, _mm_and_si128(word, fmask));
9263
    __m128i highpart = _mm_shuffle_epi8(
9264
        high_mask, _mm_and_si128(_mm_srli_epi16(word, 4), fmask));
9265
    __m128i classify = _mm_and_si128(lowpart, highpart);
9266
    __m128i is_zero = _mm_cmpeq_epi8(classify, zero);
9267
    // _mm_movemask_epi8 returns a 16-bit mask in bits 0-15, with bits 16-31
9268
    // zero. After NOT (~), bits 16-31 become 1. We must mask to 16 bits to
9269
    // avoid false positives.
9270
    int mask = ~_mm_movemask_epi8(is_zero) & 0xFFFF;
9271
    if (mask != 0) {
9272
      return view.length() - 16 + trailing_zeroes(static_cast<uint32_t>(mask));
9273
    }
9274
  }
9275
  return size_t(view.size());
9276
}
9277
#elif ADA_NEON
9278
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9279
                                                  size_t location) noexcept {
9280
  // first check for short strings in which case we do it naively.
9281
  if (view.size() - location < 16) {  // slow path
9282
    for (size_t i = location; i < view.size(); i++) {
9283
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
9284
          view[i] == '[') {
9285
        return i;
9286
      }
9287
    }
9288
    return size_t(view.size());
9289
  }
9290
  // fast path for long strings (expected to be common)
9291
  size_t i = location;
9292
  uint8x16_t low_mask =
9293
      ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9294
                          0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
9295
  uint8x16_t high_mask =
9296
      ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
9297
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
9298
  uint8x16_t fmask = vmovq_n_u8(0xf);
9299
  for (; i + 15 < view.size(); i += 16) {
9300
    uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
9301
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
9302
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
9303
    // vtstq_u8 gives us 0xFF where (lowpart & highpart) is non-zero and 0x00
9304
    // elsewhere: unlike the plain AND, that is a proper comparison mask, which
9305
    // is what to_nibble_mask requires.
9306
    uint8x8_t matches = to_nibble_mask(vtstq_u8(lowpart, highpart));
9307
    if (any_set(matches)) {
9308
      return i + first_set(matches);
9309
    }
9310
  }
9311
9312
  if (i < view.size()) {
9313
    uint8x16_t word =
9314
        vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
9315
    uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
9316
    uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
9317
    uint8x8_t matches = to_nibble_mask(vtstq_u8(lowpart, highpart));
9318
    if (any_set(matches)) {
9319
      return view.length() - 16 + first_set(matches);
9320
    }
9321
  }
9322
  return size_t(view.size());
9323
}
9324
#elif ADA_SSE2
9325
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9326
721
                                                  size_t location) noexcept {
9327
  // first check for short strings in which case we do it naively.
9328
721
  if (view.size() - location < 16) {  // slow path
9329
1.49k
    for (size_t i = location; i < view.size(); i++) {
9330
1.20k
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
9331
1.01k
          view[i] == '[') {
9332
336
        return i;
9333
336
      }
9334
1.20k
    }
9335
292
    return size_t(view.size());
9336
628
  }
9337
  // fast path for long strings (expected to be common)
9338
93
  size_t i = location;
9339
93
  const __m128i mask1 = _mm_set1_epi8(':');
9340
93
  const __m128i mask2 = _mm_set1_epi8('/');
9341
93
  const __m128i mask4 = _mm_set1_epi8('?');
9342
93
  const __m128i mask5 = _mm_set1_epi8('[');
9343
9344
120
  for (; i + 15 < view.size(); i += 16) {
9345
93
    __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
9346
93
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
9347
93
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
9348
93
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
9349
93
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
9350
93
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
9351
93
    int mask = _mm_movemask_epi8(m);
9352
93
    if (mask != 0) {
9353
66
      return i + trailing_zeroes(mask);
9354
66
    }
9355
93
  }
9356
27
  if (i < view.size()) {
9357
17
    __m128i word =
9358
17
        _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
9359
17
    __m128i m1 = _mm_cmpeq_epi8(word, mask1);
9360
17
    __m128i m2 = _mm_cmpeq_epi8(word, mask2);
9361
17
    __m128i m4 = _mm_cmpeq_epi8(word, mask4);
9362
17
    __m128i m5 = _mm_cmpeq_epi8(word, mask5);
9363
17
    __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
9364
17
    int mask = _mm_movemask_epi8(m);
9365
17
    if (mask != 0) {
9366
6
      return view.length() - 16 + trailing_zeroes(mask);
9367
6
    }
9368
17
  }
9369
21
  return size_t(view.length());
9370
27
}
9371
#elif ADA_LSX
9372
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9373
                                                  size_t location) noexcept {
9374
  // first check for short strings in which case we do it naively.
9375
  if (view.size() - location < 16) {  // slow path
9376
    for (size_t i = location; i < view.size(); i++) {
9377
      if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
9378
          view[i] == '[') {
9379
        return i;
9380
      }
9381
    }
9382
    return size_t(view.size());
9383
  }
9384
  // fast path for long strings (expected to be common)
9385
  size_t i = location;
9386
  const __m128i mask1 = __lsx_vrepli_b(':');
9387
  const __m128i mask2 = __lsx_vrepli_b('/');
9388
  const __m128i mask4 = __lsx_vrepli_b('?');
9389
  const __m128i mask5 = __lsx_vrepli_b('[');
9390
9391
  for (; i + 15 < view.size(); i += 16) {
9392
    __m128i word = __lsx_vld((const __m128i*)(view.data() + i), 0);
9393
    __m128i m1 = __lsx_vseq_b(word, mask1);
9394
    __m128i m2 = __lsx_vseq_b(word, mask2);
9395
    __m128i m4 = __lsx_vseq_b(word, mask4);
9396
    __m128i m5 = __lsx_vseq_b(word, mask5);
9397
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
9398
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
9399
    if (mask != 0) {
9400
      return i + trailing_zeroes(mask);
9401
    }
9402
  }
9403
  if (i < view.size()) {
9404
    __m128i word =
9405
        __lsx_vld((const __m128i*)(view.data() + view.length() - 16), 0);
9406
    __m128i m1 = __lsx_vseq_b(word, mask1);
9407
    __m128i m2 = __lsx_vseq_b(word, mask2);
9408
    __m128i m4 = __lsx_vseq_b(word, mask4);
9409
    __m128i m5 = __lsx_vseq_b(word, mask5);
9410
    __m128i m = __lsx_vor_v(__lsx_vor_v(m1, m2), __lsx_vor_v(m4, m5));
9411
    int mask = __lsx_vpickve2gr_hu(__lsx_vmsknz_b(m), 0);
9412
    if (mask != 0) {
9413
      return view.length() - 16 + trailing_zeroes(mask);
9414
    }
9415
  }
9416
  return size_t(view.length());
9417
}
9418
#elif ADA_RVV
9419
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9420
                                                  size_t location) noexcept {
9421
  uint8_t* src = (uint8_t*)view.data() + location;
9422
  for (size_t vl, n = view.size() - location; n > 0;
9423
       n -= vl, src += vl, location += vl) {
9424
    vl = __riscv_vsetvl_e8m1(n);
9425
    vuint8m1_t v = __riscv_vle8_v_u8m1(src, vl);
9426
    vbool8_t m1 = __riscv_vmseq(v, ':', vl);
9427
    vbool8_t m2 = __riscv_vmseq(v, '/', vl);
9428
    vbool8_t m3 = __riscv_vmseq(v, '?', vl);
9429
    vbool8_t m4 = __riscv_vmseq(v, '[', vl);
9430
    vbool8_t m =
9431
        __riscv_vmor(__riscv_vmor(m1, m2, vl), __riscv_vmor(m3, m4, vl), vl);
9432
    long idx = __riscv_vfirst(m, vl);
9433
    if (idx >= 0) return location + idx;
9434
  }
9435
  return size_t(view.size());
9436
}
9437
#else
9438
// : / [ ?
9439
static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
9440
  std::array<uint8_t, 256> result{};
9441
  for (int i : {':', '/', '?', '['}) {
9442
    result[i] = 1;
9443
  }
9444
  return result;
9445
}();
9446
// credit: @the-moisrex recommended a table-based approach
9447
ada_really_inline size_t find_next_host_delimiter(std::string_view view,
9448
                                                  size_t location) noexcept {
9449
  auto const str = view.substr(location);
9450
  for (auto pos = str.begin(); pos != str.end(); ++pos) {
9451
    if (host_delimiters[(uint8_t)*pos]) {
9452
      return pos - str.begin() + location;
9453
    }
9454
  }
9455
  return size_t(view.size());
9456
}
9457
#endif
9458
9459
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
9460
725k
    const bool is_special, std::string_view& view) noexcept {
9461
  /**
9462
   * The spec at https://url.spec.whatwg.org/#hostname-state expects us to
9463
   * compute a variable called insideBrackets but this variable is only used
9464
   * once, to check whether a ':' character was found outside brackets. Exact
9465
   * text: "Otherwise, if c is U+003A (:) and insideBrackets is false, then:".
9466
   * It is conceptually simpler and arguably more efficient to just return a
9467
   * Boolean indicating whether ':' was found outside brackets.
9468
   */
9469
725k
  const size_t view_size = view.size();
9470
725k
  size_t location = 0;
9471
725k
  bool found_colon = false;
9472
  /**
9473
   * Performance analysis:
9474
   *
9475
   * We are basically seeking the end of the hostname which can be indicated
9476
   * by the end of the view, or by one of the characters ':', '/', '?', '\\'
9477
   * (where '\\' is only applicable for special URLs). However, these must
9478
   * appear outside a bracket range. E.g., if you have [something?]fd: then the
9479
   * '?' does not count.
9480
   *
9481
   * So we can skip ahead to the next delimiter, as long as we include '[' in
9482
   * the set of delimiters, and that we handle it first.
9483
   *
9484
   * So the trick is to have a fast function that locates the next delimiter.
9485
   * Unless we find '[', then it only needs to be called once! Ideally, such a
9486
   * function would be provided by the C++ standard library, but it seems that
9487
   * find_first_of is not very fast, so we are forced to roll our own.
9488
   *
9489
   * We do not break into two loops for speed, but for clarity.
9490
   */
9491
725k
  if (is_special) {
9492
    // We move to the next delimiter.
9493
724k
    location = find_next_host_delimiter_special(view, location);
9494
    // Unless we find '[' then we are going only going to have to call
9495
    // find_next_host_delimiter_special once.
9496
738k
    for (; location < view_size;
9497
724k
         location = find_next_host_delimiter_special(view, location)) {
9498
235k
      if (view[location] == '[') {
9499
23.3k
        location = view.find(']', location);
9500
23.3k
        if (location == std::string_view::npos) {
9501
          // performance: view.find might get translated to a memchr, which
9502
          // has no notion of std::string_view::npos, so the code does not
9503
          // reflect the assembly.
9504
9.97k
          location = view_size;
9505
9.97k
          break;
9506
9.97k
        }
9507
212k
      } else {
9508
212k
        found_colon = view[location] == ':';
9509
212k
        break;
9510
212k
      }
9511
235k
    }
9512
724k
  } else {
9513
    // We move to the next delimiter.
9514
544
    location = find_next_host_delimiter(view, location);
9515
    // Unless we find '[' then we are going only going to have to call
9516
    // find_next_host_delimiter_special once.
9517
721
    for (; location < view_size;
9518
544
         location = find_next_host_delimiter(view, location)) {
9519
408
      if (view[location] == '[') {
9520
206
        location = view.find(']', location);
9521
206
        if (location == std::string_view::npos) {
9522
          // performance: view.find might get translated to a memchr, which
9523
          // has no notion of std::string_view::npos, so the code does not
9524
          // reflect the assembly.
9525
29
          location = view_size;
9526
29
          break;
9527
29
        }
9528
206
      } else {
9529
202
        found_colon = view[location] == ':';
9530
202
        break;
9531
202
      }
9532
408
    }
9533
544
  }
9534
  // performance: remove_suffix may translate into a single instruction.
9535
725k
  view.remove_suffix(view_size - location);
9536
725k
  return {location, found_colon};
9537
725k
}
9538
9539
781k
void trim_c0_whitespace(std::string_view& input) noexcept {
9540
781k
  while (!input.empty() &&
9541
781k
         ada::unicode::is_c0_control_or_space(input.front())) {
9542
0
    input.remove_prefix(1);
9543
0
  }
9544
798k
  while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
9545
17.1k
    input.remove_suffix(1);
9546
17.1k
  }
9547
781k
}
9548
9549
ada_really_inline void parse_prepared_path(std::string_view input,
9550
                                           ada::scheme::type type,
9551
0
                                           std::string& path) {
9552
0
  ada_log("parse_prepared_path ", input);
9553
0
  uint8_t accumulator = checkers::path_signature(input);
9554
  // Let us first detect a trivial case.
9555
  // If it is special, we check that we have no dot, no %,  no \ and no
9556
  // character needing percent encoding. Otherwise, we check that we have no %,
9557
  // no dot, and no character needing percent encoding.
9558
0
  constexpr uint8_t need_encoding = 1;
9559
0
  constexpr uint8_t backslash_char = 2;
9560
0
  constexpr uint8_t dot_char = 4;
9561
0
  constexpr uint8_t percent_char = 8;
9562
0
  bool special = type != ada::scheme::NOT_SPECIAL;
9563
0
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
9564
0
                                      checkers::is_windows_drive_letter(input));
9565
0
  bool trivial_path =
9566
0
      (special ? (accumulator == 0)
9567
0
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
9568
0
                  0)) &&
9569
0
      (!may_need_slow_file_handling);
9570
0
  if (accumulator == dot_char && !may_need_slow_file_handling) {
9571
    // '4' means that we have at least one dot, but nothing that requires
9572
    // percent encoding or decoding. The only part that is not trivial is
9573
    // that we may have single dots and double dots path segments.
9574
    // If we have such segments, then we either have a path that begins
9575
    // with '.' (easy to check), or we have the sequence './'.
9576
    // Note: input cannot be empty, it must at least contain one character ('.')
9577
    // Note: we know that '\' is not present.
9578
0
    if (input[0] != '.') {
9579
0
      size_t slashdot = 0;
9580
0
      bool dot_is_file = true;
9581
0
      for (;;) {
9582
0
        slashdot = input.find("/.", slashdot);
9583
0
        if (slashdot == std::string_view::npos) {  // common case
9584
0
          break;
9585
0
        } else {  // uncommon
9586
          // only three cases matter: /./, /.. or a final /
9587
0
          slashdot += 2;
9588
0
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
9589
0
                           input[slashdot] == '/');
9590
0
        }
9591
0
      }
9592
0
      trivial_path = dot_is_file;
9593
0
    }
9594
0
  }
9595
0
  if (trivial_path) {
9596
0
    ada_log("parse_path trivial");
9597
0
    path += '/';
9598
0
    path += input;
9599
0
    return;
9600
0
  }
9601
  // We are going to need to look a bit at the path, but let us see if we can
9602
  // ignore percent encoding *and* backslashes *and* percent characters.
9603
  // Except for the trivial case, this is likely to capture 99% of paths out
9604
  // there.
9605
0
  bool fast_path =
9606
0
      (special &&
9607
0
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
9608
0
      (type != ada::scheme::type::FILE);
9609
0
  if (fast_path) {
9610
0
    ada_log("parse_prepared_path fast");
9611
    // Here we don't need to worry about \ or percent encoding.
9612
    // We also do not have a file protocol. We might have dots, however,
9613
    // but dots must as appear as '.', and they cannot be encoded because
9614
    // the symbol '%' is not present.
9615
0
    size_t previous_location = 0;  // We start at 0.
9616
0
    do {
9617
0
      size_t new_location = input.find('/', previous_location);
9618
      // std::string_view path_view = input;
9619
      //  We process the last segment separately:
9620
0
      if (new_location == std::string_view::npos) {
9621
0
        std::string_view path_view = input.substr(previous_location);
9622
0
        if (path_view == "..") {  // The path ends with ..
9623
          // e.g., if you receive ".." with an empty path, you go to "/".
9624
0
          if (path.empty()) {
9625
0
            path = '/';
9626
0
            return;
9627
0
          }
9628
          // Fast case where we have nothing to do:
9629
0
          if (path.back() == '/') {
9630
0
            return;
9631
0
          }
9632
          // If you have the path "/joe/myfriend",
9633
          // then you delete 'myfriend'.
9634
0
          path.resize(path.rfind('/') + 1);
9635
0
          return;
9636
0
        }
9637
0
        path += '/';
9638
0
        if (path_view != ".") {
9639
0
          path.append(path_view);
9640
0
        }
9641
0
        return;
9642
0
      } else {
9643
        // This is a non-final segment.
9644
0
        std::string_view path_view =
9645
0
            input.substr(previous_location, new_location - previous_location);
9646
0
        previous_location = new_location + 1;
9647
0
        if (path_view == "..") {
9648
0
          size_t last_delimiter = path.rfind('/');
9649
0
          if (last_delimiter != std::string::npos) {
9650
0
            path.erase(last_delimiter);
9651
0
          }
9652
0
        } else if (path_view != ".") {
9653
0
          path += '/';
9654
0
          path.append(path_view);
9655
0
        }
9656
0
      }
9657
0
    } while (true);
9658
0
  } else {
9659
0
    ada_log("parse_path slow");
9660
    // we have reached the general case
9661
0
    bool needs_percent_encoding = (accumulator & 1);
9662
0
    std::string path_buffer_tmp;
9663
0
    do {
9664
0
      size_t location = (special && (accumulator & 2))
9665
0
                            ? input.find_first_of("/\\")
9666
0
                            : input.find('/');
9667
0
      std::string_view path_view = input;
9668
0
      if (location != std::string_view::npos) {
9669
0
        path_view.remove_suffix(path_view.size() - location);
9670
0
        input.remove_prefix(location + 1);
9671
0
      }
9672
      // path_buffer is either path_view or it might point at a percent encoded
9673
      // temporary file.
9674
0
      std::string_view path_buffer =
9675
0
          (needs_percent_encoding &&
9676
0
           ada::unicode::percent_encode<false>(
9677
0
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
9678
0
              ? path_buffer_tmp
9679
0
              : path_view;
9680
0
      if (unicode::is_double_dot_path_segment(path_buffer)) {
9681
0
        helpers::shorten_path(path, type);
9682
0
        if (location == std::string_view::npos) {
9683
0
          path += '/';
9684
0
        }
9685
0
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
9686
0
                 (location == std::string_view::npos)) {
9687
0
        path += '/';
9688
0
      }
9689
      // Otherwise, if path_buffer is not a single-dot path segment, then:
9690
0
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
9691
        // If url's scheme is "file", url's path is empty, and path_buffer is a
9692
        // Windows drive letter, then replace the second code point in
9693
        // path_buffer with U+003A (:).
9694
0
        if (type == ada::scheme::type::FILE && path.empty() &&
9695
0
            checkers::is_windows_drive_letter(path_buffer)) {
9696
0
          path += '/';
9697
0
          path += path_buffer[0];
9698
0
          path += ':';
9699
0
          path_buffer.remove_prefix(2);
9700
0
          path.append(path_buffer);
9701
0
        } else {
9702
          // Append path_buffer to url's path.
9703
0
          path += '/';
9704
0
          path.append(path_buffer);
9705
0
        }
9706
0
      }
9707
0
      if (location == std::string_view::npos) {
9708
0
        return;
9709
0
      }
9710
0
    } while (true);
9711
0
  }
9712
0
}
9713
9714
95
bool overlaps(std::string_view input1, const std::string& input2) noexcept {
9715
95
  ada_log("helpers::overlaps check if string_view '", input1, "' [",
9716
95
          input1.size(), " bytes] is part of string '", input2, "' [",
9717
95
          input2.size(), " bytes]");
9718
95
  return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
9719
85
         input1.data() < input2.data() + input2.size();
9720
95
}
9721
9722
template <class url_type>
9723
0
ada_really_inline void strip_trailing_spaces_from_opaque_path(url_type& url) {
9724
0
  ada_log("helpers::strip_trailing_spaces_from_opaque_path");
9725
0
  if (!url.has_opaque_path) return;
9726
0
  if (url.has_hash()) return;
9727
0
  if (url.has_search()) return;
9728
9729
0
  auto path = std::string(url.get_pathname());
9730
0
  while (!path.empty() && path.back() == ' ') {
9731
0
    path.resize(path.size() - 1);
9732
0
  }
9733
0
  url.update_base_pathname(path);
9734
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&)
9735
9736
// @ / \\ ?
9737
static constexpr std::array<uint8_t, 256> authority_delimiter_special =
9738
    []() consteval {
9739
      std::array<uint8_t, 256> result{};
9740
      for (uint8_t i : {'@', '/', '\\', '?'}) {
9741
        result[i] = 1;
9742
      }
9743
      return result;
9744
    }();
9745
// credit: @the-moisrex recommended a table-based approach
9746
ada_really_inline size_t
9747
80.5k
find_authority_delimiter_special(std::string_view view) noexcept {
9748
  // performance note: we might be able to gain further performance
9749
  // with SIMD intrinsics.
9750
241k
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
9751
238k
    if (authority_delimiter_special[(uint8_t)*pos]) {
9752
77.5k
      return pos - view.begin();
9753
77.5k
    }
9754
238k
  }
9755
3.03k
  return size_t(view.size());
9756
80.5k
}
9757
9758
// @ / ?
9759
static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
9760
  std::array<uint8_t, 256> result{};
9761
  for (uint8_t i : {'@', '/', '?'}) {
9762
    result[i] = 1;
9763
  }
9764
  return result;
9765
}();
9766
// credit: @the-moisrex recommended a table-based approach
9767
ada_really_inline size_t
9768
388
find_authority_delimiter(std::string_view view) noexcept {
9769
  // performance note: we might be able to gain further performance
9770
  // with SIMD instrinsics.
9771
803
  for (auto pos = view.begin(); pos != view.end(); ++pos) {
9772
693
    if (authority_delimiter[(uint8_t)*pos]) {
9773
278
      return pos - view.begin();
9774
278
    }
9775
693
  }
9776
110
  return size_t(view.size());
9777
388
}
9778
9779
}  // namespace ada::helpers
9780
9781
namespace ada {
9782
0
ada_warn_unused std::string to_string(ada::state state) {
9783
0
  return ada::helpers::get_state(state);
9784
0
}
9785
#undef ada_make_uint8x16_t
9786
}  // namespace ada
9787
/* end file src/helpers.cpp */
9788
/* begin file src/url.cpp */
9789
/* begin file include/ada/url_ip-inl.h */
9790
/**
9791
 * @file url_ip-inl.h
9792
 * @brief Shared IPv4/IPv6 parsing helpers used by url and url_aggregator.
9793
 *
9794
 * Not part of the public API. Defined inline so the single-TU amalgamation
9795
 * (ada.cpp) can include them from multiple translation-unit sources once.
9796
 */
9797
#ifndef ADA_URL_IP_INL_H
9798
#define ADA_URL_IP_INL_H
9799
9800
9801
#include <array>
9802
#include <cstddef>
9803
#include <cstdint>
9804
9805
// The IPv6 kernel needs vpermi2b/vpermb (VBMI) and vpcompressb/vpexpandb
9806
// (VBMI2) on top of ADA_AVX512's BW+VL.
9807
#if defined(ADA_AVX512) && defined(__AVX512VBMI__) && defined(__AVX512VBMI2__)
9808
#define ADA_AVX512_IPV6 1
9809
#endif
9810
9811
#if defined(ADA_AVX512)
9812
#include <immintrin.h>
9813
#endif
9814
9815
namespace ada::detail {
9816
9817
// 256-entry: 0xff = not hex, else nibble value.
9818
0
inline constexpr std::array<uint8_t, 256> make_hex_nibble_table() noexcept {
9819
0
  std::array<uint8_t, 256> t{};
9820
0
  for (size_t i = 0; i < 256; ++i) {
9821
0
    t[i] = 0xff;
9822
0
  }
9823
0
  for (size_t d = 0; d < 10; ++d) {
9824
0
    t[size_t{'0'} + d] = static_cast<uint8_t>(d);
9825
0
  }
9826
0
  for (size_t d = 0; d < 6; ++d) {
9827
0
    t[size_t{'a'} + d] = static_cast<uint8_t>(10 + d);
9828
0
    t[size_t{'A'} + d] = static_cast<uint8_t>(10 + d);
9829
0
  }
9830
0
  return t;
9831
0
}
9832
9833
inline constexpr auto hex_nibble = make_hex_nibble_table();
9834
9835
inline bool parse_ipv4_number(const char*& p, const char* end, uint64_t& value,
9836
53.9k
                              bool& is_pure_decimal) noexcept {
9837
53.9k
  is_pure_decimal = false;
9838
53.9k
  if (p >= end) [[unlikely]] {
9839
0
    return false;
9840
0
  }
9841
53.9k
  if (end - p >= 2 && p[0] == '0' && ((p[1] | 0x20) == 'x')) {
9842
9.82k
    p += 2;
9843
9.82k
    if (p == end || *p == '.') {
9844
1.10k
      value = 0;
9845
1.10k
      return true;
9846
1.10k
    }
9847
8.72k
    uint64_t v = 0;
9848
8.72k
    int digits = 0;
9849
56.6k
    while (p < end && *p != '.') {
9850
50.1k
      const uint8_t nib = hex_nibble[static_cast<unsigned char>(*p)];
9851
50.1k
      if (nib == 0xff) [[unlikely]] {
9852
125
        return false;
9853
125
      }
9854
49.9k
      if (v > (0xFFFFFFFFULL >> 4)) [[unlikely]] {
9855
2.06k
        return false;
9856
2.06k
      }
9857
47.9k
      v = (v << 4) | nib;
9858
47.9k
      ++p;
9859
47.9k
      ++digits;
9860
47.9k
    }
9861
6.52k
    if (digits == 0) [[unlikely]] {
9862
0
      return false;
9863
0
    }
9864
6.52k
    value = v;
9865
6.52k
    return true;
9866
6.52k
  }
9867
44.1k
  if (end - p >= 2 && p[0] == '0' && p[1] >= '0' && p[1] <= '9') {
9868
3.48k
    ++p;
9869
3.48k
    uint64_t v = 0;
9870
22.0k
    while (p < end && *p != '.') {
9871
19.5k
      const char c = *p;
9872
19.5k
      if (c < '0' || c > '7') [[unlikely]] {
9873
787
        return false;
9874
787
      }
9875
18.7k
      if (v > (0xFFFFFFFFULL >> 3)) [[unlikely]] {
9876
199
        return false;
9877
199
      }
9878
18.5k
      v = (v << 3) | static_cast<uint64_t>(c - '0');
9879
18.5k
      ++p;
9880
18.5k
    }
9881
2.50k
    value = v;
9882
2.50k
    return true;
9883
3.48k
  }
9884
40.6k
  if (*p < '0' || *p > '9') [[unlikely]] {
9885
5.50k
    return false;
9886
5.50k
  }
9887
35.1k
  is_pure_decimal = true;
9888
35.1k
  uint64_t v = static_cast<uint64_t>(*p - '0');
9889
35.1k
  ++p;
9890
79.0k
  while (p < end && *p != '.') {
9891
46.5k
    const char c = *p;
9892
46.5k
    if (c < '0' || c > '9') [[unlikely]] {
9893
1.48k
      return false;
9894
1.48k
    }
9895
45.0k
    if (v > 429496729ULL) [[unlikely]] {
9896
890
      return false;
9897
890
    }
9898
44.1k
    v = v * 10u + static_cast<uint64_t>(c - '0');
9899
44.1k
    if (v > 0xFFFFFFFFULL) [[unlikely]] {
9900
252
      return false;
9901
252
    }
9902
43.9k
    ++p;
9903
43.9k
  }
9904
32.5k
  value = v;
9905
32.5k
  return true;
9906
35.1k
}
9907
9908
// Parse up to 4 hex digits. Returns digit count (0 if none).
9909
inline int parse_hex_piece(const char*& pointer, const char* end,
9910
16.1k
                           uint16_t& value) noexcept {
9911
16.1k
  if (pointer == end) {
9912
0
    return 0;
9913
0
  }
9914
16.1k
  const uint8_t n0 = hex_nibble[static_cast<unsigned char>(*pointer)];
9915
16.1k
  if (n0 == 0xff) {
9916
861
    return 0;
9917
861
  }
9918
15.2k
  uint32_t v = n0;
9919
15.2k
  ++pointer;
9920
15.2k
  int length = 1;
9921
15.2k
  if (pointer != end) {
9922
13.9k
    const uint8_t n1 = hex_nibble[static_cast<unsigned char>(*pointer)];
9923
13.9k
    if (n1 != 0xff) {
9924
5.56k
      v = (v << 4) | n1;
9925
5.56k
      ++pointer;
9926
5.56k
      ++length;
9927
5.56k
      if (pointer != end) {
9928
4.98k
        const uint8_t n2 = hex_nibble[static_cast<unsigned char>(*pointer)];
9929
4.98k
        if (n2 != 0xff) {
9930
3.55k
          v = (v << 4) | n2;
9931
3.55k
          ++pointer;
9932
3.55k
          ++length;
9933
3.55k
          if (pointer != end) {
9934
2.91k
            const uint8_t n3 = hex_nibble[static_cast<unsigned char>(*pointer)];
9935
2.91k
            if (n3 != 0xff) {
9936
1.13k
              v = (v << 4) | n3;
9937
1.13k
              ++pointer;
9938
1.13k
              ++length;
9939
1.13k
            }
9940
2.91k
          }
9941
3.55k
        }
9942
4.98k
      }
9943
5.56k
    }
9944
13.9k
  }
9945
15.2k
  value = static_cast<uint16_t>(v);
9946
15.2k
  return length;
9947
16.1k
}
9948
9949
#if defined(ADA_AVX512_IPV6)
9950
// Gather each group's up-to-four nibbles and fold them into eight hextets.
9951
// `prev` is the byte before each group, so an index that runs off the front of
9952
// a short group clamps onto a colon, which translates to zero: no write mask.
9953
ada_really_inline void ipv6_gather(__m128i ends, __m128i prev, __m512i nib,
9954
                                   std::array<uint16_t, 8>& address) noexcept {
9955
  const __m256i grp =
9956
      _mm256_setr_epi8(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
9957
                       4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7);
9958
  const __m256i off = _mm256_setr_epi8(
9959
      -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, -3,
9960
      -2, -1, -4, -3, -2, -1, -4, -3, -2, -1, -4, -3, -2, -1);
9961
  const __m256i idx = _mm256_max_epi8(
9962
      _mm256_add_epi8(
9963
          _mm256_permutexvar_epi8(grp, _mm256_castsi128_si256(ends)), off),
9964
      _mm256_permutexvar_epi8(grp, _mm256_castsi128_si256(prev)));
9965
  const __m256i gathered = _mm512_castsi512_si256(
9966
      _mm512_permutexvar_epi8(_mm512_castsi256_si512(idx), nib));
9967
  // (a,b) -> 16a+b are the sixteen address bytes; 256*hi+lo pairs them.
9968
  const __m256i hextets = _mm256_madd_epi16(
9969
      _mm256_maddubs_epi16(gathered, _mm256_set1_epi16(0x0110)),
9970
      _mm256_set1_epi32(0x00010100));
9971
  _mm_storeu_si128(reinterpret_cast<__m128i*>(address.data()),
9972
                   _mm256_cvtepi32_epi16(hextets));
9973
}
9974
9975
// Parse an IPv6 host with one masked 512-bit load. Derived from
9976
// vtlmks/ipv6-avx512 (Peter Fors, MIT).
9977
//
9978
// Returns false when the input is outside this kernel's grammar and the caller
9979
// must run the scalar parser. Otherwise `valid` receives the verdict, and
9980
// `address` the eight hextets when valid.
9981
ada_really_inline bool try_parse_ipv6_avx512(const char* data, size_t len,
9982
                                             std::array<uint16_t, 8>& address,
9983
                                             bool& valid) noexcept {
9984
  if (len < 2 || len > 45) [[unlikely]] {
9985
    return false;
9986
  }
9987
  // ':' rather than 0x80 for the colon, so a clamped index reads a zero nibble.
9988
  alignas(64) static constexpr uint8_t hex_lo[64] = {
9989
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9990
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9991
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9992
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9993
      0x80, 0x80, 0x80, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
9994
      0x07, 0x08, 0x09, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80};
9995
  alignas(64) static constexpr uint8_t hex_hi[64] = {
9996
      0x80, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x80, 0x80, 0x80, 0x80,
9997
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9998
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
9999
      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x80, 0x80, 0x80, 0x80, 0x80,
10000
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
10001
      0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
10002
  alignas(64) static constexpr uint8_t iota[64] = {
10003
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
10004
      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
10005
      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
10006
      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
10007
10008
  const __mmask64 active =
10009
      static_cast<__mmask64>(_bzhi_u64(~0ULL, static_cast<uint32_t>(len)));
10010
  const __m512i colon = _mm512_set1_epi8(':');
10011
  // Merging ':' into the tail makes the terminator at `len` a real colon, so
10012
  // the compress mask below never has to be rebuilt in a general register.
10013
  const __m512i v = _mm512_mask_loadu_epi8(colon, active, data);
10014
  const __mmask64 mcolon = _mm512_cmpeq_epi8_mask(v, colon);
10015
10016
  // An embedded dotted quad is the one valid form this kernel does not cover.
10017
  // Because that is the only gap, every other input it does not accept is
10018
  // invalid, which is what makes `valid = false` below safe.
10019
  if (_mm512_cmpeq_epi8_mask(v, _mm512_set1_epi8('.'))) [[unlikely]] {
10020
    return false;
10021
  }
10022
10023
  const __m512i nib = _mm512_permutex2var_epi8(_mm512_load_si512(hex_lo), v,
10024
                                               _mm512_load_si512(hex_hi));
10025
  const __m128i comp = _mm512_castsi512_si128(
10026
      _mm512_maskz_compress_epi8(mcolon, _mm512_load_si512(iota)));
10027
  const __m128i lane0 =
10028
      _mm_setr_epi8(-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
10029
  const __m128i prev = _mm_or_si128(_mm_bslli_si128(comp, 1), lane0);
10030
  const __m128i width = _mm_sub_epi8(comp, prev);  // one too large
10031
10032
  const uint64_t mc = static_cast<uint64_t>(mcolon);
10033
  const uint64_t act = static_cast<uint64_t>(active);
10034
  const uint64_t dc = mc & (mc >> 1) & (act >> 1);  // a "::" inside [0, len)
10035
10036
  if (!dc) {
10037
    ipv6_gather(comp, prev, nib, address);
10038
    // nib | (v & 0x80): one scan for non-hex bytes and for bytes whose high
10039
    // bit made vpermi2b alias a legal one.
10040
    const __m512i fused = _mm512_ternarylogic_epi32(
10041
        nib, v, _mm512_set1_epi8(static_cast<char>(0x80)), 0xf8);
10042
    // Lanes 8..15 bound against 255, which an unsigned byte cannot exceed.
10043
    const __m128i wmax =
10044
        _mm_setr_epi8(3, 3, 3, 3, 3, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1);
10045
    __mmask64 err = _kandn_mask64(mcolon, _mm512_movepi8_mask(fused));
10046
    err = _kor_mask64(
10047
        err, static_cast<__mmask64>(static_cast<uint16_t>(_mm_cmpgt_epu8_mask(
10048
                 _mm_sub_epi8(width, _mm_set1_epi8(2)), wmax))));
10049
    valid = (_mm_popcnt_u64(mc & act) == 7) && !err;
10050
    return true;
10051
  }
10052
10053
  // Drop the zero-width gap field(s), then expand the surviving head and tail
10054
  // fields into eight slots with all-zero groups inserted at the gap.
10055
  const uint32_t head = static_cast<uint32_t>(_mm_popcnt_u64(mc & (dc - 1))) +
10056
                        static_cast<uint32_t>(dc > 1);
10057
  const __mmask16 keep = _mm_cmpgt_epi8_mask(width, _mm_set1_epi8(1));
10058
  const uint32_t kept = static_cast<uint32_t>(_mm_popcnt_u32(keep));
10059
  const __mmask16 slots = static_cast<__mmask16>(
10060
      ~(_bzhi_u32(0xFFFFFFFFu, 8 - kept) << head) & 0xFFu);
10061
  // Inserted groups take prev = -1, so their indices clamp to byte 63, a tail
10062
  // colon, and read zero.
10063
  ipv6_gather(_mm_maskz_expand_epi8(slots, _mm_maskz_compress_epi8(keep, comp)),
10064
              _mm_mask_expand_epi8(_mm_set1_epi8(-1), slots,
10065
                                   _mm_maskz_compress_epi8(keep, prev)),
10066
              nib, address);
10067
10068
  uint64_t err = _mm512_movepi8_mask(v);    // high-bit bytes
10069
  err |= _mm512_movepi8_mask(nib) & ~mc;    // non-hex
10070
  err |= _blsr_u64(dc);                     // a second "::"
10071
  err |= static_cast<uint64_t>(kept >= 8);  // "::" elides nothing
10072
  err |= _mm_cmpgt_epu8_mask(width, _mm_set1_epi8(5)) & keep;  // group > 4
10073
  err |= (mc & 1ULL) & ~dc;                                // leading lone ':'
10074
  err |= ((mc >> (len - 1)) & 1ULL) & ~(dc >> (len - 2));  // trailing lone ':'
10075
  valid = !err;
10076
  return true;
10077
}
10078
#endif  // ADA_AVX512_IPV6
10079
10080
}  // namespace ada::detail
10081
10082
#endif  // ADA_URL_IP_INL_H
10083
/* end file include/ada/url_ip-inl.h */
10084
10085
#include <algorithm>
10086
#include <array>
10087
#include <cstddef>
10088
#include <cstdint>
10089
#include <iterator>
10090
#include <numeric>
10091
#include <optional>
10092
#include <ranges>
10093
#include <string>
10094
#include <string_view>
10095
#include <utility>
10096
10097
namespace ada {
10098
10099
0
bool url::parse_opaque_host(std::string_view input) {
10100
0
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
10101
0
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
10102
0
    return is_valid = false;
10103
0
  }
10104
10105
  // Return the result of running UTF-8 percent-encode on input using the C0
10106
  // control percent-encode set.
10107
0
  host = ada::unicode::percent_encode(
10108
0
      input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
10109
0
  return true;
10110
0
}
10111
10112
0
bool url::parse_ipv4(std::string_view input) {
10113
0
  ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
10114
0
  if (input.empty()) {
10115
0
    return is_valid = false;
10116
0
  }
10117
0
  std::string_view original_input = input;
10118
0
  if (original_input.back() == '.') {
10119
0
    original_input.remove_suffix(1);
10120
0
  }
10121
0
  if (input.back() == '.') {
10122
0
    input.remove_suffix(1);
10123
0
    if (input.empty()) {
10124
0
      return is_valid = false;
10125
0
    }
10126
0
  }
10127
10128
0
  const uint64_t fast = checkers::try_parse_ipv4_fast(input);
10129
0
  if (fast < checkers::ipv4_fast_fail) [[likely]] {
10130
0
    host = original_input;
10131
0
    host_type = IPV4;
10132
0
    return true;
10133
0
  }
10134
10135
0
  const char* p = input.data();
10136
0
  const char* end = p + input.size();
10137
0
  uint64_t ipv4 = 0;
10138
0
  int digit_count = 0;
10139
0
  int pure_decimal_count = 0;
10140
10141
0
  for (; digit_count < 4 && p < end; ++digit_count) {
10142
0
    uint64_t segment = 0;
10143
0
    bool pure = false;
10144
0
    if (!detail::parse_ipv4_number(p, end, segment, pure)) {
10145
0
      return is_valid = false;
10146
0
    }
10147
0
    if (pure) {
10148
0
      ++pure_decimal_count;
10149
0
    }
10150
0
    if (p >= end) {
10151
0
      const unsigned shift = static_cast<unsigned>(32 - digit_count * 8);
10152
0
      if (segment >= (uint64_t{1} << shift)) {
10153
0
        return is_valid = false;
10154
0
      }
10155
0
      ipv4 = (ipv4 << shift) | segment;
10156
0
      host = (pure_decimal_count == 4) ? std::string(original_input)
10157
0
                                       : ada::serializers::ipv4(ipv4);
10158
0
      host_type = IPV4;
10159
0
      return true;
10160
0
    }
10161
0
    if (segment > 255 || *p != '.') {
10162
0
      return is_valid = false;
10163
0
    }
10164
0
    ipv4 = (ipv4 << 8) | segment;
10165
0
    ++p;
10166
0
  }
10167
0
  if (digit_count != 4 || p != end) {
10168
0
    return is_valid = false;
10169
0
  }
10170
0
  host = (pure_decimal_count == 4) ? std::string(original_input)
10171
0
                                   : ada::serializers::ipv4(ipv4);
10172
0
  host_type = IPV4;
10173
0
  return true;
10174
0
}
10175
10176
0
bool url::parse_ipv6(std::string_view input) {
10177
0
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
10178
0
  if (input.empty() || input.size() > 45) [[unlikely]] {
10179
0
    return is_valid = false;
10180
0
  }
10181
0
  std::array<uint16_t, 8> address{};
10182
#if defined(ADA_AVX512_IPV6)
10183
  if (bool simd_valid; detail::try_parse_ipv6_avx512(input.data(), input.size(),
10184
                                                     address, simd_valid)) {
10185
    if (!simd_valid) [[unlikely]] {
10186
      return is_valid = false;
10187
    }
10188
    host = ada::serializers::ipv6(address);
10189
    host_type = IPV6;
10190
    return true;
10191
  }
10192
  address = {};
10193
#endif
10194
0
  const char* pointer = input.data();
10195
0
  const char* const end = pointer + input.size();
10196
0
  int piece_index = 0;
10197
0
  int compress = -1;
10198
10199
0
  if (*pointer == ':') {
10200
0
    if (input.size() == 1 || pointer[1] != ':') [[unlikely]] {
10201
0
      return is_valid = false;
10202
0
    }
10203
0
    pointer += 2;
10204
0
    compress = ++piece_index;
10205
0
  }
10206
10207
0
  while (pointer != end) {
10208
0
    if (piece_index == 8) [[unlikely]] {
10209
0
      return is_valid = false;
10210
0
    }
10211
0
    if (*pointer == ':') {
10212
0
      if (compress != -1) [[unlikely]] {
10213
0
        return is_valid = false;
10214
0
      }
10215
0
      ++pointer;
10216
0
      compress = ++piece_index;
10217
0
      continue;
10218
0
    }
10219
10220
0
    uint16_t value = 0;
10221
0
    const int length = detail::parse_hex_piece(pointer, end, value);
10222
10223
0
    if (pointer != end && *pointer == '.') {
10224
0
      if (length == 0) [[unlikely]] {
10225
0
        return is_valid = false;
10226
0
      }
10227
0
      pointer -= length;
10228
0
      if (piece_index > 6) [[unlikely]] {
10229
0
        return is_valid = false;
10230
0
      }
10231
10232
0
      int numbers_seen = 0;
10233
0
      while (pointer != end) {
10234
0
        int ipv4_piece = -1;
10235
0
        if (numbers_seen > 0) {
10236
0
          if (*pointer == '.' && numbers_seen < 4) {
10237
0
            ++pointer;
10238
0
          } else {
10239
0
            return is_valid = false;
10240
0
          }
10241
0
        }
10242
0
        if (pointer == end || *pointer < '0' || *pointer > '9') [[unlikely]] {
10243
0
          return is_valid = false;
10244
0
        }
10245
0
        ipv4_piece = *pointer - '0';
10246
0
        ++pointer;
10247
0
        if (pointer != end && *pointer >= '0' && *pointer <= '9') {
10248
0
          if (ipv4_piece == 0) [[unlikely]] {
10249
0
            return is_valid = false;
10250
0
          }
10251
0
          ipv4_piece = ipv4_piece * 10 + (*pointer - '0');
10252
0
          ++pointer;
10253
0
          if (pointer != end && *pointer >= '0' && *pointer <= '9') {
10254
0
            ipv4_piece = ipv4_piece * 10 + (*pointer - '0');
10255
0
            ++pointer;
10256
0
            if (ipv4_piece > 255) [[unlikely]] {
10257
0
              return is_valid = false;
10258
0
            }
10259
0
          }
10260
0
        }
10261
0
        address[static_cast<size_t>(piece_index)] = static_cast<uint16_t>(
10262
0
            address[static_cast<size_t>(piece_index)] * 0x100 +
10263
0
            static_cast<uint16_t>(ipv4_piece));
10264
0
        ++numbers_seen;
10265
0
        if (numbers_seen == 2 || numbers_seen == 4) {
10266
0
          ++piece_index;
10267
0
        }
10268
0
      }
10269
0
      if (numbers_seen != 4) [[unlikely]] {
10270
0
        return is_valid = false;
10271
0
      }
10272
0
      break;
10273
0
    }
10274
10275
0
    if (length == 0) [[unlikely]] {
10276
0
      return is_valid = false;
10277
0
    }
10278
10279
0
    if (pointer != end && *pointer == ':') {
10280
0
      ++pointer;
10281
0
      if (pointer == end) [[unlikely]] {
10282
0
        return is_valid = false;
10283
0
      }
10284
0
    } else if (pointer != end) [[unlikely]] {
10285
0
      return is_valid = false;
10286
0
    }
10287
10288
0
    address[static_cast<size_t>(piece_index)] = value;
10289
0
    ++piece_index;
10290
0
  }
10291
10292
0
  if (compress != -1) {
10293
0
    const int right = piece_index - compress;
10294
0
    if (right > 0) {
10295
0
      const size_t dest = static_cast<size_t>(8 - right);
10296
0
      const size_t src = static_cast<size_t>(compress);
10297
0
      if (dest != src) {
10298
0
        for (size_t i = static_cast<size_t>(right); i-- > 0;) {
10299
0
          address[dest + i] = address[src + i];
10300
0
          address[src + i] = 0;
10301
0
        }
10302
0
      }
10303
0
    }
10304
0
  } else if (piece_index != 8) [[unlikely]] {
10305
0
    return is_valid = false;
10306
0
  }
10307
10308
0
  host = ada::serializers::ipv6(address);
10309
0
  ada_log("parse_ipv6 ", *host);
10310
0
  host_type = IPV6;
10311
0
  return true;
10312
0
}
10313
10314
template <bool has_state_override>
10315
0
ada_really_inline bool url::parse_scheme(const std::string_view input) {
10316
0
  auto parsed_type = ada::scheme::get_scheme_type(input);
10317
0
  bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
10318
  /**
10319
   * In the common case, we will immediately recognize a special scheme (e.g.,
10320
   *http, https), in which case, we can go really fast.
10321
   **/
10322
0
  if (is_input_special) {  // fast path!!!
10323
0
    if constexpr (has_state_override) {
10324
      // If url's scheme is not a special scheme and buffer is a special scheme,
10325
      // then return.
10326
0
      if (is_special() != is_input_special) {
10327
0
        return false;
10328
0
      }
10329
10330
      // If url includes credentials or has a non-null port, and buffer is
10331
      // "file", then return.
10332
0
      if ((has_credentials() || port.has_value()) &&
10333
0
          parsed_type == ada::scheme::type::FILE) {
10334
0
        return false;
10335
0
      }
10336
10337
      // If url's scheme is "file" and its host is an empty host, then return.
10338
      // An empty host is the empty string.
10339
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
10340
0
          host->empty()) {
10341
0
        return false;
10342
0
      }
10343
0
    }
10344
10345
0
    type = parsed_type;
10346
10347
0
    if constexpr (has_state_override) {
10348
      // This is uncommon.
10349
0
      uint16_t urls_scheme_port = get_special_port();
10350
10351
0
      if (urls_scheme_port) {
10352
        // If url's port is url's scheme's default port, then set url's port to
10353
        // null.
10354
0
        if (port.has_value() && *port == urls_scheme_port) {
10355
0
          port = std::nullopt;
10356
0
        }
10357
0
      }
10358
0
    }
10359
0
  } else {  // slow path
10360
0
    std::string _buffer(input);
10361
    // Next function is only valid if the input is ASCII and returns false
10362
    // otherwise, but it seems that we always have ascii content so we do not
10363
    // need to check the return value.
10364
    // bool is_ascii =
10365
0
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
10366
10367
0
    if constexpr (has_state_override) {
10368
      // The state-override validation errors below ("return" in the WHATWG URL
10369
      // parser) leave the URL unchanged. The setter contract is
10370
      // "true on success, false if the scheme is invalid" -- the fast path
10371
      // above already returns false here, so the slow path must agree.
10372
10373
      // If url's scheme is a special scheme and buffer is not a special scheme,
10374
      // then return. If url's scheme is not a special scheme and buffer is a
10375
      // special scheme, then return.
10376
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
10377
0
        return false;
10378
0
      }
10379
10380
      // If url includes credentials or has a non-null port, and buffer is
10381
      // "file", then return.
10382
0
      if ((has_credentials() || port.has_value()) && _buffer == "file") {
10383
0
        return false;
10384
0
      }
10385
10386
      // If url's scheme is "file" and its host is an empty host, then return.
10387
      // An empty host is the empty string.
10388
0
      if (type == ada::scheme::type::FILE && host.has_value() &&
10389
0
          host->empty()) {
10390
0
        return false;
10391
0
      }
10392
0
    }
10393
10394
0
    set_scheme(std::move(_buffer));
10395
10396
0
    if constexpr (has_state_override) {
10397
      // This is uncommon.
10398
0
      uint16_t urls_scheme_port = get_special_port();
10399
10400
0
      if (urls_scheme_port) {
10401
        // If url's port is url's scheme's default port, then set url's port to
10402
        // null.
10403
0
        if (port.has_value() && *port == urls_scheme_port) {
10404
0
          port = std::nullopt;
10405
0
        }
10406
0
      }
10407
0
    }
10408
0
  }
10409
10410
0
  return true;
10411
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> >)
10412
10413
0
ada_really_inline bool url::parse_host(std::string_view input) {
10414
0
  ada_log("parse_host ", input, " [", input.size(), " bytes]");
10415
0
  if (input.empty()) {
10416
0
    return is_valid = false;
10417
0
  }  // technically unnecessary.
10418
  // If input starts with U+005B ([), then:
10419
0
  if (input[0] == '[') {
10420
    // If input does not end with U+005D (]), validation error, return failure.
10421
0
    if (input.back() != ']') {
10422
0
      return is_valid = false;
10423
0
    }
10424
0
    ada_log("parse_host ipv6");
10425
10426
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
10427
    // trailing U+005D (]) removed.
10428
0
    input.remove_prefix(1);
10429
0
    input.remove_suffix(1);
10430
0
    return parse_ipv6(input);
10431
0
  }
10432
10433
  // If isNotSpecial is true, then return the result of opaque-host parsing
10434
  // input.
10435
0
  if (!is_special()) {
10436
0
    return parse_opaque_host(input);
10437
0
  }
10438
10439
  // Fast path: try to parse as pure decimal IPv4 first.
10440
0
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
10441
0
  if (fast_result < checkers::ipv4_fast_fail) {
10442
0
    if (!input.empty() && input.back() == '.') {
10443
0
      host = input.substr(0, input.size() - 1);
10444
0
    } else {
10445
0
      host = input;
10446
0
    }
10447
0
    host_type = IPV4;
10448
0
    is_valid = true;
10449
0
    ada_log("parse_host fast path decimal ipv4");
10450
0
    return true;
10451
0
  }
10452
  // Let domain be the result of running UTF-8 decode without BOM on the
10453
  // percent-decoding of input. Let asciiDomain be the result of running domain
10454
  // to ASCII with domain and false. The most common case is an ASCII input, in
10455
  // which case we do not need to call the expensive 'to_ascii' if a few
10456
  // conditions are met: no '%' and no 'xn-' subsequence.
10457
0
  const uint8_t forbidden_or_upper =
10458
0
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
10459
0
                                                             input.size());
10460
0
  static constexpr std::string_view xn_dash{"xn-", 3};
10461
0
  if ((forbidden_or_upper & 1) == 0) {
10462
0
    host = std::string(input);
10463
0
    if ((forbidden_or_upper & 2) != 0) {
10464
0
      unicode::to_lower_ascii(host->data(), host->size());
10465
0
    }
10466
0
    if (host->find('-') == std::string_view::npos ||
10467
0
        host->find(xn_dash) == std::string_view::npos) {
10468
0
      if (checkers::is_ipv4(*host)) {
10469
0
        ada_log("parse_host fast path ipv4");
10470
0
        return parse_ipv4(*host);
10471
0
      }
10472
0
      ada_log("parse_host fast path ", *host);
10473
0
      is_valid = true;
10474
0
      return true;
10475
0
    }
10476
0
  } else if (const size_t first_percent = input.find('%');
10477
0
             first_percent != std::string_view::npos) {
10478
0
    std::string decoded = unicode::percent_decode(input, first_percent);
10479
0
    const uint8_t decoded_flags =
10480
0
        unicode::contains_forbidden_domain_code_point_or_upper(decoded.data(),
10481
0
                                                               decoded.size());
10482
0
    if ((decoded_flags & 1) == 0) {
10483
0
      if ((decoded_flags & 2) != 0) {
10484
0
        unicode::to_lower_ascii(decoded.data(), decoded.size());
10485
0
      }
10486
0
      if (decoded.find('-') == std::string_view::npos ||
10487
0
          decoded.find(xn_dash) == std::string_view::npos) {
10488
0
        host = std::move(decoded);
10489
0
        if (checkers::is_ipv4(*host)) {
10490
0
          return parse_ipv4(*host);
10491
0
        }
10492
0
        is_valid = true;
10493
0
        return true;
10494
0
      }
10495
0
    }
10496
0
  }
10497
0
  ada_log("parse_host calling to_ascii");
10498
0
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
10499
0
  if (!is_valid || !host.has_value()) {
10500
0
    ada_log("parse_host to_ascii returns false");
10501
0
    return is_valid = false;
10502
0
  }
10503
0
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
10504
0
          " bytes]");
10505
10506
0
  if (std::any_of(host->begin(), host->end(),
10507
0
                  ada::unicode::is_forbidden_domain_code_point)) {
10508
0
    host = std::nullopt;
10509
0
    return is_valid = false;
10510
0
  }
10511
10512
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
10513
  // asciiDomain.
10514
0
  if (checkers::is_ipv4(*host)) {
10515
0
    ada_log("parse_host got ipv4 ", *host);
10516
0
    return parse_ipv4(*host);
10517
0
  }
10518
10519
0
  return true;
10520
0
}
10521
10522
0
ada_really_inline void url::parse_path(std::string_view input) {
10523
0
  ada_log("parse_path ", input);
10524
0
  std::string tmp_buffer;
10525
0
  std::string_view internal_input;
10526
0
  if (unicode::has_tabs_or_newline(input)) {
10527
0
    tmp_buffer = input;
10528
    // Optimization opportunity: Instead of copying and then pruning, we could
10529
    // just directly build the string from user_input.
10530
0
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
10531
0
    internal_input = tmp_buffer;
10532
0
  } else {
10533
0
    internal_input = input;
10534
0
  }
10535
10536
  // If url is special, then:
10537
0
  if (is_special()) {
10538
0
    if (internal_input.empty()) {
10539
0
      path = "/";
10540
0
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
10541
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
10542
0
    } else {
10543
0
      helpers::parse_prepared_path(internal_input, type, path);
10544
0
    }
10545
0
  } else if (!internal_input.empty()) {
10546
0
    if (internal_input[0] == '/') {
10547
0
      helpers::parse_prepared_path(internal_input.substr(1), type, path);
10548
0
    } else {
10549
0
      helpers::parse_prepared_path(internal_input, type, path);
10550
0
    }
10551
0
  } else {
10552
0
    if (!host.has_value()) {
10553
0
      path = "/";
10554
0
    }
10555
0
  }
10556
0
}
10557
10558
0
[[nodiscard]] std::string url::to_string() const {
10559
0
  if (!is_valid) {
10560
0
    return "null";
10561
0
  }
10562
0
  std::string answer;
10563
0
  auto back = std::back_insert_iterator(answer);
10564
0
  answer.append("{\n");
10565
0
  answer.append("\t\"protocol\":\"");
10566
0
  helpers::encode_json(get_protocol(), back);
10567
0
  answer.append("\",\n");
10568
0
  if (has_credentials()) {
10569
0
    answer.append("\t\"username\":\"");
10570
0
    helpers::encode_json(username, back);
10571
0
    answer.append("\",\n");
10572
0
    answer.append("\t\"password\":\"");
10573
0
    helpers::encode_json(password, back);
10574
0
    answer.append("\",\n");
10575
0
  }
10576
0
  if (host.has_value()) {
10577
0
    answer.append("\t\"host\":\"");
10578
0
    helpers::encode_json(host.value(), back);
10579
0
    answer.append("\",\n");
10580
0
  }
10581
0
  if (port.has_value()) {
10582
0
    answer.append("\t\"port\":\"");
10583
0
    answer.append(std::to_string(port.value()));
10584
0
    answer.append("\",\n");
10585
0
  }
10586
0
  answer.append("\t\"path\":\"");
10587
0
  helpers::encode_json(path, back);
10588
0
  answer.append("\",\n");
10589
0
  answer.append("\t\"opaque path\":");
10590
0
  answer.append((has_opaque_path ? "true" : "false"));
10591
0
  if (has_search()) {
10592
0
    answer.append(",\n");
10593
0
    answer.append("\t\"query\":\"");
10594
    // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
10595
0
    helpers::encode_json(query.value(), back);
10596
0
    answer.append("\"");
10597
0
  }
10598
0
  if (hash.has_value()) {
10599
0
    answer.append(",\n");
10600
0
    answer.append("\t\"hash\":\"");
10601
0
    helpers::encode_json(hash.value(), back);
10602
0
    answer.append("\"");
10603
0
  }
10604
0
  answer.append("\n}");
10605
0
  return answer;
10606
0
}
10607
10608
0
[[nodiscard]] bool url::has_valid_domain() const noexcept {
10609
0
  if (!host.has_value()) {
10610
0
    return false;
10611
0
  }
10612
0
  return checkers::verify_dns_length(*host);
10613
0
}
10614
10615
0
[[nodiscard]] std::string url::get_origin() const {
10616
0
  if (is_special()) {
10617
    // Return a new opaque origin.
10618
0
    if (type == scheme::FILE) {
10619
0
      return "null";
10620
0
    }
10621
0
    return ada::helpers::concat(get_protocol(), "//", get_host());
10622
0
  }
10623
10624
0
  if (non_special_scheme == "blob") {
10625
0
    if (!path.empty()) {
10626
0
      auto result = ada::parse<ada::url>(path);
10627
0
      if (result &&
10628
0
          (result->type == scheme::HTTP || result->type == scheme::HTTPS)) {
10629
        // If pathURL's scheme is not "http" and not "https", then return a
10630
        // new opaque origin.
10631
0
        return ada::helpers::concat(result->get_protocol(), "//",
10632
0
                                    result->get_host());
10633
0
      }
10634
0
    }
10635
0
  }
10636
10637
  // Return a new opaque origin.
10638
0
  return "null";
10639
0
}
10640
10641
0
[[nodiscard]] std::string url::get_protocol() const {
10642
0
  if (is_special()) {
10643
0
    return helpers::concat(ada::scheme::details::is_special_list[type], ":");
10644
0
  }
10645
  // We only move the 'scheme' if it is non-special.
10646
0
  return helpers::concat(non_special_scheme, ":");
10647
0
}
10648
10649
0
[[nodiscard]] std::string url::get_host() const {
10650
  // If url's host is null, then return the empty string.
10651
  // If url's port is null, return url's host, serialized.
10652
  // Return url's host, serialized, followed by U+003A (:) and url's port,
10653
  // serialized.
10654
0
  if (!host.has_value()) {
10655
0
    return "";
10656
0
  }
10657
0
  if (port.has_value()) {
10658
0
    return host.value() + ":" + get_port();
10659
0
  }
10660
0
  return host.value();
10661
0
}
10662
10663
0
[[nodiscard]] std::string url::get_hostname() const {
10664
0
  return host.value_or("");
10665
0
}
10666
10667
0
[[nodiscard]] std::string url::get_search() const {
10668
  // If this's URL's query is either null or the empty string, then return the
10669
  // empty string. Return U+003F (?), followed by this's URL's query.
10670
0
  return (!query.has_value() || (query->empty())) ? "" : "?" + query.value();
10671
0
}
10672
10673
0
[[nodiscard]] const std::string& url::get_username() const noexcept {
10674
0
  return username;
10675
0
}
10676
10677
0
[[nodiscard]] const std::string& url::get_password() const noexcept {
10678
0
  return password;
10679
0
}
10680
10681
0
[[nodiscard]] std::string url::get_port() const {
10682
0
  return port.has_value() ? std::to_string(port.value()) : "";
10683
0
}
10684
10685
0
[[nodiscard]] std::string url::get_hash() const {
10686
  // If this's URL's fragment is either null or the empty string, then return
10687
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
10688
0
  return (!hash.has_value() || (hash->empty())) ? "" : "#" + hash.value();
10689
0
}
10690
10691
0
bool url::needs_rollback_snapshot(size_t input_len) const noexcept {
10692
0
  return get_href_size() + input_len + 16 > ada::get_max_input_length();
10693
0
}
10694
10695
template <bool override_hostname>
10696
0
bool url::set_host_or_hostname(const std::string_view input) {
10697
0
  if (has_opaque_path) {
10698
0
    return false;
10699
0
  }
10700
10701
0
  url saved_url(*this);
10702
10703
0
  size_t host_end_pos = input.find('#');
10704
0
  std::string _host(input.data(), host_end_pos != std::string_view::npos
10705
0
                                      ? host_end_pos
10706
0
                                      : input.size());
10707
0
  helpers::remove_ascii_tab_or_newline(_host);
10708
0
  std::string_view new_host(_host);
10709
10710
0
  auto check_url_size = [&]() -> bool {
10711
0
    if (get_href_size() > ada::get_max_input_length()) {
10712
0
      *this = std::move(saved_url);
10713
0
      return false;
10714
0
    }
10715
0
    return true;
10716
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
10717
10718
  // If url's scheme is "file", then set state to file host state, instead of
10719
  // host state.
10720
0
  if (type != ada::scheme::type::FILE) {
10721
0
    std::string_view host_view(_host.data(), _host.length());
10722
0
    auto [location, found_colon] =
10723
0
        helpers::get_host_delimiter_location(is_special(), host_view);
10724
10725
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
10726
    // Note: the 'found_colon' value is true if and only if a colon was
10727
    // encountered while not inside brackets.
10728
0
    if (found_colon) {
10729
      // If buffer is the empty string, host-missing validation error, return
10730
      // failure.
10731
0
      std::string_view buffer = host_view.substr(0, location);
10732
0
      if (buffer.empty()) {
10733
0
        return false;
10734
0
      }
10735
10736
      // If state override is given and state override is hostname state, then
10737
      // return failure.
10738
0
      if constexpr (override_hostname) {
10739
0
        return false;
10740
0
      }
10741
10742
      // Let host be the result of host parsing buffer with url is not special.
10743
0
      bool succeeded = parse_host(buffer);
10744
0
      if (!succeeded) {
10745
0
        *this = std::move(saved_url);
10746
0
        return false;
10747
0
      }
10748
10749
      // Set url's host to host, buffer to the empty string, and state to port
10750
      // state.
10751
0
      std::string_view port_buffer = new_host.substr(location + 1);
10752
0
      if (!port_buffer.empty()) {
10753
0
        set_port(port_buffer);
10754
0
      }
10755
0
      return check_url_size();
10756
0
    }
10757
    // Otherwise, if one of the following is true:
10758
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
10759
    // - url is special and c is U+005C (\)
10760
0
    else {
10761
      // If url is special and host_view is the empty string, host-missing
10762
      // validation error, return failure.
10763
0
      if (host_view.empty() && is_special()) {
10764
0
        return false;
10765
0
      }
10766
10767
      // Otherwise, if state override is given, host_view is the empty string,
10768
      // and either url includes credentials or url's port is non-null, then
10769
      // return failure.
10770
0
      if (host_view.empty() && (has_credentials() || port.has_value())) {
10771
0
        return false;
10772
0
      }
10773
10774
      // Let host be the result of host parsing host_view with url is not
10775
      // special.
10776
0
      if (host_view.empty() && !is_special()) {
10777
0
        host = "";
10778
0
        return check_url_size();
10779
0
      }
10780
10781
0
      bool succeeded = parse_host(host_view);
10782
0
      if (!succeeded) {
10783
0
        *this = std::move(saved_url);
10784
0
        return false;
10785
0
      }
10786
0
      return check_url_size();
10787
0
    }
10788
0
  }
10789
10790
0
  size_t location = new_host.find_first_of("/\\?");
10791
0
  if (location != std::string_view::npos) {
10792
0
    new_host.remove_suffix(new_host.length() - location);
10793
0
  }
10794
10795
0
  if (new_host.empty()) {
10796
    // Set url's host to the empty string.
10797
0
    host = "";
10798
0
  } else {
10799
    // Let host be the result of host parsing buffer with url is not special.
10800
0
    if (!parse_host(new_host)) {
10801
0
      *this = std::move(saved_url);
10802
0
      return false;
10803
0
    }
10804
10805
    // If host is "localhost", then set host to the empty string.
10806
0
    if (host == "localhost") {
10807
0
      host = "";
10808
0
    }
10809
0
  }
10810
0
  return check_url_size();
10811
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> >)
10812
10813
0
bool url::set_host(const std::string_view input) {
10814
0
  return set_host_or_hostname<false>(input);
10815
0
}
10816
10817
0
bool url::set_hostname(const std::string_view input) {
10818
0
  return set_host_or_hostname<true>(input);
10819
0
}
10820
10821
0
bool url::set_username(const std::string_view input) {
10822
0
  if (cannot_have_credentials_or_port()) {
10823
0
    return false;
10824
0
  }
10825
0
  auto previous_username = std::move(username);
10826
0
  username = ada::unicode::percent_encode(
10827
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
10828
0
  if (get_href_size() > ada::get_max_input_length()) {
10829
0
    username = std::move(previous_username);
10830
0
    return false;
10831
0
  }
10832
0
  return true;
10833
0
}
10834
10835
0
bool url::set_password(const std::string_view input) {
10836
0
  if (cannot_have_credentials_or_port()) {
10837
0
    return false;
10838
0
  }
10839
0
  auto previous_password = std::move(password);
10840
0
  password = ada::unicode::percent_encode(
10841
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
10842
0
  if (get_href_size() > ada::get_max_input_length()) {
10843
0
    password = std::move(previous_password);
10844
0
    return false;
10845
0
  }
10846
0
  return true;
10847
0
}
10848
10849
0
bool url::set_port(const std::string_view input) {
10850
0
  if (cannot_have_credentials_or_port()) {
10851
0
    return false;
10852
0
  }
10853
10854
0
  if (input.empty()) {
10855
0
    port = std::nullopt;
10856
0
    return true;
10857
0
  }
10858
10859
0
  std::string trimmed(input);
10860
0
  helpers::remove_ascii_tab_or_newline(trimmed);
10861
10862
0
  if (trimmed.empty()) {
10863
0
    return true;
10864
0
  }
10865
10866
  // Input should not start with a non-digit character.
10867
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
10868
0
    return false;
10869
0
  }
10870
10871
  // Find the first non-digit character to determine the length of digits
10872
0
  auto first_non_digit =
10873
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
10874
0
  std::string_view digits_to_parse =
10875
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
10876
10877
  // Revert changes if parse_port fails.
10878
0
  std::optional<uint16_t> previous_port = port;
10879
0
  parse_port(digits_to_parse);
10880
0
  if (is_valid) {
10881
0
    if (get_href_size() > ada::get_max_input_length()) {
10882
0
      port = std::move(previous_port);
10883
0
      return false;
10884
0
    }
10885
0
    return true;
10886
0
  }
10887
0
  port = std::move(previous_port);
10888
0
  is_valid = true;
10889
0
  return false;
10890
0
}
10891
10892
0
void url::set_hash(const std::string_view input) {
10893
0
  if (input.empty()) {
10894
0
    hash = std::nullopt;
10895
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
10896
0
    return;
10897
0
  }
10898
10899
0
  std::string new_value;
10900
0
  new_value = input[0] == '#' ? input.substr(1) : input;
10901
0
  helpers::remove_ascii_tab_or_newline(new_value);
10902
0
  auto previous_hash = std::move(hash);
10903
0
  hash = unicode::percent_encode(new_value,
10904
0
                                 ada::character_sets::FRAGMENT_PERCENT_ENCODE);
10905
0
  if (get_href_size() > ada::get_max_input_length()) {
10906
0
    hash = std::move(previous_hash);
10907
0
  }
10908
0
}
10909
10910
0
void url::set_search(const std::string_view input) {
10911
0
  if (input.empty()) {
10912
0
    query = std::nullopt;
10913
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
10914
0
    return;
10915
0
  }
10916
10917
0
  std::string new_value;
10918
0
  new_value = input[0] == '?' ? input.substr(1) : input;
10919
0
  helpers::remove_ascii_tab_or_newline(new_value);
10920
10921
0
  auto query_percent_encode_set =
10922
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
10923
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
10924
10925
0
  auto previous_query = std::move(query);
10926
0
  query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
10927
0
  if (get_href_size() > ada::get_max_input_length()) {
10928
0
    query = std::move(previous_query);
10929
0
  }
10930
0
}
10931
10932
0
bool url::set_pathname(const std::string_view input) {
10933
0
  if (has_opaque_path) {
10934
0
    return false;
10935
0
  }
10936
0
  auto previous_path = std::move(path);
10937
0
  path.clear();
10938
0
  parse_path(input);
10939
0
  if (get_href_size() > ada::get_max_input_length()) {
10940
0
    path = std::move(previous_path);
10941
0
    return false;
10942
0
  }
10943
0
  return true;
10944
0
}
10945
10946
0
bool url::set_protocol(const std::string_view input) {
10947
0
  std::string view(input);
10948
0
  helpers::remove_ascii_tab_or_newline(view);
10949
0
  if (view.empty()) {
10950
0
    return true;
10951
0
  }
10952
10953
  // Schemes should start with alpha values.
10954
0
  if (!checkers::is_alpha(view[0])) {
10955
0
    return false;
10956
0
  }
10957
10958
0
  view.append(":");
10959
10960
0
  std::string::iterator pointer =
10961
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
10962
10963
0
  if (pointer != view.end() && *pointer == ':') {
10964
0
    std::optional<url> saved_url;
10965
0
    if (needs_rollback_snapshot(view.size())) {
10966
0
      saved_url = *this;
10967
0
    }
10968
0
    bool result = parse_scheme<true>(
10969
0
        std::string_view(view.data(), pointer - view.begin()));
10970
0
    if (result && saved_url && get_href_size() > ada::get_max_input_length()) {
10971
0
      *this = std::move(*saved_url);
10972
0
      return false;
10973
0
    }
10974
0
    return result;
10975
0
  }
10976
0
  return false;
10977
0
}
10978
10979
0
bool url::set_href(const std::string_view input) {
10980
0
  ada::result<ada::url> out = ada::parse<ada::url>(input);
10981
10982
0
  if (out) {
10983
    // The parser enforces get_max_input_length() on both the input and the
10984
    // normalized result. This is a defense-in-depth check.
10985
0
    if (out->get_href_size() > ada::get_max_input_length()) {
10986
0
      return false;
10987
0
    }
10988
0
    *this = std::move(*out);
10989
0
  }
10990
10991
0
  return out.has_value();
10992
0
}
10993
10994
}  // namespace ada
10995
/* end file src/url.cpp */
10996
/* begin file src/parser.cpp */
10997
10998
#include <array>
10999
#include <bit>
11000
#include <charconv>
11001
#include <cstdint>
11002
#include <cstring>
11003
#include <limits>
11004
#include <optional>
11005
#include <ranges>
11006
#include <string>
11007
#include <string_view>
11008
#include <utility>
11009
11010
11011
#if ADA_NEON
11012
#include <arm_neon.h>
11013
#elif defined(__SSSE3__)
11014
#include <tmmintrin.h>
11015
#define ADA_PARSER_SSSE3 1
11016
#elif (defined(__x86_64__) || defined(__amd64__)) && defined(__GNUC__) && \
11017
    !defined(_MSC_VER)
11018
// gcc/clang honor target("ssse3"). clang-cl and MSVC do not: they still
11019
// compile the function as SSE2, then reject always_inline _mm_shuffle_epi8.
11020
#include <tmmintrin.h>
11021
#define ADA_PARSER_SSSE3 1
11022
#define ADA_PARSER_NEED_SSSE3_TARGET 1
11023
#elif ADA_SSE2
11024
#include <emmintrin.h>
11025
#endif
11026
#ifndef ADA_PARSER_SSSE3
11027
#define ADA_PARSER_SSSE3 0
11028
#endif
11029
11030
#ifdef ADA_PARSER_NEED_SSSE3_TARGET
11031
// Scan loops stay on the default ISA (SSE2 for generic x86-64). pshufb lives
11032
// in a noinline SSSE3 function so the CPU check is not inside a function the
11033
// compiler is free to compile entirely with SSSE3 instructions.
11034
#define ADA_PARSER_SIMD ada_really_inline
11035
#define ADA_PARSER_SSSE3_FN __attribute__((target("ssse3"), noinline))
11036
#else
11037
#define ADA_PARSER_SIMD ada_really_inline
11038
#define ADA_PARSER_SSSE3_FN ada_really_inline
11039
#endif
11040
11041
#ifdef ADA_REGULAR_VISUAL_STUDIO
11042
#include <intrin.h>
11043
#endif
11044
11045
namespace ada::parser {
11046
11047
// Classification tables and 16-byte run scanners for the absolute-URL fast
11048
// path. Inspired by oven-sh/WebKit#452 and #454: scan 16 bytes at a time
11049
// (nibble-table pshufb/tbl when SSSE3 or NEON is available), and when the
11050
// path/query/fragment is not already canonical, keep the parsed host and
11051
// finish with the existing path helpers instead of re-parsing from scratch.
11052
namespace {
11053
11054
// 0 = host byte, 1 = host delimiter (/ ? # :), 2 = reject
11055
constexpr std::array<uint8_t, 256> k_host_class = []() consteval {
11056
  std::array<uint8_t, 256> t{};
11057
  for (size_t i = 0; i < 256; ++i) {
11058
    t[i] = 2;
11059
  }
11060
  for (size_t i = 0x21; i <= 0x7E; ++i) {
11061
    t[i] = 0;
11062
  }
11063
  for (uint8_t c :
11064
       {'#', '/', ':', '<', '>', '?', '@', '[', '\\', ']', '^', '|', '%'}) {
11065
    t[c] = 2;
11066
  }
11067
  t[static_cast<uint8_t>('/')] = 1;
11068
  t[static_cast<uint8_t>('?')] = 1;
11069
  t[static_cast<uint8_t>('#')] = 1;
11070
  t[static_cast<uint8_t>(':')] = 1;
11071
  return t;
11072
}();
11073
11074
// Path: 0 = copy, 1 = ?/#, 2 = needs work. Apostrophe is copyable in a path.
11075
constexpr std::array<uint8_t, 256> k_path = []() consteval {
11076
  std::array<uint8_t, 256> t{};
11077
  for (size_t i = 0; i < 256; ++i) {
11078
    t[i] = 2;
11079
  }
11080
  for (uint8_t c = 0x21; c <= 0x7E; ++c) {
11081
    t[c] = 0;
11082
  }
11083
  for (uint8_t c : {static_cast<uint8_t>('"'), static_cast<uint8_t>('<'),
11084
                    static_cast<uint8_t>('>'), static_cast<uint8_t>('`'),
11085
                    static_cast<uint8_t>('{'), static_cast<uint8_t>('}'),
11086
                    static_cast<uint8_t>('^'), static_cast<uint8_t>('\\'),
11087
                    static_cast<uint8_t>('%')}) {
11088
    t[c] = 2;
11089
  }
11090
  t[static_cast<uint8_t>('?')] = 1;
11091
  t[static_cast<uint8_t>('#')] = 1;
11092
  return t;
11093
}();
11094
11095
// Special-query: 0 = copy, 1 = #, 2 = needs work. Apostrophe must be encoded.
11096
constexpr std::array<uint8_t, 256> k_query = []() consteval {
11097
  std::array<uint8_t, 256> t{};
11098
  for (size_t i = 0; i < 256; ++i) {
11099
    t[i] = 2;
11100
  }
11101
  for (uint8_t c = 0x21; c <= 0x7E; ++c) {
11102
    t[c] = 0;
11103
  }
11104
  for (uint8_t c : {static_cast<uint8_t>('"'), static_cast<uint8_t>('<'),
11105
                    static_cast<uint8_t>('>'), static_cast<uint8_t>('\'')}) {
11106
    t[c] = 2;
11107
  }
11108
  t[static_cast<uint8_t>('#')] = 1;
11109
  return t;
11110
}();
11111
11112
// Fragment: 0 = copy, 2 = needs work. '?' '#' '%' are copyable.
11113
constexpr std::array<uint8_t, 256> k_hash = []() consteval {
11114
  std::array<uint8_t, 256> t{};
11115
  for (size_t i = 0; i < 256; ++i) {
11116
    t[i] = 2;
11117
  }
11118
  for (uint8_t c = 0x21; c <= 0x7E; ++c) {
11119
    t[c] = 0;
11120
  }
11121
  for (uint8_t c : {static_cast<uint8_t>('"'), static_cast<uint8_t>('<'),
11122
                    static_cast<uint8_t>('>'), static_cast<uint8_t>('`')}) {
11123
    t[c] = 2;
11124
  }
11125
  return t;
11126
}();
11127
11128
// Nibble tables for pshufb / tbl classification (oven-sh/WebKit#454).
11129
// A byte is a stop when low[b & 0xF] & high[b >> 4] != 0. High nibbles whose
11130
// sixteen bytes share a stop pattern share a bit, so any set with at most
11131
// eight distinct patterns fits. Tables are built from the scalar class
11132
// arrays, so the vector and scalar paths cannot disagree.
11133
struct nibble_tables {
11134
  alignas(16) uint8_t low[16]{};
11135
  alignas(16) uint8_t high[16]{};
11136
  bool fits{true};
11137
};
11138
11139
consteval nibble_tables make_stop_nibble_tables(
11140
    const std::array<uint8_t, 256>& cls) {
11141
  nibble_tables t{};
11142
  uint16_t patterns[16]{};
11143
  for (int hi = 0; hi < 16; ++hi) {
11144
    for (int lo = 0; lo < 16; ++lo) {
11145
      if (cls[static_cast<size_t>((hi << 4) | lo)] != 0) {
11146
        patterns[hi] = static_cast<uint16_t>(patterns[hi] | (1u << lo));
11147
      }
11148
    }
11149
  }
11150
  int bits_used = 0;
11151
  for (int hi = 0; hi < 16; ++hi) {
11152
    if (patterns[hi] == 0 || t.high[hi] != 0) {
11153
      continue;
11154
    }
11155
    if (bits_used == 8) {
11156
      t.fits = false;
11157
      return t;
11158
    }
11159
    const uint8_t bit = static_cast<uint8_t>(1u << bits_used++);
11160
    for (int other = hi; other < 16; ++other) {
11161
      if (patterns[other] == patterns[hi]) {
11162
        t.high[other] = static_cast<uint8_t>(t.high[other] | bit);
11163
      }
11164
    }
11165
    for (int lo = 0; lo < 16; ++lo) {
11166
      if ((patterns[hi] & (1u << lo)) != 0) {
11167
        t.low[lo] = static_cast<uint8_t>(t.low[lo] | bit);
11168
      }
11169
    }
11170
  }
11171
  return t;
11172
}
11173
11174
constexpr nibble_tables k_host_nibbles = make_stop_nibble_tables(k_host_class);
11175
constexpr nibble_tables k_path_nibbles = make_stop_nibble_tables(k_path);
11176
constexpr nibble_tables k_query_nibbles = make_stop_nibble_tables(k_query);
11177
constexpr nibble_tables k_hash_nibbles = make_stop_nibble_tables(k_hash);
11178
static_assert(k_host_nibbles.fits);
11179
static_assert(k_path_nibbles.fits);
11180
static_assert(k_query_nibbles.fits);
11181
static_assert(k_hash_nibbles.fits);
11182
11183
// WHATWG serializes a port as its decimal value with no leading zeros.
11184
6.02k
ada_really_inline uint32_t port_decimal_digit_count(uint32_t port) noexcept {
11185
6.02k
  uint32_t digits = 1;
11186
16.6k
  while (port >= 10) {
11187
10.5k
    port /= 10;
11188
10.5k
    ++digits;
11189
10.5k
  }
11190
6.02k
  return digits;
11191
6.02k
}
11192
11193
ada_really_inline void append_canonical_port(std::string& buffer,
11194
3.34k
                                             uint32_t port) {
11195
3.34k
  buffer += ':';
11196
3.34k
  char port_buf[5];
11197
3.34k
  auto [ptr, ec] = std::to_chars(port_buf, port_buf + 5, port);
11198
3.34k
  (void)ec;
11199
3.34k
  buffer.append(port_buf, static_cast<size_t>(ptr - port_buf));
11200
3.34k
}
11201
11202
75.5k
ada_really_inline int trailing_zeroes32(uint32_t input_num) noexcept {
11203
#ifdef ADA_REGULAR_VISUAL_STUDIO
11204
  unsigned long ret;
11205
  _BitScanForward(&ret, input_num);
11206
  return static_cast<int>(ret);
11207
#else
11208
75.5k
  return __builtin_ctz(input_num);
11209
75.5k
#endif
11210
75.5k
}
11211
11212
0
ada_really_inline int trailing_zeroes64(uint64_t input_num) noexcept {
11213
0
#ifdef ADA_REGULAR_VISUAL_STUDIO
11214
0
  unsigned long ret;
11215
0
  _BitScanForward64(&ret, input_num);
11216
0
  return static_cast<int>(ret);
11217
0
#else
11218
0
  return __builtin_ctzll(input_num);
11219
0
#endif
11220
0
}
11221
11222
#if ADA_PARSER_SSSE3
11223
163k
ADA_PARSER_SIMD __m128i nibble_load(const uint8_t* t) noexcept {
11224
163k
  return _mm_load_si128(reinterpret_cast<const __m128i*>(t));
11225
163k
}
11226
11227
// Non-zero lanes are stops. Tables are passed in so the scan loops can hoist
11228
// the loads out of the 16-byte iteration.
11229
ADA_PARSER_SSSE3_FN int ssse3_nibble_mask(__m128i w, __m128i lo_tbl,
11230
101k
                                          __m128i hi_tbl) noexcept {
11231
101k
  const __m128i nibble = _mm_set1_epi8(0x0F);
11232
101k
  const __m128i lo = _mm_and_si128(w, nibble);
11233
101k
  const __m128i hi = _mm_and_si128(_mm_srli_epi16(w, 4), nibble);
11234
101k
  const __m128i hit =
11235
101k
      _mm_and_si128(_mm_shuffle_epi8(lo_tbl, lo), _mm_shuffle_epi8(hi_tbl, hi));
11236
101k
  return _mm_movemask_epi8(_mm_cmpeq_epi8(hit, _mm_setzero_si128())) ^ 0xFFFF;
11237
101k
}
11238
#endif  // ADA_PARSER_SSSE3
11239
11240
#if ADA_SSE2
11241
#if !ADA_PARSER_SSSE3
11242
// Signed < 0x21 matches 0x00-0x20 and 0x80-0xFF; 0x7F is checked separately.
11243
ada_really_inline __m128i sse2_ctrl_or_nonascii(__m128i w) noexcept {
11244
  return _mm_or_si128(_mm_cmplt_epi8(w, _mm_set1_epi8(0x21)),
11245
                      _mm_cmpeq_epi8(w, _mm_set1_epi8(0x7F)));
11246
}
11247
11248
ada_really_inline int sse2_host_stop(__m128i w) noexcept {
11249
  const __m128i ctrl = sse2_ctrl_or_nonascii(w);
11250
  const __m128i is_upper = _mm_and_si128(
11251
      _mm_cmpgt_epi8(w, _mm_set1_epi8(static_cast<char>('A' - 1))),
11252
      _mm_cmplt_epi8(w, _mm_set1_epi8(static_cast<char>('Z' + 1))));
11253
  const __m128i at = _mm_sub_epi8(w, _mm_set1_epi8('@'));
11254
  const __m128i at_through_caret =
11255
      _mm_cmpeq_epi8(_mm_min_epu8(at, _mm_set1_epi8('^' - '@')), at);
11256
  const __m128i at_not_upper = _mm_andnot_si128(is_upper, at_through_caret);
11257
  const __m128i spec = _mm_or_si128(
11258
      _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('#')),
11259
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('%'))),
11260
                   _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('/')),
11261
                                _mm_cmpeq_epi8(w, _mm_set1_epi8(':')))),
11262
      _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('<')),
11263
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('>'))),
11264
                   _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('?')),
11265
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('|')))));
11266
  return _mm_movemask_epi8(
11267
      _mm_or_si128(_mm_or_si128(ctrl, at_not_upper), spec));
11268
}
11269
11270
ada_really_inline int sse2_path_stop(__m128i w) noexcept {
11271
  const __m128i ctrl = sse2_ctrl_or_nonascii(w);
11272
  const __m128i spec = _mm_or_si128(
11273
      _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('"')),
11274
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('#'))),
11275
                   _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('%')),
11276
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('<')))),
11277
      _mm_or_si128(
11278
          _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('>')),
11279
                                    _mm_cmpeq_epi8(w, _mm_set1_epi8('?'))),
11280
                       _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('\\')),
11281
                                    _mm_cmpeq_epi8(w, _mm_set1_epi8('^')))),
11282
          _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('`')),
11283
                                    _mm_cmpeq_epi8(w, _mm_set1_epi8('{'))),
11284
                       _mm_cmpeq_epi8(w, _mm_set1_epi8('}')))));
11285
  return _mm_movemask_epi8(_mm_or_si128(ctrl, spec));
11286
}
11287
11288
ada_really_inline int sse2_query_stop(__m128i w) noexcept {
11289
  const __m128i ctrl = sse2_ctrl_or_nonascii(w);
11290
  const __m128i spec = _mm_or_si128(
11291
      _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('"')),
11292
                   _mm_cmpeq_epi8(w, _mm_set1_epi8('#'))),
11293
      _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('<')),
11294
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('>'))),
11295
                   _mm_cmpeq_epi8(w, _mm_set1_epi8('\''))));
11296
  return _mm_movemask_epi8(_mm_or_si128(ctrl, spec));
11297
}
11298
11299
ada_really_inline int sse2_hash_stop(__m128i w) noexcept {
11300
  const __m128i ctrl = sse2_ctrl_or_nonascii(w);
11301
  const __m128i spec =
11302
      _mm_or_si128(_mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('"')),
11303
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('<'))),
11304
                   _mm_or_si128(_mm_cmpeq_epi8(w, _mm_set1_epi8('>')),
11305
                                _mm_cmpeq_epi8(w, _mm_set1_epi8('`'))));
11306
  return _mm_movemask_epi8(_mm_or_si128(ctrl, spec));
11307
}
11308
#endif  // !ADA_PARSER_SSSE3
11309
11310
64.8k
ada_really_inline int sse2_uppercase(__m128i w) noexcept {
11311
64.8k
  return _mm_movemask_epi8(_mm_and_si128(
11312
64.8k
      _mm_cmpgt_epi8(w, _mm_set1_epi8(static_cast<char>('A' - 1))),
11313
64.8k
      _mm_cmplt_epi8(w, _mm_set1_epi8(static_cast<char>('Z' + 1)))));
11314
64.8k
}
11315
#endif  // ADA_SSE2
11316
11317
#if ADA_NEON
11318
ada_really_inline uint64_t neon_nibble_bits(uint8x16_t matches) noexcept {
11319
  const uint8x8_t nib = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4);
11320
  return vget_lane_u64(vreinterpret_u64_u8(nib), 0);
11321
}
11322
11323
ada_really_inline uint64_t neon_table_stop(uint8x16_t w, uint8x16_t lo_tbl,
11324
                                           uint8x16_t hi_tbl) noexcept {
11325
  const uint8x16_t hit =
11326
      vandq_u8(vqtbl1q_u8(lo_tbl, vandq_u8(w, vdupq_n_u8(0x0F))),
11327
               vqtbl1q_u8(hi_tbl, vshrq_n_u8(w, 4)));
11328
  return neon_nibble_bits(vtstq_u8(hit, hit));
11329
}
11330
11331
ada_really_inline uint64_t neon_uppercase(uint8x16_t w) noexcept {
11332
  return neon_nibble_bits(
11333
      vandq_u8(vcgeq_u8(w, vdupq_n_u8('A')), vcleq_u8(w, vdupq_n_u8('Z'))));
11334
}
11335
#endif  // ADA_NEON
11336
11337
// True when '@' appears in the authority before '/', '?', or '#'.
11338
// One 16-byte window covers typical userinfo (SetHref's "user:pass@").
11339
// Longer userinfo still misses inside the never_inline fast path. No
11340
// '@' is a single load + compare so the parse hot path stays cheap.
11341
ada_really_inline bool authority_has_at(const uint8_t* p, size_t host_start,
11342
1.10M
                                        size_t n) noexcept {
11343
1.10M
  const size_t rem = n - host_start;
11344
1.10M
  if (rem == 0) {
11345
0
    return false;
11346
0
  }
11347
#if ADA_NEON
11348
  if (rem >= 16) {
11349
    const uint8x16_t w = vld1q_u8(p + host_start);
11350
    const uint64_t at = neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('@')));
11351
    if (at == 0) {
11352
      return false;
11353
    }
11354
    const uint64_t delim = neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('/'))) |
11355
                           neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('?'))) |
11356
                           neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('#')));
11357
    return delim == 0 || std::countr_zero(at) < std::countr_zero(delim);
11358
  }
11359
#elif ADA_SSE2
11360
1.10M
  if (rem >= 16) {
11361
68.4k
    const __m128i w =
11362
68.4k
        _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + host_start));
11363
68.4k
    const uint16_t at = static_cast<uint16_t>(
11364
68.4k
        _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('@'))));
11365
68.4k
    if (at == 0) {
11366
65.0k
      return false;
11367
65.0k
    }
11368
3.39k
    const uint16_t delim = static_cast<uint16_t>(
11369
3.39k
        _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('/'))) |
11370
3.39k
        _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('?'))) |
11371
3.39k
        _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('#'))));
11372
3.39k
    return delim == 0 || std::countr_zero(at) < std::countr_zero(delim);
11373
68.4k
  }
11374
1.03M
#endif
11375
1.03M
  const size_t lim = host_start + rem;
11376
8.58M
  for (size_t i = host_start; i < lim; ++i) {
11377
8.26M
    const uint8_t c = p[i];
11378
8.26M
    if (c == '@') {
11379
11.5k
      return true;
11380
11.5k
    }
11381
8.25M
    if (c == '/' || c == '?' || c == '#') {
11382
696k
      return false;
11383
696k
    }
11384
8.25M
  }
11385
324k
  return false;
11386
1.03M
}
11387
11388
#if ADA_PARSER_SSSE3
11389
// True when this process can execute the SSSE3 scanners. When the binary was
11390
// built for SSSE3, the check is a constant. Otherwise it is cached from the
11391
// CPU and the scanners fall back to the scalar loops below.
11392
1.11M
ada_really_inline bool parser_use_ssse3() noexcept {
11393
1.11M
#ifdef ADA_PARSER_NEED_SSSE3_TARGET
11394
1.11M
  static const bool supported = __builtin_cpu_supports("ssse3") != 0;
11395
1.11M
  return supported;
11396
#else
11397
  return true;
11398
#endif
11399
1.11M
}
11400
#endif
11401
11402
// Returns false if a forbidden host code point is found. On success, *end is
11403
// the first / ? # or len. has_upper / has_x only count host bytes, not the
11404
// path/query bytes that may sit in the same SIMD window after the delimiter.
11405
ADA_PARSER_SIMD bool scan_plain_host(const uint8_t* b, size_t start, size_t len,
11406
                                     size_t& end, bool& has_upper,
11407
765k
                                     bool& has_x) noexcept {
11408
765k
  has_upper = false;
11409
765k
  has_x = false;
11410
765k
  size_t i = start;
11411
765k
#if ADA_PARSER_SSSE3
11412
765k
  if (parser_use_ssse3() && (len - start >= 16)) {
11413
59.7k
    const __m128i lo_tbl = nibble_load(k_host_nibbles.low);
11414
59.7k
    const __m128i hi_tbl = nibble_load(k_host_nibbles.high);
11415
59.7k
    const __m128i x_splat = _mm_set1_epi8('x');
11416
64.8k
    auto visit = [&](size_t at) noexcept -> bool {
11417
64.8k
      const __m128i w =
11418
64.8k
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + at));
11419
64.8k
      const int up = sse2_uppercase(w);
11420
64.8k
      const int xs = _mm_movemask_epi8(_mm_cmpeq_epi8(w, x_splat));
11421
64.8k
      const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl);
11422
64.8k
      if (mask == 0) {
11423
5.12k
        if (up != 0) {
11424
3.11k
          has_upper = true;
11425
3.11k
        }
11426
5.12k
        if (xs != 0) {
11427
3.13k
          has_x = true;
11428
3.13k
        }
11429
5.12k
        return false;
11430
5.12k
      }
11431
59.7k
      const int hit = trailing_zeroes32(static_cast<uint32_t>(mask));
11432
59.7k
      const int valid = (1 << hit) - 1;
11433
59.7k
      if ((up & valid) != 0) {
11434
10.8k
        has_upper = true;
11435
10.8k
      }
11436
59.7k
      if ((xs & valid) != 0) {
11437
9.78k
        has_x = true;
11438
9.78k
      }
11439
59.7k
      end = at + static_cast<size_t>(hit);
11440
59.7k
      return true;
11441
64.8k
    };
11442
59.7k
    for (; i + 32 <= len; i += 32) {
11443
15.7k
      if (visit(i) || visit(i + 16)) {
11444
15.7k
        return k_host_class[b[end]] == 1;
11445
15.7k
      }
11446
15.7k
    }
11447
47.8k
    for (; i + 16 <= len; i += 16) {
11448
44.0k
      if (visit(i)) {
11449
40.2k
        return k_host_class[b[end]] == 1;
11450
40.2k
      }
11451
44.0k
    }
11452
    // Overlapping tail only after a full 16-byte step so the window cannot
11453
    // start before `start` (a prior '/' would otherwise look like a host stop).
11454
3.79k
    if (i > start && i < len) {
11455
3.78k
      if (visit(len - 16) && end >= i) {
11456
3.77k
        return k_host_class[b[end]] == 1;
11457
3.77k
      }
11458
17
      end = len;
11459
17
      return true;
11460
3.78k
    }
11461
3.79k
  }
11462
#elif ADA_SSE2
11463
  const __m128i x_splat = _mm_set1_epi8('x');
11464
  for (; i + 32 <= len; i += 32) {
11465
    for (size_t off = 0; off < 32; off += 16) {
11466
      const __m128i w =
11467
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i + off));
11468
      const int up = sse2_uppercase(w);
11469
      const int xs = _mm_movemask_epi8(_mm_cmpeq_epi8(w, x_splat));
11470
      const int mask = sse2_host_stop(w);
11471
      if (mask != 0) {
11472
        const int hit = trailing_zeroes32(static_cast<uint32_t>(mask));
11473
        const int valid = (1 << hit) - 1;
11474
        if ((up & valid) != 0) {
11475
          has_upper = true;
11476
        }
11477
        if ((xs & valid) != 0) {
11478
          has_x = true;
11479
        }
11480
        end = i + off + static_cast<size_t>(hit);
11481
        return k_host_class[b[end]] == 1;
11482
      }
11483
      if (up != 0) {
11484
        has_upper = true;
11485
      }
11486
      if (xs != 0) {
11487
        has_x = true;
11488
      }
11489
    }
11490
  }
11491
  for (; i + 16 <= len; i += 16) {
11492
    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
11493
    const int up = sse2_uppercase(w);
11494
    const int xs = _mm_movemask_epi8(_mm_cmpeq_epi8(w, x_splat));
11495
    const int mask = sse2_host_stop(w);
11496
    if (mask != 0) {
11497
      const int hit = trailing_zeroes32(static_cast<uint32_t>(mask));
11498
      const int valid = (1 << hit) - 1;
11499
      if ((up & valid) != 0) {
11500
        has_upper = true;
11501
      }
11502
      if ((xs & valid) != 0) {
11503
        has_x = true;
11504
      }
11505
      end = i + static_cast<size_t>(hit);
11506
      return k_host_class[b[end]] == 1;
11507
    }
11508
    if (up != 0) {
11509
      has_upper = true;
11510
    }
11511
    if (xs != 0) {
11512
      has_x = true;
11513
    }
11514
  }
11515
#elif ADA_NEON
11516
  if (len - start >= 16) {
11517
    const uint8x16_t lo_tbl = vld1q_u8(k_host_nibbles.low);
11518
    const uint8x16_t hi_tbl = vld1q_u8(k_host_nibbles.high);
11519
    const uint8x16_t x_splat = vdupq_n_u8('x');
11520
    auto visit = [&](size_t at) noexcept -> bool {
11521
      const uint8x16_t w = vld1q_u8(b + at);
11522
      const uint64_t up = neon_uppercase(w);
11523
      const uint64_t xs = neon_nibble_bits(vceqq_u8(w, x_splat));
11524
      const uint64_t bits = neon_table_stop(w, lo_tbl, hi_tbl);
11525
      if (bits == 0) {
11526
        if (up != 0) {
11527
          has_upper = true;
11528
        }
11529
        if (xs != 0) {
11530
          has_x = true;
11531
        }
11532
        return false;
11533
      }
11534
      const size_t hit = static_cast<size_t>(trailing_zeroes64(bits)) >> 2;
11535
      const uint64_t valid = (hit == 0) ? 0 : (uint64_t{1} << (hit * 4)) - 1;
11536
      if ((up & valid) != 0) {
11537
        has_upper = true;
11538
      }
11539
      if ((xs & valid) != 0) {
11540
        has_x = true;
11541
      }
11542
      end = at + hit;
11543
      return true;
11544
    };
11545
    for (; i + 32 <= len; i += 32) {
11546
      if (visit(i) || visit(i + 16)) {
11547
        return k_host_class[b[end]] == 1;
11548
      }
11549
    }
11550
    for (; i + 16 <= len; i += 16) {
11551
      if (visit(i)) {
11552
        return k_host_class[b[end]] == 1;
11553
      }
11554
    }
11555
    if (i > start && i < len) {
11556
      if (visit(len - 16) && end >= i) {
11557
        return k_host_class[b[end]] == 1;
11558
      }
11559
      end = len;
11560
      return true;
11561
    }
11562
  }
11563
#endif
11564
7.77M
  for (; i < len; ++i) {
11565
7.42M
    const uint8_t c = b[i];
11566
7.42M
    const uint8_t cls = k_host_class[c];
11567
7.42M
    if (cls == 1) {
11568
321k
      end = i;
11569
321k
      return true;
11570
321k
    }
11571
7.10M
    if (cls == 2) {
11572
34.0k
      return false;
11573
34.0k
    }
11574
7.07M
    if (c >= 'A' && c <= 'Z') {
11575
23.8k
      has_upper = true;
11576
7.04M
    } else if (c == 'x') {
11577
46.4k
      has_x = true;
11578
46.4k
    }
11579
7.07M
  }
11580
350k
  end = len;
11581
350k
  return true;
11582
706k
}
11583
11584
ada_really_inline void note_possible_dot_segment(
11585
    const uint8_t* b, size_t pos, size_t run_start,
11586
26.8k
    bool& maybe_dot_segment) noexcept {
11587
26.8k
  if (pos == run_start || b[pos - 1] == '/') {
11588
12.3k
    maybe_dot_segment = true;
11589
12.3k
  }
11590
26.8k
}
11591
11592
#if ADA_PARSER_SSSE3 || ADA_SSE2
11593
// valid_mask selects bytes in this 16-byte window that belong to the path
11594
// (bits after a stop are cleared). A '.' starts a possible dot-segment when
11595
// it is the first path byte or immediately follows '/'.
11596
ada_really_inline void note_dots_in_window(const uint8_t* b, size_t i,
11597
                                           size_t run_start, __m128i w,
11598
                                           int valid_mask,
11599
21.6k
                                           bool& maybe_dot_segment) noexcept {
11600
21.6k
  if (maybe_dot_segment || valid_mask == 0) {
11601
3.18k
    return;
11602
3.18k
  }
11603
18.4k
  const int dots =
11604
18.4k
      _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('.'))) & valid_mask;
11605
18.4k
  if (dots == 0) {
11606
4.27k
    return;
11607
4.27k
  }
11608
14.1k
  const int slashes =
11609
14.1k
      _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('/'))) & valid_mask;
11610
14.1k
  if (((dots & 1) != 0 && (i == run_start || b[i - 1] == '/')) ||
11611
11.0k
      (dots & (slashes << 1)) != 0) {
11612
7.41k
    maybe_dot_segment = true;
11613
7.41k
  }
11614
14.1k
}
11615
#endif
11616
11617
#if ADA_NEON
11618
// Each NEON match nibble occupies 4 bits, so a '.' immediately after '/' is
11619
// (slashes << 4) rather than (slashes << 1).
11620
ada_really_inline void note_dots_in_window_neon(
11621
    const uint8_t* b, size_t i, size_t run_start, uint8x16_t w,
11622
    uint64_t valid_bits, bool& maybe_dot_segment) noexcept {
11623
  if (maybe_dot_segment || valid_bits == 0) {
11624
    return;
11625
  }
11626
  const uint64_t dots =
11627
      neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('.'))) & valid_bits;
11628
  if (dots == 0) {
11629
    return;
11630
  }
11631
  const uint64_t slashes =
11632
      neon_nibble_bits(vceqq_u8(w, vdupq_n_u8('/'))) & valid_bits;
11633
  if (((dots & 0xF) != 0 && (i == run_start || b[i - 1] == '/')) ||
11634
      (dots & (slashes << 4)) != 0) {
11635
    maybe_dot_segment = true;
11636
  }
11637
}
11638
#endif
11639
11640
// Advance i to the first path-class 1 or 2 character (or len).
11641
ADA_PARSER_SIMD void scan_path_run(const uint8_t* b, size_t& i, size_t len,
11642
325k
                                   bool& maybe_dot_segment) noexcept {
11643
325k
  const size_t run_start = i;
11644
325k
#if ADA_PARSER_SSSE3
11645
325k
  if (parser_use_ssse3() && (i + 16 <= len)) {
11646
15.1k
    const __m128i lo_tbl = nibble_load(k_path_nibbles.low);
11647
15.1k
    const __m128i hi_tbl = nibble_load(k_path_nibbles.high);
11648
18.1k
    for (; i + 32 <= len; i += 32) {
11649
7.43k
      const __m128i w0 =
11650
7.43k
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
11651
7.43k
      const int m0 = ssse3_nibble_mask(w0, lo_tbl, hi_tbl);
11652
7.43k
      if (m0 != 0) {
11653
2.20k
        const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(m0));
11654
2.20k
        note_dots_in_window(b, i, run_start, w0, (1 << hit_bit) - 1,
11655
2.20k
                            maybe_dot_segment);
11656
2.20k
        i += static_cast<size_t>(hit_bit);
11657
2.20k
        return;
11658
2.20k
      }
11659
5.22k
      note_dots_in_window(b, i, run_start, w0, 0xFFFF, maybe_dot_segment);
11660
5.22k
      const __m128i w1 =
11661
5.22k
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i + 16));
11662
5.22k
      const int m1 = ssse3_nibble_mask(w1, lo_tbl, hi_tbl);
11663
5.22k
      if (m1 != 0) {
11664
2.27k
        const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(m1));
11665
2.27k
        note_dots_in_window(b, i + 16, run_start, w1, (1 << hit_bit) - 1,
11666
2.27k
                            maybe_dot_segment);
11667
2.27k
        i += 16 + static_cast<size_t>(hit_bit);
11668
2.27k
        return;
11669
2.27k
      }
11670
2.95k
      note_dots_in_window(b, i + 16, run_start, w1, 0xFFFF, maybe_dot_segment);
11671
2.95k
    }
11672
16.4k
    for (; i + 16 <= len; i += 16) {
11673
8.95k
      const __m128i w =
11674
8.95k
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
11675
8.95k
      const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl);
11676
8.95k
      if (mask != 0) {
11677
3.24k
        const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(mask));
11678
3.24k
        note_dots_in_window(b, i, run_start, w, (1 << hit_bit) - 1,
11679
3.24k
                            maybe_dot_segment);
11680
3.24k
        i += static_cast<size_t>(hit_bit);
11681
3.24k
        return;
11682
3.24k
      }
11683
5.70k
      note_dots_in_window(b, i, run_start, w, 0xFFFF, maybe_dot_segment);
11684
5.70k
    }
11685
7.45k
    if (i > run_start && i < len) {
11686
5.45k
      const __m128i w =
11687
5.45k
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + len - 16));
11688
5.45k
      const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl);
11689
5.45k
      if (mask != 0) {
11690
2.50k
        const size_t hit =
11691
2.50k
            len - 16 +
11692
2.50k
            static_cast<size_t>(trailing_zeroes32(static_cast<uint32_t>(mask)));
11693
2.50k
        if (hit >= i) {
11694
9.85k
          for (size_t j = i; j < hit; ++j) {
11695
7.34k
            if (b[j] == '.') {
11696
2.76k
              note_possible_dot_segment(b, j, run_start, maybe_dot_segment);
11697
2.76k
            }
11698
7.34k
          }
11699
2.50k
          i = hit;
11700
2.50k
          return;
11701
2.50k
        }
11702
2.50k
      }
11703
20.3k
      for (size_t j = i; j < len; ++j) {
11704
17.3k
        if (b[j] == '.') {
11705
5.80k
          note_possible_dot_segment(b, j, run_start, maybe_dot_segment);
11706
5.80k
        }
11707
17.3k
      }
11708
2.94k
      i = len;
11709
2.94k
      return;
11710
5.45k
    }
11711
7.45k
  }
11712
#elif ADA_SSE2
11713
  for (; i + 16 <= len; i += 16) {
11714
    const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));
11715
    const int mask = sse2_path_stop(w);
11716
    if (mask != 0) {
11717
      const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(mask));
11718
      note_dots_in_window(b, i, run_start, w, (1 << hit_bit) - 1,
11719
                          maybe_dot_segment);
11720
      i += static_cast<size_t>(hit_bit);
11721
      return;
11722
    }
11723
    note_dots_in_window(b, i, run_start, w, 0xFFFF, maybe_dot_segment);
11724
  }
11725
#elif ADA_NEON
11726
  if (i + 16 <= len) {
11727
    const uint8x16_t lo_tbl = vld1q_u8(k_path_nibbles.low);
11728
    const uint8x16_t hi_tbl = vld1q_u8(k_path_nibbles.high);
11729
    for (; i + 32 <= len; i += 32) {
11730
      const uint8x16_t w0 = vld1q_u8(b + i);
11731
      const uint64_t bits0 = neon_table_stop(w0, lo_tbl, hi_tbl);
11732
      if (bits0 != 0) {
11733
        const size_t hit_off =
11734
            static_cast<size_t>(trailing_zeroes64(bits0)) >> 2;
11735
        const uint64_t valid =
11736
            (hit_off == 0) ? 0 : (uint64_t{1} << (hit_off * 4)) - 1;
11737
        note_dots_in_window_neon(b, i, run_start, w0, valid, maybe_dot_segment);
11738
        i += hit_off;
11739
        return;
11740
      }
11741
      note_dots_in_window_neon(b, i, run_start, w0, ~uint64_t{0},
11742
                               maybe_dot_segment);
11743
      const uint8x16_t w1 = vld1q_u8(b + i + 16);
11744
      const uint64_t bits1 = neon_table_stop(w1, lo_tbl, hi_tbl);
11745
      if (bits1 != 0) {
11746
        const size_t hit_off =
11747
            static_cast<size_t>(trailing_zeroes64(bits1)) >> 2;
11748
        const uint64_t valid =
11749
            (hit_off == 0) ? 0 : (uint64_t{1} << (hit_off * 4)) - 1;
11750
        note_dots_in_window_neon(b, i + 16, run_start, w1, valid,
11751
                                 maybe_dot_segment);
11752
        i += 16 + hit_off;
11753
        return;
11754
      }
11755
      note_dots_in_window_neon(b, i + 16, run_start, w1, ~uint64_t{0},
11756
                               maybe_dot_segment);
11757
    }
11758
    for (; i + 16 <= len; i += 16) {
11759
      const uint8x16_t w = vld1q_u8(b + i);
11760
      const uint64_t bits = neon_table_stop(w, lo_tbl, hi_tbl);
11761
      if (bits != 0) {
11762
        const size_t hit_off =
11763
            static_cast<size_t>(trailing_zeroes64(bits)) >> 2;
11764
        const uint64_t valid =
11765
            (hit_off == 0) ? 0 : (uint64_t{1} << (hit_off * 4)) - 1;
11766
        note_dots_in_window_neon(b, i, run_start, w, valid, maybe_dot_segment);
11767
        i += hit_off;
11768
        return;
11769
      }
11770
      note_dots_in_window_neon(b, i, run_start, w, ~uint64_t{0},
11771
                               maybe_dot_segment);
11772
    }
11773
    if (i > run_start && i < len) {
11774
      const uint8x16_t w = vld1q_u8(b + len - 16);
11775
      const uint64_t bits = neon_table_stop(w, lo_tbl, hi_tbl);
11776
      if (bits != 0) {
11777
        const size_t hit =
11778
            len - 16 + (static_cast<size_t>(trailing_zeroes64(bits)) >> 2);
11779
        if (hit >= i) {
11780
          for (size_t j = i; j < hit; ++j) {
11781
            if (b[j] == '.') {
11782
              note_possible_dot_segment(b, j, run_start, maybe_dot_segment);
11783
            }
11784
          }
11785
          i = hit;
11786
          return;
11787
        }
11788
      }
11789
      for (size_t j = i; j < len; ++j) {
11790
        if (b[j] == '.') {
11791
          note_possible_dot_segment(b, j, run_start, maybe_dot_segment);
11792
        }
11793
      }
11794
      i = len;
11795
      return;
11796
    }
11797
  }
11798
#endif
11799
372k
  for (; i < len; ++i) {
11800
70.7k
    const uint8_t c = b[i];
11801
70.7k
    const uint8_t cls = k_path[c];
11802
70.7k
    if (cls != 0) {
11803
10.5k
      return;
11804
10.5k
    }
11805
60.2k
    if (c == '.') {
11806
18.3k
      note_possible_dot_segment(b, i, run_start, maybe_dot_segment);
11807
18.3k
    }
11808
60.2k
  }
11809
311k
}
11810
11811
// Advance i to the first class-table stop (or len). Query and hash share
11812
// this loop; path keeps its own copy because it also tracks '.' segments.
11813
#if ADA_PARSER_SSSE3
11814
#define ADA_SCAN_STOP_RUN(nibbles, cls, unused_sse2_stop)                    \
11815
20.5k
  do {                                                                       \
11816
20.5k
    const size_t scan_start = i;                                             \
11817
20.5k
    if (parser_use_ssse3() && (i + 16 <= len)) {                             \
11818
6.69k
      const __m128i lo_tbl = nibble_load((nibbles).low);                     \
11819
6.69k
      const __m128i hi_tbl = nibble_load((nibbles).high);                    \
11820
7.05k
      for (; i + 32 <= len; i += 32) {                                       \
11821
3.17k
        const __m128i w0 =                                                   \
11822
3.17k
            _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));        \
11823
3.17k
        const int m0 = ssse3_nibble_mask(w0, lo_tbl, hi_tbl);                \
11824
3.17k
        if (m0 != 0) {                                                       \
11825
1.62k
          i += static_cast<size_t>(                                          \
11826
1.62k
              trailing_zeroes32(static_cast<uint32_t>(m0)));                 \
11827
1.62k
          return;                                                            \
11828
1.62k
        }                                                                    \
11829
3.17k
        const __m128i w1 =                                                   \
11830
1.55k
            _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i + 16));   \
11831
1.55k
        const int m1 = ssse3_nibble_mask(w1, lo_tbl, hi_tbl);                \
11832
1.55k
        if (m1 != 0) {                                                       \
11833
1.18k
          i += 16 + static_cast<size_t>(                                     \
11834
1.18k
                        trailing_zeroes32(static_cast<uint32_t>(m1)));       \
11835
1.18k
          return;                                                            \
11836
1.18k
        }                                                                    \
11837
1.55k
      }                                                                      \
11838
6.69k
      for (; i + 16 <= len; i += 16) {                                       \
11839
3.51k
        const __m128i w =                                                    \
11840
3.51k
            _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i));        \
11841
3.51k
        const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl);               \
11842
3.51k
        if (mask != 0) {                                                     \
11843
1.72k
          i += static_cast<size_t>(                                          \
11844
1.72k
              trailing_zeroes32(static_cast<uint32_t>(mask)));               \
11845
1.72k
          return;                                                            \
11846
1.72k
        }                                                                    \
11847
3.51k
      }                                                                      \
11848
3.88k
      if (i > scan_start && i < len) {                                       \
11849
1.59k
        const __m128i w =                                                    \
11850
1.59k
            _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + len - 16)); \
11851
1.59k
        const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl);               \
11852
1.59k
        if (mask != 0) {                                                     \
11853
1.03k
          const size_t hit = len - 16 +                                      \
11854
1.03k
                             static_cast<size_t>(trailing_zeroes32(          \
11855
1.03k
                                 static_cast<uint32_t>(mask)));              \
11856
1.03k
          if (hit >= i) {                                                    \
11857
1.03k
            i = hit;                                                         \
11858
1.03k
            return;                                                          \
11859
1.03k
          }                                                                  \
11860
1.03k
        }                                                                    \
11861
1.59k
        i = len;                                                             \
11862
564
        return;                                                              \
11863
1.59k
      }                                                                      \
11864
2.16k
    }                                                                        \
11865
34.2k
    for (; i < len; ++i) {                                                   \
11866
25.3k
      if ((cls)[b[i]] != 0) {                                                \
11867
5.55k
        return;                                                              \
11868
5.55k
      }                                                                      \
11869
25.3k
    }                                                                        \
11870
14.3k
  } while (0)
11871
#elif ADA_NEON
11872
#define ADA_SCAN_STOP_RUN(nibbles, cls, unused_sse2_stop)                     \
11873
  do {                                                                        \
11874
    const size_t scan_start = i;                                              \
11875
    if (i + 16 <= len) {                                                      \
11876
      const uint8x16_t lo_tbl = vld1q_u8((nibbles).low);                      \
11877
      const uint8x16_t hi_tbl = vld1q_u8((nibbles).high);                     \
11878
      for (; i + 32 <= len; i += 32) {                                        \
11879
        const uint64_t bits0 =                                                \
11880
            neon_table_stop(vld1q_u8(b + i), lo_tbl, hi_tbl);                 \
11881
        if (bits0 != 0) {                                                     \
11882
          i += static_cast<size_t>(trailing_zeroes64(bits0)) >> 2;            \
11883
          return;                                                             \
11884
        }                                                                     \
11885
        const uint64_t bits1 =                                                \
11886
            neon_table_stop(vld1q_u8(b + i + 16), lo_tbl, hi_tbl);            \
11887
        if (bits1 != 0) {                                                     \
11888
          i += 16 + (static_cast<size_t>(trailing_zeroes64(bits1)) >> 2);     \
11889
          return;                                                             \
11890
        }                                                                     \
11891
      }                                                                       \
11892
      for (; i + 16 <= len; i += 16) {                                        \
11893
        const uint8x16_t w = vld1q_u8(b + i);                                 \
11894
        const uint64_t bits = neon_table_stop(w, lo_tbl, hi_tbl);             \
11895
        if (bits != 0) {                                                      \
11896
          i += static_cast<size_t>(trailing_zeroes64(bits)) >> 2;             \
11897
          return;                                                             \
11898
        }                                                                     \
11899
      }                                                                       \
11900
      if (i > scan_start && i < len) {                                        \
11901
        const uint8x16_t w = vld1q_u8(b + len - 16);                          \
11902
        const uint64_t bits = neon_table_stop(w, lo_tbl, hi_tbl);             \
11903
        if (bits != 0) {                                                      \
11904
          const size_t hit =                                                  \
11905
              len - 16 + (static_cast<size_t>(trailing_zeroes64(bits)) >> 2); \
11906
          if (hit >= i) {                                                     \
11907
            i = hit;                                                          \
11908
            return;                                                           \
11909
          }                                                                   \
11910
        }                                                                     \
11911
        i = len;                                                              \
11912
        return;                                                               \
11913
      }                                                                       \
11914
    }                                                                         \
11915
    for (; i < len; ++i) {                                                    \
11916
      if ((cls)[b[i]] != 0) {                                                 \
11917
        return;                                                               \
11918
      }                                                                       \
11919
    }                                                                         \
11920
  } while (0)
11921
#elif ADA_SSE2
11922
#define ADA_SCAN_STOP_RUN(nibbles, cls, sse2_stop)                  \
11923
  do {                                                              \
11924
    for (; i + 16 <= len; i += 16) {                                \
11925
      const __m128i w =                                             \
11926
          _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i)); \
11927
      const int mask = sse2_stop(w);                                \
11928
      if (mask != 0) {                                              \
11929
        i += static_cast<size_t>(                                   \
11930
            trailing_zeroes32(static_cast<uint32_t>(mask)));        \
11931
        return;                                                     \
11932
      }                                                             \
11933
    }                                                               \
11934
    for (; i < len; ++i) {                                          \
11935
      if ((cls)[b[i]] != 0) {                                       \
11936
        return;                                                     \
11937
      }                                                             \
11938
    }                                                               \
11939
  } while (0)
11940
#else
11941
#define ADA_SCAN_STOP_RUN(nibbles, cls, unused_sse2_stop) \
11942
  do {                                                    \
11943
    for (; i < len; ++i) {                                \
11944
      if ((cls)[b[i]] != 0) {                             \
11945
        return;                                           \
11946
      }                                                   \
11947
    }                                                     \
11948
  } while (0)
11949
#endif
11950
11951
ADA_PARSER_SIMD void scan_query_run(const uint8_t* b, size_t& i,
11952
10.9k
                                    size_t len) noexcept {
11953
10.9k
  ADA_SCAN_STOP_RUN(k_query_nibbles, k_query, sse2_query_stop);
11954
10.9k
}
11955
11956
ADA_PARSER_SIMD void scan_hash_run(const uint8_t* b, size_t& i,
11957
9.61k
                                   size_t len) noexcept {
11958
9.61k
  ADA_SCAN_STOP_RUN(k_hash_nibbles, k_hash, sse2_hash_stop);
11959
9.61k
}
11960
11961
#undef ADA_SCAN_STOP_RUN
11962
11963
12.1k
bool path_has_dot_segment(std::string_view path) noexcept {
11964
12.1k
  if (path.empty()) {
11965
0
    return false;
11966
0
  }
11967
  // "." / ".." at the start, with or without a leading '/'.
11968
12.1k
  const size_t i = (path[0] == '/') ? 1 : 0;
11969
12.1k
  if (i < path.size() && path[i] == '.') {
11970
6.30k
    const size_t after = i + 1;
11971
6.30k
    if (after == path.size() || path[after] == '/' ||
11972
5.28k
        (after < path.size() && path[after] == '.' &&
11973
3.90k
         (after + 1 == path.size() || path[after + 1] == '/'))) {
11974
3.90k
      return true;
11975
3.90k
    }
11976
6.30k
  }
11977
8.27k
  static constexpr std::string_view slash_dot{"/.", 2};
11978
8.27k
  size_t p = i;
11979
11.4k
  while ((p = path.find(slash_dot, p)) != std::string_view::npos) {
11980
7.50k
    const size_t after = p + 2;
11981
7.50k
    if (after == path.size() || path[after] == '/' ||
11982
4.53k
        (after < path.size() && path[after] == '.' &&
11983
4.37k
         (after + 1 == path.size() || path[after + 1] == '/'))) {
11984
4.37k
      return true;
11985
4.37k
    }
11986
3.13k
    p = after;
11987
3.13k
  }
11988
3.90k
  return false;
11989
8.27k
}
11990
11991
}  // namespace
11992
11993
template <class result_type>
11994
ada_never_inline bool finish_simple_absolute_with_port(
11995
    std::string_view input, result_type& out, ada::scheme::type scheme_type,
11996
    uint32_t protocol_end, size_t host_start, size_t host_end, size_t host_len,
11997
22.9k
    bool has_upper) {
11998
22.9k
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
11999
22.9k
  constexpr bool is_aggregator =
12000
22.9k
      std::is_same_v<result_type, ada::url_aggregator>;
12001
22.9k
  static_assert(is_ada_url || is_aggregator);
12002
12003
22.9k
  const size_t len = input.size();
12004
22.9k
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12005
22.9k
  size_t p = host_end + 1;
12006
22.9k
  uint32_t port_value = 0;
12007
22.9k
  bool any_digit = false;
12008
44.2k
  while (p < len && b[p] >= '0' && b[p] <= '9') {
12009
21.7k
    any_digit = true;
12010
21.7k
    port_value = port_value * 10 + static_cast<uint32_t>(b[p] - '0');
12011
21.7k
    if (port_value > 65535) [[unlikely]] {
12012
398
      return false;
12013
398
    }
12014
21.3k
    ++p;
12015
21.3k
  }
12016
22.5k
  if (p < len && b[p] != '/' && b[p] != '?' && b[p] != '#') [[unlikely]] {
12017
1.81k
    return false;
12018
1.81k
  }
12019
20.7k
  uint32_t parsed_port = url_components::omitted;
12020
20.7k
  const uint16_t default_port = ada::scheme::get_special_port(scheme_type);
12021
20.7k
  if (any_digit && port_value != default_port) {
12022
6.15k
    parsed_port = port_value;
12023
6.15k
  }
12024
20.7k
  const size_t authority_end = p;
12025
12026
20.7k
  size_t i = authority_end;
12027
20.7k
  size_t path_start = host_end;
12028
20.7k
  size_t path_end = host_end;
12029
20.7k
  size_t query_start = std::string_view::npos;
12030
20.7k
  size_t hash_start = std::string_view::npos;
12031
20.7k
  bool has_path = false;
12032
20.7k
  bool maybe_dot_segment = false;
12033
20.7k
  bool rest_simple = true;
12034
12035
20.7k
  if (i < len && b[i] == '/') {
12036
15.6k
    has_path = true;
12037
15.6k
    path_start = i;
12038
15.6k
    ++i;
12039
15.6k
    scan_path_run(b, i, len, maybe_dot_segment);
12040
15.6k
    if (i < len) {
12041
7.57k
      const uint8_t cls = k_path[b[i]];
12042
7.57k
      if (cls == 1) {
12043
1.35k
        path_end = i;
12044
1.35k
        if (b[i] == '?') {
12045
712
          query_start = i;
12046
712
          ++i;
12047
712
          goto scan_query;
12048
712
        }
12049
647
        hash_start = i;
12050
647
        ++i;
12051
647
        goto scan_hash;
12052
1.35k
      }
12053
6.21k
      rest_simple = false;
12054
54.2k
      for (; i < len; ++i) {
12055
48.9k
        if (b[i] == '?') {
12056
471
          path_end = i;
12057
471
          query_start = i;
12058
471
          ++i;
12059
471
          goto scan_query_boundary;
12060
471
        }
12061
48.4k
        if (b[i] == '#') {
12062
400
          path_end = i;
12063
400
          hash_start = i;
12064
400
          ++i;
12065
400
          goto after_rest;
12066
400
        }
12067
48.4k
      }
12068
5.34k
      path_end = i;
12069
5.34k
      goto after_rest;
12070
6.21k
    }
12071
8.08k
    path_end = i;
12072
8.08k
  } else if (i < len && b[i] == '?') {
12073
2.60k
    query_start = i;
12074
2.60k
    ++i;
12075
2.60k
    goto scan_query;
12076
2.60k
  } else if (i < len && b[i] == '#') {
12077
2.39k
    hash_start = i;
12078
2.39k
    ++i;
12079
2.39k
    goto scan_hash;
12080
2.39k
  }
12081
8.14k
  goto after_rest;
12082
12083
8.14k
scan_query:
12084
3.31k
  scan_query_run(b, i, len);
12085
3.31k
  if (i < len) {
12086
2.23k
    if (b[i] == '#') {
12087
216
      hash_start = i;
12088
216
      ++i;
12089
216
      goto scan_hash;
12090
216
    }
12091
2.01k
    rest_simple = false;
12092
2.01k
    goto scan_query_boundary;
12093
2.23k
  }
12094
1.07k
  goto after_rest;
12095
12096
2.49k
scan_query_boundary:
12097
25.8k
  for (; i < len; ++i) {
12098
23.7k
    if (b[i] == '#') {
12099
388
      hash_start = i;
12100
388
      ++i;
12101
388
      goto after_rest;
12102
388
    }
12103
23.7k
  }
12104
2.10k
  goto after_rest;
12105
12106
3.26k
scan_hash:
12107
3.26k
  scan_hash_run(b, i, len);
12108
3.26k
  if (i < len) {
12109
1.47k
    rest_simple = false;
12110
1.47k
  }
12111
12112
20.7k
after_rest:
12113
20.7k
  if (rest_simple && maybe_dot_segment) {
12114
1.81k
    const std::string_view path_body(input.data() + path_start,
12115
1.81k
                                     path_end - path_start);
12116
1.81k
    if (path_has_dot_segment(path_body)) {
12117
1.09k
      rest_simple = false;
12118
1.09k
    }
12119
1.81k
  }
12120
12121
  // The slow path removes ASCII tab/newline anywhere in the input and trims a
12122
  // trailing C0 control or space; this fast path does neither. A query or
12123
  // fragment reaching the helpers below would keep those bytes percent-encoded
12124
  // ("?a\nb" -> "?a%0Ab", "#f " -> "#f%20") instead of stripped, so hand such
12125
  // inputs back to the slow path.
12126
20.7k
  if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) ||
12127
10.0k
                       unicode::has_tabs_or_newline(input))) {
12128
1.89k
    return false;
12129
1.89k
  }
12130
12131
18.8k
  out.type = scheme_type;
12132
18.8k
  out.is_valid = true;
12133
18.8k
  out.has_opaque_path = false;
12134
18.8k
  out.host_type = DEFAULT;
12135
12136
18.8k
  const uint32_t port_bytes = (parsed_port != url_components::omitted)
12137
18.8k
                                  ? (1 + port_decimal_digit_count(parsed_port))
12138
18.8k
                                  : 0;
12139
12140
18.8k
  if (!rest_simple) {
12141
8.90k
    const std::string_view path_view =
12142
8.90k
        has_path
12143
8.90k
            ? std::string_view(input.data() + path_start, path_end - path_start)
12144
8.90k
            : std::string_view{};
12145
8.90k
    auto apply_query_and_hash = [&]() {
12146
8.90k
      if (query_start != std::string_view::npos) {
12147
2.07k
        const size_t q_end =
12148
2.07k
            (hash_start != std::string_view::npos) ? hash_start : len;
12149
2.07k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12150
2.07k
                                                q_end - query_start - 1),
12151
2.07k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12152
2.07k
      }
12153
8.90k
      if (hash_start != std::string_view::npos) {
12154
2.07k
        out.update_unencoded_base_hash(std::string_view(
12155
2.07k
            input.data() + hash_start + 1, len - hash_start - 1));
12156
2.07k
      }
12157
8.90k
    };
Unexecuted instantiation: ada::parser::finish_simple_absolute_with_port<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url&, ada::scheme::type, unsigned int, unsigned long, unsigned long, unsigned long, bool)::{lambda()#1}::operator()() const
ada::parser::finish_simple_absolute_with_port<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator&, ada::scheme::type, unsigned int, unsigned long, unsigned long, unsigned long, bool)::{lambda()#1}::operator()() const
Line
Count
Source
12145
8.90k
    auto apply_query_and_hash = [&]() {
12146
8.90k
      if (query_start != std::string_view::npos) {
12147
2.07k
        const size_t q_end =
12148
2.07k
            (hash_start != std::string_view::npos) ? hash_start : len;
12149
2.07k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12150
2.07k
                                                q_end - query_start - 1),
12151
2.07k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12152
2.07k
      }
12153
8.90k
      if (hash_start != std::string_view::npos) {
12154
2.07k
        out.update_unencoded_base_hash(std::string_view(
12155
2.07k
            input.data() + hash_start + 1, len - hash_start - 1));
12156
2.07k
      }
12157
8.90k
    };
12158
8.90k
    if constexpr (is_aggregator) {
12159
8.90k
      out.buffer.assign(input.substr(0, host_end));
12160
8.90k
      if (parsed_port != url_components::omitted) {
12161
2.12k
        append_canonical_port(out.buffer, parsed_port);
12162
2.12k
      }
12163
8.90k
      if (has_upper) {
12164
1.69k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12165
1.69k
      }
12166
8.90k
      out.components.protocol_end = protocol_end;
12167
8.90k
      out.components.username_end = protocol_end + 2;
12168
8.90k
      out.components.host_start = protocol_end + 2;
12169
8.90k
      out.components.host_end = static_cast<uint32_t>(host_end);
12170
8.90k
      out.components.port = parsed_port;
12171
8.90k
      out.components.pathname_start = static_cast<uint32_t>(out.buffer.size());
12172
8.90k
      out.components.search_start = url_components::omitted;
12173
8.90k
      out.components.hash_start = url_components::omitted;
12174
8.90k
      out.parse_path(path_view);
12175
8.90k
      apply_query_and_hash();
12176
8.90k
    } else {
12177
0
      std::string host_str(input.substr(host_start, host_len));
12178
0
      if (has_upper) {
12179
0
        unicode::to_lower_ascii(host_str.data(), host_str.size());
12180
0
      }
12181
0
      out.host = std::move(host_str);
12182
0
      if (parsed_port != url_components::omitted) {
12183
0
        out.port = static_cast<uint16_t>(parsed_port);
12184
0
      }
12185
0
      out.parse_path(path_view);
12186
0
      apply_query_and_hash();
12187
0
    }
12188
8.90k
    return true;
12189
8.90k
  }
12190
12191
9.91k
  const bool insert_slash = !has_path;
12192
9.91k
  if constexpr (is_aggregator) {
12193
9.91k
    const size_t out_len =
12194
9.91k
        host_end + port_bytes + (insert_slash ? 1 : 0) + (len - authority_end);
12195
9.91k
    const bool omit_port_bytes = parsed_port == url_components::omitted;
12196
9.91k
    if (out_len == len && !insert_slash && !omit_port_bytes) {
12197
2.68k
      out.buffer.assign(input);
12198
7.22k
    } else {
12199
7.22k
      out.buffer.clear();
12200
7.22k
      out.buffer.reserve(out_len);
12201
7.22k
      out.buffer.append(input.substr(0, host_end));
12202
7.22k
      if (parsed_port != url_components::omitted) {
12203
1.22k
        append_canonical_port(out.buffer, parsed_port);
12204
1.22k
      }
12205
7.22k
      if (insert_slash) {
12206
1.94k
        out.buffer.push_back('/');
12207
1.94k
      }
12208
7.22k
      if (authority_end < len) {
12209
7.17k
        out.buffer.append(input.substr(authority_end));
12210
7.17k
      }
12211
7.22k
    }
12212
9.91k
    if (has_upper) {
12213
2.91k
      unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12214
2.91k
    }
12215
9.91k
    const uint32_t pathname_start =
12216
9.91k
        static_cast<uint32_t>(host_end) + port_bytes;
12217
9.91k
    const int32_t tail_delta = static_cast<int32_t>(pathname_start) +
12218
9.91k
                               (insert_slash ? 1 : 0) -
12219
9.91k
                               static_cast<int32_t>(authority_end);
12220
9.91k
    out.components.protocol_end = protocol_end;
12221
9.91k
    out.components.username_end = protocol_end + 2;
12222
9.91k
    out.components.host_start = protocol_end + 2;
12223
9.91k
    out.components.host_end = static_cast<uint32_t>(host_end);
12224
9.91k
    out.components.port = parsed_port;
12225
9.91k
    out.components.pathname_start = pathname_start;
12226
9.91k
    out.components.search_start =
12227
9.91k
        (query_start != std::string_view::npos)
12228
9.91k
            ? static_cast<uint32_t>(static_cast<int32_t>(query_start) +
12229
1.20k
                                    tail_delta)
12230
9.91k
            : url_components::omitted;
12231
9.91k
    out.components.hash_start =
12232
9.91k
        (hash_start != std::string_view::npos)
12233
9.91k
            ? static_cast<uint32_t>(static_cast<int32_t>(hash_start) +
12234
1.68k
                                    tail_delta)
12235
9.91k
            : url_components::omitted;
12236
9.91k
  } else {
12237
0
    std::string host_str(input.substr(host_start, host_len));
12238
0
    if (has_upper) {
12239
0
      unicode::to_lower_ascii(host_str.data(), host_str.size());
12240
0
    }
12241
0
    out.host = std::move(host_str);
12242
0
    if (parsed_port != url_components::omitted) {
12243
0
      out.port = static_cast<uint16_t>(parsed_port);
12244
0
    }
12245
0
    if (insert_slash) {
12246
0
      out.path = "/";
12247
0
    } else {
12248
0
      out.path.assign(input.data() + path_start, path_end - path_start);
12249
0
    }
12250
0
    if (query_start != std::string_view::npos) {
12251
0
      const size_t q_end =
12252
0
          (hash_start != std::string_view::npos) ? hash_start : len;
12253
0
      out.query.emplace(input.data() + query_start + 1,
12254
0
                        q_end - query_start - 1);
12255
0
    }
12256
0
    if (hash_start != std::string_view::npos) {
12257
0
      out.hash.emplace(input.data() + hash_start + 1, len - hash_start - 1);
12258
0
    }
12259
0
  }
12260
9.91k
  return true;
12261
18.8k
}
Unexecuted instantiation: bool ada::parser::finish_simple_absolute_with_port<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url&, ada::scheme::type, unsigned int, unsigned long, unsigned long, unsigned long, bool)
bool ada::parser::finish_simple_absolute_with_port<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator&, ada::scheme::type, unsigned int, unsigned long, unsigned long, unsigned long, bool)
Line
Count
Source
11997
22.9k
    bool has_upper) {
11998
22.9k
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
11999
22.9k
  constexpr bool is_aggregator =
12000
22.9k
      std::is_same_v<result_type, ada::url_aggregator>;
12001
22.9k
  static_assert(is_ada_url || is_aggregator);
12002
12003
22.9k
  const size_t len = input.size();
12004
22.9k
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12005
22.9k
  size_t p = host_end + 1;
12006
22.9k
  uint32_t port_value = 0;
12007
22.9k
  bool any_digit = false;
12008
44.2k
  while (p < len && b[p] >= '0' && b[p] <= '9') {
12009
21.7k
    any_digit = true;
12010
21.7k
    port_value = port_value * 10 + static_cast<uint32_t>(b[p] - '0');
12011
21.7k
    if (port_value > 65535) [[unlikely]] {
12012
398
      return false;
12013
398
    }
12014
21.3k
    ++p;
12015
21.3k
  }
12016
22.5k
  if (p < len && b[p] != '/' && b[p] != '?' && b[p] != '#') [[unlikely]] {
12017
1.81k
    return false;
12018
1.81k
  }
12019
20.7k
  uint32_t parsed_port = url_components::omitted;
12020
20.7k
  const uint16_t default_port = ada::scheme::get_special_port(scheme_type);
12021
20.7k
  if (any_digit && port_value != default_port) {
12022
6.15k
    parsed_port = port_value;
12023
6.15k
  }
12024
20.7k
  const size_t authority_end = p;
12025
12026
20.7k
  size_t i = authority_end;
12027
20.7k
  size_t path_start = host_end;
12028
20.7k
  size_t path_end = host_end;
12029
20.7k
  size_t query_start = std::string_view::npos;
12030
20.7k
  size_t hash_start = std::string_view::npos;
12031
20.7k
  bool has_path = false;
12032
20.7k
  bool maybe_dot_segment = false;
12033
20.7k
  bool rest_simple = true;
12034
12035
20.7k
  if (i < len && b[i] == '/') {
12036
15.6k
    has_path = true;
12037
15.6k
    path_start = i;
12038
15.6k
    ++i;
12039
15.6k
    scan_path_run(b, i, len, maybe_dot_segment);
12040
15.6k
    if (i < len) {
12041
7.57k
      const uint8_t cls = k_path[b[i]];
12042
7.57k
      if (cls == 1) {
12043
1.35k
        path_end = i;
12044
1.35k
        if (b[i] == '?') {
12045
712
          query_start = i;
12046
712
          ++i;
12047
712
          goto scan_query;
12048
712
        }
12049
647
        hash_start = i;
12050
647
        ++i;
12051
647
        goto scan_hash;
12052
1.35k
      }
12053
6.21k
      rest_simple = false;
12054
54.2k
      for (; i < len; ++i) {
12055
48.9k
        if (b[i] == '?') {
12056
471
          path_end = i;
12057
471
          query_start = i;
12058
471
          ++i;
12059
471
          goto scan_query_boundary;
12060
471
        }
12061
48.4k
        if (b[i] == '#') {
12062
400
          path_end = i;
12063
400
          hash_start = i;
12064
400
          ++i;
12065
400
          goto after_rest;
12066
400
        }
12067
48.4k
      }
12068
5.34k
      path_end = i;
12069
5.34k
      goto after_rest;
12070
6.21k
    }
12071
8.08k
    path_end = i;
12072
8.08k
  } else if (i < len && b[i] == '?') {
12073
2.60k
    query_start = i;
12074
2.60k
    ++i;
12075
2.60k
    goto scan_query;
12076
2.60k
  } else if (i < len && b[i] == '#') {
12077
2.39k
    hash_start = i;
12078
2.39k
    ++i;
12079
2.39k
    goto scan_hash;
12080
2.39k
  }
12081
8.14k
  goto after_rest;
12082
12083
8.14k
scan_query:
12084
3.31k
  scan_query_run(b, i, len);
12085
3.31k
  if (i < len) {
12086
2.23k
    if (b[i] == '#') {
12087
216
      hash_start = i;
12088
216
      ++i;
12089
216
      goto scan_hash;
12090
216
    }
12091
2.01k
    rest_simple = false;
12092
2.01k
    goto scan_query_boundary;
12093
2.23k
  }
12094
1.07k
  goto after_rest;
12095
12096
2.49k
scan_query_boundary:
12097
25.8k
  for (; i < len; ++i) {
12098
23.7k
    if (b[i] == '#') {
12099
388
      hash_start = i;
12100
388
      ++i;
12101
388
      goto after_rest;
12102
388
    }
12103
23.7k
  }
12104
2.10k
  goto after_rest;
12105
12106
3.26k
scan_hash:
12107
3.26k
  scan_hash_run(b, i, len);
12108
3.26k
  if (i < len) {
12109
1.47k
    rest_simple = false;
12110
1.47k
  }
12111
12112
20.7k
after_rest:
12113
20.7k
  if (rest_simple && maybe_dot_segment) {
12114
1.81k
    const std::string_view path_body(input.data() + path_start,
12115
1.81k
                                     path_end - path_start);
12116
1.81k
    if (path_has_dot_segment(path_body)) {
12117
1.09k
      rest_simple = false;
12118
1.09k
    }
12119
1.81k
  }
12120
12121
  // The slow path removes ASCII tab/newline anywhere in the input and trims a
12122
  // trailing C0 control or space; this fast path does neither. A query or
12123
  // fragment reaching the helpers below would keep those bytes percent-encoded
12124
  // ("?a\nb" -> "?a%0Ab", "#f " -> "#f%20") instead of stripped, so hand such
12125
  // inputs back to the slow path.
12126
20.7k
  if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) ||
12127
10.0k
                       unicode::has_tabs_or_newline(input))) {
12128
1.89k
    return false;
12129
1.89k
  }
12130
12131
18.8k
  out.type = scheme_type;
12132
18.8k
  out.is_valid = true;
12133
18.8k
  out.has_opaque_path = false;
12134
18.8k
  out.host_type = DEFAULT;
12135
12136
18.8k
  const uint32_t port_bytes = (parsed_port != url_components::omitted)
12137
18.8k
                                  ? (1 + port_decimal_digit_count(parsed_port))
12138
18.8k
                                  : 0;
12139
12140
18.8k
  if (!rest_simple) {
12141
8.90k
    const std::string_view path_view =
12142
8.90k
        has_path
12143
8.90k
            ? std::string_view(input.data() + path_start, path_end - path_start)
12144
8.90k
            : std::string_view{};
12145
8.90k
    auto apply_query_and_hash = [&]() {
12146
8.90k
      if (query_start != std::string_view::npos) {
12147
8.90k
        const size_t q_end =
12148
8.90k
            (hash_start != std::string_view::npos) ? hash_start : len;
12149
8.90k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12150
8.90k
                                                q_end - query_start - 1),
12151
8.90k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12152
8.90k
      }
12153
8.90k
      if (hash_start != std::string_view::npos) {
12154
8.90k
        out.update_unencoded_base_hash(std::string_view(
12155
8.90k
            input.data() + hash_start + 1, len - hash_start - 1));
12156
8.90k
      }
12157
8.90k
    };
12158
8.90k
    if constexpr (is_aggregator) {
12159
8.90k
      out.buffer.assign(input.substr(0, host_end));
12160
8.90k
      if (parsed_port != url_components::omitted) {
12161
2.12k
        append_canonical_port(out.buffer, parsed_port);
12162
2.12k
      }
12163
8.90k
      if (has_upper) {
12164
1.69k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12165
1.69k
      }
12166
8.90k
      out.components.protocol_end = protocol_end;
12167
8.90k
      out.components.username_end = protocol_end + 2;
12168
8.90k
      out.components.host_start = protocol_end + 2;
12169
8.90k
      out.components.host_end = static_cast<uint32_t>(host_end);
12170
8.90k
      out.components.port = parsed_port;
12171
8.90k
      out.components.pathname_start = static_cast<uint32_t>(out.buffer.size());
12172
8.90k
      out.components.search_start = url_components::omitted;
12173
8.90k
      out.components.hash_start = url_components::omitted;
12174
8.90k
      out.parse_path(path_view);
12175
8.90k
      apply_query_and_hash();
12176
    } else {
12177
      std::string host_str(input.substr(host_start, host_len));
12178
      if (has_upper) {
12179
        unicode::to_lower_ascii(host_str.data(), host_str.size());
12180
      }
12181
      out.host = std::move(host_str);
12182
      if (parsed_port != url_components::omitted) {
12183
        out.port = static_cast<uint16_t>(parsed_port);
12184
      }
12185
      out.parse_path(path_view);
12186
      apply_query_and_hash();
12187
    }
12188
8.90k
    return true;
12189
8.90k
  }
12190
12191
9.91k
  const bool insert_slash = !has_path;
12192
9.91k
  if constexpr (is_aggregator) {
12193
9.91k
    const size_t out_len =
12194
9.91k
        host_end + port_bytes + (insert_slash ? 1 : 0) + (len - authority_end);
12195
9.91k
    const bool omit_port_bytes = parsed_port == url_components::omitted;
12196
9.91k
    if (out_len == len && !insert_slash && !omit_port_bytes) {
12197
2.68k
      out.buffer.assign(input);
12198
7.22k
    } else {
12199
7.22k
      out.buffer.clear();
12200
7.22k
      out.buffer.reserve(out_len);
12201
7.22k
      out.buffer.append(input.substr(0, host_end));
12202
7.22k
      if (parsed_port != url_components::omitted) {
12203
1.22k
        append_canonical_port(out.buffer, parsed_port);
12204
1.22k
      }
12205
7.22k
      if (insert_slash) {
12206
1.94k
        out.buffer.push_back('/');
12207
1.94k
      }
12208
7.22k
      if (authority_end < len) {
12209
7.17k
        out.buffer.append(input.substr(authority_end));
12210
7.17k
      }
12211
7.22k
    }
12212
9.91k
    if (has_upper) {
12213
2.91k
      unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12214
2.91k
    }
12215
9.91k
    const uint32_t pathname_start =
12216
9.91k
        static_cast<uint32_t>(host_end) + port_bytes;
12217
9.91k
    const int32_t tail_delta = static_cast<int32_t>(pathname_start) +
12218
9.91k
                               (insert_slash ? 1 : 0) -
12219
9.91k
                               static_cast<int32_t>(authority_end);
12220
9.91k
    out.components.protocol_end = protocol_end;
12221
9.91k
    out.components.username_end = protocol_end + 2;
12222
9.91k
    out.components.host_start = protocol_end + 2;
12223
9.91k
    out.components.host_end = static_cast<uint32_t>(host_end);
12224
9.91k
    out.components.port = parsed_port;
12225
9.91k
    out.components.pathname_start = pathname_start;
12226
9.91k
    out.components.search_start =
12227
9.91k
        (query_start != std::string_view::npos)
12228
9.91k
            ? static_cast<uint32_t>(static_cast<int32_t>(query_start) +
12229
1.20k
                                    tail_delta)
12230
9.91k
            : url_components::omitted;
12231
9.91k
    out.components.hash_start =
12232
9.91k
        (hash_start != std::string_view::npos)
12233
9.91k
            ? static_cast<uint32_t>(static_cast<int32_t>(hash_start) +
12234
1.68k
                                    tail_delta)
12235
9.91k
            : url_components::omitted;
12236
  } else {
12237
    std::string host_str(input.substr(host_start, host_len));
12238
    if (has_upper) {
12239
      unicode::to_lower_ascii(host_str.data(), host_str.size());
12240
    }
12241
    out.host = std::move(host_str);
12242
    if (parsed_port != url_components::omitted) {
12243
      out.port = static_cast<uint16_t>(parsed_port);
12244
    }
12245
    if (insert_slash) {
12246
      out.path = "/";
12247
    } else {
12248
      out.path.assign(input.data() + path_start, path_end - path_start);
12249
    }
12250
    if (query_start != std::string_view::npos) {
12251
      const size_t q_end =
12252
          (hash_start != std::string_view::npos) ? hash_start : len;
12253
      out.query.emplace(input.data() + query_start + 1,
12254
                        q_end - query_start - 1);
12255
    }
12256
    if (hash_start != std::string_view::npos) {
12257
      out.hash.emplace(input.data() + hash_start + 1, len - hash_start - 1);
12258
    }
12259
  }
12260
9.91k
  return true;
12261
18.8k
}
12262
12263
// Fast path for already-canonical special-scheme URLs of the shape
12264
// scheme://host[/path][?query][#fragment]. When the host is a plain domain
12265
// but the rest needs encoding or dot-segment normalization, the host is
12266
// kept and the path/query/hash helpers finish the URL.
12267
template <class result_type>
12268
ada_never_inline bool try_parse_simple_absolute(std::string_view input,
12269
1.13M
                                                result_type& out) {
12270
1.13M
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
12271
1.13M
  constexpr bool is_aggregator =
12272
1.13M
      std::is_same_v<result_type, ada::url_aggregator>;
12273
1.13M
  static_assert(is_ada_url || is_aggregator);
12274
12275
1.13M
  const size_t len = input.size();
12276
  // Shortest accepted form is "ws://x" (6).
12277
1.13M
  if (len < 6) [[unlikely]] {
12278
28.2k
    return false;
12279
28.2k
  }
12280
1.10M
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12281
12282
1.10M
  size_t pos = 0;
12283
1.10M
  ada::scheme::type scheme_type = ada::scheme::type::NOT_SPECIAL;
12284
1.10M
  uint32_t protocol_end = 0;
12285
1.10M
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
12286
1.10M
    defined(_M_X64) || defined(_M_IX86) || defined(_M_AMD64)
12287
  // One 8-byte load + integer compare is a single cmp/jcc on x86-64.
12288
  // Masked compares cover the shorter special schemes without extra loads.
12289
1.10M
  if (len >= 8) {
12290
1.07M
    uint64_t first8 = 0;
12291
1.07M
    std::memcpy(&first8, b, 8);
12292
1.07M
    if (first8 == 0x2f2f3a7370747468ull) {  // "https://"
12293
1.07M
      pos = 8;
12294
1.07M
      scheme_type = ada::scheme::type::HTTPS;
12295
1.07M
      protocol_end = 6;
12296
1.07M
    } else if ((first8 & 0x00ffffffffffffffull) ==
12297
1.51k
               0x002f2f3a70747468ull) {  // "http://"
12298
0
      pos = 7;
12299
0
      scheme_type = ada::scheme::type::HTTP;
12300
0
      protocol_end = 5;
12301
1.51k
    } else if ((first8 & 0x0000ffffffffffffull) ==
12302
1.51k
               0x00002f2f3a737377ull) {  // "wss://"
12303
0
      pos = 6;
12304
0
      scheme_type = ada::scheme::type::WSS;
12305
0
      protocol_end = 4;
12306
1.51k
    } else if ((first8 & 0x0000ffffffffffffull) ==
12307
1.51k
               0x00002f2f3a707466ull) {  // "ftp://"
12308
0
      pos = 6;
12309
0
      scheme_type = ada::scheme::type::FTP;
12310
0
      protocol_end = 4;
12311
1.51k
    } else if ((first8 & 0x000000ffffffffffull) ==
12312
1.51k
               0x0000002f2f3a7377ull) {  // "ws://"
12313
0
      pos = 5;
12314
0
      scheme_type = ada::scheme::type::WS;
12315
0
      protocol_end = 3;
12316
1.51k
    } else {
12317
1.51k
      return false;
12318
1.51k
    }
12319
1.07M
  } else if (b[0] == 'w' && b[1] == 's') {
12320
0
    if (b[2] == ':' && b[3] == '/' && b[4] == '/') {
12321
0
      pos = 5;
12322
0
      scheme_type = ada::scheme::type::WS;
12323
0
      protocol_end = 3;
12324
0
    } else if (b[2] == 's' && b[3] == ':' && b[4] == '/' && b[5] == '/') {
12325
0
      pos = 6;
12326
0
      scheme_type = ada::scheme::type::WSS;
12327
0
      protocol_end = 4;
12328
0
    } else {
12329
0
      return false;
12330
0
    }
12331
24.6k
  } else if (b[0] == 'f' && b[1] == 't' && b[2] == 'p' && b[3] == ':' &&
12332
0
             b[4] == '/' && b[5] == '/') {
12333
0
    pos = 6;
12334
0
    scheme_type = ada::scheme::type::FTP;
12335
0
    protocol_end = 4;
12336
24.6k
  } else if (len >= 7 && b[0] == 'h' && b[1] == 't' && b[2] == 't' &&
12337
0
             b[3] == 'p' && b[4] == ':' && b[5] == '/' && b[6] == '/') {
12338
0
    pos = 7;
12339
0
    scheme_type = ada::scheme::type::HTTP;
12340
0
    protocol_end = 5;
12341
24.6k
  } else {
12342
24.6k
    return false;
12343
24.6k
  }
12344
#else
12345
  // Big-endian / uncommon arches: byte-wise special-scheme match.
12346
  if (len >= 8 && b[0] == 'h' && b[1] == 't' && b[2] == 't' && b[3] == 'p' &&
12347
      b[4] == 's' && b[5] == ':' && b[6] == '/' && b[7] == '/') {
12348
    pos = 8;
12349
    scheme_type = ada::scheme::type::HTTPS;
12350
    protocol_end = 6;
12351
  } else if (len >= 7 && b[0] == 'h' && b[1] == 't' && b[2] == 't' &&
12352
             b[3] == 'p' && b[4] == ':' && b[5] == '/' && b[6] == '/') {
12353
    pos = 7;
12354
    scheme_type = ada::scheme::type::HTTP;
12355
    protocol_end = 5;
12356
  } else if (b[0] == 'w' && b[1] == 's') {
12357
    if (b[2] == ':' && b[3] == '/' && b[4] == '/') {
12358
      pos = 5;
12359
      scheme_type = ada::scheme::type::WS;
12360
      protocol_end = 3;
12361
    } else if (len >= 6 && b[2] == 's' && b[3] == ':' && b[4] == '/' &&
12362
               b[5] == '/') {
12363
      pos = 6;
12364
      scheme_type = ada::scheme::type::WSS;
12365
      protocol_end = 4;
12366
    } else {
12367
      return false;
12368
    }
12369
  } else if (b[0] == 'f' && b[1] == 't' && b[2] == 'p' && b[3] == ':' &&
12370
             b[4] == '/' && b[5] == '/') {
12371
    pos = 6;
12372
    scheme_type = ada::scheme::type::FTP;
12373
    protocol_end = 4;
12374
  } else {
12375
    return false;
12376
  }
12377
#endif
12378
1.07M
  if (pos < len && (b[pos] == '/' || b[pos] == '\\')) [[unlikely]] {
12379
312k
    return false;
12380
312k
  }
12381
12382
  // Digit-led hosts are IPv4/numeric; '[' is IPv6. Skip before scanning.
12383
765k
  if (pos < len && ((b[pos] >= '0' && b[pos] <= '9') || b[pos] == '[')) {
12384
0
    return false;
12385
0
  }
12386
12387
765k
  const size_t host_start = pos;
12388
765k
  bool has_upper = false;
12389
765k
  bool has_x = false;
12390
765k
  size_t host_end = pos;
12391
765k
  if (!scan_plain_host(b, pos, len, host_end, has_upper, has_x)) {
12392
64.1k
    return false;
12393
64.1k
  }
12394
701k
  if (host_start == host_end) [[unlikely]] {
12395
28.9k
    return false;
12396
28.9k
  }
12397
672k
  const size_t host_len = host_end - host_start;
12398
672k
  if (host_len > 253) [[unlikely]] {
12399
0
    return false;
12400
0
  }
12401
672k
  {
12402
672k
    std::string_view hv(input.data() + host_start, host_len);
12403
672k
    char host_buf[256];
12404
672k
    if (has_upper) [[unlikely]] {
12405
20.1k
      std::memcpy(host_buf, input.data() + host_start, host_len);
12406
20.1k
      unicode::to_lower_ascii(host_buf, host_len);
12407
20.1k
      hv = std::string_view(host_buf, host_len);
12408
20.1k
    }
12409
672k
    if (ada::checkers::last_label_may_be_a_number(hv)) [[unlikely]] {
12410
3.18k
      return false;
12411
3.18k
    }
12412
    // Punycode is "xn--...". The host scan already notes a lowercase 'x';
12413
    // uppercase 'X' is covered by has_upper after the in-place lower.
12414
669k
    static constexpr std::string_view xn{"xn-", 3};
12415
669k
    if ((has_x || has_upper) && hv.find(xn) != std::string_view::npos)
12416
3.08k
        [[unlikely]] {
12417
3.08k
      return false;
12418
3.08k
    }
12419
669k
  }
12420
12421
666k
  if (host_end < len && b[host_end] == ':') [[unlikely]] {
12422
22.9k
    return finish_simple_absolute_with_port(input, out, scheme_type,
12423
22.9k
                                            protocol_end, host_start, host_end,
12424
22.9k
                                            host_len, has_upper);
12425
22.9k
  }
12426
12427
643k
  size_t i = host_end;
12428
643k
  size_t path_start = host_end;
12429
643k
  size_t path_end = host_end;
12430
643k
  size_t query_start = std::string_view::npos;
12431
643k
  size_t hash_start = std::string_view::npos;
12432
643k
  bool has_path = false;
12433
643k
  bool maybe_dot_segment = false;
12434
643k
  bool rest_simple = true;
12435
12436
643k
  if (i < len && b[i] == '/') {
12437
309k
    has_path = true;
12438
309k
    path_start = i;
12439
309k
    ++i;
12440
309k
    scan_path_run(b, i, len, maybe_dot_segment);
12441
309k
    if (i < len) {
12442
13.1k
      const uint8_t cls = k_path[b[i]];
12443
13.1k
      if (cls == 1) {
12444
2.28k
        path_end = i;
12445
2.28k
        if (b[i] == '?') {
12446
1.55k
          query_start = i;
12447
1.55k
          ++i;
12448
1.55k
          goto scan_query;
12449
1.55k
        }
12450
734
        hash_start = i;
12451
734
        ++i;
12452
734
        goto scan_hash;
12453
2.28k
      }
12454
10.8k
      rest_simple = false;
12455
112k
      for (; i < len; ++i) {
12456
104k
        if (b[i] == '?') {
12457
1.77k
          path_end = i;
12458
1.77k
          query_start = i;
12459
1.77k
          ++i;
12460
1.77k
          goto scan_query_boundary;
12461
1.77k
        }
12462
102k
        if (b[i] == '#') {
12463
472
          path_end = i;
12464
472
          hash_start = i;
12465
472
          ++i;
12466
472
          goto after_rest;
12467
472
        }
12468
102k
      }
12469
8.64k
      path_end = i;
12470
8.64k
      goto after_rest;
12471
10.8k
    }
12472
296k
    path_end = i;
12473
334k
  } else if (i < len && b[i] == '?') {
12474
6.05k
    query_start = i;
12475
6.05k
    ++i;
12476
6.05k
    goto scan_query;
12477
328k
  } else if (i < len && b[i] == '#') {
12478
5.11k
    hash_start = i;
12479
5.11k
    ++i;
12480
5.11k
    goto scan_hash;
12481
5.11k
  }
12482
619k
  goto after_rest;
12483
12484
619k
scan_query:
12485
7.60k
  scan_query_run(b, i, len);
12486
7.60k
  if (i < len) {
12487
4.26k
    if (b[i] == '#') {
12488
500
      hash_start = i;
12489
500
      ++i;
12490
500
      goto scan_hash;
12491
500
    }
12492
3.76k
    rest_simple = false;
12493
3.76k
    goto scan_query_boundary;
12494
4.26k
  }
12495
3.33k
  goto after_rest;
12496
12497
5.54k
scan_query_boundary:
12498
49.3k
  for (; i < len; ++i) {
12499
44.8k
    if (b[i] == '#') {
12500
1.01k
      hash_start = i;
12501
1.01k
      ++i;
12502
1.01k
      goto after_rest;
12503
1.01k
    }
12504
44.8k
  }
12505
4.52k
  goto after_rest;
12506
12507
6.35k
scan_hash:
12508
6.35k
  scan_hash_run(b, i, len);
12509
6.35k
  if (i < len) {
12510
3.14k
    rest_simple = false;
12511
3.14k
  }
12512
12513
643k
after_rest:
12514
643k
  if (rest_simple && maybe_dot_segment) {
12515
10.3k
    const std::string_view path_body(input.data() + path_start,
12516
10.3k
                                     path_end - path_start);
12517
10.3k
    if (path_has_dot_segment(path_body)) {
12518
7.18k
      rest_simple = false;
12519
7.18k
    }
12520
10.3k
  }
12521
12522
  // The slow path removes ASCII tab/newline anywhere in the input and trims a
12523
  // trailing C0 control or space; this fast path does neither. A query or
12524
  // fragment reaching the helpers below would keep those bytes percent-encoded
12525
  // ("?a\nb" -> "?a%0Ab", "#f " -> "#f%20") instead of stripped, so hand such
12526
  // inputs back to the slow path.
12527
643k
  if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) ||
12528
22.6k
                       unicode::has_tabs_or_newline(input))) {
12529
3.38k
    return false;
12530
3.38k
  }
12531
12532
640k
  out.type = scheme_type;
12533
640k
  out.is_valid = true;
12534
640k
  out.has_opaque_path = false;
12535
640k
  out.host_type = DEFAULT;
12536
12537
640k
  if (!rest_simple) {
12538
    // Host is a plain domain. Finish path/query/hash with
12539
    // the regular helpers
12540
    // so percent-encoding and dot segments do not re-parse the authority.
12541
21.5k
    const std::string_view path_view =
12542
21.5k
        has_path
12543
21.5k
            ? std::string_view(input.data() + path_start, path_end - path_start)
12544
21.5k
            : std::string_view{};
12545
21.5k
    auto apply_query_and_hash = [&]() {
12546
21.5k
      if (query_start != std::string_view::npos) {
12547
5.06k
        const size_t q_end =
12548
5.06k
            (hash_start != std::string_view::npos) ? hash_start : len;
12549
5.06k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12550
5.06k
                                                q_end - query_start - 1),
12551
5.06k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12552
5.06k
      }
12553
21.5k
      if (hash_start != std::string_view::npos) {
12554
3.82k
        out.update_unencoded_base_hash(std::string_view(
12555
3.82k
            input.data() + hash_start + 1, len - hash_start - 1));
12556
3.82k
      }
12557
21.5k
    };
Unexecuted instantiation: ada::parser::try_parse_simple_absolute<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url&)::{lambda()#1}::operator()() const
ada::parser::try_parse_simple_absolute<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator&)::{lambda()#1}::operator()() const
Line
Count
Source
12545
21.5k
    auto apply_query_and_hash = [&]() {
12546
21.5k
      if (query_start != std::string_view::npos) {
12547
5.06k
        const size_t q_end =
12548
5.06k
            (hash_start != std::string_view::npos) ? hash_start : len;
12549
5.06k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12550
5.06k
                                                q_end - query_start - 1),
12551
5.06k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12552
5.06k
      }
12553
21.5k
      if (hash_start != std::string_view::npos) {
12554
3.82k
        out.update_unencoded_base_hash(std::string_view(
12555
3.82k
            input.data() + hash_start + 1, len - hash_start - 1));
12556
3.82k
      }
12557
21.5k
    };
12558
21.5k
    if constexpr (is_aggregator) {
12559
21.5k
      out.buffer.assign(input.substr(0, host_end));
12560
21.5k
      if (has_upper) {
12561
2.46k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12562
2.46k
      }
12563
21.5k
      out.components.protocol_end = protocol_end;
12564
21.5k
      out.components.username_end = protocol_end + 2;
12565
21.5k
      out.components.host_start = protocol_end + 2;
12566
21.5k
      out.components.host_end = static_cast<uint32_t>(host_end);
12567
21.5k
      out.components.port = url_components::omitted;
12568
21.5k
      out.components.pathname_start = static_cast<uint32_t>(host_end);
12569
21.5k
      out.components.search_start = url_components::omitted;
12570
21.5k
      out.components.hash_start = url_components::omitted;
12571
21.5k
      out.parse_path(path_view);
12572
21.5k
      apply_query_and_hash();
12573
21.5k
    } else {
12574
0
      std::string host_str(input.substr(host_start, host_len));
12575
0
      if (has_upper) {
12576
0
        unicode::to_lower_ascii(host_str.data(), host_str.size());
12577
0
      }
12578
0
      out.host = std::move(host_str);
12579
0
      out.parse_path(path_view);
12580
0
      apply_query_and_hash();
12581
0
    }
12582
21.5k
    return true;
12583
21.5k
  }
12584
12585
618k
  const bool need_slash = !has_path;
12586
618k
  if constexpr (is_aggregator) {
12587
618k
    if (!need_slash) {
12588
      // assign copies once. resize()+memcpy would value-init then overwrite.
12589
290k
      out.buffer.assign(input);
12590
290k
      if (has_upper) {
12591
7.99k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12592
7.99k
      }
12593
290k
      out.components.protocol_end = protocol_end;
12594
290k
      out.components.username_end = protocol_end + 2;
12595
290k
      out.components.host_start = protocol_end + 2;
12596
290k
      out.components.host_end = static_cast<uint32_t>(host_end);
12597
290k
      out.components.port = url_components::omitted;
12598
290k
      out.components.pathname_start = static_cast<uint32_t>(path_start);
12599
290k
      out.components.search_start = (query_start != std::string_view::npos)
12600
290k
                                        ? static_cast<uint32_t>(query_start)
12601
290k
                                        : url_components::omitted;
12602
290k
      out.components.hash_start = (hash_start != std::string_view::npos)
12603
290k
                                      ? static_cast<uint32_t>(hash_start)
12604
290k
                                      : url_components::omitted;
12605
327k
    } else {
12606
327k
      out.buffer.clear();
12607
327k
      out.buffer.reserve(len + 1);
12608
327k
      out.buffer.append(input.substr(0, host_end));
12609
327k
      out.buffer.push_back('/');
12610
327k
      if (host_end < len) {
12611
4.71k
        out.buffer.append(input.substr(host_end));
12612
4.71k
      }
12613
327k
      if (has_upper) {
12614
1.16k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12615
1.16k
      }
12616
327k
      out.components.protocol_end = protocol_end;
12617
327k
      out.components.username_end = protocol_end + 2;
12618
327k
      out.components.host_start = protocol_end + 2;
12619
327k
      out.components.host_end = static_cast<uint32_t>(host_end);
12620
327k
      out.components.port = url_components::omitted;
12621
327k
      out.components.pathname_start = static_cast<uint32_t>(host_end);
12622
327k
      out.components.search_start = (query_start != std::string_view::npos)
12623
327k
                                        ? static_cast<uint32_t>(query_start + 1)
12624
327k
                                        : url_components::omitted;
12625
327k
      out.components.hash_start = (hash_start != std::string_view::npos)
12626
327k
                                      ? static_cast<uint32_t>(hash_start + 1)
12627
327k
                                      : url_components::omitted;
12628
327k
    }
12629
618k
  } else {
12630
0
    std::string host_str(input.substr(host_start, host_len));
12631
0
    if (has_upper) {
12632
0
      unicode::to_lower_ascii(host_str.data(), host_str.size());
12633
0
    }
12634
0
    out.host = std::move(host_str);
12635
0
    if (need_slash) {
12636
0
      out.path = "/";
12637
0
    } else {
12638
0
      out.path.assign(input.data() + path_start, path_end - path_start);
12639
0
    }
12640
0
    if (query_start != std::string_view::npos) {
12641
0
      const size_t q_end =
12642
0
          (hash_start != std::string_view::npos) ? hash_start : len;
12643
0
      out.query.emplace(input.data() + query_start + 1,
12644
0
                        q_end - query_start - 1);
12645
0
    }
12646
0
    if (hash_start != std::string_view::npos) {
12647
0
      out.hash.emplace(input.data() + hash_start + 1, len - hash_start - 1);
12648
0
    }
12649
0
  }
12650
618k
  return true;
12651
640k
}
Unexecuted instantiation: bool ada::parser::try_parse_simple_absolute<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url&)
bool ada::parser::try_parse_simple_absolute<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator&)
Line
Count
Source
12269
1.13M
                                                result_type& out) {
12270
1.13M
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
12271
1.13M
  constexpr bool is_aggregator =
12272
1.13M
      std::is_same_v<result_type, ada::url_aggregator>;
12273
1.13M
  static_assert(is_ada_url || is_aggregator);
12274
12275
1.13M
  const size_t len = input.size();
12276
  // Shortest accepted form is "ws://x" (6).
12277
1.13M
  if (len < 6) [[unlikely]] {
12278
28.2k
    return false;
12279
28.2k
  }
12280
1.10M
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12281
12282
1.10M
  size_t pos = 0;
12283
1.10M
  ada::scheme::type scheme_type = ada::scheme::type::NOT_SPECIAL;
12284
1.10M
  uint32_t protocol_end = 0;
12285
1.10M
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
12286
1.10M
    defined(_M_X64) || defined(_M_IX86) || defined(_M_AMD64)
12287
  // One 8-byte load + integer compare is a single cmp/jcc on x86-64.
12288
  // Masked compares cover the shorter special schemes without extra loads.
12289
1.10M
  if (len >= 8) {
12290
1.07M
    uint64_t first8 = 0;
12291
1.07M
    std::memcpy(&first8, b, 8);
12292
1.07M
    if (first8 == 0x2f2f3a7370747468ull) {  // "https://"
12293
1.07M
      pos = 8;
12294
1.07M
      scheme_type = ada::scheme::type::HTTPS;
12295
1.07M
      protocol_end = 6;
12296
1.07M
    } else if ((first8 & 0x00ffffffffffffffull) ==
12297
1.51k
               0x002f2f3a70747468ull) {  // "http://"
12298
0
      pos = 7;
12299
0
      scheme_type = ada::scheme::type::HTTP;
12300
0
      protocol_end = 5;
12301
1.51k
    } else if ((first8 & 0x0000ffffffffffffull) ==
12302
1.51k
               0x00002f2f3a737377ull) {  // "wss://"
12303
0
      pos = 6;
12304
0
      scheme_type = ada::scheme::type::WSS;
12305
0
      protocol_end = 4;
12306
1.51k
    } else if ((first8 & 0x0000ffffffffffffull) ==
12307
1.51k
               0x00002f2f3a707466ull) {  // "ftp://"
12308
0
      pos = 6;
12309
0
      scheme_type = ada::scheme::type::FTP;
12310
0
      protocol_end = 4;
12311
1.51k
    } else if ((first8 & 0x000000ffffffffffull) ==
12312
1.51k
               0x0000002f2f3a7377ull) {  // "ws://"
12313
0
      pos = 5;
12314
0
      scheme_type = ada::scheme::type::WS;
12315
0
      protocol_end = 3;
12316
1.51k
    } else {
12317
1.51k
      return false;
12318
1.51k
    }
12319
1.07M
  } else if (b[0] == 'w' && b[1] == 's') {
12320
0
    if (b[2] == ':' && b[3] == '/' && b[4] == '/') {
12321
0
      pos = 5;
12322
0
      scheme_type = ada::scheme::type::WS;
12323
0
      protocol_end = 3;
12324
0
    } else if (b[2] == 's' && b[3] == ':' && b[4] == '/' && b[5] == '/') {
12325
0
      pos = 6;
12326
0
      scheme_type = ada::scheme::type::WSS;
12327
0
      protocol_end = 4;
12328
0
    } else {
12329
0
      return false;
12330
0
    }
12331
24.6k
  } else if (b[0] == 'f' && b[1] == 't' && b[2] == 'p' && b[3] == ':' &&
12332
0
             b[4] == '/' && b[5] == '/') {
12333
0
    pos = 6;
12334
0
    scheme_type = ada::scheme::type::FTP;
12335
0
    protocol_end = 4;
12336
24.6k
  } else if (len >= 7 && b[0] == 'h' && b[1] == 't' && b[2] == 't' &&
12337
0
             b[3] == 'p' && b[4] == ':' && b[5] == '/' && b[6] == '/') {
12338
0
    pos = 7;
12339
0
    scheme_type = ada::scheme::type::HTTP;
12340
0
    protocol_end = 5;
12341
24.6k
  } else {
12342
24.6k
    return false;
12343
24.6k
  }
12344
#else
12345
  // Big-endian / uncommon arches: byte-wise special-scheme match.
12346
  if (len >= 8 && b[0] == 'h' && b[1] == 't' && b[2] == 't' && b[3] == 'p' &&
12347
      b[4] == 's' && b[5] == ':' && b[6] == '/' && b[7] == '/') {
12348
    pos = 8;
12349
    scheme_type = ada::scheme::type::HTTPS;
12350
    protocol_end = 6;
12351
  } else if (len >= 7 && b[0] == 'h' && b[1] == 't' && b[2] == 't' &&
12352
             b[3] == 'p' && b[4] == ':' && b[5] == '/' && b[6] == '/') {
12353
    pos = 7;
12354
    scheme_type = ada::scheme::type::HTTP;
12355
    protocol_end = 5;
12356
  } else if (b[0] == 'w' && b[1] == 's') {
12357
    if (b[2] == ':' && b[3] == '/' && b[4] == '/') {
12358
      pos = 5;
12359
      scheme_type = ada::scheme::type::WS;
12360
      protocol_end = 3;
12361
    } else if (len >= 6 && b[2] == 's' && b[3] == ':' && b[4] == '/' &&
12362
               b[5] == '/') {
12363
      pos = 6;
12364
      scheme_type = ada::scheme::type::WSS;
12365
      protocol_end = 4;
12366
    } else {
12367
      return false;
12368
    }
12369
  } else if (b[0] == 'f' && b[1] == 't' && b[2] == 'p' && b[3] == ':' &&
12370
             b[4] == '/' && b[5] == '/') {
12371
    pos = 6;
12372
    scheme_type = ada::scheme::type::FTP;
12373
    protocol_end = 4;
12374
  } else {
12375
    return false;
12376
  }
12377
#endif
12378
1.07M
  if (pos < len && (b[pos] == '/' || b[pos] == '\\')) [[unlikely]] {
12379
312k
    return false;
12380
312k
  }
12381
12382
  // Digit-led hosts are IPv4/numeric; '[' is IPv6. Skip before scanning.
12383
765k
  if (pos < len && ((b[pos] >= '0' && b[pos] <= '9') || b[pos] == '[')) {
12384
0
    return false;
12385
0
  }
12386
12387
765k
  const size_t host_start = pos;
12388
765k
  bool has_upper = false;
12389
765k
  bool has_x = false;
12390
765k
  size_t host_end = pos;
12391
765k
  if (!scan_plain_host(b, pos, len, host_end, has_upper, has_x)) {
12392
64.1k
    return false;
12393
64.1k
  }
12394
701k
  if (host_start == host_end) [[unlikely]] {
12395
28.9k
    return false;
12396
28.9k
  }
12397
672k
  const size_t host_len = host_end - host_start;
12398
672k
  if (host_len > 253) [[unlikely]] {
12399
0
    return false;
12400
0
  }
12401
672k
  {
12402
672k
    std::string_view hv(input.data() + host_start, host_len);
12403
672k
    char host_buf[256];
12404
672k
    if (has_upper) [[unlikely]] {
12405
20.1k
      std::memcpy(host_buf, input.data() + host_start, host_len);
12406
20.1k
      unicode::to_lower_ascii(host_buf, host_len);
12407
20.1k
      hv = std::string_view(host_buf, host_len);
12408
20.1k
    }
12409
672k
    if (ada::checkers::last_label_may_be_a_number(hv)) [[unlikely]] {
12410
3.18k
      return false;
12411
3.18k
    }
12412
    // Punycode is "xn--...". The host scan already notes a lowercase 'x';
12413
    // uppercase 'X' is covered by has_upper after the in-place lower.
12414
669k
    static constexpr std::string_view xn{"xn-", 3};
12415
669k
    if ((has_x || has_upper) && hv.find(xn) != std::string_view::npos)
12416
3.08k
        [[unlikely]] {
12417
3.08k
      return false;
12418
3.08k
    }
12419
669k
  }
12420
12421
666k
  if (host_end < len && b[host_end] == ':') [[unlikely]] {
12422
22.9k
    return finish_simple_absolute_with_port(input, out, scheme_type,
12423
22.9k
                                            protocol_end, host_start, host_end,
12424
22.9k
                                            host_len, has_upper);
12425
22.9k
  }
12426
12427
643k
  size_t i = host_end;
12428
643k
  size_t path_start = host_end;
12429
643k
  size_t path_end = host_end;
12430
643k
  size_t query_start = std::string_view::npos;
12431
643k
  size_t hash_start = std::string_view::npos;
12432
643k
  bool has_path = false;
12433
643k
  bool maybe_dot_segment = false;
12434
643k
  bool rest_simple = true;
12435
12436
643k
  if (i < len && b[i] == '/') {
12437
309k
    has_path = true;
12438
309k
    path_start = i;
12439
309k
    ++i;
12440
309k
    scan_path_run(b, i, len, maybe_dot_segment);
12441
309k
    if (i < len) {
12442
13.1k
      const uint8_t cls = k_path[b[i]];
12443
13.1k
      if (cls == 1) {
12444
2.28k
        path_end = i;
12445
2.28k
        if (b[i] == '?') {
12446
1.55k
          query_start = i;
12447
1.55k
          ++i;
12448
1.55k
          goto scan_query;
12449
1.55k
        }
12450
734
        hash_start = i;
12451
734
        ++i;
12452
734
        goto scan_hash;
12453
2.28k
      }
12454
10.8k
      rest_simple = false;
12455
112k
      for (; i < len; ++i) {
12456
104k
        if (b[i] == '?') {
12457
1.77k
          path_end = i;
12458
1.77k
          query_start = i;
12459
1.77k
          ++i;
12460
1.77k
          goto scan_query_boundary;
12461
1.77k
        }
12462
102k
        if (b[i] == '#') {
12463
472
          path_end = i;
12464
472
          hash_start = i;
12465
472
          ++i;
12466
472
          goto after_rest;
12467
472
        }
12468
102k
      }
12469
8.64k
      path_end = i;
12470
8.64k
      goto after_rest;
12471
10.8k
    }
12472
296k
    path_end = i;
12473
334k
  } else if (i < len && b[i] == '?') {
12474
6.05k
    query_start = i;
12475
6.05k
    ++i;
12476
6.05k
    goto scan_query;
12477
328k
  } else if (i < len && b[i] == '#') {
12478
5.11k
    hash_start = i;
12479
5.11k
    ++i;
12480
5.11k
    goto scan_hash;
12481
5.11k
  }
12482
619k
  goto after_rest;
12483
12484
619k
scan_query:
12485
7.60k
  scan_query_run(b, i, len);
12486
7.60k
  if (i < len) {
12487
4.26k
    if (b[i] == '#') {
12488
500
      hash_start = i;
12489
500
      ++i;
12490
500
      goto scan_hash;
12491
500
    }
12492
3.76k
    rest_simple = false;
12493
3.76k
    goto scan_query_boundary;
12494
4.26k
  }
12495
3.33k
  goto after_rest;
12496
12497
5.54k
scan_query_boundary:
12498
49.3k
  for (; i < len; ++i) {
12499
44.8k
    if (b[i] == '#') {
12500
1.01k
      hash_start = i;
12501
1.01k
      ++i;
12502
1.01k
      goto after_rest;
12503
1.01k
    }
12504
44.8k
  }
12505
4.52k
  goto after_rest;
12506
12507
6.35k
scan_hash:
12508
6.35k
  scan_hash_run(b, i, len);
12509
6.35k
  if (i < len) {
12510
3.14k
    rest_simple = false;
12511
3.14k
  }
12512
12513
643k
after_rest:
12514
643k
  if (rest_simple && maybe_dot_segment) {
12515
10.3k
    const std::string_view path_body(input.data() + path_start,
12516
10.3k
                                     path_end - path_start);
12517
10.3k
    if (path_has_dot_segment(path_body)) {
12518
7.18k
      rest_simple = false;
12519
7.18k
    }
12520
10.3k
  }
12521
12522
  // The slow path removes ASCII tab/newline anywhere in the input and trims a
12523
  // trailing C0 control or space; this fast path does neither. A query or
12524
  // fragment reaching the helpers below would keep those bytes percent-encoded
12525
  // ("?a\nb" -> "?a%0Ab", "#f " -> "#f%20") instead of stripped, so hand such
12526
  // inputs back to the slow path.
12527
643k
  if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) ||
12528
22.6k
                       unicode::has_tabs_or_newline(input))) {
12529
3.38k
    return false;
12530
3.38k
  }
12531
12532
640k
  out.type = scheme_type;
12533
640k
  out.is_valid = true;
12534
640k
  out.has_opaque_path = false;
12535
640k
  out.host_type = DEFAULT;
12536
12537
640k
  if (!rest_simple) {
12538
    // Host is a plain domain. Finish path/query/hash with
12539
    // the regular helpers
12540
    // so percent-encoding and dot segments do not re-parse the authority.
12541
21.5k
    const std::string_view path_view =
12542
21.5k
        has_path
12543
21.5k
            ? std::string_view(input.data() + path_start, path_end - path_start)
12544
21.5k
            : std::string_view{};
12545
21.5k
    auto apply_query_and_hash = [&]() {
12546
21.5k
      if (query_start != std::string_view::npos) {
12547
21.5k
        const size_t q_end =
12548
21.5k
            (hash_start != std::string_view::npos) ? hash_start : len;
12549
21.5k
        out.update_base_search(std::string_view(input.data() + query_start + 1,
12550
21.5k
                                                q_end - query_start - 1),
12551
21.5k
                               character_sets::SPECIAL_QUERY_PERCENT_ENCODE);
12552
21.5k
      }
12553
21.5k
      if (hash_start != std::string_view::npos) {
12554
21.5k
        out.update_unencoded_base_hash(std::string_view(
12555
21.5k
            input.data() + hash_start + 1, len - hash_start - 1));
12556
21.5k
      }
12557
21.5k
    };
12558
21.5k
    if constexpr (is_aggregator) {
12559
21.5k
      out.buffer.assign(input.substr(0, host_end));
12560
21.5k
      if (has_upper) {
12561
2.46k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12562
2.46k
      }
12563
21.5k
      out.components.protocol_end = protocol_end;
12564
21.5k
      out.components.username_end = protocol_end + 2;
12565
21.5k
      out.components.host_start = protocol_end + 2;
12566
21.5k
      out.components.host_end = static_cast<uint32_t>(host_end);
12567
21.5k
      out.components.port = url_components::omitted;
12568
21.5k
      out.components.pathname_start = static_cast<uint32_t>(host_end);
12569
21.5k
      out.components.search_start = url_components::omitted;
12570
21.5k
      out.components.hash_start = url_components::omitted;
12571
21.5k
      out.parse_path(path_view);
12572
21.5k
      apply_query_and_hash();
12573
    } else {
12574
      std::string host_str(input.substr(host_start, host_len));
12575
      if (has_upper) {
12576
        unicode::to_lower_ascii(host_str.data(), host_str.size());
12577
      }
12578
      out.host = std::move(host_str);
12579
      out.parse_path(path_view);
12580
      apply_query_and_hash();
12581
    }
12582
21.5k
    return true;
12583
21.5k
  }
12584
12585
618k
  const bool need_slash = !has_path;
12586
618k
  if constexpr (is_aggregator) {
12587
618k
    if (!need_slash) {
12588
      // assign copies once. resize()+memcpy would value-init then overwrite.
12589
290k
      out.buffer.assign(input);
12590
290k
      if (has_upper) {
12591
7.99k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12592
7.99k
      }
12593
290k
      out.components.protocol_end = protocol_end;
12594
290k
      out.components.username_end = protocol_end + 2;
12595
290k
      out.components.host_start = protocol_end + 2;
12596
290k
      out.components.host_end = static_cast<uint32_t>(host_end);
12597
290k
      out.components.port = url_components::omitted;
12598
290k
      out.components.pathname_start = static_cast<uint32_t>(path_start);
12599
290k
      out.components.search_start = (query_start != std::string_view::npos)
12600
290k
                                        ? static_cast<uint32_t>(query_start)
12601
290k
                                        : url_components::omitted;
12602
290k
      out.components.hash_start = (hash_start != std::string_view::npos)
12603
290k
                                      ? static_cast<uint32_t>(hash_start)
12604
290k
                                      : url_components::omitted;
12605
327k
    } else {
12606
327k
      out.buffer.clear();
12607
327k
      out.buffer.reserve(len + 1);
12608
327k
      out.buffer.append(input.substr(0, host_end));
12609
327k
      out.buffer.push_back('/');
12610
327k
      if (host_end < len) {
12611
4.71k
        out.buffer.append(input.substr(host_end));
12612
4.71k
      }
12613
327k
      if (has_upper) {
12614
1.16k
        unicode::to_lower_ascii(out.buffer.data() + host_start, host_len);
12615
1.16k
      }
12616
327k
      out.components.protocol_end = protocol_end;
12617
327k
      out.components.username_end = protocol_end + 2;
12618
327k
      out.components.host_start = protocol_end + 2;
12619
327k
      out.components.host_end = static_cast<uint32_t>(host_end);
12620
327k
      out.components.port = url_components::omitted;
12621
327k
      out.components.pathname_start = static_cast<uint32_t>(host_end);
12622
327k
      out.components.search_start = (query_start != std::string_view::npos)
12623
327k
                                        ? static_cast<uint32_t>(query_start + 1)
12624
327k
                                        : url_components::omitted;
12625
327k
      out.components.hash_start = (hash_start != std::string_view::npos)
12626
327k
                                      ? static_cast<uint32_t>(hash_start + 1)
12627
327k
                                      : url_components::omitted;
12628
327k
    }
12629
  } else {
12630
    std::string host_str(input.substr(host_start, host_len));
12631
    if (has_upper) {
12632
      unicode::to_lower_ascii(host_str.data(), host_str.size());
12633
    }
12634
    out.host = std::move(host_str);
12635
    if (need_slash) {
12636
      out.path = "/";
12637
    } else {
12638
      out.path.assign(input.data() + path_start, path_end - path_start);
12639
    }
12640
    if (query_start != std::string_view::npos) {
12641
      const size_t q_end =
12642
          (hash_start != std::string_view::npos) ? hash_start : len;
12643
      out.query.emplace(input.data() + query_start + 1,
12644
                        q_end - query_start - 1);
12645
    }
12646
    if (hash_start != std::string_view::npos) {
12647
      out.hash.emplace(input.data() + hash_start + 1, len - hash_start - 1);
12648
    }
12649
  }
12650
618k
  return true;
12651
640k
}
12652
12653
// Fast path for `/path`, path-relative (`foo`, `c/d?q`), `?query`, and
12654
// `#fragment` against a special-scheme base. Scheme-relative (`//`) and
12655
// scheme-like first segments (`foo:bar`) stay on the state machine.
12656
template <class result_type>
12657
ada_never_inline bool try_parse_simple_relative(std::string_view input,
12658
                                                const result_type& base,
12659
258k
                                                result_type& out) {
12660
258k
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
12661
258k
  constexpr bool is_aggregator =
12662
258k
      std::is_same_v<result_type, ada::url_aggregator>;
12663
258k
  static_assert(is_ada_url || is_aggregator);
12664
12665
258k
  if (!base.is_special() || base.type == ada::scheme::type::FILE ||
12666
258k
      base.has_opaque_path || input.empty()) {
12667
0
    return false;
12668
0
  }
12669
258k
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12670
258k
  const size_t len = input.size();
12671
258k
  const uint8_t first = b[0];
12672
258k
  const bool path_relative = first != '/' && first != '?' && first != '#';
12673
258k
  if (first == '/' && len > 1 && (b[1] == '/' || b[1] == '\\')) {
12674
0
    return false;
12675
0
  }
12676
  // A ':' before the first / ? # is a scheme, not a path segment.
12677
258k
  if (path_relative) {
12678
258k
    const size_t delim = input.find_first_of("/?#:");
12679
258k
    if (delim != std::string_view::npos && input[delim] == ':') {
12680
258k
      return false;
12681
258k
    }
12682
258k
  }
12683
12684
0
  size_t i = 0;
12685
0
  size_t path_start = 0;
12686
0
  size_t path_end = 0;
12687
0
  size_t query_start = std::string_view::npos;
12688
0
  size_t hash_start = std::string_view::npos;
12689
0
  bool has_path = false;
12690
0
  bool maybe_dot_segment = false;
12691
12692
0
  if (first == '/' || path_relative) {
12693
0
    has_path = true;
12694
0
    path_start = 0;
12695
0
    if (first == '/') {
12696
0
      i = 1;
12697
0
    }
12698
0
    scan_path_run(b, i, len, maybe_dot_segment);
12699
0
    if (i < len) {
12700
0
      const uint8_t cls = k_path[b[i]];
12701
0
      if (cls == 2) {
12702
0
        return false;
12703
0
      }
12704
0
    }
12705
0
    path_end = i;
12706
0
    if (i < len && b[i] == '?') {
12707
0
      query_start = i;
12708
0
      ++i;
12709
0
      scan_query_run(b, i, len);
12710
0
      if (i < len) {
12711
0
        if (b[i] != '#') {
12712
0
          return false;
12713
0
        }
12714
0
        hash_start = i;
12715
0
        ++i;
12716
0
        scan_hash_run(b, i, len);
12717
0
        if (i < len) {
12718
0
          return false;
12719
0
        }
12720
0
      }
12721
0
    } else if (i < len && b[i] == '#') {
12722
0
      hash_start = i;
12723
0
      ++i;
12724
0
      scan_hash_run(b, i, len);
12725
0
      if (i < len) {
12726
0
        return false;
12727
0
      }
12728
0
    } else if (i < len) {
12729
0
      return false;
12730
0
    }
12731
0
  } else if (first == '?') {
12732
0
    query_start = 0;
12733
0
    i = 1;
12734
0
    scan_query_run(b, i, len);
12735
0
    if (i < len) {
12736
0
      if (b[i] != '#') {
12737
0
        return false;
12738
0
      }
12739
0
      hash_start = i;
12740
0
      ++i;
12741
0
      scan_hash_run(b, i, len);
12742
0
      if (i < len) {
12743
0
        return false;
12744
0
      }
12745
0
    }
12746
0
  } else {
12747
0
    hash_start = 0;
12748
0
    i = 1;
12749
0
    scan_hash_run(b, i, len);
12750
0
    if (i < len) {
12751
0
      return false;
12752
0
    }
12753
0
  }
12754
12755
0
  if (has_path && maybe_dot_segment) {
12756
0
    const std::string_view path_body(input.data() + path_start,
12757
0
                                     path_end - path_start);
12758
0
    if (path_has_dot_segment(path_body)) {
12759
0
      return false;
12760
0
    }
12761
0
  }
12762
12763
0
  out = base;
12764
0
  out.is_valid = true;
12765
0
  out.has_opaque_path = false;
12766
12767
0
  const size_t q_end =
12768
0
      (hash_start != std::string_view::npos) ? hash_start : len;
12769
0
  const bool has_query = query_start != std::string_view::npos;
12770
0
  const bool has_hash = hash_start != std::string_view::npos;
12771
0
  const std::string_view query =
12772
0
      has_query ? std::string_view(input.data() + query_start + 1,
12773
0
                                   q_end - query_start - 1)
12774
0
                : std::string_view{};
12775
0
  const std::string_view hash =
12776
0
      has_hash ? std::string_view(input.data() + hash_start + 1,
12777
0
                                  len - hash_start - 1)
12778
0
               : std::string_view{};
12779
12780
0
  if constexpr (is_aggregator) {
12781
0
    if (first == '/' || first == '?' || path_relative) {
12782
0
      out.clear_hash();
12783
0
      out.clear_search();
12784
0
    }
12785
0
    if (first == '/') {
12786
0
      out.update_base_pathname(input.substr(path_start, path_end - path_start));
12787
0
    } else if (path_relative) {
12788
0
      const std::string_view base_path = out.get_pathname();
12789
0
      const size_t slash = base_path.rfind('/');
12790
0
      const std::string_view prefix = (slash == std::string_view::npos)
12791
0
                                          ? std::string_view("/")
12792
0
                                          : base_path.substr(0, slash + 1);
12793
0
      const std::string_view rel(input.data() + path_start,
12794
0
                                 path_end - path_start);
12795
0
      std::string new_path;
12796
0
      new_path.reserve(prefix.size() + rel.size());
12797
0
      new_path.assign(prefix);
12798
0
      new_path.append(rel);
12799
0
      out.update_base_pathname(new_path);
12800
0
    }
12801
0
    if (has_query) {
12802
      // Do not use update_base_search: it strips a leading '?' and would
12803
      // collapse '??a=b' into '?a=b'.
12804
0
      out.components.search_start = static_cast<uint32_t>(out.buffer.size());
12805
0
      out.buffer += '?';
12806
0
      out.buffer.append(query);
12807
0
    }
12808
0
    if (has_hash) {
12809
0
      out.update_unencoded_base_hash(hash);
12810
0
    }
12811
0
  } else {
12812
0
    if (first == '/' || first == '?' || path_relative) {
12813
0
      out.hash.reset();
12814
0
    }
12815
0
    if (first == '/') {
12816
0
      out.query.reset();
12817
0
      out.path.assign(input.substr(path_start, path_end - path_start));
12818
0
    } else if (path_relative) {
12819
0
      out.query.reset();
12820
0
      const size_t slash = out.path.rfind('/');
12821
0
      if (slash == std::string::npos) {
12822
0
        out.path = '/';
12823
0
      } else {
12824
0
        out.path.resize(slash + 1);
12825
0
      }
12826
0
      out.path.append(input.substr(path_start, path_end - path_start));
12827
0
    }
12828
0
    if (has_query) {
12829
0
      out.query.emplace(query);
12830
0
    }
12831
0
    if (has_hash) {
12832
0
      out.hash.emplace(hash);
12833
0
    }
12834
0
  }
12835
0
  return true;
12836
0
}
Unexecuted instantiation: bool ada::parser::try_parse_simple_relative<ada::url>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const&, ada::url&)
bool ada::parser::try_parse_simple_relative<ada::url_aggregator>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const&, ada::url_aggregator&)
Line
Count
Source
12659
258k
                                                result_type& out) {
12660
258k
  constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>;
12661
258k
  constexpr bool is_aggregator =
12662
258k
      std::is_same_v<result_type, ada::url_aggregator>;
12663
258k
  static_assert(is_ada_url || is_aggregator);
12664
12665
258k
  if (!base.is_special() || base.type == ada::scheme::type::FILE ||
12666
258k
      base.has_opaque_path || input.empty()) {
12667
0
    return false;
12668
0
  }
12669
258k
  const auto* b = reinterpret_cast<const uint8_t*>(input.data());
12670
258k
  const size_t len = input.size();
12671
258k
  const uint8_t first = b[0];
12672
258k
  const bool path_relative = first != '/' && first != '?' && first != '#';
12673
258k
  if (first == '/' && len > 1 && (b[1] == '/' || b[1] == '\\')) {
12674
0
    return false;
12675
0
  }
12676
  // A ':' before the first / ? # is a scheme, not a path segment.
12677
258k
  if (path_relative) {
12678
258k
    const size_t delim = input.find_first_of("/?#:");
12679
258k
    if (delim != std::string_view::npos && input[delim] == ':') {
12680
258k
      return false;
12681
258k
    }
12682
258k
  }
12683
12684
0
  size_t i = 0;
12685
0
  size_t path_start = 0;
12686
0
  size_t path_end = 0;
12687
0
  size_t query_start = std::string_view::npos;
12688
0
  size_t hash_start = std::string_view::npos;
12689
0
  bool has_path = false;
12690
0
  bool maybe_dot_segment = false;
12691
12692
0
  if (first == '/' || path_relative) {
12693
0
    has_path = true;
12694
0
    path_start = 0;
12695
0
    if (first == '/') {
12696
0
      i = 1;
12697
0
    }
12698
0
    scan_path_run(b, i, len, maybe_dot_segment);
12699
0
    if (i < len) {
12700
0
      const uint8_t cls = k_path[b[i]];
12701
0
      if (cls == 2) {
12702
0
        return false;
12703
0
      }
12704
0
    }
12705
0
    path_end = i;
12706
0
    if (i < len && b[i] == '?') {
12707
0
      query_start = i;
12708
0
      ++i;
12709
0
      scan_query_run(b, i, len);
12710
0
      if (i < len) {
12711
0
        if (b[i] != '#') {
12712
0
          return false;
12713
0
        }
12714
0
        hash_start = i;
12715
0
        ++i;
12716
0
        scan_hash_run(b, i, len);
12717
0
        if (i < len) {
12718
0
          return false;
12719
0
        }
12720
0
      }
12721
0
    } else if (i < len && b[i] == '#') {
12722
0
      hash_start = i;
12723
0
      ++i;
12724
0
      scan_hash_run(b, i, len);
12725
0
      if (i < len) {
12726
0
        return false;
12727
0
      }
12728
0
    } else if (i < len) {
12729
0
      return false;
12730
0
    }
12731
0
  } else if (first == '?') {
12732
0
    query_start = 0;
12733
0
    i = 1;
12734
0
    scan_query_run(b, i, len);
12735
0
    if (i < len) {
12736
0
      if (b[i] != '#') {
12737
0
        return false;
12738
0
      }
12739
0
      hash_start = i;
12740
0
      ++i;
12741
0
      scan_hash_run(b, i, len);
12742
0
      if (i < len) {
12743
0
        return false;
12744
0
      }
12745
0
    }
12746
0
  } else {
12747
0
    hash_start = 0;
12748
0
    i = 1;
12749
0
    scan_hash_run(b, i, len);
12750
0
    if (i < len) {
12751
0
      return false;
12752
0
    }
12753
0
  }
12754
12755
0
  if (has_path && maybe_dot_segment) {
12756
0
    const std::string_view path_body(input.data() + path_start,
12757
0
                                     path_end - path_start);
12758
0
    if (path_has_dot_segment(path_body)) {
12759
0
      return false;
12760
0
    }
12761
0
  }
12762
12763
0
  out = base;
12764
0
  out.is_valid = true;
12765
0
  out.has_opaque_path = false;
12766
12767
0
  const size_t q_end =
12768
0
      (hash_start != std::string_view::npos) ? hash_start : len;
12769
0
  const bool has_query = query_start != std::string_view::npos;
12770
0
  const bool has_hash = hash_start != std::string_view::npos;
12771
0
  const std::string_view query =
12772
0
      has_query ? std::string_view(input.data() + query_start + 1,
12773
0
                                   q_end - query_start - 1)
12774
0
                : std::string_view{};
12775
0
  const std::string_view hash =
12776
0
      has_hash ? std::string_view(input.data() + hash_start + 1,
12777
0
                                  len - hash_start - 1)
12778
0
               : std::string_view{};
12779
12780
0
  if constexpr (is_aggregator) {
12781
0
    if (first == '/' || first == '?' || path_relative) {
12782
0
      out.clear_hash();
12783
0
      out.clear_search();
12784
0
    }
12785
0
    if (first == '/') {
12786
0
      out.update_base_pathname(input.substr(path_start, path_end - path_start));
12787
0
    } else if (path_relative) {
12788
0
      const std::string_view base_path = out.get_pathname();
12789
0
      const size_t slash = base_path.rfind('/');
12790
0
      const std::string_view prefix = (slash == std::string_view::npos)
12791
0
                                          ? std::string_view("/")
12792
0
                                          : base_path.substr(0, slash + 1);
12793
0
      const std::string_view rel(input.data() + path_start,
12794
0
                                 path_end - path_start);
12795
0
      std::string new_path;
12796
0
      new_path.reserve(prefix.size() + rel.size());
12797
0
      new_path.assign(prefix);
12798
0
      new_path.append(rel);
12799
0
      out.update_base_pathname(new_path);
12800
0
    }
12801
0
    if (has_query) {
12802
      // Do not use update_base_search: it strips a leading '?' and would
12803
      // collapse '??a=b' into '?a=b'.
12804
0
      out.components.search_start = static_cast<uint32_t>(out.buffer.size());
12805
0
      out.buffer += '?';
12806
0
      out.buffer.append(query);
12807
0
    }
12808
0
    if (has_hash) {
12809
0
      out.update_unencoded_base_hash(hash);
12810
0
    }
12811
  } else {
12812
    if (first == '/' || first == '?' || path_relative) {
12813
      out.hash.reset();
12814
    }
12815
    if (first == '/') {
12816
      out.query.reset();
12817
      out.path.assign(input.substr(path_start, path_end - path_start));
12818
    } else if (path_relative) {
12819
      out.query.reset();
12820
      const size_t slash = out.path.rfind('/');
12821
      if (slash == std::string::npos) {
12822
        out.path = '/';
12823
      } else {
12824
        out.path.resize(slash + 1);
12825
      }
12826
      out.path.append(input.substr(path_start, path_end - path_start));
12827
    }
12828
    if (has_query) {
12829
      out.query.emplace(query);
12830
    }
12831
    if (has_hash) {
12832
      out.hash.emplace(hash);
12833
    }
12834
  }
12835
0
  return true;
12836
0
}
12837
12838
template <class result_type, bool store_values>
12839
result_type parse_url_impl(std::string_view user_input,
12840
1.44M
                           const result_type* base_url) {
12841
  // We can specialize the implementation per type.
12842
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12843
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12844
  // something else } is free (at runtime). This means that ada::url_aggregator
12845
  // and ada::url **do not have to support the exact same API**.
12846
1.44M
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
12847
1.44M
  constexpr bool result_type_is_ada_url_aggregator =
12848
1.44M
      std::is_same_v<url_aggregator, result_type>;
12849
1.44M
  static_assert(result_type_is_ada_url ||
12850
1.44M
                result_type_is_ada_url_aggregator);  // We don't support
12851
                                                     // anything else for now.
12852
12853
1.44M
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12854
1.44M
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12855
1.44M
          ")");
12856
12857
1.44M
  result_type url{};
12858
12859
1.44M
  const uint32_t max_input_length = ada::get_max_input_length();
12860
12861
  // Normalization (percent-encoding, IDNA) can push the serialized URL past
12862
  // max_input_length even when the input fit under it. The check at the end of
12863
  // the state machine covers URLs that run to completion, but several states
12864
  // return early after appending a query or fragment, so run the same check on
12865
  // those exits too. Without this, a query- or fragment-terminated URL such as
12866
  // file://x/?<...> or https://user@x/?<...> is accepted while the equivalent
12867
  // https://x/?<...> that takes the absolute fast path is rejected.
12868
1.44M
  const auto enforce_max_input_length = [&]() {
12869
186k
    if constexpr (store_values) {
12870
186k
      if (url.is_valid) {
12871
186k
        if constexpr (result_type_is_ada_url_aggregator) {
12872
186k
          if (url.buffer.size() > max_input_length) [[unlikely]] {
12873
0
            url.is_valid = false;
12874
0
          }
12875
186k
        } else {
12876
0
          if (url.get_href_size() > max_input_length) [[unlikely]] {
12877
0
            url.is_valid = false;
12878
0
          }
12879
0
        }
12880
186k
      }
12881
186k
    }
12882
186k
  };
Unexecuted instantiation: ada::parser::parse_url_impl<ada::url, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url const*)::{lambda()#1}::operator()() const
ada::parser::parse_url_impl<ada::url_aggregator, true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)::{lambda()#1}::operator()() const
Line
Count
Source
12868
186k
  const auto enforce_max_input_length = [&]() {
12869
186k
    if constexpr (store_values) {
12870
186k
      if (url.is_valid) {
12871
186k
        if constexpr (result_type_is_ada_url_aggregator) {
12872
186k
          if (url.buffer.size() > max_input_length) [[unlikely]] {
12873
0
            url.is_valid = false;
12874
0
          }
12875
        } else {
12876
          if (url.get_href_size() > max_input_length) [[unlikely]] {
12877
            url.is_valid = false;
12878
          }
12879
        }
12880
186k
      }
12881
186k
    }
12882
186k
  };
Unexecuted instantiation: ada::parser::parse_url_impl<ada::url_aggregator, false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, ada::url_aggregator const*)::{lambda()#1}::operator()() const
12883
12884
  // We refuse to parse URL strings that exceed the maximum input length.
12885
  // By default, this is 4GB but can be configured via
12886
  // ada::set_max_input_length().
12887
1.44M
  if (user_input.size() > max_input_length) [[unlikely]] {
12888
0
    url.is_valid = false;
12889
0
  }
12890
  // Going forward, user_input.size() is in [0,
12891
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12892
  // base, or the optional_url was invalid, we must return.
12893
1.44M
  if (base_url != nullptr) {
12894
258k
    url.is_valid &= base_url->is_valid;
12895
258k
  }
12896
1.44M
  if (!url.is_valid) {
12897
0
    return url;
12898
0
  }
12899
12900
  // Simple absolute / relative fast paths (before tabs/newline scan).
12901
1.44M
  if constexpr (store_values) {
12902
1.44M
    bool hit_fast_path = false;
12903
1.44M
    if (base_url == nullptr) {
12904
      // IPv4/IPv6 and userinfo miss the fast path. Skip the never_inline
12905
      // call so those URLs (including SetHref) do not pay for a miss.
12906
1.18M
      const auto* p = reinterpret_cast<const uint8_t*>(user_input.data());
12907
1.18M
      const size_t n = user_input.size();
12908
1.18M
      size_t host_start = 0;
12909
1.18M
      if (n >= 8 && p[4] == ':' && p[5] == '/' && p[6] == '/') {
12910
613
        host_start = 7;
12911
1.18M
      } else if (n >= 9 && p[5] == ':' && p[6] == '/' && p[7] == '/') {
12912
1.09M
        host_start = 8;
12913
1.09M
      }
12914
1.18M
      const uint8_t host_first = host_start != 0 ? p[host_start] : 0;
12915
1.18M
      const bool skip_ip =
12916
1.18M
          host_first == '[' || (host_first >= '0' && host_first <= '9');
12917
1.18M
      const bool skip_userinfo =
12918
1.18M
          host_start != 0 && authority_has_at(p, host_start, n);
12919
1.18M
      hit_fast_path = !skip_ip && !skip_userinfo &&
12920
1.13M
                      try_parse_simple_absolute(user_input, url);
12921
1.18M
    } else {
12922
258k
      hit_fast_path = try_parse_simple_relative(user_input, *base_url, url);
12923
258k
    }
12924
1.44M
    if (hit_fast_path) {
12925
658k
      if constexpr (result_type_is_ada_url_aggregator) {
12926
658k
        if (url.buffer.size() > max_input_length) [[unlikely]] {
12927
0
          url.is_valid = false;
12928
0
        }
12929
658k
      } else {
12930
        // For a small absolute input, even worst-case normalization cannot
12931
        // exceed the limit: percent encoding expands at most 3x and IDNA at
12932
        // most 4.5x. Avoid traversing every stored component on the common
12933
        // default-limit path.
12934
0
        if ((base_url != nullptr ||
12935
0
             user_input.size() > static_cast<size_t>(max_input_length) / 5) &&
12936
0
            url.get_href_size() > max_input_length) [[unlikely]] {
12937
0
          url.is_valid = false;
12938
0
        }
12939
0
      }
12940
658k
      return url;
12941
658k
    }
12942
1.44M
  }
12943
12944
781k
  state state = state::SCHEME_START;
12945
12946
1.44M
  std::string tmp_buffer;
12947
1.44M
  std::string_view url_data;
12948
1.44M
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
12949
13.0k
    tmp_buffer = user_input;
12950
    // Optimization opportunity: Instead of copying and then pruning, we could
12951
    // just directly build the string from user_input.
12952
13.0k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12953
13.0k
    url_data = tmp_buffer;
12954
1.42M
  } else [[likely]] {
12955
1.42M
    url_data = user_input;
12956
1.42M
  }
12957
12958
  // Leading and trailing control characters are uncommon and easy to deal with
12959
  // (no performance concern).
12960
1.44M
  helpers::trim_c0_whitespace(url_data);
12961
12962
1.44M
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
12963
    // Most of the time, we just need user_input.size().
12964
    // In some instances, we may need a bit more.
12965
    ///////////////////////////
12966
    // This is *very* important. This line should *not* be removed
12967
    // hastily. There are principled reasons why reserve is important
12968
    // for performance. If you have a benchmark with small inputs,
12969
    // it may not matter, but in other instances, it could.
12970
    ////
12971
    // This rounds up to the next power of two.
12972
    // We know that user_input.size() is in [0,
12973
    // std::numeric_limits<uint32_t>::max).
12974
1.44M
    uint32_t reserve_capacity =
12975
1.44M
        (0xFFFFFFFF >>
12976
1.44M
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12977
1.44M
        1;
12978
1.44M
    url.reserve(reserve_capacity);
12979
1.44M
  }
12980
12981
  // Optimization opportunity. Most websites do not have fragment.
12982
1.44M
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12983
  // We add it last so that an implementation like ada::url_aggregator
12984
  // can append it last to its internal buffer, thus improving performance.
12985
12986
  // Here url_data no longer has its fragment.
12987
  // We are going to access the data from url_data (it is immutable).
12988
  // At any given time, we are pointing at byte 'input_position' in url_data.
12989
  // The input_position variable should range from 0 to input_size.
12990
  // It is illegal to access url_data at input_size.
12991
1.44M
  size_t input_position = 0;
12992
1.44M
  const size_t input_size = url_data.size();
12993
  // Keep running the following state machine by switching on state.
12994
  // If after a run pointer points to the EOF code point, go to the next step.
12995
  // Otherwise, increase pointer by 1 and continue with the state machine.
12996
  // We never decrement input_position.
12997
5.15M
  while (input_position <= input_size) {
12998
4.35M
    ada_log("In parsing at ", input_position, " out of ", input_size,
12999
4.35M
            " in state ", ada::to_string(state));
13000
4.35M
    switch (state) {
13001
781k
      case state::SCHEME_START: {
13002
781k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13003
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13004
        // state to scheme state.
13005
781k
        if ((input_position != input_size) &&
13006
781k
            checkers::is_alpha(url_data[input_position])) {
13007
752k
          state = state::SCHEME;
13008
752k
          input_position++;
13009
752k
        } else {
13010
          // Otherwise, if state override is not given, set state to no scheme
13011
          // state and decrease pointer by 1.
13012
29.0k
          state = state::NO_SCHEME;
13013
29.0k
        }
13014
781k
        break;
13015
0
      }
13016
752k
      case state::SCHEME: {
13017
752k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13018
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13019
        // append c, lowercased, to buffer.
13020
3.73M
        while ((input_position != input_size) &&
13021
3.73M
               (unicode::is_alnum_plus(url_data[input_position]))) {
13022
2.98M
          input_position++;
13023
2.98M
        }
13024
        // Otherwise, if c is U+003A (:), then:
13025
752k
        if ((input_position != input_size) &&
13026
752k
            (url_data[input_position] == ':')) {
13027
752k
          ada_log("SCHEME the scheme should be ",
13028
752k
                  url_data.substr(0, input_position));
13029
752k
          if constexpr (result_type_is_ada_url) {
13030
0
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13031
0
              return url;
13032
0
            }
13033
752k
          } else {
13034
            // we pass the colon along instead of painfully adding it back.
13035
752k
            if (!url.parse_scheme_with_colon(
13036
752k
                    url_data.substr(0, input_position + 1))) {
13037
0
              return url;
13038
0
            }
13039
752k
          }
13040
752k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13041
13042
          // If url's scheme is "file", then:
13043
          // NOLINTNEXTLINE(bugprone-branch-clone)
13044
752k
          if (url.type == scheme::type::FILE) {
13045
            // Set state to file state.
13046
0
            state = state::FILE;
13047
0
          }
13048
          // Otherwise, if url is special, base is non-null, and base's scheme
13049
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13050
          // != nullptr is false.
13051
752k
          else if (url.is_special() && base_url != nullptr &&
13052
258k
                   base_url->type == url.type) {
13053
            // Set state to special relative or authority state.
13054
258k
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13055
258k
          }
13056
          // Otherwise, if url is special, set state to special authority
13057
          // slashes state.
13058
494k
          else if (url.is_special()) {
13059
468k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13060
468k
          }
13061
          // Otherwise, if remaining starts with an U+002F (/), set state to
13062
          // path or authority state and increase pointer by 1.
13063
25.6k
          else if (input_position + 1 < input_size &&
13064
25.4k
                   url_data[input_position + 1] == '/') {
13065
24.8k
            state = state::PATH_OR_AUTHORITY;
13066
24.8k
            input_position++;
13067
24.8k
          }
13068
          // Otherwise, set url's path to the empty string and set state to
13069
          // opaque path state.
13070
838
          else {
13071
838
            state = state::OPAQUE_PATH;
13072
838
          }
13073
752k
        }
13074
        // Otherwise, if state override is not given, set buffer to the empty
13075
        // string, state to no scheme state, and start over (from the first code
13076
        // point in input).
13077
0
        else {
13078
0
          state = state::NO_SCHEME;
13079
0
          input_position = 0;
13080
0
          break;
13081
0
        }
13082
752k
        input_position++;
13083
752k
        break;
13084
752k
      }
13085
29.0k
      case state::NO_SCHEME: {
13086
29.0k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13087
        // The fragment was pruned from url_data before the state machine ran,
13088
        // so 'c is U+0023 (#)' holds exactly when a fragment was found and
13089
        // nothing else remains in front of it.
13090
29.0k
        const bool c_is_hash =
13091
29.0k
            fragment.has_value() && input_position == input_size;
13092
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13093
        // validation error, return failure.
13094
29.0k
        if (base_url == nullptr || (base_url->has_opaque_path && !c_is_hash)) {
13095
29.0k
          ada_log("NO_SCHEME validation error");
13096
29.0k
          url.is_valid = false;
13097
29.0k
          return url;
13098
29.0k
        }
13099
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13100
        // set url's scheme to base's scheme, url's path to base's path, url's
13101
        // query to base's query, and set state to fragment state.
13102
0
        else if (base_url->has_opaque_path && c_is_hash) {
13103
0
          ada_log("NO_SCHEME opaque base with fragment");
13104
0
          url.copy_scheme(*base_url);
13105
0
          url.has_opaque_path = base_url->has_opaque_path;
13106
13107
0
          if constexpr (result_type_is_ada_url) {
13108
0
            url.path = base_url->path;
13109
0
            url.query = base_url->query;
13110
0
          } else {
13111
0
            url.update_base_pathname(base_url->get_pathname());
13112
0
            if (base_url->has_search()) {
13113
              // get_search() returns "" for an empty query string (URL ends
13114
              // with '?'). update_base_search("") would incorrectly clear the
13115
              // query, so pass "?" to preserve the empty query distinction.
13116
0
              auto s = base_url->get_search();
13117
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13118
0
            }
13119
0
          }
13120
0
          url.update_unencoded_base_hash(*fragment);
13121
0
          enforce_max_input_length();
13122
0
          return url;
13123
0
        }
13124
        // Otherwise, if base's scheme is not "file", set state to relative
13125
        // state and decrease pointer by 1.
13126
        // NOLINTNEXTLINE(bugprone-branch-clone)
13127
0
        else if (base_url->type != scheme::type::FILE) {
13128
0
          ada_log("NO_SCHEME non-file relative path");
13129
0
          state = state::RELATIVE_SCHEME;
13130
0
        }
13131
        // Otherwise, set state to file state and decrease pointer by 1.
13132
0
        else {
13133
0
          ada_log("NO_SCHEME file base type");
13134
0
          state = state::FILE;
13135
0
        }
13136
0
        break;
13137
29.0k
      }
13138
727k
      case state::AUTHORITY: {
13139
727k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13140
        // most URLs have no @. Having no @ tells us that we don't have to worry
13141
        // about AUTHORITY. Of course, we could have @ and still not have to
13142
        // worry about AUTHORITY.
13143
        // TODO: Instead of just collecting a bool, collect the location of the
13144
        // '@' and do something useful with it.
13145
        // TODO: We could do various processing early on, using a single pass
13146
        // over the string to collect information about it, e.g., telling us
13147
        // whether there is a @ and if so, where (or how many).
13148
13149
        // Check if url data contains an @.
13150
727k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13151
700k
          state = state::HOST;
13152
700k
          break;
13153
700k
        }
13154
26.3k
        bool at_sign_seen{false};
13155
26.3k
        bool password_token_seen{false};
13156
        /**
13157
         * We expect something of the sort...
13158
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13159
         * --------^
13160
         */
13161
80.9k
        do {
13162
80.9k
          std::string_view view = url_data.substr(input_position);
13163
          // The delimiters are @, /, ? \\.
13164
80.9k
          size_t location =
13165
80.9k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13166
80.9k
                               : helpers::find_authority_delimiter(view);
13167
80.9k
          std::string_view authority_view = view.substr(0, location);
13168
80.9k
          size_t end_of_authority = input_position + authority_view.size();
13169
          // If c is U+0040 (@), then:
13170
80.9k
          if ((end_of_authority != input_size) &&
13171
77.7k
              (url_data[end_of_authority] == '@')) {
13172
            // If atSignSeen is true, then prepend "%40" to buffer.
13173
54.5k
            if (at_sign_seen) {
13174
30.0k
              if (password_token_seen) {
13175
12.2k
                if constexpr (result_type_is_ada_url) {
13176
0
                  url.password += "%40";
13177
12.2k
                } else {
13178
12.2k
                  url.append_base_password("%40");
13179
12.2k
                }
13180
17.8k
              } else {
13181
17.8k
                if constexpr (result_type_is_ada_url) {
13182
0
                  url.username += "%40";
13183
17.8k
                } else {
13184
17.8k
                  url.append_base_username("%40");
13185
17.8k
                }
13186
17.8k
              }
13187
30.0k
            }
13188
13189
54.5k
            at_sign_seen = true;
13190
13191
54.5k
            if (!password_token_seen) {
13192
42.3k
              size_t password_token_location = authority_view.find(':');
13193
42.3k
              password_token_seen =
13194
42.3k
                  password_token_location != std::string_view::npos;
13195
13196
42.3k
              if constexpr (store_values) {
13197
42.3k
                if (!password_token_seen) {
13198
34.3k
                  if constexpr (result_type_is_ada_url) {
13199
0
                    url.username += unicode::percent_encode(
13200
0
                        authority_view,
13201
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13202
34.3k
                  } else {
13203
34.3k
                    url.append_base_username(unicode::percent_encode(
13204
34.3k
                        authority_view,
13205
34.3k
                        character_sets::USERINFO_PERCENT_ENCODE));
13206
34.3k
                  }
13207
34.3k
                } else {
13208
7.92k
                  if constexpr (result_type_is_ada_url) {
13209
0
                    url.username += unicode::percent_encode(
13210
0
                        authority_view.substr(0, password_token_location),
13211
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13212
0
                    url.password += unicode::percent_encode(
13213
0
                        authority_view.substr(password_token_location + 1),
13214
0
                        character_sets::USERINFO_PERCENT_ENCODE);
13215
7.92k
                  } else {
13216
7.92k
                    url.append_base_username(unicode::percent_encode(
13217
7.92k
                        authority_view.substr(0, password_token_location),
13218
7.92k
                        character_sets::USERINFO_PERCENT_ENCODE));
13219
7.92k
                    url.append_base_password(unicode::percent_encode(
13220
7.92k
                        authority_view.substr(password_token_location + 1),
13221
7.92k
                        character_sets::USERINFO_PERCENT_ENCODE));
13222
7.92k
                  }
13223
7.92k
                }
13224
42.3k
              }
13225
42.3k
            } else if constexpr (store_values) {
13226
12.2k
              if constexpr (result_type_is_ada_url) {
13227
0
                url.password += unicode::percent_encode(
13228
0
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13229
12.2k
              } else {
13230
12.2k
                url.append_base_password(unicode::percent_encode(
13231
12.2k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13232
12.2k
              }
13233
12.2k
            }
13234
54.5k
          }
13235
          // Otherwise, if one of the following is true:
13236
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13237
          // - url is special and c is U+005C (\)
13238
26.3k
          else if (end_of_authority == input_size ||
13239
23.2k
                   url_data[end_of_authority] == '/' ||
13240
1.49k
                   url_data[end_of_authority] == '?' ||
13241
26.3k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13242
            // If atSignSeen is true and authority_view is the empty string,
13243
            // validation error, return failure.
13244
26.3k
            if (at_sign_seen && authority_view.empty()) {
13245
6.44k
              url.is_valid = false;
13246
6.44k
              return url;
13247
6.44k
            }
13248
19.9k
            state = state::HOST;
13249
19.9k
            break;
13250
26.3k
          }
13251
54.5k
          if (end_of_authority == input_size) {
13252
0
            if constexpr (store_values) {
13253
0
              if (fragment.has_value()) {
13254
0
                url.update_unencoded_base_hash(*fragment);
13255
0
              }
13256
0
            }
13257
0
            enforce_max_input_length();
13258
0
            return url;
13259
0
          }
13260
54.5k
          input_position = end_of_authority + 1;
13261
54.5k
        } while (true);
13262
13263
19.9k
        break;
13264
26.3k
      }
13265
258k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13266
258k
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13267
258k
                helpers::substring(url_data, input_position));
13268
13269
        // If c is U+002F (/) and remaining starts with U+002F (/),
13270
        // then set state to special authority ignore slashes state and increase
13271
        // pointer by 1.
13272
258k
        if (url_data.substr(input_position, 2) == "//") {
13273
258k
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13274
258k
          input_position += 2;
13275
258k
        } else {
13276
          // Otherwise, validation error, set state to relative state and
13277
          // decrease pointer by 1.
13278
0
          state = state::RELATIVE_SCHEME;
13279
0
        }
13280
13281
258k
        break;
13282
26.3k
      }
13283
24.8k
      case state::PATH_OR_AUTHORITY: {
13284
24.8k
        ada_log("PATH_OR_AUTHORITY ",
13285
24.8k
                helpers::substring(url_data, input_position));
13286
13287
        // If c is U+002F (/), then set state to authority state.
13288
24.8k
        if ((input_position != input_size) &&
13289
1.06k
            (url_data[input_position] == '/')) {
13290
612
          state = state::AUTHORITY;
13291
612
          input_position++;
13292
24.2k
        } else {
13293
          // Otherwise, set state to path state, and decrease pointer by 1.
13294
24.2k
          state = state::PATH;
13295
24.2k
        }
13296
13297
24.8k
        break;
13298
26.3k
      }
13299
0
      case state::RELATIVE_SCHEME: {
13300
0
        ada_log("RELATIVE_SCHEME ",
13301
0
                helpers::substring(url_data, input_position));
13302
13303
        // Set url's scheme to base's scheme.
13304
0
        url.copy_scheme(*base_url);
13305
13306
        // If c is U+002F (/), then set state to relative slash state.
13307
0
        if ((input_position != input_size) &&
13308
            // NOLINTNEXTLINE(bugprone-branch-clone)
13309
0
            (url_data[input_position] == '/')) {
13310
0
          ada_log(
13311
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13312
0
              "slash state");
13313
0
          state = state::RELATIVE_SLASH;
13314
0
        } else if (url.is_special() && (input_position != input_size) &&
13315
0
                   (url_data[input_position] == '\\')) {
13316
          // Otherwise, if url is special and c is U+005C (\), validation error,
13317
          // set state to relative slash state.
13318
0
          ada_log(
13319
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13320
0
              "error, set state to relative slash state");
13321
0
          state = state::RELATIVE_SLASH;
13322
0
        } else {
13323
0
          ada_log("RELATIVE_SCHEME otherwise");
13324
          // Set url's username to base's username, url's password to base's
13325
          // password, url's host to base's host, url's port to base's port,
13326
          // url's path to a clone of base's path, and url's query to base's
13327
          // query.
13328
0
          if constexpr (result_type_is_ada_url) {
13329
0
            url.username = base_url->username;
13330
0
            url.password = base_url->password;
13331
0
            url.host = base_url->host;
13332
0
            url.port = base_url->port;
13333
            // cloning the base path includes cloning the has_opaque_path flag
13334
0
            url.has_opaque_path = base_url->has_opaque_path;
13335
0
            url.path = base_url->path;
13336
0
            url.query = base_url->query;
13337
0
          } else {
13338
0
            url.update_base_authority(base_url->get_href(),
13339
0
                                      base_url->get_components());
13340
0
            url.update_host_to_base_host(base_url->get_hostname());
13341
0
            url.update_base_port(base_url->retrieve_base_port());
13342
            // cloning the base path includes cloning the has_opaque_path flag
13343
0
            url.has_opaque_path = base_url->has_opaque_path;
13344
0
            url.update_base_pathname(base_url->get_pathname());
13345
0
            if (base_url->has_search()) {
13346
              // get_search() returns "" for an empty query string (URL ends
13347
              // with '?'). update_base_search("") would incorrectly clear the
13348
              // query, so pass "?" to preserve the empty query distinction.
13349
0
              auto s = base_url->get_search();
13350
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13351
0
            }
13352
0
          }
13353
13354
0
          url.has_opaque_path = base_url->has_opaque_path;
13355
13356
          // If c is U+003F (?), then set url's query to the empty string, and
13357
          // state to query state.
13358
0
          if ((input_position != input_size) &&
13359
0
              (url_data[input_position] == '?')) {
13360
0
            state = state::QUERY;
13361
0
          }
13362
          // Otherwise, if c is not the EOF code point:
13363
0
          else if (input_position != input_size) {
13364
            // Set url's query to null.
13365
0
            url.clear_search();
13366
0
            if constexpr (result_type_is_ada_url) {
13367
              // Shorten url's path.
13368
0
              helpers::shorten_path(url.path, url.type);
13369
0
            } else {
13370
0
              std::string_view path = url.get_pathname();
13371
0
              if (helpers::shorten_path(path, url.type)) {
13372
0
                url.update_base_pathname(std::move(std::string(path)));
13373
0
              }
13374
0
            }
13375
            // Set state to path state and decrease pointer by 1.
13376
0
            state = state::PATH;
13377
0
            break;
13378
0
          }
13379
0
        }
13380
0
        input_position++;
13381
0
        break;
13382
0
      }
13383
0
      case state::RELATIVE_SLASH: {
13384
0
        ada_log("RELATIVE_SLASH ",
13385
0
                helpers::substring(url_data, input_position));
13386
13387
        // If url is special and c is U+002F (/) or U+005C (\), then:
13388
        // NOLINTNEXTLINE(bugprone-branch-clone)
13389
0
        if (url.is_special() && (input_position != input_size) &&
13390
0
            (url_data[input_position] == '/' ||
13391
0
             url_data[input_position] == '\\')) {
13392
          // Set state to special authority ignore slashes state.
13393
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13394
0
        }
13395
        // Otherwise, if c is U+002F (/), then set state to authority state.
13396
0
        else if ((input_position != input_size) &&
13397
0
                 (url_data[input_position] == '/')) {
13398
0
          state = state::AUTHORITY;
13399
0
        }
13400
        // Otherwise, set
13401
        // - url's username to base's username,
13402
        // - url's password to base's password,
13403
        // - url's host to base's host,
13404
        // - url's port to base's port,
13405
        // - state to path state, and then, decrease pointer by 1.
13406
0
        else {
13407
0
          if constexpr (result_type_is_ada_url) {
13408
0
            url.username = base_url->username;
13409
0
            url.password = base_url->password;
13410
0
            url.host = base_url->host;
13411
0
            url.port = base_url->port;
13412
0
          } else {
13413
0
            url.update_base_authority(base_url->get_href(),
13414
0
                                      base_url->get_components());
13415
0
            url.update_host_to_base_host(base_url->get_hostname());
13416
0
            url.update_base_port(base_url->retrieve_base_port());
13417
0
          }
13418
0
          state = state::PATH;
13419
0
          break;
13420
0
        }
13421
13422
0
        input_position++;
13423
0
        break;
13424
0
      }
13425
468k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13426
468k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13427
468k
                helpers::substring(url_data, input_position));
13428
13429
        // If c is U+002F (/) and remaining starts with U+002F (/),
13430
        // then set state to special authority ignore slashes state and increase
13431
        // pointer by 1.
13432
468k
        if (url_data.substr(input_position, 2) == "//") {
13433
468k
          input_position += 2;
13434
468k
        }
13435
13436
468k
        [[fallthrough]];
13437
468k
      }
13438
726k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13439
726k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13440
726k
                helpers::substring(url_data, input_position));
13441
13442
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13443
        // authority state and decrease pointer by 1.
13444
1.20M
        while ((input_position != input_size) &&
13445
736k
               ((url_data[input_position] == '/') ||
13446
477k
                (url_data[input_position] == '\\'))) {
13447
477k
          input_position++;
13448
477k
        }
13449
726k
        state = state::AUTHORITY;
13450
13451
726k
        break;
13452
468k
      }
13453
12.9k
      case state::QUERY: {
13454
12.9k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13455
12.9k
        if constexpr (store_values) {
13456
          // Let queryPercentEncodeSet be the special-query percent-encode set
13457
          // if url is special; otherwise the query percent-encode set.
13458
12.9k
          const uint8_t* query_percent_encode_set =
13459
12.9k
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13460
12.9k
                               : character_sets::QUERY_PERCENT_ENCODE;
13461
13462
          // Percent-encode after encoding, with encoding, buffer, and
13463
          // queryPercentEncodeSet, and append the result to url's query.
13464
12.9k
          url.update_base_search(url_data.substr(input_position),
13465
12.9k
                                 query_percent_encode_set);
13466
12.9k
          ada_log("QUERY update_base_search completed ");
13467
12.9k
          if (fragment.has_value()) {
13468
2.55k
            url.update_unencoded_base_hash(*fragment);
13469
2.55k
          }
13470
12.9k
        }
13471
12.9k
        enforce_max_input_length();
13472
12.9k
        return url;
13473
468k
      }
13474
720k
      case state::HOST: {
13475
720k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13476
13477
720k
        std::string_view host_view = url_data.substr(input_position);
13478
720k
        auto [location, found_colon] =
13479
720k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13480
720k
        input_position = (location != std::string_view::npos)
13481
720k
                             ? input_position + location
13482
720k
                             : input_size;
13483
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13484
        // Note: the 'found_colon' value is true if and only if a colon was
13485
        // encountered while not inside brackets.
13486
720k
        if (found_colon) {
13487
          // If buffer is the empty string, validation error, return failure.
13488
          // Let host be the result of host parsing buffer with url is not
13489
          // special.
13490
37.4k
          ada_log("HOST parsing ", host_view);
13491
37.4k
          if (!url.parse_host(host_view)) {
13492
7.00k
            return url;
13493
7.00k
          }
13494
30.4k
          ada_log("HOST parsing results in ", url.get_hostname());
13495
          // Set url's host to host, buffer to the empty string, and state to
13496
          // port state.
13497
30.4k
          state = state::PORT;
13498
30.4k
          input_position++;
13499
30.4k
        }
13500
        // Otherwise, if one of the following is true:
13501
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13502
        // - url is special and c is U+005C (\)
13503
        // The get_host_delimiter_location function either brings us to
13504
        // the colon outside of the bracket, or to one of those characters.
13505
683k
        else {
13506
          // If url is special and host_view is the empty string, validation
13507
          // error, return failure.
13508
683k
          if (host_view.empty() && url.is_special()) {
13509
468k
            url.is_valid = false;
13510
468k
            return url;
13511
468k
          }
13512
214k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13513
          // Let host be the result of host parsing host_view with url is not
13514
          // special.
13515
214k
          if (host_view.empty()) {
13516
137
            url.update_base_hostname("");
13517
214k
          } else if (!url.parse_host(host_view)) {
13518
80.2k
            return url;
13519
80.2k
          }
13520
134k
          ada_log("HOST parsing results in ", url.get_hostname(),
13521
134k
                  " href=", url.get_href());
13522
13523
          // Set url's host to host, and state to path start state.
13524
134k
          state = state::PATH_START;
13525
134k
        }
13526
13527
164k
        break;
13528
720k
      }
13529
164k
      case state::OPAQUE_PATH: {
13530
838
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13531
        // Opaque path, query, and fragment are structurally always valid:
13532
        // the parser would just percent-encode whatever is there. When we
13533
        // are not storing values (can_parse), we can return immediately.
13534
        // We must set has_opaque_path = true before returning so that when
13535
        // this URL is used as an internal base inside can_parse, NO_SCHEME
13536
        // correctly rejects relative inputs against an opaque-path base
13537
        // (e.g. can_parse("", &"W:") must return false).
13538
838
        if constexpr (!store_values) {
13539
0
          url.has_opaque_path = true;
13540
0
          return url;
13541
0
        }
13542
0
        std::string_view view = url_data.substr(input_position);
13543
        // If c is U+003F (?), then set url's query to the empty string and
13544
        // state to query state.
13545
838
        size_t location = view.find('?');
13546
838
        if (location != std::string_view::npos) {
13547
53
          view.remove_suffix(view.size() - location);
13548
53
          state = state::QUERY;
13549
53
          input_position += location + 1;
13550
785
        } else {
13551
785
          input_position = input_size + 1;
13552
785
        }
13553
838
        url.has_opaque_path = true;
13554
13555
        // This is a really unlikely scenario in real world. We should not seek
13556
        // to optimize it.
13557
838
        if (view.ends_with(' ')) {
13558
56
          std::string modified_view =
13559
56
              std::string(view.substr(0, view.size() - 1)) + "%20";
13560
56
          url.update_base_pathname(unicode::percent_encode(
13561
56
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13562
782
        } else {
13563
782
          url.update_base_pathname(unicode::percent_encode(
13564
782
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13565
782
        }
13566
838
        break;
13567
720k
      }
13568
30.4k
      case state::PORT: {
13569
30.4k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13570
30.4k
        std::string_view port_view = url_data.substr(input_position);
13571
30.4k
        input_position += url.parse_port(port_view, true);
13572
30.4k
        if (!url.is_valid) {
13573
3.76k
          return url;
13574
3.76k
        }
13575
26.6k
        state = state::PATH_START;
13576
26.6k
        [[fallthrough]];
13577
26.6k
      }
13578
161k
      case state::PATH_START: {
13579
161k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13580
        // Path, query, and fragment are structurally always valid: the
13581
        // parser would just percent-encode whatever is there. When we are
13582
        // not storing values (can_parse), we can return immediately since
13583
        // no subsequent state can invalidate the URL.
13584
161k
        if constexpr (!store_values) {
13585
0
          return url;
13586
0
        }
13587
13588
        // If url is special, then:
13589
161k
        if (url.is_special()) {
13590
          // Set state to path state.
13591
160k
          state = state::PATH;
13592
13593
          // Optimization: Avoiding going into PATH state improves the
13594
          // performance of urls ending with /.
13595
160k
          if (input_position == input_size) {
13596
29.9k
            if constexpr (store_values) {
13597
29.9k
              url.update_base_pathname("/");
13598
29.9k
              if (fragment.has_value()) {
13599
5.63k
                url.update_unencoded_base_hash(*fragment);
13600
5.63k
              }
13601
29.9k
            }
13602
29.9k
            enforce_max_input_length();
13603
29.9k
            return url;
13604
29.9k
          }
13605
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13606
          // by 1. We know that (input_position == input_size) is impossible
13607
          // here, because of the previous if-check.
13608
130k
          if ((url_data[input_position] != '/') &&
13609
11.7k
              (url_data[input_position] != '\\')) {
13610
9.73k
            break;
13611
9.73k
          }
13612
130k
        }
13613
        // Otherwise, if state override is not given and c is U+003F (?),
13614
        // set url's query to the empty string and state to query state.
13615
367
        else if ((input_position != input_size) &&
13616
80
                 (url_data[input_position] == '?')) {
13617
17
          state = state::QUERY;
13618
17
        }
13619
        // Otherwise, if c is not the EOF code point:
13620
350
        else if (input_position != input_size) {
13621
          // Set state to path state.
13622
63
          state = state::PATH;
13623
13624
          // If c is not U+002F (/), then decrease pointer by 1.
13625
63
          if (url_data[input_position] != '/') {
13626
0
            break;
13627
0
          }
13628
63
        }
13629
13630
121k
        input_position++;
13631
121k
        break;
13632
161k
      }
13633
155k
      case state::PATH: {
13634
155k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13635
        // Path, query, and fragment are structurally always valid: the
13636
        // parser would just percent-encode whatever is there. When we are
13637
        // not storing values (can_parse), we can return immediately since
13638
        // no subsequent state can invalidate the URL.
13639
155k
        if constexpr (!store_values) {
13640
0
          return url;
13641
0
        }
13642
0
        std::string_view view = url_data.substr(input_position);
13643
13644
        // Most time, we do not need percent encoding.
13645
        // Furthermore, we can immediately locate the '?'.
13646
155k
        size_t locofquestionmark = view.find('?');
13647
155k
        if (locofquestionmark != std::string_view::npos) {
13648
12.8k
          state = state::QUERY;
13649
12.8k
          view.remove_suffix(view.size() - locofquestionmark);
13650
12.8k
          input_position += locofquestionmark + 1;
13651
142k
        } else {
13652
142k
          input_position = input_size + 1;
13653
142k
        }
13654
155k
        if constexpr (store_values) {
13655
155k
          if constexpr (result_type_is_ada_url) {
13656
0
            helpers::parse_prepared_path(view, url.type, url.path);
13657
155k
          } else {
13658
155k
            url.consume_prepared_path(view);
13659
155k
            ADA_ASSERT_TRUE(url.validate());
13660
155k
          }
13661
155k
        }
13662
155k
        break;
13663
161k
      }
13664
0
      case state::FILE_SLASH: {
13665
0
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13666
13667
        // If c is U+002F (/) or U+005C (\), then:
13668
0
        if ((input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
0
          ada_log("FILE_SLASH c is U+002F or U+005C");
13672
          // Set state to file host state.
13673
0
          state = state::FILE_HOST;
13674
0
          input_position++;
13675
0
        } else {
13676
0
          ada_log("FILE_SLASH otherwise");
13677
          // If base is non-null and base's scheme is "file", then:
13678
          // Note: it is unsafe to do base_url->scheme unless you know that
13679
          // base_url_has_value() is true.
13680
0
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13681
            // Set url's host to base's host.
13682
0
            if constexpr (result_type_is_ada_url) {
13683
0
              url.host = base_url->host;
13684
0
            } else {
13685
0
              url.update_host_to_base_host(base_url->get_host());
13686
0
            }
13687
            // If the code point substring from pointer to the end of input does
13688
            // not start with a Windows drive letter and base's path[0] is a
13689
            // normalized Windows drive letter, then append base's path[0] to
13690
            // url's path.
13691
0
            if (!base_url->get_pathname().empty()) {
13692
0
              if (!checkers::is_windows_drive_letter(
13693
0
                      url_data.substr(input_position))) {
13694
0
                std::string_view first_base_url_path =
13695
0
                    base_url->get_pathname().substr(1);
13696
0
                size_t loc = first_base_url_path.find('/');
13697
0
                if (loc != std::string_view::npos) {
13698
0
                  helpers::resize(first_base_url_path, loc);
13699
0
                }
13700
0
                if (checkers::is_normalized_windows_drive_letter(
13701
0
                        first_base_url_path)) {
13702
0
                  if constexpr (result_type_is_ada_url) {
13703
0
                    url.path += '/';
13704
0
                    url.path += first_base_url_path;
13705
0
                  } else {
13706
0
                    url.append_base_pathname(
13707
0
                        helpers::concat("/", first_base_url_path));
13708
0
                  }
13709
0
                }
13710
0
              }
13711
0
            }
13712
0
          }
13713
13714
          // Set state to path state, and decrease pointer by 1.
13715
0
          state = state::PATH;
13716
0
        }
13717
13718
0
        break;
13719
161k
      }
13720
0
      case state::FILE_HOST: {
13721
0
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13722
0
        std::string_view view = url_data.substr(input_position);
13723
13724
0
        size_t location = view.find_first_of("/\\?");
13725
0
        std::string_view file_host_buffer = view.substr(
13726
0
            0, (location != std::string_view::npos) ? location : view.size());
13727
13728
0
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13729
0
          state = state::PATH;
13730
0
        } else if (file_host_buffer.empty()) {
13731
          // Set url's host to the empty string.
13732
0
          if constexpr (result_type_is_ada_url) {
13733
0
            url.host = "";
13734
0
          } else {
13735
0
            url.update_base_hostname("");
13736
0
          }
13737
          // Set state to path start state.
13738
0
          state = state::PATH_START;
13739
0
        } else {
13740
0
          size_t consumed_bytes = file_host_buffer.size();
13741
0
          input_position += consumed_bytes;
13742
          // Let host be the result of host parsing buffer with url is not
13743
          // special.
13744
0
          if (!url.parse_host(file_host_buffer)) {
13745
0
            return url;
13746
0
          }
13747
13748
0
          if constexpr (result_type_is_ada_url) {
13749
            // If host is "localhost", then set host to the empty string.
13750
0
            if (url.host.has_value() && url.host.value() == "localhost") {
13751
0
              url.host = "";
13752
0
            }
13753
0
          } else {
13754
0
            if (url.get_hostname() == "localhost") {
13755
0
              url.update_base_hostname("");
13756
0
            }
13757
0
          }
13758
13759
          // Set buffer to the empty string and state to path start state.
13760
0
          state = state::PATH_START;
13761
0
        }
13762
13763
0
        break;
13764
0
      }
13765
0
      case state::FILE: {
13766
0
        ada_log("FILE ", helpers::substring(url_data, input_position));
13767
0
        std::string_view file_view = url_data.substr(input_position);
13768
13769
0
        url.set_protocol_as_file();
13770
0
        if constexpr (result_type_is_ada_url) {
13771
          // Set url's host to the empty string.
13772
0
          url.host = "";
13773
0
        } else {
13774
0
          url.update_base_hostname("");
13775
0
        }
13776
        // If c is U+002F (/) or U+005C (\), then:
13777
0
        if (input_position != input_size &&
13778
0
            (url_data[input_position] == '/' ||
13779
0
             url_data[input_position] == '\\')) {
13780
0
          ada_log("FILE c is U+002F or U+005C");
13781
          // Set state to file slash state.
13782
0
          state = state::FILE_SLASH;
13783
0
        }
13784
        // Otherwise, if base is non-null and base's scheme is "file":
13785
0
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13786
          // Set url's host to base's host, url's path to a clone of base's
13787
          // path, and url's query to base's query.
13788
0
          ada_log("FILE base non-null");
13789
0
          if constexpr (result_type_is_ada_url) {
13790
0
            url.host = base_url->host;
13791
0
            url.path = base_url->path;
13792
0
            url.query = base_url->query;
13793
0
          } else {
13794
0
            url.update_host_to_base_host(base_url->get_hostname());
13795
0
            url.update_base_pathname(base_url->get_pathname());
13796
0
            if (base_url->has_search()) {
13797
              // get_search() returns "" for an empty query string (URL ends
13798
              // with '?'). update_base_search("") would incorrectly clear the
13799
              // query, so pass "?" to preserve the empty query distinction.
13800
0
              auto s = base_url->get_search();
13801
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13802
0
            }
13803
0
          }
13804
0
          url.has_opaque_path = base_url->has_opaque_path;
13805
13806
          // If c is U+003F (?), then set url's query to the empty string and
13807
          // state to query state.
13808
0
          if (input_position != input_size && url_data[input_position] == '?') {
13809
0
            state = state::QUERY;
13810
0
          }
13811
          // Otherwise, if c is not the EOF code point:
13812
0
          else if (input_position != input_size) {
13813
            // Set url's query to null.
13814
0
            url.clear_search();
13815
            // If the code point substring from pointer to the end of input does
13816
            // not start with a Windows drive letter, then shorten url's path.
13817
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13818
0
              if constexpr (result_type_is_ada_url) {
13819
0
                helpers::shorten_path(url.path, url.type);
13820
0
              } else {
13821
0
                std::string_view path = url.get_pathname();
13822
0
                if (helpers::shorten_path(path, url.type)) {
13823
0
                  url.update_base_pathname(std::move(std::string(path)));
13824
0
                }
13825
0
              }
13826
0
            }
13827
            // Otherwise:
13828
0
            else {
13829
              // Set url's path to an empty list.
13830
0
              url.clear_pathname();
13831
0
              url.has_opaque_path = true;
13832
0
            }
13833
13834
            // Set state to path state and decrease pointer by 1.
13835
0
            state = state::PATH;
13836
0
            break;
13837
0
          }
13838
0
        }
13839
        // Otherwise, set state to path state, and decrease pointer by 1.
13840
0
        else {
13841
0
          ada_log("FILE go to path");
13842
0
          state = state::PATH;
13843
0
          break;
13844
0
        }
13845
13846
0
        input_position++;
13847
0
        break;
13848
0
      }
13849
0
      default:
13850
0
        unreachable();
13851
4.35M
    }
13852
4.35M
  }
13853
802k
  if constexpr (store_values) {
13854
802k
    if (fragment.has_value()) {
13855
1.92k
      url.update_unencoded_base_hash(*fragment);
13856
1.92k
    }
13857
802k
  }
13858
802k
  enforce_max_input_length();
13859
802k
  return url;
13860
1.44M
}
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
12840
1.44M
                           const result_type* base_url) {
12841
  // We can specialize the implementation per type.
12842
  // Important: result_type_is_ada_url is evaluated at *compile time*. This
12843
  // means that doing if constexpr(result_type_is_ada_url) { something } else {
12844
  // something else } is free (at runtime). This means that ada::url_aggregator
12845
  // and ada::url **do not have to support the exact same API**.
12846
1.44M
  constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>;
12847
1.44M
  constexpr bool result_type_is_ada_url_aggregator =
12848
1.44M
      std::is_same_v<url_aggregator, result_type>;
12849
1.44M
  static_assert(result_type_is_ada_url ||
12850
1.44M
                result_type_is_ada_url_aggregator);  // We don't support
12851
                                                     // anything else for now.
12852
12853
1.44M
  ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(),
12854
1.44M
          " bytes],", (base_url != nullptr ? base_url->to_string() : "null"),
12855
1.44M
          ")");
12856
12857
1.44M
  result_type url{};
12858
12859
1.44M
  const uint32_t max_input_length = ada::get_max_input_length();
12860
12861
  // Normalization (percent-encoding, IDNA) can push the serialized URL past
12862
  // max_input_length even when the input fit under it. The check at the end of
12863
  // the state machine covers URLs that run to completion, but several states
12864
  // return early after appending a query or fragment, so run the same check on
12865
  // those exits too. Without this, a query- or fragment-terminated URL such as
12866
  // file://x/?<...> or https://user@x/?<...> is accepted while the equivalent
12867
  // https://x/?<...> that takes the absolute fast path is rejected.
12868
1.44M
  const auto enforce_max_input_length = [&]() {
12869
1.44M
    if constexpr (store_values) {
12870
1.44M
      if (url.is_valid) {
12871
1.44M
        if constexpr (result_type_is_ada_url_aggregator) {
12872
1.44M
          if (url.buffer.size() > max_input_length) [[unlikely]] {
12873
1.44M
            url.is_valid = false;
12874
1.44M
          }
12875
1.44M
        } else {
12876
1.44M
          if (url.get_href_size() > max_input_length) [[unlikely]] {
12877
1.44M
            url.is_valid = false;
12878
1.44M
          }
12879
1.44M
        }
12880
1.44M
      }
12881
1.44M
    }
12882
1.44M
  };
12883
12884
  // We refuse to parse URL strings that exceed the maximum input length.
12885
  // By default, this is 4GB but can be configured via
12886
  // ada::set_max_input_length().
12887
1.44M
  if (user_input.size() > max_input_length) [[unlikely]] {
12888
0
    url.is_valid = false;
12889
0
  }
12890
  // Going forward, user_input.size() is in [0,
12891
  // std::numeric_limits<uint32_t>::max). If we are provided with an invalid
12892
  // base, or the optional_url was invalid, we must return.
12893
1.44M
  if (base_url != nullptr) {
12894
258k
    url.is_valid &= base_url->is_valid;
12895
258k
  }
12896
1.44M
  if (!url.is_valid) {
12897
0
    return url;
12898
0
  }
12899
12900
  // Simple absolute / relative fast paths (before tabs/newline scan).
12901
1.44M
  if constexpr (store_values) {
12902
1.44M
    bool hit_fast_path = false;
12903
1.44M
    if (base_url == nullptr) {
12904
      // IPv4/IPv6 and userinfo miss the fast path. Skip the never_inline
12905
      // call so those URLs (including SetHref) do not pay for a miss.
12906
1.18M
      const auto* p = reinterpret_cast<const uint8_t*>(user_input.data());
12907
1.18M
      const size_t n = user_input.size();
12908
1.18M
      size_t host_start = 0;
12909
1.18M
      if (n >= 8 && p[4] == ':' && p[5] == '/' && p[6] == '/') {
12910
613
        host_start = 7;
12911
1.18M
      } else if (n >= 9 && p[5] == ':' && p[6] == '/' && p[7] == '/') {
12912
1.09M
        host_start = 8;
12913
1.09M
      }
12914
1.18M
      const uint8_t host_first = host_start != 0 ? p[host_start] : 0;
12915
1.18M
      const bool skip_ip =
12916
1.18M
          host_first == '[' || (host_first >= '0' && host_first <= '9');
12917
1.18M
      const bool skip_userinfo =
12918
1.18M
          host_start != 0 && authority_has_at(p, host_start, n);
12919
1.18M
      hit_fast_path = !skip_ip && !skip_userinfo &&
12920
1.13M
                      try_parse_simple_absolute(user_input, url);
12921
1.18M
    } else {
12922
258k
      hit_fast_path = try_parse_simple_relative(user_input, *base_url, url);
12923
258k
    }
12924
1.44M
    if (hit_fast_path) {
12925
658k
      if constexpr (result_type_is_ada_url_aggregator) {
12926
658k
        if (url.buffer.size() > max_input_length) [[unlikely]] {
12927
0
          url.is_valid = false;
12928
0
        }
12929
      } else {
12930
        // For a small absolute input, even worst-case normalization cannot
12931
        // exceed the limit: percent encoding expands at most 3x and IDNA at
12932
        // most 4.5x. Avoid traversing every stored component on the common
12933
        // default-limit path.
12934
        if ((base_url != nullptr ||
12935
             user_input.size() > static_cast<size_t>(max_input_length) / 5) &&
12936
            url.get_href_size() > max_input_length) [[unlikely]] {
12937
          url.is_valid = false;
12938
        }
12939
      }
12940
658k
      return url;
12941
658k
    }
12942
1.44M
  }
12943
12944
781k
  state state = state::SCHEME_START;
12945
12946
1.44M
  std::string tmp_buffer;
12947
1.44M
  std::string_view url_data;
12948
1.44M
  if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] {
12949
13.0k
    tmp_buffer = user_input;
12950
    // Optimization opportunity: Instead of copying and then pruning, we could
12951
    // just directly build the string from user_input.
12952
13.0k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
12953
13.0k
    url_data = tmp_buffer;
12954
1.42M
  } else [[likely]] {
12955
1.42M
    url_data = user_input;
12956
1.42M
  }
12957
12958
  // Leading and trailing control characters are uncommon and easy to deal with
12959
  // (no performance concern).
12960
1.44M
  helpers::trim_c0_whitespace(url_data);
12961
12962
1.44M
  if constexpr (result_type_is_ada_url_aggregator && store_values) {
12963
    // Most of the time, we just need user_input.size().
12964
    // In some instances, we may need a bit more.
12965
    ///////////////////////////
12966
    // This is *very* important. This line should *not* be removed
12967
    // hastily. There are principled reasons why reserve is important
12968
    // for performance. If you have a benchmark with small inputs,
12969
    // it may not matter, but in other instances, it could.
12970
    ////
12971
    // This rounds up to the next power of two.
12972
    // We know that user_input.size() is in [0,
12973
    // std::numeric_limits<uint32_t>::max).
12974
1.44M
    uint32_t reserve_capacity =
12975
1.44M
        (0xFFFFFFFF >>
12976
1.44M
         helpers::leading_zeroes(uint32_t(1 | user_input.size()))) +
12977
1.44M
        1;
12978
1.44M
    url.reserve(reserve_capacity);
12979
1.44M
  }
12980
12981
  // Optimization opportunity. Most websites do not have fragment.
12982
1.44M
  std::optional<std::string_view> fragment = helpers::prune_hash(url_data);
12983
  // We add it last so that an implementation like ada::url_aggregator
12984
  // can append it last to its internal buffer, thus improving performance.
12985
12986
  // Here url_data no longer has its fragment.
12987
  // We are going to access the data from url_data (it is immutable).
12988
  // At any given time, we are pointing at byte 'input_position' in url_data.
12989
  // The input_position variable should range from 0 to input_size.
12990
  // It is illegal to access url_data at input_size.
12991
1.44M
  size_t input_position = 0;
12992
1.44M
  const size_t input_size = url_data.size();
12993
  // Keep running the following state machine by switching on state.
12994
  // If after a run pointer points to the EOF code point, go to the next step.
12995
  // Otherwise, increase pointer by 1 and continue with the state machine.
12996
  // We never decrement input_position.
12997
5.15M
  while (input_position <= input_size) {
12998
4.35M
    ada_log("In parsing at ", input_position, " out of ", input_size,
12999
4.35M
            " in state ", ada::to_string(state));
13000
4.35M
    switch (state) {
13001
781k
      case state::SCHEME_START: {
13002
781k
        ada_log("SCHEME_START ", helpers::substring(url_data, input_position));
13003
        // If c is an ASCII alpha, append c, lowercased, to buffer, and set
13004
        // state to scheme state.
13005
781k
        if ((input_position != input_size) &&
13006
781k
            checkers::is_alpha(url_data[input_position])) {
13007
752k
          state = state::SCHEME;
13008
752k
          input_position++;
13009
752k
        } else {
13010
          // Otherwise, if state override is not given, set state to no scheme
13011
          // state and decrease pointer by 1.
13012
29.0k
          state = state::NO_SCHEME;
13013
29.0k
        }
13014
781k
        break;
13015
0
      }
13016
752k
      case state::SCHEME: {
13017
752k
        ada_log("SCHEME ", helpers::substring(url_data, input_position));
13018
        // If c is an ASCII alphanumeric, U+002B (+), U+002D (-), or U+002E (.),
13019
        // append c, lowercased, to buffer.
13020
3.73M
        while ((input_position != input_size) &&
13021
3.73M
               (unicode::is_alnum_plus(url_data[input_position]))) {
13022
2.98M
          input_position++;
13023
2.98M
        }
13024
        // Otherwise, if c is U+003A (:), then:
13025
752k
        if ((input_position != input_size) &&
13026
752k
            (url_data[input_position] == ':')) {
13027
752k
          ada_log("SCHEME the scheme should be ",
13028
752k
                  url_data.substr(0, input_position));
13029
          if constexpr (result_type_is_ada_url) {
13030
            if (!url.parse_scheme(url_data.substr(0, input_position))) {
13031
              return url;
13032
            }
13033
752k
          } else {
13034
            // we pass the colon along instead of painfully adding it back.
13035
752k
            if (!url.parse_scheme_with_colon(
13036
752k
                    url_data.substr(0, input_position + 1))) {
13037
0
              return url;
13038
0
            }
13039
752k
          }
13040
752k
          ada_log("SCHEME the scheme is ", url.get_protocol());
13041
13042
          // If url's scheme is "file", then:
13043
          // NOLINTNEXTLINE(bugprone-branch-clone)
13044
752k
          if (url.type == scheme::type::FILE) {
13045
            // Set state to file state.
13046
0
            state = state::FILE;
13047
0
          }
13048
          // Otherwise, if url is special, base is non-null, and base's scheme
13049
          // is url's scheme: Note: Doing base_url->scheme is unsafe if base_url
13050
          // != nullptr is false.
13051
752k
          else if (url.is_special() && base_url != nullptr &&
13052
258k
                   base_url->type == url.type) {
13053
            // Set state to special relative or authority state.
13054
258k
            state = state::SPECIAL_RELATIVE_OR_AUTHORITY;
13055
258k
          }
13056
          // Otherwise, if url is special, set state to special authority
13057
          // slashes state.
13058
494k
          else if (url.is_special()) {
13059
468k
            state = state::SPECIAL_AUTHORITY_SLASHES;
13060
468k
          }
13061
          // Otherwise, if remaining starts with an U+002F (/), set state to
13062
          // path or authority state and increase pointer by 1.
13063
25.6k
          else if (input_position + 1 < input_size &&
13064
25.4k
                   url_data[input_position + 1] == '/') {
13065
24.8k
            state = state::PATH_OR_AUTHORITY;
13066
24.8k
            input_position++;
13067
24.8k
          }
13068
          // Otherwise, set url's path to the empty string and set state to
13069
          // opaque path state.
13070
838
          else {
13071
838
            state = state::OPAQUE_PATH;
13072
838
          }
13073
752k
        }
13074
        // Otherwise, if state override is not given, set buffer to the empty
13075
        // string, state to no scheme state, and start over (from the first code
13076
        // point in input).
13077
0
        else {
13078
0
          state = state::NO_SCHEME;
13079
0
          input_position = 0;
13080
0
          break;
13081
0
        }
13082
752k
        input_position++;
13083
752k
        break;
13084
752k
      }
13085
29.0k
      case state::NO_SCHEME: {
13086
29.0k
        ada_log("NO_SCHEME ", helpers::substring(url_data, input_position));
13087
        // The fragment was pruned from url_data before the state machine ran,
13088
        // so 'c is U+0023 (#)' holds exactly when a fragment was found and
13089
        // nothing else remains in front of it.
13090
29.0k
        const bool c_is_hash =
13091
29.0k
            fragment.has_value() && input_position == input_size;
13092
        // If base is null, or base has an opaque path and c is not U+0023 (#),
13093
        // validation error, return failure.
13094
29.0k
        if (base_url == nullptr || (base_url->has_opaque_path && !c_is_hash)) {
13095
29.0k
          ada_log("NO_SCHEME validation error");
13096
29.0k
          url.is_valid = false;
13097
29.0k
          return url;
13098
29.0k
        }
13099
        // Otherwise, if base has an opaque path and c is U+0023 (#),
13100
        // set url's scheme to base's scheme, url's path to base's path, url's
13101
        // query to base's query, and set state to fragment state.
13102
0
        else if (base_url->has_opaque_path && c_is_hash) {
13103
0
          ada_log("NO_SCHEME opaque base with fragment");
13104
0
          url.copy_scheme(*base_url);
13105
0
          url.has_opaque_path = base_url->has_opaque_path;
13106
13107
          if constexpr (result_type_is_ada_url) {
13108
            url.path = base_url->path;
13109
            url.query = base_url->query;
13110
0
          } else {
13111
0
            url.update_base_pathname(base_url->get_pathname());
13112
0
            if (base_url->has_search()) {
13113
              // get_search() returns "" for an empty query string (URL ends
13114
              // with '?'). update_base_search("") would incorrectly clear the
13115
              // query, so pass "?" to preserve the empty query distinction.
13116
0
              auto s = base_url->get_search();
13117
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13118
0
            }
13119
0
          }
13120
0
          url.update_unencoded_base_hash(*fragment);
13121
0
          enforce_max_input_length();
13122
0
          return url;
13123
0
        }
13124
        // Otherwise, if base's scheme is not "file", set state to relative
13125
        // state and decrease pointer by 1.
13126
        // NOLINTNEXTLINE(bugprone-branch-clone)
13127
0
        else if (base_url->type != scheme::type::FILE) {
13128
0
          ada_log("NO_SCHEME non-file relative path");
13129
0
          state = state::RELATIVE_SCHEME;
13130
0
        }
13131
        // Otherwise, set state to file state and decrease pointer by 1.
13132
0
        else {
13133
0
          ada_log("NO_SCHEME file base type");
13134
0
          state = state::FILE;
13135
0
        }
13136
0
        break;
13137
29.0k
      }
13138
727k
      case state::AUTHORITY: {
13139
727k
        ada_log("AUTHORITY ", helpers::substring(url_data, input_position));
13140
        // most URLs have no @. Having no @ tells us that we don't have to worry
13141
        // about AUTHORITY. Of course, we could have @ and still not have to
13142
        // worry about AUTHORITY.
13143
        // TODO: Instead of just collecting a bool, collect the location of the
13144
        // '@' and do something useful with it.
13145
        // TODO: We could do various processing early on, using a single pass
13146
        // over the string to collect information about it, e.g., telling us
13147
        // whether there is a @ and if so, where (or how many).
13148
13149
        // Check if url data contains an @.
13150
727k
        if (url_data.find('@', input_position) == std::string_view::npos) {
13151
700k
          state = state::HOST;
13152
700k
          break;
13153
700k
        }
13154
26.3k
        bool at_sign_seen{false};
13155
26.3k
        bool password_token_seen{false};
13156
        /**
13157
         * We expect something of the sort...
13158
         * https://user:pass@example.com:1234/foo/bar?baz#quux
13159
         * --------^
13160
         */
13161
80.9k
        do {
13162
80.9k
          std::string_view view = url_data.substr(input_position);
13163
          // The delimiters are @, /, ? \\.
13164
80.9k
          size_t location =
13165
80.9k
              url.is_special() ? helpers::find_authority_delimiter_special(view)
13166
80.9k
                               : helpers::find_authority_delimiter(view);
13167
80.9k
          std::string_view authority_view = view.substr(0, location);
13168
80.9k
          size_t end_of_authority = input_position + authority_view.size();
13169
          // If c is U+0040 (@), then:
13170
80.9k
          if ((end_of_authority != input_size) &&
13171
77.7k
              (url_data[end_of_authority] == '@')) {
13172
            // If atSignSeen is true, then prepend "%40" to buffer.
13173
54.5k
            if (at_sign_seen) {
13174
30.0k
              if (password_token_seen) {
13175
                if constexpr (result_type_is_ada_url) {
13176
                  url.password += "%40";
13177
12.2k
                } else {
13178
12.2k
                  url.append_base_password("%40");
13179
12.2k
                }
13180
17.8k
              } else {
13181
                if constexpr (result_type_is_ada_url) {
13182
                  url.username += "%40";
13183
17.8k
                } else {
13184
17.8k
                  url.append_base_username("%40");
13185
17.8k
                }
13186
17.8k
              }
13187
30.0k
            }
13188
13189
54.5k
            at_sign_seen = true;
13190
13191
54.5k
            if (!password_token_seen) {
13192
42.3k
              size_t password_token_location = authority_view.find(':');
13193
42.3k
              password_token_seen =
13194
42.3k
                  password_token_location != std::string_view::npos;
13195
13196
42.3k
              if constexpr (store_values) {
13197
42.3k
                if (!password_token_seen) {
13198
                  if constexpr (result_type_is_ada_url) {
13199
                    url.username += unicode::percent_encode(
13200
                        authority_view,
13201
                        character_sets::USERINFO_PERCENT_ENCODE);
13202
34.3k
                  } else {
13203
34.3k
                    url.append_base_username(unicode::percent_encode(
13204
34.3k
                        authority_view,
13205
34.3k
                        character_sets::USERINFO_PERCENT_ENCODE));
13206
34.3k
                  }
13207
34.3k
                } else {
13208
                  if constexpr (result_type_is_ada_url) {
13209
                    url.username += unicode::percent_encode(
13210
                        authority_view.substr(0, password_token_location),
13211
                        character_sets::USERINFO_PERCENT_ENCODE);
13212
                    url.password += unicode::percent_encode(
13213
                        authority_view.substr(password_token_location + 1),
13214
                        character_sets::USERINFO_PERCENT_ENCODE);
13215
7.92k
                  } else {
13216
7.92k
                    url.append_base_username(unicode::percent_encode(
13217
7.92k
                        authority_view.substr(0, password_token_location),
13218
7.92k
                        character_sets::USERINFO_PERCENT_ENCODE));
13219
7.92k
                    url.append_base_password(unicode::percent_encode(
13220
7.92k
                        authority_view.substr(password_token_location + 1),
13221
7.92k
                        character_sets::USERINFO_PERCENT_ENCODE));
13222
7.92k
                  }
13223
7.92k
                }
13224
42.3k
              }
13225
42.3k
            } else if constexpr (store_values) {
13226
              if constexpr (result_type_is_ada_url) {
13227
                url.password += unicode::percent_encode(
13228
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE);
13229
12.2k
              } else {
13230
12.2k
                url.append_base_password(unicode::percent_encode(
13231
12.2k
                    authority_view, character_sets::USERINFO_PERCENT_ENCODE));
13232
12.2k
              }
13233
12.2k
            }
13234
54.5k
          }
13235
          // Otherwise, if one of the following is true:
13236
          // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13237
          // - url is special and c is U+005C (\)
13238
26.3k
          else if (end_of_authority == input_size ||
13239
23.2k
                   url_data[end_of_authority] == '/' ||
13240
1.49k
                   url_data[end_of_authority] == '?' ||
13241
26.3k
                   (url.is_special() && url_data[end_of_authority] == '\\')) {
13242
            // If atSignSeen is true and authority_view is the empty string,
13243
            // validation error, return failure.
13244
26.3k
            if (at_sign_seen && authority_view.empty()) {
13245
6.44k
              url.is_valid = false;
13246
6.44k
              return url;
13247
6.44k
            }
13248
19.9k
            state = state::HOST;
13249
19.9k
            break;
13250
26.3k
          }
13251
54.5k
          if (end_of_authority == input_size) {
13252
0
            if constexpr (store_values) {
13253
0
              if (fragment.has_value()) {
13254
0
                url.update_unencoded_base_hash(*fragment);
13255
0
              }
13256
0
            }
13257
0
            enforce_max_input_length();
13258
0
            return url;
13259
0
          }
13260
54.5k
          input_position = end_of_authority + 1;
13261
54.5k
        } while (true);
13262
13263
19.9k
        break;
13264
26.3k
      }
13265
258k
      case state::SPECIAL_RELATIVE_OR_AUTHORITY: {
13266
258k
        ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
13267
258k
                helpers::substring(url_data, input_position));
13268
13269
        // If c is U+002F (/) and remaining starts with U+002F (/),
13270
        // then set state to special authority ignore slashes state and increase
13271
        // pointer by 1.
13272
258k
        if (url_data.substr(input_position, 2) == "//") {
13273
258k
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13274
258k
          input_position += 2;
13275
258k
        } else {
13276
          // Otherwise, validation error, set state to relative state and
13277
          // decrease pointer by 1.
13278
0
          state = state::RELATIVE_SCHEME;
13279
0
        }
13280
13281
258k
        break;
13282
26.3k
      }
13283
24.8k
      case state::PATH_OR_AUTHORITY: {
13284
24.8k
        ada_log("PATH_OR_AUTHORITY ",
13285
24.8k
                helpers::substring(url_data, input_position));
13286
13287
        // If c is U+002F (/), then set state to authority state.
13288
24.8k
        if ((input_position != input_size) &&
13289
1.06k
            (url_data[input_position] == '/')) {
13290
612
          state = state::AUTHORITY;
13291
612
          input_position++;
13292
24.2k
        } else {
13293
          // Otherwise, set state to path state, and decrease pointer by 1.
13294
24.2k
          state = state::PATH;
13295
24.2k
        }
13296
13297
24.8k
        break;
13298
26.3k
      }
13299
0
      case state::RELATIVE_SCHEME: {
13300
0
        ada_log("RELATIVE_SCHEME ",
13301
0
                helpers::substring(url_data, input_position));
13302
13303
        // Set url's scheme to base's scheme.
13304
0
        url.copy_scheme(*base_url);
13305
13306
        // If c is U+002F (/), then set state to relative slash state.
13307
0
        if ((input_position != input_size) &&
13308
            // NOLINTNEXTLINE(bugprone-branch-clone)
13309
0
            (url_data[input_position] == '/')) {
13310
0
          ada_log(
13311
0
              "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
13312
0
              "slash state");
13313
0
          state = state::RELATIVE_SLASH;
13314
0
        } else if (url.is_special() && (input_position != input_size) &&
13315
0
                   (url_data[input_position] == '\\')) {
13316
          // Otherwise, if url is special and c is U+005C (\), validation error,
13317
          // set state to relative slash state.
13318
0
          ada_log(
13319
0
              "RELATIVE_SCHEME  if url is special and c is U+005C, validation "
13320
0
              "error, set state to relative slash state");
13321
0
          state = state::RELATIVE_SLASH;
13322
0
        } else {
13323
0
          ada_log("RELATIVE_SCHEME otherwise");
13324
          // Set url's username to base's username, url's password to base's
13325
          // password, url's host to base's host, url's port to base's port,
13326
          // url's path to a clone of base's path, and url's query to base's
13327
          // query.
13328
          if constexpr (result_type_is_ada_url) {
13329
            url.username = base_url->username;
13330
            url.password = base_url->password;
13331
            url.host = base_url->host;
13332
            url.port = base_url->port;
13333
            // cloning the base path includes cloning the has_opaque_path flag
13334
            url.has_opaque_path = base_url->has_opaque_path;
13335
            url.path = base_url->path;
13336
            url.query = base_url->query;
13337
0
          } else {
13338
0
            url.update_base_authority(base_url->get_href(),
13339
0
                                      base_url->get_components());
13340
0
            url.update_host_to_base_host(base_url->get_hostname());
13341
0
            url.update_base_port(base_url->retrieve_base_port());
13342
            // cloning the base path includes cloning the has_opaque_path flag
13343
0
            url.has_opaque_path = base_url->has_opaque_path;
13344
0
            url.update_base_pathname(base_url->get_pathname());
13345
0
            if (base_url->has_search()) {
13346
              // get_search() returns "" for an empty query string (URL ends
13347
              // with '?'). update_base_search("") would incorrectly clear the
13348
              // query, so pass "?" to preserve the empty query distinction.
13349
0
              auto s = base_url->get_search();
13350
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13351
0
            }
13352
0
          }
13353
13354
0
          url.has_opaque_path = base_url->has_opaque_path;
13355
13356
          // If c is U+003F (?), then set url's query to the empty string, and
13357
          // state to query state.
13358
0
          if ((input_position != input_size) &&
13359
0
              (url_data[input_position] == '?')) {
13360
0
            state = state::QUERY;
13361
0
          }
13362
          // Otherwise, if c is not the EOF code point:
13363
0
          else if (input_position != input_size) {
13364
            // Set url's query to null.
13365
0
            url.clear_search();
13366
            if constexpr (result_type_is_ada_url) {
13367
              // Shorten url's path.
13368
              helpers::shorten_path(url.path, url.type);
13369
0
            } else {
13370
0
              std::string_view path = url.get_pathname();
13371
0
              if (helpers::shorten_path(path, url.type)) {
13372
0
                url.update_base_pathname(std::move(std::string(path)));
13373
0
              }
13374
0
            }
13375
            // Set state to path state and decrease pointer by 1.
13376
0
            state = state::PATH;
13377
0
            break;
13378
0
          }
13379
0
        }
13380
0
        input_position++;
13381
0
        break;
13382
0
      }
13383
0
      case state::RELATIVE_SLASH: {
13384
0
        ada_log("RELATIVE_SLASH ",
13385
0
                helpers::substring(url_data, input_position));
13386
13387
        // If url is special and c is U+002F (/) or U+005C (\), then:
13388
        // NOLINTNEXTLINE(bugprone-branch-clone)
13389
0
        if (url.is_special() && (input_position != input_size) &&
13390
0
            (url_data[input_position] == '/' ||
13391
0
             url_data[input_position] == '\\')) {
13392
          // Set state to special authority ignore slashes state.
13393
0
          state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
13394
0
        }
13395
        // Otherwise, if c is U+002F (/), then set state to authority state.
13396
0
        else if ((input_position != input_size) &&
13397
0
                 (url_data[input_position] == '/')) {
13398
0
          state = state::AUTHORITY;
13399
0
        }
13400
        // Otherwise, set
13401
        // - url's username to base's username,
13402
        // - url's password to base's password,
13403
        // - url's host to base's host,
13404
        // - url's port to base's port,
13405
        // - state to path state, and then, decrease pointer by 1.
13406
0
        else {
13407
          if constexpr (result_type_is_ada_url) {
13408
            url.username = base_url->username;
13409
            url.password = base_url->password;
13410
            url.host = base_url->host;
13411
            url.port = base_url->port;
13412
0
          } else {
13413
0
            url.update_base_authority(base_url->get_href(),
13414
0
                                      base_url->get_components());
13415
0
            url.update_host_to_base_host(base_url->get_hostname());
13416
0
            url.update_base_port(base_url->retrieve_base_port());
13417
0
          }
13418
0
          state = state::PATH;
13419
0
          break;
13420
0
        }
13421
13422
0
        input_position++;
13423
0
        break;
13424
0
      }
13425
468k
      case state::SPECIAL_AUTHORITY_SLASHES: {
13426
468k
        ada_log("SPECIAL_AUTHORITY_SLASHES ",
13427
468k
                helpers::substring(url_data, input_position));
13428
13429
        // If c is U+002F (/) and remaining starts with U+002F (/),
13430
        // then set state to special authority ignore slashes state and increase
13431
        // pointer by 1.
13432
468k
        if (url_data.substr(input_position, 2) == "//") {
13433
468k
          input_position += 2;
13434
468k
        }
13435
13436
468k
        [[fallthrough]];
13437
468k
      }
13438
726k
      case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
13439
726k
        ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
13440
726k
                helpers::substring(url_data, input_position));
13441
13442
        // If c is neither U+002F (/) nor U+005C (\), then set state to
13443
        // authority state and decrease pointer by 1.
13444
1.20M
        while ((input_position != input_size) &&
13445
736k
               ((url_data[input_position] == '/') ||
13446
477k
                (url_data[input_position] == '\\'))) {
13447
477k
          input_position++;
13448
477k
        }
13449
726k
        state = state::AUTHORITY;
13450
13451
726k
        break;
13452
468k
      }
13453
12.9k
      case state::QUERY: {
13454
12.9k
        ada_log("QUERY ", helpers::substring(url_data, input_position));
13455
12.9k
        if constexpr (store_values) {
13456
          // Let queryPercentEncodeSet be the special-query percent-encode set
13457
          // if url is special; otherwise the query percent-encode set.
13458
12.9k
          const uint8_t* query_percent_encode_set =
13459
12.9k
              url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE
13460
12.9k
                               : character_sets::QUERY_PERCENT_ENCODE;
13461
13462
          // Percent-encode after encoding, with encoding, buffer, and
13463
          // queryPercentEncodeSet, and append the result to url's query.
13464
12.9k
          url.update_base_search(url_data.substr(input_position),
13465
12.9k
                                 query_percent_encode_set);
13466
12.9k
          ada_log("QUERY update_base_search completed ");
13467
12.9k
          if (fragment.has_value()) {
13468
2.55k
            url.update_unencoded_base_hash(*fragment);
13469
2.55k
          }
13470
12.9k
        }
13471
12.9k
        enforce_max_input_length();
13472
12.9k
        return url;
13473
468k
      }
13474
720k
      case state::HOST: {
13475
720k
        ada_log("HOST ", helpers::substring(url_data, input_position));
13476
13477
720k
        std::string_view host_view = url_data.substr(input_position);
13478
720k
        auto [location, found_colon] =
13479
720k
            helpers::get_host_delimiter_location(url.is_special(), host_view);
13480
720k
        input_position = (location != std::string_view::npos)
13481
720k
                             ? input_position + location
13482
720k
                             : input_size;
13483
        // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
13484
        // Note: the 'found_colon' value is true if and only if a colon was
13485
        // encountered while not inside brackets.
13486
720k
        if (found_colon) {
13487
          // If buffer is the empty string, validation error, return failure.
13488
          // Let host be the result of host parsing buffer with url is not
13489
          // special.
13490
37.4k
          ada_log("HOST parsing ", host_view);
13491
37.4k
          if (!url.parse_host(host_view)) {
13492
7.00k
            return url;
13493
7.00k
          }
13494
30.4k
          ada_log("HOST parsing results in ", url.get_hostname());
13495
          // Set url's host to host, buffer to the empty string, and state to
13496
          // port state.
13497
30.4k
          state = state::PORT;
13498
30.4k
          input_position++;
13499
30.4k
        }
13500
        // Otherwise, if one of the following is true:
13501
        // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
13502
        // - url is special and c is U+005C (\)
13503
        // The get_host_delimiter_location function either brings us to
13504
        // the colon outside of the bracket, or to one of those characters.
13505
683k
        else {
13506
          // If url is special and host_view is the empty string, validation
13507
          // error, return failure.
13508
683k
          if (host_view.empty() && url.is_special()) {
13509
468k
            url.is_valid = false;
13510
468k
            return url;
13511
468k
          }
13512
214k
          ada_log("HOST parsing ", host_view, " href=", url.get_href());
13513
          // Let host be the result of host parsing host_view with url is not
13514
          // special.
13515
214k
          if (host_view.empty()) {
13516
137
            url.update_base_hostname("");
13517
214k
          } else if (!url.parse_host(host_view)) {
13518
80.2k
            return url;
13519
80.2k
          }
13520
134k
          ada_log("HOST parsing results in ", url.get_hostname(),
13521
134k
                  " href=", url.get_href());
13522
13523
          // Set url's host to host, and state to path start state.
13524
134k
          state = state::PATH_START;
13525
134k
        }
13526
13527
164k
        break;
13528
720k
      }
13529
164k
      case state::OPAQUE_PATH: {
13530
838
        ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
13531
        // Opaque path, query, and fragment are structurally always valid:
13532
        // the parser would just percent-encode whatever is there. When we
13533
        // are not storing values (can_parse), we can return immediately.
13534
        // We must set has_opaque_path = true before returning so that when
13535
        // this URL is used as an internal base inside can_parse, NO_SCHEME
13536
        // correctly rejects relative inputs against an opaque-path base
13537
        // (e.g. can_parse("", &"W:") must return false).
13538
        if constexpr (!store_values) {
13539
          url.has_opaque_path = true;
13540
          return url;
13541
        }
13542
838
        std::string_view view = url_data.substr(input_position);
13543
        // If c is U+003F (?), then set url's query to the empty string and
13544
        // state to query state.
13545
838
        size_t location = view.find('?');
13546
838
        if (location != std::string_view::npos) {
13547
53
          view.remove_suffix(view.size() - location);
13548
53
          state = state::QUERY;
13549
53
          input_position += location + 1;
13550
785
        } else {
13551
785
          input_position = input_size + 1;
13552
785
        }
13553
838
        url.has_opaque_path = true;
13554
13555
        // This is a really unlikely scenario in real world. We should not seek
13556
        // to optimize it.
13557
838
        if (view.ends_with(' ')) {
13558
56
          std::string modified_view =
13559
56
              std::string(view.substr(0, view.size() - 1)) + "%20";
13560
56
          url.update_base_pathname(unicode::percent_encode(
13561
56
              modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13562
782
        } else {
13563
782
          url.update_base_pathname(unicode::percent_encode(
13564
782
              view, character_sets::C0_CONTROL_PERCENT_ENCODE));
13565
782
        }
13566
838
        break;
13567
720k
      }
13568
30.4k
      case state::PORT: {
13569
30.4k
        ada_log("PORT ", helpers::substring(url_data, input_position));
13570
30.4k
        std::string_view port_view = url_data.substr(input_position);
13571
30.4k
        input_position += url.parse_port(port_view, true);
13572
30.4k
        if (!url.is_valid) {
13573
3.76k
          return url;
13574
3.76k
        }
13575
26.6k
        state = state::PATH_START;
13576
26.6k
        [[fallthrough]];
13577
26.6k
      }
13578
161k
      case state::PATH_START: {
13579
161k
        ada_log("PATH_START ", helpers::substring(url_data, input_position));
13580
        // Path, query, and fragment are structurally always valid: the
13581
        // parser would just percent-encode whatever is there. When we are
13582
        // not storing values (can_parse), we can return immediately since
13583
        // no subsequent state can invalidate the URL.
13584
        if constexpr (!store_values) {
13585
          return url;
13586
        }
13587
13588
        // If url is special, then:
13589
161k
        if (url.is_special()) {
13590
          // Set state to path state.
13591
160k
          state = state::PATH;
13592
13593
          // Optimization: Avoiding going into PATH state improves the
13594
          // performance of urls ending with /.
13595
160k
          if (input_position == input_size) {
13596
29.9k
            if constexpr (store_values) {
13597
29.9k
              url.update_base_pathname("/");
13598
29.9k
              if (fragment.has_value()) {
13599
5.63k
                url.update_unencoded_base_hash(*fragment);
13600
5.63k
              }
13601
29.9k
            }
13602
29.9k
            enforce_max_input_length();
13603
29.9k
            return url;
13604
29.9k
          }
13605
          // If c is neither U+002F (/) nor U+005C (\), then decrease pointer
13606
          // by 1. We know that (input_position == input_size) is impossible
13607
          // here, because of the previous if-check.
13608
130k
          if ((url_data[input_position] != '/') &&
13609
11.7k
              (url_data[input_position] != '\\')) {
13610
9.73k
            break;
13611
9.73k
          }
13612
130k
        }
13613
        // Otherwise, if state override is not given and c is U+003F (?),
13614
        // set url's query to the empty string and state to query state.
13615
367
        else if ((input_position != input_size) &&
13616
80
                 (url_data[input_position] == '?')) {
13617
17
          state = state::QUERY;
13618
17
        }
13619
        // Otherwise, if c is not the EOF code point:
13620
350
        else if (input_position != input_size) {
13621
          // Set state to path state.
13622
63
          state = state::PATH;
13623
13624
          // If c is not U+002F (/), then decrease pointer by 1.
13625
63
          if (url_data[input_position] != '/') {
13626
0
            break;
13627
0
          }
13628
63
        }
13629
13630
121k
        input_position++;
13631
121k
        break;
13632
161k
      }
13633
155k
      case state::PATH: {
13634
155k
        ada_log("PATH ", helpers::substring(url_data, input_position));
13635
        // Path, query, and fragment are structurally always valid: the
13636
        // parser would just percent-encode whatever is there. When we are
13637
        // not storing values (can_parse), we can return immediately since
13638
        // no subsequent state can invalidate the URL.
13639
        if constexpr (!store_values) {
13640
          return url;
13641
        }
13642
155k
        std::string_view view = url_data.substr(input_position);
13643
13644
        // Most time, we do not need percent encoding.
13645
        // Furthermore, we can immediately locate the '?'.
13646
155k
        size_t locofquestionmark = view.find('?');
13647
155k
        if (locofquestionmark != std::string_view::npos) {
13648
12.8k
          state = state::QUERY;
13649
12.8k
          view.remove_suffix(view.size() - locofquestionmark);
13650
12.8k
          input_position += locofquestionmark + 1;
13651
142k
        } else {
13652
142k
          input_position = input_size + 1;
13653
142k
        }
13654
155k
        if constexpr (store_values) {
13655
          if constexpr (result_type_is_ada_url) {
13656
            helpers::parse_prepared_path(view, url.type, url.path);
13657
155k
          } else {
13658
155k
            url.consume_prepared_path(view);
13659
155k
            ADA_ASSERT_TRUE(url.validate());
13660
155k
          }
13661
155k
        }
13662
155k
        break;
13663
161k
      }
13664
0
      case state::FILE_SLASH: {
13665
0
        ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
13666
13667
        // If c is U+002F (/) or U+005C (\), then:
13668
0
        if ((input_position != input_size) &&
13669
0
            (url_data[input_position] == '/' ||
13670
0
             url_data[input_position] == '\\')) {
13671
0
          ada_log("FILE_SLASH c is U+002F or U+005C");
13672
          // Set state to file host state.
13673
0
          state = state::FILE_HOST;
13674
0
          input_position++;
13675
0
        } else {
13676
0
          ada_log("FILE_SLASH otherwise");
13677
          // If base is non-null and base's scheme is "file", then:
13678
          // Note: it is unsafe to do base_url->scheme unless you know that
13679
          // base_url_has_value() is true.
13680
0
          if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13681
            // Set url's host to base's host.
13682
            if constexpr (result_type_is_ada_url) {
13683
              url.host = base_url->host;
13684
0
            } else {
13685
0
              url.update_host_to_base_host(base_url->get_host());
13686
0
            }
13687
            // If the code point substring from pointer to the end of input does
13688
            // not start with a Windows drive letter and base's path[0] is a
13689
            // normalized Windows drive letter, then append base's path[0] to
13690
            // url's path.
13691
0
            if (!base_url->get_pathname().empty()) {
13692
0
              if (!checkers::is_windows_drive_letter(
13693
0
                      url_data.substr(input_position))) {
13694
0
                std::string_view first_base_url_path =
13695
0
                    base_url->get_pathname().substr(1);
13696
0
                size_t loc = first_base_url_path.find('/');
13697
0
                if (loc != std::string_view::npos) {
13698
0
                  helpers::resize(first_base_url_path, loc);
13699
0
                }
13700
0
                if (checkers::is_normalized_windows_drive_letter(
13701
0
                        first_base_url_path)) {
13702
                  if constexpr (result_type_is_ada_url) {
13703
                    url.path += '/';
13704
                    url.path += first_base_url_path;
13705
0
                  } else {
13706
0
                    url.append_base_pathname(
13707
0
                        helpers::concat("/", first_base_url_path));
13708
0
                  }
13709
0
                }
13710
0
              }
13711
0
            }
13712
0
          }
13713
13714
          // Set state to path state, and decrease pointer by 1.
13715
0
          state = state::PATH;
13716
0
        }
13717
13718
0
        break;
13719
161k
      }
13720
0
      case state::FILE_HOST: {
13721
0
        ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
13722
0
        std::string_view view = url_data.substr(input_position);
13723
13724
0
        size_t location = view.find_first_of("/\\?");
13725
0
        std::string_view file_host_buffer = view.substr(
13726
0
            0, (location != std::string_view::npos) ? location : view.size());
13727
13728
0
        if (checkers::is_windows_drive_letter(file_host_buffer)) {
13729
0
          state = state::PATH;
13730
0
        } else if (file_host_buffer.empty()) {
13731
          // Set url's host to the empty string.
13732
          if constexpr (result_type_is_ada_url) {
13733
            url.host = "";
13734
0
          } else {
13735
0
            url.update_base_hostname("");
13736
0
          }
13737
          // Set state to path start state.
13738
0
          state = state::PATH_START;
13739
0
        } else {
13740
0
          size_t consumed_bytes = file_host_buffer.size();
13741
0
          input_position += consumed_bytes;
13742
          // Let host be the result of host parsing buffer with url is not
13743
          // special.
13744
0
          if (!url.parse_host(file_host_buffer)) {
13745
0
            return url;
13746
0
          }
13747
13748
          if constexpr (result_type_is_ada_url) {
13749
            // If host is "localhost", then set host to the empty string.
13750
            if (url.host.has_value() && url.host.value() == "localhost") {
13751
              url.host = "";
13752
            }
13753
0
          } else {
13754
0
            if (url.get_hostname() == "localhost") {
13755
0
              url.update_base_hostname("");
13756
0
            }
13757
0
          }
13758
13759
          // Set buffer to the empty string and state to path start state.
13760
0
          state = state::PATH_START;
13761
0
        }
13762
13763
0
        break;
13764
0
      }
13765
0
      case state::FILE: {
13766
0
        ada_log("FILE ", helpers::substring(url_data, input_position));
13767
0
        std::string_view file_view = url_data.substr(input_position);
13768
13769
0
        url.set_protocol_as_file();
13770
        if constexpr (result_type_is_ada_url) {
13771
          // Set url's host to the empty string.
13772
          url.host = "";
13773
0
        } else {
13774
0
          url.update_base_hostname("");
13775
0
        }
13776
        // If c is U+002F (/) or U+005C (\), then:
13777
0
        if (input_position != input_size &&
13778
0
            (url_data[input_position] == '/' ||
13779
0
             url_data[input_position] == '\\')) {
13780
0
          ada_log("FILE c is U+002F or U+005C");
13781
          // Set state to file slash state.
13782
0
          state = state::FILE_SLASH;
13783
0
        }
13784
        // Otherwise, if base is non-null and base's scheme is "file":
13785
0
        else if (base_url != nullptr && base_url->type == scheme::type::FILE) {
13786
          // Set url's host to base's host, url's path to a clone of base's
13787
          // path, and url's query to base's query.
13788
0
          ada_log("FILE base non-null");
13789
          if constexpr (result_type_is_ada_url) {
13790
            url.host = base_url->host;
13791
            url.path = base_url->path;
13792
            url.query = base_url->query;
13793
0
          } else {
13794
0
            url.update_host_to_base_host(base_url->get_hostname());
13795
0
            url.update_base_pathname(base_url->get_pathname());
13796
0
            if (base_url->has_search()) {
13797
              // get_search() returns "" for an empty query string (URL ends
13798
              // with '?'). update_base_search("") would incorrectly clear the
13799
              // query, so pass "?" to preserve the empty query distinction.
13800
0
              auto s = base_url->get_search();
13801
0
              url.update_base_search(s.empty() ? std::string_view("?") : s);
13802
0
            }
13803
0
          }
13804
0
          url.has_opaque_path = base_url->has_opaque_path;
13805
13806
          // If c is U+003F (?), then set url's query to the empty string and
13807
          // state to query state.
13808
0
          if (input_position != input_size && url_data[input_position] == '?') {
13809
0
            state = state::QUERY;
13810
0
          }
13811
          // Otherwise, if c is not the EOF code point:
13812
0
          else if (input_position != input_size) {
13813
            // Set url's query to null.
13814
0
            url.clear_search();
13815
            // If the code point substring from pointer to the end of input does
13816
            // not start with a Windows drive letter, then shorten url's path.
13817
0
            if (!checkers::is_windows_drive_letter(file_view)) {
13818
              if constexpr (result_type_is_ada_url) {
13819
                helpers::shorten_path(url.path, url.type);
13820
0
              } else {
13821
0
                std::string_view path = url.get_pathname();
13822
0
                if (helpers::shorten_path(path, url.type)) {
13823
0
                  url.update_base_pathname(std::move(std::string(path)));
13824
0
                }
13825
0
              }
13826
0
            }
13827
            // Otherwise:
13828
0
            else {
13829
              // Set url's path to an empty list.
13830
0
              url.clear_pathname();
13831
0
              url.has_opaque_path = true;
13832
0
            }
13833
13834
            // Set state to path state and decrease pointer by 1.
13835
0
            state = state::PATH;
13836
0
            break;
13837
0
          }
13838
0
        }
13839
        // Otherwise, set state to path state, and decrease pointer by 1.
13840
0
        else {
13841
0
          ada_log("FILE go to path");
13842
0
          state = state::PATH;
13843
0
          break;
13844
0
        }
13845
13846
0
        input_position++;
13847
0
        break;
13848
0
      }
13849
0
      default:
13850
0
        unreachable();
13851
4.35M
    }
13852
4.35M
  }
13853
802k
  if constexpr (store_values) {
13854
802k
    if (fragment.has_value()) {
13855
1.92k
      url.update_unencoded_base_hash(*fragment);
13856
1.92k
    }
13857
802k
  }
13858
802k
  enforce_max_input_length();
13859
802k
  return url;
13860
1.44M
}
Unexecuted instantiation: 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*)
13861
13862
template bool try_parse_simple_absolute<url>(std::string_view, url&);
13863
template bool try_parse_simple_absolute<url_aggregator>(std::string_view,
13864
                                                        url_aggregator&);
13865
template bool finish_simple_absolute_with_port<url>(std::string_view, url&,
13866
                                                    ada::scheme::type, uint32_t,
13867
                                                    size_t, size_t, size_t,
13868
                                                    bool);
13869
template bool finish_simple_absolute_with_port<url_aggregator>(
13870
    std::string_view, url_aggregator&, ada::scheme::type, uint32_t, size_t,
13871
    size_t, size_t, bool);
13872
template bool try_parse_simple_relative<url>(std::string_view, const url&,
13873
                                             url&);
13874
template bool try_parse_simple_relative<url_aggregator>(std::string_view,
13875
                                                        const url_aggregator&,
13876
                                                        url_aggregator&);
13877
13878
template url parse_url_impl<url, true>(std::string_view user_input,
13879
                                       const url* base_url = nullptr);
13880
template url_aggregator parse_url_impl<url_aggregator, true>(
13881
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13882
template url_aggregator parse_url_impl<url_aggregator, false>(
13883
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13884
13885
template <class result_type>
13886
result_type parse_url(std::string_view user_input,
13887
0
                      const result_type* base_url) {
13888
0
  return parse_url_impl<result_type, true>(user_input, base_url);
13889
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*)
13890
13891
template url parse_url<url>(std::string_view user_input,
13892
                            const url* base_url = nullptr);
13893
template url_aggregator parse_url<url_aggregator>(
13894
    std::string_view user_input, const url_aggregator* base_url = nullptr);
13895
}  // namespace ada::parser
13896
/* end file src/parser.cpp */
13897
/* begin file src/url_components.cpp */
13898
13899
#include <iterator>
13900
#include <string>
13901
13902
namespace ada {
13903
13904
0
[[nodiscard]] std::string url_components::to_string() const {
13905
0
  std::string answer;
13906
0
  auto back = std::back_insert_iterator(answer);
13907
0
  answer.append("{\n");
13908
13909
0
  answer.append("\t\"protocol_end\":\"");
13910
0
  helpers::encode_json(std::to_string(protocol_end), back);
13911
0
  answer.append("\",\n");
13912
13913
0
  answer.append("\t\"username_end\":\"");
13914
0
  helpers::encode_json(std::to_string(username_end), back);
13915
0
  answer.append("\",\n");
13916
13917
0
  answer.append("\t\"host_start\":\"");
13918
0
  helpers::encode_json(std::to_string(host_start), back);
13919
0
  answer.append("\",\n");
13920
13921
0
  answer.append("\t\"host_end\":\"");
13922
0
  helpers::encode_json(std::to_string(host_end), back);
13923
0
  answer.append("\",\n");
13924
13925
0
  answer.append("\t\"port\":\"");
13926
0
  helpers::encode_json(std::to_string(port), back);
13927
0
  answer.append("\",\n");
13928
13929
0
  answer.append("\t\"pathname_start\":\"");
13930
0
  helpers::encode_json(std::to_string(pathname_start), back);
13931
0
  answer.append("\",\n");
13932
13933
0
  answer.append("\t\"search_start\":\"");
13934
0
  helpers::encode_json(std::to_string(search_start), back);
13935
0
  answer.append("\",\n");
13936
13937
0
  answer.append("\t\"hash_start\":\"");
13938
0
  helpers::encode_json(std::to_string(hash_start), back);
13939
0
  answer.append("\",\n");
13940
13941
0
  answer.append("\n}");
13942
0
  return answer;
13943
0
}
13944
13945
}  // namespace ada
13946
/* end file src/url_components.cpp */
13947
/* begin file src/url_aggregator.cpp */
13948
13949
#include <algorithm>
13950
#include <array>
13951
#include <cstdint>
13952
#include <cstring>
13953
#include <iterator>
13954
#include <optional>
13955
#include <ranges>
13956
#include <string>
13957
#include <string_view>
13958
#include <utility>
13959
13960
namespace {
13961
13962
ada_really_inline void apply_shifted_non_scheme_offsets(
13963
752k
    ada::url_components& components, uint32_t new_difference) {
13964
752k
  components.username_end += new_difference;
13965
752k
  components.host_start += new_difference;
13966
752k
  components.host_end += new_difference;
13967
752k
  components.pathname_start += new_difference;
13968
752k
  if (components.search_start != ada::url_components::omitted) {
13969
0
    components.search_start += new_difference;
13970
0
  }
13971
752k
  if (components.hash_start != ada::url_components::omitted) {
13972
0
    components.hash_start += new_difference;
13973
0
  }
13974
752k
}
13975
13976
}  // namespace
13977
13978
namespace ada {
13979
template <bool has_state_override>
13980
[[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon(
13981
752k
    const std::string_view input_with_colon) {
13982
752k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13983
752k
  ADA_ASSERT_TRUE(validate());
13984
752k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13985
752k
  std::string_view input{input_with_colon};
13986
752k
  input.remove_suffix(1);
13987
752k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13988
752k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13989
  /**
13990
   * In the common case, we will immediately recognize a special scheme (e.g.,
13991
   *http, https), in which case, we can go really fast.
13992
   **/
13993
752k
  if (is_input_special) {  // fast path!!!
13994
726k
    if constexpr (has_state_override) {
13995
      // If url's scheme is not a special scheme and buffer is a special scheme,
13996
      // then return.
13997
0
      if (is_special() != is_input_special) {
13998
0
        return false;
13999
0
      }
14000
14001
      // If url includes credentials or has a non-null port, and buffer is
14002
      // "file", then return.
14003
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14004
0
          parsed_type == ada::scheme::type::FILE) {
14005
0
        return false;
14006
0
      }
14007
14008
      // If url's scheme is "file" and its host is an empty host, then return.
14009
      // An empty host is the empty string.
14010
0
      if (type == ada::scheme::type::FILE &&
14011
0
          components.host_start == components.host_end) {
14012
0
        return false;
14013
0
      }
14014
0
    }
14015
14016
0
    type = parsed_type;
14017
726k
    set_scheme_from_view_with_colon(input_with_colon);
14018
14019
726k
    if constexpr (has_state_override) {
14020
      // This is uncommon.
14021
0
      uint16_t urls_scheme_port = get_special_port();
14022
14023
0
      if (urls_scheme_port) {
14024
        // If url's port is url's scheme's default port, then set url's port to
14025
        // null.
14026
0
        if (components.port == urls_scheme_port) {
14027
0
          clear_port();
14028
0
        }
14029
0
      }
14030
0
    }
14031
726k
  } else {  // slow path
14032
25.6k
    std::string _buffer(input);
14033
    // Next function is only valid if the input is ASCII and returns false
14034
    // otherwise, but it seems that we always have ascii content so we do not
14035
    // need to check the return value.
14036
25.6k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14037
14038
25.6k
    if constexpr (has_state_override) {
14039
      // The state-override validation errors below ("return" in the WHATWG URL
14040
      // parser) leave the URL unchanged. The setter contract is
14041
      // "true on success, false if the scheme is invalid" -- the fast path
14042
      // above already returns false here, so the slow path must agree.
14043
14044
      // If url's scheme is a special scheme and buffer is not a special scheme,
14045
      // then return. If url's scheme is not a special scheme and buffer is a
14046
      // special scheme, then return.
14047
0
      if (is_special() != ada::scheme::is_special(_buffer)) {
14048
0
        return false;
14049
0
      }
14050
14051
      // If url includes credentials or has a non-null port, and buffer is
14052
      // "file", then return.
14053
0
      if ((has_credentials() || components.port != url_components::omitted) &&
14054
0
          _buffer == "file") {
14055
0
        return false;
14056
0
      }
14057
14058
      // If url's scheme is "file" and its host is an empty host, then return.
14059
      // An empty host is the empty string.
14060
0
      if (type == ada::scheme::type::FILE &&
14061
0
          components.host_start == components.host_end) {
14062
0
        return false;
14063
0
      }
14064
0
    }
14065
14066
0
    set_scheme(_buffer);
14067
14068
25.6k
    if constexpr (has_state_override) {
14069
      // This is uncommon.
14070
0
      uint16_t urls_scheme_port = get_special_port();
14071
14072
0
      if (urls_scheme_port) {
14073
        // If url's port is url's scheme's default port, then set url's port to
14074
        // null.
14075
0
        if (components.port == urls_scheme_port) {
14076
0
          clear_port();
14077
0
        }
14078
0
      }
14079
0
    }
14080
25.6k
  }
14081
0
  ADA_ASSERT_TRUE(validate());
14082
752k
  return true;
14083
752k
}
bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
13981
752k
    const std::string_view input_with_colon) {
13982
752k
  ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon);
13983
752k
  ADA_ASSERT_TRUE(validate());
13984
752k
  ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer));
13985
752k
  std::string_view input{input_with_colon};
13986
752k
  input.remove_suffix(1);
13987
752k
  auto parsed_type = ada::scheme::get_scheme_type(input);
13988
752k
  const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
13989
  /**
13990
   * In the common case, we will immediately recognize a special scheme (e.g.,
13991
   *http, https), in which case, we can go really fast.
13992
   **/
13993
752k
  if (is_input_special) {  // fast path!!!
13994
    if constexpr (has_state_override) {
13995
      // If url's scheme is not a special scheme and buffer is a special scheme,
13996
      // then return.
13997
      if (is_special() != is_input_special) {
13998
        return false;
13999
      }
14000
14001
      // If url includes credentials or has a non-null port, and buffer is
14002
      // "file", then return.
14003
      if ((has_credentials() || components.port != url_components::omitted) &&
14004
          parsed_type == ada::scheme::type::FILE) {
14005
        return false;
14006
      }
14007
14008
      // If url's scheme is "file" and its host is an empty host, then return.
14009
      // An empty host is the empty string.
14010
      if (type == ada::scheme::type::FILE &&
14011
          components.host_start == components.host_end) {
14012
        return false;
14013
      }
14014
    }
14015
14016
726k
    type = parsed_type;
14017
726k
    set_scheme_from_view_with_colon(input_with_colon);
14018
14019
    if constexpr (has_state_override) {
14020
      // This is uncommon.
14021
      uint16_t urls_scheme_port = get_special_port();
14022
14023
      if (urls_scheme_port) {
14024
        // If url's port is url's scheme's default port, then set url's port to
14025
        // null.
14026
        if (components.port == urls_scheme_port) {
14027
          clear_port();
14028
        }
14029
      }
14030
    }
14031
726k
  } else {  // slow path
14032
25.6k
    std::string _buffer(input);
14033
    // Next function is only valid if the input is ASCII and returns false
14034
    // otherwise, but it seems that we always have ascii content so we do not
14035
    // need to check the return value.
14036
25.6k
    unicode::to_lower_ascii(_buffer.data(), _buffer.size());
14037
14038
    if constexpr (has_state_override) {
14039
      // The state-override validation errors below ("return" in the WHATWG URL
14040
      // parser) leave the URL unchanged. The setter contract is
14041
      // "true on success, false if the scheme is invalid" -- the fast path
14042
      // above already returns false here, so the slow path must agree.
14043
14044
      // If url's scheme is a special scheme and buffer is not a special scheme,
14045
      // then return. If url's scheme is not a special scheme and buffer is a
14046
      // special scheme, then return.
14047
      if (is_special() != ada::scheme::is_special(_buffer)) {
14048
        return false;
14049
      }
14050
14051
      // If url includes credentials or has a non-null port, and buffer is
14052
      // "file", then return.
14053
      if ((has_credentials() || components.port != url_components::omitted) &&
14054
          _buffer == "file") {
14055
        return false;
14056
      }
14057
14058
      // If url's scheme is "file" and its host is an empty host, then return.
14059
      // An empty host is the empty string.
14060
      if (type == ada::scheme::type::FILE &&
14061
          components.host_start == components.host_end) {
14062
        return false;
14063
      }
14064
    }
14065
14066
25.6k
    set_scheme(_buffer);
14067
14068
    if constexpr (has_state_override) {
14069
      // This is uncommon.
14070
      uint16_t urls_scheme_port = get_special_port();
14071
14072
      if (urls_scheme_port) {
14073
        // If url's port is url's scheme's default port, then set url's port to
14074
        // null.
14075
        if (components.port == urls_scheme_port) {
14076
          clear_port();
14077
        }
14078
      }
14079
    }
14080
25.6k
  }
14081
752k
  ADA_ASSERT_TRUE(validate());
14082
752k
  return true;
14083
752k
}
Unexecuted instantiation: bool ada::url_aggregator::parse_scheme_with_colon<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
14084
14085
0
inline void url_aggregator::copy_scheme(const url_aggregator& u) {
14086
0
  ada_log("url_aggregator::copy_scheme ", u.buffer);
14087
0
  ADA_ASSERT_TRUE(validate());
14088
  // next line could overflow but unsigned arithmetic has well-defined
14089
  // overflows.
14090
0
  uint32_t new_difference = u.components.protocol_end - components.protocol_end;
14091
14092
0
  type = u.type;
14093
0
  buffer.erase(0, components.protocol_end);
14094
0
  buffer.insert(0, u.get_protocol());
14095
0
  components.protocol_end = u.components.protocol_end;
14096
14097
  // No need to update the components
14098
0
  if (new_difference == 0) {
14099
0
    return;
14100
0
  }
14101
14102
0
  apply_shifted_non_scheme_offsets(components, new_difference);
14103
0
  ADA_ASSERT_TRUE(validate());
14104
0
}
14105
14106
inline void url_aggregator::set_scheme_from_view_with_colon(
14107
726k
    std::string_view new_scheme_with_colon) {
14108
726k
  ada_log("url_aggregator::set_scheme_from_view_with_colon ",
14109
726k
          new_scheme_with_colon);
14110
726k
  ADA_ASSERT_TRUE(validate());
14111
726k
  ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() &&
14112
726k
                  new_scheme_with_colon.back() == ':');
14113
  // next line could overflow but unsigned arithmetic has well-defined
14114
  // overflows.
14115
726k
  uint32_t new_difference =
14116
726k
      uint32_t(new_scheme_with_colon.size()) - components.protocol_end;
14117
14118
726k
  if (buffer.empty()) {
14119
726k
    buffer.append(new_scheme_with_colon);
14120
726k
  } else {
14121
0
    buffer.erase(0, components.protocol_end);
14122
0
    buffer.insert(0, new_scheme_with_colon);
14123
0
  }
14124
726k
  components.protocol_end += new_difference;
14125
14126
726k
  apply_shifted_non_scheme_offsets(components, new_difference);
14127
726k
  ADA_ASSERT_TRUE(validate());
14128
726k
}
14129
14130
25.6k
inline void url_aggregator::set_scheme(std::string_view new_scheme) {
14131
25.6k
  ada_log("url_aggregator::set_scheme ", new_scheme);
14132
25.6k
  ADA_ASSERT_TRUE(validate());
14133
25.6k
  ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':');
14134
  // next line could overflow but unsigned arithmetic has well-defined
14135
  // overflows.
14136
25.6k
  uint32_t new_difference =
14137
25.6k
      uint32_t(new_scheme.size()) - components.protocol_end + 1;
14138
14139
25.6k
  type = ada::scheme::get_scheme_type(new_scheme);
14140
25.6k
  if (buffer.empty()) {
14141
25.6k
    buffer.append(helpers::concat(new_scheme, ":"));
14142
25.6k
  } else {
14143
0
    buffer.erase(0, components.protocol_end);
14144
0
    buffer.insert(0, helpers::concat(new_scheme, ":"));
14145
0
  }
14146
25.6k
  components.protocol_end = uint32_t(new_scheme.size() + 1);
14147
14148
25.6k
  apply_shifted_non_scheme_offsets(components, new_difference);
14149
25.6k
  ADA_ASSERT_TRUE(validate());
14150
25.6k
}
14151
14152
263k
bool url_aggregator::needs_rollback_snapshot(size_t input_len) const noexcept {
14153
  // 3x should cover worst-case percent-encoding of every input byte; the
14154
  // constant covers the handful of delimiter bytes a setter may add ("/.", "?",
14155
  // "#" and so on)
14156
263k
  return buffer.size() + input_len * 3 + 16 > ada::get_max_input_length();
14157
263k
}
14158
14159
0
bool url_aggregator::set_protocol(const std::string_view input) {
14160
0
  ada_log("url_aggregator::set_protocol ", input);
14161
0
  ADA_ASSERT_TRUE(validate());
14162
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14163
0
  std::string view(input);
14164
0
  helpers::remove_ascii_tab_or_newline(view);
14165
0
  if (view.empty()) {
14166
0
    return true;
14167
0
  }
14168
14169
  // Schemes should start with alpha values.
14170
0
  if (!checkers::is_alpha(view[0])) {
14171
0
    return false;
14172
0
  }
14173
14174
0
  view.append(":");
14175
14176
0
  std::string::iterator pointer =
14177
0
      std::ranges::find_if_not(view, unicode::is_alnum_plus);
14178
14179
0
  if (pointer != view.end() && *pointer == ':') {
14180
0
    std::optional<url_aggregator> saved_url;
14181
0
    if (needs_rollback_snapshot(view.size())) {
14182
0
      saved_url = *this;
14183
0
    }
14184
0
    bool result = parse_scheme_with_colon<true>(
14185
0
        view.substr(0, pointer - view.begin() + 1));
14186
0
    if (result && saved_url && buffer.size() > ada::get_max_input_length()) {
14187
0
      *this = std::move(*saved_url);
14188
0
      return false;
14189
0
    }
14190
0
    return result;
14191
0
  }
14192
0
  return false;
14193
0
}
14194
14195
0
bool url_aggregator::set_username(const std::string_view input) {
14196
0
  ada_log("url_aggregator::set_username '", input, "' ");
14197
0
  ADA_ASSERT_TRUE(validate());
14198
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14199
0
  if (cannot_have_credentials_or_port()) {
14200
0
    return false;
14201
0
  }
14202
0
  std::optional<url_aggregator> saved_url;
14203
0
  if (needs_rollback_snapshot(input.size())) {
14204
0
    saved_url = *this;
14205
0
  }
14206
0
  size_t idx = ada::unicode::percent_encode_index(
14207
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14208
0
  if (idx == input.size()) {
14209
0
    update_base_username(input);
14210
0
  } else {
14211
    // We only create a temporary string if we have to!
14212
0
    update_base_username(ada::unicode::percent_encode(
14213
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14214
0
  }
14215
0
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14216
0
    *this = std::move(*saved_url);
14217
0
    return false;
14218
0
  }
14219
0
  ADA_ASSERT_TRUE(validate());
14220
0
  return true;
14221
0
}
14222
14223
0
bool url_aggregator::set_password(const std::string_view input) {
14224
0
  ada_log("url_aggregator::set_password '", input, "'");
14225
0
  ADA_ASSERT_TRUE(validate());
14226
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14227
0
  if (cannot_have_credentials_or_port()) {
14228
0
    return false;
14229
0
  }
14230
0
  std::optional<url_aggregator> saved_url;
14231
0
  if (needs_rollback_snapshot(input.size())) {
14232
0
    saved_url = *this;
14233
0
  }
14234
0
  size_t idx = ada::unicode::percent_encode_index(
14235
0
      input, character_sets::USERINFO_PERCENT_ENCODE);
14236
0
  if (idx == input.size()) {
14237
0
    update_base_password(input);
14238
0
  } else {
14239
    // We only create a temporary string if we have to!
14240
0
    update_base_password(ada::unicode::percent_encode(
14241
0
        input, character_sets::USERINFO_PERCENT_ENCODE, idx));
14242
0
  }
14243
0
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14244
0
    *this = std::move(*saved_url);
14245
0
    return false;
14246
0
  }
14247
0
  ADA_ASSERT_TRUE(validate());
14248
0
  return true;
14249
0
}
14250
14251
0
bool url_aggregator::set_port(const std::string_view input) {
14252
0
  ada_log("url_aggregator::set_port ", input);
14253
0
  ADA_ASSERT_TRUE(validate());
14254
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14255
0
  if (cannot_have_credentials_or_port()) {
14256
0
    return false;
14257
0
  }
14258
14259
0
  if (input.empty()) {
14260
0
    clear_port();
14261
0
    return true;
14262
0
  }
14263
14264
0
  std::string trimmed(input);
14265
0
  helpers::remove_ascii_tab_or_newline(trimmed);
14266
14267
0
  if (trimmed.empty()) {
14268
0
    return true;
14269
0
  }
14270
14271
  // Input should not start with a non-digit character.
14272
0
  if (!ada::unicode::is_ascii_digit(trimmed.front())) {
14273
0
    return false;
14274
0
  }
14275
14276
  // Find the first non-digit character to determine the length of digits
14277
0
  auto first_non_digit =
14278
0
      std::ranges::find_if_not(trimmed, ada::unicode::is_ascii_digit);
14279
0
  std::string_view digits_to_parse =
14280
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
14281
14282
  // parse_port only touches the buffer once the digits are already known to
14283
  // be in range, so an invalid port never mutates anything and needs no
14284
  // rollback; a valid one can only grow the buffer by a few bytes.
14285
0
  std::optional<url_aggregator> saved_url;
14286
0
  if (needs_rollback_snapshot(digits_to_parse.size())) {
14287
0
    saved_url = *this;
14288
0
  }
14289
0
  parse_port(digits_to_parse);
14290
0
  if (!is_valid) {
14291
0
    is_valid = true;
14292
0
    ADA_ASSERT_TRUE(validate());
14293
0
    return false;
14294
0
  }
14295
0
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14296
0
    *this = std::move(*saved_url);
14297
0
    return false;
14298
0
  }
14299
0
  return true;
14300
0
}
14301
14302
259k
bool url_aggregator::set_pathname(const std::string_view input) {
14303
259k
  ada_log("url_aggregator::set_pathname ", input);
14304
259k
  ADA_ASSERT_TRUE(validate());
14305
259k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14306
259k
  if (has_opaque_path) {
14307
0
    return false;
14308
0
  }
14309
259k
  std::optional<url_aggregator> saved_url;
14310
259k
  if (needs_rollback_snapshot(input.size())) {
14311
0
    saved_url = *this;
14312
0
  }
14313
259k
  clear_pathname();
14314
259k
  parse_path(input);
14315
259k
  if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
14316
0
    buffer.insert(components.pathname_start, "/.");
14317
0
    components.pathname_start += 2;
14318
0
    if (components.search_start != url_components::omitted) {
14319
0
      components.search_start += 2;
14320
0
    }
14321
0
    if (components.hash_start != url_components::omitted) {
14322
0
      components.hash_start += 2;
14323
0
    }
14324
0
  }
14325
259k
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14326
0
    *this = std::move(*saved_url);
14327
0
    return false;
14328
0
  }
14329
259k
  ADA_ASSERT_TRUE(validate());
14330
259k
  return true;
14331
259k
}
14332
14333
289k
ada_really_inline void url_aggregator::parse_path(std::string_view input) {
14334
289k
  ada_log("url_aggregator::parse_path ", input);
14335
289k
  ADA_ASSERT_TRUE(validate());
14336
289k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14337
289k
  std::string tmp_buffer;
14338
289k
  std::string_view internal_input;
14339
289k
  if (unicode::has_tabs_or_newline(input)) {
14340
4.45k
    tmp_buffer = input;
14341
    // Optimization opportunity: Instead of copying and then pruning, we could
14342
    // just directly build the string from user_input.
14343
4.45k
    helpers::remove_ascii_tab_or_newline(tmp_buffer);
14344
4.45k
    internal_input = tmp_buffer;
14345
285k
  } else {
14346
285k
    internal_input = input;
14347
285k
  }
14348
14349
  // If url is special, then:
14350
289k
  if (is_special()) {
14351
289k
    if (internal_input.empty()) {
14352
7.46k
      update_base_pathname("/");
14353
282k
    } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
14354
282k
      consume_prepared_path(internal_input.substr(1));
14355
282k
    } else {
14356
0
      consume_prepared_path(internal_input);
14357
0
    }
14358
289k
  } else if (!internal_input.empty()) {
14359
0
    if (internal_input[0] == '/') {
14360
0
      consume_prepared_path(internal_input.substr(1));
14361
0
    } else {
14362
0
      consume_prepared_path(internal_input);
14363
0
    }
14364
0
  } else {
14365
    // Non-special URLs with an empty host can have their paths erased
14366
    // Path-only URLs cannot have their paths erased
14367
0
    if (components.host_start == components.host_end && !has_authority()) {
14368
0
      update_base_pathname("/");
14369
0
    }
14370
0
  }
14371
289k
  ADA_ASSERT_TRUE(validate());
14372
289k
}
14373
14374
0
void url_aggregator::set_search(const std::string_view input) {
14375
0
  ada_log("url_aggregator::set_search ", input);
14376
0
  ADA_ASSERT_TRUE(validate());
14377
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14378
0
  if (input.empty()) {
14379
0
    clear_search();
14380
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14381
0
    return;
14382
0
  }
14383
14384
0
  std::string_view stripped = input[0] == '?' ? input.substr(1) : input;
14385
  // Fast path: no tabs/newlines (the common case) avoids the std::string
14386
  // allocation entirely by passing the view straight to update_base_search.
14387
0
  std::string cleaned;
14388
0
  std::string_view effective = stripped;
14389
0
  if (unicode::has_tabs_or_newline(stripped)) {
14390
0
    cleaned = stripped;
14391
0
    helpers::remove_ascii_tab_or_newline(cleaned);
14392
0
    effective = cleaned;
14393
0
  }
14394
14395
0
  auto query_percent_encode_set =
14396
0
      is_special() ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
14397
0
                   : ada::character_sets::QUERY_PERCENT_ENCODE;
14398
14399
0
  std::optional<url_aggregator> saved_url;
14400
0
  if (needs_rollback_snapshot(effective.size())) {
14401
0
    saved_url = *this;
14402
0
  }
14403
0
  update_base_search(effective, query_percent_encode_set);
14404
0
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14405
0
    *this = std::move(*saved_url);
14406
0
    return;
14407
0
  }
14408
0
  ADA_ASSERT_TRUE(validate());
14409
0
}
14410
14411
0
void url_aggregator::set_hash(const std::string_view input) {
14412
0
  ada_log("url_aggregator::set_hash ", input);
14413
0
  ADA_ASSERT_TRUE(validate());
14414
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14415
0
  if (input.empty()) {
14416
0
    if (components.hash_start != url_components::omitted) {
14417
0
      buffer.resize(components.hash_start);
14418
0
      components.hash_start = url_components::omitted;
14419
0
    }
14420
0
    helpers::strip_trailing_spaces_from_opaque_path(*this);
14421
0
    return;
14422
0
  }
14423
14424
0
  std::string_view stripped = input[0] == '#' ? input.substr(1) : input;
14425
  // Fast path: no tabs/newlines (the common case) avoids the std::string
14426
  // allocation entirely by passing the view straight through.
14427
0
  std::string cleaned;
14428
0
  std::string_view effective = stripped;
14429
0
  if (unicode::has_tabs_or_newline(stripped)) {
14430
0
    cleaned = stripped;
14431
0
    helpers::remove_ascii_tab_or_newline(cleaned);
14432
0
    effective = cleaned;
14433
0
  }
14434
0
  std::optional<url_aggregator> saved_url;
14435
0
  if (needs_rollback_snapshot(effective.size())) {
14436
0
    saved_url = *this;
14437
0
  }
14438
0
  update_unencoded_base_hash(effective);
14439
0
  if (saved_url && buffer.size() > ada::get_max_input_length()) {
14440
0
    *this = std::move(*saved_url);
14441
0
    return;
14442
0
  }
14443
0
  ADA_ASSERT_TRUE(validate());
14444
0
}
14445
14446
0
bool url_aggregator::set_href(const std::string_view input) {
14447
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14448
0
  ada_log("url_aggregator::set_href ", input, " [", input.size(), " bytes]");
14449
0
  ada::result<url_aggregator> out = ada::parse<url_aggregator>(input);
14450
0
  ada_log("url_aggregator::set_href, success :", out.has_value());
14451
14452
0
  if (out) {
14453
    // The parser enforces get_max_input_length() on both the input and the
14454
    // normalized result. This is a defense-in-depth check.
14455
0
    if (out->buffer.size() > ada::get_max_input_length()) {
14456
0
      return false;
14457
0
    }
14458
0
    ada_log("url_aggregator::set_href, parsed ", out->to_string());
14459
    // TODO: Figure out why the following line puts test to never finish.
14460
0
    *this = std::move(*out);
14461
0
  }
14462
14463
0
  return out.has_value();
14464
0
}
14465
14466
256k
ada_really_inline bool url_aggregator::parse_host(std::string_view input) {
14467
256k
  ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(),
14468
256k
          " bytes]");
14469
256k
  ADA_ASSERT_TRUE(validate());
14470
256k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14471
256k
  if (input.empty()) {
14472
911
    return is_valid = false;
14473
911
  }  // technically unnecessary.
14474
  // If input starts with U+005B ([), then:
14475
255k
  if (input[0] == '[') {
14476
    // If input does not end with U+005D (]), validation error, return failure.
14477
11.5k
    if (input.back() != ']') {
14478
2.47k
      return is_valid = false;
14479
2.47k
    }
14480
9.09k
    ada_log("parse_host ipv6");
14481
14482
    // Return the result of IPv6 parsing input with its leading U+005B ([) and
14483
    // trailing U+005D (]) removed.
14484
9.09k
    input.remove_prefix(1);
14485
9.09k
    input.remove_suffix(1);
14486
9.09k
    return parse_ipv6(input);
14487
11.5k
  }
14488
14489
  // If isNotSpecial is true, then return the result of opaque-host parsing
14490
  // input.
14491
243k
  if (!is_special()) {
14492
292
    return parse_opaque_host(input);
14493
292
  }
14494
  // Let domain be the result of running UTF-8 decode without BOM on the
14495
  // percent-decoding of input. Let asciiDomain be the result of running domain
14496
  // to ASCII with domain and false. The most common case is an ASCII input, in
14497
  // which case we do not need to call the expensive 'to_ascii' if a few
14498
  // conditions are met: no '%' and no 'xn-' subsequence.
14499
14500
  // Often, the input does not contain any forbidden code points, and no upper
14501
  // case ASCII letter, then we can just copy it to the buffer. We want to
14502
  // optimize for such a common case.
14503
14504
  // Fast path: try to parse as pure decimal IPv4 first.
14505
243k
  const uint64_t fast_result = checkers::try_parse_ipv4_fast(input);
14506
243k
  if (fast_result < checkers::ipv4_fast_fail) {
14507
868
    if (!input.empty() && input.back() == '.') {
14508
320
      update_base_hostname(input.substr(0, input.size() - 1));
14509
548
    } else {
14510
548
      update_base_hostname(input);
14511
548
    }
14512
868
    host_type = IPV4;
14513
868
    is_valid = true;
14514
868
    ada_log("parse_host fast path decimal ipv4");
14515
868
    ADA_ASSERT_TRUE(validate());
14516
868
    return true;
14517
868
  }
14518
242k
  uint8_t is_forbidden_or_upper =
14519
242k
      unicode::contains_forbidden_domain_code_point_or_upper(input.data(),
14520
242k
                                                             input.size());
14521
242k
  static constexpr std::string_view xn_dash{"xn-", 3};
14522
242k
  if ((is_forbidden_or_upper & 1) == 0) {
14523
140k
    if ((is_forbidden_or_upper & 2) != 0) {
14524
28.8k
      std::string lowered(input);
14525
28.8k
      unicode::to_lower_ascii(lowered.data(), lowered.size());
14526
28.8k
      if (lowered.find('-') == std::string_view::npos ||
14527
26.3k
          lowered.find(xn_dash) == std::string_view::npos) {
14528
        // Check IPv4 before mutating so failures leave the buffer untouched.
14529
        // This also avoids a double buffer rewrite for hex/octal IPv4.
14530
26.3k
        if (checkers::is_ipv4(lowered)) {
14531
5.66k
          ada_log("parse_host fast path ipv4");
14532
5.66k
          return parse_ipv4(lowered, false);
14533
5.66k
        }
14534
20.7k
        update_base_hostname(lowered);
14535
20.7k
        ada_log("parse_host fast path ", get_hostname());
14536
20.7k
        is_valid = true;
14537
20.7k
        return true;
14538
26.3k
      }
14539
111k
    } else if (input.find('-') == std::string_view::npos ||
14540
105k
               input.find(xn_dash) == std::string_view::npos) {
14541
      // Check IPv4 before mutating so failures leave the buffer untouched.
14542
105k
      if (checkers::is_ipv4(input)) {
14543
34.5k
        ada_log("parse_host fast path ipv4");
14544
34.5k
        return parse_ipv4(input, false);
14545
34.5k
      }
14546
70.9k
      update_base_hostname(input);
14547
70.9k
      ada_log("parse_host fast path ", get_hostname());
14548
70.9k
      is_valid = true;
14549
70.9k
      return true;
14550
105k
    }
14551
140k
  } else if (const size_t first_percent = input.find('%');
14552
102k
             first_percent != std::string_view::npos) {
14553
90.2k
    std::string decoded = unicode::percent_decode(input, first_percent);
14554
90.2k
    const uint8_t decoded_flags =
14555
90.2k
        unicode::contains_forbidden_domain_code_point_or_upper(decoded.data(),
14556
90.2k
                                                               decoded.size());
14557
90.2k
    if ((decoded_flags & 1) == 0) {
14558
10.6k
      if ((decoded_flags & 2) != 0) {
14559
3.37k
        unicode::to_lower_ascii(decoded.data(), decoded.size());
14560
3.37k
      }
14561
10.6k
      if (decoded.find('-') == std::string_view::npos ||
14562
10.2k
          decoded.find(xn_dash) == std::string_view::npos) {
14563
        // Check IPv4 before mutating so failures leave the buffer untouched.
14564
10.2k
        if (checkers::is_ipv4(decoded)) {
14565
3.95k
          return parse_ipv4(decoded, false);
14566
3.95k
        }
14567
6.29k
        update_base_hostname(decoded);
14568
6.29k
        is_valid = true;
14569
6.29k
        return true;
14570
10.2k
      }
14571
10.6k
    }
14572
90.2k
  }
14573
  // We have encountered at least one forbidden code point or the input contains
14574
  // 'xn-' (case insensitive), so we need to call 'to_ascii' to perform the full
14575
  // conversion.
14576
14577
100k
  ada_log("parse_host calling to_ascii");
14578
100k
  std::optional<std::string> host = std::string(get_hostname());
14579
100k
  is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
14580
100k
  if (!is_valid) {
14581
65.5k
    ada_log("parse_host to_ascii returns false");
14582
65.5k
    return is_valid = false;
14583
65.5k
  }
14584
35.1k
  ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
14585
35.1k
          " bytes]");
14586
14587
35.1k
  if (std::ranges::any_of(host.value(),
14588
35.1k
                          ada::unicode::is_forbidden_domain_code_point)) {
14589
0
    return is_valid = false;
14590
0
  }
14591
14592
  // If asciiDomain ends in a number, then return the result of IPv4 parsing
14593
  // asciiDomain.
14594
35.1k
  if (checkers::is_ipv4(host.value())) {
14595
3.68k
    ada_log("parse_host got ipv4 ", *host);
14596
3.68k
    return parse_ipv4(host.value(), false);
14597
3.68k
  }
14598
14599
31.5k
  update_base_hostname(host.value());
14600
31.5k
  ADA_ASSERT_TRUE(validate());
14601
31.5k
  return true;
14602
35.1k
}
14603
14604
template <bool override_hostname>
14605
4.58k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14606
4.58k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14607
4.58k
  ADA_ASSERT_TRUE(validate());
14608
4.58k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14609
4.58k
  if (has_opaque_path) {
14610
0
    return false;
14611
0
  }
14612
14613
  // parse_host no longer mutates the buffer on failure (IPv4 is checked
14614
  // before update_base_hostname), so the only rollback needed is for the
14615
  // length limit. Snapshot only when the bound can be reached, like the
14616
  // other setters do via needs_rollback_snapshot.
14617
4.58k
  const bool was_valid = is_valid;
14618
4.58k
  std::optional<url_aggregator> saved_url;
14619
4.58k
  if (needs_rollback_snapshot(input.size())) {
14620
0
    saved_url = *this;
14621
0
  }
14622
14623
4.58k
  auto restore_on_failure = [&]() {
14624
1.30k
    if (saved_url) {
14625
0
      *this = std::move(*saved_url);
14626
1.30k
    } else {
14627
      // Buffer is untouched on parse failure; just restore the is_valid flag
14628
      // that parse_host may have cleared.
14629
1.30k
      is_valid = was_valid;
14630
1.30k
    }
14631
1.30k
  };
Unexecuted instantiation: ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const
Line
Count
Source
14623
1.30k
  auto restore_on_failure = [&]() {
14624
1.30k
    if (saved_url) {
14625
0
      *this = std::move(*saved_url);
14626
1.30k
    } else {
14627
      // Buffer is untouched on parse failure; just restore the is_valid flag
14628
      // that parse_host may have cleared.
14629
1.30k
      is_valid = was_valid;
14630
1.30k
    }
14631
1.30k
  };
14632
14633
4.58k
  size_t host_end_pos = input.find('#');
14634
4.58k
  std::string_view host_input(
14635
4.58k
      input.data(),
14636
4.58k
      host_end_pos != std::string_view::npos ? host_end_pos : input.size());
14637
  // Fast path: no tabs/newlines (the common case) avoids the std::string
14638
  // allocation by viewing the input prefix directly.
14639
4.58k
  std::string _host_buf;
14640
4.58k
  std::string_view new_host;
14641
4.58k
  if (unicode::has_tabs_or_newline(host_input)) {
14642
303
    _host_buf = host_input;
14643
303
    helpers::remove_ascii_tab_or_newline(_host_buf);
14644
303
    new_host = _host_buf;
14645
4.28k
  } else {
14646
4.28k
    new_host = host_input;
14647
4.28k
  }
14648
14649
4.58k
  auto check_url_size = [&]() -> bool {
14650
3.16k
    if (saved_url && buffer.size() > ada::get_max_input_length()) {
14651
0
      *this = std::move(*saved_url);
14652
0
      return false;
14653
0
    }
14654
3.16k
    return true;
14655
3.16k
  };
Unexecuted instantiation: ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#2}::operator()() const
ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#2}::operator()() const
Line
Count
Source
14649
3.16k
  auto check_url_size = [&]() -> bool {
14650
3.16k
    if (saved_url && buffer.size() > ada::get_max_input_length()) {
14651
0
      *this = std::move(*saved_url);
14652
0
      return false;
14653
0
    }
14654
3.16k
    return true;
14655
3.16k
  };
14656
14657
  // If url's scheme is "file", then set state to file host state, instead of
14658
  // host state.
14659
4.58k
  if (type != ada::scheme::type::FILE) {
14660
4.58k
    std::string_view host_view = new_host;
14661
4.58k
    auto [location, found_colon] =
14662
4.58k
        helpers::get_host_delimiter_location(is_special(), host_view);
14663
14664
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14665
    // Note: the 'found_colon' value is true if and only if a colon was
14666
    // encountered while not inside brackets.
14667
4.58k
    if (found_colon) {
14668
      // If buffer is the empty string, host-missing validation error, return
14669
      // failure.
14670
11
      std::string_view host_buffer = host_view.substr(0, location);
14671
11
      if (host_buffer.empty()) {
14672
10
        return false;
14673
10
      }
14674
14675
      // If state override is given and state override is hostname state, then
14676
      // return failure.
14677
1
      if constexpr (override_hostname) {
14678
1
        return false;
14679
1
      }
14680
14681
      // Let host be the result of host parsing buffer with url is not special.
14682
0
      bool succeeded = parse_host(host_buffer);
14683
1
      if (!succeeded) {
14684
0
        restore_on_failure();
14685
0
        return false;
14686
1
      } else if (has_dash_dot()) {
14687
        // The url now has a non-null host, so the "/." that guarded a
14688
        // leading "//" path is no longer needed. Drop it before the port is
14689
        // inserted at host_end, otherwise it stays wedged in the path.
14690
0
        delete_dash_dot();
14691
0
      }
14692
14693
      // Set url's host to host, buffer to the empty string, and state to port
14694
      // state.
14695
1
      std::string_view port_buffer = new_host.substr(location + 1);
14696
1
      if (!port_buffer.empty()) {
14697
0
        set_port(port_buffer);
14698
0
      }
14699
1
      return check_url_size();
14700
1
    }
14701
    // Otherwise, if one of the following is true:
14702
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14703
    // - url is special and c is U+005C (\)
14704
4.57k
    else {
14705
      // If url is special and host_view is the empty string, host-missing
14706
      // validation error, return failure.
14707
4.57k
      if (host_view.empty() && is_special()) {
14708
110
        return false;
14709
110
      }
14710
14711
      // Otherwise, if state override is given, host_view is the empty string,
14712
      // and either url includes credentials or url's port is non-null, then
14713
      // return failure.
14714
4.46k
      if (host_view.empty() && (has_credentials() || has_port())) {
14715
0
        return false;
14716
0
      }
14717
14718
      // Let host be the result of host parsing host_view with url is not
14719
      // special.
14720
4.46k
      if (host_view.empty() && !is_special()) {
14721
0
        if (has_hostname()) {
14722
0
          clear_hostname();  // easy!
14723
0
        } else if (has_dash_dot()) {
14724
0
          add_authority_slashes_if_needed();
14725
0
          delete_dash_dot();
14726
0
        } else {
14727
          // The url has no authority yet (e.g. "foo:/bar"); setting an empty
14728
          // host must still give it an (empty) authority, matching ada::url.
14729
0
          add_authority_slashes_if_needed();
14730
0
        }
14731
0
        return check_url_size();
14732
0
      }
14733
14734
4.46k
      bool succeeded = parse_host(host_view);
14735
4.46k
      if (!succeeded) {
14736
1.30k
        restore_on_failure();
14737
1.30k
        return false;
14738
3.16k
      } else if (has_dash_dot()) {
14739
        // Should remove dash_dot from pathname
14740
0
        delete_dash_dot();
14741
0
      }
14742
3.16k
      return check_url_size();
14743
4.46k
    }
14744
4.58k
  }
14745
14746
0
  size_t location = new_host.find_first_of("/\\?");
14747
0
  if (location != std::string_view::npos) {
14748
0
    new_host.remove_suffix(new_host.length() - location);
14749
0
  }
14750
14751
0
  if (new_host.empty()) {
14752
    // Set url's host to the empty string.
14753
0
    clear_hostname();
14754
0
  } else {
14755
    // Let host be the result of host parsing buffer with url is not special.
14756
0
    if (!parse_host(new_host)) {
14757
0
      restore_on_failure();
14758
0
      return false;
14759
0
    }
14760
14761
    // If host is "localhost", then set host to the empty string.
14762
0
    if (helpers::substring(buffer, components.host_start,
14763
0
                           components.host_end) == "localhost") {
14764
0
      clear_hostname();
14765
0
    }
14766
0
  }
14767
0
  ADA_ASSERT_TRUE(validate());
14768
0
  return check_url_size();
14769
0
}
Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
14605
4.58k
bool url_aggregator::set_host_or_hostname(const std::string_view input) {
14606
4.58k
  ada_log("url_aggregator::set_host_or_hostname ", input);
14607
4.58k
  ADA_ASSERT_TRUE(validate());
14608
4.58k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14609
4.58k
  if (has_opaque_path) {
14610
0
    return false;
14611
0
  }
14612
14613
  // parse_host no longer mutates the buffer on failure (IPv4 is checked
14614
  // before update_base_hostname), so the only rollback needed is for the
14615
  // length limit. Snapshot only when the bound can be reached, like the
14616
  // other setters do via needs_rollback_snapshot.
14617
4.58k
  const bool was_valid = is_valid;
14618
4.58k
  std::optional<url_aggregator> saved_url;
14619
4.58k
  if (needs_rollback_snapshot(input.size())) {
14620
0
    saved_url = *this;
14621
0
  }
14622
14623
4.58k
  auto restore_on_failure = [&]() {
14624
4.58k
    if (saved_url) {
14625
4.58k
      *this = std::move(*saved_url);
14626
4.58k
    } else {
14627
      // Buffer is untouched on parse failure; just restore the is_valid flag
14628
      // that parse_host may have cleared.
14629
4.58k
      is_valid = was_valid;
14630
4.58k
    }
14631
4.58k
  };
14632
14633
4.58k
  size_t host_end_pos = input.find('#');
14634
4.58k
  std::string_view host_input(
14635
4.58k
      input.data(),
14636
4.58k
      host_end_pos != std::string_view::npos ? host_end_pos : input.size());
14637
  // Fast path: no tabs/newlines (the common case) avoids the std::string
14638
  // allocation by viewing the input prefix directly.
14639
4.58k
  std::string _host_buf;
14640
4.58k
  std::string_view new_host;
14641
4.58k
  if (unicode::has_tabs_or_newline(host_input)) {
14642
303
    _host_buf = host_input;
14643
303
    helpers::remove_ascii_tab_or_newline(_host_buf);
14644
303
    new_host = _host_buf;
14645
4.28k
  } else {
14646
4.28k
    new_host = host_input;
14647
4.28k
  }
14648
14649
4.58k
  auto check_url_size = [&]() -> bool {
14650
4.58k
    if (saved_url && buffer.size() > ada::get_max_input_length()) {
14651
4.58k
      *this = std::move(*saved_url);
14652
4.58k
      return false;
14653
4.58k
    }
14654
4.58k
    return true;
14655
4.58k
  };
14656
14657
  // If url's scheme is "file", then set state to file host state, instead of
14658
  // host state.
14659
4.58k
  if (type != ada::scheme::type::FILE) {
14660
4.58k
    std::string_view host_view = new_host;
14661
4.58k
    auto [location, found_colon] =
14662
4.58k
        helpers::get_host_delimiter_location(is_special(), host_view);
14663
14664
    // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
14665
    // Note: the 'found_colon' value is true if and only if a colon was
14666
    // encountered while not inside brackets.
14667
4.58k
    if (found_colon) {
14668
      // If buffer is the empty string, host-missing validation error, return
14669
      // failure.
14670
11
      std::string_view host_buffer = host_view.substr(0, location);
14671
11
      if (host_buffer.empty()) {
14672
10
        return false;
14673
10
      }
14674
14675
      // If state override is given and state override is hostname state, then
14676
      // return failure.
14677
1
      if constexpr (override_hostname) {
14678
1
        return false;
14679
1
      }
14680
14681
      // Let host be the result of host parsing buffer with url is not special.
14682
0
      bool succeeded = parse_host(host_buffer);
14683
1
      if (!succeeded) {
14684
0
        restore_on_failure();
14685
0
        return false;
14686
1
      } else if (has_dash_dot()) {
14687
        // The url now has a non-null host, so the "/." that guarded a
14688
        // leading "//" path is no longer needed. Drop it before the port is
14689
        // inserted at host_end, otherwise it stays wedged in the path.
14690
0
        delete_dash_dot();
14691
0
      }
14692
14693
      // Set url's host to host, buffer to the empty string, and state to port
14694
      // state.
14695
1
      std::string_view port_buffer = new_host.substr(location + 1);
14696
1
      if (!port_buffer.empty()) {
14697
0
        set_port(port_buffer);
14698
0
      }
14699
1
      return check_url_size();
14700
1
    }
14701
    // Otherwise, if one of the following is true:
14702
    // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
14703
    // - url is special and c is U+005C (\)
14704
4.57k
    else {
14705
      // If url is special and host_view is the empty string, host-missing
14706
      // validation error, return failure.
14707
4.57k
      if (host_view.empty() && is_special()) {
14708
110
        return false;
14709
110
      }
14710
14711
      // Otherwise, if state override is given, host_view is the empty string,
14712
      // and either url includes credentials or url's port is non-null, then
14713
      // return failure.
14714
4.46k
      if (host_view.empty() && (has_credentials() || has_port())) {
14715
0
        return false;
14716
0
      }
14717
14718
      // Let host be the result of host parsing host_view with url is not
14719
      // special.
14720
4.46k
      if (host_view.empty() && !is_special()) {
14721
0
        if (has_hostname()) {
14722
0
          clear_hostname();  // easy!
14723
0
        } else if (has_dash_dot()) {
14724
0
          add_authority_slashes_if_needed();
14725
0
          delete_dash_dot();
14726
0
        } else {
14727
          // The url has no authority yet (e.g. "foo:/bar"); setting an empty
14728
          // host must still give it an (empty) authority, matching ada::url.
14729
0
          add_authority_slashes_if_needed();
14730
0
        }
14731
0
        return check_url_size();
14732
0
      }
14733
14734
4.46k
      bool succeeded = parse_host(host_view);
14735
4.46k
      if (!succeeded) {
14736
1.30k
        restore_on_failure();
14737
1.30k
        return false;
14738
3.16k
      } else if (has_dash_dot()) {
14739
        // Should remove dash_dot from pathname
14740
0
        delete_dash_dot();
14741
0
      }
14742
3.16k
      return check_url_size();
14743
4.46k
    }
14744
4.58k
  }
14745
14746
0
  size_t location = new_host.find_first_of("/\\?");
14747
0
  if (location != std::string_view::npos) {
14748
0
    new_host.remove_suffix(new_host.length() - location);
14749
0
  }
14750
14751
0
  if (new_host.empty()) {
14752
    // Set url's host to the empty string.
14753
0
    clear_hostname();
14754
0
  } else {
14755
    // Let host be the result of host parsing buffer with url is not special.
14756
0
    if (!parse_host(new_host)) {
14757
0
      restore_on_failure();
14758
0
      return false;
14759
0
    }
14760
14761
    // If host is "localhost", then set host to the empty string.
14762
0
    if (helpers::substring(buffer, components.host_start,
14763
0
                           components.host_end) == "localhost") {
14764
0
      clear_hostname();
14765
0
    }
14766
0
  }
14767
0
  ADA_ASSERT_TRUE(validate());
14768
0
  return check_url_size();
14769
0
}
14770
14771
0
bool url_aggregator::set_host(const std::string_view input) {
14772
0
  ada_log("url_aggregator::set_host '", input, "'");
14773
0
  ADA_ASSERT_TRUE(validate());
14774
0
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14775
0
  return set_host_or_hostname<false>(input);
14776
0
}
14777
14778
4.58k
bool url_aggregator::set_hostname(const std::string_view input) {
14779
4.58k
  ada_log("url_aggregator::set_hostname '", input, "'");
14780
4.58k
  ADA_ASSERT_TRUE(validate());
14781
4.58k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
14782
4.58k
  return set_host_or_hostname<true>(input);
14783
4.58k
}
14784
14785
0
[[nodiscard]] std::string url_aggregator::get_origin() const {
14786
0
  ada_log("url_aggregator::get_origin");
14787
0
  if (is_special()) {
14788
    // Return a new opaque origin.
14789
0
    if (type == scheme::FILE) {
14790
0
      return "null";
14791
0
    }
14792
14793
0
    return helpers::concat(get_protocol(), "//", get_host());
14794
0
  }
14795
14796
0
  if (get_protocol() == "blob:") {
14797
0
    std::string_view path = get_pathname();
14798
0
    if (!path.empty()) {
14799
0
      auto out = ada::parse<ada::url_aggregator>(path);
14800
0
      if (out && (out->type == scheme::HTTP || out->type == scheme::HTTPS)) {
14801
        // If pathURL's scheme is not "http" and not "https", then return a
14802
        // new opaque origin.
14803
0
        return helpers::concat(out->get_protocol(), "//", out->get_host());
14804
0
      }
14805
0
    }
14806
0
  }
14807
14808
  // Return a new opaque origin.
14809
0
  return "null";
14810
0
}
14811
14812
[[nodiscard]] std::string_view url_aggregator::get_username() const
14813
236k
    ada_lifetime_bound {
14814
236k
  ada_log("url_aggregator::get_username");
14815
236k
  if (has_non_empty_username()) {
14816
12.4k
    return helpers::substring(buffer, components.protocol_end + 2,
14817
12.4k
                              components.username_end);
14818
12.4k
  }
14819
224k
  return "";
14820
236k
}
14821
14822
[[nodiscard]] std::string_view url_aggregator::get_password() const
14823
236k
    ada_lifetime_bound {
14824
236k
  ada_log("url_aggregator::get_password");
14825
236k
  if (has_non_empty_password()) {
14826
5.56k
    return helpers::substring(buffer, components.username_end + 1,
14827
5.56k
                              components.host_start);
14828
5.56k
  }
14829
231k
  return "";
14830
236k
}
14831
14832
[[nodiscard]] std::string_view url_aggregator::get_port() const
14833
267k
    ada_lifetime_bound {
14834
267k
  ada_log("url_aggregator::get_port");
14835
267k
  if (components.port == url_components::omitted) {
14836
256k
    return "";
14837
256k
  }
14838
11.8k
  return helpers::substring(buffer, components.host_end + 1,
14839
11.8k
                            components.pathname_start);
14840
267k
}
14841
14842
[[nodiscard]] std::string_view url_aggregator::get_hash() const
14843
137k
    ada_lifetime_bound {
14844
137k
  ada_log("url_aggregator::get_hash");
14845
  // If this's URL's fragment is either null or the empty string, then return
14846
  // the empty string. Return U+0023 (#), followed by this's URL's fragment.
14847
137k
  if (components.hash_start == url_components::omitted) {
14848
108k
    return "";
14849
108k
  }
14850
29.7k
  if (buffer.size() - components.hash_start <= 1) {
14851
1.86k
    return "";
14852
1.86k
  }
14853
27.8k
  return helpers::substring(buffer, components.hash_start);
14854
29.7k
}
14855
14856
[[nodiscard]] std::string_view url_aggregator::get_host() const
14857
0
    ada_lifetime_bound {
14858
0
  ada_log("url_aggregator::get_host");
14859
  // Technically, we should check if there is a hostname, but
14860
  // the code below works even if there isn't.
14861
  // if(!has_hostname()) { return ""; }
14862
0
  size_t start = components.host_start;
14863
0
  if (components.host_end > components.host_start &&
14864
0
      buffer[components.host_start] == '@') {
14865
0
    start++;
14866
0
  }
14867
  // if we have an empty host, then the space between components.host_end and
14868
  // components.pathname_start may be occupied by /.
14869
0
  if (start == components.host_end) {
14870
0
    return {};
14871
0
  }
14872
0
  return helpers::substring(buffer, start, components.pathname_start);
14873
0
}
14874
14875
[[nodiscard]] std::string_view url_aggregator::get_hostname() const
14876
374k
    ada_lifetime_bound {
14877
374k
  ada_log("url_aggregator::get_hostname");
14878
  // Technically, we should check if there is a hostname, but
14879
  // the code below works even if there isn't.
14880
  // if(!has_hostname()) { return ""; }
14881
374k
  size_t start = components.host_start;
14882
  // So host_start is not where the host begins.
14883
374k
  if (components.host_end > components.host_start &&
14884
273k
      buffer[components.host_start] == '@') {
14885
17.8k
    start++;
14886
17.8k
  }
14887
374k
  return helpers::substring(buffer, start, components.host_end);
14888
374k
}
14889
14890
[[nodiscard]] std::string_view url_aggregator::get_search() const
14891
141k
    ada_lifetime_bound {
14892
141k
  ada_log("url_aggregator::get_search");
14893
  // If this's URL's query is either null or the empty string, then return the
14894
  // empty string. Return U+003F (?), followed by this's URL's query.
14895
141k
  if (components.search_start == url_components::omitted) {
14896
106k
    return "";
14897
106k
  }
14898
35.0k
  auto ending_index = uint32_t(buffer.size());
14899
35.0k
  if (components.hash_start != url_components::omitted) {
14900
6.29k
    ending_index = components.hash_start;
14901
6.29k
  }
14902
35.0k
  if (ending_index - components.search_start <= 1) {
14903
2.38k
    return "";
14904
2.38k
  }
14905
32.6k
  return helpers::substring(buffer, components.search_start, ending_index);
14906
35.0k
}
14907
14908
[[nodiscard]] std::string_view url_aggregator::get_protocol() const
14909
386k
    ada_lifetime_bound {
14910
386k
  ada_log("url_aggregator::get_protocol");
14911
386k
  return helpers::substring(buffer, 0, components.protocol_end);
14912
386k
}
14913
14914
0
[[nodiscard]] std::string ada::url_aggregator::to_string() const {
14915
0
  ada_log("url_aggregator::to_string buffer:", buffer, " [", buffer.size(),
14916
0
          " bytes]");
14917
0
  if (!is_valid) {
14918
0
    return "null";
14919
0
  }
14920
14921
0
  std::string answer;
14922
0
  auto back = std::back_insert_iterator(answer);
14923
0
  answer.append("{\n");
14924
14925
0
  answer.append("\t\"buffer\":\"");
14926
0
  helpers::encode_json(buffer, back);
14927
0
  answer.append("\",\n");
14928
14929
0
  answer.append("\t\"protocol\":\"");
14930
0
  helpers::encode_json(get_protocol(), back);
14931
0
  answer.append("\",\n");
14932
14933
0
  if (has_credentials()) {
14934
0
    answer.append("\t\"username\":\"");
14935
0
    helpers::encode_json(get_username(), back);
14936
0
    answer.append("\",\n");
14937
0
    answer.append("\t\"password\":\"");
14938
0
    helpers::encode_json(get_password(), back);
14939
0
    answer.append("\",\n");
14940
0
  }
14941
14942
0
  answer.append("\t\"host\":\"");
14943
0
  helpers::encode_json(get_host(), back);
14944
0
  answer.append("\",\n");
14945
14946
0
  answer.append("\t\"path\":\"");
14947
0
  helpers::encode_json(get_pathname(), back);
14948
0
  answer.append("\",\n");
14949
0
  answer.append("\t\"opaque path\":");
14950
0
  answer.append((has_opaque_path ? "true" : "false"));
14951
0
  answer.append(",\n");
14952
14953
0
  if (components.search_start != url_components::omitted) {
14954
0
    answer.append("\t\"query\":\"");
14955
0
    helpers::encode_json(get_search(), back);
14956
0
    answer.append("\",\n");
14957
0
  }
14958
0
  if (components.hash_start != url_components::omitted) {
14959
0
    answer.append("\t\"fragment\":\"");
14960
0
    helpers::encode_json(get_hash(), back);
14961
0
    answer.append("\",\n");
14962
0
  }
14963
14964
0
  auto convert_offset_to_string = [](uint32_t offset) -> std::string {
14965
0
    if (offset == url_components::omitted) {
14966
0
      return "null";
14967
0
    } else {
14968
0
      return std::to_string(offset);
14969
0
    }
14970
0
  };
14971
14972
0
  answer.append("\t\"protocol_end\":");
14973
0
  answer.append(convert_offset_to_string(components.protocol_end));
14974
0
  answer.append(",\n");
14975
14976
0
  answer.append("\t\"username_end\":");
14977
0
  answer.append(convert_offset_to_string(components.username_end));
14978
0
  answer.append(",\n");
14979
14980
0
  answer.append("\t\"host_start\":");
14981
0
  answer.append(convert_offset_to_string(components.host_start));
14982
0
  answer.append(",\n");
14983
14984
0
  answer.append("\t\"host_end\":");
14985
0
  answer.append(convert_offset_to_string(components.host_end));
14986
0
  answer.append(",\n");
14987
14988
0
  answer.append("\t\"port\":");
14989
0
  answer.append(convert_offset_to_string(components.port));
14990
0
  answer.append(",\n");
14991
14992
0
  answer.append("\t\"pathname_start\":");
14993
0
  answer.append(convert_offset_to_string(components.pathname_start));
14994
0
  answer.append(",\n");
14995
14996
0
  answer.append("\t\"search_start\":");
14997
0
  answer.append(convert_offset_to_string(components.search_start));
14998
0
  answer.append(",\n");
14999
15000
0
  answer.append("\t\"hash_start\":");
15001
0
  answer.append(convert_offset_to_string(components.hash_start));
15002
0
  answer.append("\n}");
15003
15004
0
  return answer;
15005
0
}
15006
15007
0
[[nodiscard]] bool url_aggregator::has_valid_domain() const noexcept {
15008
0
  if (components.host_start == components.host_end) {
15009
0
    return false;
15010
0
  }
15011
  // Avoid allocation: construct a string_view directly into the buffer.
15012
0
  size_t start = components.host_start;
15013
0
  if (components.host_end > components.host_start &&
15014
0
      buffer[components.host_start] == '@') {
15015
0
    start++;
15016
0
  }
15017
0
  return checkers::verify_dns_length(
15018
0
      std::string_view(buffer.data() + start, components.host_end - start));
15019
0
}
15020
15021
47.8k
bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) {
15022
47.8k
  ada_log("parse_ipv4 ", input, " [", input.size(),
15023
47.8k
          " bytes], overlaps with buffer: ",
15024
47.8k
          helpers::overlaps(input, buffer) ? "yes" : "no");
15025
47.8k
  ADA_ASSERT_TRUE(validate());
15026
47.8k
  if (input.empty()) {
15027
0
    return is_valid = false;
15028
0
  }
15029
47.8k
  const bool trailing_dot = (input.back() == '.');
15030
47.8k
  if (trailing_dot) {
15031
1.19k
    input.remove_suffix(1);
15032
1.19k
    if (input.empty()) {
15033
0
      return is_valid = false;
15034
0
    }
15035
1.19k
  }
15036
15037
47.8k
  const uint64_t fast = checkers::try_parse_ipv4_fast(input);
15038
47.8k
  if (fast < checkers::ipv4_fast_fail) [[likely]] {
15039
    // Pure decimal: keep the buffer when it already holds the address.
15040
    // Otherwise write the (trailing-dot-stripped) input.
15041
95
    if (!(in_place && !trailing_dot)) {
15042
95
      if (helpers::overlaps(input, buffer)) {
15043
0
        update_base_hostname(std::string(input));
15044
95
      } else {
15045
95
        update_base_hostname(input);
15046
95
      }
15047
95
    }
15048
95
    host_type = IPV4;
15049
95
    ADA_ASSERT_TRUE(validate());
15050
95
    return true;
15051
95
  }
15052
15053
47.7k
  const char* p = input.data();
15054
47.7k
  const char* end = p + input.size();
15055
47.7k
  uint64_t ipv4 = 0;
15056
47.7k
  int digit_count = 0;
15057
47.7k
  int pure_decimal_count = 0;
15058
15059
54.1k
  for (; digit_count < 4 && p < end; ++digit_count) {
15060
53.9k
    uint64_t segment = 0;
15061
53.9k
    bool pure = false;
15062
53.9k
    if (!detail::parse_ipv4_number(p, end, segment, pure)) {
15063
11.3k
      return is_valid = false;
15064
11.3k
    }
15065
42.6k
    if (pure) {
15066
32.5k
      ++pure_decimal_count;
15067
32.5k
    }
15068
42.6k
    if (p >= end) {
15069
34.7k
      const unsigned shift = static_cast<unsigned>(32 - digit_count * 8);
15070
34.7k
      if (segment >= (uint64_t{1} << shift)) {
15071
580
        return is_valid = false;
15072
580
      }
15073
34.1k
      ipv4 = (ipv4 << shift) | segment;
15074
34.1k
      goto ipv4_done;
15075
34.7k
    }
15076
7.95k
    if (segment > 255 || *p != '.') {
15077
1.50k
      return is_valid = false;
15078
1.50k
    }
15079
6.44k
    ipv4 = (ipv4 << 8) | segment;
15080
6.44k
    ++p;
15081
6.44k
  }
15082
213
  if (digit_count != 4 || p != end) {
15083
213
    return is_valid = false;
15084
213
  }
15085
34.1k
ipv4_done:
15086
34.1k
  ada_log("url_aggregator::parse_ipv4 completed ", get_href(),
15087
34.1k
          " host: ", get_host());
15088
34.1k
  if (in_place && pure_decimal_count == 4 && !trailing_dot) {
15089
0
    ada_log(
15090
0
        "url_aggregator::parse_ipv4 completed and was already correct in the "
15091
0
        "buffer");
15092
34.1k
  } else {
15093
34.1k
    update_base_hostname(ada::serializers::ipv4(ipv4));
15094
34.1k
  }
15095
34.1k
  host_type = IPV4;
15096
34.1k
  ADA_ASSERT_TRUE(validate());
15097
34.1k
  return true;
15098
213
}
15099
15100
9.09k
bool url_aggregator::parse_ipv6(std::string_view input) {
15101
9.09k
  ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
15102
9.09k
  ADA_ASSERT_TRUE(validate());
15103
9.09k
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15104
9.09k
  if (input.empty() || input.size() > 45) [[unlikely]] {
15105
347
    return is_valid = false;
15106
347
  }
15107
8.75k
  std::array<uint16_t, 8> address{};
15108
#if defined(ADA_AVX512_IPV6)
15109
  if (bool simd_valid; detail::try_parse_ipv6_avx512(input.data(), input.size(),
15110
                                                     address, simd_valid)) {
15111
    if (!simd_valid) [[unlikely]] {
15112
      return is_valid = false;
15113
    }
15114
    const std::string serialized = ada::serializers::ipv6(address);
15115
    if (get_hostname() != serialized) {
15116
      update_base_hostname(serialized);
15117
    }
15118
    host_type = IPV6;
15119
    return true;
15120
  }
15121
  address = {};
15122
#endif
15123
8.75k
  const char* pointer = input.data();
15124
8.75k
  const char* const end = pointer + input.size();
15125
8.75k
  int piece_index = 0;
15126
8.75k
  int compress = -1;
15127
15128
8.75k
  if (*pointer == ':') {
15129
2.41k
    if (input.size() == 1 || pointer[1] != ':') [[unlikely]] {
15130
440
      return is_valid = false;
15131
440
    }
15132
1.97k
    pointer += 2;
15133
1.97k
    compress = ++piece_index;
15134
1.97k
  }
15135
15136
21.5k
  while (pointer != end) {
15137
17.6k
    if (piece_index == 8) [[unlikely]] {
15138
85
      return is_valid = false;
15139
85
    }
15140
17.6k
    if (*pointer == ':') {
15141
1.50k
      if (compress != -1) [[unlikely]] {
15142
87
        return is_valid = false;
15143
87
      }
15144
1.42k
      ++pointer;
15145
1.42k
      compress = ++piece_index;
15146
1.42k
      continue;
15147
1.50k
    }
15148
15149
16.1k
    uint16_t value = 0;
15150
16.1k
    const int length = detail::parse_hex_piece(pointer, end, value);
15151
15152
16.1k
    if (pointer != end && *pointer == '.') {
15153
2.92k
      if (length == 0) [[unlikely]] {
15154
151
        return is_valid = false;
15155
151
      }
15156
2.77k
      pointer -= length;
15157
2.77k
      if (piece_index > 6) [[unlikely]] {
15158
85
        return is_valid = false;
15159
85
      }
15160
15161
2.69k
      int numbers_seen = 0;
15162
6.73k
      while (pointer != end) {
15163
6.20k
        int ipv4_piece = -1;
15164
6.20k
        if (numbers_seen > 0) {
15165
3.51k
          if (*pointer == '.' && numbers_seen < 4) {
15166
2.82k
            ++pointer;
15167
2.82k
          } else {
15168
686
            return is_valid = false;
15169
686
          }
15170
3.51k
        }
15171
5.51k
        if (pointer == end || *pointer < '0' || *pointer > '9') [[unlikely]] {
15172
1.18k
          return is_valid = false;
15173
1.18k
        }
15174
4.33k
        ipv4_piece = *pointer - '0';
15175
4.33k
        ++pointer;
15176
4.33k
        if (pointer != end && *pointer >= '0' && *pointer <= '9') {
15177
1.31k
          if (ipv4_piece == 0) [[unlikely]] {
15178
95
            return is_valid = false;
15179
95
          }
15180
1.22k
          ipv4_piece = ipv4_piece * 10 + (*pointer - '0');
15181
1.22k
          ++pointer;
15182
1.22k
          if (pointer != end && *pointer >= '0' && *pointer <= '9') {
15183
574
            ipv4_piece = ipv4_piece * 10 + (*pointer - '0');
15184
574
            ++pointer;
15185
574
            if (ipv4_piece > 255) [[unlikely]] {
15186
202
              return is_valid = false;
15187
202
            }
15188
574
          }
15189
1.22k
        }
15190
4.03k
        address[static_cast<size_t>(piece_index)] = static_cast<uint16_t>(
15191
4.03k
            address[static_cast<size_t>(piece_index)] * 0x100 +
15192
4.03k
            static_cast<uint16_t>(ipv4_piece));
15193
4.03k
        ++numbers_seen;
15194
4.03k
        if (numbers_seen == 2 || numbers_seen == 4) {
15195
1.29k
          ++piece_index;
15196
1.29k
        }
15197
4.03k
      }
15198
527
      if (numbers_seen != 4) [[unlikely]] {
15199
372
        return is_valid = false;
15200
372
      }
15201
155
      break;
15202
527
    }
15203
15204
13.1k
    if (length == 0) [[unlikely]] {
15205
710
      return is_valid = false;
15206
710
    }
15207
15208
12.4k
    if (pointer != end && *pointer == ':') {
15209
8.92k
      ++pointer;
15210
8.92k
      if (pointer == end) [[unlikely]] {
15211
205
        return is_valid = false;
15212
205
      }
15213
8.92k
    } else if (pointer != end) [[unlikely]] {
15214
406
      return is_valid = false;
15215
406
    }
15216
15217
11.8k
    address[static_cast<size_t>(piece_index)] = value;
15218
11.8k
    ++piece_index;
15219
11.8k
  }
15220
15221
4.04k
  if (compress != -1) {
15222
3.03k
    const int right = piece_index - compress;
15223
3.03k
    if (right > 0) {
15224
2.27k
      const size_t dest = static_cast<size_t>(8 - right);
15225
2.27k
      const size_t src = static_cast<size_t>(compress);
15226
2.27k
      if (dest != src) {
15227
5.90k
        for (size_t i = static_cast<size_t>(right); i-- > 0;) {
15228
3.76k
          address[dest + i] = address[src + i];
15229
3.76k
          address[src + i] = 0;
15230
3.76k
        }
15231
2.13k
      }
15232
2.27k
    }
15233
3.03k
  } else if (piece_index != 8) [[unlikely]] {
15234
927
    return is_valid = false;
15235
927
  }
15236
15237
  // Serialize once; skip rewrite when hostname is already canonical.
15238
3.11k
  const std::string serialized = ada::serializers::ipv6(address);
15239
3.11k
  const std::string_view current = get_hostname();
15240
3.11k
  if (current.size() == serialized.size() &&
15241
3
      std::memcmp(current.data(), serialized.data(), serialized.size()) == 0) {
15242
0
    ada_log("parse_ipv6 in-place canonical match");
15243
3.11k
  } else {
15244
3.11k
    update_base_hostname(serialized);
15245
3.11k
  }
15246
3.11k
  ada_log("parse_ipv6 ", get_hostname());
15247
3.11k
  ADA_ASSERT_TRUE(validate());
15248
3.11k
  host_type = IPV6;
15249
3.11k
  return true;
15250
4.04k
}
15251
15252
292
bool url_aggregator::parse_opaque_host(std::string_view input) {
15253
292
  ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
15254
292
  ADA_ASSERT_TRUE(validate());
15255
292
  ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer));
15256
292
  if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) {
15257
24
    return is_valid = false;
15258
24
  }
15259
15260
  // Return the result of running UTF-8 percent-encode on input using the C0
15261
  // control percent-encode set.
15262
268
  size_t idx = ada::unicode::percent_encode_index(
15263
268
      input, character_sets::C0_CONTROL_PERCENT_ENCODE);
15264
268
  if (idx == input.size()) {
15265
105
    update_base_hostname(input);
15266
163
  } else {
15267
    // We only create a temporary string if we need to.
15268
163
    update_base_hostname(ada::unicode::percent_encode(
15269
163
        input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx));
15270
163
  }
15271
268
  ADA_ASSERT_TRUE(validate());
15272
268
  return true;
15273
292
}
15274
15275
0
[[nodiscard]] std::string url_aggregator::to_diagram() const {
15276
0
  if (!is_valid) {
15277
0
    return "invalid";
15278
0
  }
15279
0
  std::string answer;
15280
0
  answer.append(buffer);
15281
0
  answer.append(" [");
15282
0
  answer.append(std::to_string(buffer.size()));
15283
0
  answer.append(" bytes]");
15284
0
  answer.append("\n");
15285
  // first line
15286
0
  std::string line1;
15287
0
  line1.resize(buffer.size(), ' ');
15288
0
  if (components.hash_start != url_components::omitted) {
15289
0
    line1[components.hash_start] = '|';
15290
0
  }
15291
0
  if (components.search_start != url_components::omitted) {
15292
0
    line1[components.search_start] = '|';
15293
0
  }
15294
0
  if (components.pathname_start != buffer.size()) {
15295
0
    line1[components.pathname_start] = '|';
15296
0
  }
15297
0
  if (components.host_end != buffer.size()) {
15298
0
    line1[components.host_end] = '|';
15299
0
  }
15300
0
  if (components.host_start != buffer.size()) {
15301
0
    line1[components.host_start] = '|';
15302
0
  }
15303
0
  if (components.username_end != buffer.size()) {
15304
0
    line1[components.username_end] = '|';
15305
0
  }
15306
0
  if (components.protocol_end != buffer.size()) {
15307
0
    line1[components.protocol_end] = '|';
15308
0
  }
15309
0
  answer.append(line1);
15310
0
  answer.append("\n");
15311
15312
0
  std::string line2 = line1;
15313
0
  if (components.hash_start != url_components::omitted) {
15314
0
    line2[components.hash_start] = '`';
15315
0
    line1[components.hash_start] = ' ';
15316
15317
0
    for (size_t i = components.hash_start + 1; i < line2.size(); i++) {
15318
0
      line2[i] = '-';
15319
0
    }
15320
0
    line2.append(" hash_start");
15321
0
    answer.append(line2);
15322
0
    answer.append("\n");
15323
0
  }
15324
15325
0
  std::string line3 = line1;
15326
0
  if (components.search_start != url_components::omitted) {
15327
0
    line3[components.search_start] = '`';
15328
0
    line1[components.search_start] = ' ';
15329
15330
0
    for (size_t i = components.search_start + 1; i < line3.size(); i++) {
15331
0
      line3[i] = '-';
15332
0
    }
15333
0
    line3.append(" search_start ");
15334
0
    line3.append(std::to_string(components.search_start));
15335
0
    answer.append(line3);
15336
0
    answer.append("\n");
15337
0
  }
15338
15339
0
  std::string line4 = line1;
15340
0
  if (components.pathname_start != buffer.size()) {
15341
0
    line4[components.pathname_start] = '`';
15342
0
    line1[components.pathname_start] = ' ';
15343
0
    for (size_t i = components.pathname_start + 1; i < line4.size(); i++) {
15344
0
      line4[i] = '-';
15345
0
    }
15346
0
    line4.append(" pathname_start ");
15347
0
    line4.append(std::to_string(components.pathname_start));
15348
0
    answer.append(line4);
15349
0
    answer.append("\n");
15350
0
  }
15351
15352
0
  std::string line5 = line1;
15353
0
  if (components.host_end != buffer.size()) {
15354
0
    line5[components.host_end] = '`';
15355
0
    line1[components.host_end] = ' ';
15356
15357
0
    for (size_t i = components.host_end + 1; i < line5.size(); i++) {
15358
0
      line5[i] = '-';
15359
0
    }
15360
0
    line5.append(" host_end ");
15361
0
    line5.append(std::to_string(components.host_end));
15362
0
    answer.append(line5);
15363
0
    answer.append("\n");
15364
0
  }
15365
15366
0
  std::string line6 = line1;
15367
0
  if (components.host_start != buffer.size()) {
15368
0
    line6[components.host_start] = '`';
15369
0
    line1[components.host_start] = ' ';
15370
15371
0
    for (size_t i = components.host_start + 1; i < line6.size(); i++) {
15372
0
      line6[i] = '-';
15373
0
    }
15374
0
    line6.append(" host_start ");
15375
0
    line6.append(std::to_string(components.host_start));
15376
0
    answer.append(line6);
15377
0
    answer.append("\n");
15378
0
  }
15379
15380
0
  std::string line7 = line1;
15381
0
  if (components.username_end != buffer.size()) {
15382
0
    line7[components.username_end] = '`';
15383
0
    line1[components.username_end] = ' ';
15384
15385
0
    for (size_t i = components.username_end + 1; i < line7.size(); i++) {
15386
0
      line7[i] = '-';
15387
0
    }
15388
0
    line7.append(" username_end ");
15389
0
    line7.append(std::to_string(components.username_end));
15390
0
    answer.append(line7);
15391
0
    answer.append("\n");
15392
0
  }
15393
15394
0
  std::string line8 = line1;
15395
0
  if (components.protocol_end != buffer.size()) {
15396
0
    line8[components.protocol_end] = '`';
15397
0
    line1[components.protocol_end] = ' ';
15398
15399
0
    for (size_t i = components.protocol_end + 1; i < line8.size(); i++) {
15400
0
      line8[i] = '-';
15401
0
    }
15402
0
    line8.append(" protocol_end ");
15403
0
    line8.append(std::to_string(components.protocol_end));
15404
0
    answer.append(line8);
15405
0
    answer.append("\n");
15406
0
  }
15407
15408
0
  if (components.hash_start == url_components::omitted) {
15409
0
    answer.append("note: hash omitted\n");
15410
0
  }
15411
0
  if (components.search_start == url_components::omitted) {
15412
0
    answer.append("note: search omitted\n");
15413
0
  }
15414
0
  if (components.protocol_end > buffer.size()) {
15415
0
    answer.append("warning: protocol_end overflows\n");
15416
0
  }
15417
0
  if (components.username_end > buffer.size()) {
15418
0
    answer.append("warning: username_end overflows\n");
15419
0
  }
15420
0
  if (components.host_start > buffer.size()) {
15421
0
    answer.append("warning: host_start overflows\n");
15422
0
  }
15423
0
  if (components.host_end > buffer.size()) {
15424
0
    answer.append("warning: host_end overflows\n");
15425
0
  }
15426
0
  if (components.pathname_start > buffer.size()) {
15427
0
    answer.append("warning: pathname_start overflows\n");
15428
0
  }
15429
0
  return answer;
15430
0
}
15431
15432
0
void url_aggregator::delete_dash_dot() {
15433
0
  ada_log("url_aggregator::delete_dash_dot");
15434
0
  ADA_ASSERT_TRUE(validate());
15435
0
  ADA_ASSERT_TRUE(has_dash_dot());
15436
0
  buffer.erase(components.host_end, 2);
15437
0
  components.pathname_start -= 2;
15438
0
  if (components.search_start != url_components::omitted) {
15439
0
    components.search_start -= 2;
15440
0
  }
15441
0
  if (components.hash_start != url_components::omitted) {
15442
0
    components.hash_start -= 2;
15443
0
  }
15444
0
  ADA_ASSERT_TRUE(validate());
15445
0
  ADA_ASSERT_TRUE(!has_dash_dot());
15446
0
}
15447
15448
437k
inline void url_aggregator::consume_prepared_path(std::string_view input) {
15449
437k
  ada_log("url_aggregator::consume_prepared_path ", input);
15450
  /***
15451
   * This is largely duplicated code from helpers::parse_prepared_path, which is
15452
   * unfortunate. This particular function is nearly identical, except that it
15453
   * is a method on url_aggregator. The idea is that the trivial path (which is
15454
   * very common) merely appends to the buffer. This is the same trivial path as
15455
   * with helpers::parse_prepared_path, except that we have the additional check
15456
   * for is_at_path(). Otherwise, we grab a copy of the current path and we
15457
   * modify it, and then insert it back into the buffer.
15458
   */
15459
437k
  uint8_t accumulator = checkers::path_signature(input);
15460
  // Let us first detect a trivial case.
15461
  // If it is special, we check that we have no dot, no %,  no \ and no
15462
  // character needing percent encoding. Otherwise, we check that we have no %,
15463
  // no dot, and no character needing percent encoding.
15464
437k
  constexpr uint8_t need_encoding = 1;
15465
437k
  constexpr uint8_t backslash_char = 2;
15466
437k
  constexpr uint8_t dot_char = 4;
15467
437k
  constexpr uint8_t percent_char = 8;
15468
437k
  bool special = type != ada::scheme::NOT_SPECIAL;
15469
437k
  bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
15470
0
                                      checkers::is_windows_drive_letter(input));
15471
437k
  bool trivial_path =
15472
437k
      (special ? (accumulator == 0)
15473
437k
               : ((accumulator & (need_encoding | dot_char | percent_char)) ==
15474
24.2k
                  0)) &&
15475
316k
      (!may_need_slow_file_handling);
15476
437k
  if (accumulator == dot_char && !may_need_slow_file_handling) {
15477
    // '4' means that we have at least one dot, but nothing that requires
15478
    // percent encoding or decoding. The only part that is not trivial is
15479
    // that we may have single dots and double dots path segments.
15480
    // If we have such segments, then we either have a path that begins
15481
    // with '.' (easy to check), or we have the sequence './'.
15482
    // Note: input cannot be empty, it must at least contain one character ('.')
15483
    // Note: we know that '\' is not present.
15484
33.0k
    if (input[0] != '.') {
15485
24.6k
      size_t slashdot = 0;
15486
24.6k
      bool dot_is_file = true;
15487
53.1k
      for (;;) {
15488
53.1k
        slashdot = input.find("/.", slashdot);
15489
53.1k
        if (slashdot == std::string_view::npos) {  // common case
15490
24.6k
          break;
15491
28.5k
        } else {  // uncommon
15492
          // only three cases matter: /./, /.. or a final /
15493
28.5k
          slashdot += 2;
15494
28.5k
          dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' ||
15495
16.1k
                           input[slashdot] == '/');
15496
28.5k
        }
15497
53.1k
      }
15498
24.6k
      trivial_path = dot_is_file;
15499
24.6k
    }
15500
33.0k
  }
15501
437k
  if (trivial_path && is_at_path()) {
15502
326k
    ada_log("parse_path trivial");
15503
326k
    buffer += '/';
15504
326k
    buffer += input;
15505
326k
    return;
15506
326k
  }
15507
110k
  std::string path = std::string(get_pathname());
15508
  // We are going to need to look a bit at the path, but let us see if we can
15509
  // ignore percent encoding *and* backslashes *and* percent characters.
15510
  // Except for the trivial case, this is likely to capture 99% of paths out
15511
  // there.
15512
110k
  bool fast_path =
15513
110k
      (special &&
15514
110k
       (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
15515
22.3k
      (type != ada::scheme::type::FILE);
15516
110k
  if (fast_path) {
15517
22.3k
    ada_log("parse_prepared_path fast");
15518
    // Here we don't need to worry about \ or percent encoding.
15519
    // We also do not have a file protocol. We might have dots, however,
15520
    // but dots must as appear as '.', and they cannot be encoded because
15521
    // the symbol '%' is not present.
15522
22.3k
    size_t previous_location = 0;  // We start at 0.
15523
125k
    do {
15524
125k
      size_t new_location = input.find('/', previous_location);
15525
      // std::string_view path_view = input;
15526
      //  We process the last segment separately:
15527
125k
      if (new_location == std::string_view::npos) {
15528
22.3k
        std::string_view path_view = input.substr(previous_location);
15529
22.3k
        if (path_view == "..") {  // The path ends with ..
15530
          // e.g., if you receive ".." with an empty path, you go to "/".
15531
2.13k
          if (path.empty()) {
15532
656
            path = '/';
15533
656
            update_base_pathname(path);
15534
656
            return;
15535
656
          }
15536
          // Fast case where we have nothing to do:
15537
1.48k
          if (path.back() == '/') {
15538
605
            update_base_pathname(path);
15539
605
            return;
15540
605
          }
15541
          // If you have the path "/joe/myfriend",
15542
          // then you delete 'myfriend'.
15543
875
          path.resize(path.rfind('/') + 1);
15544
875
          update_base_pathname(path);
15545
875
          return;
15546
1.48k
        }
15547
20.2k
        path += '/';
15548
20.2k
        if (path_view != ".") {
15549
17.5k
          path.append(path_view);
15550
17.5k
        }
15551
20.2k
        update_base_pathname(path);
15552
20.2k
        return;
15553
103k
      } else {
15554
        // This is a non-final segment.
15555
103k
        std::string_view path_view =
15556
103k
            input.substr(previous_location, new_location - previous_location);
15557
103k
        previous_location = new_location + 1;
15558
103k
        if (path_view == "..") {
15559
11.5k
          size_t last_delimiter = path.rfind('/');
15560
11.5k
          if (last_delimiter != std::string::npos) {
15561
5.69k
            path.erase(last_delimiter);
15562
5.69k
          }
15563
91.5k
        } else if (path_view != ".") {
15564
77.3k
          path += '/';
15565
77.3k
          path.append(path_view);
15566
77.3k
        }
15567
103k
      }
15568
125k
    } while (true);
15569
88.0k
  } else {
15570
88.0k
    ada_log("parse_path slow");
15571
    // we have reached the general case
15572
88.0k
    bool needs_percent_encoding = (accumulator & 1);
15573
88.0k
    std::string path_buffer_tmp;
15574
379k
    do {
15575
379k
      size_t location = (special && (accumulator & 2))
15576
379k
                            ? input.find_first_of("/\\")
15577
379k
                            : input.find('/');
15578
379k
      std::string_view path_view = input;
15579
379k
      if (location != std::string_view::npos) {
15580
291k
        path_view.remove_suffix(path_view.size() - location);
15581
291k
        input.remove_prefix(location + 1);
15582
291k
      }
15583
      // path_buffer is either path_view or it might point at a percent encoded
15584
      // temporary string.
15585
379k
      std::string_view path_buffer =
15586
379k
          (needs_percent_encoding &&
15587
235k
           ada::unicode::percent_encode<false>(
15588
235k
               path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
15589
379k
              ? path_buffer_tmp
15590
379k
              : path_view;
15591
379k
      if (unicode::is_double_dot_path_segment(path_buffer)) {
15592
5.74k
        helpers::shorten_path(path, type);
15593
5.74k
        if (location == std::string_view::npos) {
15594
758
          path += '/';
15595
758
        }
15596
373k
      } else if (unicode::is_single_dot_path_segment(path_buffer) &&
15597
8.88k
                 (location == std::string_view::npos)) {
15598
930
        path += '/';
15599
930
      }
15600
      // Otherwise, if path_buffer is not a single-dot path segment, then:
15601
372k
      else if (!unicode::is_single_dot_path_segment(path_buffer)) {
15602
        // If url's scheme is "file", url's path is empty, and path_buffer is a
15603
        // Windows drive letter, then replace the second code point in
15604
        // path_buffer with U+003A (:).
15605
364k
        if (type == ada::scheme::type::FILE && path.empty() &&
15606
0
            checkers::is_windows_drive_letter(path_buffer)) {
15607
0
          path += '/';
15608
0
          path += path_buffer[0];
15609
0
          path += ':';
15610
0
          path_buffer.remove_prefix(2);
15611
0
          path.append(path_buffer);
15612
364k
        } else {
15613
          // Append path_buffer to url's path.
15614
364k
          path += '/';
15615
364k
          path.append(path_buffer);
15616
364k
        }
15617
364k
      }
15618
379k
      if (location == std::string_view::npos) {
15619
88.0k
        update_base_pathname(path);
15620
88.0k
        return;
15621
88.0k
      }
15622
379k
    } while (true);
15623
88.0k
  }
15624
110k
}
15625
}  // namespace ada
15626
/* end file src/url_aggregator.cpp */
15627
15628
#if ADA_INCLUDE_URL_PATTERN
15629
/* begin file src/url_pattern.cpp */
15630
#if ADA_INCLUDE_URL_PATTERN
15631
15632
15633
#include <algorithm>
15634
#include <optional>
15635
#include <string>
15636
#include <string_view>
15637
#include <utility>
15638
15639
namespace ada {
15640
15641
tl::expected<url_pattern_init, errors> url_pattern_init::process(
15642
    const url_pattern_init& init, url_pattern_init::process_type type,
15643
    std::optional<std::string_view> protocol,
15644
    std::optional<std::string_view> username,
15645
    std::optional<std::string_view> password,
15646
    std::optional<std::string_view> hostname,
15647
    std::optional<std::string_view> port,
15648
    std::optional<std::string_view> pathname,
15649
    std::optional<std::string_view> search,
15650
451k
    std::optional<std::string_view> hash) {
15651
  // Let result be the result of creating a new URLPatternInit.
15652
451k
  auto result = url_pattern_init{};
15653
15654
  // If protocol is not null, set result["protocol"] to protocol.
15655
451k
  if (protocol.has_value()) result.protocol = *protocol;
15656
15657
  // If username is not null, set result["username"] to username.
15658
451k
  if (username.has_value()) result.username = *username;
15659
15660
  // If password is not null, set result["password"] to password.
15661
451k
  if (password.has_value()) result.password = *password;
15662
15663
  // If hostname is not null, set result["hostname"] to hostname.
15664
451k
  if (hostname.has_value()) result.hostname = *hostname;
15665
15666
  // If port is not null, set result["port"] to port.
15667
451k
  if (port.has_value()) result.port = *port;
15668
15669
  // If pathname is not null, set result["pathname"] to pathname.
15670
451k
  if (pathname.has_value()) result.pathname = *pathname;
15671
15672
  // If search is not null, set result["search"] to search.
15673
451k
  if (search.has_value()) result.search = *search;
15674
15675
  // If hash is not null, set result["hash"] to hash.
15676
451k
  if (hash.has_value()) result.hash = *hash;
15677
15678
  // Let baseURL be null.
15679
451k
  std::optional<url_aggregator> base_url{};
15680
15681
  // If init["baseURL"] exists:
15682
451k
  if (init.base_url.has_value()) {
15683
    // Set baseURL to the result of parsing init["baseURL"].
15684
118k
    auto parsing_result = ada::parse<url_aggregator>(*init.base_url);
15685
    // If baseURL is failure, then throw a TypeError.
15686
118k
    if (!parsing_result) {
15687
57.4k
      return tl::unexpected(errors::type_error);
15688
57.4k
    }
15689
61.3k
    base_url = std::move(*parsing_result);
15690
15691
    // If init["protocol"] does not exist, then set result["protocol"] to the
15692
    // result of processing a base URL string given baseURL's scheme and type.
15693
61.3k
    if (!init.protocol.has_value()) {
15694
31.4k
      ADA_ASSERT_TRUE(base_url.has_value());
15695
31.4k
      std::string_view base_url_protocol = base_url->get_protocol();
15696
31.4k
      if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1);
15697
31.4k
      result.protocol =
15698
31.4k
          url_pattern_helpers::process_base_url_string(base_url_protocol, type);
15699
31.4k
    }
15700
15701
    // If type is not "pattern" and init contains none of "protocol",
15702
    // "hostname", "port" and "username", then set result["username"] to the
15703
    // result of processing a base URL string given baseURL's username and type.
15704
61.3k
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15705
0
        !init.port && !init.username) {
15706
0
      result.username = url_pattern_helpers::process_base_url_string(
15707
0
          base_url->get_username(), type);
15708
0
    }
15709
15710
    // TODO: Optimization opportunity: Merge this with the previous check.
15711
    // If type is not "pattern" and init contains none of "protocol",
15712
    // "hostname", "port", "username" and "password", then set
15713
    // result["password"] to the result of processing a base URL string given
15714
    // baseURL's password and type.
15715
61.3k
    if (type != process_type::pattern && !init.protocol && !init.hostname &&
15716
0
        !init.port && !init.username && !init.password) {
15717
0
      result.password = url_pattern_helpers::process_base_url_string(
15718
0
          base_url->get_password(), type);
15719
0
    }
15720
15721
    // If init contains neither "protocol" nor "hostname", then:
15722
61.3k
    if (!init.protocol && !init.hostname) {
15723
      // Let baseHost be baseURL's host.
15724
      // If baseHost is null, then set baseHost to the empty string.
15725
31.4k
      auto base_host = base_url->get_hostname();
15726
      // Set result["hostname"] to the result of processing a base URL string
15727
      // given baseHost and type.
15728
31.4k
      result.hostname =
15729
31.4k
          url_pattern_helpers::process_base_url_string(base_host, type);
15730
31.4k
    }
15731
15732
    // If init contains none of "protocol", "hostname", and "port", then:
15733
61.3k
    if (!init.protocol && !init.hostname && !init.port) {
15734
      // If baseURL's port is null, then set result["port"] to the empty string.
15735
      // Otherwise, set result["port"] to baseURL's port, serialized.
15736
31.4k
      result.port = base_url->get_port();
15737
31.4k
    }
15738
15739
    // If init contains none of "protocol", "hostname", "port", and "pathname",
15740
    // then set result["pathname"] to the result of processing a base URL string
15741
    // given the result of URL path serializing baseURL and type.
15742
61.3k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname) {
15743
0
      result.pathname = url_pattern_helpers::process_base_url_string(
15744
0
          base_url->get_pathname(), type);
15745
0
    }
15746
15747
    // If init contains none of "protocol", "hostname", "port", "pathname", and
15748
    // "search", then:
15749
61.3k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15750
0
        !init.search) {
15751
      // Let baseQuery be baseURL's query. get_search() carries the leading "?"
15752
      // delimiter, but the spec inherits the query itself, so drop it.
15753
0
      std::string_view base_query = base_url->get_search();
15754
0
      if (base_query.starts_with("?")) base_query.remove_prefix(1);
15755
      // Set result["search"] to the result of processing a base URL string
15756
      // given baseQuery and type.
15757
0
      result.search =
15758
0
          url_pattern_helpers::process_base_url_string(base_query, type);
15759
0
    }
15760
15761
    // If init contains none of "protocol", "hostname", "port", "pathname",
15762
    // "search", and "hash", then:
15763
61.3k
    if (!init.protocol && !init.hostname && !init.port && !init.pathname &&
15764
0
        !init.search && !init.hash) {
15765
      // Let baseFragment be baseURL's fragment. get_hash() carries the leading
15766
      // "#" delimiter, but the spec inherits the fragment itself, so drop it.
15767
0
      std::string_view base_fragment = base_url->get_hash();
15768
0
      if (base_fragment.starts_with("#")) base_fragment.remove_prefix(1);
15769
      // Set result["hash"] to the result of processing a base URL string given
15770
      // baseFragment and type.
15771
0
      result.hash =
15772
0
          url_pattern_helpers::process_base_url_string(base_fragment, type);
15773
0
    }
15774
61.3k
  }
15775
15776
  // If init["protocol"] exists, then set result["protocol"] to the result of
15777
  // process protocol for init given init["protocol"] and type.
15778
394k
  if (init.protocol) {
15779
75.8k
    auto process_result = process_protocol(*init.protocol, type);
15780
75.8k
    if (!process_result) {
15781
0
      return tl::unexpected(process_result.error());
15782
0
    }
15783
75.8k
    result.protocol = std::move(*process_result);
15784
75.8k
  }
15785
15786
  // If init["username"] exists, then set result["username"] to the result of
15787
  // process username for init given init["username"] and type.
15788
394k
  if (init.username.has_value()) {
15789
31.0k
    auto process_result = process_username(*init.username, type);
15790
31.0k
    if (!process_result) {
15791
0
      return tl::unexpected(process_result.error());
15792
0
    }
15793
31.0k
    result.username = std::move(*process_result);
15794
31.0k
  }
15795
15796
  // If init["password"] exists, then set result["password"] to the result of
15797
  // process password for init given init["password"] and type.
15798
394k
  if (init.password.has_value()) {
15799
30.4k
    auto process_result = process_password(*init.password, type);
15800
30.4k
    if (!process_result) {
15801
0
      return tl::unexpected(process_result.error());
15802
0
    }
15803
30.4k
    result.password = std::move(*process_result);
15804
30.4k
  }
15805
15806
  // If init["hostname"] exists, then set result["hostname"] to the result of
15807
  // process hostname for init given init["hostname"] and type.
15808
394k
  if (init.hostname.has_value()) {
15809
75.7k
    auto process_result = process_hostname(*init.hostname, type);
15810
75.7k
    if (!process_result) {
15811
0
      return tl::unexpected(process_result.error());
15812
0
    }
15813
75.7k
    result.hostname = std::move(*process_result);
15814
75.7k
  }
15815
15816
  // If init["port"] exists, then set result["port"] to the result of process
15817
  // port for init given init["port"], result["protocol"], and type.
15818
394k
  if (init.port) {
15819
75.8k
    auto process_result =
15820
75.8k
        process_port(*init.port, result.protocol.value_or("fake"), type);
15821
75.8k
    if (!process_result) {
15822
0
      return tl::unexpected(process_result.error());
15823
0
    }
15824
75.8k
    result.port = std::move(*process_result);
15825
75.8k
  }
15826
15827
  // If init["pathname"] exists:
15828
394k
  if (init.pathname.has_value()) {
15829
    // Set result["pathname"] to init["pathname"].
15830
365k
    result.pathname = init.pathname;
15831
15832
    // If the following are all true:
15833
    // - baseURL is not null;
15834
    // - baseURL has an opaque path; and
15835
    // - the result of running is an absolute pathname given result["pathname"]
15836
    // and type is false,
15837
365k
    if (base_url && !base_url->has_opaque_path &&
15838
61.3k
        !url_pattern_helpers::is_absolute_pathname(*result.pathname, type)) {
15839
      // Let baseURLPath be the result of running process a base URL string
15840
      // given the result of URL path serializing baseURL and type.
15841
      // TODO: Optimization opportunity: Avoid returning a string if no slash
15842
      // exist.
15843
0
      std::string base_url_path = url_pattern_helpers::process_base_url_string(
15844
0
          base_url->get_pathname(), type);
15845
15846
      // Let slash index be the index of the last U+002F (/) code point found in
15847
      // baseURLPath, interpreted as a sequence of code points, or null if there
15848
      // are no instances of the code point.
15849
0
      auto slash_index = base_url_path.find_last_of('/');
15850
15851
      // If slash index is not null:
15852
0
      if (slash_index != std::string::npos) {
15853
        // Let new pathname be the code point substring from 0 to slash index +
15854
        // 1 within baseURLPath.
15855
0
        base_url_path.resize(slash_index + 1);
15856
        // Append result["pathname"] to the end of new pathname.
15857
0
        ADA_ASSERT_TRUE(result.pathname.has_value());
15858
0
        base_url_path.append(std::move(*result.pathname));
15859
        // Set result["pathname"] to new pathname.
15860
0
        result.pathname = std::move(base_url_path);
15861
0
      }
15862
0
    }
15863
15864
    // Set result["pathname"] to the result of process pathname for init given
15865
    // result["pathname"], result["protocol"], and type.
15866
365k
    auto pathname_processing_result =
15867
365k
        process_pathname(*result.pathname, result.protocol.value_or(""), type);
15868
365k
    if (!pathname_processing_result) {
15869
602
      return tl::unexpected(pathname_processing_result.error());
15870
602
    }
15871
364k
    result.pathname = std::move(*pathname_processing_result);
15872
364k
  }
15873
15874
  // If init["search"] exists then set result["search"] to the result of process
15875
  // search for init given init["search"] and type.
15876
393k
  if (init.search) {
15877
30.9k
    auto process_result = process_search(*init.search, type);
15878
30.9k
    if (!process_result) {
15879
0
      return tl::unexpected(process_result.error());
15880
0
    }
15881
30.9k
    result.search = std::move(*process_result);
15882
30.9k
  }
15883
15884
  // If init["hash"] exists then set result["hash"] to the result of process
15885
  // hash for init given init["hash"] and type.
15886
393k
  if (init.hash) {
15887
31.0k
    auto process_result = process_hash(*init.hash, type);
15888
31.0k
    if (!process_result) {
15889
0
      return tl::unexpected(process_result.error());
15890
0
    }
15891
31.0k
    result.hash = std::move(*process_result);
15892
31.0k
  }
15893
  // Return result.
15894
393k
  return result;
15895
393k
}
15896
15897
tl::expected<std::string, errors> url_pattern_init::process_protocol(
15898
75.8k
    std::string_view value, process_type type) {
15899
75.8k
  ada_log("process_protocol=", value, " [", type, "]");
15900
  // Let strippedValue be the given value with a single trailing U+003A (:)
15901
  // removed, if any.
15902
75.8k
  if (value.ends_with(":")) {
15903
39
    value.remove_suffix(1);
15904
39
  }
15905
  // If type is "pattern" then return strippedValue.
15906
75.8k
  if (type == process_type::pattern) {
15907
75.8k
    return std::string(value);
15908
75.8k
  }
15909
  // Return the result of running canonicalize a protocol given strippedValue.
15910
0
  return url_pattern_helpers::canonicalize_protocol(value);
15911
75.8k
}
15912
15913
tl::expected<std::string, errors> url_pattern_init::process_username(
15914
31.0k
    std::string_view value, process_type type) {
15915
  // If type is "pattern" then return value.
15916
31.0k
  if (type == process_type::pattern) {
15917
31.0k
    return std::string(value);
15918
31.0k
  }
15919
  // Return the result of running canonicalize a username given value.
15920
0
  return url_pattern_helpers::canonicalize_username(value);
15921
31.0k
}
15922
15923
tl::expected<std::string, errors> url_pattern_init::process_password(
15924
30.4k
    std::string_view value, process_type type) {
15925
  // If type is "pattern" then return value.
15926
30.4k
  if (type == process_type::pattern) {
15927
30.4k
    return std::string(value);
15928
30.4k
  }
15929
  // Return the result of running canonicalize a password given value.
15930
0
  return url_pattern_helpers::canonicalize_password(value);
15931
30.4k
}
15932
15933
tl::expected<std::string, errors> url_pattern_init::process_hostname(
15934
75.7k
    std::string_view value, process_type type) {
15935
75.7k
  ada_log("process_hostname value=", value, " type=", type);
15936
  // If type is "pattern" then return value.
15937
75.7k
  if (type == process_type::pattern) {
15938
75.7k
    return std::string(value);
15939
75.7k
  }
15940
  // Return the result of running canonicalize a hostname given value.
15941
0
  return url_pattern_helpers::canonicalize_hostname(value);
15942
75.7k
}
15943
15944
tl::expected<std::string, errors> url_pattern_init::process_port(
15945
75.8k
    std::string_view port, std::string_view protocol, process_type type) {
15946
  // If type is "pattern" then return portValue.
15947
75.8k
  if (type == process_type::pattern) {
15948
75.8k
    return std::string(port);
15949
75.8k
  }
15950
  // Return the result of running canonicalize a port given portValue and
15951
  // protocolValue.
15952
0
  return url_pattern_helpers::canonicalize_port_with_protocol(port, protocol);
15953
75.8k
}
15954
15955
tl::expected<std::string, errors> url_pattern_init::process_pathname(
15956
365k
    std::string_view value, std::string_view protocol, process_type type) {
15957
  // If type is "pattern" then return pathnameValue.
15958
365k
  if (type == process_type::pattern) {
15959
107k
    return std::string(value);
15960
107k
  }
15961
15962
  // If protocolValue is a special scheme or the empty string, then return the
15963
  // result of running canonicalize a pathname given pathnameValue.
15964
258k
  if (protocol.empty() || scheme::is_special(protocol)) {
15965
258k
    return url_pattern_helpers::canonicalize_pathname(value);
15966
258k
  }
15967
15968
  // Return the result of running canonicalize an opaque pathname given
15969
  // pathnameValue.
15970
0
  return url_pattern_helpers::canonicalize_opaque_pathname(value);
15971
258k
}
15972
15973
tl::expected<std::string, errors> url_pattern_init::process_search(
15974
30.9k
    std::string_view value, process_type type) {
15975
  // Let strippedValue be the given value with a single leading U+003F (?)
15976
  // removed, if any.
15977
30.9k
  if (value.starts_with("?")) {
15978
14
    value.remove_prefix(1);
15979
14
  }
15980
  // We cannot assert that the value is no longer starting with a single
15981
  // question mark because technically it can start. The question is whether or
15982
  // not we should remove the first question mark. Ref:
15983
  // https://github.com/ada-url/ada/pull/992 The spec is not clear on this.
15984
15985
  // If type is "pattern" then return strippedValue.
15986
30.9k
  if (type == process_type::pattern) {
15987
30.9k
    return std::string(value);
15988
30.9k
  }
15989
  // Return the result of running canonicalize a search given strippedValue.
15990
0
  return url_pattern_helpers::canonicalize_search(value);
15991
30.9k
}
15992
15993
tl::expected<std::string, errors> url_pattern_init::process_hash(
15994
31.0k
    std::string_view value, process_type type) {
15995
  // Let strippedValue be the given value with a single leading U+0023 (#)
15996
  // removed, if any.
15997
31.0k
  if (value.starts_with("#")) {
15998
13
    value.remove_prefix(1);
15999
13
  }
16000
31.0k
  ADA_ASSERT_TRUE(!value.starts_with("#"));
16001
  // If type is "pattern" then return strippedValue.
16002
31.0k
  if (type == process_type::pattern) {
16003
31.0k
    return std::string(value);
16004
31.0k
  }
16005
  // Return the result of running canonicalize a hash given strippedValue.
16006
0
  return url_pattern_helpers::canonicalize_hash(value);
16007
31.0k
}
16008
16009
}  // namespace ada
16010
16011
#endif  // ADA_INCLUDE_URL_PATTERN
16012
/* end file src/url_pattern.cpp */
16013
/* begin file src/url_pattern_helpers.cpp */
16014
#if ADA_INCLUDE_URL_PATTERN
16015
16016
#include <algorithm>
16017
#include <array>
16018
#include <charconv>
16019
#include <cstddef>
16020
#include <cstdint>
16021
#include <optional>
16022
#include <ranges>
16023
#include <string>
16024
#include <string_view>
16025
#include <system_error>
16026
#include <tuple>
16027
#include <utility>
16028
#include <vector>
16029
16030
16031
namespace ada::url_pattern_helpers {
16032
16033
std::tuple<std::string, std::vector<std::string>>
16034
generate_regular_expression_and_name_list(
16035
    const std::vector<url_pattern_part>& part_list,
16036
52.0k
    url_pattern_compile_component_options options) {
16037
  // Let result be "^"
16038
52.0k
  std::string result = "^";
16039
  // Reserve capacity to reduce reallocations
16040
52.0k
  result.reserve(part_list.size() * 16);
16041
16042
  // Let name list be a new list
16043
52.0k
  std::vector<std::string> name_list{};
16044
52.0k
  name_list.reserve(part_list.size());
16045
16046
  // Pre-generate segment wildcard regexp if needed (avoids repeated generation)
16047
52.0k
  std::string segment_wildcard_regexp;
16048
16049
  // For each part of part list:
16050
66.1k
  for (const url_pattern_part& part : part_list) {
16051
    // If part's type is "fixed-text":
16052
66.1k
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
16053
      // If part's modifier is "none"
16054
6.95k
      if (part.modifier == url_pattern_part_modifier::none) {
16055
6.59k
        result.append(escape_regexp_string(part.value));
16056
6.59k
      } else {
16057
        // (?:<fixed text>)<modifier>
16058
362
        result.append("(?:");
16059
362
        result.append(escape_regexp_string(part.value));
16060
362
        result.push_back(')');
16061
362
        result.append(convert_modifier_to_string(part.modifier));
16062
362
      }
16063
6.95k
      continue;
16064
6.95k
    }
16065
16066
    // Assert: part's name is not the empty string
16067
59.2k
    ADA_ASSERT_TRUE(!part.name.empty());
16068
59.2k
    name_list.push_back(part.name);
16069
16070
    // Use string_view to avoid copies where possible
16071
59.2k
    std::string_view regexp_value = part.value;
16072
16073
59.2k
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) {
16074
      // Lazy generate segment wildcard regexp
16075
2.26k
      if (segment_wildcard_regexp.empty()) {
16076
1.60k
        segment_wildcard_regexp = generate_segment_wildcard_regexp(options);
16077
1.60k
      }
16078
2.26k
      regexp_value = segment_wildcard_regexp;
16079
56.9k
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
16080
54.5k
      regexp_value = ".*";
16081
54.5k
    }
16082
16083
    // If part's prefix is the empty string and part's suffix is the empty
16084
    // string
16085
59.2k
    if (part.prefix.empty() && part.suffix.empty()) {
16086
      // If part's modifier is "none" or "optional"
16087
11.4k
      if (part.modifier == url_pattern_part_modifier::none ||
16088
9.19k
          part.modifier == url_pattern_part_modifier::optional) {
16089
        // (<regexp value>)<modifier>
16090
9.19k
        result.push_back('(');
16091
9.19k
        result.append(regexp_value);
16092
9.19k
        result.push_back(')');
16093
9.19k
        result.append(convert_modifier_to_string(part.modifier));
16094
9.19k
      } else {
16095
        // ((?:<regexp value>)<modifier>)
16096
2.30k
        result.append("((?:");
16097
2.30k
        result.append(regexp_value);
16098
2.30k
        result.push_back(')');
16099
2.30k
        result.append(convert_modifier_to_string(part.modifier));
16100
2.30k
        result.push_back(')');
16101
2.30k
      }
16102
11.4k
      continue;
16103
11.4k
    }
16104
16105
    // If part's modifier is "none" or "optional"
16106
47.7k
    if (part.modifier == url_pattern_part_modifier::none ||
16107
46.0k
        part.modifier == url_pattern_part_modifier::optional) {
16108
      // (?:<prefix>(<regexp value>)<suffix>)<modifier>
16109
46.0k
      result.append("(?:");
16110
46.0k
      result.append(escape_regexp_string(part.prefix));
16111
46.0k
      result.push_back('(');
16112
46.0k
      result.append(regexp_value);
16113
46.0k
      result.push_back(')');
16114
46.0k
      result.append(escape_regexp_string(part.suffix));
16115
46.0k
      result.push_back(')');
16116
46.0k
      result.append(convert_modifier_to_string(part.modifier));
16117
46.0k
      continue;
16118
46.0k
    }
16119
16120
    // Assert: part's modifier is "zero-or-more" or "one-or-more"
16121
1.61k
    ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more ||
16122
1.61k
                    part.modifier == url_pattern_part_modifier::one_or_more);
16123
16124
    // Assert: part's prefix is not the empty string or part's suffix is not the
16125
    // empty string
16126
1.61k
    ADA_ASSERT_TRUE(!part.prefix.empty() || !part.suffix.empty());
16127
16128
    // (?:<prefix>((?:<regexp value>)(?:<suffix><prefix>(?:<regexp
16129
    // value>))*)<suffix>)?
16130
    // Append "(?:" to the end of result.
16131
1.61k
    result.append("(?:");
16132
    // Append the result of running escape a regexp string given part's prefix
16133
    // to the end of result.
16134
1.61k
    result.append(escape_regexp_string(part.prefix));
16135
    // Append "((?:" to the end of result.
16136
1.61k
    result.append("((?:");
16137
    // Append regexp value to the end of result.
16138
1.61k
    result.append(regexp_value);
16139
    // Append ")(?:" to the end of result.
16140
1.61k
    result.append(")(?:");
16141
    // Append the result of running escape a regexp string given part's suffix
16142
    // to the end of result.
16143
1.61k
    result.append(escape_regexp_string(part.suffix));
16144
    // Append the result of running escape a regexp string given part's prefix
16145
    // to the end of result.
16146
1.61k
    result.append(escape_regexp_string(part.prefix));
16147
    // Append "(?:" to the end of result.
16148
1.61k
    result.append("(?:");
16149
    // Append regexp value to the end of result.
16150
1.61k
    result.append(regexp_value);
16151
    // Append "))*)" to the end of result.
16152
1.61k
    result.append("))*)");
16153
    // Append the result of running escape a regexp string given part's suffix
16154
    // to the end of result.
16155
1.61k
    result.append(escape_regexp_string(part.suffix));
16156
    // Append ")" to the end of result.
16157
1.61k
    result.append(")");
16158
16159
    // If part's modifier is "zero-or-more" then append "?" to the end of result
16160
1.61k
    if (part.modifier == url_pattern_part_modifier::zero_or_more) {
16161
1.11k
      result += "?";
16162
1.11k
    }
16163
1.61k
  }
16164
16165
  // Append "$" to the end of result
16166
52.0k
  result += "$";
16167
16168
  // Return (result, name list)
16169
52.0k
  return {std::move(result), std::move(name_list)};
16170
52.0k
}
16171
16172
133k
bool is_ipv6_address(std::string_view input) noexcept {
16173
  // If input's code point length is less than 2, then return false.
16174
133k
  if (input.size() < 2) return false;
16175
16176
  // Let input code points be input interpreted as a list of code points.
16177
  // If input code points[0] is U+005B ([), then return true.
16178
78.8k
  if (input.front() == '[') return true;
16179
  // If input code points[0] is U+007B ({) and input code points[1] is U+005B
16180
  // ([), then return true.
16181
78.7k
  if (input.starts_with("{[")) return true;
16182
  // If input code points[0] is U+005C (\) and input code points[1] is U+005B
16183
  // ([), then return true.
16184
78.7k
  return input.starts_with("\\[");
16185
78.7k
}
16186
16187
std::string_view convert_modifier_to_string(
16188
648k
    url_pattern_part_modifier modifier) {
16189
648k
  switch (modifier) {
16190
      // If modifier is "zero-or-more", then return "*".
16191
5.70k
    case url_pattern_part_modifier::zero_or_more:
16192
5.70k
      return "*";
16193
    // If modifier is "optional", then return "?".
16194
1.05k
    case url_pattern_part_modifier::optional:
16195
1.05k
      return "?";
16196
    // If modifier is "one-or-more", then return "+".
16197
1.09k
    case url_pattern_part_modifier::one_or_more:
16198
1.09k
      return "+";
16199
    // Return the empty string.
16200
640k
    default:
16201
640k
      return "";
16202
648k
  }
16203
648k
}
16204
16205
std::string generate_segment_wildcard_regexp(
16206
1.10M
    url_pattern_compile_component_options options) {
16207
  // Let result be "[^".
16208
1.10M
  std::string result = "[^";
16209
  // Append the result of running escape a regexp string given options's
16210
  // delimiter code point to the end of result.
16211
1.10M
  result.append(escape_regexp_string(options.get_delimiter()));
16212
  // Append "]+?" to the end of result.
16213
1.10M
  result.append("]+?");
16214
  // Return result.
16215
1.10M
  ada_log("generate_segment_wildcard_regexp result: ", result);
16216
1.10M
  return result;
16217
1.10M
}
16218
16219
namespace {
16220
// Unified lookup table for URL pattern character classification
16221
// Bit flags for different character types
16222
constexpr uint8_t CHAR_SCHEME = 1;  // valid in scheme (a-z, A-Z, 0-9, +, -, .)
16223
constexpr uint8_t CHAR_UPPER = 2;   // uppercase letter (needs lowercasing)
16224
constexpr uint8_t CHAR_SIMPLE_HOSTNAME = 4;  // simple hostname (a-z, 0-9, -, .)
16225
constexpr uint8_t CHAR_SIMPLE_PATHNAME =
16226
    8;  // simple pathname (a-z, A-Z, 0-9, /, -, _, ~)
16227
16228
constexpr std::array<uint8_t, 256> char_class_table = []() consteval {
16229
  std::array<uint8_t, 256> table{};
16230
  for (int c = 'a'; c <= 'z'; c++)
16231
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16232
  for (int c = 'A'; c <= 'Z'; c++)
16233
    table[c] = CHAR_SCHEME | CHAR_UPPER | CHAR_SIMPLE_PATHNAME;
16234
  for (int c = '0'; c <= '9'; c++)
16235
    table[c] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16236
  table['+'] = CHAR_SCHEME;
16237
  table['-'] = CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME | CHAR_SIMPLE_PATHNAME;
16238
  table['.'] =
16239
      CHAR_SCHEME | CHAR_SIMPLE_HOSTNAME;  // not pathname (needs normalization)
16240
  table['/'] = CHAR_SIMPLE_PATHNAME;
16241
  table['_'] = CHAR_SIMPLE_PATHNAME;
16242
  table['~'] = CHAR_SIMPLE_PATHNAME;
16243
  return table;
16244
}();
16245
}  // namespace
16246
16247
tl::expected<std::string, errors> canonicalize_protocol(
16248
191k
    std::string_view input) {
16249
191k
  ada_log("canonicalize_protocol called with input=", input);
16250
191k
  if (input.empty()) [[unlikely]] {
16251
66.6k
    return "";
16252
66.6k
  }
16253
16254
124k
  if (input.ends_with(":")) {
16255
16
    input.remove_suffix(1);
16256
16
  }
16257
16258
  // Fast path: special schemes are already canonical
16259
124k
  if (scheme::is_special(input)) {
16260
121k
    return std::string(input);
16261
121k
  }
16262
16263
  // Fast path: validate scheme chars and check for uppercase
16264
  // First char must be alpha (not +, -, ., or digit)
16265
3.25k
  uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])];
16266
3.25k
  if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' ||
16267
2.24k
      input[0] == '.' || unicode::is_ascii_digit(input[0])) {
16268
2.24k
    return tl::unexpected(errors::type_error);
16269
2.24k
  }
16270
16271
1.01k
  uint8_t needs_lowercase = first_flags & CHAR_UPPER;
16272
1.53k
  for (size_t i = 1; i < input.size(); i++) {
16273
539
    uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])];
16274
539
    if (!(flags & CHAR_SCHEME)) {
16275
23
      return tl::unexpected(errors::type_error);
16276
23
    }
16277
516
    needs_lowercase |= flags & CHAR_UPPER;
16278
516
  }
16279
16280
994
  if (needs_lowercase == 0) {
16281
541
    return std::string(input);
16282
541
  }
16283
16284
453
  std::string result(input);
16285
453
  unicode::to_lower_ascii(result.data(), result.size());
16286
453
  return result;
16287
994
}
16288
16289
tl::expected<std::string, errors> canonicalize_username(
16290
213k
    std::string_view input) {
16291
  // If value is the empty string, return value.
16292
213k
  if (input.empty()) [[unlikely]] {
16293
212k
    return "";
16294
212k
  }
16295
  // Percent-encode the input using the userinfo percent-encode set.
16296
1.26k
  size_t idx = ada::unicode::percent_encode_index(
16297
1.26k
      input, character_sets::USERINFO_PERCENT_ENCODE);
16298
1.26k
  if (idx == input.size()) {
16299
    // No encoding needed, return input as-is
16300
664
    return std::string(input);
16301
664
  }
16302
  // Percent-encode from the first character that needs encoding
16303
603
  return ada::unicode::percent_encode(
16304
603
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16305
1.26k
}
16306
16307
tl::expected<std::string, errors> canonicalize_password(
16308
213k
    std::string_view input) {
16309
  // If value is the empty string, return value.
16310
213k
  if (input.empty()) [[unlikely]] {
16311
212k
    return "";
16312
212k
  }
16313
  // Percent-encode the input using the userinfo percent-encode set.
16314
835
  size_t idx = ada::unicode::percent_encode_index(
16315
835
      input, character_sets::USERINFO_PERCENT_ENCODE);
16316
835
  if (idx == input.size()) {
16317
    // No encoding needed, return input as-is
16318
442
    return std::string(input);
16319
442
  }
16320
  // Percent-encode from the first character that needs encoding
16321
393
  return ada::unicode::percent_encode(
16322
393
      input, character_sets::USERINFO_PERCENT_ENCODE, idx);
16323
835
}
16324
16325
tl::expected<std::string, errors> canonicalize_hostname(
16326
144k
    std::string_view input) {
16327
144k
  ada_log("canonicalize_hostname input=", input);
16328
144k
  if (input.empty()) [[unlikely]] {
16329
64.2k
    return "";
16330
64.2k
  }
16331
16332
  // Fast path: simple hostnames (lowercase ASCII, digits, -, .) need no IDNA.
16333
  // The simple character set also covers IPv4-shaped hosts, which the slow
16334
  // path rewrites ("0" -> "0.0.0.0", "0x7f.1" -> "127.0.0.1"). Exclude those
16335
  // so the fast path can't return a non-canonical hostname.
16336
  //
16337
  // Pure-ASCII "xn--" labels are intentionally left on the fast path: with
16338
  // beStrict=false, domain-to-ASCII returns the lowercased ASCII input even
16339
  // when Unicode ToASCII would fail (e.g. invalid ACE "xn--a"). See
16340
  // https://url.spec.whatwg.org/#concept-domain-to-ascii
16341
80.6k
  bool needs_processing = false;
16342
852k
  for (char c : input) {
16343
852k
    needs_processing |=
16344
852k
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME);
16345
852k
  }
16346
80.6k
  if (!needs_processing && !checkers::is_ipv4(input)) {
16347
76.0k
    return std::string(input);
16348
76.0k
  }
16349
16350
  // Let dummyURL be a new URL record.
16351
  // Let parseResult be the result of running the basic URL parser given value
16352
  // with dummyURL as url and hostname state as state override.
16353
16354
  // IMPORTANT: The protocol needs to be a special protocol, otherwise the
16355
  // hostname will not be converted using IDNA.
16356
4.58k
  auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr);
16357
4.58k
  ADA_ASSERT_TRUE(url);
16358
  // if (!isValidHostnameInput(hostname)) return kj::none;
16359
4.58k
  if (!url->set_hostname(input)) {
16360
    // If parseResult is failure, then throw a TypeError.
16361
1.42k
    return tl::unexpected(errors::type_error);
16362
1.42k
  }
16363
  // Return dummyURL's host, serialized, or empty string if it is null.
16364
3.16k
  return std::string(url->get_hostname());
16365
4.58k
}
16366
16367
tl::expected<std::string, errors> canonicalize_ipv6_hostname(
16368
442
    std::string_view input) {
16369
442
  ada_log("canonicalize_ipv6_hostname input=", input);
16370
  // TODO: Optimization opportunity: Use lookup table to speed up checking
16371
1.21k
  if (std::ranges::any_of(input, [](char c) {
16372
1.21k
        return c != '[' && c != ']' && c != ':' &&
16373
492
               !unicode::is_ascii_hex_digit(c);
16374
1.21k
      })) {
16375
24
    return tl::unexpected(errors::type_error);
16376
24
  }
16377
  // Append the result of running ASCII lowercase given code point to the end of
16378
  // result.
16379
418
  auto hostname = std::string(input);
16380
418
  unicode::to_lower_ascii(hostname.data(), hostname.size());
16381
418
  return hostname;
16382
442
}
16383
16384
tl::expected<std::string, errors> canonicalize_port(
16385
58.2k
    std::string_view port_value) {
16386
  // If portValue is the empty string, return portValue.
16387
58.2k
  if (port_value.empty()) [[unlikely]] {
16388
57.3k
    return "";
16389
57.3k
  }
16390
16391
  // Remove ASCII tab or newline characters
16392
969
  std::string trimmed(port_value);
16393
969
  helpers::remove_ascii_tab_or_newline(trimmed);
16394
16395
969
  if (trimmed.empty()) {
16396
140
    return "";
16397
140
  }
16398
16399
  // Input should start with a digit character
16400
829
  if (!unicode::is_ascii_digit(trimmed.front())) {
16401
557
    return tl::unexpected(errors::type_error);
16402
557
  }
16403
16404
  // Find the first non-digit character
16405
272
  auto first_non_digit =
16406
272
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16407
272
  std::string_view digits_to_parse =
16408
272
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16409
16410
  // Here we have a range of ASCII digit characters identified by
16411
  // digits_to_parse. It is non-empty. The port state of the URL parser reads
16412
  // it as an integer, so leading zeros are part of the number: "0080" is 80
16413
  // and "065535" is 65535, not a six-digit overflow. Only the significant
16414
  // digits count toward the 5-digit maximum, matching the fast path in
16415
  // implementation.cpp.
16416
272
  size_t first_significant = digits_to_parse.find_first_not_of('0');
16417
272
  if (first_significant == std::string_view::npos) {
16418
    // The value is all zeros, i.e. port 0.
16419
54
    return "0";
16420
54
  }
16421
218
  digits_to_parse.remove_prefix(first_significant);
16422
  // We want to determine whether it is a valid port number (0-65535).
16423
  // Clearly, if the length is greater than 5, it is invalid.
16424
  // If the length is 5, we need to compare lexicographically to "65535".
16425
  // Otherwise it is valid.
16426
218
  if (digits_to_parse.size() == 5) {
16427
42
    if (digits_to_parse > "65535") {
16428
11
      return tl::unexpected(errors::type_error);
16429
11
    }
16430
176
  } else if (digits_to_parse.size() > 5) {
16431
0
    return tl::unexpected(errors::type_error);
16432
0
  }
16433
  // It is valid! Most times, we do not need to parse it into an integer.
16434
207
  return std::string(digits_to_parse);
16435
218
}
16436
16437
tl::expected<std::string, errors> canonicalize_port_with_protocol(
16438
0
    std::string_view port_value, std::string_view protocol) {
16439
  // If portValue is the empty string, return portValue.
16440
0
  if (port_value.empty()) [[unlikely]] {
16441
0
    return "";
16442
0
  }
16443
16444
  // Handle empty or trailing colon in protocol
16445
0
  if (protocol.empty()) {
16446
0
    protocol = "fake";
16447
0
  } else if (protocol.ends_with(":")) {
16448
0
    protocol.remove_suffix(1);
16449
0
  }
16450
16451
  // Remove ASCII tab or newline characters
16452
0
  std::string trimmed(port_value);
16453
0
  helpers::remove_ascii_tab_or_newline(trimmed);
16454
16455
0
  if (trimmed.empty()) {
16456
0
    return "";
16457
0
  }
16458
16459
  // Input should start with a digit character
16460
0
  if (!unicode::is_ascii_digit(trimmed.front())) {
16461
0
    return tl::unexpected(errors::type_error);
16462
0
  }
16463
16464
  // Find the first non-digit character
16465
0
  auto first_non_digit =
16466
0
      std::ranges::find_if_not(trimmed, unicode::is_ascii_digit);
16467
0
  std::string_view digits_to_parse =
16468
0
      std::string_view(trimmed.data(), first_non_digit - trimmed.begin());
16469
16470
  // Parse the port number
16471
0
  uint16_t parsed_port{};
16472
  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)
16473
0
  auto result = std::from_chars(digits_to_parse.data(),
16474
0
                                digits_to_parse.data() + digits_to_parse.size(),
16475
0
                                parsed_port);
16476
16477
0
  if (result.ec == std::errc::result_out_of_range) {
16478
0
    return tl::unexpected(errors::type_error);
16479
0
  }
16480
16481
0
  if (result.ec == std::errc()) {
16482
    // Check if this is the default port for the scheme
16483
0
    uint16_t default_port = scheme::get_special_port(protocol);
16484
16485
    // If it's the default port for a special scheme, return empty string
16486
0
    if (default_port != 0 && default_port == parsed_port) {
16487
0
      return "";
16488
0
    }
16489
16490
    // Successfully parsed, return as string
16491
0
    return std::to_string(parsed_port);
16492
0
  }
16493
16494
0
  return tl::unexpected(errors::type_error);
16495
0
}
16496
16497
tl::expected<std::string, errors> canonicalize_pathname(
16498
441k
    std::string_view input) {
16499
441k
  if (input.empty()) [[unlikely]] {
16500
104k
    return "";
16501
104k
  }
16502
16503
  // Fast path: simple pathnames (no . which needs normalization) can be
16504
  // returned as-is
16505
337k
  bool needs_processing = false;
16506
3.65M
  for (char c : input) {
16507
3.65M
    needs_processing |=
16508
3.65M
        !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME);
16509
3.65M
  }
16510
337k
  if (!needs_processing) {
16511
78.4k
    return std::string(input);
16512
78.4k
  }
16513
16514
  // Let leading slash be true if the first code point in value is U+002F (/)
16515
  // and otherwise false.
16516
259k
  const bool leading_slash = input.starts_with("/");
16517
  // Let modified value be "/-" if leading slash is false and otherwise the
16518
  // empty string.
16519
259k
  const auto modified_value =
16520
259k
      (leading_slash ? std::string() : std::string("/-")) + std::string(input);
16521
  // The spec runs the basic URL parser with the path in state override, where
16522
  // '?' and '#' are ordinary path code points (percent-encoded) and leading or
16523
  // trailing C0 control or space is kept. Building a full URL string and
16524
  // parsing it (no state override) instead let '?' and '#' start the
16525
  // query/fragment, so the pathname was silently truncated at the first literal
16526
  // '?' or '#'. set_pathname runs the parser in path state override, matching
16527
  // how canonicalize_hostname uses set_hostname.
16528
  // The spec's "create a dummy URL" is "https://dummy.invalid/": a special
16529
  // URL, so the path parser turns "\\" into "/" as it does in a special URL.
16530
  // A non-special dummy kept a literal backslash, so a pattern such as
16531
  // "/a\\b" never matched "https://h/a/b".
16532
259k
  auto url = ada::parse<url_aggregator>("https://dummy.invalid/", nullptr);
16533
259k
  ADA_ASSERT_TRUE(url);
16534
259k
  if (!url->set_pathname(modified_value)) {
16535
    // If parseResult is failure, then throw a TypeError.
16536
0
    return tl::unexpected(errors::type_error);
16537
0
  }
16538
259k
  const auto pathname = url->get_pathname();
16539
  // If leading slash is false, then set result to the code point substring
16540
  // from 2 to the end of the string within result.
16541
259k
  if (!leading_slash) {
16542
    // pathname should start with "/-" but path traversal (e.g. "../../")
16543
    // can reduce it to just "/" which is shorter than 2 characters.
16544
258k
    if (pathname.size() < 2) {
16545
618
      return tl::unexpected(errors::type_error);
16546
618
    }
16547
258k
    return std::string(pathname.substr(2));
16548
258k
  }
16549
520
  return std::string(pathname);
16550
259k
}
16551
16552
tl::expected<std::string, errors> canonicalize_opaque_pathname(
16553
28.2k
    std::string_view input) {
16554
  // If value is the empty string, return value.
16555
28.2k
  if (input.empty()) [[unlikely]] {
16556
2.62k
    return "";
16557
2.62k
  }
16558
  // Let dummyURL be a new URL record.
16559
  // Set dummyURL's path to the empty string.
16560
  // Let parseResult be the result of running URL parsing given value with
16561
  // dummyURL as url and opaque path state as state override.
16562
25.6k
  if (auto url =
16563
25.6k
          ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) {
16564
    // Return the result of URL path serializing dummyURL.
16565
25.4k
    return std::string(url->get_pathname());
16566
25.4k
  }
16567
  // If parseResult is failure, then throw a TypeError.
16568
245
  return tl::unexpected(errors::type_error);
16569
25.6k
}
16570
16571
207k
tl::expected<std::string, errors> canonicalize_search(std::string_view input) {
16572
  // If value is the empty string, return value.
16573
207k
  if (input.empty()) [[unlikely]] {
16574
206k
    return "";
16575
206k
  }
16576
  // A leading '?' is a valid query code point here: it is the caller (process a
16577
  // search) that removes a single delimiter, not this step, which mirrors the
16578
  // basic URL parser's query state.
16579
662
  std::string new_value(input);
16580
  // Remove ASCII tab or newline characters
16581
662
  helpers::remove_ascii_tab_or_newline(new_value);
16582
16583
662
  if (new_value.empty()) {
16584
137
    return "";
16585
137
  }
16586
16587
  // Percent-encode using QUERY_PERCENT_ENCODE (for non-special URLs)
16588
  // Note: "fake://dummy.test" is not a special URL, so we use
16589
  // QUERY_PERCENT_ENCODE
16590
525
  size_t idx = ada::unicode::percent_encode_index(
16591
525
      new_value, character_sets::QUERY_PERCENT_ENCODE);
16592
525
  if (idx == new_value.size()) {
16593
    // No encoding needed
16594
251
    return new_value;
16595
251
  }
16596
  // Percent-encode from the first character that needs encoding
16597
274
  return ada::unicode::percent_encode(
16598
274
      new_value, character_sets::QUERY_PERCENT_ENCODE, idx);
16599
525
}
16600
16601
206k
tl::expected<std::string, errors> canonicalize_hash(std::string_view input) {
16602
  // If value is the empty string, return value.
16603
206k
  if (input.empty()) [[unlikely]] {
16604
206k
    return "";
16605
206k
  }
16606
  // A leading '#' is a valid fragment code point here: it is the caller
16607
  // (process a hash) that removes a single delimiter, not this step, which
16608
  // mirrors the basic URL parser's fragment state.
16609
486
  std::string new_value(input);
16610
  // Remove ASCII tab or newline characters
16611
486
  helpers::remove_ascii_tab_or_newline(new_value);
16612
16613
486
  if (new_value.empty()) {
16614
119
    return "";
16615
119
  }
16616
16617
  // Percent-encode using FRAGMENT_PERCENT_ENCODE
16618
367
  size_t idx = ada::unicode::percent_encode_index(
16619
367
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE);
16620
367
  if (idx == new_value.size()) {
16621
    // No encoding needed
16622
192
    return new_value;
16623
192
  }
16624
  // Percent-encode from the first character that needs encoding
16625
175
  return ada::unicode::percent_encode(
16626
175
      new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx);
16627
367
}
16628
16629
tl::expected<std::vector<token>, errors> tokenize(std::string_view input,
16630
1.19M
                                                  token_policy policy) {
16631
1.19M
  ada_log("tokenize input: ", input);
16632
  // Let tokenizer be a new tokenizer.
16633
  // Set tokenizer's input to input.
16634
  // Set tokenizer's policy to policy.
16635
1.19M
  auto tokenizer = Tokenizer(input, policy);
16636
  // While tokenizer's index is less than tokenizer's input's code point length:
16637
4.48M
  while (tokenizer.index < tokenizer.input.size()) {
16638
    // Run seek and get the next code point given tokenizer and tokenizer's
16639
    // index.
16640
3.28M
    tokenizer.seek_and_get_next_code_point(tokenizer.index);
16641
16642
    // Malformed UTF-8 must not stall tokenization: report an invalid-char
16643
    // token (lenient) or fail fast (strict), while always making progress.
16644
3.28M
    if (tokenizer.had_invalid_code_point()) {
16645
0
      if (auto error = tokenizer.process_tokenizing_error(tokenizer.next_index,
16646
0
                                                          tokenizer.index)) {
16647
0
        return tl::unexpected(*error);
16648
0
      }
16649
0
      continue;
16650
0
    }
16651
16652
    // If tokenizer's code point is U+002A (*):
16653
3.28M
    if (tokenizer.code_point == '*') {
16654
      // Run add a token with default position and length given tokenizer and
16655
      // "asterisk".
16656
637k
      tokenizer.add_token_with_defaults(token_type::ASTERISK);
16657
637k
      ada_log("add ASTERISK token");
16658
      // Continue.
16659
637k
      continue;
16660
637k
    }
16661
16662
    // If tokenizer's code point is U+002B (+) or U+003F (?):
16663
2.65M
    if (tokenizer.code_point == '+' || tokenizer.code_point == '?') {
16664
      // Run add a token with default position and length given tokenizer and
16665
      // "other-modifier".
16666
4.81k
      tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER);
16667
      // Continue.
16668
4.81k
      continue;
16669
4.81k
    }
16670
16671
    // If tokenizer's code point is U+005C (\):
16672
2.64M
    if (tokenizer.code_point == '\\') {
16673
      // If tokenizer's index is equal to tokenizer's input's code point length
16674
      // - 1:
16675
4.65k
      if (tokenizer.index == tokenizer.input.size() - 1) {
16676
        // Run process a tokenizing error given tokenizer, tokenizer's next
16677
        // index, and tokenizer's index.
16678
744
        if (auto error = tokenizer.process_tokenizing_error(
16679
744
                tokenizer.next_index, tokenizer.index)) {
16680
702
          ada_log("process_tokenizing_error failed");
16681
702
          return tl::unexpected(*error);
16682
702
        }
16683
42
        continue;
16684
744
      }
16685
16686
      // Let escaped index be tokenizer's next index.
16687
3.90k
      auto escaped_index = tokenizer.next_index;
16688
      // Run get the next code point given tokenizer.
16689
3.90k
      tokenizer.get_next_code_point();
16690
3.90k
      if (tokenizer.had_invalid_code_point()) {
16691
0
        if (auto error = tokenizer.process_tokenizing_error(
16692
0
                tokenizer.next_index, escaped_index)) {
16693
0
          return tl::unexpected(*error);
16694
0
        }
16695
0
        continue;
16696
0
      }
16697
      // Run add a token with default length given tokenizer, "escaped-char",
16698
      // tokenizer's next index, and escaped index.
16699
3.90k
      tokenizer.add_token_with_default_length(
16700
3.90k
          token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index);
16701
3.90k
      ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index,
16702
3.90k
              " with escaped index ", escaped_index);
16703
      // Continue.
16704
3.90k
      continue;
16705
3.90k
    }
16706
16707
    // If tokenizer's code point is U+007B ({):
16708
2.64M
    if (tokenizer.code_point == '{') {
16709
      // Run add a token with default position and length given tokenizer and
16710
      // "open".
16711
4.84k
      tokenizer.add_token_with_defaults(token_type::OPEN);
16712
4.84k
      ada_log("add OPEN token");
16713
4.84k
      continue;
16714
4.84k
    }
16715
16716
    // If tokenizer's code point is U+007D (}):
16717
2.63M
    if (tokenizer.code_point == '}') {
16718
      // Run add a token with default position and length given tokenizer and
16719
      // "close".
16720
5.61k
      tokenizer.add_token_with_defaults(token_type::CLOSE);
16721
5.61k
      ada_log("add CLOSE token");
16722
5.61k
      continue;
16723
5.61k
    }
16724
16725
    // If tokenizer's code point is U+003A (:):
16726
2.63M
    if (tokenizer.code_point == ':') {
16727
      // Let name position be tokenizer's next index.
16728
52.7k
      auto name_position = tokenizer.next_index;
16729
      // Let name start be name position.
16730
52.7k
      auto name_start = name_position;
16731
52.7k
      bool invalid_name = false;
16732
      // While name position is less than tokenizer's input's code point length:
16733
62.1k
      while (name_position < tokenizer.input.size()) {
16734
        // Run seek and get the next code point given tokenizer and name
16735
        // position.
16736
60.3k
        tokenizer.seek_and_get_next_code_point(name_position);
16737
60.3k
        if (tokenizer.had_invalid_code_point()) {
16738
0
          if (auto error = tokenizer.process_tokenizing_error(
16739
0
                  tokenizer.next_index, name_position)) {
16740
0
            return tl::unexpected(*error);
16741
0
          }
16742
0
          invalid_name = true;
16743
0
          break;
16744
0
        }
16745
        // Let first code point be true if name position equals name start and
16746
        // false otherwise.
16747
60.3k
        bool first_code_point = name_position == name_start;
16748
        // Let valid code point be the result of running is a valid name code
16749
        // point given tokenizer's code point and first code point.
16750
60.3k
        auto valid_code_point =
16751
60.3k
            idna::valid_name_code_point(tokenizer.code_point, first_code_point);
16752
60.3k
        ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point),
16753
60.3k
                " first_code_point=", first_code_point,
16754
60.3k
                " valid_code_point=", valid_code_point);
16755
        // If valid code point is false break.
16756
60.3k
        if (!valid_code_point) break;
16757
        // Set name position to tokenizer's next index.
16758
9.31k
        name_position = tokenizer.next_index;
16759
9.31k
      }
16760
16761
52.7k
      if (invalid_name) {
16762
0
        continue;
16763
0
      }
16764
16765
      // If name position is less than or equal to name start:
16766
52.7k
      if (name_position <= name_start) {
16767
        // Run process a tokenizing error given tokenizer, name start, and
16768
        // tokenizer's index.
16769
48.2k
        if (auto error = tokenizer.process_tokenizing_error(name_start,
16770
48.2k
                                                            tokenizer.index)) {
16771
551
          ada_log("process_tokenizing_error failed");
16772
551
          return tl::unexpected(*error);
16773
551
        }
16774
        // Continue
16775
47.6k
        continue;
16776
48.2k
      }
16777
16778
      // Run add a token with default length given tokenizer, "name", name
16779
      // position, and name start.
16780
4.57k
      tokenizer.add_token_with_default_length(token_type::NAME, name_position,
16781
4.57k
                                              name_start);
16782
4.57k
      continue;
16783
52.7k
    }
16784
16785
    // If tokenizer's code point is U+0028 (():
16786
2.57M
    if (tokenizer.code_point == '(') {
16787
      // Let depth be 1.
16788
6.48k
      size_t depth = 1;
16789
      // Let regexp position be tokenizer's next index.
16790
6.48k
      auto regexp_position = tokenizer.next_index;
16791
      // Let regexp start be regexp position.
16792
6.48k
      auto regexp_start = regexp_position;
16793
      // Let error be false.
16794
6.48k
      bool error = false;
16795
16796
      // While regexp position is less than tokenizer's input's code point
16797
      // length:
16798
22.9k
      while (regexp_position < tokenizer.input.size()) {
16799
        // Run seek and get the next code point given tokenizer and regexp
16800
        // position.
16801
22.4k
        tokenizer.seek_and_get_next_code_point(regexp_position);
16802
22.4k
        if (tokenizer.had_invalid_code_point()) {
16803
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16804
0
                  tokenizer.next_index, regexp_position)) {
16805
0
            return tl::unexpected(*process_error);
16806
0
          }
16807
0
          error = true;
16808
0
          break;
16809
0
        }
16810
16811
        // TODO: Optimization opportunity: The next 2 if statements can be
16812
        // merged. If the result of running is ASCII given tokenizer's code
16813
        // point is false:
16814
22.4k
        if (!unicode::is_ascii(tokenizer.code_point)) {
16815
          // Run process a tokenizing error given tokenizer, regexp start, and
16816
          // tokenizer's index.
16817
0
          if (auto process_error = tokenizer.process_tokenizing_error(
16818
0
                  regexp_start, tokenizer.index)) {
16819
0
            return tl::unexpected(*process_error);
16820
0
          }
16821
          // Set error to true.
16822
0
          error = true;
16823
0
          break;
16824
0
        }
16825
16826
        // If regexp position equals regexp start and tokenizer's code point is
16827
        // U+003F (?):
16828
22.4k
        if (regexp_position == regexp_start && tokenizer.code_point == '?') {
16829
          // Run process a tokenizing error given tokenizer, regexp start, and
16830
          // tokenizer's index.
16831
479
          if (auto process_error = tokenizer.process_tokenizing_error(
16832
479
                  regexp_start, tokenizer.index)) {
16833
11
            return tl::unexpected(*process_error);
16834
11
          }
16835
          // Set error to true;
16836
468
          error = true;
16837
468
          break;
16838
479
        }
16839
16840
        // If tokenizer's code point is U+005C (\):
16841
21.9k
        if (tokenizer.code_point == '\\') {
16842
          // If regexp position equals tokenizer's input's code point length - 1
16843
2.10k
          if (regexp_position == tokenizer.input.size() - 1) {
16844
            // Run process a tokenizing error given tokenizer, regexp start, and
16845
            // tokenizer's index.
16846
31
            if (auto process_error = tokenizer.process_tokenizing_error(
16847
31
                    regexp_start, tokenizer.index)) {
16848
16
              return tl::unexpected(*process_error);
16849
16
            }
16850
            // Set error to true.
16851
15
            error = true;
16852
15
            break;
16853
31
          }
16854
          // Run get the next code point given tokenizer.
16855
2.07k
          auto escaped_index = tokenizer.next_index;
16856
2.07k
          tokenizer.get_next_code_point();
16857
2.07k
          if (tokenizer.had_invalid_code_point()) {
16858
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16859
0
                    tokenizer.next_index, escaped_index)) {
16860
0
              return tl::unexpected(*process_error);
16861
0
            }
16862
0
            error = true;
16863
0
            break;
16864
0
          }
16865
          // If the result of running is ASCII given tokenizer's code point is
16866
          // false:
16867
2.07k
          if (!unicode::is_ascii(tokenizer.code_point)) {
16868
            // Run process a tokenizing error given tokenizer, regexp start, and
16869
            // tokenizer's index.
16870
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16871
0
                    regexp_start, tokenizer.index);
16872
0
                process_error.has_value()) {
16873
0
              return tl::unexpected(*process_error);
16874
0
            }
16875
            // Set error to true.
16876
0
            error = true;
16877
0
            break;
16878
0
          }
16879
          // Set regexp position to tokenizer's next index.
16880
2.07k
          regexp_position = tokenizer.next_index;
16881
2.07k
          continue;
16882
2.07k
        }
16883
16884
        // If tokenizer's code point is U+0029 ()):
16885
19.8k
        if (tokenizer.code_point == ')') {
16886
          // Decrement depth by 1.
16887
4.26k
          depth--;
16888
          // If depth is 0:
16889
4.26k
          if (depth == 0) {
16890
            // Set regexp position to tokenizer's next index.
16891
3.79k
            regexp_position = tokenizer.next_index;
16892
            // Break.
16893
3.79k
            break;
16894
3.79k
          }
16895
15.5k
        } else if (tokenizer.code_point == '(') {
16896
          // Otherwise if tokenizer's code point is U+0028 (():
16897
          // Increment depth by 1.
16898
2.40k
          depth++;
16899
          // If regexp position equals tokenizer's input's code point length -
16900
          // 1:
16901
2.40k
          if (regexp_position == tokenizer.input.size() - 1) {
16902
            // Run process a tokenizing error given tokenizer, regexp start, and
16903
            // tokenizer's index.
16904
31
            if (auto process_error = tokenizer.process_tokenizing_error(
16905
31
                    regexp_start, tokenizer.index)) {
16906
25
              return tl::unexpected(*process_error);
16907
25
            }
16908
            // Set error to true.
16909
6
            error = true;
16910
6
            break;
16911
31
          }
16912
          // Let temporary position be tokenizer's next index.
16913
2.37k
          auto temporary_position = tokenizer.next_index;
16914
          // Run get the next code point given tokenizer.
16915
2.37k
          tokenizer.get_next_code_point();
16916
2.37k
          if (tokenizer.had_invalid_code_point()) {
16917
0
            if (auto process_error = tokenizer.process_tokenizing_error(
16918
0
                    tokenizer.next_index, temporary_position)) {
16919
0
              return tl::unexpected(*process_error);
16920
0
            }
16921
0
            error = true;
16922
0
            break;
16923
0
          }
16924
          // If tokenizer's code point is not U+003F (?):
16925
2.37k
          if (tokenizer.code_point != '?') {
16926
            // Run process a tokenizing error given tokenizer, regexp start, and
16927
            // tokenizer's index.
16928
1.62k
            if (auto process_error = tokenizer.process_tokenizing_error(
16929
1.62k
                    regexp_start, tokenizer.index)) {
16930
22
              return tl::unexpected(*process_error);
16931
22
            }
16932
            // Set error to true.
16933
1.59k
            error = true;
16934
1.59k
            break;
16935
1.62k
          }
16936
          // Set tokenizer's next index to temporary position.
16937
756
          tokenizer.next_index = temporary_position;
16938
756
        }
16939
        // Set regexp position to tokenizer's next index.
16940
14.3k
        regexp_position = tokenizer.next_index;
16941
14.3k
      }
16942
16943
      // If error is true continue.
16944
6.40k
      if (error) continue;
16945
      // If depth is not zero:
16946
4.31k
      if (depth != 0) {
16947
        // Run process a tokenizing error given tokenizer, regexp start, and
16948
        // tokenizer's index.
16949
520
        if (auto process_error = tokenizer.process_tokenizing_error(
16950
520
                regexp_start, tokenizer.index)) {
16951
211
          return tl::unexpected(*process_error);
16952
211
        }
16953
309
        continue;
16954
520
      }
16955
      // Let regexp length be regexp position - regexp start - 1.
16956
3.79k
      auto regexp_length = regexp_position - regexp_start - 1;
16957
      // If regexp length is zero:
16958
3.79k
      if (regexp_length == 0) {
16959
        // Run process a tokenizing error given tokenizer, regexp start, and
16960
        // tokenizer's index.
16961
328
        if (auto process_error = tokenizer.process_tokenizing_error(
16962
328
                regexp_start, tokenizer.index)) {
16963
22
          ada_log("process_tokenizing_error failed");
16964
22
          return tl::unexpected(*process_error);
16965
22
        }
16966
306
        continue;
16967
328
      }
16968
      // Run add a token given tokenizer, "regexp", regexp position, regexp
16969
      // start, and regexp length.
16970
3.47k
      tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start,
16971
3.47k
                          regexp_length);
16972
3.47k
      continue;
16973
3.79k
    }
16974
    // Run add a token with default position and length given tokenizer and
16975
    // "char".
16976
2.57M
    tokenizer.add_token_with_defaults(token_type::CHAR);
16977
2.57M
  }
16978
  // Run add a token with default length given tokenizer, "end", tokenizer's
16979
  // index, and tokenizer's index.
16980
1.19M
  tokenizer.add_token_with_default_length(token_type::END, tokenizer.index,
16981
1.19M
                                          tokenizer.index);
16982
16983
1.19M
  ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size());
16984
  // Return tokenizer's token list.
16985
1.19M
  return tokenizer.token_list;
16986
1.19M
}
16987
16988
namespace {
16989
constexpr std::array<uint8_t, 256> escape_pattern_table = []() consteval {
16990
  std::array<uint8_t, 256> out{};
16991
  for (auto& c : {'+', '*', '?', ':', '{', '}', '(', ')', '\\'}) {
16992
    out[c] = 1;
16993
  }
16994
  return out;
16995
}();
16996
16997
2.08M
constexpr bool should_escape_pattern_char(char c) {
16998
2.08M
  return escape_pattern_table[static_cast<uint8_t>(c)];
16999
2.08M
}
17000
}  // namespace
17001
17002
1.50M
std::string escape_pattern_string(std::string_view input) {
17003
1.50M
  ada_log("escape_pattern_string called with input=", input);
17004
1.50M
  if (input.empty()) [[unlikely]] {
17005
1.13M
    return "";
17006
1.13M
  }
17007
  // Assert: input is an ASCII string.
17008
371k
  ADA_ASSERT_TRUE(ada::idna::is_ascii(input));
17009
  // Let result be the empty string.
17010
371k
  std::string result{};
17011
  // Reserve extra space for potential escapes
17012
371k
  result.reserve(input.size() * 2);
17013
17014
  // While index is less than input's length:
17015
2.08M
  for (const char c : input) {
17016
2.08M
    if (should_escape_pattern_char(c)) {
17017
      // Append U+005C (\) to the end of result.
17018
1.35k
      result.push_back('\\');
17019
1.35k
    }
17020
    // Append c to the end of result.
17021
2.08M
    result.push_back(c);
17022
2.08M
  }
17023
  // Return result.
17024
371k
  return result;
17025
1.50M
}
17026
17027
namespace {
17028
constexpr std::array<uint8_t, 256> escape_regexp_table = []() consteval {
17029
  std::array<uint8_t, 256> out{};
17030
  for (auto& c : {'.', '+', '*', '?', '^', '$', '{', '}', '(', ')', '[', ']',
17031
                  '|', '/', '\\'}) {
17032
    out[c] = 1;
17033
  }
17034
  return out;
17035
}();
17036
17037
329k
constexpr bool should_escape_regexp_char(char c) {
17038
329k
  return escape_regexp_table[(uint8_t)c];
17039
329k
}
17040
}  // namespace
17041
17042
1.21M
std::string escape_regexp_string(std::string_view input) {
17043
  // Assert: input is an ASCII string.
17044
1.21M
  ADA_ASSERT_TRUE(idna::is_ascii(input));
17045
  // Let result be the empty string.
17046
1.21M
  std::string result{};
17047
  // Reserve extra space for potential escapes (worst case: all chars escaped)
17048
1.21M
  result.reserve(input.size() * 2);
17049
1.21M
  for (const char c : input) {
17050
329k
    if (should_escape_regexp_char(c)) {
17051
      // Avoid temporary string allocation - directly append characters
17052
292k
      result.push_back('\\');
17053
292k
      result.push_back(c);
17054
292k
    } else {
17055
36.8k
      result.push_back(c);
17056
36.8k
    }
17057
329k
  }
17058
1.21M
  return result;
17059
1.21M
}
17060
17061
std::string process_base_url_string(std::string_view input,
17062
62.8k
                                    url_pattern_init::process_type type) {
17063
  // If type is not "pattern" return input.
17064
62.8k
  if (type != url_pattern_init::process_type::pattern) {
17065
0
    return std::string(input);
17066
0
  }
17067
  // Return the result of escaping a pattern string given input.
17068
62.8k
  return escape_pattern_string(input);
17069
62.8k
}
17070
17071
constexpr bool is_absolute_pathname(
17072
61.3k
    std::string_view input, url_pattern_init::process_type type) noexcept {
17073
  // If input is the empty string, then return false.
17074
61.3k
  if (input.empty()) [[unlikely]] {
17075
0
    return false;
17076
0
  }
17077
  // If input[0] is U+002F (/), then return true.
17078
61.3k
  if (input.starts_with("/")) return true;
17079
  // If type is "url", then return false.
17080
0
  if (type == url_pattern_init::process_type::url) return false;
17081
  // If input's code point length is less than 2, then return false.
17082
0
  if (input.size() < 2) return false;
17083
  // If input[0] is U+005C (\) and input[1] is U+002F (/), then return true.
17084
  // If input[0] is U+007B ({) and input[1] is U+002F (/), then return true.
17085
  // Return false.
17086
0
  return input[1] == '/' && (input[0] == '\\' || input[0] == '{');
17087
0
}
17088
17089
std::string generate_pattern_string(
17090
    std::vector<url_pattern_part>& part_list,
17091
1.09M
    url_pattern_compile_component_options& options) {
17092
  // Let result be the empty string.
17093
1.09M
  std::string result{};
17094
  // Let index list be the result of getting the indices for part list.
17095
  // For each index of index list:
17096
1.95M
  for (size_t index = 0; index < part_list.size(); index++) {
17097
    // Let part be part list[index].
17098
    // Use reference to avoid copy
17099
851k
    const auto& part = part_list[index];
17100
    // Let previous part be part list[index - 1] if index is greater than 0,
17101
    // otherwise let it be null.
17102
    // Use pointer to avoid copy
17103
851k
    const url_pattern_part* previous_part =
17104
851k
        index == 0 ? nullptr : &part_list[index - 1];
17105
    // Let next part be part list[index + 1] if index is less than index list's
17106
    // size - 1, otherwise let it be null.
17107
851k
    const url_pattern_part* next_part =
17108
851k
        index < part_list.size() - 1 ? &part_list[index + 1] : nullptr;
17109
    // If part's type is "fixed-text" then:
17110
851k
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
17111
      // If part's modifier is "none" then:
17112
261k
      if (part.modifier == url_pattern_part_modifier::none) {
17113
        // Append the result of running escape a pattern string given part's
17114
        // value to the end of result.
17115
261k
        result.append(escape_pattern_string(part.value));
17116
261k
        continue;
17117
261k
      }
17118
      // Append "{" to the end of result.
17119
362
      result += "{";
17120
      // Append the result of running escape a pattern string given part's value
17121
      // to the end of result.
17122
362
      result.append(escape_pattern_string(part.value));
17123
      // Append "}" to the end of result.
17124
362
      result += "}";
17125
      // Append the result of running convert a modifier to a string given
17126
      // part's modifier to the end of result.
17127
362
      result.append(convert_modifier_to_string(part.modifier));
17128
362
      continue;
17129
261k
    }
17130
    // Let custom name be true if part's name[0] is not an ASCII digit;
17131
    // otherwise false.
17132
589k
    bool custom_name = !unicode::is_ascii_digit(part.name[0]);
17133
    // Let needs grouping be true if at least one of the following are true,
17134
    // otherwise let it be false:
17135
    // - part's suffix is not the empty string.
17136
    // - part's prefix is not the empty string and is not options's prefix code
17137
    // point.
17138
589k
    bool needs_grouping =
17139
589k
        !part.suffix.empty() ||
17140
589k
        (!part.prefix.empty() && (options.get_prefix().empty() ||
17141
46.5k
                                  part.prefix[0] != options.get_prefix()[0]));
17142
17143
    // If all of the following are true:
17144
    // - needs grouping is false; and
17145
    // - custom name is true; and
17146
    // - part's type is "segment-wildcard"; and
17147
    // - part's modifier is "none"; and
17148
    // - next part is not null; and
17149
    // - next part's prefix is the empty string; and
17150
    // - next part's suffix is the empty string
17151
589k
    if (!needs_grouping && custom_name &&
17152
1.93k
        part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17153
1.89k
        part.modifier == url_pattern_part_modifier::none && next_part &&
17154
771
        next_part->prefix.empty() && next_part->suffix.empty()) {
17155
      // If next part's type is "fixed-text":
17156
715
      if (next_part->type == url_pattern_part_type::FIXED_TEXT) {
17157
        // Set needs grouping to true if the result of running is a valid name
17158
        // code point given next part's value's first code point and the boolean
17159
        // false is true.
17160
275
        if (idna::valid_name_code_point(next_part->value[0], false)) {
17161
78
          needs_grouping = true;
17162
78
        }
17163
440
      } else {
17164
        // Set needs grouping to true if next part's name[0] is an ASCII digit.
17165
440
        needs_grouping = !next_part->name.empty() &&
17166
440
                         unicode::is_ascii_digit(next_part->name[0]);
17167
440
      }
17168
715
    }
17169
17170
    // If all of the following are true:
17171
    // - needs grouping is false; and
17172
    // - part's prefix is the empty string; and
17173
    // - previous part is not null; and
17174
    // - previous part's type is "fixed-text"; and
17175
    // - previous part's value's last code point is options's prefix code point.
17176
    // then set needs grouping to true.
17177
589k
    if (!needs_grouping && part.prefix.empty() && previous_part &&
17178
8.10k
        previous_part->type == url_pattern_part_type::FIXED_TEXT &&
17179
4.39k
        !previous_part->value.empty() && !options.get_prefix().empty() &&
17180
379
        previous_part->value.back() == options.get_prefix()[0]) {
17181
97
      needs_grouping = true;
17182
97
    }
17183
17184
    // Assert: part's name is not the empty string or null.
17185
589k
    ADA_ASSERT_TRUE(!part.name.empty());
17186
17187
    // If needs grouping is true, then append "{" to the end of result.
17188
589k
    if (needs_grouping) {
17189
1.43k
      result.append("{");
17190
1.43k
    }
17191
17192
    // Append the result of running escape a pattern string given part's prefix
17193
    // to the end of result.
17194
589k
    result.append(escape_pattern_string(part.prefix));
17195
17196
    // If custom name is true:
17197
589k
    if (custom_name) {
17198
      // Append ":" to the end of result.
17199
2.27k
      result.append(":");
17200
      // Append part's name to the end of result.
17201
2.27k
      result.append(part.name);
17202
2.27k
    }
17203
17204
    // If part's type is "regexp" then:
17205
589k
    if (part.type == url_pattern_part_type::REGEXP) {
17206
      // Append "(" to the end of result.
17207
2.36k
      result.append("(");
17208
      // Append part's value to the end of result.
17209
2.36k
      result.append(part.value);
17210
      // Append ")" to the end of result.
17211
2.36k
      result.append(")");
17212
587k
    } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD &&
17213
2.26k
               !custom_name) {
17214
      // Otherwise if part's type is "segment-wildcard" and custom name is
17215
      // false: Append "(" to the end of result.
17216
29
      result.append("(");
17217
      // Append the result of running generate a segment wildcard regexp given
17218
      // options to the end of result.
17219
29
      result.append(generate_segment_wildcard_regexp(options));
17220
      // Append ")" to the end of result.
17221
29
      result.append(")");
17222
587k
    } else if (part.type == url_pattern_part_type::FULL_WILDCARD) {
17223
      // Otherwise if part's type is "full-wildcard":
17224
      // If custom name is false and one of the following is true:
17225
      // - previous part is null; or
17226
      // - previous part's type is "fixed-text"; or
17227
      // - previous part's modifier is not "none"; or
17228
      // - needs grouping is true; or
17229
      // - part's prefix is not the empty string
17230
      // - then append "*" to the end of result.
17231
585k
      if (!custom_name &&
17232
585k
          (!previous_part ||
17233
7.25k
           previous_part->type == url_pattern_part_type::FIXED_TEXT ||
17234
2.94k
           previous_part->modifier != url_pattern_part_modifier::none ||
17235
585k
           needs_grouping || !part.prefix.empty())) {
17236
585k
        result.append("*");
17237
585k
      } else {
17238
        // Append "(" to the end of result.
17239
        // Append full wildcard regexp value to the end of result.
17240
        // Append ")" to the end of result.
17241
111
        result.append("(.*)");
17242
111
      }
17243
585k
    }
17244
17245
    // If all of the following are true:
17246
    // - part's type is "segment-wildcard"; and
17247
    // - custom name is true; and
17248
    // - part's suffix is not the empty string; and
17249
    // - The result of running is a valid name code point given part's suffix's
17250
    // first code point and the boolean false is true then append U+005C (\) to
17251
    // the end of result.
17252
589k
    if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name &&
17253
2.23k
        !part.suffix.empty() &&
17254
156
        idna::valid_name_code_point(part.suffix[0], false)) {
17255
67
      result.append("\\");
17256
67
    }
17257
17258
    // Append the result of running escape a pattern string given part's suffix
17259
    // to the end of result.
17260
589k
    result.append(escape_pattern_string(part.suffix));
17261
    // If needs grouping is true, then append "}" to the end of result.
17262
589k
    if (needs_grouping) result.append("}");
17263
    // Append the result of running convert a modifier to a string given part's
17264
    // modifier to the end of result.
17265
589k
    result.append(convert_modifier_to_string(part.modifier));
17266
589k
  }
17267
  // Return result.
17268
1.09M
  return result;
17269
1.09M
}
17270
}  // namespace ada::url_pattern_helpers
17271
17272
#endif  // ADA_INCLUDE_URL_PATTERN
17273
/* end file src/url_pattern_helpers.cpp */
17274
/* begin file src/url_pattern_regex.cpp */
17275
#if ADA_INCLUDE_URL_PATTERN
17276
17277
17278
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17279
#include <cstddef>
17280
#include <optional>
17281
#include <regex>
17282
#include <string>
17283
#include <string_view>
17284
#include <vector>
17285
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17286
17287
namespace ada::url_pattern_regex {
17288
17289
#ifdef ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17290
std::optional<std::regex> std_regex_provider::create_instance(
17291
52.0k
    std::string_view pattern, bool ignore_case) {
17292
  // Let flags be an empty string.
17293
  // If options's ignore case is true then set flags to "vi".
17294
  // Otherwise set flags to "v"
17295
52.0k
  auto flags = ignore_case
17296
52.0k
                   ? std::regex::icase | std::regex_constants::ECMAScript
17297
52.0k
                   : std::regex_constants::ECMAScript;
17298
52.0k
  try {
17299
52.0k
    return std::regex(pattern.data(), pattern.size(), flags);
17300
52.0k
  } catch (const std::regex_error& e) {
17301
1.19k
    (void)e;
17302
1.19k
    ada_log("std_regex_provider::create_instance failed:", e.what());
17303
1.19k
    return std::nullopt;
17304
1.19k
  }
17305
52.0k
}
17306
17307
std::optional<std::vector<std::optional<std::string>>>
17308
std_regex_provider::regex_search(std::string_view input,
17309
8.13k
                                 const std::regex& pattern) {
17310
  // Use iterator-based regex_search to avoid string allocation
17311
8.13k
  std::match_results<std::string_view::const_iterator> match_result;
17312
8.13k
  try {
17313
8.13k
    if (!std::regex_search(input.begin(), input.end(), match_result, pattern,
17314
8.13k
                           std::regex_constants::match_any)) {
17315
3.61k
      return std::nullopt;
17316
3.61k
    }
17317
8.13k
  } catch (const std::regex_error& e) {
17318
51
    (void)e;
17319
51
    ada_log("std_regex_provider::regex_search failed:", e.what());
17320
51
    return std::nullopt;
17321
51
  }
17322
4.47k
  std::vector<std::optional<std::string>> matches;
17323
  // An empty input can still match with capture groups (e.g. "(x*)" or an
17324
  // optional ":a?" against ""), so the group values must be extracted here
17325
  // just like for a non-empty input. A successful regex_search always leaves
17326
  // the full match at index 0, so match_result is never empty at this point.
17327
4.47k
  if (match_result.empty()) {
17328
0
    return matches;
17329
0
  }
17330
4.47k
  matches.reserve(match_result.size());
17331
15.6k
  for (size_t i = 1; i < match_result.size(); ++i) {
17332
11.1k
    if (auto entry = match_result[i]; entry.matched) {
17333
10.0k
      matches.emplace_back(entry.str());
17334
10.0k
    } else {
17335
      // A capture group that did not participate in the match is undefined,
17336
      // not absent. Emitting nullopt keeps the result aligned by position with
17337
      // the component's group name list; dropping it shifts every later group
17338
      // onto the wrong name.
17339
1.03k
      matches.emplace_back(std::nullopt);
17340
1.03k
    }
17341
11.1k
  }
17342
4.47k
  return matches;
17343
4.47k
}
17344
17345
bool std_regex_provider::regex_match(std::string_view input,
17346
13.2k
                                     const std::regex& pattern) {
17347
13.2k
  try {
17348
13.2k
    return std::regex_match(input.begin(), input.end(), pattern);
17349
13.2k
  } catch (const std::regex_error& e) {
17350
87
    (void)e;
17351
87
    ada_log("std_regex_provider::regex_match failed:", e.what());
17352
87
    return false;
17353
87
  }
17354
13.2k
}
17355
17356
#endif  // ADA_USE_UNSAFE_STD_REGEX_PROVIDER
17357
17358
}  // namespace ada::url_pattern_regex
17359
17360
#endif  // ADA_INCLUDE_URL_PATTERN
17361
/* end file src/url_pattern_regex.cpp */
17362
#if !defined(ADA_URL_PATTERN_LIST_SEPARATE_TU)
17363
/* begin file src/url_pattern_list.cpp */
17364
/**
17365
 * @file url_pattern_list.cpp
17366
 * @brief Route-set compiler backing ada::url_pattern_list.
17367
 *
17368
 * The provider-independent build side: classification of URLPattern part
17369
 * lists into pattern segments, the compiler (segment trie, per-node dispatch,
17370
 * auxiliary-route pruning), the arena packing, and the sequential reference
17371
 * matcher used beyond the fast-path limits. The matcher itself is inline in
17372
 * url_pattern_list-inl.h.
17373
 *
17374
 * Every dispatch decision is made at build time so that the per-request
17375
 * residual is a segment scan and a trie walk with bounded backtracking.
17376
 * Offline searches (witness plans, perfect multipliers) that fail demote the
17377
 * affected node to a linear scan: slower, never incorrect.
17378
 */
17379
/* begin file src/url_pattern_list_compiler.h */
17380
/**
17381
 * @file url_pattern_list_compiler.h
17382
 * @brief The url_pattern_list route-set compiler: pattern classification and
17383
 * the build-time table construction behind ada::parse_url_pattern_list.
17384
 *
17385
 * This header is NOT part of the public API and is not included from ada.h:
17386
 * only src/url_pattern_list.cpp (and, through the amalgamated ada.cpp, the
17387
 * url_pattern_list fuzzer) include it. The matcher-visible table layout it
17388
 * produces is declared in include/ada/url_pattern_list.h.
17389
 */
17390
#ifndef ADA_URL_PATTERN_LIST_COMPILER_H
17391
#define ADA_URL_PATTERN_LIST_COMPILER_H
17392
17393
17394
#include <cstddef>
17395
#include <cstdint>
17396
#include <string>
17397
#include <vector>
17398
17399
#if ADA_INCLUDE_URL_PATTERN
17400
namespace ada::url_pattern_list_compiler {
17401
17402
/**
17403
 * Maximum number of entries a perfect-hash dispatch table may index (slot
17404
 * ordinals are 8-bit, with 0xFF reserved for "empty"). Nodes with a larger
17405
 * static fanout are demoted to a linear scan: slower, never incorrect.
17406
 */
17407
inline constexpr uint32_t max_dispatch_table_entries = 254;
17408
17409
/**
17410
 * Static fanout up to which a node compares its children directly, in
17411
 * turn; wider nodes dispatch through a projection table. Measured on a
17412
 * synthetic node hit uniformly: direct compares beat the projection by
17413
 * about 1 ns for keys of varied length up to about 12 children, while for
17414
 * keys of one length (which the length gate cannot reject) the projection
17415
 * wins by 4-5 ns at every fanout and by more on misses, because the direct
17416
 * loop's exit is unpredictable. Eight keeps the first case and bounds the
17417
 * second.
17418
 */
17419
inline constexpr uint32_t max_direct_children = 8;
17420
17421
/**
17422
 * The kind of one compiled pattern segment. The numeric values define match
17423
 * priority: at the first differing segment, a literal beats a ":param" and a
17424
 * ":param" beats a "*" (find-my-way / Express-compatible specificity order).
17425
 */
17426
enum class segment_kind : uint8_t {
17427
  literal = 0,
17428
  param = 1,
17429
  wildcard = 2,
17430
};
17431
17432
/**
17433
 * One '/'-separated segment of a compiled pattern: a literal text (already
17434
 * canonicalized by the URLPattern pattern parser), a ":param" (text = group
17435
 * name), or a trailing "*" wildcard.
17436
 */
17437
struct route_segment {
17438
  segment_kind kind = segment_kind::literal;
17439
  std::string text{};
17440
};
17441
17442
/**
17443
 * Everything the compiler knows about one route. `kind_sequence` packs the
17444
 * per-segment kinds two bits per segment, most significant first, so that
17445
 * comparing (kind_sequence, kind_length, route index) as a tuple is exactly
17446
 * the documented specificity order. For regexp-mode routes, `segments`
17447
 * holds only the anchored literal prefix (the leading segments that are
17448
 * whole fixed text, closed by a '/'), which the auxiliary-route pruning
17449
 * uses to rule out routes that can never match the same input.
17450
 */
17451
struct route_info {
17452
  std::vector<route_segment> segments{};
17453
  // Capture group names, in capture order (params left to right, then the
17454
  // wildcard group). Regexp-mode routes: filled from the compiled component.
17455
  std::vector<std::string> group_names{};
17456
  uint64_t kind_sequence = 0;
17457
  uint8_t kind_length = 0;
17458
  url_pattern_list_detail::route_mode mode =
17459
      url_pattern_list_detail::route_mode::sequential;
17460
  bool has_wildcard = false;
17461
  bool all_literal = false;
17462
};
17463
17464
/**
17465
 * Classifies a URLPattern part list into '/'-separated pattern segments.
17466
 * Returns true when the pattern is expressible in the static/":param"/"*"
17467
 * subset (every segment wholly a literal, a param, or a final wildcard);
17468
 * `segments` and `group_names` are only valid on success.
17469
 */
17470
bool classify_parts(const std::vector<url_pattern_part>& parts,
17471
                    std::vector<route_segment>& segments,
17472
                    std::vector<std::string>& group_names);
17473
17474
/**
17475
 * Computes kind sequence and flags from route.segments and decides the
17476
 * route's mode: trie when every fast-path build limit is met, sequential
17477
 * otherwise (the empty pattern, more than max_trie_pattern_segments
17478
 * segments, or more than max_captures_per_route capture groups).
17479
 */
17480
void finalize_route(route_info& route) noexcept;
17481
17482
/**
17483
 * Best-effort kind sequence for a route that needs regexp matching, so it can
17484
 * participate in the specificity order: custom "(...)" groups count as params,
17485
 * full wildcards and modified ("?", "+", "*") groups terminate the sequence as
17486
 * a wildcard tail. This mapping is an approximation and is called out as an
17487
 * open question in the class documentation. Also records the route's
17488
 * anchored literal prefix in route.segments and sets mode = regexp.
17489
 */
17490
void approximate_kind_sequence(const std::vector<url_pattern_part>& parts,
17491
                               route_info& route);
17492
17493
/**
17494
 * True when route `a` (at insertion index `a_index`) outranks route `b`.
17495
 */
17496
constexpr bool route_outranks(const route_info& a, size_t a_index,
17497
0
                              const route_info& b, size_t b_index) noexcept {
17498
0
  return url_pattern_list_detail::outranks(a.kind_sequence, a.kind_length,
17499
0
                                           a_index, b.kind_sequence,
17500
0
                                           b.kind_length, b_index);
17501
0
}
17502
17503
/**
17504
 * Compiles the route set: builds the trie and its dispatch plans over the
17505
 * trie-mode routes, the segment table, the auxiliary-route table with its
17506
 * per-route challenger ranges, and packs everything into one arena. Never
17507
 * fails: any node whose offline search fails is demoted to a slower but
17508
 * correct plan.
17509
 * Literal texts are used as given (the caller has already case-folded them
17510
 * when ignore_case is set).
17511
 */
17512
url_pattern_list_detail::compiled_routes compile_route_set(
17513
    std::vector<route_info>& routes);
17514
17515
}  // namespace ada::url_pattern_list_compiler
17516
#endif  // ADA_INCLUDE_URL_PATTERN
17517
#endif  // ADA_URL_PATTERN_LIST_COMPILER_H
17518
/* end file src/url_pattern_list_compiler.h */
17519
17520
#include <algorithm>
17521
#include <array>
17522
#include <bit>
17523
#include <cstdint>
17524
#include <cstring>
17525
#include <limits>
17526
#include <span>
17527
#include <string_view>
17528
#include <utility>
17529
#include <vector>
17530
17531
#if ADA_INCLUDE_URL_PATTERN
17532
17533
namespace ada::url_pattern_list_compiler {
17534
17535
namespace {
17536
17537
using url_pattern_list_detail::compiled_routes;
17538
using url_pattern_list_detail::edge_record;
17539
using url_pattern_list_detail::hash_record;
17540
using url_pattern_list_detail::node_record;
17541
using url_pattern_list_detail::route_mode;
17542
using url_pattern_list_detail::route_record;
17543
using url_pattern_list_detail::segment_record;
17544
using url_pattern_list_limits::max_captures_per_route;
17545
using url_pattern_list_limits::max_trie_pattern_segments;
17546
17547
// The tables under construction, one vector per section; packed into the
17548
// single arena of compiled_routes at the end of the build.
17549
struct builder_tables {
17550
  std::vector<node_record> nodes{};
17551
  std::vector<hash_record> hashes{};
17552
  std::vector<edge_record> edges{};
17553
  std::vector<uint8_t> slots{};
17554
  std::vector<char> blob{};
17555
  std::vector<route_record> routes{};
17556
  std::vector<segment_record> segments{};
17557
  std::vector<uint32_t> aux{};
17558
  std::vector<uint16_t> root_index{};
17559
  uint32_t n_aux_all = 0;
17560
};
17561
17562
// Witness plan for single-string tables: nibbles 0..2 hold witness ids
17563
// (distinct ids first, remaining slots duplicating id 0 so the runtime
17564
// gather is fixed-shape and branch-free); bits 12..14 are metadata.
17565
constexpr uint16_t pack_witness_plan(const uint8_t* ids, uint32_t n_ids,
17566
0
                                     bool use_len) noexcept {
17567
0
  uint16_t w = 0;
17568
0
  for (uint32_t j = 0; j < 3; j++) {
17569
0
    w = static_cast<uint16_t>(
17570
0
        w | static_cast<uint16_t>((j < n_ids ? ids[j] : ids[0]) & 15u)
17571
0
                << (4 * j));
17572
0
  }
17573
0
  w = static_cast<uint16_t>(w | static_cast<uint16_t>(n_ids << 12));
17574
0
  if (use_len) {
17575
0
    w = static_cast<uint16_t>(w | static_cast<uint16_t>(1) << 14);
17576
0
  }
17577
0
  return w;
17578
0
}
17579
17580
// Bytes [from, min(from + 8, len)) of a key, packed little-endian and
17581
// zero-padded; the build-time twin of the matcher's window load.
17582
constexpr uint64_t pack_window_le(const char* p, uint32_t len,
17583
0
                                  uint32_t from) noexcept {
17584
0
  uint64_t x = 0;
17585
0
  for (uint32_t j = 0; j < 8 && from + j < len; j++) {
17586
0
    x |= static_cast<uint64_t>(static_cast<uint8_t>(p[from + j])) << (8 * j);
17587
0
  }
17588
0
  return x;
17589
0
}
17590
17591
// Deterministic RNG for the multiplier search (splitmix64).
17592
struct splitmix64 {
17593
  uint64_t state;
17594
0
  constexpr explicit splitmix64(uint64_t seed) noexcept : state(seed) {}
17595
0
  constexpr uint64_t next() noexcept {
17596
0
    uint64_t z = (state += 0x9E3779B97F4A7C15ull);
17597
0
    z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ull;
17598
0
    z = (z ^ (z >> 27)) * 0x94D049BB133111EBull;
17599
0
    return z ^ (z >> 31);
17600
0
  }
17601
};
17602
17603
struct transient_node {  // build-time trie (views into route segment storage)
17604
  std::vector<std::pair<std::string_view, int32_t>> kids{};
17605
  int32_t param = -1;
17606
  int32_t wild_route = -1;
17607
  int32_t terminal = -1;
17608
};
17609
17610
0
constexpr unsigned ceil_log2(size_t n) noexcept {
17611
0
  unsigned b = 0;
17612
0
  while ((size_t{1} << b) < n) {
17613
0
    b++;
17614
0
  }
17615
0
  return b;
17616
0
}
17617
17618
// Starting table size for n keys: load factor <= ~1/4, loosened as n grows
17619
// so the multiplier search still lands inside the budget.
17620
0
constexpr unsigned initial_slot_bits(size_t n) noexcept {
17621
0
  unsigned headroom = 1;
17622
0
  if (n > 64) {
17623
0
    headroom = 3;
17624
0
  } else if (n > 8) {
17625
0
    headroom = 2;
17626
0
  }
17627
0
  return ceil_log2(n) + headroom;
17628
0
}
17629
17630
bool find_multiplier(const std::vector<uint64_t>& proj, unsigned b0,
17631
0
                     uint64_t& multiplier_out, uint8_t& bits_out) {
17632
0
  const size_t n = proj.size();
17633
0
  for (unsigned b = b0; b <= 12; b++) {
17634
0
    std::vector<uint32_t> stamp(size_t{1} << b, 0);
17635
0
    splitmix64 rng(0x14C0FFEEull + b);
17636
0
    for (uint32_t t = 1; t <= 4000; t++) {
17637
0
      const uint64_t m = rng.next() | 1;
17638
0
      bool ok = true;
17639
0
      for (size_t i = 0; i < n; i++) {
17640
0
        const uint64_t s = (proj[i] * m) >> (64 - b);
17641
0
        if (stamp[s] == t) {
17642
0
          ok = false;
17643
0
          break;
17644
0
        }
17645
0
        stamp[s] = t;
17646
0
      }
17647
0
      if (ok) {
17648
0
        multiplier_out = m;
17649
0
        bits_out = static_cast<uint8_t>(b);
17650
0
        return true;
17651
0
      }
17652
0
    }
17653
0
  }
17654
0
  return false;
17655
0
}
17656
17657
// Emits a perfect-hash slot table for `proj` at the end of `slots`. Returns
17658
// false if the search failed, in which case nothing was appended and the
17659
// caller demotes that table to a linear scan.
17660
bool emit_slot_table(const std::vector<uint64_t>& proj,
17661
                     std::vector<uint8_t>& slots, uint64_t& multiplier_out,
17662
0
                     uint8_t& bits_out, uint32_t& base_out) {
17663
0
  if (!find_multiplier(proj, initial_slot_bits(proj.size()), multiplier_out,
17664
0
                       bits_out)) {
17665
0
    return false;
17666
0
  }
17667
0
  base_out = static_cast<uint32_t>(slots.size());
17668
0
  slots.resize(slots.size() + (size_t{1} << bits_out), 0xFF);
17669
0
  for (size_t i = 0; i < proj.size(); i++) {
17670
0
    slots[base_out +
17671
0
          url_pattern_list_detail::slot_of(proj[i], multiplier_out, bits_out)] =
17672
0
        static_cast<uint8_t>(i);
17673
0
  }
17674
0
  return true;
17675
0
}
17676
17677
// Advances `c` to the next k-combination of {0..n-1} in lexicographic
17678
// order; false once the last one has been visited.
17679
template <size_t N>
17680
constexpr bool next_combination(std::array<uint32_t, N>& c, uint32_t k,
17681
0
                                uint32_t n) noexcept {
17682
0
  int32_t j = static_cast<int32_t>(k) - 1;
17683
0
  while (j >= 0 &&
17684
0
         c[static_cast<uint32_t>(j)] == n - k + static_cast<uint32_t>(j)) {
17685
0
    j--;
17686
0
  }
17687
0
  if (j < 0) {
17688
0
    return false;
17689
0
  }
17690
0
  c[static_cast<uint32_t>(j)]++;
17691
0
  for (uint32_t t = static_cast<uint32_t>(j) + 1; t < k; t++) {
17692
0
    c[t] = c[t - 1] + 1;
17693
0
  }
17694
0
  return true;
17695
0
}
17696
17697
// Witness-subset search over the given id alphabet, cost-ordered: fewest
17698
// distinct witness ids first (the length is always packed -- it is free).
17699
// The first injective subset wins.
17700
bool find_witness_plan(
17701
    const std::vector<std::pair<std::string_view, int32_t>>& kids,
17702
    const uint8_t* alphabet, uint32_t n_alpha, uint32_t max_reads,
17703
0
    uint16_t& plan_out) {
17704
0
  const size_t n = kids.size();
17705
0
  auto injective = [&](uint16_t wp) {  // sort + adjacent compare
17706
0
    std::vector<uint64_t> proj(n);
17707
0
    for (size_t i = 0; i < n; i++) {
17708
0
      proj[i] = url_pattern_list_detail::project(
17709
0
          kids[i].first.data(), static_cast<uint32_t>(kids[i].first.size()),
17710
0
          wp);
17711
0
    }
17712
0
    std::sort(proj.begin(), proj.end());
17713
0
    for (size_t i = 1; i < n; i++) {
17714
0
      if (proj[i] == proj[i - 1]) {
17715
0
        return false;
17716
0
      }
17717
0
    }
17718
0
    return true;
17719
0
  };
17720
0
  for (uint32_t k = 1; k <= max_reads && k <= n_alpha; k++) {
17721
0
    std::array<uint32_t, 3> c{0, 1, 2};
17722
0
    do {
17723
0
      uint8_t ids[3] = {0, 0, 0};
17724
0
      for (uint32_t j = 0; j < k; j++) {
17725
0
        ids[j] = alphabet[c[j]];
17726
0
      }
17727
0
      const uint16_t wp = pack_witness_plan(ids, k, true);
17728
0
      if (injective(wp)) {
17729
0
        plan_out = wp;
17730
0
        return true;
17731
0
      }
17732
0
    } while (next_combination(c, k, n_alpha));
17733
0
  }
17734
0
  return false;
17735
0
}
17736
17737
// ---- build stages ----------------------------------------------------------
17738
17739
// Segment trie over the trie-mode routes. Priority is resolved here, at
17740
// build, into each node's fixed decision order (static children -> param ->
17741
// wildcard); a DFS in that order returns the match with the
17742
// lexicographically minimal kind sequence. Duplicate patterns collapse onto
17743
// one slot: an occupied slot is never overwritten, so the smallest route
17744
// index survives.
17745
0
std::vector<transient_node> build_trie(const std::vector<route_info>& routes) {
17746
0
  std::vector<transient_node> t(1);
17747
0
  for (size_t i = 0; i < routes.size(); i++) {
17748
0
    const route_info& rt = routes[i];
17749
0
    if (rt.mode != route_mode::trie) {
17750
0
      continue;
17751
0
    }
17752
0
    int32_t cur = 0;
17753
0
    for (const route_segment& ps : rt.segments) {
17754
0
      if (ps.kind == segment_kind::literal) {
17755
0
        int32_t nxt = -1;
17756
0
        for (auto& kv : t[static_cast<size_t>(cur)].kids) {
17757
0
          if (kv.first == ps.text) {
17758
0
            nxt = kv.second;
17759
0
            break;
17760
0
          }
17761
0
        }
17762
0
        if (nxt < 0) {
17763
0
          nxt = static_cast<int32_t>(t.size());
17764
0
          t[static_cast<size_t>(cur)].kids.emplace_back(ps.text, nxt);
17765
0
          t.emplace_back();
17766
0
        }
17767
0
        cur = nxt;
17768
0
      } else if (ps.kind == segment_kind::param) {
17769
0
        if (t[static_cast<size_t>(cur)].param < 0) {
17770
0
          t[static_cast<size_t>(cur)].param = static_cast<int32_t>(t.size());
17771
0
          t.emplace_back();
17772
0
        }
17773
0
        cur = t[static_cast<size_t>(cur)].param;
17774
0
      } else {  // wildcard (classification guarantees final)
17775
0
        if (t[static_cast<size_t>(cur)].wild_route < 0) {
17776
0
          t[static_cast<size_t>(cur)].wild_route = static_cast<int32_t>(i);
17777
0
        }
17778
0
        cur = -1;
17779
0
        break;
17780
0
      }
17781
0
    }
17782
0
    if (cur >= 0 && t[static_cast<size_t>(cur)].terminal < 0) {
17783
0
      t[static_cast<size_t>(cur)].terminal = static_cast<int32_t>(i);
17784
0
    }
17785
0
  }
17786
  // The root's children are sorted by first byte so that the first-byte
17787
  // index can address each run of same-byte children as one contiguous
17788
  // block of edges.
17789
0
  std::stable_sort(
17790
0
      t[0].kids.begin(), t[0].kids.end(), [](const auto& a, const auto& b) {
17791
0
        const int ka = a.first.empty() ? -1 : static_cast<uint8_t>(a.first[0]);
17792
0
        const int kb = b.first.empty() ? -1 : static_cast<uint8_t>(b.first[0]);
17793
0
        return ka < kb;
17794
0
      });
17795
0
  return t;
17796
0
}
17797
17798
// Per-route records: priority data, capture positions (so extracting params
17799
// at match time is a fixed walk over param_positions), regexp ordinals.
17800
void compile_route_records(builder_tables& r,
17801
0
                           const std::vector<route_info>& routes) {
17802
0
  r.routes.resize(routes.size());
17803
0
  int32_t n_regexp = 0;
17804
0
  for (size_t i = 0; i < routes.size(); i++) {
17805
0
    const route_info& rt = routes[i];
17806
0
    route_record& rm = r.routes[i];
17807
0
    rm.kind_sequence = rt.kind_sequence;
17808
0
    rm.kind_length = rt.kind_length;
17809
0
    rm.mode = rt.mode;
17810
0
    rm.wild = rt.has_wildcard ? 1 : 0;
17811
0
    if (rt.mode == route_mode::regexp) {
17812
0
      rm.regexp_component = n_regexp++;
17813
0
      continue;
17814
0
    }
17815
0
    if (rt.mode != route_mode::trie) {
17816
0
      continue;  // capture positions are only read for trie-answered routes
17817
0
    }
17818
0
    for (size_t s = 0; s < rt.segments.size(); s++) {
17819
0
      if (rt.segments[s].kind == segment_kind::param) {
17820
        // Classification guarantees n_params <= max_captures_per_route for
17821
        // trie-mode routes.
17822
0
        rm.param_positions[rm.n_params++] = static_cast<uint8_t>(s);
17823
0
      }
17824
0
    }
17825
0
  }
17826
0
}
17827
17828
// BFS layout: assign final node ids breadth-first so each node's static
17829
// children occupy a contiguous block of edges[]. Returns the transient-node
17830
// id per final id.
17831
std::vector<int32_t> layout_nodes(builder_tables& r,
17832
0
                                  const std::vector<transient_node>& t) {
17833
0
  std::vector<int32_t> order;  // transient id per final id
17834
0
  order.push_back(0);
17835
0
  r.nodes.resize(1);
17836
0
  for (size_t head = 0; head < order.size(); head++) {
17837
0
    const transient_node& tn = t[static_cast<size_t>(order[head])];
17838
0
    node_record nd{};
17839
0
    nd.wild_route = tn.wild_route;
17840
0
    nd.terminal_route = tn.terminal;
17841
0
    nd.first_child = static_cast<int32_t>(r.edges.size());
17842
0
    nd.n_static = static_cast<uint16_t>(tn.kids.size());
17843
0
    const size_t id_base = order.size();  // children take the next BFS ids
17844
0
    for (size_t ci = 0; ci < tn.kids.size(); ci++) {
17845
0
      const std::string_view k = tn.kids[ci].first;
17846
0
      edge_record e{};
17847
0
      e.key_length = static_cast<uint16_t>(k.size());
17848
0
      e.key_offset = static_cast<uint32_t>(r.blob.size());
17849
0
      r.blob.insert(r.blob.end(), k.begin(), k.end());
17850
0
      e.prefix = pack_window_le(k.data(), static_cast<uint32_t>(k.size()), 0);
17851
0
      e.suffix = pack_window_le(
17852
0
          k.data(), static_cast<uint32_t>(k.size()),
17853
0
          k.size() >= 8 ? static_cast<uint32_t>(k.size()) - 8 : 0);
17854
0
      e.node = static_cast<int32_t>(id_base + ci);
17855
0
      r.edges.push_back(e);
17856
0
    }
17857
0
    for (size_t ci = 0; ci < tn.kids.size(); ci++) {
17858
0
      order.push_back(tn.kids[ci].second);
17859
0
    }
17860
0
    if (tn.param >= 0) {
17861
0
      nd.param_child = static_cast<int32_t>(order.size());
17862
0
      order.push_back(tn.param);
17863
0
    }
17864
0
    nd.has_alternative = (nd.param_child >= 0 || nd.wild_route >= 0) ? 1 : 0;
17865
0
    r.nodes.resize(order.size());
17866
0
    r.nodes[head] = nd;
17867
0
  }
17868
0
  return order;
17869
0
}
17870
17871
// Root first-byte index: a 256-entry table from the first byte of the
17872
// input's first segment to the first root child starting with it (the
17873
// children are sorted by first byte). Built for a root with at least three
17874
// children; a run of same-byte children longer than max_direct_children, or
17875
// an empty key, falls back to the regular ladder. Returns true when the
17876
// index was emitted.
17877
0
bool build_root_index(builder_tables& r, const transient_node& root) {
17878
0
  const size_t nk = root.kids.size();
17879
0
  if (nk < 3) {
17880
0
    return false;
17881
0
  }
17882
0
  std::array<uint16_t, 256> index{};
17883
0
  index.fill(0xFFFF);
17884
0
  std::array<uint32_t, 256> run{};
17885
0
  for (size_t ci = 0; ci < nk; ci++) {
17886
0
    if (root.kids[ci].first.empty()) {
17887
0
      return false;  // an empty key has no first byte: regular ladder
17888
0
    }
17889
0
    const uint8_t b = static_cast<uint8_t>(root.kids[ci].first[0]);
17890
0
    if (index[b] == 0xFFFF) {
17891
0
      index[b] = static_cast<uint16_t>(ci);
17892
0
    }
17893
0
    if (++run[b] > max_direct_children) {
17894
0
      return false;
17895
0
    }
17896
0
  }
17897
0
  r.root_index.assign(index.begin(), index.end());
17898
0
  return true;
17899
0
}
17900
17901
// Per-node dispatch ladder, chosen by static child count: 0 none, up to
17902
// max_direct_children direct compares, then projection over a restricted
17903
// alphabet (escalating to the full alphabet); linear demotion when a search
17904
// fails or when the fanout exceeds max_dispatch_table_entries. The root
17905
// gets the first-byte index when its fanout allows. Never incorrect, only
17906
// slower.
17907
void compile_dispatch(builder_tables& r, const std::vector<transient_node>& t,
17908
0
                      const std::vector<int32_t>& order) {
17909
0
  for (size_t ni = 0; ni < r.nodes.size(); ni++) {
17910
0
    node_record& nd = r.nodes[ni];
17911
0
    const transient_node& tn = t[static_cast<size_t>(order[ni])];
17912
0
    const size_t nk = tn.kids.size();
17913
0
    if (nk == 0) {
17914
0
      nd.dispatch = 0;
17915
0
      continue;
17916
0
    }
17917
0
    if (ni == 0 && build_root_index(r, tn)) {
17918
0
      nd.dispatch = 4;
17919
0
      continue;
17920
0
    }
17921
0
    if (nk <= max_direct_children) {
17922
0
      nd.dispatch = 1;
17923
0
      continue;
17924
0
    }
17925
0
    if (nk > max_dispatch_table_entries) {
17926
0
      nd.dispatch = 3;  // slot ordinals are 8-bit; linear scan stays correct
17927
0
      continue;
17928
0
    }
17929
0
    uint16_t wp = 0;
17930
0
    bool found = false;
17931
0
    if (nk <= 16) {
17932
0
      constexpr uint8_t alpha_small[2] = {0, 8};  // s[0], s[len - 1]
17933
0
      found = find_witness_plan(tn.kids, alpha_small, 2, 2, wp);
17934
0
    }
17935
0
    if (!found) {  // full alphabet (also the escalation path for <= 16)
17936
0
      uint8_t alpha_full[16] = {0, 1, 2,  3,  4,  5,  6,  7,
17937
0
                                8, 9, 10, 11, 12, 13, 14, 15};
17938
0
      found = find_witness_plan(tn.kids, alpha_full, 16, 3, wp);
17939
0
    }
17940
0
    hash_record h{};
17941
0
    if (found) {
17942
0
      std::vector<uint64_t> proj(nk);
17943
0
      for (size_t i = 0; i < nk; i++) {
17944
0
        proj[i] = url_pattern_list_detail::project(
17945
0
            tn.kids[i].first.data(),
17946
0
            static_cast<uint32_t>(tn.kids[i].first.size()), wp);
17947
0
      }
17948
0
      found = emit_slot_table(proj, r.slots, h.multiplier, h.slot_bits,
17949
0
                              h.slot_base);
17950
0
    }
17951
0
    if (!found) {
17952
0
      nd.dispatch = 3;  // demoted: correct, slower
17953
0
      continue;
17954
0
    }
17955
0
    nd.dispatch = 2;
17956
0
    h.witness_plan = wp;
17957
0
    nd.hash_index = static_cast<uint32_t>(r.hashes.size());
17958
0
    r.hashes.push_back(h);
17959
0
  }
17960
0
}
17961
17962
// Pure-leaf edge encoding, last: a child that is a pure leaf (terminal
17963
// route only) is encoded as -2 - route directly in the edge, so the walk
17964
// finishes or dead-ends there without loading the leaf node. -1 keeps
17965
// meaning "absent" for param_child.
17966
0
void encode_leaf_shortcuts(builder_tables& r) {
17967
0
  auto pure_leaf = [&](int32_t ni) {
17968
0
    const node_record& nd = r.nodes[static_cast<size_t>(ni)];
17969
0
    return nd.n_static == 0 && nd.param_child < 0 && nd.wild_route < 0 &&
17970
0
           nd.terminal_route >= 0;
17971
0
  };
17972
0
  for (auto& e : r.edges) {
17973
0
    if (pure_leaf(e.node)) {
17974
0
      e.node = -2 - r.nodes[static_cast<size_t>(e.node)].terminal_route;
17975
0
    }
17976
0
  }
17977
0
  for (auto& nd : r.nodes) {
17978
0
    if (nd.param_child >= 0 && pure_leaf(nd.param_child)) {
17979
0
      nd.param_child =
17980
0
          -2 - r.nodes[static_cast<size_t>(nd.param_child)].terminal_route;
17981
0
    }
17982
0
  }
17983
0
}
17984
17985
// Segment table: every non-regexp route's segments (kind plus literal text
17986
// in the blob), so the sequential fallback beyond the fast-path limits can
17987
// match any route without the compiler's types; for regexp routes, the
17988
// anchored literal prefix the matcher checks before running the provider.
17989
void build_segment_table(builder_tables& r,
17990
0
                         const std::vector<route_info>& routes) {
17991
0
  for (size_t i = 0; i < routes.size(); i++) {
17992
0
    const route_info& rt = routes[i];
17993
0
    route_record& rm = r.routes[i];
17994
0
    rm.segment_first = static_cast<uint32_t>(r.segments.size());
17995
0
    rm.segment_count = static_cast<uint32_t>(rt.segments.size());
17996
0
    for (const route_segment& s : rt.segments) {
17997
0
      segment_record sr{};
17998
0
      sr.kind = static_cast<uint8_t>(s.kind);
17999
0
      if (s.kind == segment_kind::literal) {
18000
0
        sr.text_offset = static_cast<uint32_t>(r.blob.size());
18001
0
        sr.text_length = static_cast<uint32_t>(s.text.size());
18002
0
        r.blob.insert(r.blob.end(), s.text.begin(), s.text.end());
18003
0
      }
18004
0
      r.segments.push_back(sr);
18005
0
    }
18006
0
  }
18007
0
}
18008
18009
// Could some pathname match both a fast-path route `w` (full segment
18010
// information) and route `c`? Conservative: true unless a literal conflict
18011
// or a segment-count conflict proves otherwise. For a regexp-mode `c`,
18012
// segments are what approximate_kind_sequence could certify (see there);
18013
// has_wildcard means the input needs at least segments.size() segments
18014
// rather than exactly that many.
18015
0
bool co_matchable(const route_info& w, const route_info& c) noexcept {
18016
0
  const bool c_regexp = c.mode == route_mode::regexp;
18017
0
  const size_t wn = w.segments.size();
18018
0
  const size_t cn = c.segments.size();
18019
0
  constexpr size_t unbounded = ~size_t{0};
18020
  // Segment counts each route accepts: [min, max].
18021
0
  const size_t w_max = w.has_wildcard ? unbounded : wn;
18022
0
  const size_t c_max = c.has_wildcard ? unbounded : cn;
18023
0
  if ((wn > cn ? wn : cn) > (w_max < c_max ? w_max : c_max)) {
18024
0
    return false;
18025
0
  }
18026
  // Positions both routes constrain (a safe wildcard segment constrains
18027
  // nothing; a regexp route's segments are all constraining).
18028
0
  const size_t w_fixed = w.has_wildcard ? wn - 1 : wn;
18029
0
  const size_t c_fixed = (!c_regexp && c.has_wildcard) ? cn - 1 : cn;
18030
0
  const size_t upto = w_fixed < c_fixed ? w_fixed : c_fixed;
18031
0
  for (size_t j = 0; j < upto; j++) {
18032
0
    const route_segment& ws = w.segments[j];
18033
0
    const route_segment& cs = c.segments[j];
18034
0
    if (ws.kind == segment_kind::literal && cs.kind == segment_kind::literal) {
18035
0
      if (ws.text != cs.text) {
18036
0
        return false;
18037
0
      }
18038
0
    } else if (ws.kind == segment_kind::literal &&
18039
0
               cs.kind == segment_kind::param) {
18040
0
      if (ws.text.empty()) {
18041
0
        return false;  // params never bind an empty segment
18042
0
      }
18043
0
    } else if (ws.kind == segment_kind::param &&
18044
0
               cs.kind == segment_kind::literal) {
18045
0
      if (cs.text.empty()) {
18046
0
        return false;
18047
0
      }
18048
0
    }
18049
0
  }
18050
0
  return true;
18051
0
}
18052
18053
// Auxiliary routes: those the trie cannot answer for (regexp mode and
18054
// sequential mode), in insertion order, followed by one challenger range per
18055
// trie route: the auxiliary routes that outrank it AND could match the same
18056
// input. After a fast-path hit only the winner's challengers are tested
18057
// (usually none).
18058
0
void build_aux_table(builder_tables& r, const std::vector<route_info>& routes) {
18059
0
  std::vector<uint32_t> aux_all;
18060
0
  for (size_t i = 0; i < routes.size(); i++) {
18061
0
    if (routes[i].mode != route_mode::trie) {
18062
0
      aux_all.push_back(static_cast<uint32_t>(i));
18063
0
    }
18064
0
  }
18065
0
  r.aux = aux_all;
18066
0
  r.n_aux_all = static_cast<uint32_t>(aux_all.size());
18067
0
  for (size_t w = 0; w < routes.size(); w++) {
18068
0
    const route_info& winner = routes[w];
18069
0
    if (winner.mode != route_mode::trie) {
18070
0
      continue;  // never a fast-path winner
18071
0
    }
18072
0
    route_record& rm = r.routes[w];
18073
0
    rm.challenger_first = static_cast<uint32_t>(r.aux.size());
18074
0
    for (const uint32_t c : aux_all) {
18075
0
      if (route_outranks(routes[c], c, winner, w) &&
18076
0
          co_matchable(winner, routes[c])) {
18077
0
        r.aux.push_back(c);
18078
0
      }
18079
0
    }
18080
0
    rm.challenger_count =
18081
0
        static_cast<uint32_t>(r.aux.size()) - rm.challenger_first;
18082
0
  }
18083
0
}
18084
18085
// Packs every table into one arena, each section 8-byte aligned, and
18086
// records the section offsets. The blob gets 8 bytes of zero padding so
18087
// short key windows can always be loaded whole.
18088
0
compiled_routes pack_arena(builder_tables& r) {
18089
0
  compiled_routes out{};
18090
0
  r.blob.insert(r.blob.end(), 8, '\0');
18091
0
  size_t total = 0;
18092
0
  const auto reserve = [&](size_t bytes) {
18093
0
    const size_t offset = total;
18094
0
    total += (bytes + 7) & ~size_t{7};
18095
0
    return static_cast<uint32_t>(offset);
18096
0
  };
18097
0
  const auto bytes_of = [](const auto& v) { return v.size() * sizeof(v[0]); };
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<ada::url_pattern_list_detail::node_record, std::__1::allocator<ada::url_pattern_list_detail::node_record> > >(std::__1::vector<ada::url_pattern_list_detail::node_record, std::__1::allocator<ada::url_pattern_list_detail::node_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<ada::url_pattern_list_detail::hash_record, std::__1::allocator<ada::url_pattern_list_detail::hash_record> > >(std::__1::vector<ada::url_pattern_list_detail::hash_record, std::__1::allocator<ada::url_pattern_list_detail::hash_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<ada::url_pattern_list_detail::edge_record, std::__1::allocator<ada::url_pattern_list_detail::edge_record> > >(std::__1::vector<ada::url_pattern_list_detail::edge_record, std::__1::allocator<ada::url_pattern_list_detail::edge_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<char, std::__1::allocator<char> > >(std::__1::vector<char, std::__1::allocator<char> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<ada::url_pattern_list_detail::route_record, std::__1::allocator<ada::url_pattern_list_detail::route_record> > >(std::__1::vector<ada::url_pattern_list_detail::route_record, std::__1::allocator<ada::url_pattern_list_detail::route_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<ada::url_pattern_list_detail::segment_record, std::__1::allocator<ada::url_pattern_list_detail::segment_record> > >(std::__1::vector<ada::url_pattern_list_detail::segment_record, std::__1::allocator<ada::url_pattern_list_detail::segment_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > >(std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_0::operator()<std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > >(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) const
18098
0
  out.nodes_offset = reserve(bytes_of(r.nodes));
18099
0
  out.hashes_offset = reserve(bytes_of(r.hashes));
18100
0
  out.edges_offset = reserve(bytes_of(r.edges));
18101
0
  out.slots_offset = reserve(bytes_of(r.slots));
18102
0
  out.blob_offset = reserve(bytes_of(r.blob));
18103
0
  out.routes_offset = reserve(bytes_of(r.routes));
18104
0
  out.segments_offset = reserve(bytes_of(r.segments));
18105
0
  out.aux_offset = reserve(bytes_of(r.aux));
18106
0
  out.root_index_offset = reserve(bytes_of(r.root_index));
18107
0
  out.arena.assign(total, 0);
18108
0
  const auto place = [&](uint32_t offset, const auto& v) {
18109
0
    if (!v.empty()) {
18110
0
      std::memcpy(out.arena.data() + offset, v.data(), v.size() * sizeof(v[0]));
18111
0
    }
18112
0
  };
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<ada::url_pattern_list_detail::node_record, std::__1::allocator<ada::url_pattern_list_detail::node_record> > >(unsigned int, std::__1::vector<ada::url_pattern_list_detail::node_record, std::__1::allocator<ada::url_pattern_list_detail::node_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<ada::url_pattern_list_detail::hash_record, std::__1::allocator<ada::url_pattern_list_detail::hash_record> > >(unsigned int, std::__1::vector<ada::url_pattern_list_detail::hash_record, std::__1::allocator<ada::url_pattern_list_detail::hash_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<ada::url_pattern_list_detail::edge_record, std::__1::allocator<ada::url_pattern_list_detail::edge_record> > >(unsigned int, std::__1::vector<ada::url_pattern_list_detail::edge_record, std::__1::allocator<ada::url_pattern_list_detail::edge_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > >(unsigned int, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<char, std::__1::allocator<char> > >(unsigned int, std::__1::vector<char, std::__1::allocator<char> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<ada::url_pattern_list_detail::route_record, std::__1::allocator<ada::url_pattern_list_detail::route_record> > >(unsigned int, std::__1::vector<ada::url_pattern_list_detail::route_record, std::__1::allocator<ada::url_pattern_list_detail::route_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<ada::url_pattern_list_detail::segment_record, std::__1::allocator<ada::url_pattern_list_detail::segment_record> > >(unsigned int, std::__1::vector<ada::url_pattern_list_detail::segment_record, std::__1::allocator<ada::url_pattern_list_detail::segment_record> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > >(unsigned int, std::__1::vector<unsigned int, std::__1::allocator<unsigned int> > const&) const
Unexecuted instantiation: url_pattern.cc:auto ada::url_pattern_list_compiler::(anonymous namespace)::pack_arena(ada::url_pattern_list_compiler::(anonymous namespace)::builder_tables&)::$_1::operator()<std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > >(unsigned int, std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&) const
18113
0
  place(out.nodes_offset, r.nodes);
18114
0
  place(out.hashes_offset, r.hashes);
18115
0
  place(out.edges_offset, r.edges);
18116
0
  place(out.slots_offset, r.slots);
18117
0
  place(out.blob_offset, r.blob);
18118
0
  place(out.routes_offset, r.routes);
18119
0
  place(out.segments_offset, r.segments);
18120
0
  place(out.aux_offset, r.aux);
18121
0
  place(out.root_index_offset, r.root_index);
18122
0
  out.n_routes = static_cast<uint32_t>(r.routes.size());
18123
0
  out.n_aux_all = r.n_aux_all;
18124
0
  return out;
18125
0
}
18126
18127
// Fills route.kind_sequence / kind_length from route.segments.
18128
0
void compute_kind_sequence(route_info& route) noexcept {
18129
0
  uint64_t seq = 0;
18130
0
  const size_t n = route.segments.size();
18131
0
  for (size_t j = 0; j < n && j < 32; j++) {
18132
0
    seq |= static_cast<uint64_t>(route.segments[j].kind) << (62 - 2 * j);
18133
0
  }
18134
0
  route.kind_sequence = seq;
18135
0
  route.kind_length = static_cast<uint8_t>(n < 255 ? n : 255);
18136
0
}
18137
18138
}  // namespace
18139
18140
// ---- compiler entry points -------------------------------------------------
18141
18142
bool classify_parts(const std::vector<url_pattern_part>& parts,
18143
                    std::vector<route_segment>& segments,
18144
0
                    std::vector<std::string>& group_names) {
18145
0
  segments.clear();
18146
0
  group_names.clear();
18147
0
  bool started = false;        // leading '/' consumed
18148
0
  bool group_open = false;     // the open segment slot is a group
18149
0
  bool wildcard_seen = false;  // a "*" segment was consumed (must stay last)
18150
0
  std::string literal;
18151
0
  const auto close_segment = [&]() {
18152
0
    if (!group_open) {
18153
0
      segments.push_back(route_segment{segment_kind::literal, literal});
18154
0
    }
18155
0
    literal.clear();
18156
0
    group_open = false;
18157
0
  };
18158
0
  const auto process_text = [&](std::string_view text) {
18159
0
    for (const char c : text) {
18160
0
      if (wildcard_seen) {
18161
0
        return false;  // nothing may follow a "*" segment
18162
0
      }
18163
0
      if (c == '/') {
18164
0
        if (!started) {
18165
0
          started = true;
18166
0
        } else {
18167
0
          close_segment();
18168
0
        }
18169
0
      } else {
18170
0
        if (!started || group_open) {
18171
0
          return false;  // text before '/', or suffix text after a group
18172
0
        }
18173
0
        literal += c;
18174
0
      }
18175
0
    }
18176
0
    return true;
18177
0
  };
18178
0
  for (const url_pattern_part& part : parts) {
18179
0
    if (part.type == url_pattern_part_type::FIXED_TEXT &&
18180
0
        part.modifier == url_pattern_part_modifier::none) {
18181
0
      if (!process_text(part.prefix) || !process_text(part.value) ||
18182
0
          !process_text(part.suffix)) {
18183
0
        return false;
18184
0
      }
18185
0
    } else if ((part.type == url_pattern_part_type::SEGMENT_WILDCARD ||
18186
0
                part.type == url_pattern_part_type::FULL_WILDCARD) &&
18187
0
               part.modifier == url_pattern_part_modifier::none &&
18188
0
               part.suffix.empty()) {
18189
0
      if (wildcard_seen) {
18190
0
        return false;
18191
0
      }
18192
0
      if (part.prefix == "/") {
18193
0
        if (!started) {
18194
0
          started = true;
18195
0
        } else {
18196
0
          close_segment();
18197
0
        }
18198
0
      } else if (part.prefix.empty()) {
18199
        // The group must occupy a whole, freshly opened segment slot.
18200
0
        if (!started || group_open || !literal.empty()) {
18201
0
          return false;
18202
0
        }
18203
0
      } else {
18204
0
        return false;  // group not aligned on a '/' boundary
18205
0
      }
18206
0
      const bool is_wildcard =
18207
0
          part.type == url_pattern_part_type::FULL_WILDCARD;
18208
0
      segments.push_back(route_segment{
18209
0
          is_wildcard ? segment_kind::wildcard : segment_kind::param,
18210
0
          part.name});
18211
0
      group_names.push_back(part.name);
18212
0
      group_open = true;
18213
0
      wildcard_seen = is_wildcard;
18214
0
    } else {
18215
0
      return false;  // regexp group or a "?" / "+" / "*" modifier
18216
0
    }
18217
0
  }
18218
0
  if (!started) {
18219
    // Only the empty pattern (zero parts) is representable without a leading
18220
    // '/': it matches exactly the empty pathname.
18221
0
    return parts.empty();
18222
0
  }
18223
0
  close_segment();
18224
0
  return true;
18225
0
}
18226
18227
0
void finalize_route(route_info& route) noexcept {
18228
0
  compute_kind_sequence(route);
18229
0
  route.all_literal = true;
18230
0
  route.has_wildcard = false;
18231
0
  size_t n_params = 0;
18232
  // A trie edge keeps its literal segment length in edge_record::key_length, a
18233
  // uint16_t. A literal longer than that wraps around, so the trie would match
18234
  // a shorter, truncated length (e.g. a 65536-byte segment becomes length 0 and
18235
  // matches an empty segment). Keep such a route out of the trie and let the
18236
  // sequential matcher, which compares the whole segment, answer it.
18237
0
  bool literal_fits_edge = true;
18238
0
  for (const route_segment& s : route.segments) {
18239
0
    if (s.kind != segment_kind::literal) {
18240
0
      route.all_literal = false;
18241
0
      if (s.kind == segment_kind::param) {
18242
0
        n_params++;
18243
0
      } else {
18244
0
        route.has_wildcard = true;
18245
0
      }
18246
0
    } else if (s.text.size() > std::numeric_limits<uint16_t>::max()) {
18247
0
      literal_fits_edge = false;
18248
0
    }
18249
0
  }
18250
0
  const size_t n_captures = n_params + (route.has_wildcard ? 1 : 0);
18251
0
  const bool trie_safe = !route.segments.empty() &&
18252
0
                         route.segments.size() <= max_trie_pattern_segments &&
18253
0
                         n_captures <= max_captures_per_route &&
18254
0
                         literal_fits_edge;
18255
0
  route.mode = trie_safe ? route_mode::trie : route_mode::sequential;
18256
0
}
18257
18258
void approximate_kind_sequence(const std::vector<url_pattern_part>& parts,
18259
0
                               route_info& route) {
18260
0
  std::vector<uint8_t> kinds;
18261
  // The route's segment shape, as far as it is known: literal segments carry
18262
  // their text, opaque ones (a ":name" group, alone or mixed with text) are
18263
  // params. Exact while every group is a ":name" segment wildcard, which
18264
  // cannot match '/': then the segment count and every literal position are
18265
  // certain. A custom "(...)" group, a "*" or a modifier can span segments,
18266
  // so from there on nothing is known and only the anchored literal prefix
18267
  // before it is kept.
18268
0
  std::vector<route_segment> shape;
18269
0
  std::string literal;
18270
0
  bool started = false;
18271
0
  bool open = false;
18272
0
  bool leading_slash = false;  // the pattern is anchored at a '/'
18273
0
  bool exact = true;           // no part can span a segment boundary
18274
0
  bool tail_known = true;      // segments after the last closed one are known
18275
0
  uint8_t current = 0;
18276
  // Closes the open segment; `complete` is true only when a '/' of fixed
18277
  // text closed it, i.e. the segment is exactly what was accumulated.
18278
0
  const auto close = [&](bool complete) {
18279
0
    if (open) {
18280
0
      kinds.push_back(current);
18281
0
      if (complete || exact) {
18282
0
        shape.push_back(current == 0
18283
0
                            ? route_segment{segment_kind::literal, literal}
18284
0
                            : route_segment{segment_kind::param, {}});
18285
0
      } else {
18286
0
        tail_known = false;
18287
0
      }
18288
0
      open = false;
18289
0
      current = 0;
18290
0
    }
18291
0
    literal.clear();
18292
0
  };
18293
0
  const auto process_text = [&](std::string_view text) {
18294
0
    for (const char c : text) {
18295
0
      if (c == '/') {
18296
0
        if (started) {
18297
0
          close(true);
18298
0
        } else {
18299
0
          leading_slash = true;
18300
0
        }
18301
0
        started = true;
18302
0
        open = true;
18303
0
        current = 0;
18304
0
      } else {
18305
0
        if (!started) {
18306
0
          started = true;
18307
0
        }
18308
0
        if (!open) {
18309
0
          open = true;
18310
0
          current = 0;
18311
0
        }
18312
0
        literal += c;
18313
0
      }
18314
0
    }
18315
0
  };
18316
0
  const auto add_group = [&](uint8_t kind) {
18317
0
    if (!open) {
18318
0
      started = true;
18319
0
      open = true;
18320
0
      current = 0;
18321
0
    }
18322
0
    current = current < kind ? kind : current;
18323
0
  };
18324
0
  for (const url_pattern_part& part : parts) {
18325
0
    if (part.type == url_pattern_part_type::FULL_WILDCARD ||
18326
0
        part.modifier != url_pattern_part_modifier::none) {
18327
      // A greedy or modified group can span segments: treat the rest of the
18328
      // route as a wildcard tail and stop. A "/" prefix closes the previous
18329
      // segment only when this part must occur. An optional ("?") or
18330
      // zero-or-more ("*") part, prefix included, may be absent, so the text
18331
      // after it stays in the same segment ("/reports{/:id}?.json" matches
18332
      // "/reports.json"). Treating that "/" as a definite boundary certified
18333
      // a segment the input does not have, and the shape check rejected the
18334
      // match before the provider ran.
18335
0
      exact = false;
18336
0
      const bool must_occur =
18337
0
          part.modifier != url_pattern_part_modifier::optional &&
18338
0
          part.modifier != url_pattern_part_modifier::zero_or_more;
18339
0
      close(must_occur && part.prefix == "/");
18340
0
      tail_known = false;
18341
0
      kinds.push_back(2);
18342
0
      break;
18343
0
    }
18344
0
    if (part.type == url_pattern_part_type::FIXED_TEXT) {
18345
0
      process_text(part.value);
18346
0
    } else {  // SEGMENT_WILDCARD or REGEXP, modifier none
18347
0
      if (part.type == url_pattern_part_type::REGEXP) {
18348
0
        exact = false;  // a custom group may match '/'
18349
0
      }
18350
0
      process_text(part.prefix);
18351
0
      add_group(1);
18352
0
      process_text(part.suffix);
18353
0
    }
18354
0
  }
18355
0
  close(exact);
18356
0
  uint64_t seq = 0;
18357
0
  for (size_t j = 0; j < kinds.size() && j < 32; j++) {
18358
0
    seq |= static_cast<uint64_t>(kinds[j]) << (62 - 2 * j);
18359
0
  }
18360
0
  route.kind_sequence = seq;
18361
0
  route.kind_length =
18362
0
      static_cast<uint8_t>(kinds.size() < 255 ? kinds.size() : 255);
18363
0
  route.mode = route_mode::regexp;
18364
0
  route.all_literal = false;
18365
0
  route.segments.clear();
18366
0
  if (!leading_slash) {
18367
    // Not anchored at '/': nothing about the segments is known.
18368
0
    route.has_wildcard = true;
18369
0
    return;
18370
0
  }
18371
  // has_wildcard here means "the tail is unconstrained": the input needs at
18372
  // least segments.size() segments; otherwise exactly that many.
18373
0
  route.has_wildcard = !(exact && tail_known);
18374
0
  if (route.has_wildcard) {
18375
    // Keep only the anchored literal prefix.
18376
0
    size_t n_prefix = 0;
18377
0
    while (n_prefix < shape.size() &&
18378
0
           shape[n_prefix].kind == segment_kind::literal) {
18379
0
      n_prefix++;
18380
0
    }
18381
0
    shape.resize(n_prefix);
18382
0
  }
18383
0
  route.segments = std::move(shape);
18384
0
}
18385
18386
0
compiled_routes compile_route_set(std::vector<route_info>& routes) {
18387
0
  builder_tables r{};
18388
0
  const std::vector<transient_node> t = build_trie(routes);
18389
0
  compile_route_records(r, routes);
18390
0
  const std::vector<int32_t> order = layout_nodes(r, t);
18391
0
  compile_dispatch(r, t, order);
18392
0
  encode_leaf_shortcuts(r);  // last: must not confuse the stages above
18393
0
  build_segment_table(r, routes);
18394
0
  build_aux_table(r, routes);
18395
0
  compiled_routes out = pack_arena(r);
18396
0
  out.group_names.resize(routes.size());
18397
0
  for (size_t i = 0; i < routes.size(); i++) {
18398
0
    if (routes[i].mode != route_mode::regexp) {
18399
0
      out.group_names[i] = routes[i].group_names;
18400
0
    }
18401
0
  }
18402
0
  return out;
18403
0
}
18404
18405
}  // namespace ada::url_pattern_list_compiler
18406
18407
namespace ada::url_pattern_list_detail {
18408
18409
tl::expected<compiled_routes, errors> compile_pathname_patterns(
18410
0
    std::span<const std::string> patterns, bool ignore_case) {
18411
0
  namespace compiler = url_pattern_list_compiler;
18412
0
  std::vector<compiler::route_info> routes;
18413
0
  routes.reserve(patterns.size());
18414
0
  for (const std::string& pattern : patterns) {
18415
    // The pattern side goes through ada's own URLPattern machinery: the
18416
    // pattern parser tokenizes and canonicalizes exactly as a URLPattern
18417
    // pathname component would.
18418
0
    auto options = url_pattern_compile_component_options::PATHNAME;
18419
0
    auto part_list = url_pattern_helpers::parse_pattern_string(
18420
0
        pattern, options, url_pattern_helpers::canonicalize_pathname);
18421
0
    if (!part_list) {
18422
0
      return tl::unexpected(part_list.error());
18423
0
    }
18424
0
    compiler::route_info route{};
18425
0
    if (compiler::classify_parts(*part_list, route.segments,
18426
0
                                 route.group_names)) {
18427
0
      compiler::finalize_route(route);
18428
0
    } else {
18429
      // The pattern needs URLPattern regexp semantics: the caller compiles
18430
      // it as a pathname component through the provider; it participates
18431
      // in the priority order via its approximated kind sequence.
18432
0
      compiler::approximate_kind_sequence(*part_list, route);
18433
0
    }
18434
0
    if (ignore_case) {
18435
      // The compiled literals are ASCII-folded; the matcher folds the input
18436
      // the same way.
18437
0
      for (compiler::route_segment& s : route.segments) {
18438
0
        if (s.kind == compiler::segment_kind::literal) {
18439
0
          ascii_fold(s.text.data(), static_cast<uint32_t>(s.text.size()),
18440
0
                     s.text.data());
18441
0
        }
18442
0
      }
18443
0
    }
18444
0
    routes.push_back(std::move(route));
18445
0
  }
18446
0
  compiled_routes compiled = compiler::compile_route_set(routes);
18447
0
  compiled.ignore_case = ignore_case ? 1 : 0;
18448
0
  return compiled;
18449
0
}
18450
18451
namespace {
18452
18453
// Literal-segment compare against the blob, folding the input on request
18454
// (the blob text is already folded).
18455
bool literal_equals(std::string_view s, const char* text, uint32_t length,
18456
0
                    bool fold_input) noexcept {
18457
0
  if (s.size() != length) {
18458
0
    return false;
18459
0
  }
18460
0
  if (!fold_input) {
18461
0
    return s.size() == 0 || std::memcmp(s.data(), text, s.size()) == 0;
18462
0
  }
18463
0
  for (size_t i = 0; i < s.size(); i++) {
18464
0
    const uint8_t c = static_cast<uint8_t>(s[i]);
18465
0
    const char folded =
18466
0
        static_cast<char>(c | ((c >= 'A' && c <= 'Z') ? 0x20u : 0u));
18467
0
    if (folded != text[i]) {
18468
0
      return false;
18469
0
    }
18470
0
  }
18471
0
  return true;
18472
0
}
18473
18474
}  // namespace
18475
18476
// Kept out of line on purpose: inlined into the walk, this loop cost the
18477
// static and ":param" paths, which never run it, about 5 ns through register
18478
// allocation; as a call it costs only wildcard hits. It lives in this
18479
// translation unit rather than the header because MSVC's ada_never_inline
18480
// expands to __declspec(noinline) with no inline linkage, so a definition in
18481
// the header is emitted in every translation unit and the link fails.
18482
//
18483
// On AArch64 whole 16-byte blocks go through NEON (a running byte minimum);
18484
// the rest is SWAR, 8 bytes per step: "some byte is below 0x20" ("hasless"
18485
// of Bit Twiddling Hacks) is exact as a yes/no answer, because a borrow can
18486
// only leave a lane that itself qualifies. Only a tail holding a control
18487
// byte gets the exact byte check.
18488
0
bool wildcard_tail_ok(const char* p, uint32_t n) noexcept {
18489
0
  constexpr uint64_t spaces = 0x2020202020202020ull;
18490
0
  constexpr uint64_t highs = 0x8080808080808080ull;
18491
0
  const auto below_space = [](uint64_t x) noexcept {
18492
0
    return (x - spaces) & ~x & highs;
18493
0
  };
18494
0
  uint64_t control = 0;
18495
0
  uint32_t i = 0;
18496
#if ADA_NEON
18497
  if (n >= 16) {
18498
    uint8x16_t lowest = vdupq_n_u8(0xFF);
18499
    for (; i + 16 <= n; i += 16) {
18500
      lowest =
18501
          vminq_u8(lowest, vld1q_u8(reinterpret_cast<const uint8_t*>(p + i)));
18502
    }
18503
    control = vminvq_u8(lowest) < 0x20 ? 1 : 0;
18504
  }
18505
#endif
18506
0
  for (; i + 8 <= n; i += 8) {
18507
0
    control |= below_space(load8_le(p + i));
18508
0
  }
18509
0
  if (i < n) {  // 1..7 bytes, padded with spaces
18510
0
    control |= below_space(gather_le(p + i, n - i) |
18511
0
                           (spaces & ~low_bytes_mask(n - i)));
18512
0
  }
18513
0
  if (control == 0) {
18514
0
    return true;
18515
0
  }
18516
0
  for (uint32_t j = 0; j < n; j++) {
18517
0
    if (p[j] == '\n' || p[j] == '\r') {
18518
0
      return false;
18519
0
    }
18520
0
  }
18521
0
  return true;
18522
0
}
18523
18524
bool match_regexp_shape(const compiled_routes& r, uint32_t route,
18525
0
                        std::string_view pathname, bool fold_input) noexcept {
18526
0
  const route_record& rt = r.section<route_record>(r.routes_offset)[route];
18527
0
  const segment_record* segs =
18528
0
      r.section<segment_record>(r.segments_offset) + rt.segment_first;
18529
0
  const char* blob = r.section<char>(r.blob_offset);
18530
0
  if (rt.segment_count == 0 && rt.wild != 0) {
18531
0
    return true;  // nothing is known about the route's shape
18532
0
  }
18533
0
  if (pathname.empty() || pathname[0] != '/') {
18534
0
    return false;  // a known shape always starts with '/'
18535
0
  }
18536
0
  size_t seg_start = 1;
18537
0
  for (uint32_t si = 0; si < rt.segment_count; si++) {
18538
0
    if (seg_start > pathname.size()) {
18539
0
      return false;  // fewer segments than the shape
18540
0
    }
18541
0
    const size_t slash = pathname.find('/', seg_start);
18542
0
    const size_t seg_end =
18543
0
        slash == std::string_view::npos ? pathname.size() : slash;
18544
0
    const std::string_view s(pathname.data() + seg_start, seg_end - seg_start);
18545
0
    if (segs[si].kind == 0) {  // literal
18546
0
      if (!literal_equals(s, blob + segs[si].text_offset, segs[si].text_length,
18547
0
                          fold_input)) {
18548
0
        return false;
18549
0
      }
18550
0
    } else if (s.empty()) {
18551
0
      return false;  // a ":name" group, mixed or not, never binds ""
18552
0
    }
18553
0
    seg_start = seg_end + 1;
18554
0
  }
18555
  // An exact shape admits no further segments.
18556
0
  return rt.wild != 0 || seg_start == pathname.size() + 1;
18557
0
}
18558
18559
bool match_route_sequential(const compiled_routes& r, uint32_t route,
18560
                            std::string_view pathname, bool fold_input,
18561
0
                            engine_result& result) noexcept {
18562
0
  using url_pattern_list_limits::max_captures_per_route;
18563
0
  result.capture_count = 0;
18564
0
  result.captures_truncated = false;
18565
0
  const route_record& rt = r.section<route_record>(r.routes_offset)[route];
18566
0
  const segment_record* segs =
18567
0
      r.section<segment_record>(r.segments_offset) + rt.segment_first;
18568
0
  const char* blob = r.section<char>(r.blob_offset);
18569
0
  const size_t n_pattern = rt.segment_count;
18570
0
  if (n_pattern == 0) {
18571
0
    return pathname.empty();  // the empty pattern matches only ""
18572
0
  }
18573
0
  if (pathname.empty() || pathname[0] != '/') {
18574
0
    return false;
18575
0
  }
18576
0
  const bool wild = rt.wild != 0;  // wildcard is always the last segment
18577
0
  const size_t n_fixed = wild ? n_pattern - 1 : n_pattern;
18578
0
  uint32_t total_captures = 0;
18579
0
  const auto add_capture = [&](size_t offset, size_t length) {
18580
0
    if (total_captures < max_captures_per_route) {
18581
0
      result.captures[total_captures] = {static_cast<uint32_t>(offset),
18582
0
                                         static_cast<uint32_t>(length)};
18583
0
    } else {
18584
0
      result.captures_truncated = true;
18585
0
    }
18586
0
    total_captures++;
18587
0
  };
18588
0
  size_t seg_start = 1;
18589
0
  for (size_t si = 0; si < n_fixed; si++) {
18590
0
    if (seg_start > pathname.size()) {
18591
0
      return false;  // the input has fewer segments than the pattern
18592
0
    }
18593
0
    const size_t slash = pathname.find('/', seg_start);
18594
0
    const size_t seg_end =
18595
0
        slash == std::string_view::npos ? pathname.size() : slash;
18596
    // seg_start <= pathname.size() was checked above, so this is in range
18597
    // (spelled without substr to keep the function provably non-throwing).
18598
0
    const std::string_view s(pathname.data() + seg_start, seg_end - seg_start);
18599
0
    if (segs[si].kind == 0) {  // literal
18600
0
      if (!literal_equals(s, blob + segs[si].text_offset, segs[si].text_length,
18601
0
                          fold_input)) {
18602
0
        return false;
18603
0
      }
18604
0
    } else {  // param: binds one non-empty segment
18605
0
      if (s.empty()) {
18606
0
        return false;
18607
0
      }
18608
0
      add_capture(seg_start, s.size());
18609
0
    }
18610
0
    seg_start = seg_end + 1;
18611
0
  }
18612
0
  if (wild) {
18613
0
    if (seg_start > pathname.size()) {
18614
0
      return false;  // the wildcard still needs its (possibly empty) segment
18615
0
    }
18616
    // "(.*)" does not match a line terminator (see wildcard_tail_ok).
18617
0
    if (pathname.find_first_of("\n\r", seg_start) != std::string_view::npos) {
18618
0
      return false;
18619
0
    }
18620
0
    add_capture(seg_start, pathname.size() - seg_start);
18621
0
  } else if (seg_start != pathname.size() + 1) {
18622
0
    return false;  // the input has more segments than the pattern
18623
0
  }
18624
0
  result.capture_count = total_captures < max_captures_per_route
18625
0
                             ? total_captures
18626
0
                             : max_captures_per_route;
18627
0
  return true;
18628
0
}
18629
18630
}  // namespace ada::url_pattern_list_detail
18631
#endif  // ADA_INCLUDE_URL_PATTERN
18632
/* end file src/url_pattern_list.cpp */
18633
#endif
18634
#endif  // ADA_INCLUDE_URL_PATTERN
18635
18636
/* begin file src/ada_c.cpp */
18637
// NOLINTBEGIN(bugprone-exception-escape,
18638
// bugprone-suspicious-stringview-data-usage)
18639
18640
0
ada::result<ada::url_aggregator>& get_instance(void* result) noexcept {
18641
0
  return *(ada::result<ada::url_aggregator>*)result;
18642
0
}
18643
18644
extern "C" {
18645
typedef void* ada_url;
18646
typedef void* ada_url_search_params;
18647
typedef void* ada_strings;
18648
typedef void* ada_url_search_params_keys_iter;
18649
typedef void* ada_url_search_params_values_iter;
18650
typedef void* ada_url_search_params_entries_iter;
18651
18652
struct ada_string {
18653
  const char* data;
18654
  size_t length;
18655
};
18656
18657
struct ada_owned_string {
18658
  const char* data;
18659
  size_t length;
18660
};
18661
18662
struct ada_string_pair {
18663
  ada_string key;
18664
  ada_string value;
18665
};
18666
18667
0
ada_string ada_string_create(const char* data, size_t length) {
18668
0
  ada_string out{};
18669
0
  out.data = data;
18670
0
  out.length = length;
18671
0
  return out;
18672
0
}
18673
18674
struct ada_url_components {
18675
  /*
18676
   * By using 32-bit integers, we implicitly assume that the URL string
18677
   * cannot exceed 4 GB.
18678
   *
18679
   * https://user:pass@example.com:1234/foo/bar?baz#quux
18680
   *       |     |    |          | ^^^^|       |   |
18681
   *       |     |    |          | |   |       |   `----- hash_start
18682
   *       |     |    |          | |   |       `--------- search_start
18683
   *       |     |    |          | |   `----------------- pathname_start
18684
   *       |     |    |          | `--------------------- port
18685
   *       |     |    |          `----------------------- host_end
18686
   *       |     |    `---------------------------------- host_start
18687
   *       |     `--------------------------------------- username_end
18688
   *       `--------------------------------------------- protocol_end
18689
   */
18690
  uint32_t protocol_end;
18691
  /**
18692
   * Username end is not `omitted` by default (-1) to make username and password
18693
   * getters less costly to implement.
18694
   */
18695
  uint32_t username_end;
18696
  uint32_t host_start;
18697
  uint32_t host_end;
18698
  uint32_t port;
18699
  uint32_t pathname_start;
18700
  uint32_t search_start;
18701
  uint32_t hash_start;
18702
};
18703
18704
0
ada_url ada_parse(const char* input, size_t length) noexcept {
18705
0
  return new ada::result<ada::url_aggregator>(
18706
0
      ada::parse<ada::url_aggregator>(std::string_view(input, length)));
18707
0
}
18708
18709
ada_url ada_parse_with_base(const char* input, size_t input_length,
18710
0
                            const char* base, size_t base_length) noexcept {
18711
0
  auto base_out =
18712
0
      ada::parse<ada::url_aggregator>(std::string_view(base, base_length));
18713
18714
0
  if (!base_out) {
18715
0
    return new ada::result<ada::url_aggregator>(base_out);
18716
0
  }
18717
18718
0
  return new ada::result<ada::url_aggregator>(ada::parse<ada::url_aggregator>(
18719
0
      std::string_view(input, input_length), &base_out.value()));
18720
0
}
18721
18722
0
bool ada_can_parse(const char* input, size_t length) noexcept {
18723
0
  return ada::can_parse(std::string_view(input, length));
18724
0
}
18725
18726
bool ada_can_parse_with_base(const char* input, size_t input_length,
18727
0
                             const char* base, size_t base_length) noexcept {
18728
0
  std::string_view base_view(base, base_length);
18729
0
  return ada::can_parse(std::string_view(input, input_length), &base_view);
18730
0
}
18731
18732
0
void ada_free(ada_url result) noexcept {
18733
0
  auto* r = (ada::result<ada::url_aggregator>*)result;
18734
0
  delete r;
18735
0
}
18736
18737
0
ada_url ada_copy(ada_url input) noexcept {
18738
0
  ada::result<ada::url_aggregator>& r = get_instance(input);
18739
0
  return new ada::result<ada::url_aggregator>(r);
18740
0
}
18741
18742
0
bool ada_is_valid(ada_url result) noexcept {
18743
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18744
0
  return r.has_value();
18745
0
}
18746
18747
// caller must free the result with ada_free_owned_string
18748
0
ada_owned_string ada_get_origin(ada_url result) noexcept {
18749
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18750
0
  ada_owned_string owned{};
18751
0
  if (!r) {
18752
0
    owned.data = nullptr;
18753
0
    owned.length = 0;
18754
0
    return owned;
18755
0
  }
18756
0
  std::string out = r->get_origin();
18757
0
  owned.length = out.size();
18758
0
  owned.data = new char[owned.length];
18759
0
  memcpy((void*)owned.data, out.data(), owned.length);
18760
0
  return owned;
18761
0
}
18762
18763
0
void ada_free_owned_string(ada_owned_string owned) noexcept {
18764
0
  delete[] owned.data;
18765
0
}
18766
18767
0
ada_string ada_get_href(ada_url result) noexcept {
18768
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18769
0
  if (!r) {
18770
0
    return ada_string_create(nullptr, 0);
18771
0
  }
18772
0
  std::string_view out = r->get_href();
18773
0
  return ada_string_create(out.data(), out.length());
18774
0
}
18775
18776
0
ada_string ada_get_username(ada_url result) noexcept {
18777
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18778
0
  if (!r) {
18779
0
    return ada_string_create(nullptr, 0);
18780
0
  }
18781
0
  std::string_view out = r->get_username();
18782
0
  return ada_string_create(out.data(), out.length());
18783
0
}
18784
18785
0
ada_string ada_get_password(ada_url result) noexcept {
18786
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18787
0
  if (!r) {
18788
0
    return ada_string_create(nullptr, 0);
18789
0
  }
18790
0
  std::string_view out = r->get_password();
18791
0
  return ada_string_create(out.data(), out.length());
18792
0
}
18793
18794
0
ada_string ada_get_port(ada_url result) noexcept {
18795
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18796
0
  if (!r) {
18797
0
    return ada_string_create(nullptr, 0);
18798
0
  }
18799
0
  std::string_view out = r->get_port();
18800
0
  return ada_string_create(out.data(), out.length());
18801
0
}
18802
18803
0
ada_string ada_get_hash(ada_url result) noexcept {
18804
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18805
0
  if (!r) {
18806
0
    return ada_string_create(nullptr, 0);
18807
0
  }
18808
0
  std::string_view out = r->get_hash();
18809
0
  return ada_string_create(out.data(), out.length());
18810
0
}
18811
18812
0
ada_string ada_get_host(ada_url result) noexcept {
18813
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18814
0
  if (!r) {
18815
0
    return ada_string_create(nullptr, 0);
18816
0
  }
18817
0
  std::string_view out = r->get_host();
18818
0
  return ada_string_create(out.data(), out.length());
18819
0
}
18820
18821
0
ada_string ada_get_hostname(ada_url result) noexcept {
18822
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18823
0
  if (!r) {
18824
0
    return ada_string_create(nullptr, 0);
18825
0
  }
18826
0
  std::string_view out = r->get_hostname();
18827
0
  return ada_string_create(out.data(), out.length());
18828
0
}
18829
18830
0
ada_string ada_get_pathname(ada_url result) noexcept {
18831
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18832
0
  if (!r) {
18833
0
    return ada_string_create(nullptr, 0);
18834
0
  }
18835
0
  std::string_view out = r->get_pathname();
18836
0
  return ada_string_create(out.data(), out.length());
18837
0
}
18838
18839
0
ada_string ada_get_search(ada_url result) noexcept {
18840
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18841
0
  if (!r) {
18842
0
    return ada_string_create(nullptr, 0);
18843
0
  }
18844
0
  std::string_view out = r->get_search();
18845
0
  return ada_string_create(out.data(), out.length());
18846
0
}
18847
18848
0
ada_string ada_get_protocol(ada_url result) noexcept {
18849
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18850
0
  if (!r) {
18851
0
    return ada_string_create(nullptr, 0);
18852
0
  }
18853
0
  std::string_view out = r->get_protocol();
18854
0
  return ada_string_create(out.data(), out.length());
18855
0
}
18856
18857
0
uint8_t ada_get_host_type(ada_url result) noexcept {
18858
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18859
0
  if (!r) {
18860
0
    return 0;
18861
0
  }
18862
0
  return r->host_type;
18863
0
}
18864
18865
0
uint8_t ada_get_scheme_type(ada_url result) noexcept {
18866
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18867
0
  if (!r) {
18868
0
    return 0;
18869
0
  }
18870
0
  return r->type;
18871
0
}
18872
18873
0
bool ada_set_href(ada_url result, const char* input, size_t length) noexcept {
18874
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18875
0
  if (!r) {
18876
0
    return false;
18877
0
  }
18878
0
  return r->set_href(std::string_view(input, length));
18879
0
}
18880
18881
0
bool ada_set_host(ada_url result, const char* input, size_t length) noexcept {
18882
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18883
0
  if (!r) {
18884
0
    return false;
18885
0
  }
18886
0
  return r->set_host(std::string_view(input, length));
18887
0
}
18888
18889
bool ada_set_hostname(ada_url result, const char* input,
18890
0
                      size_t length) noexcept {
18891
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18892
0
  if (!r) {
18893
0
    return false;
18894
0
  }
18895
0
  return r->set_hostname(std::string_view(input, length));
18896
0
}
18897
18898
bool ada_set_protocol(ada_url result, const char* input,
18899
0
                      size_t length) noexcept {
18900
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18901
0
  if (!r) {
18902
0
    return false;
18903
0
  }
18904
0
  return r->set_protocol(std::string_view(input, length));
18905
0
}
18906
18907
bool ada_set_username(ada_url result, const char* input,
18908
0
                      size_t length) noexcept {
18909
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18910
0
  if (!r) {
18911
0
    return false;
18912
0
  }
18913
0
  return r->set_username(std::string_view(input, length));
18914
0
}
18915
18916
bool ada_set_password(ada_url result, const char* input,
18917
0
                      size_t length) noexcept {
18918
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18919
0
  if (!r) {
18920
0
    return false;
18921
0
  }
18922
0
  return r->set_password(std::string_view(input, length));
18923
0
}
18924
18925
0
bool ada_set_port(ada_url result, const char* input, size_t length) noexcept {
18926
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18927
0
  if (!r) {
18928
0
    return false;
18929
0
  }
18930
0
  return r->set_port(std::string_view(input, length));
18931
0
}
18932
18933
bool ada_set_pathname(ada_url result, const char* input,
18934
0
                      size_t length) noexcept {
18935
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18936
0
  if (!r) {
18937
0
    return false;
18938
0
  }
18939
0
  return r->set_pathname(std::string_view(input, length));
18940
0
}
18941
18942
/**
18943
 * Update the search/query of the URL.
18944
 *
18945
 * If a URL has `?` as the search value, passing empty string to this function
18946
 * does not remove the attribute. If you need to remove it, please use
18947
 * `ada_clear_search` method.
18948
 */
18949
0
void ada_set_search(ada_url result, const char* input, size_t length) noexcept {
18950
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18951
0
  if (r) {
18952
0
    r->set_search(std::string_view(input, length));
18953
0
  }
18954
0
}
18955
18956
/**
18957
 * Update the hash/fragment of the URL.
18958
 *
18959
 * If a URL has `#` as the hash value, passing empty string to this function
18960
 * does not remove the attribute. If you need to remove it, please use
18961
 * `ada_clear_hash` method.
18962
 */
18963
0
void ada_set_hash(ada_url result, const char* input, size_t length) noexcept {
18964
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18965
0
  if (r) {
18966
0
    r->set_hash(std::string_view(input, length));
18967
0
  }
18968
0
}
18969
18970
0
void ada_clear_port(ada_url result) noexcept {
18971
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18972
0
  if (r) {
18973
0
    r->clear_port();
18974
0
  }
18975
0
}
18976
18977
/**
18978
 * Removes the hash of the URL.
18979
 *
18980
 * Despite `ada_set_hash` method, this function allows the complete
18981
 * removal of the hash attribute, even if it has a value of `#`.
18982
 */
18983
0
void ada_clear_hash(ada_url result) noexcept {
18984
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18985
0
  if (r) {
18986
0
    r->clear_hash();
18987
0
  }
18988
0
}
18989
18990
/**
18991
 * Removes the search of the URL.
18992
 *
18993
 * Despite `ada_set_search` method, this function allows the complete
18994
 * removal of the search attribute, even if it has a value of `?`.
18995
 */
18996
0
void ada_clear_search(ada_url result) noexcept {
18997
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
18998
0
  if (r) {
18999
0
    r->clear_search();
19000
0
  }
19001
0
}
19002
19003
0
bool ada_has_credentials(ada_url result) noexcept {
19004
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19005
0
  if (!r) {
19006
0
    return false;
19007
0
  }
19008
0
  return r->has_credentials();
19009
0
}
19010
19011
0
bool ada_has_empty_hostname(ada_url result) noexcept {
19012
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19013
0
  if (!r) {
19014
0
    return false;
19015
0
  }
19016
0
  return r->has_empty_hostname();
19017
0
}
19018
19019
0
bool ada_has_hostname(ada_url result) noexcept {
19020
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19021
0
  if (!r) {
19022
0
    return false;
19023
0
  }
19024
0
  return r->has_hostname();
19025
0
}
19026
19027
0
bool ada_has_non_empty_username(ada_url result) noexcept {
19028
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19029
0
  if (!r) {
19030
0
    return false;
19031
0
  }
19032
0
  return r->has_non_empty_username();
19033
0
}
19034
19035
0
bool ada_has_non_empty_password(ada_url result) noexcept {
19036
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19037
0
  if (!r) {
19038
0
    return false;
19039
0
  }
19040
0
  return r->has_non_empty_password();
19041
0
}
19042
19043
0
bool ada_has_port(ada_url result) noexcept {
19044
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19045
0
  if (!r) {
19046
0
    return false;
19047
0
  }
19048
0
  return r->has_port();
19049
0
}
19050
19051
0
bool ada_has_password(ada_url result) noexcept {
19052
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19053
0
  if (!r) {
19054
0
    return false;
19055
0
  }
19056
0
  return r->has_password();
19057
0
}
19058
19059
0
bool ada_has_hash(ada_url result) noexcept {
19060
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19061
0
  if (!r) {
19062
0
    return false;
19063
0
  }
19064
0
  return r->has_hash();
19065
0
}
19066
19067
0
bool ada_has_search(ada_url result) noexcept {
19068
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19069
0
  if (!r) {
19070
0
    return false;
19071
0
  }
19072
0
  return r->has_search();
19073
0
}
19074
19075
// returns a pointer to the internal url_aggregator::url_components
19076
0
const ada_url_components* ada_get_components(ada_url result) noexcept {
19077
0
  static_assert(sizeof(ada_url_components) == sizeof(ada::url_components));
19078
0
  ada::result<ada::url_aggregator>& r = get_instance(result);
19079
0
  if (!r) {
19080
0
    return nullptr;
19081
0
  }
19082
0
  return reinterpret_cast<const ada_url_components*>(&r->get_components());
19083
0
}
19084
19085
0
ada_owned_string ada_idna_to_unicode(const char* input, size_t length) {
19086
0
  std::string out = ada::idna::to_unicode(std::string_view(input, length));
19087
0
  ada_owned_string owned{};
19088
0
  owned.length = out.length();
19089
0
  owned.data = new char[owned.length];
19090
0
  memcpy((void*)owned.data, out.data(), owned.length);
19091
0
  return owned;
19092
0
}
19093
19094
0
ada_owned_string ada_idna_to_ascii(const char* input, size_t length) {
19095
0
  std::string out = ada::idna::to_ascii(std::string_view(input, length));
19096
0
  ada_owned_string owned{};
19097
0
  owned.length = out.size();
19098
0
  owned.data = new char[owned.length];
19099
0
  memcpy((void*)owned.data, out.data(), owned.length);
19100
0
  return owned;
19101
0
}
19102
19103
ada_url_search_params ada_parse_search_params(const char* input,
19104
0
                                              size_t length) {
19105
0
  return new ada::result<ada::url_search_params>(
19106
0
      ada::url_search_params(std::string_view(input, length)));
19107
0
}
19108
19109
0
void ada_free_search_params(ada_url_search_params result) {
19110
0
  auto* r = (ada::result<ada::url_search_params>*)result;
19111
0
  delete r;
19112
0
}
19113
19114
0
ada_owned_string ada_search_params_to_string(ada_url_search_params result) {
19115
0
  ada::result<ada::url_search_params>& r =
19116
0
      *(ada::result<ada::url_search_params>*)result;
19117
0
  if (!r) return ada_owned_string{nullptr, 0};
19118
0
  std::string out = r->to_string();
19119
0
  ada_owned_string owned{};
19120
0
  owned.length = out.size();
19121
0
  owned.data = new char[owned.length];
19122
0
  memcpy((void*)owned.data, out.data(), owned.length);
19123
0
  return owned;
19124
0
}
19125
19126
0
size_t ada_search_params_size(ada_url_search_params result) {
19127
0
  ada::result<ada::url_search_params>& r =
19128
0
      *(ada::result<ada::url_search_params>*)result;
19129
0
  if (!r) {
19130
0
    return 0;
19131
0
  }
19132
0
  return r->size();
19133
0
}
19134
19135
0
void ada_search_params_sort(ada_url_search_params result) {
19136
0
  ada::result<ada::url_search_params>& r =
19137
0
      *(ada::result<ada::url_search_params>*)result;
19138
0
  if (r) {
19139
0
    r->sort();
19140
0
  }
19141
0
}
19142
19143
void ada_search_params_reset(ada_url_search_params result, const char* input,
19144
0
                             size_t length) {
19145
0
  ada::result<ada::url_search_params>& r =
19146
0
      *(ada::result<ada::url_search_params>*)result;
19147
0
  if (r) {
19148
0
    r->reset(std::string_view(input, length));
19149
0
  }
19150
0
}
19151
19152
void ada_search_params_append(ada_url_search_params result, const char* key,
19153
                              size_t key_length, const char* value,
19154
0
                              size_t value_length) {
19155
0
  ada::result<ada::url_search_params>& r =
19156
0
      *(ada::result<ada::url_search_params>*)result;
19157
0
  if (r) {
19158
0
    r->append(std::string_view(key, key_length),
19159
0
              std::string_view(value, value_length));
19160
0
  }
19161
0
}
19162
19163
void ada_search_params_set(ada_url_search_params result, const char* key,
19164
                           size_t key_length, const char* value,
19165
0
                           size_t value_length) {
19166
0
  ada::result<ada::url_search_params>& r =
19167
0
      *(ada::result<ada::url_search_params>*)result;
19168
0
  if (r) {
19169
0
    r->set(std::string_view(key, key_length),
19170
0
           std::string_view(value, value_length));
19171
0
  }
19172
0
}
19173
19174
void ada_search_params_remove(ada_url_search_params result, const char* key,
19175
0
                              size_t key_length) {
19176
0
  ada::result<ada::url_search_params>& r =
19177
0
      *(ada::result<ada::url_search_params>*)result;
19178
0
  if (r) {
19179
0
    r->remove(std::string_view(key, key_length));
19180
0
  }
19181
0
}
19182
19183
void ada_search_params_remove_value(ada_url_search_params result,
19184
                                    const char* key, size_t key_length,
19185
0
                                    const char* value, size_t value_length) {
19186
0
  ada::result<ada::url_search_params>& r =
19187
0
      *(ada::result<ada::url_search_params>*)result;
19188
0
  if (r) {
19189
0
    r->remove(std::string_view(key, key_length),
19190
0
              std::string_view(value, value_length));
19191
0
  }
19192
0
}
19193
19194
bool ada_search_params_has(ada_url_search_params result, const char* key,
19195
0
                           size_t key_length) {
19196
0
  ada::result<ada::url_search_params>& r =
19197
0
      *(ada::result<ada::url_search_params>*)result;
19198
0
  if (!r) {
19199
0
    return false;
19200
0
  }
19201
0
  return r->has(std::string_view(key, key_length));
19202
0
}
19203
19204
bool ada_search_params_has_value(ada_url_search_params result, const char* key,
19205
                                 size_t key_length, const char* value,
19206
0
                                 size_t value_length) {
19207
0
  ada::result<ada::url_search_params>& r =
19208
0
      *(ada::result<ada::url_search_params>*)result;
19209
0
  if (!r) {
19210
0
    return false;
19211
0
  }
19212
0
  return r->has(std::string_view(key, key_length),
19213
0
                std::string_view(value, value_length));
19214
0
}
19215
19216
ada_string ada_search_params_get(ada_url_search_params result, const char* key,
19217
0
                                 size_t key_length) {
19218
0
  ada::result<ada::url_search_params>& r =
19219
0
      *(ada::result<ada::url_search_params>*)result;
19220
0
  if (!r) {
19221
0
    return ada_string_create(nullptr, 0);
19222
0
  }
19223
0
  auto found = r->get(std::string_view(key, key_length));
19224
0
  if (!found.has_value()) {
19225
0
    return ada_string_create(nullptr, 0);
19226
0
  }
19227
0
  return ada_string_create(found->data(), found->length());
19228
0
}
19229
19230
ada_strings ada_search_params_get_all(ada_url_search_params result,
19231
0
                                      const char* key, size_t key_length) {
19232
0
  ada::result<ada::url_search_params>& r =
19233
0
      *(ada::result<ada::url_search_params>*)result;
19234
0
  if (!r) {
19235
0
    return new ada::result<std::vector<std::string>>(
19236
0
        std::vector<std::string>());
19237
0
  }
19238
0
  return new ada::result<std::vector<std::string>>(
19239
0
      r->get_all(std::string_view(key, key_length)));
19240
0
}
19241
19242
ada_url_search_params_keys_iter ada_search_params_get_keys(
19243
0
    ada_url_search_params result) {
19244
0
  ada::result<ada::url_search_params>& r =
19245
0
      *(ada::result<ada::url_search_params>*)result;
19246
0
  if (!r) {
19247
0
    return new ada::result<ada::url_search_params_keys_iter>(
19248
0
        ada::url_search_params_keys_iter());
19249
0
  }
19250
0
  return new ada::result<ada::url_search_params_keys_iter>(r->get_keys());
19251
0
}
19252
19253
ada_url_search_params_values_iter ada_search_params_get_values(
19254
0
    ada_url_search_params result) {
19255
0
  ada::result<ada::url_search_params>& r =
19256
0
      *(ada::result<ada::url_search_params>*)result;
19257
0
  if (!r) {
19258
0
    return new ada::result<ada::url_search_params_values_iter>(
19259
0
        ada::url_search_params_values_iter());
19260
0
  }
19261
0
  return new ada::result<ada::url_search_params_values_iter>(r->get_values());
19262
0
}
19263
19264
ada_url_search_params_entries_iter ada_search_params_get_entries(
19265
0
    ada_url_search_params result) {
19266
0
  ada::result<ada::url_search_params>& r =
19267
0
      *(ada::result<ada::url_search_params>*)result;
19268
0
  if (!r) {
19269
0
    return new ada::result<ada::url_search_params_entries_iter>(
19270
0
        ada::url_search_params_entries_iter());
19271
0
  }
19272
0
  return new ada::result<ada::url_search_params_entries_iter>(r->get_entries());
19273
0
}
19274
19275
0
void ada_free_strings(ada_strings result) {
19276
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
19277
0
  delete r;
19278
0
}
19279
19280
0
size_t ada_strings_size(ada_strings result) {
19281
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
19282
0
  if (!r) {
19283
0
    return 0;
19284
0
  }
19285
0
  return (*r)->size();
19286
0
}
19287
19288
0
ada_string ada_strings_get(ada_strings result, size_t index) {
19289
0
  auto* r = (ada::result<std::vector<std::string>>*)result;
19290
0
  if (!r || index >= (*r)->size()) {
19291
0
    return ada_string_create(nullptr, 0);
19292
0
  }
19293
0
  std::string_view view = (*r)->at(index);
19294
0
  return ada_string_create(view.data(), view.length());
19295
0
}
19296
19297
0
void ada_free_search_params_keys_iter(ada_url_search_params_keys_iter result) {
19298
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
19299
0
  delete r;
19300
0
}
19301
19302
ada_string ada_search_params_keys_iter_next(
19303
0
    ada_url_search_params_keys_iter result) {
19304
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
19305
0
  if (!r) {
19306
0
    return ada_string_create(nullptr, 0);
19307
0
  }
19308
0
  auto next = (*r)->next();
19309
0
  if (!next.has_value()) {
19310
0
    return ada_string_create(nullptr, 0);
19311
0
  }
19312
0
  return ada_string_create(next->data(), next->length());
19313
0
}
19314
19315
bool ada_search_params_keys_iter_has_next(
19316
0
    ada_url_search_params_keys_iter result) {
19317
0
  auto* r = (ada::result<ada::url_search_params_keys_iter>*)result;
19318
0
  if (!r) {
19319
0
    return false;
19320
0
  }
19321
0
  return (*r)->has_next();
19322
0
}
19323
19324
void ada_free_search_params_values_iter(
19325
0
    ada_url_search_params_values_iter result) {
19326
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
19327
0
  delete r;
19328
0
}
19329
19330
ada_string ada_search_params_values_iter_next(
19331
0
    ada_url_search_params_values_iter result) {
19332
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
19333
0
  if (!r) {
19334
0
    return ada_string_create(nullptr, 0);
19335
0
  }
19336
0
  auto next = (*r)->next();
19337
0
  if (!next.has_value()) {
19338
0
    return ada_string_create(nullptr, 0);
19339
0
  }
19340
0
  return ada_string_create(next->data(), next->length());
19341
0
}
19342
19343
bool ada_search_params_values_iter_has_next(
19344
0
    ada_url_search_params_values_iter result) {
19345
0
  auto* r = (ada::result<ada::url_search_params_values_iter>*)result;
19346
0
  if (!r) {
19347
0
    return false;
19348
0
  }
19349
0
  return (*r)->has_next();
19350
0
}
19351
19352
void ada_free_search_params_entries_iter(
19353
0
    ada_url_search_params_entries_iter result) {
19354
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
19355
0
  delete r;
19356
0
}
19357
19358
ada_string_pair ada_search_params_entries_iter_next(
19359
0
    ada_url_search_params_entries_iter result) {
19360
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
19361
0
  if (!r) return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
19362
0
  auto next = (*r)->next();
19363
0
  if (!next.has_value()) {
19364
0
    return {ada_string_create(nullptr, 0), ada_string_create(nullptr, 0)};
19365
0
  }
19366
0
  return ada_string_pair{
19367
0
      ada_string_create(next->first.data(), next->first.length()),
19368
0
      ada_string_create(next->second.data(), next->second.length())};
19369
0
}
19370
19371
bool ada_search_params_entries_iter_has_next(
19372
0
    ada_url_search_params_entries_iter result) {
19373
0
  auto* r = (ada::result<ada::url_search_params_entries_iter>*)result;
19374
0
  if (!r) {
19375
0
    return false;
19376
0
  }
19377
0
  return (*r)->has_next();
19378
0
}
19379
19380
0
void ada_set_max_input_length(uint32_t length) noexcept {
19381
0
  ada::set_max_input_length(length);
19382
0
}
19383
19384
0
uint32_t ada_get_max_input_length() noexcept {
19385
0
  return ada::get_max_input_length();
19386
0
}
19387
19388
typedef struct {
19389
  int major;
19390
  int minor;
19391
  int revision;
19392
} ada_version_components;
19393
19394
0
const char* ada_get_version() { return ADA_VERSION; }
19395
19396
0
ada_version_components ada_get_version_components() {
19397
0
  return ada_version_components{
19398
0
      .major = ada::ADA_VERSION_MAJOR,
19399
0
      .minor = ada::ADA_VERSION_MINOR,
19400
0
      .revision = ada::ADA_VERSION_REVISION,
19401
0
  };
19402
0
}
19403
19404
}  // extern "C"
19405
// NOLINTEND(bugprone-exception-escape,
19406
// bugprone-suspicious-stringview-data-usage)
19407
/* end file src/ada_c.cpp */
19408
/* end file src/ada.cpp */