/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 | 9.40k | 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 | 9.40k | if (!last_label_may_be_a_number(view)) { |
17 | 858 | return false; |
18 | 858 | } |
19 | | // If the address ends with a dot, we need to prune it (special case). |
20 | 8.55k | if (view.ends_with('.')) { |
21 | 135 | view.remove_suffix(1); |
22 | 135 | } |
23 | | // From the last character, find the last dot. |
24 | 8.55k | size_t last_dot = view.rfind('.'); |
25 | 8.55k | if (last_dot != std::string_view::npos) { |
26 | | // We have at least one dot. |
27 | 7.61k | view.remove_prefix(last_dot + 1); |
28 | 7.61k | } |
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 | 8.55k | if (std::ranges::all_of(view, ada::checkers::is_digit)) { |
33 | 7.95k | return true; |
34 | 7.95k | } |
35 | | // It could be hex (0x), but not if there is a single character. |
36 | 596 | if (view.size() == 1) { |
37 | 0 | return false; |
38 | 0 | } |
39 | | // It must start with 0x. |
40 | 596 | if (!view.starts_with("0x")) { |
41 | 78 | return false; |
42 | 78 | } |
43 | | // We must allow "0x". |
44 | 518 | if (view.size() == 2) { |
45 | 32 | return true; |
46 | 32 | } |
47 | | // We have 0x followed by some characters, we need to check that they are |
48 | | // hexadecimals. |
49 | 486 | view.remove_prefix(2); |
50 | 486 | return std::ranges::all_of(view, ada::unicode::is_lowercase_hex); |
51 | 518 | } |
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 | 8.97k | 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 | 8.97k | size_t i = 0; |
84 | 8.97k | uint8_t accumulator{}; |
85 | 26.1k | for (; i + 7 < input.size(); i += 8) { |
86 | 17.1k | accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] | |
87 | 17.1k | path_signature_table[uint8_t(input[i + 1])] | |
88 | 17.1k | path_signature_table[uint8_t(input[i + 2])] | |
89 | 17.1k | path_signature_table[uint8_t(input[i + 3])] | |
90 | 17.1k | path_signature_table[uint8_t(input[i + 4])] | |
91 | 17.1k | path_signature_table[uint8_t(input[i + 5])] | |
92 | 17.1k | path_signature_table[uint8_t(input[i + 6])] | |
93 | 17.1k | path_signature_table[uint8_t(input[i + 7])]); |
94 | 17.1k | } |
95 | 36.1k | for (; i < input.size(); i++) { |
96 | 27.1k | accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]); |
97 | 27.1k | } |
98 | 8.97k | return accumulator; |
99 | 8.97k | } |
100 | | |
101 | | ada_really_inline constexpr bool verify_dns_length( |
102 | 7.11k | std::string_view input) noexcept { |
103 | 7.11k | if (input.empty()) return false; |
104 | 6.24k | if (input.back() == '.') { |
105 | 110 | if (input.size() > 254) return false; |
106 | 6.13k | } else if (input.size() > 253) |
107 | 0 | return false; |
108 | | |
109 | 6.24k | size_t start = 0; |
110 | 21.2k | while (start < input.size()) { |
111 | 15.9k | auto dot_location = input.find('.', start); |
112 | | // If not found, it's likely the end of the domain |
113 | 15.9k | if (dot_location == std::string_view::npos) dot_location = input.size(); |
114 | | |
115 | 15.9k | auto label_size = dot_location - start; |
116 | 15.9k | if (label_size > 63 || label_size == 0) return false; |
117 | | |
118 | 14.9k | start = dot_location + 1; |
119 | 14.9k | } |
120 | | |
121 | 5.27k | return true; |
122 | 6.24k | } |
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 | 2.61k | size_t utf8_to_utf32(const char* buf, size_t len, char32_t* utf32_output) { |
163 | 2.61k | const uint8_t* data = reinterpret_cast<const uint8_t*>(buf); |
164 | 2.61k | size_t pos = 0; |
165 | 2.61k | const char32_t* start{utf32_output}; |
166 | 28.7k | while (pos < len) { |
167 | | // try to convert the next block of 16 ASCII bytes |
168 | 26.2k | if (pos + 16 <= len) { // if it is safe to read 16 more |
169 | | // bytes, check that they are ascii |
170 | 9.78k | uint64_t v1; |
171 | 9.78k | std::memcpy(&v1, data + pos, sizeof(uint64_t)); |
172 | 9.78k | uint64_t v2; |
173 | 9.78k | std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t)); |
174 | 9.78k | uint64_t v{v1 | v2}; |
175 | 9.78k | if ((v & 0x8080808080808080) == 0) { |
176 | 857 | size_t final_pos = pos + 16; |
177 | 14.5k | while (pos < final_pos) { |
178 | 13.7k | *utf32_output++ = char32_t(buf[pos]); |
179 | 13.7k | pos++; |
180 | 13.7k | } |
181 | 857 | continue; |
182 | 857 | } |
183 | 9.78k | } |
184 | 25.3k | uint8_t leading_byte = data[pos]; // leading byte |
185 | 25.3k | if (leading_byte < 0b10000000) { |
186 | | // converting one ASCII byte !!! |
187 | 16.1k | *utf32_output++ = char32_t(leading_byte); |
188 | 16.1k | pos++; |
189 | 16.1k | } else if ((leading_byte & 0b11100000) == 0b11000000) { |
190 | | // We have a two-byte UTF-8 |
191 | 3.05k | if (pos + 1 >= len) { |
192 | 3 | return 0; |
193 | 3 | } // minimal bound checking |
194 | 3.04k | if ((data[pos + 1] & 0b11000000) != 0b10000000) { |
195 | 26 | return 0; |
196 | 26 | } |
197 | | // range check |
198 | 3.02k | uint32_t code_point = |
199 | 3.02k | (leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111); |
200 | 3.02k | if (code_point < 0x80 || 0x7ff < code_point) { |
201 | 2 | return 0; |
202 | 2 | } |
203 | 3.01k | *utf32_output++ = char32_t(code_point); |
204 | 3.01k | pos += 2; |
205 | 6.14k | } else if ((leading_byte & 0b11110000) == 0b11100000) { |
206 | | // We have a three-byte UTF-8 |
207 | 5.69k | if (pos + 2 >= len) { |
208 | 2 | return 0; |
209 | 2 | } // minimal bound checking |
210 | | |
211 | 5.69k | if ((data[pos + 1] & 0b11000000) != 0b10000000) { |
212 | 14 | return 0; |
213 | 14 | } |
214 | 5.68k | if ((data[pos + 2] & 0b11000000) != 0b10000000) { |
215 | 4 | return 0; |
216 | 4 | } |
217 | | // range check |
218 | 5.67k | uint32_t code_point = (leading_byte & 0b00001111) << 12 | |
219 | 5.67k | (data[pos + 1] & 0b00111111) << 6 | |
220 | 5.67k | (data[pos + 2] & 0b00111111); |
221 | 5.67k | if (code_point < 0x800 || 0xffff < code_point || |
222 | 5.67k | (0xd7ff < code_point && code_point < 0xe000)) { |
223 | 7 | return 0; |
224 | 7 | } |
225 | 5.67k | *utf32_output++ = char32_t(code_point); |
226 | 5.67k | pos += 3; |
227 | 5.67k | } else if ((leading_byte & 0b11111000) == 0b11110000) { // 0b11110000 |
228 | | // we have a 4-byte UTF-8 word. |
229 | 372 | if (pos + 3 >= len) { |
230 | 10 | return 0; |
231 | 10 | } // minimal bound checking |
232 | 362 | if ((data[pos + 1] & 0b11000000) != 0b10000000) { |
233 | 8 | return 0; |
234 | 8 | } |
235 | 354 | if ((data[pos + 2] & 0b11000000) != 0b10000000) { |
236 | 4 | return 0; |
237 | 4 | } |
238 | 350 | if ((data[pos + 3] & 0b11000000) != 0b10000000) { |
239 | 3 | return 0; |
240 | 3 | } |
241 | | |
242 | | // range check |
243 | 347 | uint32_t code_point = (leading_byte & 0b00000111) << 18 | |
244 | 347 | (data[pos + 1] & 0b00111111) << 12 | |
245 | 347 | (data[pos + 2] & 0b00111111) << 6 | |
246 | 347 | (data[pos + 3] & 0b00111111); |
247 | 347 | if (code_point <= 0xffff || 0x10ffff < code_point) { |
248 | 6 | return 0; |
249 | 6 | } |
250 | 341 | *utf32_output++ = char32_t(code_point); |
251 | 341 | pos += 4; |
252 | 341 | } else { |
253 | 70 | return 0; |
254 | 70 | } |
255 | 25.3k | } |
256 | 2.45k | return utf32_output - start; |
257 | 2.61k | } |
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 | 2.62k | size_t utf32_length_from_utf8(const char* buf, size_t len) { |
273 | 2.62k | const int8_t* p = reinterpret_cast<const int8_t*>(buf); |
274 | 56.2k | 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 | 56.2k | return c > -65; |
278 | 56.2k | }); |
279 | 2.62k | } |
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 | 3.63k | [[nodiscard]] inline bool tables_are_ready() noexcept { |
5081 | 3.63k | return tables_init_state.load(std::memory_order_acquire) == kTablesReady; |
5082 | 3.63k | } |
5083 | | |
5084 | | // Returns true only when all table pointers are safe to use. |
5085 | 8.62k | [[nodiscard]] inline bool ensure_tables() noexcept { |
5086 | 8.62k | uint8_t state = tables_init_state.load(std::memory_order_acquire); |
5087 | 8.62k | if (state == kTablesReady) { |
5088 | 8.62k | return true; |
5089 | 8.62k | } |
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 | 177k | inline const uint16_t* decomposition_block_row(uint8_t bi) noexcept { |
5195 | 177k | if (bi >= kDecompBlockRows) { |
5196 | 0 | bi = 0; |
5197 | 0 | } |
5198 | 177k | return decomposition_block_flat + static_cast<size_t>(bi) * kDecompBlockCols; |
5199 | 177k | } |
5200 | | |
5201 | 262k | inline const uint8_t* ccc_block_row(uint8_t bi) noexcept { |
5202 | 262k | if (bi >= kCccBlockRows) { |
5203 | 0 | bi = 0; |
5204 | 0 | } |
5205 | 262k | return ccc_block_flat + static_cast<size_t>(bi) * kCccBlockCols; |
5206 | 262k | } |
5207 | | |
5208 | 89.0k | inline const uint16_t* composition_block_row(uint8_t bi) noexcept { |
5209 | 89.0k | if (bi >= kCompBlockRows) { |
5210 | 0 | bi = 0; |
5211 | 0 | } |
5212 | 89.0k | return composition_block_flat + static_cast<size_t>(bi) * kCompBlockCols; |
5213 | 89.0k | } |
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 | 97.0k | static uint16_t idna_lookup(uint32_t cp) noexcept { |
5278 | 97.0k | if (cp < IDNA_LOW_RANGE_END) { |
5279 | 96.4k | uint16_t ref = idna_stage1[cp >> IDNA_BLOCK_BITS]; |
5280 | 96.4k | if (ref & IDNA_BOOL_FLAG) { |
5281 | 47.6k | uint32_t bit_idx = |
5282 | 47.6k | static_cast<uint32_t>(ref & ~IDNA_BOOL_FLAG) * IDNA_BLOCK_SIZE + |
5283 | 47.6k | (cp & IDNA_BLOCK_MASK); |
5284 | 47.6k | bool is_valid = (idna_bool_blocks[bit_idx >> 6] >> (bit_idx & 63u)) & 1u; |
5285 | 47.6k | return is_valid ? IDNA_VALID : IDNA_DISALLOWED; |
5286 | 47.6k | } |
5287 | 48.8k | return idna_stage2[ref + (cp & IDNA_BLOCK_MASK)]; |
5288 | 96.4k | } |
5289 | | |
5290 | 564 | if (cp >= IDNA_HIGH_IGNORED_START && cp < IDNA_HIGH_IGNORED_END) { |
5291 | 420 | return IDNA_IGNORED; |
5292 | 420 | } |
5293 | | |
5294 | 144 | return IDNA_DISALLOWED; |
5295 | 564 | } |
5296 | | |
5297 | | // Advances *ptr past one well-formed UTF-8 code point from the mapping table. |
5298 | 45.6k | static char32_t utf8_next(const uint8_t*& ptr) noexcept { |
5299 | 45.6k | uint8_t b0 = *ptr++; |
5300 | 45.6k | if (b0 < 0x80u) return static_cast<char32_t>(b0); |
5301 | 31.4k | if (b0 < 0xE0u) { |
5302 | 19.5k | uint32_t cp = (b0 & 0x1Fu) << 6; |
5303 | 19.5k | cp |= (*ptr++ & 0x3Fu); |
5304 | 19.5k | return static_cast<char32_t>(cp); |
5305 | 19.5k | } |
5306 | 11.9k | if (b0 < 0xF0u) { |
5307 | 11.6k | uint32_t cp = (b0 & 0x0Fu) << 12; |
5308 | 11.6k | cp |= ((*ptr++ & 0x3Fu) << 6); |
5309 | 11.6k | cp |= (*ptr++ & 0x3Fu); |
5310 | 11.6k | return static_cast<char32_t>(cp); |
5311 | 11.6k | } |
5312 | 326 | uint32_t cp = (b0 & 0x07u) << 18; |
5313 | 326 | cp |= ((*ptr++ & 0x3Fu) << 12); |
5314 | 326 | cp |= ((*ptr++ & 0x3Fu) << 6); |
5315 | 326 | cp |= (*ptr++ & 0x3Fu); |
5316 | 326 | return static_cast<char32_t>(cp); |
5317 | 11.9k | } |
5318 | | |
5319 | | // Count UTF-8 code points in a null-terminated mapping string (trusted table). |
5320 | 10.6k | static size_t utf8_count_codepoints(const uint8_t* ptr) noexcept { |
5321 | 10.6k | size_t n = 0; |
5322 | 56.3k | while (*ptr != 0) { |
5323 | 45.6k | ++n; |
5324 | 45.6k | if (*ptr < 0x80u) { |
5325 | 14.1k | ++ptr; |
5326 | 31.5k | } else if (*ptr < 0xE0u) { |
5327 | 19.5k | ptr += 2; |
5328 | 19.5k | } else if (*ptr < 0xF0u) { |
5329 | 11.6k | ptr += 3; |
5330 | 11.6k | } else { |
5331 | 371 | ptr += 4; |
5332 | 371 | } |
5333 | 45.6k | } |
5334 | 10.6k | return n; |
5335 | 10.6k | } |
5336 | | |
5337 | | // --- ASCII fast path --------------------------------------------------------- |
5338 | 145 | void ascii_map(char* input, size_t length) { |
5339 | 435 | auto broadcast = [](uint8_t v) -> uint64_t { |
5340 | 435 | return 0x101010101010101ull * v; |
5341 | 435 | }; |
5342 | 145 | uint64_t broadcast_80 = broadcast(0x80); |
5343 | 145 | uint64_t broadcast_Ap = broadcast(128 - 'A'); |
5344 | 145 | uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1); |
5345 | 145 | size_t i = 0; |
5346 | | |
5347 | 480 | for (; i + 7 < length; i += 8) { |
5348 | 335 | uint64_t word{}; |
5349 | 335 | std::memcpy(&word, input + i, sizeof(word)); |
5350 | 335 | word ^= |
5351 | 335 | (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2; |
5352 | 335 | std::memcpy(input + i, &word, sizeof(word)); |
5353 | 335 | } |
5354 | 145 | if (i < length) { |
5355 | 119 | uint64_t word{}; |
5356 | 119 | std::memcpy(&word, input + i, length - i); |
5357 | 119 | word ^= |
5358 | 119 | (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2; |
5359 | 119 | std::memcpy(input + i, &word, length - i); |
5360 | 119 | } |
5361 | 145 | } |
5362 | | |
5363 | | // Two-pass map: first validate + exact size, then write once (no growth |
5364 | | // realloc). |
5365 | 3.48k | bool map(std::u32string_view input, std::u32string& out) { |
5366 | | // [Map](https://www.unicode.org/reports/tr46/#ProcessingStepMap). |
5367 | 3.48k | out.clear(); |
5368 | 3.48k | if (!ensure_tables()) { |
5369 | 0 | return false; |
5370 | 0 | } |
5371 | | |
5372 | | // Pass 1: validate and compute exact output length. |
5373 | 3.48k | size_t out_size = 0; |
5374 | 48.6k | for (char32_t x : input) { |
5375 | 48.6k | uint16_t status = idna_lookup(static_cast<uint32_t>(x)); |
5376 | 48.6k | if (status == IDNA_DISALLOWED) { |
5377 | 178 | return false; |
5378 | 178 | } |
5379 | 48.4k | if (status == IDNA_VALID) { |
5380 | 37.8k | ++out_size; |
5381 | 37.8k | continue; |
5382 | 37.8k | } |
5383 | 10.6k | if (static_cast<size_t>(status) >= idna_utf8_mappings_size) { |
5384 | 0 | return false; |
5385 | 0 | } |
5386 | 10.6k | out_size += utf8_count_codepoints(idna_utf8_mappings + status); |
5387 | 10.6k | } |
5388 | | |
5389 | | // Pass 2: write into a single allocation. |
5390 | 3.31k | out.resize(out_size); |
5391 | 3.31k | size_t w = 0; |
5392 | 48.3k | for (char32_t x : input) { |
5393 | 48.3k | uint16_t status = idna_lookup(static_cast<uint32_t>(x)); |
5394 | 48.3k | if (status == IDNA_VALID) { |
5395 | 37.7k | out[w++] = x; |
5396 | 37.7k | continue; |
5397 | 37.7k | } |
5398 | | // IGNORED or mapped (status already validated in pass 1). |
5399 | 10.6k | const uint8_t* ptr = idna_utf8_mappings + status; |
5400 | 56.2k | while (*ptr != 0) { |
5401 | 45.6k | out[w++] = utf8_next(ptr); |
5402 | 45.6k | } |
5403 | 10.6k | } |
5404 | 3.31k | return true; |
5405 | 3.48k | } |
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 | 71.3k | static size_t canonical_decomp_length(char32_t current_character) noexcept { |
5479 | 71.3k | if (current_character >= hangul_sbase && |
5480 | 4.26k | current_character < hangul_sbase + hangul_scount) { |
5481 | | // Hangul precomposed syllables are NFC. |
5482 | 2.07k | return 0; |
5483 | 2.07k | } |
5484 | 69.3k | if (current_character >= 0x110000) { |
5485 | 0 | return 0; |
5486 | 0 | } |
5487 | 69.3k | const uint8_t di = decomposition_index[current_character >> 8]; |
5488 | 69.3k | const uint16_t* const decomposition = |
5489 | 69.3k | decomposition_block_row(di) + (current_character % 256); |
5490 | 69.3k | size_t decomposition_length = |
5491 | 69.3k | (decomposition[1] >> 2) - (decomposition[0] >> 2); |
5492 | 69.3k | if ((decomposition_length > 0) && (decomposition[0] & 1)) { |
5493 | 0 | decomposition_length = 0; // compatibility-only: ignored for NFC |
5494 | 0 | } |
5495 | 69.3k | return decomposition_length; |
5496 | 69.3k | } |
5497 | | |
5498 | | std::pair<bool, size_t> compute_decomposition_length( |
5499 | 878 | const std::u32string_view input) noexcept { |
5500 | 878 | bool decomposition_needed{false}; |
5501 | 878 | size_t additional_elements{0}; |
5502 | 17.3k | for (char32_t current_character : input) { |
5503 | 17.3k | size_t decomposition_length{0}; |
5504 | | |
5505 | 17.3k | if (current_character >= hangul_sbase && |
5506 | 2.08k | current_character < hangul_sbase + hangul_scount) { |
5507 | | // Full NFD-style Hangul decomp for the decompose() step. |
5508 | 998 | decomposition_length = 2; |
5509 | 998 | if ((current_character - hangul_sbase) % hangul_tcount) { |
5510 | 665 | decomposition_length = 3; |
5511 | 665 | } |
5512 | 16.3k | } else if (current_character < 0x110000) { |
5513 | 16.3k | const uint8_t di = decomposition_index[current_character >> 8]; |
5514 | 16.3k | const uint16_t* const decomposition = |
5515 | 16.3k | decomposition_block_row(di) + (current_character % 256); |
5516 | 16.3k | decomposition_length = (decomposition[1] >> 2) - (decomposition[0] >> 2); |
5517 | 16.3k | if ((decomposition_length > 0) && (decomposition[0] & 1)) { |
5518 | 0 | decomposition_length = 0; |
5519 | 0 | } |
5520 | 16.3k | } |
5521 | 17.3k | if (decomposition_length != 0) { |
5522 | 3.17k | decomposition_needed = true; |
5523 | 3.17k | additional_elements += decomposition_length - 1; |
5524 | 3.17k | } |
5525 | 17.3k | } |
5526 | 878 | return {decomposition_needed, additional_elements}; |
5527 | 878 | } |
5528 | | |
5529 | 568 | void decompose(std::u32string& input, size_t additional_elements) { |
5530 | 568 | input.resize(input.size() + additional_elements); |
5531 | 568 | for (size_t descending_idx = input.size(), |
5532 | 568 | input_count = descending_idx - additional_elements; |
5533 | 12.0k | input_count--;) { |
5534 | 11.4k | if (input[input_count] >= hangul_sbase && |
5535 | 1.59k | input[input_count] < hangul_sbase + hangul_scount) { |
5536 | | // Hangul decomposition. |
5537 | 998 | char32_t s_index = input[input_count] - hangul_sbase; |
5538 | 998 | if (s_index % hangul_tcount != 0) { |
5539 | 665 | input[--descending_idx] = hangul_tbase + s_index % hangul_tcount; |
5540 | 665 | } |
5541 | 998 | input[--descending_idx] = |
5542 | 998 | hangul_vbase + (s_index % hangul_ncount) / hangul_tcount; |
5543 | 998 | input[--descending_idx] = hangul_lbase + s_index / hangul_ncount; |
5544 | 10.4k | } else if (input[input_count] < 0x110000) { |
5545 | 10.4k | const uint16_t* decomposition = |
5546 | 10.4k | decomposition_block_row( |
5547 | 10.4k | decomposition_index[input[input_count] >> 8]) + |
5548 | 10.4k | (input[input_count] % 256); |
5549 | 10.4k | uint16_t decomposition_length = |
5550 | 10.4k | (decomposition[1] >> 2) - (decomposition[0] >> 2); |
5551 | 10.4k | if (decomposition_length > 0 && (decomposition[0] & 1)) { |
5552 | 0 | decomposition_length = 0; |
5553 | 0 | } |
5554 | 10.4k | if (decomposition_length > 0) { |
5555 | 2.17k | const size_t base = static_cast<size_t>(decomposition[0] >> 2); |
5556 | 2.17k | if (base + decomposition_length > decomposition_data_size) { |
5557 | 0 | input[--descending_idx] = input[input_count]; |
5558 | 2.17k | } else { |
5559 | 7.20k | while (decomposition_length-- > 0) { |
5560 | 5.02k | input[--descending_idx] = |
5561 | 5.02k | decomposition_data[base + decomposition_length]; |
5562 | 5.02k | } |
5563 | 2.17k | } |
5564 | 8.26k | } else { |
5565 | 8.26k | input[--descending_idx] = input[input_count]; |
5566 | 8.26k | } |
5567 | 10.4k | } else { |
5568 | 0 | input[--descending_idx] = input[input_count]; |
5569 | 0 | } |
5570 | 11.4k | } |
5571 | 568 | } |
5572 | | |
5573 | 262k | uint8_t get_ccc(char32_t c) noexcept { |
5574 | 262k | if (c >= 0x110000) { |
5575 | 0 | return 0; |
5576 | 0 | } |
5577 | 262k | return ccc_block_row(ccc_index[c >> 8])[c % 256]; |
5578 | 262k | } |
5579 | | |
5580 | 878 | void sort_marks(std::u32string& input) { |
5581 | 21.8k | for (size_t idx = 1; idx < input.size(); idx++) { |
5582 | 21.0k | uint8_t ccc = get_ccc(input[idx]); |
5583 | 21.0k | if (ccc == 0) { |
5584 | 15.9k | continue; |
5585 | 15.9k | } |
5586 | 5.01k | auto current_character = input[idx]; |
5587 | 5.01k | size_t back_idx = idx; |
5588 | 16.5k | while (back_idx != 0 && get_ccc(input[back_idx - 1]) > ccc) { |
5589 | 11.5k | input[back_idx] = input[back_idx - 1]; |
5590 | 11.5k | back_idx--; |
5591 | 11.5k | } |
5592 | 5.01k | input[back_idx] = current_character; |
5593 | 5.01k | } |
5594 | 878 | } |
5595 | | |
5596 | 878 | 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 | 878 | auto [decomposition_needed, additional_elements] = |
5602 | 878 | compute_decomposition_length(input); |
5603 | 878 | if (decomposition_needed) { |
5604 | 568 | decompose(input, additional_elements); |
5605 | 568 | } |
5606 | 878 | sort_marks(input); |
5607 | 878 | } |
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 | 19.8k | char32_t second) noexcept { |
5612 | 19.8k | int left = composition[0]; |
5613 | 19.8k | int right = composition[1]; |
5614 | 19.8k | if (left < 0 || right <= left || |
5615 | 17.0k | static_cast<size_t>(right) > composition_data_size) { |
5616 | 2.80k | return false; |
5617 | 2.80k | } |
5618 | 41.0k | while (left + 2 < right) { |
5619 | 24.0k | int middle = left + (((right - left) >> 1) & ~1); |
5620 | 24.0k | if (composition_data[static_cast<size_t>(middle)] <= second) { |
5621 | 2.70k | left = middle; |
5622 | 2.70k | } |
5623 | 24.0k | if (composition_data[static_cast<size_t>(middle)] >= second) { |
5624 | 21.7k | right = middle; |
5625 | 21.7k | } |
5626 | 24.0k | } |
5627 | 17.0k | return static_cast<size_t>(left + 1) < composition_data_size && |
5628 | 17.0k | composition_data[static_cast<size_t>(left)] == second; |
5629 | 19.8k | } |
5630 | | |
5631 | | // Returns true if a composition step would change the string. |
5632 | 2.52k | static bool would_compose(std::u32string_view input) noexcept { |
5633 | 60.5k | for (size_t input_count = 0; input_count < input.size();) { |
5634 | 58.7k | const char32_t current = input[input_count]; |
5635 | 58.7k | if (current >= hangul_lbase && current < hangul_lbase + hangul_lcount) { |
5636 | 538 | if (input_count + 1 < input.size() && |
5637 | 514 | input[input_count + 1] >= hangul_vbase && |
5638 | 224 | input[input_count + 1] < hangul_vbase + hangul_vcount) { |
5639 | 74 | return true; |
5640 | 74 | } |
5641 | 464 | ++input_count; |
5642 | 464 | continue; |
5643 | 538 | } |
5644 | 58.1k | if (current >= hangul_sbase && current < hangul_sbase + hangul_scount) { |
5645 | 1.44k | if ((current - hangul_sbase) % hangul_tcount == 0 && |
5646 | 571 | input_count + 1 < input.size() && |
5647 | 552 | input[input_count + 1] > hangul_tbase && |
5648 | 412 | input[input_count + 1] < hangul_tbase + hangul_tcount) { |
5649 | 44 | return true; |
5650 | 44 | } |
5651 | 1.39k | ++input_count; |
5652 | 1.39k | continue; |
5653 | 1.44k | } |
5654 | 56.7k | if (current < 0x110000) { |
5655 | 56.7k | const uint16_t* composition = |
5656 | 56.7k | composition_block_row(composition_index[current >> 8]) + |
5657 | 56.7k | (current % 256); |
5658 | 56.7k | int32_t previous_ccc = -1; |
5659 | 56.7k | size_t j = input_count; |
5660 | 58.0k | for (; j + 1 < input.size(); ++j) { |
5661 | 56.2k | uint8_t ccc = get_ccc(input[j + 1]); |
5662 | 56.2k | if (composition[1] != composition[0] && previous_ccc < ccc && |
5663 | 15.6k | has_composition(composition, input[j + 1])) { |
5664 | 528 | return true; |
5665 | 528 | } |
5666 | 55.7k | if (ccc == 0) { |
5667 | 54.3k | break; |
5668 | 54.3k | } |
5669 | 1.33k | previous_ccc = ccc; |
5670 | 1.33k | } |
5671 | 56.2k | input_count = j + 1; |
5672 | 56.2k | continue; |
5673 | 56.7k | } |
5674 | 0 | ++input_count; |
5675 | 0 | } |
5676 | 1.87k | return false; |
5677 | 2.52k | } |
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 | 71.3k | static uint8_t trailing_ccc(char32_t c) noexcept { |
5685 | 71.3k | const size_t length = canonical_decomp_length(c); |
5686 | 71.3k | if (length == 0) { |
5687 | 66.7k | return get_ccc(c); |
5688 | 66.7k | } |
5689 | 4.62k | const uint16_t* const decomposition = |
5690 | 4.62k | decomposition_block_row(decomposition_index[c >> 8]) + (c % 256); |
5691 | 4.62k | const size_t base = decomposition[0] >> 2; |
5692 | 4.62k | return get_ccc(decomposition_data[base + length - 1]); |
5693 | 71.3k | } |
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 | 78.8k | static bool decomposition_is_not_nfc(char32_t previous, char32_t c) noexcept { |
5708 | 78.8k | if (c >= hangul_sbase && c < hangul_sbase + hangul_scount) { |
5709 | 2.25k | return false; |
5710 | 2.25k | } |
5711 | 76.5k | if (c >= 0x110000) { |
5712 | 0 | return false; |
5713 | 0 | } |
5714 | 76.5k | const uint16_t* const decomposition = |
5715 | 76.5k | decomposition_block_row(decomposition_index[c >> 8]) + (c % 256); |
5716 | 76.5k | const size_t length = (decomposition[1] >> 2) - (decomposition[0] >> 2); |
5717 | 76.5k | if (length == 0 || (decomposition[0] & 1)) { |
5718 | 71.5k | return false; // no canonical decomposition (or compatibility-only) |
5719 | 71.5k | } |
5720 | 4.98k | if (length == 1) { |
5721 | 0 | return true; // singleton |
5722 | 0 | } |
5723 | 4.98k | const size_t base = decomposition[0] >> 2; |
5724 | 4.98k | 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 | 4.98k | std::u32string decomposed(decomposition_data + base, |
5730 | 4.98k | decomposition_data + base + length); |
5731 | 4.98k | compose(decomposed); |
5732 | 4.98k | if (!(decomposed.size() == 1 && decomposed[0] == c)) { |
5733 | 0 | return true; |
5734 | 0 | } |
5735 | 4.98k | return previous < 0x110000 && |
5736 | 4.18k | has_composition( |
5737 | 4.18k | composition_block_row(composition_index[previous >> 8]) + |
5738 | 4.18k | (previous % 256), |
5739 | 4.18k | decomposition_data[base]); |
5740 | 4.98k | } |
5741 | | |
5742 | 3.63k | bool is_already_nfc(std::u32string_view input) noexcept { |
5743 | 3.63k | if (input.empty()) { |
5744 | 0 | return true; |
5745 | 0 | } |
5746 | 3.63k | 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 | 3.63k | char32_t previous = 0x110000; // none |
5755 | 78.8k | for (char32_t c : input) { |
5756 | 78.8k | if (decomposition_is_not_nfc(previous, c)) { |
5757 | 8 | return false; |
5758 | 8 | } |
5759 | 78.8k | previous = c; |
5760 | 78.8k | } |
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 | 3.62k | uint8_t prev_ccc = 0; |
5765 | 72.4k | for (char32_t c : input) { |
5766 | 72.4k | uint8_t ccc = get_ccc(c); |
5767 | 72.4k | if (ccc != 0 && prev_ccc > ccc) { |
5768 | 1.10k | return false; |
5769 | 1.10k | } |
5770 | 71.3k | prev_ccc = trailing_ccc(c); |
5771 | 71.3k | } |
5772 | | // 3) No pairwise composition would apply (including Hangul L+V / LV+T). |
5773 | 2.52k | return !would_compose(input); |
5774 | 3.62k | } |
5775 | | |
5776 | 5.86k | 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 | 5.86k | size_t input_count{0}; |
5782 | 5.86k | size_t composition_count{0}; |
5783 | 25.7k | for (; input_count < input.size(); input_count++, composition_count++) { |
5784 | 19.9k | input[composition_count] = input[input_count]; |
5785 | 19.9k | if (input[input_count] >= hangul_lbase && |
5786 | 4.24k | input[input_count] < hangul_lbase + hangul_lcount) { |
5787 | 1.33k | if (input_count + 1 < input.size() && |
5788 | 1.31k | input[input_count + 1] >= hangul_vbase && |
5789 | 1.12k | input[input_count + 1] < hangul_vbase + hangul_vcount) { |
5790 | 1.03k | input[composition_count] = |
5791 | 1.03k | hangul_sbase + |
5792 | 1.03k | ((input[input_count] - hangul_lbase) * hangul_vcount + |
5793 | 1.03k | input[input_count + 1] - hangul_vbase) * |
5794 | 1.03k | hangul_tcount; |
5795 | 1.03k | input_count++; |
5796 | 1.03k | if (input_count + 1 < input.size() && |
5797 | 1.01k | input[input_count + 1] > hangul_tbase && |
5798 | 762 | input[input_count + 1] < hangul_tbase + hangul_tcount) { |
5799 | 687 | input[composition_count] += input[++input_count] - hangul_tbase; |
5800 | 687 | } |
5801 | 1.03k | } |
5802 | 18.5k | } else if (input[input_count] >= hangul_sbase && |
5803 | 1.49k | 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 | 18.5k | } else if (input[input_count] < 0x110000) { |
5811 | 18.5k | const uint16_t* composition = |
5812 | 18.5k | composition_block_row(composition_index[input[input_count] >> 8]) + |
5813 | 18.5k | (input[input_count] % 256); |
5814 | 18.5k | size_t initial_composition_count = composition_count; |
5815 | 30.2k | for (int32_t previous_ccc = -1; input_count + 1 < input.size(); |
5816 | 24.4k | input_count++) { |
5817 | 24.4k | uint8_t ccc = get_ccc(input[input_count + 1]); |
5818 | | |
5819 | 24.4k | if (composition[1] != composition[0] && previous_ccc < ccc) { |
5820 | 13.6k | int left = composition[0]; |
5821 | 13.6k | int right = composition[1]; |
5822 | 13.6k | if (left < 0 || right < left || |
5823 | 13.6k | static_cast<size_t>(right) > composition_data_size) { |
5824 | 0 | break; |
5825 | 0 | } |
5826 | 32.7k | while (left + 2 < right) { |
5827 | 19.1k | int middle = left + (((right - left) >> 1) & ~1); |
5828 | 19.1k | if (composition_data[static_cast<size_t>(middle)] <= |
5829 | 19.1k | input[input_count + 1]) { |
5830 | 10.0k | left = middle; |
5831 | 10.0k | } |
5832 | 19.1k | if (composition_data[static_cast<size_t>(middle)] >= |
5833 | 19.1k | input[input_count + 1]) { |
5834 | 16.4k | right = middle; |
5835 | 16.4k | } |
5836 | 19.1k | } |
5837 | 13.6k | if (static_cast<size_t>(left + 1) < composition_data_size && |
5838 | 13.6k | composition_data[static_cast<size_t>(left)] == |
5839 | 13.6k | input[input_count + 1]) { |
5840 | 9.54k | char32_t composed = composition_data[static_cast<size_t>(left + 1)]; |
5841 | 9.54k | input[initial_composition_count] = composed; |
5842 | 9.54k | composition = |
5843 | 9.54k | composition_block_row(composition_index[composed >> 8]) + |
5844 | 9.54k | (composed % 256); |
5845 | 9.54k | continue; |
5846 | 9.54k | } |
5847 | 13.6k | } |
5848 | | |
5849 | 14.8k | if (ccc == 0) { |
5850 | 12.7k | break; |
5851 | 12.7k | } |
5852 | 2.11k | previous_ccc = ccc; |
5853 | 2.11k | input[++composition_count] = input[input_count + 1]; |
5854 | 2.11k | } |
5855 | 18.5k | } |
5856 | 19.9k | } |
5857 | | |
5858 | 5.86k | if (composition_count < input_count) { |
5859 | 5.76k | input.resize(composition_count); |
5860 | 5.76k | } |
5861 | 5.86k | } |
5862 | | |
5863 | 878 | 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 | 878 | if (!ensure_tables() || decomposition_index == nullptr || |
5869 | 878 | composition_index == nullptr) { |
5870 | 0 | return false; |
5871 | 0 | } |
5872 | 878 | if (is_already_nfc(input)) { |
5873 | 0 | return true; |
5874 | 0 | } |
5875 | 878 | decompose_nfc(input); |
5876 | 878 | compose(input); |
5877 | 878 | return true; |
5878 | 878 | } |
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 | 14.5k | static constexpr int32_t char_to_digit_value(char value) { |
5914 | 14.5k | if (value >= 'a' && value <= 'z') return value - 'a'; |
5915 | 2.39k | if (value >= '0' && value <= '9') return value - '0' + 26; |
5916 | 17 | return -1; |
5917 | 2.39k | } |
5918 | | |
5919 | 29.9k | static constexpr char digit_to_char(int32_t digit) { |
5920 | 29.9k | return digit < 26 ? char(digit + 97) : char(digit + 22); |
5921 | 29.9k | } |
5922 | | |
5923 | 24.5k | static constexpr int32_t adapt(int32_t d, int32_t n, bool firsttime) { |
5924 | 24.5k | if (firsttime) { |
5925 | 4.14k | d = d / damp; |
5926 | 20.3k | } else { |
5927 | 20.3k | d = d / 2; |
5928 | 20.3k | } |
5929 | 24.5k | d += d / n; |
5930 | 24.5k | int32_t k = 0; |
5931 | 27.1k | while (d > ((base - tmin) * tmax) / 2) { |
5932 | 2.65k | d /= base - tmin; |
5933 | 2.65k | k += base; |
5934 | 2.65k | } |
5935 | 24.5k | return k + (((base - tmin + 1) * d) / (d + skew)); |
5936 | 24.5k | } |
5937 | | |
5938 | 1.16k | bool punycode_to_utf32(std::string_view input, std::u32string &out) { |
5939 | 1.16k | int32_t written_out{0}; |
5940 | 1.16k | out.reserve(out.size() + input.size()); |
5941 | 1.16k | uint32_t n = initial_n; |
5942 | 1.16k | int32_t i = 0; |
5943 | 1.16k | 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 | 1.16k | size_t end_of_ascii = input.find_last_of('-'); |
5951 | 1.16k | if (end_of_ascii != std::string_view::npos && end_of_ascii > 0) { |
5952 | 1.61k | for (uint8_t c : input.substr(0, end_of_ascii)) { |
5953 | 1.61k | if (c >= 0x80) { |
5954 | 0 | return false; |
5955 | 0 | } |
5956 | 1.61k | out.push_back(c); |
5957 | 1.61k | written_out++; |
5958 | 1.61k | } |
5959 | 193 | input.remove_prefix(end_of_ascii + 1); |
5960 | 193 | } |
5961 | 11.3k | while (!input.empty()) { |
5962 | 10.2k | int32_t oldi = i; |
5963 | 10.2k | int32_t w = 1; |
5964 | 14.6k | for (int32_t k = base;; k += base) { |
5965 | 14.6k | if (input.empty()) { |
5966 | 41 | return false; |
5967 | 41 | } |
5968 | 14.5k | uint8_t code_point = input.front(); |
5969 | 14.5k | input.remove_prefix(1); |
5970 | 14.5k | int32_t digit = char_to_digit_value(code_point); |
5971 | 14.5k | if (digit < 0) { |
5972 | 17 | return false; |
5973 | 17 | } |
5974 | 14.5k | if (digit > (0x7fffffff - i) / w) { |
5975 | 6 | return false; |
5976 | 6 | } |
5977 | 14.5k | i = i + digit * w; |
5978 | 14.5k | int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; |
5979 | 14.5k | if (digit < t) { |
5980 | 10.2k | break; |
5981 | 10.2k | } |
5982 | 4.33k | if (w > 0x7fffffff / (base - t)) { |
5983 | 0 | return false; |
5984 | 0 | } |
5985 | 4.33k | w = w * (base - t); |
5986 | 4.33k | } |
5987 | 10.2k | bias = adapt(i - oldi, written_out + 1, oldi == 0); |
5988 | 10.2k | if (i / (written_out + 1) > int32_t(0x7fffffff - n)) { |
5989 | 27 | return false; |
5990 | 27 | } |
5991 | 10.1k | n = n + i / (written_out + 1); |
5992 | 10.1k | i = i % (written_out + 1); |
5993 | 10.1k | if (n < 0x80) { |
5994 | 0 | return false; |
5995 | 0 | } |
5996 | 10.1k | out.insert(out.begin() + i, n); |
5997 | 10.1k | written_out++; |
5998 | 10.1k | ++i; |
5999 | 10.1k | } |
6000 | | // See https://github.com/whatwg/url/issues/803 |
6001 | | // Reject labels whose decoded form begins with "xn--" (double-encoded ACE). |
6002 | 1.07k | if (out.size() >= 4 && out[0] == U'x' && out[1] == U'n' && out[2] == U'-' && |
6003 | 46 | out[3] == U'-') { |
6004 | 2 | return false; |
6005 | 2 | } |
6006 | 1.07k | return true; |
6007 | 1.07k | } |
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 | 3.05k | bool utf32_to_punycode(std::u32string_view input, std::string &out) { |
6088 | 3.05k | out.reserve(input.size() + out.size()); |
6089 | 3.05k | uint32_t n = initial_n; |
6090 | 3.05k | int32_t d = 0; |
6091 | 3.05k | int32_t bias = initial_bias; |
6092 | 3.05k | size_t h = 0; |
6093 | | // first push the ascii content |
6094 | 16.6k | for (uint32_t c : input) { |
6095 | 16.6k | if (c < 0x80) { |
6096 | 2.37k | ++h; |
6097 | 2.37k | out.push_back(char(c)); |
6098 | 2.37k | } |
6099 | 16.6k | if (c > 0x10ffff || (c >= 0xd800 && c < 0xe000)) { |
6100 | 0 | return false; |
6101 | 0 | } |
6102 | 16.6k | } |
6103 | 3.05k | size_t b = h; |
6104 | 3.05k | if (b > 0) { |
6105 | 482 | out.push_back('-'); |
6106 | 482 | } |
6107 | 14.6k | while (h < input.size()) { |
6108 | 11.5k | uint32_t m = 0x10FFFF; |
6109 | 87.3k | for (auto code_point : input) { |
6110 | 87.3k | if (code_point >= n && code_point < m) m = code_point; |
6111 | 87.3k | } |
6112 | | |
6113 | 11.5k | if ((m - n) > (0x7fffffff - d) / (h + 1)) { |
6114 | 0 | return false; |
6115 | 0 | } |
6116 | 11.5k | d = d + int32_t((m - n) * (h + 1)); |
6117 | 11.5k | n = m; |
6118 | 87.3k | for (auto c : input) { |
6119 | 87.3k | if (c < n) { |
6120 | 38.6k | if (d == 0x7fffffff) { |
6121 | 0 | return false; |
6122 | 0 | } |
6123 | 38.6k | ++d; |
6124 | 38.6k | } |
6125 | 87.3k | if (c == n) { |
6126 | 14.3k | int32_t q = d; |
6127 | 29.9k | for (int32_t k = base;; k += base) { |
6128 | 29.9k | int32_t t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias; |
6129 | | |
6130 | 29.9k | if (q < t) { |
6131 | 14.3k | break; |
6132 | 14.3k | } |
6133 | 15.6k | out.push_back(digit_to_char(t + ((q - t) % (base - t)))); |
6134 | 15.6k | q = (q - t) / (base - t); |
6135 | 15.6k | } |
6136 | 14.3k | out.push_back(digit_to_char(q)); |
6137 | 14.3k | bias = adapt(d, int32_t(h + 1), h == b); |
6138 | 14.3k | d = 0; |
6139 | 14.3k | ++h; |
6140 | 14.3k | } |
6141 | 87.3k | } |
6142 | 11.5k | ++d; |
6143 | 11.5k | ++n; |
6144 | 11.5k | } |
6145 | 3.05k | return true; |
6146 | 3.05k | } |
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 | 48.2k | size_t count, uint32_t code_point) noexcept { |
6204 | 48.2k | size_t lo = 0, hi = count; |
6205 | 556k | while (lo < hi) { |
6206 | 508k | size_t mid = lo + (hi - lo) / 2; |
6207 | 508k | if (last[mid] < code_point) { |
6208 | 153k | lo = mid + 1; |
6209 | 354k | } else { |
6210 | 354k | hi = mid; |
6211 | 354k | } |
6212 | 508k | } |
6213 | 48.2k | return lo < count && code_point >= start[lo] ? lo : count; |
6214 | 48.2k | } |
6215 | | |
6216 | | // Assumes ensure_tables() has already been called by is_label_valid(). |
6217 | 47.2k | inline static direction find_direction(uint32_t code_point) noexcept { |
6218 | 47.2k | size_t i = find_range(dir_start, dir_final, dir_table_count, code_point); |
6219 | 47.2k | return i == dir_table_count ? direction::NONE |
6220 | 47.2k | : static_cast<direction>(dir_value[i]); |
6221 | 47.2k | } |
6222 | | |
6223 | | // Assumes ensure_tables() has already been called by is_label_valid(). |
6224 | 1.03k | inline static joining_type find_joining_type(uint32_t code_point) noexcept { |
6225 | 1.03k | size_t i = |
6226 | 1.03k | find_range(joining_start, joining_final, joining_table_count, code_point); |
6227 | 1.03k | return i == joining_table_count ? joining_type::U |
6228 | 1.03k | : static_cast<joining_type>(joining_value[i]); |
6229 | 1.03k | } |
6230 | | |
6231 | | // The ContextJ rules for U+200C and U+200D from RFC 5892 Appendix A. |
6232 | 4.18k | inline static bool is_contextj_valid(std::u32string_view label) noexcept { |
6233 | 4.18k | constexpr uint8_t virama_ccc = 9; |
6234 | 43.0k | for (size_t i = 0; i < label.size(); i++) { |
6235 | 39.0k | if (label[i] != 0x200C && label[i] != 0x200D) { |
6236 | 38.6k | continue; |
6237 | 38.6k | } |
6238 | | // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True; |
6239 | 369 | if (i > 0 && get_ccc(label[i - 1]) == virama_ccc) { |
6240 | 70 | continue; |
6241 | 70 | } |
6242 | 299 | if (label[i] == 0x200D) { |
6243 | 9 | return false; |
6244 | 9 | } |
6245 | | // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C |
6246 | | // (Joining_Type:T)*(Joining_Type:{R,D})) Then True; |
6247 | 290 | joining_type before = joining_type::U; |
6248 | 535 | for (size_t j = i; j > 0;) { |
6249 | 533 | before = find_joining_type(label[--j]); |
6250 | 533 | if (before != joining_type::T) { |
6251 | 288 | break; |
6252 | 288 | } |
6253 | 533 | } |
6254 | 290 | if (before != joining_type::L && before != joining_type::D) { |
6255 | 54 | return false; |
6256 | 54 | } |
6257 | 236 | joining_type after = joining_type::U; |
6258 | 541 | for (size_t j = i + 1; j < label.size(); j++) { |
6259 | 498 | after = find_joining_type(label[j]); |
6260 | 498 | if (after != joining_type::T) { |
6261 | 193 | break; |
6262 | 193 | } |
6263 | 498 | } |
6264 | 236 | if (after != joining_type::R && after != joining_type::D) { |
6265 | 83 | return false; |
6266 | 83 | } |
6267 | 236 | } |
6268 | 4.03k | return true; |
6269 | 4.18k | } |
6270 | | |
6271 | | inline static size_t find_last_not_of_nsm( |
6272 | 4.03k | const std::u32string_view label) noexcept { |
6273 | 4.98k | for (int i = static_cast<int>(label.size() - 1); i >= 0; i--) |
6274 | 4.98k | if (find_direction(label[i]) != direction::NSM) return i; |
6275 | | |
6276 | 0 | return std::u32string_view::npos; |
6277 | 4.03k | } |
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 | 4.03k | inline static bool is_rtl_label(const std::u32string_view label) noexcept { |
6282 | 4.03k | const size_t mask = |
6283 | 4.03k | (1u << direction::R) | (1u << direction::AL) | (1u << direction::AN); |
6284 | | |
6285 | 4.03k | size_t directions = 0; |
6286 | 40.4k | for (size_t i = 0; i < label.size(); i++) { |
6287 | 36.3k | directions |= 1u << find_direction(label[i]); |
6288 | 36.3k | } |
6289 | 4.03k | return (directions & mask) != 0; |
6290 | 4.03k | } |
6291 | | |
6292 | 4.26k | bool is_label_valid(const std::u32string_view label) { |
6293 | 4.26k | if (label.empty()) { |
6294 | 0 | return true; |
6295 | 0 | } |
6296 | 4.26k | if (!ensure_tables() || combining_ranges == nullptr || dir_start == nullptr || |
6297 | 4.26k | dir_final == nullptr || dir_value == nullptr || |
6298 | 4.26k | joining_start == nullptr || joining_final == nullptr || |
6299 | 4.26k | 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 | 4.26k | const std::span<const uint32_t[2]> comb_span{combining_ranges, |
6325 | 4.26k | combining_range_count}; |
6326 | 4.26k | const auto comb_it = std::ranges::lower_bound( |
6327 | 35.5k | comb_span, label.front(), {}, [](const auto& range) { return range[1]; }); |
6328 | 4.26k | if (comb_it != comb_span.end() && label.front() >= (*comb_it)[0]) { |
6329 | 80 | return false; |
6330 | 80 | } |
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 | 4.18k | if (!is_contextj_valid(label)) { |
6343 | 146 | return false; |
6344 | 146 | } |
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 | 4.03k | size_t last_non_nsm_char = find_last_not_of_nsm(label); |
6377 | 4.03k | 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 | 4.03k | 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 | 935 | 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 | 1.20k | for (size_t i = 0; i <= last_non_nsm_char; i++) { |
6395 | 1.20k | const direction d = find_direction(label[i]); |
6396 | 1.20k | if (!(d == direction::L || d == direction::EN || d == direction::ES || |
6397 | 555 | d == direction::CS || d == direction::ET || d == direction::ON || |
6398 | 294 | d == direction::BN || d == direction::NSM)) { |
6399 | 115 | return false; |
6400 | 115 | } |
6401 | 1.20k | } |
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 | 820 | } 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 | 820 | const direction first_dir = find_direction(label[0]); |
6416 | 820 | if (first_dir != direction::R && first_dir != direction::AL) { |
6417 | 29 | return false; |
6418 | 29 | } |
6419 | | |
6420 | 791 | bool has_an = false; |
6421 | 791 | bool has_en = false; |
6422 | 3.55k | for (size_t i = 0; i <= last_non_nsm_char; i++) { |
6423 | 2.88k | 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 | 2.88k | if ((d == direction::EN && ((has_en = true) && has_an)) || |
6428 | 2.88k | (d == direction::AN && ((has_an = true) && has_en))) { |
6429 | 2 | return false; |
6430 | 2 | } |
6431 | | |
6432 | 2.88k | if (!(d == direction::R || d == direction::AL || d == direction::AN || |
6433 | 929 | d == direction::EN || d == direction::ES || d == direction::CS || |
6434 | 571 | d == direction::ET || d == direction::ON || d == direction::BN || |
6435 | 202 | d == direction::NSM)) { |
6436 | 72 | return false; |
6437 | 72 | } |
6438 | | |
6439 | 2.80k | if (i == last_non_nsm_char && |
6440 | 717 | !(d == direction::R || d == direction::AL || d == direction::AN || |
6441 | 113 | d == direction::EN)) { |
6442 | 45 | return false; |
6443 | 45 | } |
6444 | 2.80k | } |
6445 | | |
6446 | 672 | return true; |
6447 | 791 | } |
6448 | 935 | } |
6449 | | |
6450 | 3.09k | return true; |
6451 | 4.03k | } |
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 | 9.46k | bool constexpr is_ascii(std::u32string_view view) { |
6544 | 37.7k | for (uint32_t c : view) { |
6545 | 37.7k | if (c >= 0x80) { |
6546 | 7.30k | return false; |
6547 | 7.30k | } |
6548 | 37.7k | } |
6549 | 2.15k | return true; |
6550 | 9.46k | } |
6551 | | |
6552 | 2.76k | bool constexpr is_ascii(std::string_view view) { |
6553 | 19.9k | for (uint8_t c : view) { |
6554 | 19.9k | if (c >= 0x80) { |
6555 | 2.62k | return false; |
6556 | 2.62k | } |
6557 | 19.9k | } |
6558 | 145 | return true; |
6559 | 2.76k | } |
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 | 145 | static void from_ascii_to_ascii(std::string_view ut8_string, std::string& out) { |
6590 | 145 | out.assign(ut8_string); |
6591 | 145 | ascii_map(out.data(), out.size()); |
6592 | 145 | } |
6593 | | |
6594 | | // Append ASCII code units from a UTF-32 label (all values < 0x80). |
6595 | 2.77k | static void append_ascii_label(std::string& out, std::u32string_view label) { |
6596 | 2.77k | const size_t old = out.size(); |
6597 | 2.77k | out.resize(old + label.size()); |
6598 | 2.77k | char* dest = out.data() + old; |
6599 | 24.9k | for (char32_t c : label) { |
6600 | 24.9k | *dest++ = static_cast<char>(c); |
6601 | 24.9k | } |
6602 | 2.77k | } |
6603 | | |
6604 | | // True if label begins with "xn--" (already lowercased by mapping). |
6605 | 6.30k | static bool is_ace_prefix(std::u32string_view label) noexcept { |
6606 | 6.30k | return label.size() >= 4 && label[0] == U'x' && label[1] == U'n' && |
6607 | 1.27k | label[2] == U'-' && label[3] == U'-'; |
6608 | 6.30k | } |
6609 | | |
6610 | 2.76k | [[nodiscard]] bool to_ascii(std::string_view ut8_string, std::string& out) { |
6611 | 2.76k | 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 | 2.76k | if (is_ascii(ut8_string)) { |
6616 | 145 | from_ascii_to_ascii(ut8_string, out); |
6617 | 145 | return true; |
6618 | 145 | } |
6619 | 2.62k | 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 | 2.62k | size_t utf32_length = |
6634 | 2.62k | ada::idna::utf32_length_from_utf8(ut8_string.data(), ut8_string.size()); |
6635 | 2.62k | if (utf32_length == 0 && !ut8_string.empty()) { |
6636 | 4 | return false; |
6637 | 4 | } |
6638 | 2.61k | std::u32string working(utf32_length, U'\0'); |
6639 | 2.61k | size_t actual_utf32_length = ada::idna::utf8_to_utf32( |
6640 | 2.61k | ut8_string.data(), ut8_string.size(), working.data()); |
6641 | 2.61k | #endif |
6642 | 2.61k | if (actual_utf32_length == 0 || actual_utf32_length != utf32_length) { |
6643 | 159 | return false; |
6644 | 159 | } |
6645 | 2.45k | working.resize(actual_utf32_length); |
6646 | | |
6647 | | // Map into a second buffer with exact sizing (no growth reallocs). |
6648 | 2.45k | std::u32string mapped; |
6649 | 2.45k | if (!ada::idna::map(working, mapped)) { |
6650 | 36 | return false; |
6651 | 36 | } |
6652 | | // Drop UTF-32 input; reuse `working` as scratch for ACE validation below. |
6653 | 2.42k | working.clear(); |
6654 | | |
6655 | | // Skip NFC when already normalized (ASCII is a fast subset of this check). |
6656 | 2.42k | if (!is_ascii(mapped) && !is_already_nfc(mapped)) { |
6657 | 449 | if (!normalize(mapped)) { |
6658 | 0 | return false; |
6659 | 0 | } |
6660 | 449 | } |
6661 | | |
6662 | | // Estimate ASCII output size (punycode may expand non-ASCII labels). |
6663 | 2.42k | out.reserve(mapped.size() + 8); |
6664 | | |
6665 | | // Walk labels with a single pointer scan (no repeated string::find). |
6666 | 2.42k | const char32_t* p = mapped.data(); |
6667 | 2.42k | const char32_t* const end = p + mapped.size(); |
6668 | 2.42k | std::u32string post_map; |
6669 | | |
6670 | 8.05k | while (p < end) { |
6671 | 6.56k | const char32_t* label_begin = p; |
6672 | 65.3k | while (p < end && *p != U'.') { |
6673 | 58.8k | ++p; |
6674 | 58.8k | } |
6675 | 6.56k | const size_t label_size = static_cast<size_t>(p - label_begin); |
6676 | 6.56k | std::u32string_view label_view(label_begin, label_size); |
6677 | 6.56k | const bool is_last_label = (p == end); |
6678 | 6.56k | if (p < end) { |
6679 | 5.08k | ++p; // skip dot |
6680 | 5.08k | } |
6681 | | |
6682 | 6.56k | if (label_size == 0) { |
6683 | | // empty label |
6684 | 6.30k | } else if (is_ace_prefix(label_view)) { |
6685 | 21.4k | for (char32_t c : label_view) { |
6686 | 21.4k | if (c >= 0x80) { |
6687 | 12 | out.clear(); |
6688 | 12 | return false; |
6689 | 12 | } |
6690 | 21.4k | } |
6691 | 1.16k | append_ascii_label(out, label_view); |
6692 | 1.16k | std::string_view puny_segment_ascii( |
6693 | 1.16k | out.data() + (out.size() - label_size) + 4, label_size - 4); |
6694 | 1.16k | working.clear(); |
6695 | 1.16k | if (!ada::idna::punycode_to_utf32(puny_segment_ascii, working)) { |
6696 | 93 | out.clear(); |
6697 | 93 | return false; |
6698 | 93 | } |
6699 | 1.07k | if (is_ascii(working)) { |
6700 | 46 | out.clear(); |
6701 | 46 | return false; |
6702 | 46 | } |
6703 | 1.03k | if (!ada::idna::map(working, post_map) || working != post_map) { |
6704 | 194 | out.clear(); |
6705 | 194 | return false; |
6706 | 194 | } |
6707 | | // Mapping must be stable; NFC must not change the mapped form either. |
6708 | 836 | if (!is_ascii(post_map) && !is_already_nfc(post_map)) { |
6709 | 429 | if (!normalize(post_map) || post_map != working) { |
6710 | 97 | out.clear(); |
6711 | 97 | return false; |
6712 | 97 | } |
6713 | 429 | } |
6714 | 739 | if (post_map.empty() || !is_label_valid(post_map)) { |
6715 | 18 | out.clear(); |
6716 | 18 | return false; |
6717 | 18 | } |
6718 | 5.12k | } else if (is_ascii(label_view)) { |
6719 | 1.60k | append_ascii_label(out, label_view); |
6720 | 3.52k | } else { |
6721 | 3.52k | if (!is_label_valid(label_view)) { |
6722 | 471 | out.clear(); |
6723 | 471 | return false; |
6724 | 471 | } |
6725 | 3.05k | out.append("xn--"); |
6726 | 3.05k | if (!ada::idna::utf32_to_punycode(label_view, out)) { |
6727 | 0 | out.clear(); |
6728 | 0 | return false; |
6729 | 0 | } |
6730 | 3.05k | } |
6731 | 5.63k | if (!is_last_label) { |
6732 | 4.16k | out.push_back('.'); |
6733 | 4.16k | } |
6734 | 5.63k | } |
6735 | 1.49k | return true; |
6736 | 2.42k | } |
6737 | | |
6738 | 2.76k | std::string to_ascii(std::string_view ut8_string) { |
6739 | 2.76k | std::string out; |
6740 | 2.76k | if (!to_ascii(ut8_string, out)) { |
6741 | 1.13k | return {}; |
6742 | 1.13k | } |
6743 | 1.63k | return out; |
6744 | 2.76k | } |
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 | 0 | constexpr bool is_ascii_letter(char32_t c) noexcept { |
6939 | 0 | return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); |
6940 | 0 | } |
6941 | | |
6942 | 0 | constexpr bool is_ascii_letter_or_digit(char32_t c) noexcept { |
6943 | 0 | return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || |
6944 | 0 | (c >= '0' && c <= '9'); |
6945 | 0 | } |
6946 | | |
6947 | 0 | 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 | 0 | if (first && (code_point == U'$' || code_point == U'_' || |
6952 | 0 | is_ascii_letter(code_point))) { |
6953 | 0 | return true; |
6954 | 0 | } |
6955 | 0 | if (!first && (code_point == U'$' || is_ascii_letter_or_digit(code_point))) { |
6956 | 0 | return true; |
6957 | 0 | } |
6958 | | |
6959 | | // Minimal error handling for invalid code point |
6960 | 0 | if (code_point > 0x10FFFF) { |
6961 | 0 | return false; |
6962 | 0 | } |
6963 | 0 | if (code_point >= 0xD800 && code_point <= 0xDFFF) { |
6964 | 0 | return false; |
6965 | 0 | } |
6966 | | |
6967 | 0 | 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 | 0 | const std::span<const uint32_t[2]> ranges = |
6974 | 0 | first ? std::span<const uint32_t[2]>{ada::idna::id_start, |
6975 | 0 | ada::idna::id_start_count} |
6976 | 0 | : std::span<const uint32_t[2]>{ada::idna::id_continue, |
6977 | 0 | ada::idna::id_continue_count}; |
6978 | |
|
6979 | 0 | const auto iter = std::ranges::lower_bound( |
6980 | 0 | ranges, code_point, {}, |
6981 | 0 | [](const auto& range) { return range[1]; }); // project to range-high |
6982 | |
|
6983 | 0 | return iter != ranges.end() && code_point >= (*iter)[0]; |
6984 | 0 | } |
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 | 54.1k | constexpr bool is_tabs_or_newline(char c) noexcept { |
7017 | 54.1k | return c == '\r' || c == '\n' || c == '\t'; |
7018 | 54.1k | } |
7019 | | |
7020 | 24.5k | constexpr uint64_t broadcast(uint8_t v) noexcept { |
7021 | 24.5k | return 0x101010101010101ull * v; |
7022 | 24.5k | } |
7023 | | |
7024 | 8.17k | constexpr bool to_lower_ascii(char* input, size_t length) noexcept { |
7025 | 8.17k | uint64_t broadcast_80 = broadcast(0x80); |
7026 | 8.17k | uint64_t broadcast_Ap = broadcast(128 - 'A'); |
7027 | 8.17k | uint64_t broadcast_Zp = broadcast(128 - 'Z' - 1); |
7028 | 8.17k | uint64_t non_ascii = 0; |
7029 | 8.17k | size_t i = 0; |
7030 | | |
7031 | 24.0k | for (; i + 7 < length; i += 8) { |
7032 | 15.9k | uint64_t word{}; |
7033 | 15.9k | memcpy(&word, input + i, sizeof(word)); |
7034 | 15.9k | non_ascii |= (word & broadcast_80); |
7035 | 15.9k | word ^= |
7036 | 15.9k | (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2; |
7037 | 15.9k | memcpy(input + i, &word, sizeof(word)); |
7038 | 15.9k | } |
7039 | 8.17k | if (i < length) { |
7040 | 6.31k | uint64_t word{}; |
7041 | 6.31k | memcpy(&word, input + i, length - i); |
7042 | 6.31k | non_ascii |= (word & broadcast_80); |
7043 | 6.31k | word ^= |
7044 | 6.31k | (((word + broadcast_Ap) ^ (word + broadcast_Zp)) & broadcast_80) >> 2; |
7045 | 6.31k | memcpy(input + i, &word, length - i); |
7046 | 6.31k | } |
7047 | 8.17k | return non_ascii == 0; |
7048 | 8.17k | } |
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 | 21.2k | std::string_view user_input) noexcept { |
7132 | | // first check for short strings in which case we do it naively. |
7133 | 21.2k | if (user_input.size() < 16) { // slow path |
7134 | 6.89k | return std::ranges::any_of(user_input, is_tabs_or_newline); |
7135 | 6.89k | } |
7136 | | // fast path for long strings (expected to be common) |
7137 | 14.3k | size_t i = 0; |
7138 | 14.3k | const __m128i mask1 = _mm_set1_epi8('\r'); |
7139 | 14.3k | const __m128i mask2 = _mm_set1_epi8('\n'); |
7140 | 14.3k | const __m128i mask3 = _mm_set1_epi8('\t'); |
7141 | | // If we supported SSSE3, we could use the algorithm that we use for NEON. |
7142 | 14.3k | __m128i running{0}; |
7143 | 49.1k | for (; i + 15 < user_input.size(); i += 16) { |
7144 | 34.8k | __m128i word = _mm_loadu_si128((const __m128i*)(user_input.data() + i)); |
7145 | 34.8k | running = _mm_or_si128( |
7146 | 34.8k | _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1), |
7147 | 34.8k | _mm_cmpeq_epi8(word, mask2))), |
7148 | 34.8k | _mm_cmpeq_epi8(word, mask3)); |
7149 | 34.8k | } |
7150 | 14.3k | if (i < user_input.size()) { |
7151 | 13.4k | __m128i word = _mm_loadu_si128( |
7152 | 13.4k | (const __m128i*)(user_input.data() + user_input.length() - 16)); |
7153 | 13.4k | running = _mm_or_si128( |
7154 | 13.4k | _mm_or_si128(running, _mm_or_si128(_mm_cmpeq_epi8(word, mask1), |
7155 | 13.4k | _mm_cmpeq_epi8(word, mask2))), |
7156 | 13.4k | _mm_cmpeq_epi8(word, mask3)); |
7157 | 13.4k | } |
7158 | 14.3k | return _mm_movemask_epi8(running) != 0; |
7159 | 21.2k | } |
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 | 0 | const char c) noexcept { |
7255 | 0 | return is_forbidden_host_code_point_table[uint8_t(c)]; |
7256 | 0 | } |
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 | 57.1k | const char c) noexcept { |
7278 | 57.1k | return is_forbidden_domain_code_point_table[uint8_t(c)]; |
7279 | 57.1k | } |
7280 | | |
7281 | | ada_really_inline constexpr bool contains_forbidden_domain_code_point( |
7282 | 8.75k | const char* input, size_t length) noexcept { |
7283 | 8.75k | size_t i = 0; |
7284 | 8.75k | uint8_t accumulator{}; |
7285 | 55.6k | for (; i + 4 <= length; i += 4) { |
7286 | 46.8k | accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])]; |
7287 | 46.8k | accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 1])]; |
7288 | 46.8k | accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 2])]; |
7289 | 46.8k | accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i + 3])]; |
7290 | 46.8k | } |
7291 | 20.5k | for (; i < length; i++) { |
7292 | 11.8k | accumulator |= is_forbidden_domain_code_point_table[uint8_t(input[i])]; |
7293 | 11.8k | } |
7294 | 8.75k | return accumulator; |
7295 | 8.75k | } |
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 | 11.9k | size_t length) noexcept { |
7319 | 11.9k | size_t i = 0; |
7320 | 11.9k | uint8_t accumulator{}; |
7321 | 61.6k | for (; i + 4 <= length; i += 4) { |
7322 | 49.6k | accumulator |= |
7323 | 49.6k | is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])]; |
7324 | 49.6k | accumulator |= |
7325 | 49.6k | is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 1])]; |
7326 | 49.6k | accumulator |= |
7327 | 49.6k | is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 2])]; |
7328 | 49.6k | accumulator |= |
7329 | 49.6k | is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i + 3])]; |
7330 | 49.6k | } |
7331 | 28.1k | for (; i < length; i++) { |
7332 | 16.2k | accumulator |= |
7333 | 16.2k | is_forbidden_domain_code_point_table_or_upper[uint8_t(input[i])]; |
7334 | 16.2k | } |
7335 | 11.9k | return accumulator; |
7336 | 11.9k | } |
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 | 48.4k | ada_really_inline constexpr bool is_alnum_plus(const char c) noexcept { |
7349 | 48.4k | 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 | 48.4k | } |
7354 | | |
7355 | 11.8k | ada_really_inline constexpr bool is_ascii_hex_digit(const char c) noexcept { |
7356 | 11.8k | return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || |
7357 | 2.74k | (c >= 'a' && c <= 'f'); |
7358 | 11.8k | } |
7359 | | |
7360 | 0 | 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 | 0 | return (c >= '0' && c <= '9'); |
7364 | 0 | } |
7365 | | |
7366 | 0 | 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 | 0 | return c <= 0x7F; |
7369 | 0 | } |
7370 | | |
7371 | 25.1k | ada_really_inline constexpr bool is_c0_control_or_space(const char c) noexcept { |
7372 | 25.1k | return (unsigned char)c <= ' '; |
7373 | 25.1k | } |
7374 | | |
7375 | | ada_really_inline constexpr bool is_ascii_tab_or_newline( |
7376 | 5.29k | const char c) noexcept { |
7377 | 5.29k | return c == '\t' || c == '\n' || c == '\r'; |
7378 | 5.29k | } |
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 | 4.17k | 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 | 4.17k | uint64_t half_length = uint64_t(input.size()) / 2; |
7390 | 4.17k | if (half_length - 1 > 2) { |
7391 | 2.45k | return false; |
7392 | 2.45k | } |
7393 | | // We have a string of length 2, 4 or 6. |
7394 | | // We now check the first character: |
7395 | 1.71k | if ((input[0] != '.') && (input[0] != '%')) { |
7396 | 222 | return false; |
7397 | 222 | } |
7398 | | // We are unlikely the get beyond this point. |
7399 | 1.49k | int hash_value = (input.size() + (unsigned)(input[0])) & 3; |
7400 | 1.49k | const std::string_view target = table_is_double_dot_path_segment[hash_value]; |
7401 | 1.49k | if (target.size() != input.size()) { |
7402 | 624 | return false; |
7403 | 624 | } |
7404 | | // We almost never get here. |
7405 | | // Optimizing the rest is relatively unimportant. |
7406 | 872 | auto prefix_equal_unsafe = [](std::string_view a, std::string_view b) { |
7407 | 872 | uint16_t A, B; |
7408 | 872 | memcpy(&A, a.data(), sizeof(A)); |
7409 | 872 | memcpy(&B, b.data(), sizeof(B)); |
7410 | 872 | return A == B; |
7411 | 872 | }; |
7412 | 872 | if (!prefix_equal_unsafe(input, target)) { |
7413 | 253 | return false; |
7414 | 253 | } |
7415 | 928 | for (size_t i = 2; i < input.size(); i++) { |
7416 | 567 | char c = input[i]; |
7417 | 567 | if ((uint8_t((c | 0x20) - 0x61) <= 25 ? (c | 0x20) : c) != target[i]) { |
7418 | 258 | return false; |
7419 | 258 | } |
7420 | 567 | } |
7421 | 361 | 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 | 619 | } |
7431 | | |
7432 | | ada_really_inline constexpr bool is_single_dot_path_segment( |
7433 | 7.61k | std::string_view input) noexcept { |
7434 | 7.61k | return input == "." || input == "%2e" || input == "%2E"; |
7435 | 7.61k | } |
7436 | | |
7437 | 4.74k | ada_really_inline constexpr bool is_lowercase_hex(const char c) noexcept { |
7438 | 4.74k | return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); |
7439 | 4.74k | } |
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 | 9.73k | unsigned constexpr convert_hex_to_binary(const char c) noexcept { |
7446 | 9.73k | return hex_to_binary_table[c - '0']; |
7447 | 9.73k | } |
7448 | | |
7449 | 1.03k | 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 | 1.03k | if (first_percent == std::string_view::npos) { |
7453 | 0 | return std::string(input); |
7454 | 0 | } |
7455 | | |
7456 | | // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) |
7457 | 1.03k | const char* const src = input.data(); |
7458 | 1.03k | 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 | 1.03k | std::string out(input.size(), '\0'); |
7464 | 1.03k | char* d = out.data(); |
7465 | 1.03k | char* const d0 = d; |
7466 | | |
7467 | 1.03k | std::memcpy(d, src, first_percent); |
7468 | 1.03k | d += first_percent; |
7469 | | |
7470 | 1.03k | const char* p = src + first_percent; |
7471 | 5.66k | while (p < end) { |
7472 | 4.63k | if (*p == '%') { |
7473 | | // Decode runs of valid %XX tightly (common for nested/encoded URLs). |
7474 | 7.80k | while (p + 2 < end && *p == '%') { |
7475 | 6.45k | if (!is_ascii_hex_digit(p[1]) || !is_ascii_hex_digit(p[2])) { |
7476 | 1.59k | break; |
7477 | 1.59k | } |
7478 | 4.86k | *d++ = static_cast<char>(convert_hex_to_binary(p[1]) * 16 + |
7479 | 4.86k | convert_hex_to_binary(p[2])); |
7480 | 4.86k | p += 3; |
7481 | 4.86k | } |
7482 | 2.93k | 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 | 1.73k | *d++ = *p++; |
7486 | 1.73k | } |
7487 | 2.93k | } else { |
7488 | 1.70k | const char* q = static_cast<const char*>( |
7489 | 1.70k | std::memchr(p, '%', static_cast<size_t>(end - p))); |
7490 | 1.70k | const char* run_end = q ? q : end; |
7491 | 1.70k | const size_t n = static_cast<size_t>(run_end - p); |
7492 | 1.70k | std::memcpy(d, p, n); |
7493 | 1.70k | d += n; |
7494 | 1.70k | p = run_end; |
7495 | 1.70k | } |
7496 | 4.63k | } |
7497 | | |
7498 | 1.03k | out.resize(static_cast<size_t>(d - d0)); |
7499 | 1.03k | return out; |
7500 | 1.03k | } |
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 | 51.6k | const uint8_t character_set[]) { |
7589 | 51.6k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { |
7590 | 29.8k | return character_sets::bit_at(character_set, c); |
7591 | 29.8k | }); |
7592 | | // Optimization: Don't iterate if percent encode is not required |
7593 | 51.6k | if (pointer == input.end()) { |
7594 | 49.0k | return std::string(input); |
7595 | 49.0k | } |
7596 | | |
7597 | 2.65k | std::string result; |
7598 | 2.65k | result.reserve(input.length()); // in the worst case, percent encoding might |
7599 | | // produce 3 characters. |
7600 | 2.65k | result.append(input.substr(0, std::distance(input.begin(), pointer))); |
7601 | 2.65k | if (static_cast<size_t>(input.end() - pointer) >= 48) { |
7602 | 491 | percent_encode_suffix(&*pointer, input.data() + input.size(), character_set, |
7603 | 491 | result); |
7604 | 2.16k | } else { |
7605 | 25.6k | for (; pointer != input.end(); pointer++) { |
7606 | 23.4k | if (character_sets::bit_at(character_set, *pointer)) { |
7607 | 14.0k | result.append(character_sets::hex + uint8_t(*pointer) * 4, 3); |
7608 | 14.0k | } else { |
7609 | 9.39k | result += *pointer; |
7610 | 9.39k | } |
7611 | 23.4k | } |
7612 | 2.16k | } |
7613 | 2.65k | return result; |
7614 | 51.6k | } |
7615 | | |
7616 | | template <bool append> |
7617 | | bool percent_encode(const std::string_view input, const uint8_t character_set[], |
7618 | 89.9k | std::string& out) { |
7619 | 89.9k | ada_log("percent_encode ", input, " to output string while ", |
7620 | 89.9k | append ? "appending" : "overwriting"); |
7621 | 89.9k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { |
7622 | 60.0k | return character_sets::bit_at(character_set, c); |
7623 | 60.0k | }); ada::unicode::percent_encode<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)::{lambda(char)#1}::operator()(char) constLine | Count | Source | 7621 | 28.8k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { | 7622 | 28.8k | return character_sets::bit_at(character_set, c); | 7623 | 28.8k | }); |
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) constLine | Count | Source | 7621 | 31.2k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { | 7622 | 31.2k | return character_sets::bit_at(character_set, c); | 7623 | 31.2k | }); |
|
7624 | 89.9k | ada_log("percent_encode done checking, moved to ", |
7625 | 89.9k | std::distance(input.begin(), pointer)); |
7626 | | |
7627 | | // Optimization: Don't iterate if percent encode is not required |
7628 | 89.9k | if (pointer == input.end()) { |
7629 | 84.4k | ada_log("percent_encode encoding not needed."); |
7630 | 84.4k | return false; |
7631 | 84.4k | } |
7632 | 5.45k | if constexpr (!append) { |
7633 | 3.19k | out.clear(); |
7634 | 3.19k | } |
7635 | 5.45k | ada_log("percent_encode appending ", std::distance(input.begin(), pointer), |
7636 | 5.45k | " bytes"); |
7637 | | // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) |
7638 | 5.45k | out.append(input.data(), std::distance(input.begin(), pointer)); |
7639 | 5.45k | ada_log("percent_encode processing ", std::distance(pointer, input.end()), |
7640 | 5.45k | " bytes"); |
7641 | 110k | for (; pointer != input.end(); pointer++) { |
7642 | 104k | if (character_sets::bit_at(character_set, *pointer)) { |
7643 | 57.0k | out.append(character_sets::hex + uint8_t(*pointer) * 4, 3); |
7644 | 57.0k | } else { |
7645 | 47.6k | out += *pointer; |
7646 | 47.6k | } |
7647 | 104k | } |
7648 | 5.45k | return true; |
7649 | 89.9k | } 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 | 43.5k | std::string& out) { | 7619 | 43.5k | ada_log("percent_encode ", input, " to output string while ", | 7620 | 43.5k | append ? "appending" : "overwriting"); | 7621 | 43.5k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { | 7622 | 43.5k | return character_sets::bit_at(character_set, c); | 7623 | 43.5k | }); | 7624 | 43.5k | ada_log("percent_encode done checking, moved to ", | 7625 | 43.5k | std::distance(input.begin(), pointer)); | 7626 | | | 7627 | | // Optimization: Don't iterate if percent encode is not required | 7628 | 43.5k | if (pointer == input.end()) { | 7629 | 41.3k | ada_log("percent_encode encoding not needed."); | 7630 | 41.3k | return false; | 7631 | 41.3k | } | 7632 | | if constexpr (!append) { | 7633 | | out.clear(); | 7634 | | } | 7635 | 2.25k | ada_log("percent_encode appending ", std::distance(input.begin(), pointer), | 7636 | 2.25k | " bytes"); | 7637 | | // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) | 7638 | 2.25k | out.append(input.data(), std::distance(input.begin(), pointer)); | 7639 | 2.25k | ada_log("percent_encode processing ", std::distance(pointer, input.end()), | 7640 | 2.25k | " bytes"); | 7641 | 52.5k | for (; pointer != input.end(); pointer++) { | 7642 | 50.3k | if (character_sets::bit_at(character_set, *pointer)) { | 7643 | 26.4k | out.append(character_sets::hex + uint8_t(*pointer) * 4, 3); | 7644 | 26.4k | } else { | 7645 | 23.8k | out += *pointer; | 7646 | 23.8k | } | 7647 | 50.3k | } | 7648 | 2.25k | return true; | 7649 | 43.5k | } |
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 | 46.3k | std::string& out) { | 7619 | 46.3k | ada_log("percent_encode ", input, " to output string while ", | 7620 | 46.3k | append ? "appending" : "overwriting"); | 7621 | 46.3k | auto pointer = std::ranges::find_if(input, [character_set](const char c) { | 7622 | 46.3k | return character_sets::bit_at(character_set, c); | 7623 | 46.3k | }); | 7624 | 46.3k | ada_log("percent_encode done checking, moved to ", | 7625 | 46.3k | std::distance(input.begin(), pointer)); | 7626 | | | 7627 | | // Optimization: Don't iterate if percent encode is not required | 7628 | 46.3k | if (pointer == input.end()) { | 7629 | 43.1k | ada_log("percent_encode encoding not needed."); | 7630 | 43.1k | return false; | 7631 | 43.1k | } | 7632 | 3.19k | if constexpr (!append) { | 7633 | 3.19k | out.clear(); | 7634 | 3.19k | } | 7635 | 3.19k | ada_log("percent_encode appending ", std::distance(input.begin(), pointer), | 7636 | 3.19k | " bytes"); | 7637 | | // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) | 7638 | 3.19k | out.append(input.data(), std::distance(input.begin(), pointer)); | 7639 | 3.19k | ada_log("percent_encode processing ", std::distance(pointer, input.end()), | 7640 | 3.19k | " bytes"); | 7641 | 57.6k | for (; pointer != input.end(); pointer++) { | 7642 | 54.4k | if (character_sets::bit_at(character_set, *pointer)) { | 7643 | 30.6k | out.append(character_sets::hex + uint8_t(*pointer) * 4, 3); | 7644 | 30.6k | } else { | 7645 | 23.7k | out += *pointer; | 7646 | 23.7k | } | 7647 | 54.4k | } | 7648 | 3.19k | return true; | 7649 | 46.3k | } |
|
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 | 2.76k | size_t first_percent) { |
7660 | 2.76k | std::string percent_decoded_buffer; |
7661 | 2.76k | std::string_view input = plain; |
7662 | 2.76k | if (first_percent != std::string_view::npos) { |
7663 | 126 | percent_decoded_buffer = unicode::percent_decode(plain, first_percent); |
7664 | 126 | input = percent_decoded_buffer; |
7665 | 126 | } |
7666 | | // input is a non-empty UTF-8 string, must be percent decoded |
7667 | 2.76k | std::string idna_ascii = ada::idna::to_ascii(input); |
7668 | 2.76k | if (idna_ascii.empty() || contains_forbidden_domain_code_point( |
7669 | 1.63k | idna_ascii.data(), idna_ascii.size())) { |
7670 | 1.33k | return false; |
7671 | 1.33k | } |
7672 | 1.43k | out = std::move(idna_ascii); |
7673 | 1.43k | return true; |
7674 | 2.76k | } |
7675 | | |
7676 | | std::string percent_encode(const std::string_view input, |
7677 | 42.7k | const uint8_t character_set[], size_t index) { |
7678 | 42.7k | std::string out; |
7679 | | // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage) |
7680 | 42.7k | out.append(input.data(), index); |
7681 | 42.7k | auto pointer = input.begin() + index; |
7682 | 42.7k | if (static_cast<size_t>(input.end() - pointer) >= 48) { |
7683 | 746 | percent_encode_suffix(&*pointer, input.data() + input.size(), character_set, |
7684 | 746 | out); |
7685 | 41.9k | } else { |
7686 | 58.4k | for (; pointer != input.end(); pointer++) { |
7687 | 16.4k | if (character_sets::bit_at(character_set, *pointer)) { |
7688 | 6.61k | out.append(character_sets::hex + uint8_t(*pointer) * 4, 3); |
7689 | 9.83k | } else { |
7690 | 9.83k | out += *pointer; |
7691 | 9.83k | } |
7692 | 16.4k | } |
7693 | 41.9k | } |
7694 | 42.7k | return out; |
7695 | 42.7k | } |
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 | 33.3k | 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 | 33.3k | return __builtin_ctz(input_num); |
7752 | 33.3k | #endif |
7753 | 33.3k | } |
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 | 3.74k | size_t width, std::string& out) { |
7758 | 3.74k | uint64_t bits = mask; |
7759 | 3.74k | size_t off = 0; |
7760 | 37.0k | while (bits != 0) { |
7761 | 33.3k | const int zero_run = trailing_zeroes32(static_cast<uint32_t>(bits)); |
7762 | 33.3k | if (zero_run != 0) { |
7763 | 4.33k | out.append(p + off, static_cast<size_t>(zero_run)); |
7764 | 4.33k | } |
7765 | 33.3k | off += static_cast<size_t>(zero_run); |
7766 | 33.3k | out.append(character_sets::hex + uint8_t(p[off]) * 4, 3); |
7767 | 33.3k | ++off; |
7768 | 33.3k | bits >>= static_cast<unsigned>(zero_run + 1); |
7769 | 33.3k | } |
7770 | 3.74k | if (off < width) { |
7771 | 1.69k | out.append(p + off, width - off); |
7772 | 1.69k | } |
7773 | 3.74k | } |
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 | 1.23k | std::string& out) { |
7779 | 4.42k | for (; p != end; ++p) { |
7780 | 3.18k | if (character_sets::bit_at(character_set, *p)) { |
7781 | 971 | out.append(character_sets::hex + uint8_t(*p) * 4, 3); |
7782 | 2.21k | } else { |
7783 | 2.21k | out += *p; |
7784 | 2.21k | } |
7785 | 3.18k | } |
7786 | 1.23k | } |
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 | 1.23k | load_ssse3_percent_tables(const uint8_t character_set[]) noexcept { |
7803 | 1.23k | ssse3_percent_tables t{}; |
7804 | 1.23k | t.cs_lo = _mm_loadu_si128(reinterpret_cast<const __m128i*>(character_set)); |
7805 | 1.23k | t.cs_hi = |
7806 | 1.23k | _mm_loadu_si128(reinterpret_cast<const __m128i*>(character_set + 16)); |
7807 | | // 1 << (0..7), duplicated so pshufb(index & 7) works for every lane. |
7808 | 1.23k | t.pow2 = |
7809 | 1.23k | _mm_setr_epi8(1, 2, 4, 8, 16, 32, 64, -128, 1, 2, 4, 8, 16, 32, 64, -128); |
7810 | 1.23k | t.mask_0f = _mm_set1_epi8(0x0F); |
7811 | 1.23k | t.mask_07 = _mm_set1_epi8(0x07); |
7812 | 1.23k | t.zero = _mm_setzero_si128(); |
7813 | 1.23k | return t; |
7814 | 1.23k | } |
7815 | | |
7816 | | ADA_UNICODE_SIMD int ssse3_percent_mask( |
7817 | 5.06k | __m128i word, const ssse3_percent_tables& tables) noexcept { |
7818 | 5.06k | const __m128i idx = _mm_and_si128(_mm_srli_epi16(word, 3), tables.mask_0f); |
7819 | 5.06k | const __m128i lo = _mm_shuffle_epi8(tables.cs_lo, idx); |
7820 | 5.06k | 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 | 5.06k | const __m128i high_byte = _mm_cmpgt_epi8(tables.zero, word); |
7823 | 5.06k | const __m128i cs_byte = _mm_or_si128(_mm_and_si128(hi, high_byte), |
7824 | 5.06k | _mm_andnot_si128(high_byte, lo)); |
7825 | 5.06k | const __m128i bits = |
7826 | 5.06k | _mm_shuffle_epi8(tables.pow2, _mm_and_si128(word, tables.mask_07)); |
7827 | 5.06k | const __m128i hits = _mm_and_si128(cs_byte, bits); |
7828 | 5.06k | return _mm_movemask_epi8(_mm_cmpeq_epi8(hits, tables.zero)) ^ 0xFFFF; |
7829 | 5.06k | } |
7830 | | |
7831 | | ADA_UNICODE_SIMD void percent_encode_to_ssse3( |
7832 | | const char* p, const char* end, const uint8_t character_set[], |
7833 | 1.23k | const ssse3_percent_tables& tables, std::string& out) { |
7834 | | // Pair 16-byte windows so a fully clean 32-byte run is one append. |
7835 | 3.33k | while (p + 32 <= end) { |
7836 | 2.09k | const __m128i word0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p)); |
7837 | 2.09k | const __m128i word1 = |
7838 | 2.09k | _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + 16)); |
7839 | 2.09k | const int mask0 = ssse3_percent_mask(word0, tables); |
7840 | 2.09k | const int mask1 = ssse3_percent_mask(word1, tables); |
7841 | 2.09k | if ((mask0 | mask1) == 0) { |
7842 | 349 | out.append(p, 32); |
7843 | 1.74k | } else { |
7844 | 1.74k | if (mask0 == 0) { |
7845 | 183 | out.append(p, 16); |
7846 | 1.56k | } else { |
7847 | 1.56k | encode_mask_window(p, static_cast<uint32_t>(mask0), 16, out); |
7848 | 1.56k | } |
7849 | 1.74k | if (mask1 == 0) { |
7850 | 242 | out.append(p + 16, 16); |
7851 | 1.50k | } else { |
7852 | 1.50k | encode_mask_window(p + 16, static_cast<uint32_t>(mask1), 16, out); |
7853 | 1.50k | } |
7854 | 1.74k | } |
7855 | 2.09k | p += 32; |
7856 | 2.09k | } |
7857 | 1.23k | if (p + 16 <= end) { |
7858 | 874 | const __m128i word = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p)); |
7859 | 874 | const int mask = ssse3_percent_mask(word, tables); |
7860 | 874 | if (mask == 0) { |
7861 | 198 | out.append(p, 16); |
7862 | 676 | } else { |
7863 | 676 | encode_mask_window(p, static_cast<uint32_t>(mask), 16, out); |
7864 | 676 | } |
7865 | 874 | p += 16; |
7866 | 874 | } |
7867 | 1.23k | percent_encode_to_scalar(p, end, character_set, out); |
7868 | 1.23k | } |
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 | 1.23k | const uint8_t character_set[], std::string& out) { |
7976 | | // Worst case every byte becomes %XX. Avoids realloc while walking windows. |
7977 | 1.23k | out.reserve(out.size() + static_cast<size_t>(end - p) * 3); |
7978 | 1.23k | #if ADA_UNICODE_SSSE3 |
7979 | 1.23k | const ssse3_percent_tables tables = load_ssse3_percent_tables(character_set); |
7980 | 1.23k | 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 | 1.23k | } |
7988 | | #endif |
7989 | | |
7990 | | } // namespace |
7991 | | |
7992 | | void percent_encode_suffix(const char* p, const char* end, |
7993 | 1.23k | const uint8_t character_set[], std::string& out) { |
7994 | 1.23k | #if ADA_UNICODE_SSSE3 || ADA_NEON || ADA_RVV |
7995 | 1.23k | #ifdef ADA_UNICODE_NEED_SSSE3_TARGET |
7996 | 1.23k | static const bool ssse3_supported = __builtin_cpu_supports("ssse3") != 0; |
7997 | 1.23k | const bool use_wide = ssse3_supported; |
7998 | | #else |
7999 | | const bool use_wide = true; |
8000 | | #endif |
8001 | 1.23k | if (use_wide && static_cast<size_t>(end - p) >= kPercentEncodeSimdMin) { |
8002 | 1.23k | percent_encode_to_wide(p, end, character_set, out); |
8003 | 1.23k | return; |
8004 | 1.23k | } |
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 | 31.4k | ada_really_inline char* write_u8(char* p, uint8_t v) noexcept { |
8035 | 31.4k | if (v < 10) { |
8036 | 7.02k | *p++ = static_cast<char>('0' + v); |
8037 | 24.3k | } else if (v < 100) { |
8038 | 14.0k | std::memcpy(p, &digit_pairs[static_cast<size_t>(v) * 2], 2); |
8039 | 14.0k | p += 2; |
8040 | 14.0k | } else { |
8041 | 10.3k | *p++ = static_cast<char>('0' + v / 100); |
8042 | 10.3k | std::memcpy(p, &digit_pairs[static_cast<size_t>(v % 100) * 2], 2); |
8043 | 10.3k | p += 2; |
8044 | 10.3k | } |
8045 | 31.4k | return p; |
8046 | 31.4k | } |
8047 | | |
8048 | 52.7k | ada_really_inline char* write_hex_u16(char* p, uint16_t v) noexcept { |
8049 | 52.7k | static constexpr char kHex[] = "0123456789abcdef"; |
8050 | 52.7k | if (v >= 0x1000) { |
8051 | 47.3k | *p++ = kHex[(v >> 12) & 0xf]; |
8052 | 47.3k | *p++ = kHex[(v >> 8) & 0xf]; |
8053 | 47.3k | *p++ = kHex[(v >> 4) & 0xf]; |
8054 | 47.3k | *p++ = kHex[v & 0xf]; |
8055 | 47.3k | } else if (v >= 0x100) { |
8056 | 1.39k | *p++ = kHex[(v >> 8) & 0xf]; |
8057 | 1.39k | *p++ = kHex[(v >> 4) & 0xf]; |
8058 | 1.39k | *p++ = kHex[v & 0xf]; |
8059 | 4.03k | } else if (v >= 0x10) { |
8060 | 2.04k | *p++ = kHex[(v >> 4) & 0xf]; |
8061 | 2.04k | *p++ = kHex[v & 0xf]; |
8062 | 2.04k | } else { |
8063 | 1.99k | *p++ = kHex[v & 0xf]; |
8064 | 1.99k | } |
8065 | 52.7k | return p; |
8066 | 52.7k | } |
8067 | | |
8068 | | } // namespace |
8069 | | |
8070 | | void find_longest_sequence_of_ipv6_pieces( |
8071 | | const std::array<uint16_t, 8>& address, size_t& compress, |
8072 | 14.2k | size_t& compress_length) noexcept { |
8073 | 14.2k | compress = 0; |
8074 | 14.2k | compress_length = 0; |
8075 | 14.2k | size_t i = 0; |
8076 | 121k | while (i < 8) { |
8077 | 107k | if (address[i] != 0) { |
8078 | 102k | ++i; |
8079 | 102k | continue; |
8080 | 102k | } |
8081 | 4.97k | size_t next = i + 1; |
8082 | 11.4k | while (next < 8 && address[next] == 0) { |
8083 | 6.47k | ++next; |
8084 | 6.47k | } |
8085 | 4.97k | const size_t count = next - i; |
8086 | 4.97k | if (count > compress_length) { |
8087 | 4.42k | compress_length = count; |
8088 | 4.42k | compress = i; |
8089 | 4.42k | } |
8090 | 4.97k | i = next; |
8091 | 4.97k | } |
8092 | 14.2k | } |
8093 | | |
8094 | 7.13k | std::string ipv6(const std::array<uint16_t, 8>& address) { |
8095 | 7.13k | size_t compress = 0; |
8096 | 7.13k | size_t compress_length = 0; |
8097 | 7.13k | find_longest_sequence_of_ipv6_pieces(address, compress, compress_length); |
8098 | | |
8099 | | // Skip compression when the longest zero run is a single piece. |
8100 | 7.13k | if (compress_length <= 1) { |
8101 | 6.04k | compress = compress_length = 8; |
8102 | 6.04k | } |
8103 | | |
8104 | | // Max: '[' + 8*4 hex + 7 ':' + ']' = 41 |
8105 | 7.13k | std::string output(4 * 8 + 7 + 2, '\0'); |
8106 | 7.13k | char* point = output.data(); |
8107 | 7.13k | *point++ = '['; |
8108 | 7.13k | size_t piece_index = 0; |
8109 | 53.1k | while (true) { |
8110 | 53.1k | if (piece_index == compress) { |
8111 | 1.09k | *point++ = ':'; |
8112 | | // If we skip a value initially, we need to write '::'. |
8113 | 1.09k | if (piece_index == 0) { |
8114 | 445 | *point++ = ':'; |
8115 | 445 | } |
8116 | 1.09k | piece_index += compress_length; |
8117 | 1.09k | if (piece_index == 8) { |
8118 | 356 | break; |
8119 | 356 | } |
8120 | 1.09k | } |
8121 | 52.7k | point = write_hex_u16(point, address[piece_index]); |
8122 | 52.7k | ++piece_index; |
8123 | 52.7k | if (piece_index == 8) { |
8124 | 6.78k | break; |
8125 | 6.78k | } |
8126 | 45.9k | *point++ = ':'; |
8127 | 45.9k | } |
8128 | 7.13k | *point++ = ']'; |
8129 | 7.13k | output.resize(static_cast<size_t>(point - output.data())); |
8130 | 7.13k | return output; |
8131 | 7.13k | } |
8132 | | |
8133 | 7.85k | std::string ipv4(const uint64_t address) { |
8134 | 7.85k | std::string output(15, '\0'); |
8135 | 7.85k | char* point = output.data(); |
8136 | 7.85k | point = write_u8(point, static_cast<uint8_t>(address >> 24)); |
8137 | 7.85k | *point++ = '.'; |
8138 | 7.85k | point = write_u8(point, static_cast<uint8_t>(address >> 16)); |
8139 | 7.85k | *point++ = '.'; |
8140 | 7.85k | point = write_u8(point, static_cast<uint8_t>(address >> 8)); |
8141 | 7.85k | *point++ = '.'; |
8142 | 7.85k | point = write_u8(point, static_cast<uint8_t>(address)); |
8143 | 7.85k | output.resize(static_cast<size_t>(point - output.data())); |
8144 | 7.85k | return output; |
8145 | 7.85k | } |
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 | 13.4k | uint32_t get_max_input_length() { |
8171 | 13.4k | return max_input_length_.load(std::memory_order_relaxed); |
8172 | 13.4k | } |
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 | 13.4k | std::string_view input, const result_type* base_url) { |
8550 | 13.4k | result_type u = ada::parser::parse_url_impl<result_type>(input, base_url); |
8551 | 13.4k | if (!u.is_valid) { |
8552 | 10.8k | return tl::unexpected(errors::type_error); |
8553 | 10.8k | } |
8554 | 2.52k | return u; |
8555 | 13.4k | } 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 | 13.4k | std::string_view input, const result_type* base_url) { | 8550 | 13.4k | result_type u = ada::parser::parse_url_impl<result_type>(input, base_url); | 8551 | 13.4k | if (!u.is_valid) { | 8552 | 10.8k | return tl::unexpected(errors::type_error); | 8553 | 10.8k | } | 8554 | 2.52k | return u; | 8555 | 13.4k | } |
|
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 | 12.1k | 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 | 12.1k | size_t location_of_first = input.find('#'); |
8788 | 12.1k | if (location_of_first == std::string_view::npos) { |
8789 | 11.9k | return std::nullopt; |
8790 | 11.9k | } |
8791 | 175 | std::string_view hash = input; |
8792 | 175 | hash.remove_prefix(location_of_first + 1); |
8793 | 175 | input.remove_suffix(input.size() - location_of_first); |
8794 | 175 | return hash; |
8795 | 12.1k | } |
8796 | | |
8797 | 361 | 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 | 361 | 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 | 361 | size_t last_delimiter = path.rfind('/'); |
8811 | 361 | if (last_delimiter != std::string::npos) { |
8812 | 166 | path.erase(last_delimiter); |
8813 | 166 | return true; |
8814 | 166 | } |
8815 | | |
8816 | 195 | return false; |
8817 | 361 | } |
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 | 174 | 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 | 174 | if (!ada::unicode::has_tabs_or_newline(input)) { |
8850 | 0 | return; |
8851 | 0 | } |
8852 | 174 | std::erase_if(input, ada::unicode::is_ascii_tab_or_newline); |
8853 | 174 | } |
8854 | | |
8855 | | ada_really_inline constexpr std::string_view substring(std::string_view input, |
8856 | 0 | size_t pos) { |
8857 | 0 | 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 | 0 | return input.substr(pos); |
8861 | 0 | } |
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 | 8.86k | 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 | 8.86k | return __builtin_ctzl(input_num); |
8879 | 8.86k | #endif // ADA_REGULAR_VISUAL_STUDIO |
8880 | 8.86k | } |
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 | 19.5k | std::string_view view, size_t location) noexcept { |
9051 | | // first check for short strings in which case we do it naively. |
9052 | 19.5k | if (view.size() - location < 16) { // slow path |
9053 | 42.2k | for (size_t i = location; i < view.size(); i++) { |
9054 | 42.2k | if (view[i] == ':' || view[i] == '/' || view[i] == '\\' || |
9055 | 32.1k | view[i] == '?' || view[i] == '[') { |
9056 | 10.5k | return i; |
9057 | 10.5k | } |
9058 | 42.2k | } |
9059 | 72 | return size_t(view.size()); |
9060 | 10.6k | } |
9061 | | // fast path for long strings (expected to be common) |
9062 | 8.88k | size_t i = location; |
9063 | 8.88k | const __m128i mask1 = _mm_set1_epi8(':'); |
9064 | 8.88k | const __m128i mask2 = _mm_set1_epi8('/'); |
9065 | 8.88k | const __m128i mask3 = _mm_set1_epi8('\\'); |
9066 | 8.88k | const __m128i mask4 = _mm_set1_epi8('?'); |
9067 | 8.88k | const __m128i mask5 = _mm_set1_epi8('['); |
9068 | | |
9069 | 11.7k | for (; i + 15 < view.size(); i += 16) { |
9070 | 10.5k | __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i)); |
9071 | 10.5k | __m128i m1 = _mm_cmpeq_epi8(word, mask1); |
9072 | 10.5k | __m128i m2 = _mm_cmpeq_epi8(word, mask2); |
9073 | 10.5k | __m128i m3 = _mm_cmpeq_epi8(word, mask3); |
9074 | 10.5k | __m128i m4 = _mm_cmpeq_epi8(word, mask4); |
9075 | 10.5k | __m128i m5 = _mm_cmpeq_epi8(word, mask5); |
9076 | 10.5k | __m128i m = _mm_or_si128( |
9077 | 10.5k | _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5); |
9078 | 10.5k | int mask = _mm_movemask_epi8(m); |
9079 | 10.5k | if (mask != 0) { |
9080 | 7.73k | return i + trailing_zeroes(mask); |
9081 | 7.73k | } |
9082 | 10.5k | } |
9083 | 1.14k | if (i < view.size()) { |
9084 | 1.14k | __m128i word = |
9085 | 1.14k | _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16)); |
9086 | 1.14k | __m128i m1 = _mm_cmpeq_epi8(word, mask1); |
9087 | 1.14k | __m128i m2 = _mm_cmpeq_epi8(word, mask2); |
9088 | 1.14k | __m128i m3 = _mm_cmpeq_epi8(word, mask3); |
9089 | 1.14k | __m128i m4 = _mm_cmpeq_epi8(word, mask4); |
9090 | 1.14k | __m128i m5 = _mm_cmpeq_epi8(word, mask5); |
9091 | 1.14k | __m128i m = _mm_or_si128( |
9092 | 1.14k | _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5); |
9093 | 1.14k | int mask = _mm_movemask_epi8(m); |
9094 | 1.14k | if (mask != 0) { |
9095 | 1.12k | return view.length() - 16 + trailing_zeroes(mask); |
9096 | 1.12k | } |
9097 | 1.14k | } |
9098 | 20 | return size_t(view.length()); |
9099 | 1.14k | } |
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 | 0 | size_t location) noexcept { |
9327 | | // first check for short strings in which case we do it naively. |
9328 | 0 | if (view.size() - location < 16) { // slow path |
9329 | 0 | for (size_t i = location; i < view.size(); i++) { |
9330 | 0 | if (view[i] == ':' || view[i] == '/' || view[i] == '?' || |
9331 | 0 | view[i] == '[') { |
9332 | 0 | return i; |
9333 | 0 | } |
9334 | 0 | } |
9335 | 0 | return size_t(view.size()); |
9336 | 0 | } |
9337 | | // fast path for long strings (expected to be common) |
9338 | 0 | size_t i = location; |
9339 | 0 | const __m128i mask1 = _mm_set1_epi8(':'); |
9340 | 0 | const __m128i mask2 = _mm_set1_epi8('/'); |
9341 | 0 | const __m128i mask4 = _mm_set1_epi8('?'); |
9342 | 0 | const __m128i mask5 = _mm_set1_epi8('['); |
9343 | |
|
9344 | 0 | for (; i + 15 < view.size(); i += 16) { |
9345 | 0 | __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i)); |
9346 | 0 | __m128i m1 = _mm_cmpeq_epi8(word, mask1); |
9347 | 0 | __m128i m2 = _mm_cmpeq_epi8(word, mask2); |
9348 | 0 | __m128i m4 = _mm_cmpeq_epi8(word, mask4); |
9349 | 0 | __m128i m5 = _mm_cmpeq_epi8(word, mask5); |
9350 | 0 | __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5)); |
9351 | 0 | int mask = _mm_movemask_epi8(m); |
9352 | 0 | if (mask != 0) { |
9353 | 0 | return i + trailing_zeroes(mask); |
9354 | 0 | } |
9355 | 0 | } |
9356 | 0 | if (i < view.size()) { |
9357 | 0 | __m128i word = |
9358 | 0 | _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16)); |
9359 | 0 | __m128i m1 = _mm_cmpeq_epi8(word, mask1); |
9360 | 0 | __m128i m2 = _mm_cmpeq_epi8(word, mask2); |
9361 | 0 | __m128i m4 = _mm_cmpeq_epi8(word, mask4); |
9362 | 0 | __m128i m5 = _mm_cmpeq_epi8(word, mask5); |
9363 | 0 | __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5)); |
9364 | 0 | int mask = _mm_movemask_epi8(m); |
9365 | 0 | if (mask != 0) { |
9366 | 0 | return view.length() - 16 + trailing_zeroes(mask); |
9367 | 0 | } |
9368 | 0 | } |
9369 | 0 | return size_t(view.length()); |
9370 | 0 | } |
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 | 12.0k | 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 | 12.0k | const size_t view_size = view.size(); |
9470 | 12.0k | size_t location = 0; |
9471 | 12.0k | 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 | 12.0k | if (is_special) { |
9492 | | // We move to the next delimiter. |
9493 | 12.0k | 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 | 19.5k | for (; location < view_size; |
9497 | 19.4k | location = find_next_host_delimiter_special(view, location)) { |
9498 | 19.4k | if (view[location] == '[') { |
9499 | 7.58k | location = view.find(']', location); |
9500 | 7.58k | 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 | 139 | location = view_size; |
9505 | 139 | break; |
9506 | 139 | } |
9507 | 11.8k | } else { |
9508 | 11.8k | found_colon = view[location] == ':'; |
9509 | 11.8k | break; |
9510 | 11.8k | } |
9511 | 19.4k | } |
9512 | 12.0k | } else { |
9513 | | // We move to the next delimiter. |
9514 | 0 | 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 | 0 | for (; location < view_size; |
9518 | 0 | location = find_next_host_delimiter(view, location)) { |
9519 | 0 | if (view[location] == '[') { |
9520 | 0 | location = view.find(']', location); |
9521 | 0 | 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 | 0 | location = view_size; |
9526 | 0 | break; |
9527 | 0 | } |
9528 | 0 | } else { |
9529 | 0 | found_colon = view[location] == ':'; |
9530 | 0 | break; |
9531 | 0 | } |
9532 | 0 | } |
9533 | 0 | } |
9534 | | // performance: remove_suffix may translate into a single instruction. |
9535 | 12.0k | view.remove_suffix(view_size - location); |
9536 | 12.0k | return {location, found_colon}; |
9537 | 12.0k | } |
9538 | | |
9539 | 12.1k | void trim_c0_whitespace(std::string_view& input) noexcept { |
9540 | 12.1k | while (!input.empty() && |
9541 | 12.1k | ada::unicode::is_c0_control_or_space(input.front())) { |
9542 | 0 | input.remove_prefix(1); |
9543 | 0 | } |
9544 | 12.1k | while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) { |
9545 | 0 | input.remove_suffix(1); |
9546 | 0 | } |
9547 | 12.1k | } |
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 | 7 | bool overlaps(std::string_view input1, const std::string& input2) noexcept { |
9715 | 7 | ada_log("helpers::overlaps check if string_view '", input1, "' [", |
9716 | 7 | input1.size(), " bytes] is part of string '", input2, "' [", |
9717 | 7 | input2.size(), " bytes]"); |
9718 | 7 | return !input1.empty() && !input2.empty() && input1.data() >= input2.data() && |
9719 | 6 | input1.data() < input2.data() + input2.size(); |
9720 | 7 | } |
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 | 2.02k | 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 | 7.49k | for (auto pos = view.begin(); pos != view.end(); ++pos) { |
9751 | 7.47k | if (authority_delimiter_special[(uint8_t)*pos]) { |
9752 | 2.00k | return pos - view.begin(); |
9753 | 2.00k | } |
9754 | 7.47k | } |
9755 | 28 | return size_t(view.size()); |
9756 | 2.02k | } |
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 | 0 | find_authority_delimiter(std::string_view view) noexcept { |
9769 | | // performance note: we might be able to gain further performance |
9770 | | // with SIMD instrinsics. |
9771 | 0 | for (auto pos = view.begin(); pos != view.end(); ++pos) { |
9772 | 0 | if (authority_delimiter[(uint8_t)*pos]) { |
9773 | 0 | return pos - view.begin(); |
9774 | 0 | } |
9775 | 0 | } |
9776 | 0 | return size_t(view.size()); |
9777 | 0 | } |
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 | 2.65k | bool& is_pure_decimal) noexcept { |
9837 | 2.65k | is_pure_decimal = false; |
9838 | 2.65k | if (p >= end) [[unlikely]] { |
9839 | 0 | return false; |
9840 | 0 | } |
9841 | 2.65k | if (end - p >= 2 && p[0] == '0' && ((p[1] | 0x20) == 'x')) { |
9842 | 210 | p += 2; |
9843 | 210 | if (p == end || *p == '.') { |
9844 | 16 | value = 0; |
9845 | 16 | return true; |
9846 | 16 | } |
9847 | 194 | uint64_t v = 0; |
9848 | 194 | int digits = 0; |
9849 | 1.34k | while (p < end && *p != '.') { |
9850 | 1.20k | const uint8_t nib = hex_nibble[static_cast<unsigned char>(*p)]; |
9851 | 1.20k | if (nib == 0xff) [[unlikely]] { |
9852 | 4 | return false; |
9853 | 4 | } |
9854 | 1.19k | if (v > (0xFFFFFFFFULL >> 4)) [[unlikely]] { |
9855 | 45 | return false; |
9856 | 45 | } |
9857 | 1.15k | v = (v << 4) | nib; |
9858 | 1.15k | ++p; |
9859 | 1.15k | ++digits; |
9860 | 1.15k | } |
9861 | 145 | if (digits == 0) [[unlikely]] { |
9862 | 0 | return false; |
9863 | 0 | } |
9864 | 145 | value = v; |
9865 | 145 | return true; |
9866 | 145 | } |
9867 | 2.44k | if (end - p >= 2 && p[0] == '0' && p[1] >= '0' && p[1] <= '9') { |
9868 | 88 | ++p; |
9869 | 88 | uint64_t v = 0; |
9870 | 647 | while (p < end && *p != '.') { |
9871 | 577 | const char c = *p; |
9872 | 577 | if (c < '0' || c > '7') [[unlikely]] { |
9873 | 14 | return false; |
9874 | 14 | } |
9875 | 563 | if (v > (0xFFFFFFFFULL >> 3)) [[unlikely]] { |
9876 | 4 | return false; |
9877 | 4 | } |
9878 | 559 | v = (v << 3) | static_cast<uint64_t>(c - '0'); |
9879 | 559 | ++p; |
9880 | 559 | } |
9881 | 70 | value = v; |
9882 | 70 | return true; |
9883 | 88 | } |
9884 | 2.36k | if (*p < '0' || *p > '9') [[unlikely]] { |
9885 | 1.57k | return false; |
9886 | 1.57k | } |
9887 | 782 | is_pure_decimal = true; |
9888 | 782 | uint64_t v = static_cast<uint64_t>(*p - '0'); |
9889 | 782 | ++p; |
9890 | 1.67k | while (p < end && *p != '.') { |
9891 | 946 | const char c = *p; |
9892 | 946 | if (c < '0' || c > '9') [[unlikely]] { |
9893 | 33 | return false; |
9894 | 33 | } |
9895 | 913 | if (v > 429496729ULL) [[unlikely]] { |
9896 | 17 | return false; |
9897 | 17 | } |
9898 | 896 | v = v * 10u + static_cast<uint64_t>(c - '0'); |
9899 | 896 | if (v > 0xFFFFFFFFULL) [[unlikely]] { |
9900 | 2 | return false; |
9901 | 2 | } |
9902 | 894 | ++p; |
9903 | 894 | } |
9904 | 730 | value = v; |
9905 | 730 | return true; |
9906 | 782 | } |
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 | 7.36k | uint16_t& value) noexcept { |
9911 | 7.36k | if (pointer == end) { |
9912 | 0 | return 0; |
9913 | 0 | } |
9914 | 7.36k | const uint8_t n0 = hex_nibble[static_cast<unsigned char>(*pointer)]; |
9915 | 7.36k | if (n0 == 0xff) { |
9916 | 7.13k | return 0; |
9917 | 7.13k | } |
9918 | 231 | uint32_t v = n0; |
9919 | 231 | ++pointer; |
9920 | 231 | int length = 1; |
9921 | 231 | if (pointer != end) { |
9922 | 212 | const uint8_t n1 = hex_nibble[static_cast<unsigned char>(*pointer)]; |
9923 | 212 | if (n1 != 0xff) { |
9924 | 74 | v = (v << 4) | n1; |
9925 | 74 | ++pointer; |
9926 | 74 | ++length; |
9927 | 74 | if (pointer != end) { |
9928 | 69 | const uint8_t n2 = hex_nibble[static_cast<unsigned char>(*pointer)]; |
9929 | 69 | if (n2 != 0xff) { |
9930 | 43 | v = (v << 4) | n2; |
9931 | 43 | ++pointer; |
9932 | 43 | ++length; |
9933 | 43 | if (pointer != end) { |
9934 | 42 | const uint8_t n3 = hex_nibble[static_cast<unsigned char>(*pointer)]; |
9935 | 42 | if (n3 != 0xff) { |
9936 | 18 | v = (v << 4) | n3; |
9937 | 18 | ++pointer; |
9938 | 18 | ++length; |
9939 | 18 | } |
9940 | 42 | } |
9941 | 43 | } |
9942 | 69 | } |
9943 | 74 | } |
9944 | 212 | } |
9945 | 231 | value = static_cast<uint16_t>(v); |
9946 | 231 | return length; |
9947 | 7.36k | } |
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()() constUnexecuted 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 | 127 | ada_really_inline uint32_t port_decimal_digit_count(uint32_t port) noexcept { |
11185 | 127 | uint32_t digits = 1; |
11186 | 396 | while (port >= 10) { |
11187 | 269 | port /= 10; |
11188 | 269 | ++digits; |
11189 | 269 | } |
11190 | 127 | return digits; |
11191 | 127 | } |
11192 | | |
11193 | | ada_really_inline void append_canonical_port(std::string& buffer, |
11194 | 118 | uint32_t port) { |
11195 | 118 | buffer += ':'; |
11196 | 118 | char port_buf[5]; |
11197 | 118 | auto [ptr, ec] = std::to_chars(port_buf, port_buf + 5, port); |
11198 | 118 | (void)ec; |
11199 | 118 | buffer.append(port_buf, static_cast<size_t>(ptr - port_buf)); |
11200 | 118 | } |
11201 | | |
11202 | 2.75k | 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 | 2.75k | return __builtin_ctz(input_num); |
11209 | 2.75k | #endif |
11210 | 2.75k | } |
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 | 5.96k | ADA_PARSER_SIMD __m128i nibble_load(const uint8_t* t) noexcept { |
11224 | 5.96k | return _mm_load_si128(reinterpret_cast<const __m128i*>(t)); |
11225 | 5.96k | } |
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 | 4.78k | __m128i hi_tbl) noexcept { |
11231 | 4.78k | const __m128i nibble = _mm_set1_epi8(0x0F); |
11232 | 4.78k | const __m128i lo = _mm_and_si128(w, nibble); |
11233 | 4.78k | const __m128i hi = _mm_and_si128(_mm_srli_epi16(w, 4), nibble); |
11234 | 4.78k | const __m128i hit = |
11235 | 4.78k | _mm_and_si128(_mm_shuffle_epi8(lo_tbl, lo), _mm_shuffle_epi8(hi_tbl, hi)); |
11236 | 4.78k | return _mm_movemask_epi8(_mm_cmpeq_epi8(hit, _mm_setzero_si128())) ^ 0xFFFF; |
11237 | 4.78k | } |
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 | 3.09k | ada_really_inline int sse2_uppercase(__m128i w) noexcept { |
11311 | 3.09k | return _mm_movemask_epi8(_mm_and_si128( |
11312 | 3.09k | _mm_cmpgt_epi8(w, _mm_set1_epi8(static_cast<char>('A' - 1))), |
11313 | 3.09k | _mm_cmplt_epi8(w, _mm_set1_epi8(static_cast<char>('Z' + 1))))); |
11314 | 3.09k | } |
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 | 13.4k | size_t n) noexcept { |
11343 | 13.4k | const size_t rem = n - host_start; |
11344 | 13.4k | 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 | 13.4k | if (rem >= 16) { |
11361 | 9.71k | const __m128i w = |
11362 | 9.71k | _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + host_start)); |
11363 | 9.71k | const uint16_t at = static_cast<uint16_t>( |
11364 | 9.71k | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('@')))); |
11365 | 9.71k | if (at == 0) { |
11366 | 9.59k | return false; |
11367 | 9.59k | } |
11368 | 120 | const uint16_t delim = static_cast<uint16_t>( |
11369 | 120 | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('/'))) | |
11370 | 120 | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('?'))) | |
11371 | 120 | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('#')))); |
11372 | 120 | return delim == 0 || std::countr_zero(at) < std::countr_zero(delim); |
11373 | 9.71k | } |
11374 | 3.70k | #endif |
11375 | 3.70k | const size_t lim = host_start + rem; |
11376 | 25.9k | for (size_t i = host_start; i < lim; ++i) { |
11377 | 25.9k | const uint8_t c = p[i]; |
11378 | 25.9k | if (c == '@') { |
11379 | 93 | return true; |
11380 | 93 | } |
11381 | 25.8k | if (c == '/' || c == '?' || c == '#') { |
11382 | 3.61k | return false; |
11383 | 3.61k | } |
11384 | 25.8k | } |
11385 | 0 | return false; |
11386 | 3.70k | } |
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 | 6.28k | ada_really_inline bool parser_use_ssse3() noexcept { |
11393 | 6.28k | #ifdef ADA_PARSER_NEED_SSSE3_TARGET |
11394 | 6.28k | static const bool supported = __builtin_cpu_supports("ssse3") != 0; |
11395 | 6.28k | return supported; |
11396 | | #else |
11397 | | return true; |
11398 | | #endif |
11399 | 6.28k | } |
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 | 4.71k | bool& has_x) noexcept { |
11408 | 4.71k | has_upper = false; |
11409 | 4.71k | has_x = false; |
11410 | 4.71k | size_t i = start; |
11411 | 4.71k | #if ADA_PARSER_SSSE3 |
11412 | 4.71k | if (parser_use_ssse3() && (len - start >= 16)) { |
11413 | 2.17k | const __m128i lo_tbl = nibble_load(k_host_nibbles.low); |
11414 | 2.17k | const __m128i hi_tbl = nibble_load(k_host_nibbles.high); |
11415 | 2.17k | const __m128i x_splat = _mm_set1_epi8('x'); |
11416 | 3.09k | auto visit = [&](size_t at) noexcept -> bool { |
11417 | 3.09k | const __m128i w = |
11418 | 3.09k | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + at)); |
11419 | 3.09k | const int up = sse2_uppercase(w); |
11420 | 3.09k | const int xs = _mm_movemask_epi8(_mm_cmpeq_epi8(w, x_splat)); |
11421 | 3.09k | const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl); |
11422 | 3.09k | if (mask == 0) { |
11423 | 920 | if (up != 0) { |
11424 | 536 | has_upper = true; |
11425 | 536 | } |
11426 | 920 | if (xs != 0) { |
11427 | 496 | has_x = true; |
11428 | 496 | } |
11429 | 920 | return false; |
11430 | 920 | } |
11431 | 2.17k | const int hit = trailing_zeroes32(static_cast<uint32_t>(mask)); |
11432 | 2.17k | const int valid = (1 << hit) - 1; |
11433 | 2.17k | if ((up & valid) != 0) { |
11434 | 491 | has_upper = true; |
11435 | 491 | } |
11436 | 2.17k | if ((xs & valid) != 0) { |
11437 | 508 | has_x = true; |
11438 | 508 | } |
11439 | 2.17k | end = at + static_cast<size_t>(hit); |
11440 | 2.17k | return true; |
11441 | 3.09k | }; |
11442 | 2.48k | for (; i + 32 <= len; i += 32) { |
11443 | 1.33k | if (visit(i) || visit(i + 16)) { |
11444 | 1.02k | return k_host_class[b[end]] == 1; |
11445 | 1.02k | } |
11446 | 1.33k | } |
11447 | 1.34k | for (; i + 16 <= len; i += 16) { |
11448 | 1.04k | if (visit(i)) { |
11449 | 845 | return k_host_class[b[end]] == 1; |
11450 | 845 | } |
11451 | 1.04k | } |
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 | 304 | if (i > start && i < len) { |
11455 | 304 | if (visit(len - 16) && end >= i) { |
11456 | 304 | return k_host_class[b[end]] == 1; |
11457 | 304 | } |
11458 | 0 | end = len; |
11459 | 0 | return true; |
11460 | 304 | } |
11461 | 304 | } |
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 | 5.78k | for (; i < len; ++i) { |
11565 | 5.78k | const uint8_t c = b[i]; |
11566 | 5.78k | const uint8_t cls = k_host_class[c]; |
11567 | 5.78k | if (cls == 1) { |
11568 | 889 | end = i; |
11569 | 889 | return true; |
11570 | 889 | } |
11571 | 4.89k | if (cls == 2) { |
11572 | 1.65k | return false; |
11573 | 1.65k | } |
11574 | 3.24k | if (c >= 'A' && c <= 'Z') { |
11575 | 444 | has_upper = true; |
11576 | 2.80k | } else if (c == 'x') { |
11577 | 511 | has_x = true; |
11578 | 511 | } |
11579 | 3.24k | } |
11580 | 0 | end = len; |
11581 | 0 | return true; |
11582 | 2.53k | } |
11583 | | |
11584 | | ada_really_inline void note_possible_dot_segment( |
11585 | | const uint8_t* b, size_t pos, size_t run_start, |
11586 | 677 | bool& maybe_dot_segment) noexcept { |
11587 | 677 | if (pos == run_start || b[pos - 1] == '/') { |
11588 | 347 | maybe_dot_segment = true; |
11589 | 347 | } |
11590 | 677 | } |
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 | 1.12k | bool& maybe_dot_segment) noexcept { |
11600 | 1.12k | if (maybe_dot_segment || valid_mask == 0) { |
11601 | 334 | return; |
11602 | 334 | } |
11603 | 791 | const int dots = |
11604 | 791 | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('.'))) & valid_mask; |
11605 | 791 | if (dots == 0) { |
11606 | 221 | return; |
11607 | 221 | } |
11608 | 570 | const int slashes = |
11609 | 570 | _mm_movemask_epi8(_mm_cmpeq_epi8(w, _mm_set1_epi8('/'))) & valid_mask; |
11610 | 570 | if (((dots & 1) != 0 && (i == run_start || b[i - 1] == '/')) || |
11611 | 438 | (dots & (slashes << 1)) != 0) { |
11612 | 263 | maybe_dot_segment = true; |
11613 | 263 | } |
11614 | 570 | } |
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 | 1.06k | bool& maybe_dot_segment) noexcept { |
11643 | 1.06k | const size_t run_start = i; |
11644 | 1.06k | #if ADA_PARSER_SSSE3 |
11645 | 1.06k | if (parser_use_ssse3() && (i + 16 <= len)) { |
11646 | 612 | const __m128i lo_tbl = nibble_load(k_path_nibbles.low); |
11647 | 612 | const __m128i hi_tbl = nibble_load(k_path_nibbles.high); |
11648 | 879 | for (; i + 32 <= len; i += 32) { |
11649 | 488 | const __m128i w0 = |
11650 | 488 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i)); |
11651 | 488 | const int m0 = ssse3_nibble_mask(w0, lo_tbl, hi_tbl); |
11652 | 488 | if (m0 != 0) { |
11653 | 149 | const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(m0)); |
11654 | 149 | note_dots_in_window(b, i, run_start, w0, (1 << hit_bit) - 1, |
11655 | 149 | maybe_dot_segment); |
11656 | 149 | i += static_cast<size_t>(hit_bit); |
11657 | 149 | return; |
11658 | 149 | } |
11659 | 339 | note_dots_in_window(b, i, run_start, w0, 0xFFFF, maybe_dot_segment); |
11660 | 339 | const __m128i w1 = |
11661 | 339 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i + 16)); |
11662 | 339 | const int m1 = ssse3_nibble_mask(w1, lo_tbl, hi_tbl); |
11663 | 339 | if (m1 != 0) { |
11664 | 72 | const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(m1)); |
11665 | 72 | note_dots_in_window(b, i + 16, run_start, w1, (1 << hit_bit) - 1, |
11666 | 72 | maybe_dot_segment); |
11667 | 72 | i += 16 + static_cast<size_t>(hit_bit); |
11668 | 72 | return; |
11669 | 72 | } |
11670 | 267 | note_dots_in_window(b, i + 16, run_start, w1, 0xFFFF, maybe_dot_segment); |
11671 | 267 | } |
11672 | 561 | for (; i + 16 <= len; i += 16) { |
11673 | 298 | const __m128i w = |
11674 | 298 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i)); |
11675 | 298 | const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl); |
11676 | 298 | if (mask != 0) { |
11677 | 128 | const int hit_bit = trailing_zeroes32(static_cast<uint32_t>(mask)); |
11678 | 128 | note_dots_in_window(b, i, run_start, w, (1 << hit_bit) - 1, |
11679 | 128 | maybe_dot_segment); |
11680 | 128 | i += static_cast<size_t>(hit_bit); |
11681 | 128 | return; |
11682 | 128 | } |
11683 | 170 | note_dots_in_window(b, i, run_start, w, 0xFFFF, maybe_dot_segment); |
11684 | 170 | } |
11685 | 263 | if (i > run_start && i < len) { |
11686 | 189 | const __m128i w = |
11687 | 189 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + len - 16)); |
11688 | 189 | const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl); |
11689 | 189 | if (mask != 0) { |
11690 | 89 | const size_t hit = |
11691 | 89 | len - 16 + |
11692 | 89 | static_cast<size_t>(trailing_zeroes32(static_cast<uint32_t>(mask))); |
11693 | 89 | if (hit >= i) { |
11694 | 403 | for (size_t j = i; j < hit; ++j) { |
11695 | 314 | if (b[j] == '.') { |
11696 | 126 | note_possible_dot_segment(b, j, run_start, maybe_dot_segment); |
11697 | 126 | } |
11698 | 314 | } |
11699 | 89 | i = hit; |
11700 | 89 | return; |
11701 | 89 | } |
11702 | 89 | } |
11703 | 556 | for (size_t j = i; j < len; ++j) { |
11704 | 456 | if (b[j] == '.') { |
11705 | 157 | note_possible_dot_segment(b, j, run_start, maybe_dot_segment); |
11706 | 157 | } |
11707 | 456 | } |
11708 | 100 | i = len; |
11709 | 100 | return; |
11710 | 189 | } |
11711 | 263 | } |
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 | 1.68k | for (; i < len; ++i) { |
11800 | 1.47k | const uint8_t c = b[i]; |
11801 | 1.47k | const uint8_t cls = k_path[c]; |
11802 | 1.47k | if (cls != 0) { |
11803 | 320 | return; |
11804 | 320 | } |
11805 | 1.15k | if (c == '.') { |
11806 | 394 | note_possible_dot_segment(b, i, run_start, maybe_dot_segment); |
11807 | 394 | } |
11808 | 1.15k | } |
11809 | 527 | } |
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 | 507 | do { \ |
11816 | 507 | const size_t scan_start = i; \ |
11817 | 507 | if (parser_use_ssse3() && (i + 16 <= len)) { \ |
11818 | 190 | const __m128i lo_tbl = nibble_load((nibbles).low); \ |
11819 | 190 | const __m128i hi_tbl = nibble_load((nibbles).high); \ |
11820 | 249 | for (; i + 32 <= len; i += 32) { \ |
11821 | 134 | const __m128i w0 = \ |
11822 | 134 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i)); \ |
11823 | 134 | const int m0 = ssse3_nibble_mask(w0, lo_tbl, hi_tbl); \ |
11824 | 134 | if (m0 != 0) { \ |
11825 | 42 | i += static_cast<size_t>( \ |
11826 | 42 | trailing_zeroes32(static_cast<uint32_t>(m0))); \ |
11827 | 42 | return; \ |
11828 | 42 | } \ |
11829 | 134 | const __m128i w1 = \ |
11830 | 92 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i + 16)); \ |
11831 | 92 | const int m1 = ssse3_nibble_mask(w1, lo_tbl, hi_tbl); \ |
11832 | 92 | if (m1 != 0) { \ |
11833 | 33 | i += 16 + static_cast<size_t>( \ |
11834 | 33 | trailing_zeroes32(static_cast<uint32_t>(m1))); \ |
11835 | 33 | return; \ |
11836 | 33 | } \ |
11837 | 92 | } \ |
11838 | 190 | for (; i + 16 <= len; i += 16) { \ |
11839 | 98 | const __m128i w = \ |
11840 | 98 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + i)); \ |
11841 | 98 | const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl); \ |
11842 | 98 | if (mask != 0) { \ |
11843 | 49 | i += static_cast<size_t>( \ |
11844 | 49 | trailing_zeroes32(static_cast<uint32_t>(mask))); \ |
11845 | 49 | return; \ |
11846 | 49 | } \ |
11847 | 98 | } \ |
11848 | 115 | if (i > scan_start && i < len) { \ |
11849 | 45 | const __m128i w = \ |
11850 | 45 | _mm_loadu_si128(reinterpret_cast<const __m128i*>(b + len - 16)); \ |
11851 | 45 | const int mask = ssse3_nibble_mask(w, lo_tbl, hi_tbl); \ |
11852 | 45 | if (mask != 0) { \ |
11853 | 16 | const size_t hit = len - 16 + \ |
11854 | 16 | static_cast<size_t>(trailing_zeroes32( \ |
11855 | 16 | static_cast<uint32_t>(mask))); \ |
11856 | 16 | if (hit >= i) { \ |
11857 | 16 | i = hit; \ |
11858 | 16 | return; \ |
11859 | 16 | } \ |
11860 | 16 | } \ |
11861 | 45 | i = len; \ |
11862 | 29 | return; \ |
11863 | 45 | } \ |
11864 | 66 | } \ |
11865 | 1.25k | for (; i < len; ++i) { \ |
11866 | 1.00k | if ((cls)[b[i]] != 0) { \ |
11867 | 87 | return; \ |
11868 | 87 | } \ |
11869 | 1.00k | } \ |
11870 | 338 | } 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 | 296 | size_t len) noexcept { |
11953 | 296 | ADA_SCAN_STOP_RUN(k_query_nibbles, k_query, sse2_query_stop); |
11954 | 296 | } |
11955 | | |
11956 | | ADA_PARSER_SIMD void scan_hash_run(const uint8_t* b, size_t& i, |
11957 | 211 | size_t len) noexcept { |
11958 | 211 | ADA_SCAN_STOP_RUN(k_hash_nibbles, k_hash, sse2_hash_stop); |
11959 | 211 | } |
11960 | | |
11961 | | #undef ADA_SCAN_STOP_RUN |
11962 | | |
11963 | 298 | bool path_has_dot_segment(std::string_view path) noexcept { |
11964 | 298 | if (path.empty()) { |
11965 | 0 | return false; |
11966 | 0 | } |
11967 | | // "." / ".." at the start, with or without a leading '/'. |
11968 | 298 | const size_t i = (path[0] == '/') ? 1 : 0; |
11969 | 298 | if (i < path.size() && path[i] == '.') { |
11970 | 126 | const size_t after = i + 1; |
11971 | 126 | if (after == path.size() || path[after] == '/' || |
11972 | 96 | (after < path.size() && path[after] == '.' && |
11973 | 47 | (after + 1 == path.size() || path[after + 1] == '/'))) { |
11974 | 46 | return true; |
11975 | 46 | } |
11976 | 126 | } |
11977 | 252 | static constexpr std::string_view slash_dot{"/.", 2}; |
11978 | 252 | size_t p = i; |
11979 | 450 | while ((p = path.find(slash_dot, p)) != std::string_view::npos) { |
11980 | 309 | const size_t after = p + 2; |
11981 | 309 | if (after == path.size() || path[after] == '/' || |
11982 | 260 | (after < path.size() && path[after] == '.' && |
11983 | 118 | (after + 1 == path.size() || path[after + 1] == '/'))) { |
11984 | 111 | return true; |
11985 | 111 | } |
11986 | 198 | p = after; |
11987 | 198 | } |
11988 | 141 | return false; |
11989 | 252 | } |
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 | 670 | bool has_upper) { |
11998 | 670 | constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>; |
11999 | 670 | constexpr bool is_aggregator = |
12000 | 670 | std::is_same_v<result_type, ada::url_aggregator>; |
12001 | 670 | static_assert(is_ada_url || is_aggregator); |
12002 | | |
12003 | 670 | const size_t len = input.size(); |
12004 | 670 | const auto* b = reinterpret_cast<const uint8_t*>(input.data()); |
12005 | 670 | size_t p = host_end + 1; |
12006 | 670 | uint32_t port_value = 0; |
12007 | 670 | bool any_digit = false; |
12008 | 1.31k | while (p < len && b[p] >= '0' && b[p] <= '9') { |
12009 | 651 | any_digit = true; |
12010 | 651 | port_value = port_value * 10 + static_cast<uint32_t>(b[p] - '0'); |
12011 | 651 | if (port_value > 65535) [[unlikely]] { |
12012 | 9 | return false; |
12013 | 9 | } |
12014 | 642 | ++p; |
12015 | 642 | } |
12016 | 661 | if (p < len && b[p] != '/' && b[p] != '?' && b[p] != '#') [[unlikely]] { |
12017 | 180 | return false; |
12018 | 180 | } |
12019 | 481 | uint32_t parsed_port = url_components::omitted; |
12020 | 481 | const uint16_t default_port = ada::scheme::get_special_port(scheme_type); |
12021 | 481 | if (any_digit && port_value != default_port) { |
12022 | 128 | parsed_port = port_value; |
12023 | 128 | } |
12024 | 481 | const size_t authority_end = p; |
12025 | | |
12026 | 481 | size_t i = authority_end; |
12027 | 481 | size_t path_start = host_end; |
12028 | 481 | size_t path_end = host_end; |
12029 | 481 | size_t query_start = std::string_view::npos; |
12030 | 481 | size_t hash_start = std::string_view::npos; |
12031 | 481 | bool has_path = false; |
12032 | 481 | bool maybe_dot_segment = false; |
12033 | 481 | bool rest_simple = true; |
12034 | | |
12035 | 481 | if (i < len && b[i] == '/') { |
12036 | 302 | has_path = true; |
12037 | 302 | path_start = i; |
12038 | 302 | ++i; |
12039 | 302 | scan_path_run(b, i, len, maybe_dot_segment); |
12040 | 302 | if (i < len) { |
12041 | 204 | const uint8_t cls = k_path[b[i]]; |
12042 | 204 | if (cls == 1) { |
12043 | 47 | path_end = i; |
12044 | 47 | if (b[i] == '?') { |
12045 | 29 | query_start = i; |
12046 | 29 | ++i; |
12047 | 29 | goto scan_query; |
12048 | 29 | } |
12049 | 18 | hash_start = i; |
12050 | 18 | ++i; |
12051 | 18 | goto scan_hash; |
12052 | 47 | } |
12053 | 157 | rest_simple = false; |
12054 | 1.84k | for (; i < len; ++i) { |
12055 | 1.70k | if (b[i] == '?') { |
12056 | 12 | path_end = i; |
12057 | 12 | query_start = i; |
12058 | 12 | ++i; |
12059 | 12 | goto scan_query_boundary; |
12060 | 12 | } |
12061 | 1.69k | if (b[i] == '#') { |
12062 | 11 | path_end = i; |
12063 | 11 | hash_start = i; |
12064 | 11 | ++i; |
12065 | 11 | goto after_rest; |
12066 | 11 | } |
12067 | 1.69k | } |
12068 | 134 | path_end = i; |
12069 | 134 | goto after_rest; |
12070 | 157 | } |
12071 | 98 | path_end = i; |
12072 | 179 | } else if (i < len && b[i] == '?') { |
12073 | 91 | query_start = i; |
12074 | 91 | ++i; |
12075 | 91 | goto scan_query; |
12076 | 91 | } else if (i < len && b[i] == '#') { |
12077 | 88 | hash_start = i; |
12078 | 88 | ++i; |
12079 | 88 | goto scan_hash; |
12080 | 88 | } |
12081 | 98 | goto after_rest; |
12082 | | |
12083 | 120 | scan_query: |
12084 | 120 | scan_query_run(b, i, len); |
12085 | 120 | if (i < len) { |
12086 | 58 | if (b[i] == '#') { |
12087 | 10 | hash_start = i; |
12088 | 10 | ++i; |
12089 | 10 | goto scan_hash; |
12090 | 10 | } |
12091 | 48 | rest_simple = false; |
12092 | 48 | goto scan_query_boundary; |
12093 | 58 | } |
12094 | 62 | goto after_rest; |
12095 | | |
12096 | 62 | scan_query_boundary: |
12097 | 918 | for (; i < len; ++i) { |
12098 | 868 | if (b[i] == '#') { |
12099 | 10 | hash_start = i; |
12100 | 10 | ++i; |
12101 | 10 | goto after_rest; |
12102 | 10 | } |
12103 | 868 | } |
12104 | 50 | goto after_rest; |
12105 | | |
12106 | 116 | scan_hash: |
12107 | 116 | scan_hash_run(b, i, len); |
12108 | 116 | if (i < len) { |
12109 | 40 | rest_simple = false; |
12110 | 40 | } |
12111 | | |
12112 | 481 | after_rest: |
12113 | 481 | if (rest_simple && maybe_dot_segment) { |
12114 | 78 | const std::string_view path_body(input.data() + path_start, |
12115 | 78 | path_end - path_start); |
12116 | 78 | if (path_has_dot_segment(path_body)) { |
12117 | 38 | rest_simple = false; |
12118 | 38 | } |
12119 | 78 | } |
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 | 481 | if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) || |
12127 | 283 | unicode::has_tabs_or_newline(input))) { |
12128 | 40 | return false; |
12129 | 40 | } |
12130 | | |
12131 | 441 | out.type = scheme_type; |
12132 | 441 | out.is_valid = true; |
12133 | 441 | out.has_opaque_path = false; |
12134 | 441 | out.host_type = DEFAULT; |
12135 | | |
12136 | 441 | const uint32_t port_bytes = (parsed_port != url_components::omitted) |
12137 | 441 | ? (1 + port_decimal_digit_count(parsed_port)) |
12138 | 441 | : 0; |
12139 | | |
12140 | 441 | if (!rest_simple) { |
12141 | 243 | const std::string_view path_view = |
12142 | 243 | has_path |
12143 | 243 | ? std::string_view(input.data() + path_start, path_end - path_start) |
12144 | 243 | : std::string_view{}; |
12145 | 243 | auto apply_query_and_hash = [&]() { |
12146 | 243 | if (query_start != std::string_view::npos) { |
12147 | 64 | const size_t q_end = |
12148 | 64 | (hash_start != std::string_view::npos) ? hash_start : len; |
12149 | 64 | out.update_base_search(std::string_view(input.data() + query_start + 1, |
12150 | 64 | q_end - query_start - 1), |
12151 | 64 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); |
12152 | 64 | } |
12153 | 243 | if (hash_start != std::string_view::npos) { |
12154 | 51 | out.update_unencoded_base_hash(std::string_view( |
12155 | 51 | input.data() + hash_start + 1, len - hash_start - 1)); |
12156 | 51 | } |
12157 | 243 | }; 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()() constada::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()() constLine | Count | Source | 12145 | 243 | auto apply_query_and_hash = [&]() { | 12146 | 243 | if (query_start != std::string_view::npos) { | 12147 | 64 | const size_t q_end = | 12148 | 64 | (hash_start != std::string_view::npos) ? hash_start : len; | 12149 | 64 | out.update_base_search(std::string_view(input.data() + query_start + 1, | 12150 | 64 | q_end - query_start - 1), | 12151 | 64 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); | 12152 | 64 | } | 12153 | 243 | if (hash_start != std::string_view::npos) { | 12154 | 51 | out.update_unencoded_base_hash(std::string_view( | 12155 | 51 | input.data() + hash_start + 1, len - hash_start - 1)); | 12156 | 51 | } | 12157 | 243 | }; |
|
12158 | 243 | if constexpr (is_aggregator) { |
12159 | 243 | out.buffer.assign(input.substr(0, host_end)); |
12160 | 243 | if (parsed_port != url_components::omitted) { |
12161 | 36 | append_canonical_port(out.buffer, parsed_port); |
12162 | 36 | } |
12163 | 243 | if (has_upper) { |
12164 | 32 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); |
12165 | 32 | } |
12166 | 243 | out.components.protocol_end = protocol_end; |
12167 | 243 | out.components.username_end = protocol_end + 2; |
12168 | 243 | out.components.host_start = protocol_end + 2; |
12169 | 243 | out.components.host_end = static_cast<uint32_t>(host_end); |
12170 | 243 | out.components.port = parsed_port; |
12171 | 243 | out.components.pathname_start = static_cast<uint32_t>(out.buffer.size()); |
12172 | 243 | out.components.search_start = url_components::omitted; |
12173 | 243 | out.components.hash_start = url_components::omitted; |
12174 | 243 | out.parse_path(path_view); |
12175 | 243 | apply_query_and_hash(); |
12176 | 243 | } 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 | 243 | return true; |
12189 | 243 | } |
12190 | | |
12191 | 198 | const bool insert_slash = !has_path; |
12192 | 198 | if constexpr (is_aggregator) { |
12193 | 198 | const size_t out_len = |
12194 | 198 | host_end + port_bytes + (insert_slash ? 1 : 0) + (len - authority_end); |
12195 | 198 | const bool omit_port_bytes = parsed_port == url_components::omitted; |
12196 | 198 | if (out_len == len && !insert_slash && !omit_port_bytes) { |
12197 | 9 | out.buffer.assign(input); |
12198 | 189 | } else { |
12199 | 189 | out.buffer.clear(); |
12200 | 189 | out.buffer.reserve(out_len); |
12201 | 189 | out.buffer.append(input.substr(0, host_end)); |
12202 | 189 | if (parsed_port != url_components::omitted) { |
12203 | 82 | append_canonical_port(out.buffer, parsed_port); |
12204 | 82 | } |
12205 | 189 | if (insert_slash) { |
12206 | 105 | out.buffer.push_back('/'); |
12207 | 105 | } |
12208 | 189 | if (authority_end < len) { |
12209 | 189 | out.buffer.append(input.substr(authority_end)); |
12210 | 189 | } |
12211 | 189 | } |
12212 | 198 | if (has_upper) { |
12213 | 38 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); |
12214 | 38 | } |
12215 | 198 | const uint32_t pathname_start = |
12216 | 198 | static_cast<uint32_t>(host_end) + port_bytes; |
12217 | 198 | const int32_t tail_delta = static_cast<int32_t>(pathname_start) + |
12218 | 198 | (insert_slash ? 1 : 0) - |
12219 | 198 | static_cast<int32_t>(authority_end); |
12220 | 198 | out.components.protocol_end = protocol_end; |
12221 | 198 | out.components.username_end = protocol_end + 2; |
12222 | 198 | out.components.host_start = protocol_end + 2; |
12223 | 198 | out.components.host_end = static_cast<uint32_t>(host_end); |
12224 | 198 | out.components.port = parsed_port; |
12225 | 198 | out.components.pathname_start = pathname_start; |
12226 | 198 | out.components.search_start = |
12227 | 198 | (query_start != std::string_view::npos) |
12228 | 198 | ? static_cast<uint32_t>(static_cast<int32_t>(query_start) + |
12229 | 60 | tail_delta) |
12230 | 198 | : url_components::omitted; |
12231 | 198 | out.components.hash_start = |
12232 | 198 | (hash_start != std::string_view::npos) |
12233 | 198 | ? static_cast<uint32_t>(static_cast<int32_t>(hash_start) + |
12234 | 70 | tail_delta) |
12235 | 198 | : url_components::omitted; |
12236 | 198 | } 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 | 198 | return true; |
12261 | 441 | } 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 | 670 | bool has_upper) { | 11998 | 670 | constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>; | 11999 | 670 | constexpr bool is_aggregator = | 12000 | 670 | std::is_same_v<result_type, ada::url_aggregator>; | 12001 | 670 | static_assert(is_ada_url || is_aggregator); | 12002 | | | 12003 | 670 | const size_t len = input.size(); | 12004 | 670 | const auto* b = reinterpret_cast<const uint8_t*>(input.data()); | 12005 | 670 | size_t p = host_end + 1; | 12006 | 670 | uint32_t port_value = 0; | 12007 | 670 | bool any_digit = false; | 12008 | 1.31k | while (p < len && b[p] >= '0' && b[p] <= '9') { | 12009 | 651 | any_digit = true; | 12010 | 651 | port_value = port_value * 10 + static_cast<uint32_t>(b[p] - '0'); | 12011 | 651 | if (port_value > 65535) [[unlikely]] { | 12012 | 9 | return false; | 12013 | 9 | } | 12014 | 642 | ++p; | 12015 | 642 | } | 12016 | 661 | if (p < len && b[p] != '/' && b[p] != '?' && b[p] != '#') [[unlikely]] { | 12017 | 180 | return false; | 12018 | 180 | } | 12019 | 481 | uint32_t parsed_port = url_components::omitted; | 12020 | 481 | const uint16_t default_port = ada::scheme::get_special_port(scheme_type); | 12021 | 481 | if (any_digit && port_value != default_port) { | 12022 | 128 | parsed_port = port_value; | 12023 | 128 | } | 12024 | 481 | const size_t authority_end = p; | 12025 | | | 12026 | 481 | size_t i = authority_end; | 12027 | 481 | size_t path_start = host_end; | 12028 | 481 | size_t path_end = host_end; | 12029 | 481 | size_t query_start = std::string_view::npos; | 12030 | 481 | size_t hash_start = std::string_view::npos; | 12031 | 481 | bool has_path = false; | 12032 | 481 | bool maybe_dot_segment = false; | 12033 | 481 | bool rest_simple = true; | 12034 | | | 12035 | 481 | if (i < len && b[i] == '/') { | 12036 | 302 | has_path = true; | 12037 | 302 | path_start = i; | 12038 | 302 | ++i; | 12039 | 302 | scan_path_run(b, i, len, maybe_dot_segment); | 12040 | 302 | if (i < len) { | 12041 | 204 | const uint8_t cls = k_path[b[i]]; | 12042 | 204 | if (cls == 1) { | 12043 | 47 | path_end = i; | 12044 | 47 | if (b[i] == '?') { | 12045 | 29 | query_start = i; | 12046 | 29 | ++i; | 12047 | 29 | goto scan_query; | 12048 | 29 | } | 12049 | 18 | hash_start = i; | 12050 | 18 | ++i; | 12051 | 18 | goto scan_hash; | 12052 | 47 | } | 12053 | 157 | rest_simple = false; | 12054 | 1.84k | for (; i < len; ++i) { | 12055 | 1.70k | if (b[i] == '?') { | 12056 | 12 | path_end = i; | 12057 | 12 | query_start = i; | 12058 | 12 | ++i; | 12059 | 12 | goto scan_query_boundary; | 12060 | 12 | } | 12061 | 1.69k | if (b[i] == '#') { | 12062 | 11 | path_end = i; | 12063 | 11 | hash_start = i; | 12064 | 11 | ++i; | 12065 | 11 | goto after_rest; | 12066 | 11 | } | 12067 | 1.69k | } | 12068 | 134 | path_end = i; | 12069 | 134 | goto after_rest; | 12070 | 157 | } | 12071 | 98 | path_end = i; | 12072 | 179 | } else if (i < len && b[i] == '?') { | 12073 | 91 | query_start = i; | 12074 | 91 | ++i; | 12075 | 91 | goto scan_query; | 12076 | 91 | } else if (i < len && b[i] == '#') { | 12077 | 88 | hash_start = i; | 12078 | 88 | ++i; | 12079 | 88 | goto scan_hash; | 12080 | 88 | } | 12081 | 98 | goto after_rest; | 12082 | | | 12083 | 120 | scan_query: | 12084 | 120 | scan_query_run(b, i, len); | 12085 | 120 | if (i < len) { | 12086 | 58 | if (b[i] == '#') { | 12087 | 10 | hash_start = i; | 12088 | 10 | ++i; | 12089 | 10 | goto scan_hash; | 12090 | 10 | } | 12091 | 48 | rest_simple = false; | 12092 | 48 | goto scan_query_boundary; | 12093 | 58 | } | 12094 | 62 | goto after_rest; | 12095 | | | 12096 | 62 | scan_query_boundary: | 12097 | 918 | for (; i < len; ++i) { | 12098 | 868 | if (b[i] == '#') { | 12099 | 10 | hash_start = i; | 12100 | 10 | ++i; | 12101 | 10 | goto after_rest; | 12102 | 10 | } | 12103 | 868 | } | 12104 | 50 | goto after_rest; | 12105 | | | 12106 | 116 | scan_hash: | 12107 | 116 | scan_hash_run(b, i, len); | 12108 | 116 | if (i < len) { | 12109 | 40 | rest_simple = false; | 12110 | 40 | } | 12111 | | | 12112 | 481 | after_rest: | 12113 | 481 | if (rest_simple && maybe_dot_segment) { | 12114 | 78 | const std::string_view path_body(input.data() + path_start, | 12115 | 78 | path_end - path_start); | 12116 | 78 | if (path_has_dot_segment(path_body)) { | 12117 | 38 | rest_simple = false; | 12118 | 38 | } | 12119 | 78 | } | 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 | 481 | if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) || | 12127 | 283 | unicode::has_tabs_or_newline(input))) { | 12128 | 40 | return false; | 12129 | 40 | } | 12130 | | | 12131 | 441 | out.type = scheme_type; | 12132 | 441 | out.is_valid = true; | 12133 | 441 | out.has_opaque_path = false; | 12134 | 441 | out.host_type = DEFAULT; | 12135 | | | 12136 | 441 | const uint32_t port_bytes = (parsed_port != url_components::omitted) | 12137 | 441 | ? (1 + port_decimal_digit_count(parsed_port)) | 12138 | 441 | : 0; | 12139 | | | 12140 | 441 | if (!rest_simple) { | 12141 | 243 | const std::string_view path_view = | 12142 | 243 | has_path | 12143 | 243 | ? std::string_view(input.data() + path_start, path_end - path_start) | 12144 | 243 | : std::string_view{}; | 12145 | 243 | auto apply_query_and_hash = [&]() { | 12146 | 243 | if (query_start != std::string_view::npos) { | 12147 | 243 | const size_t q_end = | 12148 | 243 | (hash_start != std::string_view::npos) ? hash_start : len; | 12149 | 243 | out.update_base_search(std::string_view(input.data() + query_start + 1, | 12150 | 243 | q_end - query_start - 1), | 12151 | 243 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); | 12152 | 243 | } | 12153 | 243 | if (hash_start != std::string_view::npos) { | 12154 | 243 | out.update_unencoded_base_hash(std::string_view( | 12155 | 243 | input.data() + hash_start + 1, len - hash_start - 1)); | 12156 | 243 | } | 12157 | 243 | }; | 12158 | 243 | if constexpr (is_aggregator) { | 12159 | 243 | out.buffer.assign(input.substr(0, host_end)); | 12160 | 243 | if (parsed_port != url_components::omitted) { | 12161 | 36 | append_canonical_port(out.buffer, parsed_port); | 12162 | 36 | } | 12163 | 243 | if (has_upper) { | 12164 | 32 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); | 12165 | 32 | } | 12166 | 243 | out.components.protocol_end = protocol_end; | 12167 | 243 | out.components.username_end = protocol_end + 2; | 12168 | 243 | out.components.host_start = protocol_end + 2; | 12169 | 243 | out.components.host_end = static_cast<uint32_t>(host_end); | 12170 | 243 | out.components.port = parsed_port; | 12171 | 243 | out.components.pathname_start = static_cast<uint32_t>(out.buffer.size()); | 12172 | 243 | out.components.search_start = url_components::omitted; | 12173 | 243 | out.components.hash_start = url_components::omitted; | 12174 | 243 | out.parse_path(path_view); | 12175 | 243 | 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 | 243 | return true; | 12189 | 243 | } | 12190 | | | 12191 | 198 | const bool insert_slash = !has_path; | 12192 | 198 | if constexpr (is_aggregator) { | 12193 | 198 | const size_t out_len = | 12194 | 198 | host_end + port_bytes + (insert_slash ? 1 : 0) + (len - authority_end); | 12195 | 198 | const bool omit_port_bytes = parsed_port == url_components::omitted; | 12196 | 198 | if (out_len == len && !insert_slash && !omit_port_bytes) { | 12197 | 9 | out.buffer.assign(input); | 12198 | 189 | } else { | 12199 | 189 | out.buffer.clear(); | 12200 | 189 | out.buffer.reserve(out_len); | 12201 | 189 | out.buffer.append(input.substr(0, host_end)); | 12202 | 189 | if (parsed_port != url_components::omitted) { | 12203 | 82 | append_canonical_port(out.buffer, parsed_port); | 12204 | 82 | } | 12205 | 189 | if (insert_slash) { | 12206 | 105 | out.buffer.push_back('/'); | 12207 | 105 | } | 12208 | 189 | if (authority_end < len) { | 12209 | 189 | out.buffer.append(input.substr(authority_end)); | 12210 | 189 | } | 12211 | 189 | } | 12212 | 198 | if (has_upper) { | 12213 | 38 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); | 12214 | 38 | } | 12215 | 198 | const uint32_t pathname_start = | 12216 | 198 | static_cast<uint32_t>(host_end) + port_bytes; | 12217 | 198 | const int32_t tail_delta = static_cast<int32_t>(pathname_start) + | 12218 | 198 | (insert_slash ? 1 : 0) - | 12219 | 198 | static_cast<int32_t>(authority_end); | 12220 | 198 | out.components.protocol_end = protocol_end; | 12221 | 198 | out.components.username_end = protocol_end + 2; | 12222 | 198 | out.components.host_start = protocol_end + 2; | 12223 | 198 | out.components.host_end = static_cast<uint32_t>(host_end); | 12224 | 198 | out.components.port = parsed_port; | 12225 | 198 | out.components.pathname_start = pathname_start; | 12226 | 198 | out.components.search_start = | 12227 | 198 | (query_start != std::string_view::npos) | 12228 | 198 | ? static_cast<uint32_t>(static_cast<int32_t>(query_start) + | 12229 | 60 | tail_delta) | 12230 | 198 | : url_components::omitted; | 12231 | 198 | out.components.hash_start = | 12232 | 198 | (hash_start != std::string_view::npos) | 12233 | 198 | ? static_cast<uint32_t>(static_cast<int32_t>(hash_start) + | 12234 | 70 | tail_delta) | 12235 | 198 | : 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 | 198 | return true; | 12261 | 441 | } |
|
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 | 4.74k | result_type& out) { |
12270 | 4.74k | constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>; |
12271 | 4.74k | constexpr bool is_aggregator = |
12272 | 4.74k | std::is_same_v<result_type, ada::url_aggregator>; |
12273 | 4.74k | static_assert(is_ada_url || is_aggregator); |
12274 | | |
12275 | 4.74k | const size_t len = input.size(); |
12276 | | // Shortest accepted form is "ws://x" (6). |
12277 | 4.74k | if (len < 6) [[unlikely]] { |
12278 | 0 | return false; |
12279 | 0 | } |
12280 | 4.74k | const auto* b = reinterpret_cast<const uint8_t*>(input.data()); |
12281 | | |
12282 | 4.74k | size_t pos = 0; |
12283 | 4.74k | ada::scheme::type scheme_type = ada::scheme::type::NOT_SPECIAL; |
12284 | 4.74k | uint32_t protocol_end = 0; |
12285 | 4.74k | #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ |
12286 | 4.74k | 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 | 4.74k | if (len >= 8) { |
12290 | 4.74k | uint64_t first8 = 0; |
12291 | 4.74k | std::memcpy(&first8, b, 8); |
12292 | 4.74k | if (first8 == 0x2f2f3a7370747468ull) { // "https://" |
12293 | 0 | pos = 8; |
12294 | 0 | scheme_type = ada::scheme::type::HTTPS; |
12295 | 0 | protocol_end = 6; |
12296 | 4.74k | } else if ((first8 & 0x00ffffffffffffffull) == |
12297 | 4.74k | 0x002f2f3a70747468ull) { // "http://" |
12298 | 4.74k | pos = 7; |
12299 | 4.74k | scheme_type = ada::scheme::type::HTTP; |
12300 | 4.74k | protocol_end = 5; |
12301 | 4.74k | } else if ((first8 & 0x0000ffffffffffffull) == |
12302 | 0 | 0x00002f2f3a737377ull) { // "wss://" |
12303 | 0 | pos = 6; |
12304 | 0 | scheme_type = ada::scheme::type::WSS; |
12305 | 0 | protocol_end = 4; |
12306 | 0 | } else if ((first8 & 0x0000ffffffffffffull) == |
12307 | 0 | 0x00002f2f3a707466ull) { // "ftp://" |
12308 | 0 | pos = 6; |
12309 | 0 | scheme_type = ada::scheme::type::FTP; |
12310 | 0 | protocol_end = 4; |
12311 | 0 | } else if ((first8 & 0x000000ffffffffffull) == |
12312 | 0 | 0x0000002f2f3a7377ull) { // "ws://" |
12313 | 0 | pos = 5; |
12314 | 0 | scheme_type = ada::scheme::type::WS; |
12315 | 0 | protocol_end = 3; |
12316 | 0 | } else { |
12317 | 0 | return false; |
12318 | 0 | } |
12319 | 4.74k | } 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 | 0 | } 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 | 0 | } 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 | 0 | } else { |
12342 | 0 | return false; |
12343 | 0 | } |
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 | 4.74k | if (pos < len && (b[pos] == '/' || b[pos] == '\\')) [[unlikely]] { |
12379 | 26 | return false; |
12380 | 26 | } |
12381 | | |
12382 | | // Digit-led hosts are IPv4/numeric; '[' is IPv6. Skip before scanning. |
12383 | 4.71k | if (pos < len && ((b[pos] >= '0' && b[pos] <= '9') || b[pos] == '[')) { |
12384 | 0 | return false; |
12385 | 0 | } |
12386 | | |
12387 | 4.71k | const size_t host_start = pos; |
12388 | 4.71k | bool has_upper = false; |
12389 | 4.71k | bool has_x = false; |
12390 | 4.71k | size_t host_end = pos; |
12391 | 4.71k | if (!scan_plain_host(b, pos, len, host_end, has_upper, has_x)) { |
12392 | 2.82k | return false; |
12393 | 2.82k | } |
12394 | 1.89k | if (host_start == host_end) [[unlikely]] { |
12395 | 11 | return false; |
12396 | 11 | } |
12397 | 1.88k | const size_t host_len = host_end - host_start; |
12398 | 1.88k | if (host_len > 253) [[unlikely]] { |
12399 | 0 | return false; |
12400 | 0 | } |
12401 | 1.88k | { |
12402 | 1.88k | std::string_view hv(input.data() + host_start, host_len); |
12403 | 1.88k | char host_buf[256]; |
12404 | 1.88k | if (has_upper) [[unlikely]] { |
12405 | 441 | std::memcpy(host_buf, input.data() + host_start, host_len); |
12406 | 441 | unicode::to_lower_ascii(host_buf, host_len); |
12407 | 441 | hv = std::string_view(host_buf, host_len); |
12408 | 441 | } |
12409 | 1.88k | if (ada::checkers::last_label_may_be_a_number(hv)) [[unlikely]] { |
12410 | 244 | return false; |
12411 | 244 | } |
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 | 1.63k | static constexpr std::string_view xn{"xn-", 3}; |
12415 | 1.63k | if ((has_x || has_upper) && hv.find(xn) != std::string_view::npos) |
12416 | 28 | [[unlikely]] { |
12417 | 28 | return false; |
12418 | 28 | } |
12419 | 1.63k | } |
12420 | | |
12421 | 1.60k | if (host_end < len && b[host_end] == ':') [[unlikely]] { |
12422 | 670 | return finish_simple_absolute_with_port(input, out, scheme_type, |
12423 | 670 | protocol_end, host_start, host_end, |
12424 | 670 | host_len, has_upper); |
12425 | 670 | } |
12426 | | |
12427 | 939 | size_t i = host_end; |
12428 | 939 | size_t path_start = host_end; |
12429 | 939 | size_t path_end = host_end; |
12430 | 939 | size_t query_start = std::string_view::npos; |
12431 | 939 | size_t hash_start = std::string_view::npos; |
12432 | 939 | bool has_path = false; |
12433 | 939 | bool maybe_dot_segment = false; |
12434 | 939 | bool rest_simple = true; |
12435 | | |
12436 | 939 | if (i < len && b[i] == '/') { |
12437 | 763 | has_path = true; |
12438 | 763 | path_start = i; |
12439 | 763 | ++i; |
12440 | 763 | scan_path_run(b, i, len, maybe_dot_segment); |
12441 | 763 | if (i < len) { |
12442 | 554 | const uint8_t cls = k_path[b[i]]; |
12443 | 554 | if (cls == 1) { |
12444 | 80 | path_end = i; |
12445 | 80 | if (b[i] == '?') { |
12446 | 52 | query_start = i; |
12447 | 52 | ++i; |
12448 | 52 | goto scan_query; |
12449 | 52 | } |
12450 | 28 | hash_start = i; |
12451 | 28 | ++i; |
12452 | 28 | goto scan_hash; |
12453 | 80 | } |
12454 | 474 | rest_simple = false; |
12455 | 10.2k | for (; i < len; ++i) { |
12456 | 9.80k | if (b[i] == '?') { |
12457 | 55 | path_end = i; |
12458 | 55 | query_start = i; |
12459 | 55 | ++i; |
12460 | 55 | goto scan_query_boundary; |
12461 | 55 | } |
12462 | 9.74k | if (b[i] == '#') { |
12463 | 17 | path_end = i; |
12464 | 17 | hash_start = i; |
12465 | 17 | ++i; |
12466 | 17 | goto after_rest; |
12467 | 17 | } |
12468 | 9.74k | } |
12469 | 402 | path_end = i; |
12470 | 402 | goto after_rest; |
12471 | 474 | } |
12472 | 209 | path_end = i; |
12473 | 209 | } else if (i < len && b[i] == '?') { |
12474 | 124 | query_start = i; |
12475 | 124 | ++i; |
12476 | 124 | goto scan_query; |
12477 | 124 | } else if (i < len && b[i] == '#') { |
12478 | 52 | hash_start = i; |
12479 | 52 | ++i; |
12480 | 52 | goto scan_hash; |
12481 | 52 | } |
12482 | 209 | goto after_rest; |
12483 | | |
12484 | 209 | scan_query: |
12485 | 176 | scan_query_run(b, i, len); |
12486 | 176 | if (i < len) { |
12487 | 96 | if (b[i] == '#') { |
12488 | 15 | hash_start = i; |
12489 | 15 | ++i; |
12490 | 15 | goto scan_hash; |
12491 | 15 | } |
12492 | 81 | rest_simple = false; |
12493 | 81 | goto scan_query_boundary; |
12494 | 96 | } |
12495 | 80 | goto after_rest; |
12496 | | |
12497 | 136 | scan_query_boundary: |
12498 | 1.45k | for (; i < len; ++i) { |
12499 | 1.34k | if (b[i] == '#') { |
12500 | 23 | hash_start = i; |
12501 | 23 | ++i; |
12502 | 23 | goto after_rest; |
12503 | 23 | } |
12504 | 1.34k | } |
12505 | 113 | goto after_rest; |
12506 | | |
12507 | 113 | scan_hash: |
12508 | 95 | scan_hash_run(b, i, len); |
12509 | 95 | if (i < len) { |
12510 | 33 | rest_simple = false; |
12511 | 33 | } |
12512 | | |
12513 | 939 | after_rest: |
12514 | 939 | if (rest_simple && maybe_dot_segment) { |
12515 | 220 | const std::string_view path_body(input.data() + path_start, |
12516 | 220 | path_end - path_start); |
12517 | 220 | if (path_has_dot_segment(path_body)) { |
12518 | 119 | rest_simple = false; |
12519 | 119 | } |
12520 | 220 | } |
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 | 939 | if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) || |
12528 | 707 | unicode::has_tabs_or_newline(input))) { |
12529 | 63 | return false; |
12530 | 63 | } |
12531 | | |
12532 | 876 | out.type = scheme_type; |
12533 | 876 | out.is_valid = true; |
12534 | 876 | out.has_opaque_path = false; |
12535 | 876 | out.host_type = DEFAULT; |
12536 | | |
12537 | 876 | 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 | 644 | const std::string_view path_view = |
12542 | 644 | has_path |
12543 | 644 | ? std::string_view(input.data() + path_start, path_end - path_start) |
12544 | 644 | : std::string_view{}; |
12545 | 644 | auto apply_query_and_hash = [&]() { |
12546 | 644 | if (query_start != std::string_view::npos) { |
12547 | 140 | const size_t q_end = |
12548 | 140 | (hash_start != std::string_view::npos) ? hash_start : len; |
12549 | 140 | out.update_base_search(std::string_view(input.data() + query_start + 1, |
12550 | 140 | q_end - query_start - 1), |
12551 | 140 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); |
12552 | 140 | } |
12553 | 644 | if (hash_start != std::string_view::npos) { |
12554 | 70 | out.update_unencoded_base_hash(std::string_view( |
12555 | 70 | input.data() + hash_start + 1, len - hash_start - 1)); |
12556 | 70 | } |
12557 | 644 | }; 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()() constada::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()() constLine | Count | Source | 12545 | 644 | auto apply_query_and_hash = [&]() { | 12546 | 644 | if (query_start != std::string_view::npos) { | 12547 | 140 | const size_t q_end = | 12548 | 140 | (hash_start != std::string_view::npos) ? hash_start : len; | 12549 | 140 | out.update_base_search(std::string_view(input.data() + query_start + 1, | 12550 | 140 | q_end - query_start - 1), | 12551 | 140 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); | 12552 | 140 | } | 12553 | 644 | if (hash_start != std::string_view::npos) { | 12554 | 70 | out.update_unencoded_base_hash(std::string_view( | 12555 | 70 | input.data() + hash_start + 1, len - hash_start - 1)); | 12556 | 70 | } | 12557 | 644 | }; |
|
12558 | 644 | if constexpr (is_aggregator) { |
12559 | 644 | out.buffer.assign(input.substr(0, host_end)); |
12560 | 644 | if (has_upper) { |
12561 | 71 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); |
12562 | 71 | } |
12563 | 644 | out.components.protocol_end = protocol_end; |
12564 | 644 | out.components.username_end = protocol_end + 2; |
12565 | 644 | out.components.host_start = protocol_end + 2; |
12566 | 644 | out.components.host_end = static_cast<uint32_t>(host_end); |
12567 | 644 | out.components.port = url_components::omitted; |
12568 | 644 | out.components.pathname_start = static_cast<uint32_t>(host_end); |
12569 | 644 | out.components.search_start = url_components::omitted; |
12570 | 644 | out.components.hash_start = url_components::omitted; |
12571 | 644 | out.parse_path(path_view); |
12572 | 644 | apply_query_and_hash(); |
12573 | 644 | } 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 | 644 | return true; |
12583 | 644 | } |
12584 | | |
12585 | 232 | const bool need_slash = !has_path; |
12586 | 232 | if constexpr (is_aggregator) { |
12587 | 232 | if (!need_slash) { |
12588 | | // assign copies once. resize()+memcpy would value-init then overwrite. |
12589 | 159 | out.buffer.assign(input); |
12590 | 159 | if (has_upper) { |
12591 | 29 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); |
12592 | 29 | } |
12593 | 159 | out.components.protocol_end = protocol_end; |
12594 | 159 | out.components.username_end = protocol_end + 2; |
12595 | 159 | out.components.host_start = protocol_end + 2; |
12596 | 159 | out.components.host_end = static_cast<uint32_t>(host_end); |
12597 | 159 | out.components.port = url_components::omitted; |
12598 | 159 | out.components.pathname_start = static_cast<uint32_t>(path_start); |
12599 | 159 | out.components.search_start = (query_start != std::string_view::npos) |
12600 | 159 | ? static_cast<uint32_t>(query_start) |
12601 | 159 | : url_components::omitted; |
12602 | 159 | out.components.hash_start = (hash_start != std::string_view::npos) |
12603 | 159 | ? static_cast<uint32_t>(hash_start) |
12604 | 159 | : url_components::omitted; |
12605 | 159 | } else { |
12606 | 73 | out.buffer.clear(); |
12607 | 73 | out.buffer.reserve(len + 1); |
12608 | 73 | out.buffer.append(input.substr(0, host_end)); |
12609 | 73 | out.buffer.push_back('/'); |
12610 | 73 | if (host_end < len) { |
12611 | 73 | out.buffer.append(input.substr(host_end)); |
12612 | 73 | } |
12613 | 73 | if (has_upper) { |
12614 | 26 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); |
12615 | 26 | } |
12616 | 73 | out.components.protocol_end = protocol_end; |
12617 | 73 | out.components.username_end = protocol_end + 2; |
12618 | 73 | out.components.host_start = protocol_end + 2; |
12619 | 73 | out.components.host_end = static_cast<uint32_t>(host_end); |
12620 | 73 | out.components.port = url_components::omitted; |
12621 | 73 | out.components.pathname_start = static_cast<uint32_t>(host_end); |
12622 | 73 | out.components.search_start = (query_start != std::string_view::npos) |
12623 | 73 | ? static_cast<uint32_t>(query_start + 1) |
12624 | 73 | : url_components::omitted; |
12625 | 73 | out.components.hash_start = (hash_start != std::string_view::npos) |
12626 | 73 | ? static_cast<uint32_t>(hash_start + 1) |
12627 | 73 | : url_components::omitted; |
12628 | 73 | } |
12629 | 232 | } 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 | 232 | return true; |
12651 | 876 | } 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 | 4.74k | result_type& out) { | 12270 | 4.74k | constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>; | 12271 | 4.74k | constexpr bool is_aggregator = | 12272 | 4.74k | std::is_same_v<result_type, ada::url_aggregator>; | 12273 | 4.74k | static_assert(is_ada_url || is_aggregator); | 12274 | | | 12275 | 4.74k | const size_t len = input.size(); | 12276 | | // Shortest accepted form is "ws://x" (6). | 12277 | 4.74k | if (len < 6) [[unlikely]] { | 12278 | 0 | return false; | 12279 | 0 | } | 12280 | 4.74k | const auto* b = reinterpret_cast<const uint8_t*>(input.data()); | 12281 | | | 12282 | 4.74k | size_t pos = 0; | 12283 | 4.74k | ada::scheme::type scheme_type = ada::scheme::type::NOT_SPECIAL; | 12284 | 4.74k | uint32_t protocol_end = 0; | 12285 | 4.74k | #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ | 12286 | 4.74k | 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 | 4.74k | if (len >= 8) { | 12290 | 4.74k | uint64_t first8 = 0; | 12291 | 4.74k | std::memcpy(&first8, b, 8); | 12292 | 4.74k | if (first8 == 0x2f2f3a7370747468ull) { // "https://" | 12293 | 0 | pos = 8; | 12294 | 0 | scheme_type = ada::scheme::type::HTTPS; | 12295 | 0 | protocol_end = 6; | 12296 | 4.74k | } else if ((first8 & 0x00ffffffffffffffull) == | 12297 | 4.74k | 0x002f2f3a70747468ull) { // "http://" | 12298 | 4.74k | pos = 7; | 12299 | 4.74k | scheme_type = ada::scheme::type::HTTP; | 12300 | 4.74k | protocol_end = 5; | 12301 | 4.74k | } else if ((first8 & 0x0000ffffffffffffull) == | 12302 | 0 | 0x00002f2f3a737377ull) { // "wss://" | 12303 | 0 | pos = 6; | 12304 | 0 | scheme_type = ada::scheme::type::WSS; | 12305 | 0 | protocol_end = 4; | 12306 | 0 | } else if ((first8 & 0x0000ffffffffffffull) == | 12307 | 0 | 0x00002f2f3a707466ull) { // "ftp://" | 12308 | 0 | pos = 6; | 12309 | 0 | scheme_type = ada::scheme::type::FTP; | 12310 | 0 | protocol_end = 4; | 12311 | 0 | } else if ((first8 & 0x000000ffffffffffull) == | 12312 | 0 | 0x0000002f2f3a7377ull) { // "ws://" | 12313 | 0 | pos = 5; | 12314 | 0 | scheme_type = ada::scheme::type::WS; | 12315 | 0 | protocol_end = 3; | 12316 | 0 | } else { | 12317 | 0 | return false; | 12318 | 0 | } | 12319 | 4.74k | } 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 | 0 | } 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 | 0 | } 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 | 0 | } else { | 12342 | 0 | return false; | 12343 | 0 | } | 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 | 4.74k | if (pos < len && (b[pos] == '/' || b[pos] == '\\')) [[unlikely]] { | 12379 | 26 | return false; | 12380 | 26 | } | 12381 | | | 12382 | | // Digit-led hosts are IPv4/numeric; '[' is IPv6. Skip before scanning. | 12383 | 4.71k | if (pos < len && ((b[pos] >= '0' && b[pos] <= '9') || b[pos] == '[')) { | 12384 | 0 | return false; | 12385 | 0 | } | 12386 | | | 12387 | 4.71k | const size_t host_start = pos; | 12388 | 4.71k | bool has_upper = false; | 12389 | 4.71k | bool has_x = false; | 12390 | 4.71k | size_t host_end = pos; | 12391 | 4.71k | if (!scan_plain_host(b, pos, len, host_end, has_upper, has_x)) { | 12392 | 2.82k | return false; | 12393 | 2.82k | } | 12394 | 1.89k | if (host_start == host_end) [[unlikely]] { | 12395 | 11 | return false; | 12396 | 11 | } | 12397 | 1.88k | const size_t host_len = host_end - host_start; | 12398 | 1.88k | if (host_len > 253) [[unlikely]] { | 12399 | 0 | return false; | 12400 | 0 | } | 12401 | 1.88k | { | 12402 | 1.88k | std::string_view hv(input.data() + host_start, host_len); | 12403 | 1.88k | char host_buf[256]; | 12404 | 1.88k | if (has_upper) [[unlikely]] { | 12405 | 441 | std::memcpy(host_buf, input.data() + host_start, host_len); | 12406 | 441 | unicode::to_lower_ascii(host_buf, host_len); | 12407 | 441 | hv = std::string_view(host_buf, host_len); | 12408 | 441 | } | 12409 | 1.88k | if (ada::checkers::last_label_may_be_a_number(hv)) [[unlikely]] { | 12410 | 244 | return false; | 12411 | 244 | } | 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 | 1.63k | static constexpr std::string_view xn{"xn-", 3}; | 12415 | 1.63k | if ((has_x || has_upper) && hv.find(xn) != std::string_view::npos) | 12416 | 28 | [[unlikely]] { | 12417 | 28 | return false; | 12418 | 28 | } | 12419 | 1.63k | } | 12420 | | | 12421 | 1.60k | if (host_end < len && b[host_end] == ':') [[unlikely]] { | 12422 | 670 | return finish_simple_absolute_with_port(input, out, scheme_type, | 12423 | 670 | protocol_end, host_start, host_end, | 12424 | 670 | host_len, has_upper); | 12425 | 670 | } | 12426 | | | 12427 | 939 | size_t i = host_end; | 12428 | 939 | size_t path_start = host_end; | 12429 | 939 | size_t path_end = host_end; | 12430 | 939 | size_t query_start = std::string_view::npos; | 12431 | 939 | size_t hash_start = std::string_view::npos; | 12432 | 939 | bool has_path = false; | 12433 | 939 | bool maybe_dot_segment = false; | 12434 | 939 | bool rest_simple = true; | 12435 | | | 12436 | 939 | if (i < len && b[i] == '/') { | 12437 | 763 | has_path = true; | 12438 | 763 | path_start = i; | 12439 | 763 | ++i; | 12440 | 763 | scan_path_run(b, i, len, maybe_dot_segment); | 12441 | 763 | if (i < len) { | 12442 | 554 | const uint8_t cls = k_path[b[i]]; | 12443 | 554 | if (cls == 1) { | 12444 | 80 | path_end = i; | 12445 | 80 | if (b[i] == '?') { | 12446 | 52 | query_start = i; | 12447 | 52 | ++i; | 12448 | 52 | goto scan_query; | 12449 | 52 | } | 12450 | 28 | hash_start = i; | 12451 | 28 | ++i; | 12452 | 28 | goto scan_hash; | 12453 | 80 | } | 12454 | 474 | rest_simple = false; | 12455 | 10.2k | for (; i < len; ++i) { | 12456 | 9.80k | if (b[i] == '?') { | 12457 | 55 | path_end = i; | 12458 | 55 | query_start = i; | 12459 | 55 | ++i; | 12460 | 55 | goto scan_query_boundary; | 12461 | 55 | } | 12462 | 9.74k | if (b[i] == '#') { | 12463 | 17 | path_end = i; | 12464 | 17 | hash_start = i; | 12465 | 17 | ++i; | 12466 | 17 | goto after_rest; | 12467 | 17 | } | 12468 | 9.74k | } | 12469 | 402 | path_end = i; | 12470 | 402 | goto after_rest; | 12471 | 474 | } | 12472 | 209 | path_end = i; | 12473 | 209 | } else if (i < len && b[i] == '?') { | 12474 | 124 | query_start = i; | 12475 | 124 | ++i; | 12476 | 124 | goto scan_query; | 12477 | 124 | } else if (i < len && b[i] == '#') { | 12478 | 52 | hash_start = i; | 12479 | 52 | ++i; | 12480 | 52 | goto scan_hash; | 12481 | 52 | } | 12482 | 209 | goto after_rest; | 12483 | | | 12484 | 209 | scan_query: | 12485 | 176 | scan_query_run(b, i, len); | 12486 | 176 | if (i < len) { | 12487 | 96 | if (b[i] == '#') { | 12488 | 15 | hash_start = i; | 12489 | 15 | ++i; | 12490 | 15 | goto scan_hash; | 12491 | 15 | } | 12492 | 81 | rest_simple = false; | 12493 | 81 | goto scan_query_boundary; | 12494 | 96 | } | 12495 | 80 | goto after_rest; | 12496 | | | 12497 | 136 | scan_query_boundary: | 12498 | 1.45k | for (; i < len; ++i) { | 12499 | 1.34k | if (b[i] == '#') { | 12500 | 23 | hash_start = i; | 12501 | 23 | ++i; | 12502 | 23 | goto after_rest; | 12503 | 23 | } | 12504 | 1.34k | } | 12505 | 113 | goto after_rest; | 12506 | | | 12507 | 113 | scan_hash: | 12508 | 95 | scan_hash_run(b, i, len); | 12509 | 95 | if (i < len) { | 12510 | 33 | rest_simple = false; | 12511 | 33 | } | 12512 | | | 12513 | 939 | after_rest: | 12514 | 939 | if (rest_simple && maybe_dot_segment) { | 12515 | 220 | const std::string_view path_body(input.data() + path_start, | 12516 | 220 | path_end - path_start); | 12517 | 220 | if (path_has_dot_segment(path_body)) { | 12518 | 119 | rest_simple = false; | 12519 | 119 | } | 12520 | 220 | } | 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 | 939 | if (!rest_simple && (unicode::is_c0_control_or_space(input.back()) || | 12528 | 707 | unicode::has_tabs_or_newline(input))) { | 12529 | 63 | return false; | 12530 | 63 | } | 12531 | | | 12532 | 876 | out.type = scheme_type; | 12533 | 876 | out.is_valid = true; | 12534 | 876 | out.has_opaque_path = false; | 12535 | 876 | out.host_type = DEFAULT; | 12536 | | | 12537 | 876 | 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 | 644 | const std::string_view path_view = | 12542 | 644 | has_path | 12543 | 644 | ? std::string_view(input.data() + path_start, path_end - path_start) | 12544 | 644 | : std::string_view{}; | 12545 | 644 | auto apply_query_and_hash = [&]() { | 12546 | 644 | if (query_start != std::string_view::npos) { | 12547 | 644 | const size_t q_end = | 12548 | 644 | (hash_start != std::string_view::npos) ? hash_start : len; | 12549 | 644 | out.update_base_search(std::string_view(input.data() + query_start + 1, | 12550 | 644 | q_end - query_start - 1), | 12551 | 644 | character_sets::SPECIAL_QUERY_PERCENT_ENCODE); | 12552 | 644 | } | 12553 | 644 | if (hash_start != std::string_view::npos) { | 12554 | 644 | out.update_unencoded_base_hash(std::string_view( | 12555 | 644 | input.data() + hash_start + 1, len - hash_start - 1)); | 12556 | 644 | } | 12557 | 644 | }; | 12558 | 644 | if constexpr (is_aggregator) { | 12559 | 644 | out.buffer.assign(input.substr(0, host_end)); | 12560 | 644 | if (has_upper) { | 12561 | 71 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); | 12562 | 71 | } | 12563 | 644 | out.components.protocol_end = protocol_end; | 12564 | 644 | out.components.username_end = protocol_end + 2; | 12565 | 644 | out.components.host_start = protocol_end + 2; | 12566 | 644 | out.components.host_end = static_cast<uint32_t>(host_end); | 12567 | 644 | out.components.port = url_components::omitted; | 12568 | 644 | out.components.pathname_start = static_cast<uint32_t>(host_end); | 12569 | 644 | out.components.search_start = url_components::omitted; | 12570 | 644 | out.components.hash_start = url_components::omitted; | 12571 | 644 | out.parse_path(path_view); | 12572 | 644 | 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 | 644 | return true; | 12583 | 644 | } | 12584 | | | 12585 | 232 | const bool need_slash = !has_path; | 12586 | 232 | if constexpr (is_aggregator) { | 12587 | 232 | if (!need_slash) { | 12588 | | // assign copies once. resize()+memcpy would value-init then overwrite. | 12589 | 159 | out.buffer.assign(input); | 12590 | 159 | if (has_upper) { | 12591 | 29 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); | 12592 | 29 | } | 12593 | 159 | out.components.protocol_end = protocol_end; | 12594 | 159 | out.components.username_end = protocol_end + 2; | 12595 | 159 | out.components.host_start = protocol_end + 2; | 12596 | 159 | out.components.host_end = static_cast<uint32_t>(host_end); | 12597 | 159 | out.components.port = url_components::omitted; | 12598 | 159 | out.components.pathname_start = static_cast<uint32_t>(path_start); | 12599 | 159 | out.components.search_start = (query_start != std::string_view::npos) | 12600 | 159 | ? static_cast<uint32_t>(query_start) | 12601 | 159 | : url_components::omitted; | 12602 | 159 | out.components.hash_start = (hash_start != std::string_view::npos) | 12603 | 159 | ? static_cast<uint32_t>(hash_start) | 12604 | 159 | : url_components::omitted; | 12605 | 159 | } else { | 12606 | 73 | out.buffer.clear(); | 12607 | 73 | out.buffer.reserve(len + 1); | 12608 | 73 | out.buffer.append(input.substr(0, host_end)); | 12609 | 73 | out.buffer.push_back('/'); | 12610 | 73 | if (host_end < len) { | 12611 | 73 | out.buffer.append(input.substr(host_end)); | 12612 | 73 | } | 12613 | 73 | if (has_upper) { | 12614 | 26 | unicode::to_lower_ascii(out.buffer.data() + host_start, host_len); | 12615 | 26 | } | 12616 | 73 | out.components.protocol_end = protocol_end; | 12617 | 73 | out.components.username_end = protocol_end + 2; | 12618 | 73 | out.components.host_start = protocol_end + 2; | 12619 | 73 | out.components.host_end = static_cast<uint32_t>(host_end); | 12620 | 73 | out.components.port = url_components::omitted; | 12621 | 73 | out.components.pathname_start = static_cast<uint32_t>(host_end); | 12622 | 73 | out.components.search_start = (query_start != std::string_view::npos) | 12623 | 73 | ? static_cast<uint32_t>(query_start + 1) | 12624 | 73 | : url_components::omitted; | 12625 | 73 | out.components.hash_start = (hash_start != std::string_view::npos) | 12626 | 73 | ? static_cast<uint32_t>(hash_start + 1) | 12627 | 73 | : url_components::omitted; | 12628 | 73 | } | 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 | 232 | return true; | 12651 | 876 | } |
|
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 | 0 | result_type& out) { |
12660 | 0 | constexpr bool is_ada_url = std::is_same_v<result_type, ada::url>; |
12661 | 0 | constexpr bool is_aggregator = |
12662 | 0 | std::is_same_v<result_type, ada::url_aggregator>; |
12663 | 0 | static_assert(is_ada_url || is_aggregator); |
12664 | |
|
12665 | 0 | if (!base.is_special() || base.type == ada::scheme::type::FILE || |
12666 | 0 | base.has_opaque_path || input.empty()) { |
12667 | 0 | return false; |
12668 | 0 | } |
12669 | 0 | const auto* b = reinterpret_cast<const uint8_t*>(input.data()); |
12670 | 0 | const size_t len = input.size(); |
12671 | 0 | const uint8_t first = b[0]; |
12672 | 0 | const bool path_relative = first != '/' && first != '?' && first != '#'; |
12673 | 0 | 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 | 0 | if (path_relative) { |
12678 | 0 | const size_t delim = input.find_first_of("/?#:"); |
12679 | 0 | if (delim != std::string_view::npos && input[delim] == ':') { |
12680 | 0 | return false; |
12681 | 0 | } |
12682 | 0 | } |
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&) Unexecuted instantiation: 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&) |
12837 | | |
12838 | | template <class result_type, bool store_values> |
12839 | | result_type parse_url_impl(std::string_view user_input, |
12840 | 13.4k | 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 | 13.4k | constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>; |
12847 | 13.4k | constexpr bool result_type_is_ada_url_aggregator = |
12848 | 13.4k | std::is_same_v<url_aggregator, result_type>; |
12849 | 13.4k | static_assert(result_type_is_ada_url || |
12850 | 13.4k | result_type_is_ada_url_aggregator); // We don't support |
12851 | | // anything else for now. |
12852 | | |
12853 | 13.4k | ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(), |
12854 | 13.4k | " bytes],", (base_url != nullptr ? base_url->to_string() : "null"), |
12855 | 13.4k | ")"); |
12856 | | |
12857 | 13.4k | result_type url{}; |
12858 | | |
12859 | 13.4k | 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 | 13.4k | const auto enforce_max_input_length = [&]() { |
12869 | 1.20k | if constexpr (store_values) { |
12870 | 1.20k | if (url.is_valid) { |
12871 | 1.20k | if constexpr (result_type_is_ada_url_aggregator) { |
12872 | 1.20k | if (url.buffer.size() > max_input_length) [[unlikely]] { |
12873 | 0 | url.is_valid = false; |
12874 | 0 | } |
12875 | 1.20k | } else { |
12876 | 0 | if (url.get_href_size() > max_input_length) [[unlikely]] { |
12877 | 0 | url.is_valid = false; |
12878 | 0 | } |
12879 | 0 | } |
12880 | 1.20k | } |
12881 | 1.20k | } |
12882 | 1.20k | }; 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()() constada::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()() constLine | Count | Source | 12868 | 1.20k | const auto enforce_max_input_length = [&]() { | 12869 | 1.20k | if constexpr (store_values) { | 12870 | 1.20k | if (url.is_valid) { | 12871 | 1.20k | if constexpr (result_type_is_ada_url_aggregator) { | 12872 | 1.20k | 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 | 1.20k | } | 12881 | 1.20k | } | 12882 | 1.20k | }; |
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 | 13.4k | 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 | 13.4k | if (base_url != nullptr) { |
12894 | 0 | url.is_valid &= base_url->is_valid; |
12895 | 0 | } |
12896 | 13.4k | if (!url.is_valid) { |
12897 | 0 | return url; |
12898 | 0 | } |
12899 | | |
12900 | | // Simple absolute / relative fast paths (before tabs/newline scan). |
12901 | 13.4k | if constexpr (store_values) { |
12902 | 13.4k | bool hit_fast_path = false; |
12903 | 13.4k | 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 | 13.4k | const auto* p = reinterpret_cast<const uint8_t*>(user_input.data()); |
12907 | 13.4k | const size_t n = user_input.size(); |
12908 | 13.4k | size_t host_start = 0; |
12909 | 13.4k | if (n >= 8 && p[4] == ':' && p[5] == '/' && p[6] == '/') { |
12910 | 13.4k | host_start = 7; |
12911 | 13.4k | } else if (n >= 9 && p[5] == ':' && p[6] == '/' && p[7] == '/') { |
12912 | 0 | host_start = 8; |
12913 | 0 | } |
12914 | 13.4k | const uint8_t host_first = host_start != 0 ? p[host_start] : 0; |
12915 | 13.4k | const bool skip_ip = |
12916 | 13.4k | host_first == '[' || (host_first >= '0' && host_first <= '9'); |
12917 | 13.4k | const bool skip_userinfo = |
12918 | 13.4k | host_start != 0 && authority_has_at(p, host_start, n); |
12919 | 13.4k | hit_fast_path = !skip_ip && !skip_userinfo && |
12920 | 4.74k | try_parse_simple_absolute(user_input, url); |
12921 | 13.4k | } else { |
12922 | 0 | hit_fast_path = try_parse_simple_relative(user_input, *base_url, url); |
12923 | 0 | } |
12924 | 13.4k | if (hit_fast_path) { |
12925 | 1.31k | if constexpr (result_type_is_ada_url_aggregator) { |
12926 | 1.31k | if (url.buffer.size() > max_input_length) [[unlikely]] { |
12927 | 0 | url.is_valid = false; |
12928 | 0 | } |
12929 | 1.31k | } 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 | 1.31k | return url; |
12941 | 1.31k | } |
12942 | 13.4k | } |
12943 | | |
12944 | 12.1k | state state = state::SCHEME_START; |
12945 | | |
12946 | 13.4k | std::string tmp_buffer; |
12947 | 13.4k | std::string_view url_data; |
12948 | 13.4k | if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] { |
12949 | 174 | 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 | 174 | helpers::remove_ascii_tab_or_newline(tmp_buffer); |
12953 | 174 | url_data = tmp_buffer; |
12954 | 13.2k | } else [[likely]] { |
12955 | 13.2k | url_data = user_input; |
12956 | 13.2k | } |
12957 | | |
12958 | | // Leading and trailing control characters are uncommon and easy to deal with |
12959 | | // (no performance concern). |
12960 | 13.4k | helpers::trim_c0_whitespace(url_data); |
12961 | | |
12962 | 13.4k | 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 | 13.4k | uint32_t reserve_capacity = |
12975 | 13.4k | (0xFFFFFFFF >> |
12976 | 13.4k | helpers::leading_zeroes(uint32_t(1 | user_input.size()))) + |
12977 | 13.4k | 1; |
12978 | 13.4k | url.reserve(reserve_capacity); |
12979 | 13.4k | } |
12980 | | |
12981 | | // Optimization opportunity. Most websites do not have fragment. |
12982 | 13.4k | 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 | 13.4k | size_t input_position = 0; |
12992 | 13.4k | 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 | 65.7k | while (input_position <= input_size) { |
12998 | 63.7k | ada_log("In parsing at ", input_position, " out of ", input_size, |
12999 | 63.7k | " in state ", ada::to_string(state)); |
13000 | 63.7k | switch (state) { |
13001 | 12.1k | case state::SCHEME_START: { |
13002 | 12.1k | 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 | 12.1k | if ((input_position != input_size) && |
13006 | 12.1k | checkers::is_alpha(url_data[input_position])) { |
13007 | 12.1k | state = state::SCHEME; |
13008 | 12.1k | input_position++; |
13009 | 12.1k | } else { |
13010 | | // Otherwise, if state override is not given, set state to no scheme |
13011 | | // state and decrease pointer by 1. |
13012 | 0 | state = state::NO_SCHEME; |
13013 | 0 | } |
13014 | 12.1k | break; |
13015 | 0 | } |
13016 | 12.1k | case state::SCHEME: { |
13017 | 12.1k | 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 | 48.4k | while ((input_position != input_size) && |
13021 | 48.4k | (unicode::is_alnum_plus(url_data[input_position]))) { |
13022 | 36.3k | input_position++; |
13023 | 36.3k | } |
13024 | | // Otherwise, if c is U+003A (:), then: |
13025 | 12.1k | if ((input_position != input_size) && |
13026 | 12.1k | (url_data[input_position] == ':')) { |
13027 | 12.1k | ada_log("SCHEME the scheme should be ", |
13028 | 12.1k | url_data.substr(0, input_position)); |
13029 | 12.1k | 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 | 12.1k | } else { |
13034 | | // we pass the colon along instead of painfully adding it back. |
13035 | 12.1k | if (!url.parse_scheme_with_colon( |
13036 | 12.1k | url_data.substr(0, input_position + 1))) { |
13037 | 0 | return url; |
13038 | 0 | } |
13039 | 12.1k | } |
13040 | 12.1k | ada_log("SCHEME the scheme is ", url.get_protocol()); |
13041 | | |
13042 | | // If url's scheme is "file", then: |
13043 | | // NOLINTNEXTLINE(bugprone-branch-clone) |
13044 | 12.1k | 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 | 12.1k | else if (url.is_special() && base_url != nullptr && |
13052 | 0 | base_url->type == url.type) { |
13053 | | // Set state to special relative or authority state. |
13054 | 0 | state = state::SPECIAL_RELATIVE_OR_AUTHORITY; |
13055 | 0 | } |
13056 | | // Otherwise, if url is special, set state to special authority |
13057 | | // slashes state. |
13058 | 12.1k | else if (url.is_special()) { |
13059 | 12.1k | state = state::SPECIAL_AUTHORITY_SLASHES; |
13060 | 12.1k | } |
13061 | | // Otherwise, if remaining starts with an U+002F (/), set state to |
13062 | | // path or authority state and increase pointer by 1. |
13063 | 0 | else if (input_position + 1 < input_size && |
13064 | 0 | url_data[input_position + 1] == '/') { |
13065 | 0 | state = state::PATH_OR_AUTHORITY; |
13066 | 0 | input_position++; |
13067 | 0 | } |
13068 | | // Otherwise, set url's path to the empty string and set state to |
13069 | | // opaque path state. |
13070 | 0 | else { |
13071 | 0 | state = state::OPAQUE_PATH; |
13072 | 0 | } |
13073 | 12.1k | } |
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 | 12.1k | input_position++; |
13083 | 12.1k | break; |
13084 | 12.1k | } |
13085 | 0 | case state::NO_SCHEME: { |
13086 | 0 | 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 | 0 | const bool c_is_hash = |
13091 | 0 | 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 | 0 | if (base_url == nullptr || (base_url->has_opaque_path && !c_is_hash)) { |
13095 | 0 | ada_log("NO_SCHEME validation error"); |
13096 | 0 | url.is_valid = false; |
13097 | 0 | return url; |
13098 | 0 | } |
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 | 0 | } |
13138 | 12.1k | case state::AUTHORITY: { |
13139 | 12.1k | 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 | 12.1k | if (url_data.find('@', input_position) == std::string_view::npos) { |
13151 | 11.8k | state = state::HOST; |
13152 | 11.8k | break; |
13153 | 11.8k | } |
13154 | 257 | bool at_sign_seen{false}; |
13155 | 257 | 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 | 2.02k | do { |
13162 | 2.02k | std::string_view view = url_data.substr(input_position); |
13163 | | // The delimiters are @, /, ? \\. |
13164 | 2.02k | size_t location = |
13165 | 2.02k | url.is_special() ? helpers::find_authority_delimiter_special(view) |
13166 | 2.02k | : helpers::find_authority_delimiter(view); |
13167 | 2.02k | std::string_view authority_view = view.substr(0, location); |
13168 | 2.02k | size_t end_of_authority = input_position + authority_view.size(); |
13169 | | // If c is U+0040 (@), then: |
13170 | 2.02k | if ((end_of_authority != input_size) && |
13171 | 2.00k | (url_data[end_of_authority] == '@')) { |
13172 | | // If atSignSeen is true, then prepend "%40" to buffer. |
13173 | 1.77k | if (at_sign_seen) { |
13174 | 1.53k | if (password_token_seen) { |
13175 | 430 | if constexpr (result_type_is_ada_url) { |
13176 | 0 | url.password += "%40"; |
13177 | 430 | } else { |
13178 | 430 | url.append_base_password("%40"); |
13179 | 430 | } |
13180 | 1.10k | } else { |
13181 | 1.10k | if constexpr (result_type_is_ada_url) { |
13182 | 0 | url.username += "%40"; |
13183 | 1.10k | } else { |
13184 | 1.10k | url.append_base_username("%40"); |
13185 | 1.10k | } |
13186 | 1.10k | } |
13187 | 1.53k | } |
13188 | | |
13189 | 1.77k | at_sign_seen = true; |
13190 | | |
13191 | 1.77k | if (!password_token_seen) { |
13192 | 1.34k | size_t password_token_location = authority_view.find(':'); |
13193 | 1.34k | password_token_seen = |
13194 | 1.34k | password_token_location != std::string_view::npos; |
13195 | | |
13196 | 1.34k | if constexpr (store_values) { |
13197 | 1.34k | if (!password_token_seen) { |
13198 | 1.27k | 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 | 1.27k | } else { |
13203 | 1.27k | url.append_base_username(unicode::percent_encode( |
13204 | 1.27k | authority_view, |
13205 | 1.27k | character_sets::USERINFO_PERCENT_ENCODE)); |
13206 | 1.27k | } |
13207 | 1.27k | } else { |
13208 | 68 | 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 | 68 | } else { |
13216 | 68 | url.append_base_username(unicode::percent_encode( |
13217 | 68 | authority_view.substr(0, password_token_location), |
13218 | 68 | character_sets::USERINFO_PERCENT_ENCODE)); |
13219 | 68 | url.append_base_password(unicode::percent_encode( |
13220 | 68 | authority_view.substr(password_token_location + 1), |
13221 | 68 | character_sets::USERINFO_PERCENT_ENCODE)); |
13222 | 68 | } |
13223 | 68 | } |
13224 | 1.34k | } |
13225 | 1.34k | } else if constexpr (store_values) { |
13226 | 430 | if constexpr (result_type_is_ada_url) { |
13227 | 0 | url.password += unicode::percent_encode( |
13228 | 0 | authority_view, character_sets::USERINFO_PERCENT_ENCODE); |
13229 | 430 | } else { |
13230 | 430 | url.append_base_password(unicode::percent_encode( |
13231 | 430 | authority_view, character_sets::USERINFO_PERCENT_ENCODE)); |
13232 | 430 | } |
13233 | 430 | } |
13234 | 1.77k | } |
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 | 257 | else if (end_of_authority == input_size || |
13239 | 229 | url_data[end_of_authority] == '/' || |
13240 | 22 | url_data[end_of_authority] == '?' || |
13241 | 257 | (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 | 257 | if (at_sign_seen && authority_view.empty()) { |
13245 | 8 | url.is_valid = false; |
13246 | 8 | return url; |
13247 | 8 | } |
13248 | 249 | state = state::HOST; |
13249 | 249 | break; |
13250 | 257 | } |
13251 | 1.77k | 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 | 1.77k | input_position = end_of_authority + 1; |
13261 | 1.77k | } while (true); |
13262 | | |
13263 | 249 | break; |
13264 | 257 | } |
13265 | 249 | case state::SPECIAL_RELATIVE_OR_AUTHORITY: { |
13266 | 0 | ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ", |
13267 | 0 | 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 | 0 | if (url_data.substr(input_position, 2) == "//") { |
13273 | 0 | state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES; |
13274 | 0 | input_position += 2; |
13275 | 0 | } 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 | 0 | break; |
13282 | 257 | } |
13283 | 0 | case state::PATH_OR_AUTHORITY: { |
13284 | 0 | ada_log("PATH_OR_AUTHORITY ", |
13285 | 0 | helpers::substring(url_data, input_position)); |
13286 | | |
13287 | | // If c is U+002F (/), then set state to authority state. |
13288 | 0 | if ((input_position != input_size) && |
13289 | 0 | (url_data[input_position] == '/')) { |
13290 | 0 | state = state::AUTHORITY; |
13291 | 0 | input_position++; |
13292 | 0 | } else { |
13293 | | // Otherwise, set state to path state, and decrease pointer by 1. |
13294 | 0 | state = state::PATH; |
13295 | 0 | } |
13296 | |
|
13297 | 0 | break; |
13298 | 257 | } |
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 | 12.1k | case state::SPECIAL_AUTHORITY_SLASHES: { |
13426 | 12.1k | ada_log("SPECIAL_AUTHORITY_SLASHES ", |
13427 | 12.1k | 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 | 12.1k | if (url_data.substr(input_position, 2) == "//") { |
13433 | 12.1k | input_position += 2; |
13434 | 12.1k | } |
13435 | | |
13436 | 12.1k | [[fallthrough]]; |
13437 | 12.1k | } |
13438 | 12.1k | case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: { |
13439 | 12.1k | ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ", |
13440 | 12.1k | 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 | 12.3k | while ((input_position != input_size) && |
13445 | 12.3k | ((url_data[input_position] == '/') || |
13446 | 12.2k | (url_data[input_position] == '\\'))) { |
13447 | 254 | input_position++; |
13448 | 254 | } |
13449 | 12.1k | state = state::AUTHORITY; |
13450 | | |
13451 | 12.1k | break; |
13452 | 12.1k | } |
13453 | 425 | case state::QUERY: { |
13454 | 425 | ada_log("QUERY ", helpers::substring(url_data, input_position)); |
13455 | 425 | 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 | 425 | const uint8_t* query_percent_encode_set = |
13459 | 425 | url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE |
13460 | 425 | : 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 | 425 | url.update_base_search(url_data.substr(input_position), |
13465 | 425 | query_percent_encode_set); |
13466 | 425 | ada_log("QUERY update_base_search completed "); |
13467 | 425 | if (fragment.has_value()) { |
13468 | 10 | url.update_unencoded_base_hash(*fragment); |
13469 | 10 | } |
13470 | 425 | } |
13471 | 425 | enforce_max_input_length(); |
13472 | 425 | return url; |
13473 | 12.1k | } |
13474 | 12.0k | case state::HOST: { |
13475 | 12.0k | ada_log("HOST ", helpers::substring(url_data, input_position)); |
13476 | | |
13477 | 12.0k | std::string_view host_view = url_data.substr(input_position); |
13478 | 12.0k | auto [location, found_colon] = |
13479 | 12.0k | helpers::get_host_delimiter_location(url.is_special(), host_view); |
13480 | 12.0k | input_position = (location != std::string_view::npos) |
13481 | 12.0k | ? input_position + location |
13482 | 12.0k | : 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 | 12.0k | 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 | 759 | ada_log("HOST parsing ", host_view); |
13491 | 759 | if (!url.parse_host(host_view)) { |
13492 | 155 | return url; |
13493 | 155 | } |
13494 | 604 | 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 | 604 | state = state::PORT; |
13498 | 604 | input_position++; |
13499 | 604 | } |
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 | 11.3k | else { |
13506 | | // If url is special and host_view is the empty string, validation |
13507 | | // error, return failure. |
13508 | 11.3k | if (host_view.empty() && url.is_special()) { |
13509 | 5 | url.is_valid = false; |
13510 | 5 | return url; |
13511 | 5 | } |
13512 | 11.3k | 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 | 11.3k | if (host_view.empty()) { |
13516 | 0 | url.update_base_hostname(""); |
13517 | 11.3k | } else if (!url.parse_host(host_view)) { |
13518 | 10.2k | return url; |
13519 | 10.2k | } |
13520 | 1.11k | ada_log("HOST parsing results in ", url.get_hostname(), |
13521 | 1.11k | " href=", url.get_href()); |
13522 | | |
13523 | | // Set url's host to host, and state to path start state. |
13524 | 1.11k | state = state::PATH_START; |
13525 | 1.11k | } |
13526 | | |
13527 | 1.71k | break; |
13528 | 12.0k | } |
13529 | 1.71k | case state::OPAQUE_PATH: { |
13530 | 0 | 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 | 0 | 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 | 0 | size_t location = view.find('?'); |
13546 | 0 | if (location != std::string_view::npos) { |
13547 | 0 | view.remove_suffix(view.size() - location); |
13548 | 0 | state = state::QUERY; |
13549 | 0 | input_position += location + 1; |
13550 | 0 | } else { |
13551 | 0 | input_position = input_size + 1; |
13552 | 0 | } |
13553 | 0 | 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 | 0 | if (view.ends_with(' ')) { |
13558 | 0 | std::string modified_view = |
13559 | 0 | std::string(view.substr(0, view.size() - 1)) + "%20"; |
13560 | 0 | url.update_base_pathname(unicode::percent_encode( |
13561 | 0 | modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE)); |
13562 | 0 | } else { |
13563 | 0 | url.update_base_pathname(unicode::percent_encode( |
13564 | 0 | view, character_sets::C0_CONTROL_PERCENT_ENCODE)); |
13565 | 0 | } |
13566 | 0 | break; |
13567 | 12.0k | } |
13568 | 604 | case state::PORT: { |
13569 | 604 | ada_log("PORT ", helpers::substring(url_data, input_position)); |
13570 | 604 | std::string_view port_view = url_data.substr(input_position); |
13571 | 604 | input_position += url.parse_port(port_view, true); |
13572 | 604 | if (!url.is_valid) { |
13573 | 511 | return url; |
13574 | 511 | } |
13575 | 93 | state = state::PATH_START; |
13576 | 93 | [[fallthrough]]; |
13577 | 93 | } |
13578 | 1.20k | case state::PATH_START: { |
13579 | 1.20k | 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 | 1.20k | if constexpr (!store_values) { |
13585 | 0 | return url; |
13586 | 0 | } |
13587 | | |
13588 | | // If url is special, then: |
13589 | 1.20k | if (url.is_special()) { |
13590 | | // Set state to path state. |
13591 | 1.20k | state = state::PATH; |
13592 | | |
13593 | | // Optimization: Avoiding going into PATH state improves the |
13594 | | // performance of urls ending with /. |
13595 | 1.20k | if (input_position == input_size) { |
13596 | 105 | if constexpr (store_values) { |
13597 | 105 | url.update_base_pathname("/"); |
13598 | 105 | if (fragment.has_value()) { |
13599 | 105 | url.update_unencoded_base_hash(*fragment); |
13600 | 105 | } |
13601 | 105 | } |
13602 | 105 | enforce_max_input_length(); |
13603 | 105 | return url; |
13604 | 105 | } |
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 | 1.10k | if ((url_data[input_position] != '/') && |
13609 | 108 | (url_data[input_position] != '\\')) { |
13610 | 105 | break; |
13611 | 105 | } |
13612 | 1.10k | } |
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 | 0 | else if ((input_position != input_size) && |
13616 | 0 | (url_data[input_position] == '?')) { |
13617 | 0 | state = state::QUERY; |
13618 | 0 | } |
13619 | | // Otherwise, if c is not the EOF code point: |
13620 | 0 | else if (input_position != input_size) { |
13621 | | // Set state to path state. |
13622 | 0 | state = state::PATH; |
13623 | | |
13624 | | // If c is not U+002F (/), then decrease pointer by 1. |
13625 | 0 | if (url_data[input_position] != '/') { |
13626 | 0 | break; |
13627 | 0 | } |
13628 | 0 | } |
13629 | | |
13630 | 997 | input_position++; |
13631 | 997 | break; |
13632 | 1.20k | } |
13633 | 1.10k | case state::PATH: { |
13634 | 1.10k | 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 | 1.10k | 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 | 1.10k | size_t locofquestionmark = view.find('?'); |
13647 | 1.10k | if (locofquestionmark != std::string_view::npos) { |
13648 | 425 | state = state::QUERY; |
13649 | 425 | view.remove_suffix(view.size() - locofquestionmark); |
13650 | 425 | input_position += locofquestionmark + 1; |
13651 | 677 | } else { |
13652 | 677 | input_position = input_size + 1; |
13653 | 677 | } |
13654 | 1.10k | if constexpr (store_values) { |
13655 | 1.10k | if constexpr (result_type_is_ada_url) { |
13656 | 0 | helpers::parse_prepared_path(view, url.type, url.path); |
13657 | 1.10k | } else { |
13658 | 1.10k | url.consume_prepared_path(view); |
13659 | 1.10k | ADA_ASSERT_TRUE(url.validate()); |
13660 | 1.10k | } |
13661 | 1.10k | } |
13662 | 1.10k | break; |
13663 | 1.20k | } |
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 | 1.20k | } |
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 | 63.7k | } |
13852 | 63.7k | } |
13853 | 1.99k | if constexpr (store_values) { |
13854 | 1.99k | if (fragment.has_value()) { |
13855 | 26 | url.update_unencoded_base_hash(*fragment); |
13856 | 26 | } |
13857 | 1.99k | } |
13858 | 1.99k | enforce_max_input_length(); |
13859 | 1.99k | return url; |
13860 | 13.4k | } 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 | 13.4k | 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 | 13.4k | constexpr bool result_type_is_ada_url = std::is_same_v<url, result_type>; | 12847 | 13.4k | constexpr bool result_type_is_ada_url_aggregator = | 12848 | 13.4k | std::is_same_v<url_aggregator, result_type>; | 12849 | 13.4k | static_assert(result_type_is_ada_url || | 12850 | 13.4k | result_type_is_ada_url_aggregator); // We don't support | 12851 | | // anything else for now. | 12852 | | | 12853 | 13.4k | ada_log("ada::parser::parse_url('", user_input, "' [", user_input.size(), | 12854 | 13.4k | " bytes],", (base_url != nullptr ? base_url->to_string() : "null"), | 12855 | 13.4k | ")"); | 12856 | | | 12857 | 13.4k | result_type url{}; | 12858 | | | 12859 | 13.4k | 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 | 13.4k | const auto enforce_max_input_length = [&]() { | 12869 | 13.4k | if constexpr (store_values) { | 12870 | 13.4k | if (url.is_valid) { | 12871 | 13.4k | if constexpr (result_type_is_ada_url_aggregator) { | 12872 | 13.4k | if (url.buffer.size() > max_input_length) [[unlikely]] { | 12873 | 13.4k | url.is_valid = false; | 12874 | 13.4k | } | 12875 | 13.4k | } else { | 12876 | 13.4k | if (url.get_href_size() > max_input_length) [[unlikely]] { | 12877 | 13.4k | url.is_valid = false; | 12878 | 13.4k | } | 12879 | 13.4k | } | 12880 | 13.4k | } | 12881 | 13.4k | } | 12882 | 13.4k | }; | 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 | 13.4k | 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 | 13.4k | if (base_url != nullptr) { | 12894 | 0 | url.is_valid &= base_url->is_valid; | 12895 | 0 | } | 12896 | 13.4k | if (!url.is_valid) { | 12897 | 0 | return url; | 12898 | 0 | } | 12899 | | | 12900 | | // Simple absolute / relative fast paths (before tabs/newline scan). | 12901 | 13.4k | if constexpr (store_values) { | 12902 | 13.4k | bool hit_fast_path = false; | 12903 | 13.4k | 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 | 13.4k | const auto* p = reinterpret_cast<const uint8_t*>(user_input.data()); | 12907 | 13.4k | const size_t n = user_input.size(); | 12908 | 13.4k | size_t host_start = 0; | 12909 | 13.4k | if (n >= 8 && p[4] == ':' && p[5] == '/' && p[6] == '/') { | 12910 | 13.4k | host_start = 7; | 12911 | 13.4k | } else if (n >= 9 && p[5] == ':' && p[6] == '/' && p[7] == '/') { | 12912 | 0 | host_start = 8; | 12913 | 0 | } | 12914 | 13.4k | const uint8_t host_first = host_start != 0 ? p[host_start] : 0; | 12915 | 13.4k | const bool skip_ip = | 12916 | 13.4k | host_first == '[' || (host_first >= '0' && host_first <= '9'); | 12917 | 13.4k | const bool skip_userinfo = | 12918 | 13.4k | host_start != 0 && authority_has_at(p, host_start, n); | 12919 | 13.4k | hit_fast_path = !skip_ip && !skip_userinfo && | 12920 | 4.74k | try_parse_simple_absolute(user_input, url); | 12921 | 13.4k | } else { | 12922 | 0 | hit_fast_path = try_parse_simple_relative(user_input, *base_url, url); | 12923 | 0 | } | 12924 | 13.4k | if (hit_fast_path) { | 12925 | 1.31k | if constexpr (result_type_is_ada_url_aggregator) { | 12926 | 1.31k | 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 | 1.31k | return url; | 12941 | 1.31k | } | 12942 | 13.4k | } | 12943 | | | 12944 | 12.1k | state state = state::SCHEME_START; | 12945 | | | 12946 | 13.4k | std::string tmp_buffer; | 12947 | 13.4k | std::string_view url_data; | 12948 | 13.4k | if (unicode::has_tabs_or_newline(user_input)) [[unlikely]] { | 12949 | 174 | 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 | 174 | helpers::remove_ascii_tab_or_newline(tmp_buffer); | 12953 | 174 | url_data = tmp_buffer; | 12954 | 13.2k | } else [[likely]] { | 12955 | 13.2k | url_data = user_input; | 12956 | 13.2k | } | 12957 | | | 12958 | | // Leading and trailing control characters are uncommon and easy to deal with | 12959 | | // (no performance concern). | 12960 | 13.4k | helpers::trim_c0_whitespace(url_data); | 12961 | | | 12962 | 13.4k | 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 | 13.4k | uint32_t reserve_capacity = | 12975 | 13.4k | (0xFFFFFFFF >> | 12976 | 13.4k | helpers::leading_zeroes(uint32_t(1 | user_input.size()))) + | 12977 | 13.4k | 1; | 12978 | 13.4k | url.reserve(reserve_capacity); | 12979 | 13.4k | } | 12980 | | | 12981 | | // Optimization opportunity. Most websites do not have fragment. | 12982 | 13.4k | 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 | 13.4k | size_t input_position = 0; | 12992 | 13.4k | 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 | 65.7k | while (input_position <= input_size) { | 12998 | 63.7k | ada_log("In parsing at ", input_position, " out of ", input_size, | 12999 | 63.7k | " in state ", ada::to_string(state)); | 13000 | 63.7k | switch (state) { | 13001 | 12.1k | case state::SCHEME_START: { | 13002 | 12.1k | 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 | 12.1k | if ((input_position != input_size) && | 13006 | 12.1k | checkers::is_alpha(url_data[input_position])) { | 13007 | 12.1k | state = state::SCHEME; | 13008 | 12.1k | input_position++; | 13009 | 12.1k | } else { | 13010 | | // Otherwise, if state override is not given, set state to no scheme | 13011 | | // state and decrease pointer by 1. | 13012 | 0 | state = state::NO_SCHEME; | 13013 | 0 | } | 13014 | 12.1k | break; | 13015 | 0 | } | 13016 | 12.1k | case state::SCHEME: { | 13017 | 12.1k | 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 | 48.4k | while ((input_position != input_size) && | 13021 | 48.4k | (unicode::is_alnum_plus(url_data[input_position]))) { | 13022 | 36.3k | input_position++; | 13023 | 36.3k | } | 13024 | | // Otherwise, if c is U+003A (:), then: | 13025 | 12.1k | if ((input_position != input_size) && | 13026 | 12.1k | (url_data[input_position] == ':')) { | 13027 | 12.1k | ada_log("SCHEME the scheme should be ", | 13028 | 12.1k | 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 | 12.1k | } else { | 13034 | | // we pass the colon along instead of painfully adding it back. | 13035 | 12.1k | if (!url.parse_scheme_with_colon( | 13036 | 12.1k | url_data.substr(0, input_position + 1))) { | 13037 | 0 | return url; | 13038 | 0 | } | 13039 | 12.1k | } | 13040 | 12.1k | ada_log("SCHEME the scheme is ", url.get_protocol()); | 13041 | | | 13042 | | // If url's scheme is "file", then: | 13043 | | // NOLINTNEXTLINE(bugprone-branch-clone) | 13044 | 12.1k | 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 | 12.1k | else if (url.is_special() && base_url != nullptr && | 13052 | 0 | base_url->type == url.type) { | 13053 | | // Set state to special relative or authority state. | 13054 | 0 | state = state::SPECIAL_RELATIVE_OR_AUTHORITY; | 13055 | 0 | } | 13056 | | // Otherwise, if url is special, set state to special authority | 13057 | | // slashes state. | 13058 | 12.1k | else if (url.is_special()) { | 13059 | 12.1k | state = state::SPECIAL_AUTHORITY_SLASHES; | 13060 | 12.1k | } | 13061 | | // Otherwise, if remaining starts with an U+002F (/), set state to | 13062 | | // path or authority state and increase pointer by 1. | 13063 | 0 | else if (input_position + 1 < input_size && | 13064 | 0 | url_data[input_position + 1] == '/') { | 13065 | 0 | state = state::PATH_OR_AUTHORITY; | 13066 | 0 | input_position++; | 13067 | 0 | } | 13068 | | // Otherwise, set url's path to the empty string and set state to | 13069 | | // opaque path state. | 13070 | 0 | else { | 13071 | 0 | state = state::OPAQUE_PATH; | 13072 | 0 | } | 13073 | 12.1k | } | 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 | 12.1k | input_position++; | 13083 | 12.1k | break; | 13084 | 12.1k | } | 13085 | 0 | case state::NO_SCHEME: { | 13086 | 0 | 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 | 0 | const bool c_is_hash = | 13091 | 0 | 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 | 0 | if (base_url == nullptr || (base_url->has_opaque_path && !c_is_hash)) { | 13095 | 0 | ada_log("NO_SCHEME validation error"); | 13096 | 0 | url.is_valid = false; | 13097 | 0 | return url; | 13098 | 0 | } | 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 | 0 | } | 13138 | 12.1k | case state::AUTHORITY: { | 13139 | 12.1k | 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 | 12.1k | if (url_data.find('@', input_position) == std::string_view::npos) { | 13151 | 11.8k | state = state::HOST; | 13152 | 11.8k | break; | 13153 | 11.8k | } | 13154 | 257 | bool at_sign_seen{false}; | 13155 | 257 | 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 | 2.02k | do { | 13162 | 2.02k | std::string_view view = url_data.substr(input_position); | 13163 | | // The delimiters are @, /, ? \\. | 13164 | 2.02k | size_t location = | 13165 | 2.02k | url.is_special() ? helpers::find_authority_delimiter_special(view) | 13166 | 2.02k | : helpers::find_authority_delimiter(view); | 13167 | 2.02k | std::string_view authority_view = view.substr(0, location); | 13168 | 2.02k | size_t end_of_authority = input_position + authority_view.size(); | 13169 | | // If c is U+0040 (@), then: | 13170 | 2.02k | if ((end_of_authority != input_size) && | 13171 | 2.00k | (url_data[end_of_authority] == '@')) { | 13172 | | // If atSignSeen is true, then prepend "%40" to buffer. | 13173 | 1.77k | if (at_sign_seen) { | 13174 | 1.53k | if (password_token_seen) { | 13175 | | if constexpr (result_type_is_ada_url) { | 13176 | | url.password += "%40"; | 13177 | 430 | } else { | 13178 | 430 | url.append_base_password("%40"); | 13179 | 430 | } | 13180 | 1.10k | } else { | 13181 | | if constexpr (result_type_is_ada_url) { | 13182 | | url.username += "%40"; | 13183 | 1.10k | } else { | 13184 | 1.10k | url.append_base_username("%40"); | 13185 | 1.10k | } | 13186 | 1.10k | } | 13187 | 1.53k | } | 13188 | | | 13189 | 1.77k | at_sign_seen = true; | 13190 | | | 13191 | 1.77k | if (!password_token_seen) { | 13192 | 1.34k | size_t password_token_location = authority_view.find(':'); | 13193 | 1.34k | password_token_seen = | 13194 | 1.34k | password_token_location != std::string_view::npos; | 13195 | | | 13196 | 1.34k | if constexpr (store_values) { | 13197 | 1.34k | 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 | 1.27k | } else { | 13203 | 1.27k | url.append_base_username(unicode::percent_encode( | 13204 | 1.27k | authority_view, | 13205 | 1.27k | character_sets::USERINFO_PERCENT_ENCODE)); | 13206 | 1.27k | } | 13207 | 1.27k | } 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 | 68 | } else { | 13216 | 68 | url.append_base_username(unicode::percent_encode( | 13217 | 68 | authority_view.substr(0, password_token_location), | 13218 | 68 | character_sets::USERINFO_PERCENT_ENCODE)); | 13219 | 68 | url.append_base_password(unicode::percent_encode( | 13220 | 68 | authority_view.substr(password_token_location + 1), | 13221 | 68 | character_sets::USERINFO_PERCENT_ENCODE)); | 13222 | 68 | } | 13223 | 68 | } | 13224 | 1.34k | } | 13225 | 1.34k | } 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 | 430 | } else { | 13230 | 430 | url.append_base_password(unicode::percent_encode( | 13231 | 430 | authority_view, character_sets::USERINFO_PERCENT_ENCODE)); | 13232 | 430 | } | 13233 | 430 | } | 13234 | 1.77k | } | 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 | 257 | else if (end_of_authority == input_size || | 13239 | 229 | url_data[end_of_authority] == '/' || | 13240 | 22 | url_data[end_of_authority] == '?' || | 13241 | 257 | (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 | 257 | if (at_sign_seen && authority_view.empty()) { | 13245 | 8 | url.is_valid = false; | 13246 | 8 | return url; | 13247 | 8 | } | 13248 | 249 | state = state::HOST; | 13249 | 249 | break; | 13250 | 257 | } | 13251 | 1.77k | 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 | 1.77k | input_position = end_of_authority + 1; | 13261 | 1.77k | } while (true); | 13262 | | | 13263 | 249 | break; | 13264 | 257 | } | 13265 | 249 | case state::SPECIAL_RELATIVE_OR_AUTHORITY: { | 13266 | 0 | ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ", | 13267 | 0 | 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 | 0 | if (url_data.substr(input_position, 2) == "//") { | 13273 | 0 | state = state::SPECIAL_AUTHORITY_IGNORE_SLASHES; | 13274 | 0 | input_position += 2; | 13275 | 0 | } 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 | 0 | break; | 13282 | 257 | } | 13283 | 0 | case state::PATH_OR_AUTHORITY: { | 13284 | 0 | ada_log("PATH_OR_AUTHORITY ", | 13285 | 0 | helpers::substring(url_data, input_position)); | 13286 | | | 13287 | | // If c is U+002F (/), then set state to authority state. | 13288 | 0 | if ((input_position != input_size) && | 13289 | 0 | (url_data[input_position] == '/')) { | 13290 | 0 | state = state::AUTHORITY; | 13291 | 0 | input_position++; | 13292 | 0 | } else { | 13293 | | // Otherwise, set state to path state, and decrease pointer by 1. | 13294 | 0 | state = state::PATH; | 13295 | 0 | } | 13296 | |
| 13297 | 0 | break; | 13298 | 257 | } | 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 | 12.1k | case state::SPECIAL_AUTHORITY_SLASHES: { | 13426 | 12.1k | ada_log("SPECIAL_AUTHORITY_SLASHES ", | 13427 | 12.1k | 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 | 12.1k | if (url_data.substr(input_position, 2) == "//") { | 13433 | 12.1k | input_position += 2; | 13434 | 12.1k | } | 13435 | | | 13436 | 12.1k | [[fallthrough]]; | 13437 | 12.1k | } | 13438 | 12.1k | case state::SPECIAL_AUTHORITY_IGNORE_SLASHES: { | 13439 | 12.1k | ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ", | 13440 | 12.1k | 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 | 12.3k | while ((input_position != input_size) && | 13445 | 12.3k | ((url_data[input_position] == '/') || | 13446 | 12.2k | (url_data[input_position] == '\\'))) { | 13447 | 254 | input_position++; | 13448 | 254 | } | 13449 | 12.1k | state = state::AUTHORITY; | 13450 | | | 13451 | 12.1k | break; | 13452 | 12.1k | } | 13453 | 425 | case state::QUERY: { | 13454 | 425 | ada_log("QUERY ", helpers::substring(url_data, input_position)); | 13455 | 425 | 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 | 425 | const uint8_t* query_percent_encode_set = | 13459 | 425 | url.is_special() ? character_sets::SPECIAL_QUERY_PERCENT_ENCODE | 13460 | 425 | : 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 | 425 | url.update_base_search(url_data.substr(input_position), | 13465 | 425 | query_percent_encode_set); | 13466 | 425 | ada_log("QUERY update_base_search completed "); | 13467 | 425 | if (fragment.has_value()) { | 13468 | 10 | url.update_unencoded_base_hash(*fragment); | 13469 | 10 | } | 13470 | 425 | } | 13471 | 425 | enforce_max_input_length(); | 13472 | 425 | return url; | 13473 | 12.1k | } | 13474 | 12.0k | case state::HOST: { | 13475 | 12.0k | ada_log("HOST ", helpers::substring(url_data, input_position)); | 13476 | | | 13477 | 12.0k | std::string_view host_view = url_data.substr(input_position); | 13478 | 12.0k | auto [location, found_colon] = | 13479 | 12.0k | helpers::get_host_delimiter_location(url.is_special(), host_view); | 13480 | 12.0k | input_position = (location != std::string_view::npos) | 13481 | 12.0k | ? input_position + location | 13482 | 12.0k | : 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 | 12.0k | 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 | 759 | ada_log("HOST parsing ", host_view); | 13491 | 759 | if (!url.parse_host(host_view)) { | 13492 | 155 | return url; | 13493 | 155 | } | 13494 | 604 | 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 | 604 | state = state::PORT; | 13498 | 604 | input_position++; | 13499 | 604 | } | 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 | 11.3k | else { | 13506 | | // If url is special and host_view is the empty string, validation | 13507 | | // error, return failure. | 13508 | 11.3k | if (host_view.empty() && url.is_special()) { | 13509 | 5 | url.is_valid = false; | 13510 | 5 | return url; | 13511 | 5 | } | 13512 | 11.3k | 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 | 11.3k | if (host_view.empty()) { | 13516 | 0 | url.update_base_hostname(""); | 13517 | 11.3k | } else if (!url.parse_host(host_view)) { | 13518 | 10.2k | return url; | 13519 | 10.2k | } | 13520 | 1.11k | ada_log("HOST parsing results in ", url.get_hostname(), | 13521 | 1.11k | " href=", url.get_href()); | 13522 | | | 13523 | | // Set url's host to host, and state to path start state. | 13524 | 1.11k | state = state::PATH_START; | 13525 | 1.11k | } | 13526 | | | 13527 | 1.71k | break; | 13528 | 12.0k | } | 13529 | 1.71k | case state::OPAQUE_PATH: { | 13530 | 0 | 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 | 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 | 0 | size_t location = view.find('?'); | 13546 | 0 | if (location != std::string_view::npos) { | 13547 | 0 | view.remove_suffix(view.size() - location); | 13548 | 0 | state = state::QUERY; | 13549 | 0 | input_position += location + 1; | 13550 | 0 | } else { | 13551 | 0 | input_position = input_size + 1; | 13552 | 0 | } | 13553 | 0 | 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 | 0 | if (view.ends_with(' ')) { | 13558 | 0 | std::string modified_view = | 13559 | 0 | std::string(view.substr(0, view.size() - 1)) + "%20"; | 13560 | 0 | url.update_base_pathname(unicode::percent_encode( | 13561 | 0 | modified_view, character_sets::C0_CONTROL_PERCENT_ENCODE)); | 13562 | 0 | } else { | 13563 | 0 | url.update_base_pathname(unicode::percent_encode( | 13564 | 0 | view, character_sets::C0_CONTROL_PERCENT_ENCODE)); | 13565 | 0 | } | 13566 | 0 | break; | 13567 | 12.0k | } | 13568 | 604 | case state::PORT: { | 13569 | 604 | ada_log("PORT ", helpers::substring(url_data, input_position)); | 13570 | 604 | std::string_view port_view = url_data.substr(input_position); | 13571 | 604 | input_position += url.parse_port(port_view, true); | 13572 | 604 | if (!url.is_valid) { | 13573 | 511 | return url; | 13574 | 511 | } | 13575 | 93 | state = state::PATH_START; | 13576 | 93 | [[fallthrough]]; | 13577 | 93 | } | 13578 | 1.20k | case state::PATH_START: { | 13579 | 1.20k | 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 | 1.20k | if (url.is_special()) { | 13590 | | // Set state to path state. | 13591 | 1.20k | state = state::PATH; | 13592 | | | 13593 | | // Optimization: Avoiding going into PATH state improves the | 13594 | | // performance of urls ending with /. | 13595 | 1.20k | if (input_position == input_size) { | 13596 | 105 | if constexpr (store_values) { | 13597 | 105 | url.update_base_pathname("/"); | 13598 | 105 | if (fragment.has_value()) { | 13599 | 105 | url.update_unencoded_base_hash(*fragment); | 13600 | 105 | } | 13601 | 105 | } | 13602 | 105 | enforce_max_input_length(); | 13603 | 105 | return url; | 13604 | 105 | } | 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 | 1.10k | if ((url_data[input_position] != '/') && | 13609 | 108 | (url_data[input_position] != '\\')) { | 13610 | 105 | break; | 13611 | 105 | } | 13612 | 1.10k | } | 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 | 0 | else if ((input_position != input_size) && | 13616 | 0 | (url_data[input_position] == '?')) { | 13617 | 0 | state = state::QUERY; | 13618 | 0 | } | 13619 | | // Otherwise, if c is not the EOF code point: | 13620 | 0 | else if (input_position != input_size) { | 13621 | | // Set state to path state. | 13622 | 0 | state = state::PATH; | 13623 | | | 13624 | | // If c is not U+002F (/), then decrease pointer by 1. | 13625 | 0 | if (url_data[input_position] != '/') { | 13626 | 0 | break; | 13627 | 0 | } | 13628 | 0 | } | 13629 | | | 13630 | 997 | input_position++; | 13631 | 997 | break; | 13632 | 1.20k | } | 13633 | 1.10k | case state::PATH: { | 13634 | 1.10k | 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 | 1.10k | 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 | 1.10k | size_t locofquestionmark = view.find('?'); | 13647 | 1.10k | if (locofquestionmark != std::string_view::npos) { | 13648 | 425 | state = state::QUERY; | 13649 | 425 | view.remove_suffix(view.size() - locofquestionmark); | 13650 | 425 | input_position += locofquestionmark + 1; | 13651 | 677 | } else { | 13652 | 677 | input_position = input_size + 1; | 13653 | 677 | } | 13654 | 1.10k | if constexpr (store_values) { | 13655 | | if constexpr (result_type_is_ada_url) { | 13656 | | helpers::parse_prepared_path(view, url.type, url.path); | 13657 | 1.10k | } else { | 13658 | 1.10k | url.consume_prepared_path(view); | 13659 | 1.10k | ADA_ASSERT_TRUE(url.validate()); | 13660 | 1.10k | } | 13661 | 1.10k | } | 13662 | 1.10k | break; | 13663 | 1.20k | } | 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 | 1.20k | } | 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 | 63.7k | } | 13852 | 63.7k | } | 13853 | 1.99k | if constexpr (store_values) { | 13854 | 1.99k | if (fragment.has_value()) { | 13855 | 26 | url.update_unencoded_base_hash(*fragment); | 13856 | 26 | } | 13857 | 1.99k | } | 13858 | 1.99k | enforce_max_input_length(); | 13859 | 1.99k | return url; | 13860 | 13.4k | } |
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 | 12.1k | ada::url_components& components, uint32_t new_difference) { |
13964 | 12.1k | components.username_end += new_difference; |
13965 | 12.1k | components.host_start += new_difference; |
13966 | 12.1k | components.host_end += new_difference; |
13967 | 12.1k | components.pathname_start += new_difference; |
13968 | 12.1k | if (components.search_start != ada::url_components::omitted) { |
13969 | 0 | components.search_start += new_difference; |
13970 | 0 | } |
13971 | 12.1k | if (components.hash_start != ada::url_components::omitted) { |
13972 | 0 | components.hash_start += new_difference; |
13973 | 0 | } |
13974 | 12.1k | } |
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 | 12.1k | const std::string_view input_with_colon) { |
13982 | 12.1k | ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon); |
13983 | 12.1k | ADA_ASSERT_TRUE(validate()); |
13984 | 12.1k | ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer)); |
13985 | 12.1k | std::string_view input{input_with_colon}; |
13986 | 12.1k | input.remove_suffix(1); |
13987 | 12.1k | auto parsed_type = ada::scheme::get_scheme_type(input); |
13988 | 12.1k | 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 | 12.1k | if (is_input_special) { // fast path!!! |
13994 | 12.1k | 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 | 12.1k | set_scheme_from_view_with_colon(input_with_colon); |
14018 | | |
14019 | 12.1k | 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 | 12.1k | } else { // slow path |
14032 | 0 | 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 | 0 | unicode::to_lower_ascii(_buffer.data(), _buffer.size()); |
14037 | |
|
14038 | 0 | 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 | 0 | 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 | 0 | } |
14081 | 0 | ADA_ASSERT_TRUE(validate()); |
14082 | 12.1k | return true; |
14083 | 12.1k | } bool ada::url_aggregator::parse_scheme_with_colon<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Line | Count | Source | 13981 | 12.1k | const std::string_view input_with_colon) { | 13982 | 12.1k | ada_log("url_aggregator::parse_scheme_with_colon ", input_with_colon); | 13983 | 12.1k | ADA_ASSERT_TRUE(validate()); | 13984 | 12.1k | ADA_ASSERT_TRUE(!helpers::overlaps(input_with_colon, buffer)); | 13985 | 12.1k | std::string_view input{input_with_colon}; | 13986 | 12.1k | input.remove_suffix(1); | 13987 | 12.1k | auto parsed_type = ada::scheme::get_scheme_type(input); | 13988 | 12.1k | 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 | 12.1k | 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 | 12.1k | type = parsed_type; | 14017 | 12.1k | 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 | 12.1k | } else { // slow path | 14032 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | } | 14081 | 12.1k | ADA_ASSERT_TRUE(validate()); | 14082 | 12.1k | return true; | 14083 | 12.1k | } |
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 | 12.1k | std::string_view new_scheme_with_colon) { |
14108 | 12.1k | ada_log("url_aggregator::set_scheme_from_view_with_colon ", |
14109 | 12.1k | new_scheme_with_colon); |
14110 | 12.1k | ADA_ASSERT_TRUE(validate()); |
14111 | 12.1k | ADA_ASSERT_TRUE(!new_scheme_with_colon.empty() && |
14112 | 12.1k | new_scheme_with_colon.back() == ':'); |
14113 | | // next line could overflow but unsigned arithmetic has well-defined |
14114 | | // overflows. |
14115 | 12.1k | uint32_t new_difference = |
14116 | 12.1k | uint32_t(new_scheme_with_colon.size()) - components.protocol_end; |
14117 | | |
14118 | 12.1k | if (buffer.empty()) { |
14119 | 12.1k | buffer.append(new_scheme_with_colon); |
14120 | 12.1k | } else { |
14121 | 0 | buffer.erase(0, components.protocol_end); |
14122 | 0 | buffer.insert(0, new_scheme_with_colon); |
14123 | 0 | } |
14124 | 12.1k | components.protocol_end += new_difference; |
14125 | | |
14126 | 12.1k | apply_shifted_non_scheme_offsets(components, new_difference); |
14127 | 12.1k | ADA_ASSERT_TRUE(validate()); |
14128 | 12.1k | } |
14129 | | |
14130 | 0 | inline void url_aggregator::set_scheme(std::string_view new_scheme) { |
14131 | 0 | ada_log("url_aggregator::set_scheme ", new_scheme); |
14132 | 0 | ADA_ASSERT_TRUE(validate()); |
14133 | 0 | ADA_ASSERT_TRUE(new_scheme.empty() || new_scheme.back() != ':'); |
14134 | | // next line could overflow but unsigned arithmetic has well-defined |
14135 | | // overflows. |
14136 | 0 | uint32_t new_difference = |
14137 | 0 | uint32_t(new_scheme.size()) - components.protocol_end + 1; |
14138 | |
|
14139 | 0 | type = ada::scheme::get_scheme_type(new_scheme); |
14140 | 0 | if (buffer.empty()) { |
14141 | 0 | buffer.append(helpers::concat(new_scheme, ":")); |
14142 | 0 | } else { |
14143 | 0 | buffer.erase(0, components.protocol_end); |
14144 | 0 | buffer.insert(0, helpers::concat(new_scheme, ":")); |
14145 | 0 | } |
14146 | 0 | components.protocol_end = uint32_t(new_scheme.size() + 1); |
14147 | |
|
14148 | 0 | apply_shifted_non_scheme_offsets(components, new_difference); |
14149 | 0 | ADA_ASSERT_TRUE(validate()); |
14150 | 0 | } |
14151 | | |
14152 | 0 | 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 | 0 | return buffer.size() + input_len * 3 + 16 > ada::get_max_input_length(); |
14157 | 0 | } |
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 | 0 | bool url_aggregator::set_pathname(const std::string_view input) { |
14303 | 0 | ada_log("url_aggregator::set_pathname ", input); |
14304 | 0 | ADA_ASSERT_TRUE(validate()); |
14305 | 0 | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
14306 | 0 | if (has_opaque_path) { |
14307 | 0 | return false; |
14308 | 0 | } |
14309 | 0 | std::optional<url_aggregator> saved_url; |
14310 | 0 | if (needs_rollback_snapshot(input.size())) { |
14311 | 0 | saved_url = *this; |
14312 | 0 | } |
14313 | 0 | clear_pathname(); |
14314 | 0 | parse_path(input); |
14315 | 0 | 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 | 0 | if (saved_url && buffer.size() > ada::get_max_input_length()) { |
14326 | 0 | *this = std::move(*saved_url); |
14327 | 0 | return false; |
14328 | 0 | } |
14329 | 0 | ADA_ASSERT_TRUE(validate()); |
14330 | 0 | return true; |
14331 | 0 | } |
14332 | | |
14333 | 887 | ada_really_inline void url_aggregator::parse_path(std::string_view input) { |
14334 | 887 | ada_log("url_aggregator::parse_path ", input); |
14335 | 887 | ADA_ASSERT_TRUE(validate()); |
14336 | 887 | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
14337 | 887 | std::string tmp_buffer; |
14338 | 887 | std::string_view internal_input; |
14339 | 887 | if (unicode::has_tabs_or_newline(input)) { |
14340 | 0 | tmp_buffer = input; |
14341 | | // Optimization opportunity: Instead of copying and then pruning, we could |
14342 | | // just directly build the string from user_input. |
14343 | 0 | helpers::remove_ascii_tab_or_newline(tmp_buffer); |
14344 | 0 | internal_input = tmp_buffer; |
14345 | 887 | } else { |
14346 | 887 | internal_input = input; |
14347 | 887 | } |
14348 | | |
14349 | | // If url is special, then: |
14350 | 887 | if (is_special()) { |
14351 | 887 | if (internal_input.empty()) { |
14352 | 134 | update_base_pathname("/"); |
14353 | 753 | } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) { |
14354 | 753 | consume_prepared_path(internal_input.substr(1)); |
14355 | 753 | } else { |
14356 | 0 | consume_prepared_path(internal_input); |
14357 | 0 | } |
14358 | 887 | } 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 | 887 | ADA_ASSERT_TRUE(validate()); |
14372 | 887 | } |
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 | 12.0k | ada_really_inline bool url_aggregator::parse_host(std::string_view input) { |
14467 | 12.0k | ada_log("url_aggregator:parse_host \"", input, "\" [", input.size(), |
14468 | 12.0k | " bytes]"); |
14469 | 12.0k | ADA_ASSERT_TRUE(validate()); |
14470 | 12.0k | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
14471 | 12.0k | if (input.empty()) { |
14472 | 1 | return is_valid = false; |
14473 | 1 | } // technically unnecessary. |
14474 | | // If input starts with U+005B ([), then: |
14475 | 12.0k | if (input[0] == '[') { |
14476 | | // If input does not end with U+005D (]), validation error, return failure. |
14477 | 7.30k | if (input.back() != ']') { |
14478 | 64 | return is_valid = false; |
14479 | 64 | } |
14480 | 7.23k | 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 | 7.23k | input.remove_prefix(1); |
14485 | 7.23k | input.remove_suffix(1); |
14486 | 7.23k | return parse_ipv6(input); |
14487 | 7.30k | } |
14488 | | |
14489 | | // If isNotSpecial is true, then return the result of opaque-host parsing |
14490 | | // input. |
14491 | 4.78k | if (!is_special()) { |
14492 | 0 | return parse_opaque_host(input); |
14493 | 0 | } |
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 | 4.78k | const uint64_t fast_result = checkers::try_parse_ipv4_fast(input); |
14506 | 4.78k | if (fast_result < checkers::ipv4_fast_fail) { |
14507 | 287 | if (!input.empty() && input.back() == '.') { |
14508 | 2 | update_base_hostname(input.substr(0, input.size() - 1)); |
14509 | 285 | } else { |
14510 | 285 | update_base_hostname(input); |
14511 | 285 | } |
14512 | 287 | host_type = IPV4; |
14513 | 287 | is_valid = true; |
14514 | 287 | ada_log("parse_host fast path decimal ipv4"); |
14515 | 287 | ADA_ASSERT_TRUE(validate()); |
14516 | 287 | return true; |
14517 | 287 | } |
14518 | 4.50k | uint8_t is_forbidden_or_upper = |
14519 | 4.50k | unicode::contains_forbidden_domain_code_point_or_upper(input.data(), |
14520 | 4.50k | input.size()); |
14521 | 4.50k | static constexpr std::string_view xn_dash{"xn-", 3}; |
14522 | 4.50k | if ((is_forbidden_or_upper & 1) == 0) { |
14523 | 1.59k | if ((is_forbidden_or_upper & 2) != 0) { |
14524 | 350 | std::string lowered(input); |
14525 | 350 | unicode::to_lower_ascii(lowered.data(), lowered.size()); |
14526 | 350 | if (lowered.find('-') == std::string_view::npos || |
14527 | 324 | 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 | 324 | if (checkers::is_ipv4(lowered)) { |
14531 | 170 | ada_log("parse_host fast path ipv4"); |
14532 | 170 | return parse_ipv4(lowered, false); |
14533 | 170 | } |
14534 | 154 | update_base_hostname(lowered); |
14535 | 154 | ada_log("parse_host fast path ", get_hostname()); |
14536 | 154 | is_valid = true; |
14537 | 154 | return true; |
14538 | 324 | } |
14539 | 1.24k | } else if (input.find('-') == std::string_view::npos || |
14540 | 1.21k | input.find(xn_dash) == std::string_view::npos) { |
14541 | | // Check IPv4 before mutating so failures leave the buffer untouched. |
14542 | 1.21k | if (checkers::is_ipv4(input)) { |
14543 | 954 | ada_log("parse_host fast path ipv4"); |
14544 | 954 | return parse_ipv4(input, false); |
14545 | 954 | } |
14546 | 263 | update_base_hostname(input); |
14547 | 263 | ada_log("parse_host fast path ", get_hostname()); |
14548 | 263 | is_valid = true; |
14549 | 263 | return true; |
14550 | 1.21k | } |
14551 | 2.90k | } else if (const size_t first_percent = input.find('%'); |
14552 | 2.90k | first_percent != std::string_view::npos) { |
14553 | 319 | std::string decoded = unicode::percent_decode(input, first_percent); |
14554 | 319 | const uint8_t decoded_flags = |
14555 | 319 | unicode::contains_forbidden_domain_code_point_or_upper(decoded.data(), |
14556 | 319 | decoded.size()); |
14557 | 319 | if ((decoded_flags & 1) == 0) { |
14558 | 204 | if ((decoded_flags & 2) != 0) { |
14559 | 75 | unicode::to_lower_ascii(decoded.data(), decoded.size()); |
14560 | 75 | } |
14561 | 204 | if (decoded.find('-') == std::string_view::npos || |
14562 | 193 | decoded.find(xn_dash) == std::string_view::npos) { |
14563 | | // Check IPv4 before mutating so failures leave the buffer untouched. |
14564 | 193 | if (checkers::is_ipv4(decoded)) { |
14565 | 102 | return parse_ipv4(decoded, false); |
14566 | 102 | } |
14567 | 91 | update_base_hostname(decoded); |
14568 | 91 | is_valid = true; |
14569 | 91 | return true; |
14570 | 193 | } |
14571 | 204 | } |
14572 | 319 | } |
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 | 2.76k | ada_log("parse_host calling to_ascii"); |
14578 | 2.76k | std::optional<std::string> host = std::string(get_hostname()); |
14579 | 2.76k | is_valid = ada::unicode::to_ascii(host, input, input.find('%')); |
14580 | 2.76k | if (!is_valid) { |
14581 | 1.33k | ada_log("parse_host to_ascii returns false"); |
14582 | 1.33k | return is_valid = false; |
14583 | 1.33k | } |
14584 | 1.43k | ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(), |
14585 | 1.43k | " bytes]"); |
14586 | | |
14587 | 1.43k | if (std::ranges::any_of(host.value(), |
14588 | 1.43k | 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 | 1.43k | if (checkers::is_ipv4(host.value())) { |
14595 | 1.20k | ada_log("parse_host got ipv4 ", *host); |
14596 | 1.20k | return parse_ipv4(host.value(), false); |
14597 | 1.20k | } |
14598 | | |
14599 | 229 | update_base_hostname(host.value()); |
14600 | 229 | ADA_ASSERT_TRUE(validate()); |
14601 | 229 | return true; |
14602 | 1.43k | } |
14603 | | |
14604 | | template <bool override_hostname> |
14605 | 0 | bool url_aggregator::set_host_or_hostname(const std::string_view input) { |
14606 | 0 | ada_log("url_aggregator::set_host_or_hostname ", input); |
14607 | 0 | ADA_ASSERT_TRUE(validate()); |
14608 | 0 | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
14609 | 0 | 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 | 0 | const bool was_valid = is_valid; |
14618 | 0 | std::optional<url_aggregator> saved_url; |
14619 | 0 | if (needs_rollback_snapshot(input.size())) { |
14620 | 0 | saved_url = *this; |
14621 | 0 | } |
14622 | |
|
14623 | 0 | auto restore_on_failure = [&]() { |
14624 | 0 | if (saved_url) { |
14625 | 0 | *this = std::move(*saved_url); |
14626 | 0 | } else { |
14627 | | // Buffer is untouched on parse failure; just restore the is_valid flag |
14628 | | // that parse_host may have cleared. |
14629 | 0 | is_valid = was_valid; |
14630 | 0 | } |
14631 | 0 | }; Unexecuted instantiation: ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() constUnexecuted instantiation: ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#1}::operator()() const |
14632 | |
|
14633 | 0 | size_t host_end_pos = input.find('#'); |
14634 | 0 | std::string_view host_input( |
14635 | 0 | input.data(), |
14636 | 0 | 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 | 0 | std::string _host_buf; |
14640 | 0 | std::string_view new_host; |
14641 | 0 | if (unicode::has_tabs_or_newline(host_input)) { |
14642 | 0 | _host_buf = host_input; |
14643 | 0 | helpers::remove_ascii_tab_or_newline(_host_buf); |
14644 | 0 | new_host = _host_buf; |
14645 | 0 | } else { |
14646 | 0 | new_host = host_input; |
14647 | 0 | } |
14648 | |
|
14649 | 0 | auto check_url_size = [&]() -> bool { |
14650 | 0 | if (saved_url && buffer.size() > ada::get_max_input_length()) { |
14651 | 0 | *this = std::move(*saved_url); |
14652 | 0 | return false; |
14653 | 0 | } |
14654 | 0 | return true; |
14655 | 0 | }; Unexecuted instantiation: ada::url_aggregator::set_host_or_hostname<false>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#2}::operator()() constUnexecuted instantiation: ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)::{lambda()#2}::operator()() const |
14656 | | |
14657 | | // If url's scheme is "file", then set state to file host state, instead of |
14658 | | // host state. |
14659 | 0 | if (type != ada::scheme::type::FILE) { |
14660 | 0 | std::string_view host_view = new_host; |
14661 | 0 | auto [location, found_colon] = |
14662 | 0 | 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 | 0 | if (found_colon) { |
14668 | | // If buffer is the empty string, host-missing validation error, return |
14669 | | // failure. |
14670 | 0 | std::string_view host_buffer = host_view.substr(0, location); |
14671 | 0 | if (host_buffer.empty()) { |
14672 | 0 | return false; |
14673 | 0 | } |
14674 | | |
14675 | | // If state override is given and state override is hostname state, then |
14676 | | // return failure. |
14677 | 0 | if constexpr (override_hostname) { |
14678 | 0 | return false; |
14679 | 0 | } |
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 | 0 | if (!succeeded) { |
14684 | 0 | restore_on_failure(); |
14685 | 0 | return false; |
14686 | 0 | } 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 | 0 | std::string_view port_buffer = new_host.substr(location + 1); |
14696 | 0 | if (!port_buffer.empty()) { |
14697 | 0 | set_port(port_buffer); |
14698 | 0 | } |
14699 | 0 | return check_url_size(); |
14700 | 0 | } |
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 | 0 | else { |
14705 | | // If url is special and host_view is the empty string, host-missing |
14706 | | // validation error, return failure. |
14707 | 0 | if (host_view.empty() && is_special()) { |
14708 | 0 | return false; |
14709 | 0 | } |
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 | 0 | 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 | 0 | 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 | 0 | bool succeeded = parse_host(host_view); |
14735 | 0 | if (!succeeded) { |
14736 | 0 | restore_on_failure(); |
14737 | 0 | return false; |
14738 | 0 | } else if (has_dash_dot()) { |
14739 | | // Should remove dash_dot from pathname |
14740 | 0 | delete_dash_dot(); |
14741 | 0 | } |
14742 | 0 | return check_url_size(); |
14743 | 0 | } |
14744 | 0 | } |
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> >) Unexecuted instantiation: bool ada::url_aggregator::set_host_or_hostname<true>(std::__1::basic_string_view<char, std::__1::char_traits<char> >) |
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 | 0 | bool url_aggregator::set_hostname(const std::string_view input) { |
14779 | 0 | ada_log("url_aggregator::set_hostname '", input, "'"); |
14780 | 0 | ADA_ASSERT_TRUE(validate()); |
14781 | 0 | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
14782 | 0 | return set_host_or_hostname<true>(input); |
14783 | 0 | } |
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 | 0 | ada_lifetime_bound { |
14814 | 0 | ada_log("url_aggregator::get_username"); |
14815 | 0 | if (has_non_empty_username()) { |
14816 | 0 | return helpers::substring(buffer, components.protocol_end + 2, |
14817 | 0 | components.username_end); |
14818 | 0 | } |
14819 | 0 | return ""; |
14820 | 0 | } |
14821 | | |
14822 | | [[nodiscard]] std::string_view url_aggregator::get_password() const |
14823 | 0 | ada_lifetime_bound { |
14824 | 0 | ada_log("url_aggregator::get_password"); |
14825 | 0 | if (has_non_empty_password()) { |
14826 | 0 | return helpers::substring(buffer, components.username_end + 1, |
14827 | 0 | components.host_start); |
14828 | 0 | } |
14829 | 0 | return ""; |
14830 | 0 | } |
14831 | | |
14832 | | [[nodiscard]] std::string_view url_aggregator::get_port() const |
14833 | 0 | ada_lifetime_bound { |
14834 | 0 | ada_log("url_aggregator::get_port"); |
14835 | 0 | if (components.port == url_components::omitted) { |
14836 | 0 | return ""; |
14837 | 0 | } |
14838 | 0 | return helpers::substring(buffer, components.host_end + 1, |
14839 | 0 | components.pathname_start); |
14840 | 0 | } |
14841 | | |
14842 | | [[nodiscard]] std::string_view url_aggregator::get_hash() const |
14843 | 0 | ada_lifetime_bound { |
14844 | 0 | 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 | 0 | if (components.hash_start == url_components::omitted) { |
14848 | 0 | return ""; |
14849 | 0 | } |
14850 | 0 | if (buffer.size() - components.hash_start <= 1) { |
14851 | 0 | return ""; |
14852 | 0 | } |
14853 | 0 | return helpers::substring(buffer, components.hash_start); |
14854 | 0 | } |
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 | 3.06k | ada_lifetime_bound { |
14877 | 3.06k | 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 | 3.06k | size_t start = components.host_start; |
14882 | | // So host_start is not where the host begins. |
14883 | 3.06k | if (components.host_end > components.host_start && |
14884 | 303 | buffer[components.host_start] == '@') { |
14885 | 23 | start++; |
14886 | 23 | } |
14887 | 3.06k | return helpers::substring(buffer, start, components.host_end); |
14888 | 3.06k | } |
14889 | | |
14890 | | [[nodiscard]] std::string_view url_aggregator::get_search() const |
14891 | 0 | ada_lifetime_bound { |
14892 | 0 | 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 | 0 | if (components.search_start == url_components::omitted) { |
14896 | 0 | return ""; |
14897 | 0 | } |
14898 | 0 | auto ending_index = uint32_t(buffer.size()); |
14899 | 0 | if (components.hash_start != url_components::omitted) { |
14900 | 0 | ending_index = components.hash_start; |
14901 | 0 | } |
14902 | 0 | if (ending_index - components.search_start <= 1) { |
14903 | 0 | return ""; |
14904 | 0 | } |
14905 | 0 | return helpers::substring(buffer, components.search_start, ending_index); |
14906 | 0 | } |
14907 | | |
14908 | | [[nodiscard]] std::string_view url_aggregator::get_protocol() const |
14909 | 0 | ada_lifetime_bound { |
14910 | 0 | ada_log("url_aggregator::get_protocol"); |
14911 | 0 | return helpers::substring(buffer, 0, components.protocol_end); |
14912 | 0 | } |
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 | 2.42k | bool url_aggregator::parse_ipv4(std::string_view input, bool in_place) { |
15022 | 2.42k | ada_log("parse_ipv4 ", input, " [", input.size(), |
15023 | 2.42k | " bytes], overlaps with buffer: ", |
15024 | 2.42k | helpers::overlaps(input, buffer) ? "yes" : "no"); |
15025 | 2.42k | ADA_ASSERT_TRUE(validate()); |
15026 | 2.42k | if (input.empty()) { |
15027 | 0 | return is_valid = false; |
15028 | 0 | } |
15029 | 2.42k | const bool trailing_dot = (input.back() == '.'); |
15030 | 2.42k | if (trailing_dot) { |
15031 | 30 | input.remove_suffix(1); |
15032 | 30 | if (input.empty()) { |
15033 | 0 | return is_valid = false; |
15034 | 0 | } |
15035 | 30 | } |
15036 | | |
15037 | 2.42k | const uint64_t fast = checkers::try_parse_ipv4_fast(input); |
15038 | 2.42k | 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 | 7 | if (!(in_place && !trailing_dot)) { |
15042 | 7 | if (helpers::overlaps(input, buffer)) { |
15043 | 0 | update_base_hostname(std::string(input)); |
15044 | 7 | } else { |
15045 | 7 | update_base_hostname(input); |
15046 | 7 | } |
15047 | 7 | } |
15048 | 7 | host_type = IPV4; |
15049 | 7 | ADA_ASSERT_TRUE(validate()); |
15050 | 7 | return true; |
15051 | 7 | } |
15052 | | |
15053 | 2.42k | const char* p = input.data(); |
15054 | 2.42k | const char* end = p + input.size(); |
15055 | 2.42k | uint64_t ipv4 = 0; |
15056 | 2.42k | int digit_count = 0; |
15057 | 2.42k | int pure_decimal_count = 0; |
15058 | | |
15059 | 2.66k | for (; digit_count < 4 && p < end; ++digit_count) { |
15060 | 2.65k | uint64_t segment = 0; |
15061 | 2.65k | bool pure = false; |
15062 | 2.65k | if (!detail::parse_ipv4_number(p, end, segment, pure)) { |
15063 | 1.69k | return is_valid = false; |
15064 | 1.69k | } |
15065 | 961 | if (pure) { |
15066 | 730 | ++pure_decimal_count; |
15067 | 730 | } |
15068 | 961 | if (p >= end) { |
15069 | 686 | const unsigned shift = static_cast<unsigned>(32 - digit_count * 8); |
15070 | 686 | if (segment >= (uint64_t{1} << shift)) { |
15071 | 21 | return is_valid = false; |
15072 | 21 | } |
15073 | 665 | ipv4 = (ipv4 << shift) | segment; |
15074 | 665 | goto ipv4_done; |
15075 | 686 | } |
15076 | 275 | if (segment > 255 || *p != '.') { |
15077 | 32 | return is_valid = false; |
15078 | 32 | } |
15079 | 243 | ipv4 = (ipv4 << 8) | segment; |
15080 | 243 | ++p; |
15081 | 243 | } |
15082 | 6 | if (digit_count != 4 || p != end) { |
15083 | 6 | return is_valid = false; |
15084 | 6 | } |
15085 | 665 | ipv4_done: |
15086 | 665 | ada_log("url_aggregator::parse_ipv4 completed ", get_href(), |
15087 | 665 | " host: ", get_host()); |
15088 | 665 | 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 | 665 | } else { |
15093 | 665 | update_base_hostname(ada::serializers::ipv4(ipv4)); |
15094 | 665 | } |
15095 | 665 | host_type = IPV4; |
15096 | 665 | ADA_ASSERT_TRUE(validate()); |
15097 | 665 | return true; |
15098 | 6 | } |
15099 | | |
15100 | 7.23k | bool url_aggregator::parse_ipv6(std::string_view input) { |
15101 | 7.23k | ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]"); |
15102 | 7.23k | ADA_ASSERT_TRUE(validate()); |
15103 | 7.23k | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
15104 | 7.23k | if (input.empty() || input.size() > 45) [[unlikely]] { |
15105 | 6 | return is_valid = false; |
15106 | 6 | } |
15107 | 7.23k | 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 | 7.23k | const char* pointer = input.data(); |
15124 | 7.23k | const char* const end = pointer + input.size(); |
15125 | 7.23k | int piece_index = 0; |
15126 | 7.23k | int compress = -1; |
15127 | | |
15128 | 7.23k | if (*pointer == ':') { |
15129 | 19 | if (input.size() == 1 || pointer[1] != ':') [[unlikely]] { |
15130 | 7 | return is_valid = false; |
15131 | 7 | } |
15132 | 12 | pointer += 2; |
15133 | 12 | compress = ++piece_index; |
15134 | 12 | } |
15135 | | |
15136 | 7.41k | while (pointer != end) { |
15137 | 7.37k | if (piece_index == 8) [[unlikely]] { |
15138 | 2 | return is_valid = false; |
15139 | 2 | } |
15140 | 7.37k | if (*pointer == ':') { |
15141 | 13 | if (compress != -1) [[unlikely]] { |
15142 | 1 | return is_valid = false; |
15143 | 1 | } |
15144 | 12 | ++pointer; |
15145 | 12 | compress = ++piece_index; |
15146 | 12 | continue; |
15147 | 13 | } |
15148 | | |
15149 | 7.36k | uint16_t value = 0; |
15150 | 7.36k | const int length = detail::parse_hex_piece(pointer, end, value); |
15151 | | |
15152 | 7.36k | if (pointer != end && *pointer == '.') { |
15153 | 40 | if (length == 0) [[unlikely]] { |
15154 | 1 | return is_valid = false; |
15155 | 1 | } |
15156 | 39 | pointer -= length; |
15157 | 39 | if (piece_index > 6) [[unlikely]] { |
15158 | 1 | return is_valid = false; |
15159 | 1 | } |
15160 | | |
15161 | 38 | int numbers_seen = 0; |
15162 | 105 | while (pointer != end) { |
15163 | 98 | int ipv4_piece = -1; |
15164 | 98 | if (numbers_seen > 0) { |
15165 | 60 | if (*pointer == '.' && numbers_seen < 4) { |
15166 | 43 | ++pointer; |
15167 | 43 | } else { |
15168 | 17 | return is_valid = false; |
15169 | 17 | } |
15170 | 60 | } |
15171 | 81 | if (pointer == end || *pointer < '0' || *pointer > '9') [[unlikely]] { |
15172 | 12 | return is_valid = false; |
15173 | 12 | } |
15174 | 69 | ipv4_piece = *pointer - '0'; |
15175 | 69 | ++pointer; |
15176 | 69 | if (pointer != end && *pointer >= '0' && *pointer <= '9') { |
15177 | 26 | if (ipv4_piece == 0) [[unlikely]] { |
15178 | 1 | return is_valid = false; |
15179 | 1 | } |
15180 | 25 | ipv4_piece = ipv4_piece * 10 + (*pointer - '0'); |
15181 | 25 | ++pointer; |
15182 | 25 | if (pointer != end && *pointer >= '0' && *pointer <= '9') { |
15183 | 11 | ipv4_piece = ipv4_piece * 10 + (*pointer - '0'); |
15184 | 11 | ++pointer; |
15185 | 11 | if (ipv4_piece > 255) [[unlikely]] { |
15186 | 1 | return is_valid = false; |
15187 | 1 | } |
15188 | 11 | } |
15189 | 25 | } |
15190 | 67 | address[static_cast<size_t>(piece_index)] = static_cast<uint16_t>( |
15191 | 67 | address[static_cast<size_t>(piece_index)] * 0x100 + |
15192 | 67 | static_cast<uint16_t>(ipv4_piece)); |
15193 | 67 | ++numbers_seen; |
15194 | 67 | if (numbers_seen == 2 || numbers_seen == 4) { |
15195 | 25 | ++piece_index; |
15196 | 25 | } |
15197 | 67 | } |
15198 | 7 | if (numbers_seen != 4) [[unlikely]] { |
15199 | 5 | return is_valid = false; |
15200 | 5 | } |
15201 | 2 | break; |
15202 | 7 | } |
15203 | | |
15204 | 7.32k | if (length == 0) [[unlikely]] { |
15205 | 7.13k | return is_valid = false; |
15206 | 7.13k | } |
15207 | | |
15208 | 192 | if (pointer != end && *pointer == ':') { |
15209 | 154 | ++pointer; |
15210 | 154 | if (pointer == end) [[unlikely]] { |
15211 | 5 | return is_valid = false; |
15212 | 5 | } |
15213 | 154 | } else if (pointer != end) [[unlikely]] { |
15214 | 8 | return is_valid = false; |
15215 | 8 | } |
15216 | | |
15217 | 179 | address[static_cast<size_t>(piece_index)] = value; |
15218 | 179 | ++piece_index; |
15219 | 179 | } |
15220 | | |
15221 | 41 | if (compress != -1) { |
15222 | 20 | const int right = piece_index - compress; |
15223 | 20 | if (right > 0) { |
15224 | 11 | const size_t dest = static_cast<size_t>(8 - right); |
15225 | 11 | const size_t src = static_cast<size_t>(compress); |
15226 | 11 | if (dest != src) { |
15227 | 33 | for (size_t i = static_cast<size_t>(right); i-- > 0;) { |
15228 | 24 | address[dest + i] = address[src + i]; |
15229 | 24 | address[src + i] = 0; |
15230 | 24 | } |
15231 | 9 | } |
15232 | 11 | } |
15233 | 21 | } else if (piece_index != 8) [[unlikely]] { |
15234 | 19 | return is_valid = false; |
15235 | 19 | } |
15236 | | |
15237 | | // Serialize once; skip rewrite when hostname is already canonical. |
15238 | 22 | const std::string serialized = ada::serializers::ipv6(address); |
15239 | 22 | const std::string_view current = get_hostname(); |
15240 | 22 | if (current.size() == serialized.size() && |
15241 | 0 | std::memcmp(current.data(), serialized.data(), serialized.size()) == 0) { |
15242 | 0 | ada_log("parse_ipv6 in-place canonical match"); |
15243 | 22 | } else { |
15244 | 22 | update_base_hostname(serialized); |
15245 | 22 | } |
15246 | 22 | ada_log("parse_ipv6 ", get_hostname()); |
15247 | 22 | ADA_ASSERT_TRUE(validate()); |
15248 | 22 | host_type = IPV6; |
15249 | 22 | return true; |
15250 | 41 | } |
15251 | | |
15252 | 0 | bool url_aggregator::parse_opaque_host(std::string_view input) { |
15253 | 0 | ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]"); |
15254 | 0 | ADA_ASSERT_TRUE(validate()); |
15255 | 0 | ADA_ASSERT_TRUE(!helpers::overlaps(input, buffer)); |
15256 | 0 | if (std::ranges::any_of(input, ada::unicode::is_forbidden_host_code_point)) { |
15257 | 0 | return is_valid = false; |
15258 | 0 | } |
15259 | | |
15260 | | // Return the result of running UTF-8 percent-encode on input using the C0 |
15261 | | // control percent-encode set. |
15262 | 0 | size_t idx = ada::unicode::percent_encode_index( |
15263 | 0 | input, character_sets::C0_CONTROL_PERCENT_ENCODE); |
15264 | 0 | if (idx == input.size()) { |
15265 | 0 | update_base_hostname(input); |
15266 | 0 | } else { |
15267 | | // We only create a temporary string if we need to. |
15268 | 0 | update_base_hostname(ada::unicode::percent_encode( |
15269 | 0 | input, character_sets::C0_CONTROL_PERCENT_ENCODE, idx)); |
15270 | 0 | } |
15271 | 0 | ADA_ASSERT_TRUE(validate()); |
15272 | 0 | return true; |
15273 | 0 | } |
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 | 1.85k | inline void url_aggregator::consume_prepared_path(std::string_view input) { |
15449 | 1.85k | 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 | 1.85k | 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 | 1.85k | constexpr uint8_t need_encoding = 1; |
15465 | 1.85k | constexpr uint8_t backslash_char = 2; |
15466 | 1.85k | constexpr uint8_t dot_char = 4; |
15467 | 1.85k | constexpr uint8_t percent_char = 8; |
15468 | 1.85k | bool special = type != ada::scheme::NOT_SPECIAL; |
15469 | 1.85k | bool may_need_slow_file_handling = (type == ada::scheme::type::FILE && |
15470 | 0 | checkers::is_windows_drive_letter(input)); |
15471 | 1.85k | bool trivial_path = |
15472 | 1.85k | (special ? (accumulator == 0) |
15473 | 1.85k | : ((accumulator & (need_encoding | dot_char | percent_char)) == |
15474 | 0 | 0)) && |
15475 | 688 | (!may_need_slow_file_handling); |
15476 | 1.85k | 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 | 506 | if (input[0] != '.') { |
15485 | 207 | size_t slashdot = 0; |
15486 | 207 | bool dot_is_file = true; |
15487 | 875 | for (;;) { |
15488 | 875 | slashdot = input.find("/.", slashdot); |
15489 | 875 | if (slashdot == std::string_view::npos) { // common case |
15490 | 207 | break; |
15491 | 668 | } else { // uncommon |
15492 | | // only three cases matter: /./, /.. or a final / |
15493 | 668 | slashdot += 2; |
15494 | 668 | dot_is_file &= !(slashdot == input.size() || input[slashdot] == '.' || |
15495 | 323 | input[slashdot] == '/'); |
15496 | 668 | } |
15497 | 875 | } |
15498 | 207 | trivial_path = dot_is_file; |
15499 | 207 | } |
15500 | 506 | } |
15501 | 1.85k | if (trivial_path && is_at_path()) { |
15502 | 724 | ada_log("parse_path trivial"); |
15503 | 724 | buffer += '/'; |
15504 | 724 | buffer += input; |
15505 | 724 | return; |
15506 | 724 | } |
15507 | 1.13k | 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 | 1.13k | bool fast_path = |
15513 | 1.13k | (special && |
15514 | 1.13k | (accumulator & (need_encoding | backslash_char | percent_char)) == 0) && |
15515 | 470 | (type != ada::scheme::type::FILE); |
15516 | 1.13k | if (fast_path) { |
15517 | 470 | 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 | 470 | size_t previous_location = 0; // We start at 0. |
15523 | 2.72k | do { |
15524 | 2.72k | size_t new_location = input.find('/', previous_location); |
15525 | | // std::string_view path_view = input; |
15526 | | // We process the last segment separately: |
15527 | 2.72k | if (new_location == std::string_view::npos) { |
15528 | 470 | std::string_view path_view = input.substr(previous_location); |
15529 | 470 | if (path_view == "..") { // The path ends with .. |
15530 | | // e.g., if you receive ".." with an empty path, you go to "/". |
15531 | 18 | if (path.empty()) { |
15532 | 2 | path = '/'; |
15533 | 2 | update_base_pathname(path); |
15534 | 2 | return; |
15535 | 2 | } |
15536 | | // Fast case where we have nothing to do: |
15537 | 16 | if (path.back() == '/') { |
15538 | 4 | update_base_pathname(path); |
15539 | 4 | return; |
15540 | 4 | } |
15541 | | // If you have the path "/joe/myfriend", |
15542 | | // then you delete 'myfriend'. |
15543 | 12 | path.resize(path.rfind('/') + 1); |
15544 | 12 | update_base_pathname(path); |
15545 | 12 | return; |
15546 | 16 | } |
15547 | 452 | path += '/'; |
15548 | 452 | if (path_view != ".") { |
15549 | 443 | path.append(path_view); |
15550 | 443 | } |
15551 | 452 | update_base_pathname(path); |
15552 | 452 | return; |
15553 | 2.25k | } else { |
15554 | | // This is a non-final segment. |
15555 | 2.25k | std::string_view path_view = |
15556 | 2.25k | input.substr(previous_location, new_location - previous_location); |
15557 | 2.25k | previous_location = new_location + 1; |
15558 | 2.25k | if (path_view == "..") { |
15559 | 381 | size_t last_delimiter = path.rfind('/'); |
15560 | 381 | if (last_delimiter != std::string::npos) { |
15561 | 172 | path.erase(last_delimiter); |
15562 | 172 | } |
15563 | 1.87k | } else if (path_view != ".") { |
15564 | 1.56k | path += '/'; |
15565 | 1.56k | path.append(path_view); |
15566 | 1.56k | } |
15567 | 2.25k | } |
15568 | 2.72k | } while (true); |
15569 | 661 | } else { |
15570 | 661 | ada_log("parse_path slow"); |
15571 | | // we have reached the general case |
15572 | 661 | bool needs_percent_encoding = (accumulator & 1); |
15573 | 661 | std::string path_buffer_tmp; |
15574 | 4.17k | do { |
15575 | 4.17k | size_t location = (special && (accumulator & 2)) |
15576 | 4.17k | ? input.find_first_of("/\\") |
15577 | 4.17k | : input.find('/'); |
15578 | 4.17k | std::string_view path_view = input; |
15579 | 4.17k | if (location != std::string_view::npos) { |
15580 | 3.51k | path_view.remove_suffix(path_view.size() - location); |
15581 | 3.51k | input.remove_prefix(location + 1); |
15582 | 3.51k | } |
15583 | | // path_buffer is either path_view or it might point at a percent encoded |
15584 | | // temporary string. |
15585 | 4.17k | std::string_view path_buffer = |
15586 | 4.17k | (needs_percent_encoding && |
15587 | 3.63k | ada::unicode::percent_encode<false>( |
15588 | 3.63k | path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp)) |
15589 | 4.17k | ? path_buffer_tmp |
15590 | 4.17k | : path_view; |
15591 | 4.17k | if (unicode::is_double_dot_path_segment(path_buffer)) { |
15592 | 361 | helpers::shorten_path(path, type); |
15593 | 361 | if (location == std::string_view::npos) { |
15594 | 20 | path += '/'; |
15595 | 20 | } |
15596 | 3.81k | } else if (unicode::is_single_dot_path_segment(path_buffer) && |
15597 | 252 | (location == std::string_view::npos)) { |
15598 | 13 | path += '/'; |
15599 | 13 | } |
15600 | | // Otherwise, if path_buffer is not a single-dot path segment, then: |
15601 | 3.80k | 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 | 3.56k | 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 | 3.56k | } else { |
15613 | | // Append path_buffer to url's path. |
15614 | 3.56k | path += '/'; |
15615 | 3.56k | path.append(path_buffer); |
15616 | 3.56k | } |
15617 | 3.56k | } |
15618 | 4.17k | if (location == std::string_view::npos) { |
15619 | 661 | update_base_pathname(path); |
15620 | 661 | return; |
15621 | 661 | } |
15622 | 4.17k | } while (true); |
15623 | 661 | } |
15624 | 1.13k | } |
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 | 0 | std::optional<std::string_view> hash) { |
15651 | | // Let result be the result of creating a new URLPatternInit. |
15652 | 0 | auto result = url_pattern_init{}; |
15653 | | |
15654 | | // If protocol is not null, set result["protocol"] to protocol. |
15655 | 0 | if (protocol.has_value()) result.protocol = *protocol; |
15656 | | |
15657 | | // If username is not null, set result["username"] to username. |
15658 | 0 | if (username.has_value()) result.username = *username; |
15659 | | |
15660 | | // If password is not null, set result["password"] to password. |
15661 | 0 | if (password.has_value()) result.password = *password; |
15662 | | |
15663 | | // If hostname is not null, set result["hostname"] to hostname. |
15664 | 0 | if (hostname.has_value()) result.hostname = *hostname; |
15665 | | |
15666 | | // If port is not null, set result["port"] to port. |
15667 | 0 | if (port.has_value()) result.port = *port; |
15668 | | |
15669 | | // If pathname is not null, set result["pathname"] to pathname. |
15670 | 0 | if (pathname.has_value()) result.pathname = *pathname; |
15671 | | |
15672 | | // If search is not null, set result["search"] to search. |
15673 | 0 | if (search.has_value()) result.search = *search; |
15674 | | |
15675 | | // If hash is not null, set result["hash"] to hash. |
15676 | 0 | if (hash.has_value()) result.hash = *hash; |
15677 | | |
15678 | | // Let baseURL be null. |
15679 | 0 | std::optional<url_aggregator> base_url{}; |
15680 | | |
15681 | | // If init["baseURL"] exists: |
15682 | 0 | if (init.base_url.has_value()) { |
15683 | | // Set baseURL to the result of parsing init["baseURL"]. |
15684 | 0 | auto parsing_result = ada::parse<url_aggregator>(*init.base_url); |
15685 | | // If baseURL is failure, then throw a TypeError. |
15686 | 0 | if (!parsing_result) { |
15687 | 0 | return tl::unexpected(errors::type_error); |
15688 | 0 | } |
15689 | 0 | 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 | 0 | if (!init.protocol.has_value()) { |
15694 | 0 | ADA_ASSERT_TRUE(base_url.has_value()); |
15695 | 0 | std::string_view base_url_protocol = base_url->get_protocol(); |
15696 | 0 | if (base_url_protocol.ends_with(":")) base_url_protocol.remove_suffix(1); |
15697 | 0 | result.protocol = |
15698 | 0 | url_pattern_helpers::process_base_url_string(base_url_protocol, type); |
15699 | 0 | } |
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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | result.hostname = |
15729 | 0 | url_pattern_helpers::process_base_url_string(base_host, type); |
15730 | 0 | } |
15731 | | |
15732 | | // If init contains none of "protocol", "hostname", and "port", then: |
15733 | 0 | 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 | 0 | result.port = base_url->get_port(); |
15737 | 0 | } |
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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | } |
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 | 0 | if (init.protocol) { |
15779 | 0 | auto process_result = process_protocol(*init.protocol, type); |
15780 | 0 | if (!process_result) { |
15781 | 0 | return tl::unexpected(process_result.error()); |
15782 | 0 | } |
15783 | 0 | result.protocol = std::move(*process_result); |
15784 | 0 | } |
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 | 0 | if (init.username.has_value()) { |
15789 | 0 | auto process_result = process_username(*init.username, type); |
15790 | 0 | if (!process_result) { |
15791 | 0 | return tl::unexpected(process_result.error()); |
15792 | 0 | } |
15793 | 0 | result.username = std::move(*process_result); |
15794 | 0 | } |
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 | 0 | if (init.password.has_value()) { |
15799 | 0 | auto process_result = process_password(*init.password, type); |
15800 | 0 | if (!process_result) { |
15801 | 0 | return tl::unexpected(process_result.error()); |
15802 | 0 | } |
15803 | 0 | result.password = std::move(*process_result); |
15804 | 0 | } |
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 | 0 | if (init.hostname.has_value()) { |
15809 | 0 | auto process_result = process_hostname(*init.hostname, type); |
15810 | 0 | if (!process_result) { |
15811 | 0 | return tl::unexpected(process_result.error()); |
15812 | 0 | } |
15813 | 0 | result.hostname = std::move(*process_result); |
15814 | 0 | } |
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 | 0 | if (init.port) { |
15819 | 0 | auto process_result = |
15820 | 0 | process_port(*init.port, result.protocol.value_or("fake"), type); |
15821 | 0 | if (!process_result) { |
15822 | 0 | return tl::unexpected(process_result.error()); |
15823 | 0 | } |
15824 | 0 | result.port = std::move(*process_result); |
15825 | 0 | } |
15826 | | |
15827 | | // If init["pathname"] exists: |
15828 | 0 | if (init.pathname.has_value()) { |
15829 | | // Set result["pathname"] to init["pathname"]. |
15830 | 0 | 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 | 0 | if (base_url && !base_url->has_opaque_path && |
15838 | 0 | !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 | 0 | auto pathname_processing_result = |
15867 | 0 | process_pathname(*result.pathname, result.protocol.value_or(""), type); |
15868 | 0 | if (!pathname_processing_result) { |
15869 | 0 | return tl::unexpected(pathname_processing_result.error()); |
15870 | 0 | } |
15871 | 0 | result.pathname = std::move(*pathname_processing_result); |
15872 | 0 | } |
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 | 0 | if (init.search) { |
15877 | 0 | auto process_result = process_search(*init.search, type); |
15878 | 0 | if (!process_result) { |
15879 | 0 | return tl::unexpected(process_result.error()); |
15880 | 0 | } |
15881 | 0 | result.search = std::move(*process_result); |
15882 | 0 | } |
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 | 0 | if (init.hash) { |
15887 | 0 | auto process_result = process_hash(*init.hash, type); |
15888 | 0 | if (!process_result) { |
15889 | 0 | return tl::unexpected(process_result.error()); |
15890 | 0 | } |
15891 | 0 | result.hash = std::move(*process_result); |
15892 | 0 | } |
15893 | | // Return result. |
15894 | 0 | return result; |
15895 | 0 | } |
15896 | | |
15897 | | tl::expected<std::string, errors> url_pattern_init::process_protocol( |
15898 | 0 | std::string_view value, process_type type) { |
15899 | 0 | ada_log("process_protocol=", value, " [", type, "]"); |
15900 | | // Let strippedValue be the given value with a single trailing U+003A (:) |
15901 | | // removed, if any. |
15902 | 0 | if (value.ends_with(":")) { |
15903 | 0 | value.remove_suffix(1); |
15904 | 0 | } |
15905 | | // If type is "pattern" then return strippedValue. |
15906 | 0 | if (type == process_type::pattern) { |
15907 | 0 | return std::string(value); |
15908 | 0 | } |
15909 | | // Return the result of running canonicalize a protocol given strippedValue. |
15910 | 0 | return url_pattern_helpers::canonicalize_protocol(value); |
15911 | 0 | } |
15912 | | |
15913 | | tl::expected<std::string, errors> url_pattern_init::process_username( |
15914 | 0 | std::string_view value, process_type type) { |
15915 | | // If type is "pattern" then return value. |
15916 | 0 | if (type == process_type::pattern) { |
15917 | 0 | return std::string(value); |
15918 | 0 | } |
15919 | | // Return the result of running canonicalize a username given value. |
15920 | 0 | return url_pattern_helpers::canonicalize_username(value); |
15921 | 0 | } |
15922 | | |
15923 | | tl::expected<std::string, errors> url_pattern_init::process_password( |
15924 | 0 | std::string_view value, process_type type) { |
15925 | | // If type is "pattern" then return value. |
15926 | 0 | if (type == process_type::pattern) { |
15927 | 0 | return std::string(value); |
15928 | 0 | } |
15929 | | // Return the result of running canonicalize a password given value. |
15930 | 0 | return url_pattern_helpers::canonicalize_password(value); |
15931 | 0 | } |
15932 | | |
15933 | | tl::expected<std::string, errors> url_pattern_init::process_hostname( |
15934 | 0 | std::string_view value, process_type type) { |
15935 | 0 | ada_log("process_hostname value=", value, " type=", type); |
15936 | | // If type is "pattern" then return value. |
15937 | 0 | if (type == process_type::pattern) { |
15938 | 0 | return std::string(value); |
15939 | 0 | } |
15940 | | // Return the result of running canonicalize a hostname given value. |
15941 | 0 | return url_pattern_helpers::canonicalize_hostname(value); |
15942 | 0 | } |
15943 | | |
15944 | | tl::expected<std::string, errors> url_pattern_init::process_port( |
15945 | 0 | std::string_view port, std::string_view protocol, process_type type) { |
15946 | | // If type is "pattern" then return portValue. |
15947 | 0 | if (type == process_type::pattern) { |
15948 | 0 | return std::string(port); |
15949 | 0 | } |
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 | 0 | } |
15954 | | |
15955 | | tl::expected<std::string, errors> url_pattern_init::process_pathname( |
15956 | 0 | std::string_view value, std::string_view protocol, process_type type) { |
15957 | | // If type is "pattern" then return pathnameValue. |
15958 | 0 | if (type == process_type::pattern) { |
15959 | 0 | return std::string(value); |
15960 | 0 | } |
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 | 0 | if (protocol.empty() || scheme::is_special(protocol)) { |
15965 | 0 | return url_pattern_helpers::canonicalize_pathname(value); |
15966 | 0 | } |
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 | 0 | } |
15972 | | |
15973 | | tl::expected<std::string, errors> url_pattern_init::process_search( |
15974 | 0 | 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 | 0 | if (value.starts_with("?")) { |
15978 | 0 | value.remove_prefix(1); |
15979 | 0 | } |
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 | 0 | if (type == process_type::pattern) { |
15987 | 0 | return std::string(value); |
15988 | 0 | } |
15989 | | // Return the result of running canonicalize a search given strippedValue. |
15990 | 0 | return url_pattern_helpers::canonicalize_search(value); |
15991 | 0 | } |
15992 | | |
15993 | | tl::expected<std::string, errors> url_pattern_init::process_hash( |
15994 | 0 | 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 | 0 | if (value.starts_with("#")) { |
15998 | 0 | value.remove_prefix(1); |
15999 | 0 | } |
16000 | 0 | ADA_ASSERT_TRUE(!value.starts_with("#")); |
16001 | | // If type is "pattern" then return strippedValue. |
16002 | 0 | if (type == process_type::pattern) { |
16003 | 0 | return std::string(value); |
16004 | 0 | } |
16005 | | // Return the result of running canonicalize a hash given strippedValue. |
16006 | 0 | return url_pattern_helpers::canonicalize_hash(value); |
16007 | 0 | } |
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 | 0 | url_pattern_compile_component_options options) { |
16037 | | // Let result be "^" |
16038 | 0 | std::string result = "^"; |
16039 | | // Reserve capacity to reduce reallocations |
16040 | 0 | result.reserve(part_list.size() * 16); |
16041 | | |
16042 | | // Let name list be a new list |
16043 | 0 | std::vector<std::string> name_list{}; |
16044 | 0 | name_list.reserve(part_list.size()); |
16045 | | |
16046 | | // Pre-generate segment wildcard regexp if needed (avoids repeated generation) |
16047 | 0 | std::string segment_wildcard_regexp; |
16048 | | |
16049 | | // For each part of part list: |
16050 | 0 | for (const url_pattern_part& part : part_list) { |
16051 | | // If part's type is "fixed-text": |
16052 | 0 | if (part.type == url_pattern_part_type::FIXED_TEXT) { |
16053 | | // If part's modifier is "none" |
16054 | 0 | if (part.modifier == url_pattern_part_modifier::none) { |
16055 | 0 | result.append(escape_regexp_string(part.value)); |
16056 | 0 | } else { |
16057 | | // (?:<fixed text>)<modifier> |
16058 | 0 | result.append("(?:"); |
16059 | 0 | result.append(escape_regexp_string(part.value)); |
16060 | 0 | result.push_back(')'); |
16061 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
16062 | 0 | } |
16063 | 0 | continue; |
16064 | 0 | } |
16065 | | |
16066 | | // Assert: part's name is not the empty string |
16067 | 0 | ADA_ASSERT_TRUE(!part.name.empty()); |
16068 | 0 | name_list.push_back(part.name); |
16069 | | |
16070 | | // Use string_view to avoid copies where possible |
16071 | 0 | std::string_view regexp_value = part.value; |
16072 | |
|
16073 | 0 | if (part.type == url_pattern_part_type::SEGMENT_WILDCARD) { |
16074 | | // Lazy generate segment wildcard regexp |
16075 | 0 | if (segment_wildcard_regexp.empty()) { |
16076 | 0 | segment_wildcard_regexp = generate_segment_wildcard_regexp(options); |
16077 | 0 | } |
16078 | 0 | regexp_value = segment_wildcard_regexp; |
16079 | 0 | } else if (part.type == url_pattern_part_type::FULL_WILDCARD) { |
16080 | 0 | regexp_value = ".*"; |
16081 | 0 | } |
16082 | | |
16083 | | // If part's prefix is the empty string and part's suffix is the empty |
16084 | | // string |
16085 | 0 | if (part.prefix.empty() && part.suffix.empty()) { |
16086 | | // If part's modifier is "none" or "optional" |
16087 | 0 | if (part.modifier == url_pattern_part_modifier::none || |
16088 | 0 | part.modifier == url_pattern_part_modifier::optional) { |
16089 | | // (<regexp value>)<modifier> |
16090 | 0 | result.push_back('('); |
16091 | 0 | result.append(regexp_value); |
16092 | 0 | result.push_back(')'); |
16093 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
16094 | 0 | } else { |
16095 | | // ((?:<regexp value>)<modifier>) |
16096 | 0 | result.append("((?:"); |
16097 | 0 | result.append(regexp_value); |
16098 | 0 | result.push_back(')'); |
16099 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
16100 | 0 | result.push_back(')'); |
16101 | 0 | } |
16102 | 0 | continue; |
16103 | 0 | } |
16104 | | |
16105 | | // If part's modifier is "none" or "optional" |
16106 | 0 | if (part.modifier == url_pattern_part_modifier::none || |
16107 | 0 | part.modifier == url_pattern_part_modifier::optional) { |
16108 | | // (?:<prefix>(<regexp value>)<suffix>)<modifier> |
16109 | 0 | result.append("(?:"); |
16110 | 0 | result.append(escape_regexp_string(part.prefix)); |
16111 | 0 | result.push_back('('); |
16112 | 0 | result.append(regexp_value); |
16113 | 0 | result.push_back(')'); |
16114 | 0 | result.append(escape_regexp_string(part.suffix)); |
16115 | 0 | result.push_back(')'); |
16116 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
16117 | 0 | continue; |
16118 | 0 | } |
16119 | | |
16120 | | // Assert: part's modifier is "zero-or-more" or "one-or-more" |
16121 | 0 | ADA_ASSERT_TRUE(part.modifier == url_pattern_part_modifier::zero_or_more || |
16122 | 0 | 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 | 0 | 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 | 0 | result.append("(?:"); |
16132 | | // Append the result of running escape a regexp string given part's prefix |
16133 | | // to the end of result. |
16134 | 0 | result.append(escape_regexp_string(part.prefix)); |
16135 | | // Append "((?:" to the end of result. |
16136 | 0 | result.append("((?:"); |
16137 | | // Append regexp value to the end of result. |
16138 | 0 | result.append(regexp_value); |
16139 | | // Append ")(?:" to the end of result. |
16140 | 0 | result.append(")(?:"); |
16141 | | // Append the result of running escape a regexp string given part's suffix |
16142 | | // to the end of result. |
16143 | 0 | 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 | 0 | result.append(escape_regexp_string(part.prefix)); |
16147 | | // Append "(?:" to the end of result. |
16148 | 0 | result.append("(?:"); |
16149 | | // Append regexp value to the end of result. |
16150 | 0 | result.append(regexp_value); |
16151 | | // Append "))*)" to the end of result. |
16152 | 0 | result.append("))*)"); |
16153 | | // Append the result of running escape a regexp string given part's suffix |
16154 | | // to the end of result. |
16155 | 0 | result.append(escape_regexp_string(part.suffix)); |
16156 | | // Append ")" to the end of result. |
16157 | 0 | result.append(")"); |
16158 | | |
16159 | | // If part's modifier is "zero-or-more" then append "?" to the end of result |
16160 | 0 | if (part.modifier == url_pattern_part_modifier::zero_or_more) { |
16161 | 0 | result += "?"; |
16162 | 0 | } |
16163 | 0 | } |
16164 | | |
16165 | | // Append "$" to the end of result |
16166 | 0 | result += "$"; |
16167 | | |
16168 | | // Return (result, name list) |
16169 | 0 | return {std::move(result), std::move(name_list)}; |
16170 | 0 | } |
16171 | | |
16172 | 0 | bool is_ipv6_address(std::string_view input) noexcept { |
16173 | | // If input's code point length is less than 2, then return false. |
16174 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | return input.starts_with("\\["); |
16185 | 0 | } |
16186 | | |
16187 | | std::string_view convert_modifier_to_string( |
16188 | 0 | url_pattern_part_modifier modifier) { |
16189 | 0 | switch (modifier) { |
16190 | | // If modifier is "zero-or-more", then return "*". |
16191 | 0 | case url_pattern_part_modifier::zero_or_more: |
16192 | 0 | return "*"; |
16193 | | // If modifier is "optional", then return "?". |
16194 | 0 | case url_pattern_part_modifier::optional: |
16195 | 0 | return "?"; |
16196 | | // If modifier is "one-or-more", then return "+". |
16197 | 0 | case url_pattern_part_modifier::one_or_more: |
16198 | 0 | return "+"; |
16199 | | // Return the empty string. |
16200 | 0 | default: |
16201 | 0 | return ""; |
16202 | 0 | } |
16203 | 0 | } |
16204 | | |
16205 | | std::string generate_segment_wildcard_regexp( |
16206 | 0 | url_pattern_compile_component_options options) { |
16207 | | // Let result be "[^". |
16208 | 0 | 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 | 0 | result.append(escape_regexp_string(options.get_delimiter())); |
16212 | | // Append "]+?" to the end of result. |
16213 | 0 | result.append("]+?"); |
16214 | | // Return result. |
16215 | 0 | ada_log("generate_segment_wildcard_regexp result: ", result); |
16216 | 0 | return result; |
16217 | 0 | } |
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 | 0 | std::string_view input) { |
16249 | 0 | ada_log("canonicalize_protocol called with input=", input); |
16250 | 0 | if (input.empty()) [[unlikely]] { |
16251 | 0 | return ""; |
16252 | 0 | } |
16253 | | |
16254 | 0 | if (input.ends_with(":")) { |
16255 | 0 | input.remove_suffix(1); |
16256 | 0 | } |
16257 | | |
16258 | | // Fast path: special schemes are already canonical |
16259 | 0 | if (scheme::is_special(input)) { |
16260 | 0 | return std::string(input); |
16261 | 0 | } |
16262 | | |
16263 | | // Fast path: validate scheme chars and check for uppercase |
16264 | | // First char must be alpha (not +, -, ., or digit) |
16265 | 0 | uint8_t first_flags = char_class_table[static_cast<uint8_t>(input[0])]; |
16266 | 0 | if (!(first_flags & CHAR_SCHEME) || input[0] == '+' || input[0] == '-' || |
16267 | 0 | input[0] == '.' || unicode::is_ascii_digit(input[0])) { |
16268 | 0 | return tl::unexpected(errors::type_error); |
16269 | 0 | } |
16270 | | |
16271 | 0 | uint8_t needs_lowercase = first_flags & CHAR_UPPER; |
16272 | 0 | for (size_t i = 1; i < input.size(); i++) { |
16273 | 0 | uint8_t flags = char_class_table[static_cast<uint8_t>(input[i])]; |
16274 | 0 | if (!(flags & CHAR_SCHEME)) { |
16275 | 0 | return tl::unexpected(errors::type_error); |
16276 | 0 | } |
16277 | 0 | needs_lowercase |= flags & CHAR_UPPER; |
16278 | 0 | } |
16279 | | |
16280 | 0 | if (needs_lowercase == 0) { |
16281 | 0 | return std::string(input); |
16282 | 0 | } |
16283 | | |
16284 | 0 | std::string result(input); |
16285 | 0 | unicode::to_lower_ascii(result.data(), result.size()); |
16286 | 0 | return result; |
16287 | 0 | } |
16288 | | |
16289 | | tl::expected<std::string, errors> canonicalize_username( |
16290 | 0 | std::string_view input) { |
16291 | | // If value is the empty string, return value. |
16292 | 0 | if (input.empty()) [[unlikely]] { |
16293 | 0 | return ""; |
16294 | 0 | } |
16295 | | // Percent-encode the input using the userinfo percent-encode set. |
16296 | 0 | size_t idx = ada::unicode::percent_encode_index( |
16297 | 0 | input, character_sets::USERINFO_PERCENT_ENCODE); |
16298 | 0 | if (idx == input.size()) { |
16299 | | // No encoding needed, return input as-is |
16300 | 0 | return std::string(input); |
16301 | 0 | } |
16302 | | // Percent-encode from the first character that needs encoding |
16303 | 0 | return ada::unicode::percent_encode( |
16304 | 0 | input, character_sets::USERINFO_PERCENT_ENCODE, idx); |
16305 | 0 | } |
16306 | | |
16307 | | tl::expected<std::string, errors> canonicalize_password( |
16308 | 0 | std::string_view input) { |
16309 | | // If value is the empty string, return value. |
16310 | 0 | if (input.empty()) [[unlikely]] { |
16311 | 0 | return ""; |
16312 | 0 | } |
16313 | | // Percent-encode the input using the userinfo percent-encode set. |
16314 | 0 | size_t idx = ada::unicode::percent_encode_index( |
16315 | 0 | input, character_sets::USERINFO_PERCENT_ENCODE); |
16316 | 0 | if (idx == input.size()) { |
16317 | | // No encoding needed, return input as-is |
16318 | 0 | return std::string(input); |
16319 | 0 | } |
16320 | | // Percent-encode from the first character that needs encoding |
16321 | 0 | return ada::unicode::percent_encode( |
16322 | 0 | input, character_sets::USERINFO_PERCENT_ENCODE, idx); |
16323 | 0 | } |
16324 | | |
16325 | | tl::expected<std::string, errors> canonicalize_hostname( |
16326 | 0 | std::string_view input) { |
16327 | 0 | ada_log("canonicalize_hostname input=", input); |
16328 | 0 | if (input.empty()) [[unlikely]] { |
16329 | 0 | return ""; |
16330 | 0 | } |
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 | 0 | bool needs_processing = false; |
16342 | 0 | for (char c : input) { |
16343 | 0 | needs_processing |= |
16344 | 0 | !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_HOSTNAME); |
16345 | 0 | } |
16346 | 0 | if (!needs_processing && !checkers::is_ipv4(input)) { |
16347 | 0 | return std::string(input); |
16348 | 0 | } |
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 | 0 | auto url = ada::parse<url_aggregator>("https://dummy.test", nullptr); |
16357 | 0 | ADA_ASSERT_TRUE(url); |
16358 | | // if (!isValidHostnameInput(hostname)) return kj::none; |
16359 | 0 | if (!url->set_hostname(input)) { |
16360 | | // If parseResult is failure, then throw a TypeError. |
16361 | 0 | return tl::unexpected(errors::type_error); |
16362 | 0 | } |
16363 | | // Return dummyURL's host, serialized, or empty string if it is null. |
16364 | 0 | return std::string(url->get_hostname()); |
16365 | 0 | } |
16366 | | |
16367 | | tl::expected<std::string, errors> canonicalize_ipv6_hostname( |
16368 | 0 | std::string_view input) { |
16369 | 0 | ada_log("canonicalize_ipv6_hostname input=", input); |
16370 | | // TODO: Optimization opportunity: Use lookup table to speed up checking |
16371 | 0 | if (std::ranges::any_of(input, [](char c) { |
16372 | 0 | return c != '[' && c != ']' && c != ':' && |
16373 | 0 | !unicode::is_ascii_hex_digit(c); |
16374 | 0 | })) { |
16375 | 0 | return tl::unexpected(errors::type_error); |
16376 | 0 | } |
16377 | | // Append the result of running ASCII lowercase given code point to the end of |
16378 | | // result. |
16379 | 0 | auto hostname = std::string(input); |
16380 | 0 | unicode::to_lower_ascii(hostname.data(), hostname.size()); |
16381 | 0 | return hostname; |
16382 | 0 | } |
16383 | | |
16384 | | tl::expected<std::string, errors> canonicalize_port( |
16385 | 0 | std::string_view port_value) { |
16386 | | // If portValue is the empty string, return portValue. |
16387 | 0 | if (port_value.empty()) [[unlikely]] { |
16388 | 0 | return ""; |
16389 | 0 | } |
16390 | | |
16391 | | // Remove ASCII tab or newline characters |
16392 | 0 | std::string trimmed(port_value); |
16393 | 0 | helpers::remove_ascii_tab_or_newline(trimmed); |
16394 | |
|
16395 | 0 | if (trimmed.empty()) { |
16396 | 0 | return ""; |
16397 | 0 | } |
16398 | | |
16399 | | // Input should start with a digit character |
16400 | 0 | if (!unicode::is_ascii_digit(trimmed.front())) { |
16401 | 0 | return tl::unexpected(errors::type_error); |
16402 | 0 | } |
16403 | | |
16404 | | // Find the first non-digit character |
16405 | 0 | auto first_non_digit = |
16406 | 0 | std::ranges::find_if_not(trimmed, unicode::is_ascii_digit); |
16407 | 0 | std::string_view digits_to_parse = |
16408 | 0 | 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 | 0 | size_t first_significant = digits_to_parse.find_first_not_of('0'); |
16417 | 0 | if (first_significant == std::string_view::npos) { |
16418 | | // The value is all zeros, i.e. port 0. |
16419 | 0 | return "0"; |
16420 | 0 | } |
16421 | 0 | 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 | 0 | if (digits_to_parse.size() == 5) { |
16427 | 0 | if (digits_to_parse > "65535") { |
16428 | 0 | return tl::unexpected(errors::type_error); |
16429 | 0 | } |
16430 | 0 | } 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 | 0 | return std::string(digits_to_parse); |
16435 | 0 | } |
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 | 0 | std::string_view input) { |
16499 | 0 | if (input.empty()) [[unlikely]] { |
16500 | 0 | return ""; |
16501 | 0 | } |
16502 | | |
16503 | | // Fast path: simple pathnames (no . which needs normalization) can be |
16504 | | // returned as-is |
16505 | 0 | bool needs_processing = false; |
16506 | 0 | for (char c : input) { |
16507 | 0 | needs_processing |= |
16508 | 0 | !(char_class_table[static_cast<uint8_t>(c)] & CHAR_SIMPLE_PATHNAME); |
16509 | 0 | } |
16510 | 0 | if (!needs_processing) { |
16511 | 0 | return std::string(input); |
16512 | 0 | } |
16513 | | |
16514 | | // Let leading slash be true if the first code point in value is U+002F (/) |
16515 | | // and otherwise false. |
16516 | 0 | const bool leading_slash = input.starts_with("/"); |
16517 | | // Let modified value be "/-" if leading slash is false and otherwise the |
16518 | | // empty string. |
16519 | 0 | const auto modified_value = |
16520 | 0 | (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 | 0 | auto url = ada::parse<url_aggregator>("https://dummy.invalid/", nullptr); |
16533 | 0 | ADA_ASSERT_TRUE(url); |
16534 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | if (pathname.size() < 2) { |
16545 | 0 | return tl::unexpected(errors::type_error); |
16546 | 0 | } |
16547 | 0 | return std::string(pathname.substr(2)); |
16548 | 0 | } |
16549 | 0 | return std::string(pathname); |
16550 | 0 | } |
16551 | | |
16552 | | tl::expected<std::string, errors> canonicalize_opaque_pathname( |
16553 | 0 | std::string_view input) { |
16554 | | // If value is the empty string, return value. |
16555 | 0 | if (input.empty()) [[unlikely]] { |
16556 | 0 | return ""; |
16557 | 0 | } |
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 | 0 | if (auto url = |
16563 | 0 | ada::parse<url_aggregator>("fake:" + std::string(input), nullptr)) { |
16564 | | // Return the result of URL path serializing dummyURL. |
16565 | 0 | return std::string(url->get_pathname()); |
16566 | 0 | } |
16567 | | // If parseResult is failure, then throw a TypeError. |
16568 | 0 | return tl::unexpected(errors::type_error); |
16569 | 0 | } |
16570 | | |
16571 | 0 | tl::expected<std::string, errors> canonicalize_search(std::string_view input) { |
16572 | | // If value is the empty string, return value. |
16573 | 0 | if (input.empty()) [[unlikely]] { |
16574 | 0 | return ""; |
16575 | 0 | } |
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 | 0 | std::string new_value(input); |
16580 | | // Remove ASCII tab or newline characters |
16581 | 0 | helpers::remove_ascii_tab_or_newline(new_value); |
16582 | |
|
16583 | 0 | if (new_value.empty()) { |
16584 | 0 | return ""; |
16585 | 0 | } |
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 | 0 | size_t idx = ada::unicode::percent_encode_index( |
16591 | 0 | new_value, character_sets::QUERY_PERCENT_ENCODE); |
16592 | 0 | if (idx == new_value.size()) { |
16593 | | // No encoding needed |
16594 | 0 | return new_value; |
16595 | 0 | } |
16596 | | // Percent-encode from the first character that needs encoding |
16597 | 0 | return ada::unicode::percent_encode( |
16598 | 0 | new_value, character_sets::QUERY_PERCENT_ENCODE, idx); |
16599 | 0 | } |
16600 | | |
16601 | 0 | tl::expected<std::string, errors> canonicalize_hash(std::string_view input) { |
16602 | | // If value is the empty string, return value. |
16603 | 0 | if (input.empty()) [[unlikely]] { |
16604 | 0 | return ""; |
16605 | 0 | } |
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 | 0 | std::string new_value(input); |
16610 | | // Remove ASCII tab or newline characters |
16611 | 0 | helpers::remove_ascii_tab_or_newline(new_value); |
16612 | |
|
16613 | 0 | if (new_value.empty()) { |
16614 | 0 | return ""; |
16615 | 0 | } |
16616 | | |
16617 | | // Percent-encode using FRAGMENT_PERCENT_ENCODE |
16618 | 0 | size_t idx = ada::unicode::percent_encode_index( |
16619 | 0 | new_value, character_sets::FRAGMENT_PERCENT_ENCODE); |
16620 | 0 | if (idx == new_value.size()) { |
16621 | | // No encoding needed |
16622 | 0 | return new_value; |
16623 | 0 | } |
16624 | | // Percent-encode from the first character that needs encoding |
16625 | 0 | return ada::unicode::percent_encode( |
16626 | 0 | new_value, character_sets::FRAGMENT_PERCENT_ENCODE, idx); |
16627 | 0 | } |
16628 | | |
16629 | | tl::expected<std::vector<token>, errors> tokenize(std::string_view input, |
16630 | 0 | token_policy policy) { |
16631 | 0 | 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 | 0 | auto tokenizer = Tokenizer(input, policy); |
16636 | | // While tokenizer's index is less than tokenizer's input's code point length: |
16637 | 0 | while (tokenizer.index < tokenizer.input.size()) { |
16638 | | // Run seek and get the next code point given tokenizer and tokenizer's |
16639 | | // index. |
16640 | 0 | 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 | 0 | 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 | 0 | if (tokenizer.code_point == '*') { |
16654 | | // Run add a token with default position and length given tokenizer and |
16655 | | // "asterisk". |
16656 | 0 | tokenizer.add_token_with_defaults(token_type::ASTERISK); |
16657 | 0 | ada_log("add ASTERISK token"); |
16658 | | // Continue. |
16659 | 0 | continue; |
16660 | 0 | } |
16661 | | |
16662 | | // If tokenizer's code point is U+002B (+) or U+003F (?): |
16663 | 0 | if (tokenizer.code_point == '+' || tokenizer.code_point == '?') { |
16664 | | // Run add a token with default position and length given tokenizer and |
16665 | | // "other-modifier". |
16666 | 0 | tokenizer.add_token_with_defaults(token_type::OTHER_MODIFIER); |
16667 | | // Continue. |
16668 | 0 | continue; |
16669 | 0 | } |
16670 | | |
16671 | | // If tokenizer's code point is U+005C (\): |
16672 | 0 | if (tokenizer.code_point == '\\') { |
16673 | | // If tokenizer's index is equal to tokenizer's input's code point length |
16674 | | // - 1: |
16675 | 0 | 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 | 0 | if (auto error = tokenizer.process_tokenizing_error( |
16679 | 0 | tokenizer.next_index, tokenizer.index)) { |
16680 | 0 | ada_log("process_tokenizing_error failed"); |
16681 | 0 | return tl::unexpected(*error); |
16682 | 0 | } |
16683 | 0 | continue; |
16684 | 0 | } |
16685 | | |
16686 | | // Let escaped index be tokenizer's next index. |
16687 | 0 | auto escaped_index = tokenizer.next_index; |
16688 | | // Run get the next code point given tokenizer. |
16689 | 0 | tokenizer.get_next_code_point(); |
16690 | 0 | 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 | 0 | tokenizer.add_token_with_default_length( |
16700 | 0 | token_type::ESCAPED_CHAR, tokenizer.next_index, escaped_index); |
16701 | 0 | ada_log("add ESCAPED_CHAR token on next_index ", tokenizer.next_index, |
16702 | 0 | " with escaped index ", escaped_index); |
16703 | | // Continue. |
16704 | 0 | continue; |
16705 | 0 | } |
16706 | | |
16707 | | // If tokenizer's code point is U+007B ({): |
16708 | 0 | if (tokenizer.code_point == '{') { |
16709 | | // Run add a token with default position and length given tokenizer and |
16710 | | // "open". |
16711 | 0 | tokenizer.add_token_with_defaults(token_type::OPEN); |
16712 | 0 | ada_log("add OPEN token"); |
16713 | 0 | continue; |
16714 | 0 | } |
16715 | | |
16716 | | // If tokenizer's code point is U+007D (}): |
16717 | 0 | if (tokenizer.code_point == '}') { |
16718 | | // Run add a token with default position and length given tokenizer and |
16719 | | // "close". |
16720 | 0 | tokenizer.add_token_with_defaults(token_type::CLOSE); |
16721 | 0 | ada_log("add CLOSE token"); |
16722 | 0 | continue; |
16723 | 0 | } |
16724 | | |
16725 | | // If tokenizer's code point is U+003A (:): |
16726 | 0 | if (tokenizer.code_point == ':') { |
16727 | | // Let name position be tokenizer's next index. |
16728 | 0 | auto name_position = tokenizer.next_index; |
16729 | | // Let name start be name position. |
16730 | 0 | auto name_start = name_position; |
16731 | 0 | bool invalid_name = false; |
16732 | | // While name position is less than tokenizer's input's code point length: |
16733 | 0 | while (name_position < tokenizer.input.size()) { |
16734 | | // Run seek and get the next code point given tokenizer and name |
16735 | | // position. |
16736 | 0 | tokenizer.seek_and_get_next_code_point(name_position); |
16737 | 0 | 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 | 0 | 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 | 0 | auto valid_code_point = |
16751 | 0 | idna::valid_name_code_point(tokenizer.code_point, first_code_point); |
16752 | 0 | ada_log("tokenizer.code_point=", uint32_t(tokenizer.code_point), |
16753 | 0 | " first_code_point=", first_code_point, |
16754 | 0 | " valid_code_point=", valid_code_point); |
16755 | | // If valid code point is false break. |
16756 | 0 | if (!valid_code_point) break; |
16757 | | // Set name position to tokenizer's next index. |
16758 | 0 | name_position = tokenizer.next_index; |
16759 | 0 | } |
16760 | | |
16761 | 0 | if (invalid_name) { |
16762 | 0 | continue; |
16763 | 0 | } |
16764 | | |
16765 | | // If name position is less than or equal to name start: |
16766 | 0 | if (name_position <= name_start) { |
16767 | | // Run process a tokenizing error given tokenizer, name start, and |
16768 | | // tokenizer's index. |
16769 | 0 | if (auto error = tokenizer.process_tokenizing_error(name_start, |
16770 | 0 | tokenizer.index)) { |
16771 | 0 | ada_log("process_tokenizing_error failed"); |
16772 | 0 | return tl::unexpected(*error); |
16773 | 0 | } |
16774 | | // Continue |
16775 | 0 | continue; |
16776 | 0 | } |
16777 | | |
16778 | | // Run add a token with default length given tokenizer, "name", name |
16779 | | // position, and name start. |
16780 | 0 | tokenizer.add_token_with_default_length(token_type::NAME, name_position, |
16781 | 0 | name_start); |
16782 | 0 | continue; |
16783 | 0 | } |
16784 | | |
16785 | | // If tokenizer's code point is U+0028 ((): |
16786 | 0 | if (tokenizer.code_point == '(') { |
16787 | | // Let depth be 1. |
16788 | 0 | size_t depth = 1; |
16789 | | // Let regexp position be tokenizer's next index. |
16790 | 0 | auto regexp_position = tokenizer.next_index; |
16791 | | // Let regexp start be regexp position. |
16792 | 0 | auto regexp_start = regexp_position; |
16793 | | // Let error be false. |
16794 | 0 | bool error = false; |
16795 | | |
16796 | | // While regexp position is less than tokenizer's input's code point |
16797 | | // length: |
16798 | 0 | while (regexp_position < tokenizer.input.size()) { |
16799 | | // Run seek and get the next code point given tokenizer and regexp |
16800 | | // position. |
16801 | 0 | tokenizer.seek_and_get_next_code_point(regexp_position); |
16802 | 0 | 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 | 0 | 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 | 0 | if (regexp_position == regexp_start && tokenizer.code_point == '?') { |
16829 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16830 | | // tokenizer's index. |
16831 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16832 | 0 | regexp_start, tokenizer.index)) { |
16833 | 0 | return tl::unexpected(*process_error); |
16834 | 0 | } |
16835 | | // Set error to true; |
16836 | 0 | error = true; |
16837 | 0 | break; |
16838 | 0 | } |
16839 | | |
16840 | | // If tokenizer's code point is U+005C (\): |
16841 | 0 | if (tokenizer.code_point == '\\') { |
16842 | | // If regexp position equals tokenizer's input's code point length - 1 |
16843 | 0 | if (regexp_position == tokenizer.input.size() - 1) { |
16844 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16845 | | // tokenizer's index. |
16846 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16847 | 0 | regexp_start, tokenizer.index)) { |
16848 | 0 | return tl::unexpected(*process_error); |
16849 | 0 | } |
16850 | | // Set error to true. |
16851 | 0 | error = true; |
16852 | 0 | break; |
16853 | 0 | } |
16854 | | // Run get the next code point given tokenizer. |
16855 | 0 | auto escaped_index = tokenizer.next_index; |
16856 | 0 | tokenizer.get_next_code_point(); |
16857 | 0 | 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 | 0 | 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 | 0 | regexp_position = tokenizer.next_index; |
16881 | 0 | continue; |
16882 | 0 | } |
16883 | | |
16884 | | // If tokenizer's code point is U+0029 ()): |
16885 | 0 | if (tokenizer.code_point == ')') { |
16886 | | // Decrement depth by 1. |
16887 | 0 | depth--; |
16888 | | // If depth is 0: |
16889 | 0 | if (depth == 0) { |
16890 | | // Set regexp position to tokenizer's next index. |
16891 | 0 | regexp_position = tokenizer.next_index; |
16892 | | // Break. |
16893 | 0 | break; |
16894 | 0 | } |
16895 | 0 | } else if (tokenizer.code_point == '(') { |
16896 | | // Otherwise if tokenizer's code point is U+0028 ((): |
16897 | | // Increment depth by 1. |
16898 | 0 | depth++; |
16899 | | // If regexp position equals tokenizer's input's code point length - |
16900 | | // 1: |
16901 | 0 | if (regexp_position == tokenizer.input.size() - 1) { |
16902 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16903 | | // tokenizer's index. |
16904 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16905 | 0 | regexp_start, tokenizer.index)) { |
16906 | 0 | return tl::unexpected(*process_error); |
16907 | 0 | } |
16908 | | // Set error to true. |
16909 | 0 | error = true; |
16910 | 0 | break; |
16911 | 0 | } |
16912 | | // Let temporary position be tokenizer's next index. |
16913 | 0 | auto temporary_position = tokenizer.next_index; |
16914 | | // Run get the next code point given tokenizer. |
16915 | 0 | tokenizer.get_next_code_point(); |
16916 | 0 | 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 | 0 | if (tokenizer.code_point != '?') { |
16926 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16927 | | // tokenizer's index. |
16928 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16929 | 0 | regexp_start, tokenizer.index)) { |
16930 | 0 | return tl::unexpected(*process_error); |
16931 | 0 | } |
16932 | | // Set error to true. |
16933 | 0 | error = true; |
16934 | 0 | break; |
16935 | 0 | } |
16936 | | // Set tokenizer's next index to temporary position. |
16937 | 0 | tokenizer.next_index = temporary_position; |
16938 | 0 | } |
16939 | | // Set regexp position to tokenizer's next index. |
16940 | 0 | regexp_position = tokenizer.next_index; |
16941 | 0 | } |
16942 | | |
16943 | | // If error is true continue. |
16944 | 0 | if (error) continue; |
16945 | | // If depth is not zero: |
16946 | 0 | if (depth != 0) { |
16947 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16948 | | // tokenizer's index. |
16949 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16950 | 0 | regexp_start, tokenizer.index)) { |
16951 | 0 | return tl::unexpected(*process_error); |
16952 | 0 | } |
16953 | 0 | continue; |
16954 | 0 | } |
16955 | | // Let regexp length be regexp position - regexp start - 1. |
16956 | 0 | auto regexp_length = regexp_position - regexp_start - 1; |
16957 | | // If regexp length is zero: |
16958 | 0 | if (regexp_length == 0) { |
16959 | | // Run process a tokenizing error given tokenizer, regexp start, and |
16960 | | // tokenizer's index. |
16961 | 0 | if (auto process_error = tokenizer.process_tokenizing_error( |
16962 | 0 | regexp_start, tokenizer.index)) { |
16963 | 0 | ada_log("process_tokenizing_error failed"); |
16964 | 0 | return tl::unexpected(*process_error); |
16965 | 0 | } |
16966 | 0 | continue; |
16967 | 0 | } |
16968 | | // Run add a token given tokenizer, "regexp", regexp position, regexp |
16969 | | // start, and regexp length. |
16970 | 0 | tokenizer.add_token(token_type::REGEXP, regexp_position, regexp_start, |
16971 | 0 | regexp_length); |
16972 | 0 | continue; |
16973 | 0 | } |
16974 | | // Run add a token with default position and length given tokenizer and |
16975 | | // "char". |
16976 | 0 | tokenizer.add_token_with_defaults(token_type::CHAR); |
16977 | 0 | } |
16978 | | // Run add a token with default length given tokenizer, "end", tokenizer's |
16979 | | // index, and tokenizer's index. |
16980 | 0 | tokenizer.add_token_with_default_length(token_type::END, tokenizer.index, |
16981 | 0 | tokenizer.index); |
16982 | |
|
16983 | 0 | ada_log("tokenizer.token_list size is: ", tokenizer.token_list.size()); |
16984 | | // Return tokenizer's token list. |
16985 | 0 | return tokenizer.token_list; |
16986 | 0 | } |
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 | 0 | constexpr bool should_escape_pattern_char(char c) { |
16998 | 0 | return escape_pattern_table[static_cast<uint8_t>(c)]; |
16999 | 0 | } |
17000 | | } // namespace |
17001 | | |
17002 | 0 | std::string escape_pattern_string(std::string_view input) { |
17003 | 0 | ada_log("escape_pattern_string called with input=", input); |
17004 | 0 | if (input.empty()) [[unlikely]] { |
17005 | 0 | return ""; |
17006 | 0 | } |
17007 | | // Assert: input is an ASCII string. |
17008 | 0 | ADA_ASSERT_TRUE(ada::idna::is_ascii(input)); |
17009 | | // Let result be the empty string. |
17010 | 0 | std::string result{}; |
17011 | | // Reserve extra space for potential escapes |
17012 | 0 | result.reserve(input.size() * 2); |
17013 | | |
17014 | | // While index is less than input's length: |
17015 | 0 | for (const char c : input) { |
17016 | 0 | if (should_escape_pattern_char(c)) { |
17017 | | // Append U+005C (\) to the end of result. |
17018 | 0 | result.push_back('\\'); |
17019 | 0 | } |
17020 | | // Append c to the end of result. |
17021 | 0 | result.push_back(c); |
17022 | 0 | } |
17023 | | // Return result. |
17024 | 0 | return result; |
17025 | 0 | } |
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 | 0 | constexpr bool should_escape_regexp_char(char c) { |
17038 | 0 | return escape_regexp_table[(uint8_t)c]; |
17039 | 0 | } |
17040 | | } // namespace |
17041 | | |
17042 | 0 | std::string escape_regexp_string(std::string_view input) { |
17043 | | // Assert: input is an ASCII string. |
17044 | 0 | ADA_ASSERT_TRUE(idna::is_ascii(input)); |
17045 | | // Let result be the empty string. |
17046 | 0 | std::string result{}; |
17047 | | // Reserve extra space for potential escapes (worst case: all chars escaped) |
17048 | 0 | result.reserve(input.size() * 2); |
17049 | 0 | for (const char c : input) { |
17050 | 0 | if (should_escape_regexp_char(c)) { |
17051 | | // Avoid temporary string allocation - directly append characters |
17052 | 0 | result.push_back('\\'); |
17053 | 0 | result.push_back(c); |
17054 | 0 | } else { |
17055 | 0 | result.push_back(c); |
17056 | 0 | } |
17057 | 0 | } |
17058 | 0 | return result; |
17059 | 0 | } |
17060 | | |
17061 | | std::string process_base_url_string(std::string_view input, |
17062 | 0 | url_pattern_init::process_type type) { |
17063 | | // If type is not "pattern" return input. |
17064 | 0 | 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 | 0 | return escape_pattern_string(input); |
17069 | 0 | } |
17070 | | |
17071 | | constexpr bool is_absolute_pathname( |
17072 | 0 | std::string_view input, url_pattern_init::process_type type) noexcept { |
17073 | | // If input is the empty string, then return false. |
17074 | 0 | if (input.empty()) [[unlikely]] { |
17075 | 0 | return false; |
17076 | 0 | } |
17077 | | // If input[0] is U+002F (/), then return true. |
17078 | 0 | 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 | 0 | url_pattern_compile_component_options& options) { |
17092 | | // Let result be the empty string. |
17093 | 0 | 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 | 0 | for (size_t index = 0; index < part_list.size(); index++) { |
17097 | | // Let part be part list[index]. |
17098 | | // Use reference to avoid copy |
17099 | 0 | 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 | 0 | const url_pattern_part* previous_part = |
17104 | 0 | 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 | 0 | const url_pattern_part* next_part = |
17108 | 0 | index < part_list.size() - 1 ? &part_list[index + 1] : nullptr; |
17109 | | // If part's type is "fixed-text" then: |
17110 | 0 | if (part.type == url_pattern_part_type::FIXED_TEXT) { |
17111 | | // If part's modifier is "none" then: |
17112 | 0 | 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 | 0 | result.append(escape_pattern_string(part.value)); |
17116 | 0 | continue; |
17117 | 0 | } |
17118 | | // Append "{" to the end of result. |
17119 | 0 | result += "{"; |
17120 | | // Append the result of running escape a pattern string given part's value |
17121 | | // to the end of result. |
17122 | 0 | result.append(escape_pattern_string(part.value)); |
17123 | | // Append "}" to the end of result. |
17124 | 0 | result += "}"; |
17125 | | // Append the result of running convert a modifier to a string given |
17126 | | // part's modifier to the end of result. |
17127 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
17128 | 0 | continue; |
17129 | 0 | } |
17130 | | // Let custom name be true if part's name[0] is not an ASCII digit; |
17131 | | // otherwise false. |
17132 | 0 | 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 | 0 | bool needs_grouping = |
17139 | 0 | !part.suffix.empty() || |
17140 | 0 | (!part.prefix.empty() && (options.get_prefix().empty() || |
17141 | 0 | 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 | 0 | if (!needs_grouping && custom_name && |
17152 | 0 | part.type == url_pattern_part_type::SEGMENT_WILDCARD && |
17153 | 0 | part.modifier == url_pattern_part_modifier::none && next_part && |
17154 | 0 | next_part->prefix.empty() && next_part->suffix.empty()) { |
17155 | | // If next part's type is "fixed-text": |
17156 | 0 | 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 | 0 | if (idna::valid_name_code_point(next_part->value[0], false)) { |
17161 | 0 | needs_grouping = true; |
17162 | 0 | } |
17163 | 0 | } else { |
17164 | | // Set needs grouping to true if next part's name[0] is an ASCII digit. |
17165 | 0 | needs_grouping = !next_part->name.empty() && |
17166 | 0 | unicode::is_ascii_digit(next_part->name[0]); |
17167 | 0 | } |
17168 | 0 | } |
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 | 0 | if (!needs_grouping && part.prefix.empty() && previous_part && |
17178 | 0 | previous_part->type == url_pattern_part_type::FIXED_TEXT && |
17179 | 0 | !previous_part->value.empty() && !options.get_prefix().empty() && |
17180 | 0 | previous_part->value.back() == options.get_prefix()[0]) { |
17181 | 0 | needs_grouping = true; |
17182 | 0 | } |
17183 | | |
17184 | | // Assert: part's name is not the empty string or null. |
17185 | 0 | ADA_ASSERT_TRUE(!part.name.empty()); |
17186 | | |
17187 | | // If needs grouping is true, then append "{" to the end of result. |
17188 | 0 | if (needs_grouping) { |
17189 | 0 | result.append("{"); |
17190 | 0 | } |
17191 | | |
17192 | | // Append the result of running escape a pattern string given part's prefix |
17193 | | // to the end of result. |
17194 | 0 | result.append(escape_pattern_string(part.prefix)); |
17195 | | |
17196 | | // If custom name is true: |
17197 | 0 | if (custom_name) { |
17198 | | // Append ":" to the end of result. |
17199 | 0 | result.append(":"); |
17200 | | // Append part's name to the end of result. |
17201 | 0 | result.append(part.name); |
17202 | 0 | } |
17203 | | |
17204 | | // If part's type is "regexp" then: |
17205 | 0 | if (part.type == url_pattern_part_type::REGEXP) { |
17206 | | // Append "(" to the end of result. |
17207 | 0 | result.append("("); |
17208 | | // Append part's value to the end of result. |
17209 | 0 | result.append(part.value); |
17210 | | // Append ")" to the end of result. |
17211 | 0 | result.append(")"); |
17212 | 0 | } else if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && |
17213 | 0 | !custom_name) { |
17214 | | // Otherwise if part's type is "segment-wildcard" and custom name is |
17215 | | // false: Append "(" to the end of result. |
17216 | 0 | result.append("("); |
17217 | | // Append the result of running generate a segment wildcard regexp given |
17218 | | // options to the end of result. |
17219 | 0 | result.append(generate_segment_wildcard_regexp(options)); |
17220 | | // Append ")" to the end of result. |
17221 | 0 | result.append(")"); |
17222 | 0 | } 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 | 0 | if (!custom_name && |
17232 | 0 | (!previous_part || |
17233 | 0 | previous_part->type == url_pattern_part_type::FIXED_TEXT || |
17234 | 0 | previous_part->modifier != url_pattern_part_modifier::none || |
17235 | 0 | needs_grouping || !part.prefix.empty())) { |
17236 | 0 | result.append("*"); |
17237 | 0 | } 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 | 0 | result.append("(.*)"); |
17242 | 0 | } |
17243 | 0 | } |
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 | 0 | if (part.type == url_pattern_part_type::SEGMENT_WILDCARD && custom_name && |
17253 | 0 | !part.suffix.empty() && |
17254 | 0 | idna::valid_name_code_point(part.suffix[0], false)) { |
17255 | 0 | result.append("\\"); |
17256 | 0 | } |
17257 | | |
17258 | | // Append the result of running escape a pattern string given part's suffix |
17259 | | // to the end of result. |
17260 | 0 | result.append(escape_pattern_string(part.suffix)); |
17261 | | // If needs grouping is true, then append "}" to the end of result. |
17262 | 0 | 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 | 0 | result.append(convert_modifier_to_string(part.modifier)); |
17266 | 0 | } |
17267 | | // Return result. |
17268 | 0 | return result; |
17269 | 0 | } |
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 | | 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 | | auto flags = ignore_case |
17296 | | ? std::regex::icase | std::regex_constants::ECMAScript |
17297 | | : std::regex_constants::ECMAScript; |
17298 | | try { |
17299 | | return std::regex(pattern.data(), pattern.size(), flags); |
17300 | | } catch (const std::regex_error& e) { |
17301 | | (void)e; |
17302 | | ada_log("std_regex_provider::create_instance failed:", e.what()); |
17303 | | return std::nullopt; |
17304 | | } |
17305 | | } |
17306 | | |
17307 | | std::optional<std::vector<std::optional<std::string>>> |
17308 | | std_regex_provider::regex_search(std::string_view input, |
17309 | | const std::regex& pattern) { |
17310 | | // Use iterator-based regex_search to avoid string allocation |
17311 | | std::match_results<std::string_view::const_iterator> match_result; |
17312 | | try { |
17313 | | if (!std::regex_search(input.begin(), input.end(), match_result, pattern, |
17314 | | std::regex_constants::match_any)) { |
17315 | | return std::nullopt; |
17316 | | } |
17317 | | } catch (const std::regex_error& e) { |
17318 | | (void)e; |
17319 | | ada_log("std_regex_provider::regex_search failed:", e.what()); |
17320 | | return std::nullopt; |
17321 | | } |
17322 | | 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 | | if (match_result.empty()) { |
17328 | | return matches; |
17329 | | } |
17330 | | matches.reserve(match_result.size()); |
17331 | | for (size_t i = 1; i < match_result.size(); ++i) { |
17332 | | if (auto entry = match_result[i]; entry.matched) { |
17333 | | matches.emplace_back(entry.str()); |
17334 | | } 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 | | matches.emplace_back(std::nullopt); |
17340 | | } |
17341 | | } |
17342 | | return matches; |
17343 | | } |
17344 | | |
17345 | | bool std_regex_provider::regex_match(std::string_view input, |
17346 | | const std::regex& pattern) { |
17347 | | try { |
17348 | | return std::regex_match(input.begin(), input.end(), pattern); |
17349 | | } catch (const std::regex_error& e) { |
17350 | | (void)e; |
17351 | | ada_log("std_regex_provider::regex_match failed:", e.what()); |
17352 | | return false; |
17353 | | } |
17354 | | } |
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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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: serializers.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 */ |