From 6d48cfafebee546aa455e9a13a38b93210de9d49 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2026 15:36:49 +0000 Subject: [PATCH] fix(deps): update module github.com/gofiber/fiber/v3 to v3.6.0 --- src/go.mod | 33 +- src/go.sum | 32 + .../github.com/andybalholm/brotli/.gitignore | 2 - .../github.com/andybalholm/brotli/README.md | 19 - .../andybalholm/brotli/backward_references.go | 185 - .../brotli/backward_references_hq.go | 796 - .../github.com/andybalholm/brotli/bit_cost.go | 436 - .../andybalholm/brotli/bit_reader.go | 266 - .../andybalholm/brotli/bitwriter.go | 56 - .../andybalholm/brotli/block_splitter.go | 144 - .../brotli/block_splitter_command.go | 434 - .../brotli/block_splitter_distance.go | 433 - .../brotli/block_splitter_literal.go | 433 - .../andybalholm/brotli/brotli_bit_stream.go | 1435 - .../github.com/andybalholm/brotli/cluster.go | 30 - .../andybalholm/brotli/cluster_command.go | 164 - .../andybalholm/brotli/cluster_distance.go | 326 - .../andybalholm/brotli/cluster_literal.go | 326 - .../github.com/andybalholm/brotli/command.go | 254 - .../andybalholm/brotli/compress_fragment.go | 834 - .../brotli/compress_fragment_two_pass.go | 775 - .../andybalholm/brotli/constants.go | 77 - .../github.com/andybalholm/brotli/context.go | 2176 - .../github.com/andybalholm/brotli/decode.go | 2570 - .../andybalholm/brotli/dictionary.go | 122890 --------------- .../andybalholm/brotli/dictionary_hash.go | 32779 ---- .../github.com/andybalholm/brotli/encode.go | 1220 - .../github.com/andybalholm/brotli/encoder.go | 177 - .../andybalholm/brotli/encoder_dict.go | 22 - .../andybalholm/brotli/encoder_fast.go | 197 - .../andybalholm/brotli/entropy_encode.go | 592 - .../brotli/entropy_encode_static.go | 4399 - .../github.com/andybalholm/brotli/fast_log.go | 290 - .../andybalholm/brotli/find_match_length.go | 45 - .../andybalholm/brotli/flate/LICENSE | 27 - .../andybalholm/brotli/flate/README.md | 2 - .../andybalholm/brotli/flate/gzip.go | 65 - .../brotli/flate/huffman_bit_writer.go | 517 - .../andybalholm/brotli/flate/huffman_code.go | 346 - .../andybalholm/brotli/flate/token.go | 80 - .../andybalholm/brotli/flate/writer.go | 66 - .../github.com/andybalholm/brotli/h10.go | 287 - .../github.com/andybalholm/brotli/h5.go | 214 - .../github.com/andybalholm/brotli/h6.go | 216 - .../github.com/andybalholm/brotli/hash.go | 342 - .../andybalholm/brotli/hash_composite.go | 93 - .../brotli/hash_forgetful_chain.go | 252 - .../brotli/hash_longest_match_quickly.go | 214 - .../andybalholm/brotli/hash_rolling.go | 168 - .../andybalholm/brotli/histogram.go | 226 - .../github.com/andybalholm/brotli/http.go | 189 - .../github.com/andybalholm/brotli/huffman.go | 653 - .../andybalholm/brotli/literal_cost.go | 182 - .../brotli/matchfinder/bargain1.go | 212 - .../brotli/matchfinder/bargain2.go | 248 - .../brotli/matchfinder/bargain3.go | 278 - .../andybalholm/brotli/matchfinder/emitter.go | 34 - .../andybalholm/brotli/matchfinder/m0.go | 175 - .../andybalholm/brotli/matchfinder/m4.go | 339 - .../brotli/matchfinder/matchfinder.go | 103 - .../brotli/matchfinder/pathfinder.go | 328 - .../brotli/matchfinder/textencoder.go | 53 - .../andybalholm/brotli/matchfinder/trio.go | 326 - .../andybalholm/brotli/matchfinder/zdfast.go | 258 - .../andybalholm/brotli/matchfinder/zfast.go | 206 - .../andybalholm/brotli/matchfinder/zm.go | 301 - .../github.com/andybalholm/brotli/memory.go | 66 - .../andybalholm/brotli/metablock.go | 574 - .../andybalholm/brotli/metablock_command.go | 165 - .../andybalholm/brotli/metablock_distance.go | 165 - .../andybalholm/brotli/metablock_literal.go | 165 - .../github.com/andybalholm/brotli/params.go | 37 - .../github.com/andybalholm/brotli/platform.go | 103 - .../github.com/andybalholm/brotli/prefix.go | 30 - .../andybalholm/brotli/prefix_dec.go | 723 - .../github.com/andybalholm/brotli/quality.go | 196 - .../github.com/andybalholm/brotli/reader.go | 126 - .../andybalholm/brotli/ringbuffer.go | 134 - .../github.com/andybalholm/brotli/state.go | 313 - .../andybalholm/brotli/static_dict.go | 662 - .../andybalholm/brotli/static_dict_lut.go | 75094 --------- .../andybalholm/brotli/symbol_list.go | 22 - .../andybalholm/brotli/transform.go | 641 - .../andybalholm/brotli/utf8_util.go | 70 - .../andybalholm/brotli/write_bits.go | 52 - .../github.com/andybalholm/brotli/writer.go | 162 - .../github.com/fxamacker/cbor/v2/cache.go | 141 +- .../github.com/fxamacker/cbor/v2/decode.go | 139 +- .../github.com/fxamacker/cbor/v2/encode.go | 229 +- .../fxamacker/cbor/v2/encode_map.go | 6 +- .../github.com/fxamacker/cbor/v2/valid.go | 10 +- .../github.com/gofiber/fiber/v3/.golangci.yml | 17 + .../github.com/gofiber/fiber/v3/AGENTS.md | 6 +- .../github.com/gofiber/fiber/v3/README.md | 879 + src/vendor/github.com/gofiber/fiber/v3/app.go | 326 +- .../github.com/gofiber/fiber/v3/appconfig.go | 26 + .../github.com/gofiber/fiber/v3/bind.go | 129 +- .../gofiber/fiber/v3/binder/cookie.go | 8 +- .../gofiber/fiber/v3/binder/form.go | 111 +- .../gofiber/fiber/v3/binder/header.go | 8 +- .../gofiber/fiber/v3/binder/mapping.go | 630 +- .../gofiber/fiber/v3/binder/query.go | 8 +- .../gofiber/fiber/v3/binder/resp_header.go | 8 +- .../github.com/gofiber/fiber/v3/binder/uri.go | 8 +- .../github.com/gofiber/fiber/v3/constants.go | 12 +- .../github.com/gofiber/fiber/v3/constraint.go | 76 +- src/vendor/github.com/gofiber/fiber/v3/ctx.go | 579 +- .../gofiber/fiber/v3/ctx_interface.go | 3 + .../gofiber/fiber/v3/ctx_interface_gen.go | 373 +- .../github.com/gofiber/fiber/v3/domain.go | 251 +- .../github.com/gofiber/fiber/v3/error.go | 27 +- .../github.com/gofiber/fiber/v3/group.go | 3 +- .../github.com/gofiber/fiber/v3/helpers.go | 690 +- .../github.com/gofiber/fiber/v3/hooks.go | 30 +- .../fiber/v3/internal/appconfig/appconfig.go | 46 + .../fiber/v3/internal/byterange/byterange.go | 204 + .../fiber/v3/internal/cookie/samesite.go | 78 + .../gofiber/fiber/v3/internal/etag/etag.go | 102 + .../fiber/v3/internal/fieldname/fieldname.go | 314 + .../v3/internal/headerlist/headerlist.go | 331 + .../v3/internal/headerlookup/headerlookup.go | 214 + .../fiber/v3/internal/logtemplate/sanitize.go | 73 + .../fiber/v3/internal/mediatype/mediatype.go | 104 + .../fiber/v3/internal/memory/memory.go | 44 +- .../fiber/v3/internal/origin/origin.go | 179 + .../v3/internal/paramdelim/paramdelim.go | 17 + .../v3/internal/quotedstring/quotedstring.go | 80 + .../v3/internal/schemehost/schemehost.go | 125 +- .../fiber/v3/internal/urlnorm/urlnorm.go | 68 + .../github.com/gofiber/fiber/v3/listen.go | 193 +- .../gofiber/fiber/v3/log/context.go | 56 +- .../gofiber/fiber/v3/log/default.go | 31 +- .../fiber/v3/middleware/compress/compress.go | 112 +- .../gofiber/fiber/v3/middleware/cors/cors.go | 183 +- .../gofiber/fiber/v3/middleware/cors/utils.go | 96 - .../gofiber/fiber/v3/middleware/etag/etag.go | 76 +- .../fiber/v3/middleware/favicon/favicon.go | 7 +- .../fiber/v3/middleware/limiter/config.go | 25 +- .../fiber/v3/middleware/limiter/limiter.go | 25 +- .../v3/middleware/limiter/limiter_fixed.go | 40 +- .../v3/middleware/limiter/limiter_sliding.go | 36 +- .../fiber/v3/middleware/limiter/manager.go | 47 + .../fiber/v3/middleware/logger/context_tag.go | 8 +- .../v3/middleware/logger/default_logger.go | 213 +- .../fiber/v3/middleware/logger/logger.go | 8 +- .../fiber/v3/middleware/logger/tags.go | 99 +- .../fiber/v3/middleware/logger/utils.go | 120 + .../fiber/v3/middleware/recover/recover.go | 4 +- .../v3/middleware/requestid/requestid.go | 28 +- .../fiber/v3/middleware/static/config.go | 3 +- .../fiber/v3/middleware/static/static.go | 559 +- .../github.com/gofiber/fiber/v3/mount.go | 661 +- .../github.com/gofiber/fiber/v3/path.go | 950 +- .../github.com/gofiber/fiber/v3/prefork.go | 1 + .../github.com/gofiber/fiber/v3/redirect.go | 211 +- src/vendor/github.com/gofiber/fiber/v3/req.go | 928 +- .../gofiber/fiber/v3/req_interface_gen.go | 180 +- src/vendor/github.com/gofiber/fiber/v3/res.go | 855 +- .../gofiber/fiber/v3/res_interface_gen.go | 69 + .../github.com/gofiber/fiber/v3/router.go | 967 +- .../gofiber/fiber/v3/router_filter.go | 303 + .../gofiber/fiber/v3/router_skip.go | 278 + .../github.com/gofiber/fiber/v3/services.go | 40 +- .../github.com/gofiber/fiber/v3/state.go | 60 +- .../github.com/gofiber/schema/.golangci.yml | 2 +- .../github.com/gofiber/schema/README.md | 42 +- src/vendor/github.com/gofiber/schema/cache.go | 520 +- .../github.com/gofiber/schema/converter.go | 38 + .../github.com/gofiber/schema/decoder.go | 941 +- .../github.com/gofiber/schema/encoder.go | 198 +- .../github.com/gofiber/schema/floatfmt.go | 105 + .../github.com/gofiber/schema/values.go | 225 + .../github.com/gofiber/utils/v2/AGENTS.md | 3 +- .../github.com/gofiber/utils/v2/Makefile | 7 +- .../github.com/gofiber/utils/v2/README.md | 1492 +- .../github.com/gofiber/utils/v2/ascii.go | 64 +- .../github.com/gofiber/utils/v2/bytes/case.go | 31 +- .../github.com/gofiber/utils/v2/byteseq.go | 73 + .../github.com/gofiber/utils/v2/control.go | 83 + src/vendor/github.com/gofiber/utils/v2/cut.go | 25 + .../github.com/gofiber/utils/v2/duration.go | 121 + .../github.com/gofiber/utils/v2/format.go | 178 +- .../github.com/gofiber/utils/v2/headerkey.go | 71 + .../github.com/gofiber/utils/v2/hostport.go | 35 + .../github.com/gofiber/utils/v2/http.go | 83 +- .../github.com/gofiber/utils/v2/httpdate.go | 283 + .../utils/v2/internal/caseconv/swar.go | 203 +- .../v2/internal/unsafeconv/unsafeconv.go | 22 + .../github.com/gofiber/utils/v2/ipparse.go | 177 + src/vendor/github.com/gofiber/utils/v2/ips.go | 74 +- .../github.com/gofiber/utils/v2/jsonstring.go | 126 + .../github.com/gofiber/utils/v2/parse.go | 7 +- .../github.com/gofiber/utils/v2/search.go | 14 +- src/vendor/github.com/gofiber/utils/v2/seq.go | 32 + .../github.com/gofiber/utils/v2/simd/LICENSE | 21 + .../github.com/gofiber/utils/v2/simd/ascii.go | 177 + .../gofiber/utils/v2/simd/ascii_amd64.go | 55 + .../gofiber/utils/v2/simd/ascii_amd64.s | 399 + .../gofiber/utils/v2/simd/ascii_other.go | 21 + .../gofiber/utils/v2/simd/block_align_amd64.h | 31 + .../gofiber/utils/v2/simd/byte_frequencies.go | 102 + .../gofiber/utils/v2/simd/cpu_amd64.go | 22 + .../gofiber/utils/v2/simd/cpu_other.go | 7 + .../gofiber/utils/v2/simd/memchr.go | 242 + .../gofiber/utils/v2/simd/memchr_amd64.go | 52 + .../gofiber/utils/v2/simd/memchr_amd64.s | 570 + .../gofiber/utils/v2/simd/memchr_class.go | 177 + .../utils/v2/simd/memchr_class_amd64.go | 35 + .../utils/v2/simd/memchr_class_amd64.s | 417 + .../utils/v2/simd/memchr_class_other.go | 17 + .../gofiber/utils/v2/simd/memchr_digit.go | 79 + .../utils/v2/simd/memchr_digit_amd64.go | 23 + .../utils/v2/simd/memchr_digit_amd64.s | 192 + .../utils/v2/simd/memchr_digit_other.go | 12 + .../gofiber/utils/v2/simd/memchr_other.go | 21 + .../gofiber/utils/v2/simd/memmem.go | 162 + .../github.com/gofiber/utils/v2/simd/simd.go | 51 + .../gofiber/utils/v2/strings/case.go | 33 +- .../github.com/gofiber/utils/v2/swar/swar.go | 32 +- .../github.com/gofiber/utils/v2/time.go | 32 +- src/vendor/github.com/gofiber/utils/v2/url.go | 182 + .../github.com/klauspost/compress/README.md | 2 + .../klauspost/compress/flate/deflate.go | 36 +- .../klauspost/compress/flate/fast_encoder.go | 3 +- .../compress/flate/huffman_bit_writer.go | 224 +- .../klauspost/compress/flate/huffman_code.go | 138 +- .../compress/flate/huffman_sortByFreq.go | 159 - .../compress/flate/huffman_sortByLiteral.go | 201 - .../klauspost/compress/flate/inflate.go | 12 +- .../klauspost/compress/flate/inflate_gen.go | 142 +- .../compress/flate/matchlen_generic.go | 13 +- .../klauspost/compress/flate/regmask_amd64.go | 37 - .../klauspost/compress/flate/regmask_other.go | 39 - .../klauspost/compress/flate/token.go | 18 +- .../klauspost/compress/huff0/bitreader.go | 63 + .../compress/huff0/decompress_amd64.go | 274 +- .../compress/huff0/decompress_amd64.s | 4106 +- .../compress/huff0/decompress_arm64.go | 72 + .../compress/huff0/decompress_arm64.s | 1657 + .../compress/huff0/decompress_asm.go | 253 + .../compress/huff0/decompress_generic.go | 2 +- .../compress/internal/regmask/regmask.go | 50 + .../compress/internal/regmask/regmask_386.go | 39 + .../s2/{encode_amd64.go => encode_asm.go} | 4 +- .../klauspost/compress/s2/encode_better.go | 8 +- .../klauspost/compress/s2/encode_go.go | 4 +- .../klauspost/compress/s2/encodeblock_amd64.s | 844 +- .../klauspost/compress/s2/encodeblock_arm64.s | 23562 +++ ...ncodeblock_amd64.go => encodeblock_asm.go} | 4 +- .../github.com/klauspost/compress/s2/index.go | 4 +- .../klauspost/compress/s2/lz4convert.go | 4 +- .../klauspost/compress/s2/lz4sconvert.go | 4 +- .../klauspost/compress/s2/reader.go | 6 +- .../klauspost/compress/s2/writer.go | 8 +- .../klauspost/compress/zstd/blockdec.go | 12 +- .../klauspost/compress/zstd/decoder.go | 125 +- .../klauspost/compress/zstd/dict.go | 85 +- .../klauspost/compress/zstd/framedec.go | 11 +- .../compress/zstd/fse_decoder_arm64.s | 35 +- .../compress/zstd/internal/xxhash/xxhash.go | 12 + .../zstd/internal/xxhash/xxhash_amd64.s | 6 +- .../zstd/internal/xxhash/xxhash_arm64.s | 6 +- .../klauspost/compress/zstd/seqdec.go | 23 + .../klauspost/compress/zstd/seqdec_amd64.s | 2085 +- .../klauspost/compress/zstd/seqdec_arm64.s | 1900 +- .../klauspost/compress/zstd/seqdec_asm.go | 34 +- .../mattn/go-colorable/colorable_windows.go | 715 +- .../go-colorable/colorable_windows_palette.go | 25 + .../mattn/go-colorable/noncolorable.go | 40 +- ...{isatty_tcgets.go => isatty_tiocgwinsz.go} | 6 +- .../molecule-man/go-brrr/.gitignore | 39 + .../molecule-man/go-brrr/.gitmodules | 3 + .../molecule-man/go-brrr/.golangci.yml | 139 + .../go-brrr/.pre-commit-config.yaml | 38 + .../molecule-man/go-brrr/CONTRIBUTING.md | 199 + .../brotli => molecule-man/go-brrr}/LICENSE | 14 +- .../github.com/molecule-man/go-brrr/Makefile | 16 + .../github.com/molecule-man/go-brrr/README.md | 205 + .../molecule-man/go-brrr/bitreader.go | 279 + .../github.com/molecule-man/go-brrr/brotli.go | 54 + .../github.com/molecule-man/go-brrr/decode.go | 2382 + .../molecule-man/go-brrr/decode_state.go | 627 + .../molecule-man/go-brrr/dictionary.go | 27 + .../github.com/molecule-man/go-brrr/doc.go | 81 + .../go-brrr/internal/core/cmdlut.go | 722 + .../go-brrr/internal/core/constants.go | 63 + .../go-brrr/internal/core/context.go | 202 + .../go-brrr/internal/core/dictionary.bin | 432 + .../go-brrr/internal/core/dictionary.go | 39 + .../molecule-man/go-brrr/internal/core/doc.go | 3 + .../go-brrr/internal/core/huffman.go | 326 + .../go-brrr/internal/core/transforms.go | 357 + .../go-brrr/internal/encoder/arena.go | 305 + .../go-brrr/internal/encoder/assert.go} | 2 +- .../internal/encoder/backward_match.go | 46 + .../go-brrr/internal/encoder/bitwriter.go | 709 + .../go-brrr/internal/encoder/block_encoder.go | 273 + .../go-brrr/internal/encoder/block_split.go | 664 + .../internal/encoder/block_splitter.go | 821 + .../go-brrr/internal/encoder/cluster.go | 467 + .../go-brrr/internal/encoder/coderange.go | 50 + .../go-brrr/internal/encoder/command.go | 372 + .../go-brrr/internal/encoder/compound_dict.go | 467 + .../encoder/compress_fragment_fast.go | 683 + .../encoder/compress_fragment_two_pass.go | 790 + .../go-brrr/internal/encoder/compressor.go | 57 + .../go-brrr/internal/encoder/constants.go | 69 + .../go-brrr/internal/encoder/context_model.go | 263 + .../internal/encoder/distance_params.go | 119 + .../go-brrr/internal/encoder/encode_state.go | 361 + .../go-brrr/internal/encoder/encoder.go | 1545 + .../internal/encoder/entropy_static.go | 485 + .../internal/encoder/fast_compressor.go | 272 + .../go-brrr/internal/encoder/fastlog.go | 123 + .../go-brrr/internal/encoder/fill.go | 11 + .../encoder/findblocks_kernel_generic.go | 61 + .../encoder/findblocks_kernel_simd_amd64.go | 17 + .../encoder/findblocks_kernel_simd_amd64.s | 566 + .../go-brrr/internal/encoder/hash.go | 77 + .../go-brrr/internal/encoder/hash10.go | 502 + .../go-brrr/internal/encoder/hash2.go | 703 + .../go-brrr/internal/encoder/hash2u16.go | 625 + .../go-brrr/internal/encoder/hash3.go | 791 + .../go-brrr/internal/encoder/hash3u16.go | 379 + .../go-brrr/internal/encoder/hash4.go | 898 + .../go-brrr/internal/encoder/hash40.go | 564 + .../go-brrr/internal/encoder/hash41.go | 598 + .../go-brrr/internal/encoder/hash42.go | 363 + .../go-brrr/internal/encoder/hash4u16.go | 884 + .../go-brrr/internal/encoder/hash5.go | 932 + .../go-brrr/internal/encoder/hash54.go | 868 + .../go-brrr/internal/encoder/hash5b.go | 1370 + .../go-brrr/internal/encoder/hash5b5.go | 749 + .../go-brrr/internal/encoder/hash5b6u16.go | 533 + .../go-brrr/internal/encoder/hash5b8.go | 1680 + .../go-brrr/internal/encoder/hash6.go | 536 + .../go-brrr/internal/encoder/hash6b.go | 763 + .../go-brrr/internal/encoder/hash6b5.go | 862 + .../go-brrr/internal/encoder/hash6b8.go | 1409 + .../go-brrr/internal/encoder/hasher_pool.go | 80 + .../go-brrr/internal/encoder/histogram.go | 142 + .../internal/encoder/histogram_add_generic.go | 10 + .../encoder/histogram_add_simd_amd64.go | 15 + .../encoder/histogram_add_simd_amd64.s | 77 + .../encoder/histogram_total_count_generic.go | 12 + .../histogram_total_count_simd_amd64.go | 15 + .../histogram_total_count_simd_amd64.s | 66 + .../go-brrr/internal/encoder/huffman_block.go | 114 + .../internal/encoder/huffman_encode.go | 538 + .../go-brrr/internal/encoder/le_generic.go | 70 + .../go-brrr/internal/encoder/le_unsafe.go | 62 + .../go-brrr/internal/encoder/literal_cost.go | 293 + .../go-brrr/internal/encoder/log2.go | 120 + .../go-brrr/internal/encoder/matchlen.go | 93 + .../internal/encoder/matchlen_simd_amd64.go | 10 + .../internal/encoder/matchlen_simd_amd64.s | 76 + .../internal/encoder/matchlen_simd_other.go | 26 + .../go-brrr/internal/encoder/metablock.go | 253 + .../internal/encoder/population_cost.go | 129 + .../internal/encoder/prefetch_amd64.go | 10 + .../go-brrr/internal/encoder/prefetch_amd64.s | 11 + .../internal/encoder/prefetch_generic.go | 9 + .../internal/encoder/prefix2mask_generic.go | 10 + .../encoder/prefix2mask_simd_amd64.go | 12 + .../internal/encoder/prefix2mask_simd_amd64.s | 59 + .../go-brrr/internal/encoder/ringbuffer.go | 131 + .../go-brrr/internal/encoder/static_dict.go | 223 + .../internal/encoder/static_dict_all.go | 677 + .../internal/encoder/static_dict_lut.go | 10636 ++ .../internal/encoder/streaming_compressor.go | 167 + .../go-brrr/internal/encoder/testseeder.go | 31 + .../go-brrr/internal/encoder/zopfli.go | 547 + .../internal/encoder/zopfli_cost_model.go | 200 + .../go-brrr/internal/encoder/zopfli_hq.go | 479 + .../go-brrr/internal/encoder/zopfli_node.go | 155 + .../internal/encoder/zopfli_shortest_path.go | 126 + .../molecule-man/go-brrr/output_chunks.go | 53 + .../github.com/molecule-man/go-brrr/reader.go | 213 + .../github.com/molecule-man/go-brrr/writer.go | 238 + .../github.com/tinylib/msgp/msgp/edit.go | 4 + .../github.com/tinylib/msgp/msgp/errors.go | 9 + .../github.com/tinylib/msgp/msgp/read.go | 6 +- .../tinylib/msgp/msgp/setof/generated.go | 1281 +- .../tinylib/msgp/msgp/setof/json.go | 155 + .../tinylib/msgp/msgp/setof/setof.go | 6 +- .../github.com/tinylib/msgp/msgp/write.go | 2 +- .../github.com/valyala/fasthttp/.golangci.yml | 30 +- .../github.com/valyala/fasthttp/README.md | 24 +- .../github.com/valyala/fasthttp/args.go | 65 +- .../github.com/valyala/fasthttp/brotli.go | 79 +- .../github.com/valyala/fasthttp/bytesconv.go | 118 +- .../valyala/fasthttp/bytesconv_table.go | 3 +- .../github.com/valyala/fasthttp/client.go | 551 +- .../github.com/valyala/fasthttp/compress.go | 16 +- .../github.com/valyala/fasthttp/cookie.go | 48 +- src/vendor/github.com/valyala/fasthttp/doc.go | 5 +- .../fasthttp/fasthttpadaptor/adaptor.go | 369 +- .../fasthttp/fasthttpadaptor/request.go | 436 +- .../fasthttputil/inmemory_listener.go | 2 +- .../fasthttp/fasthttputil/pipeconns.go | 6 +- src/vendor/github.com/valyala/fasthttp/fs.go | 324 +- .../github.com/valyala/fasthttp/fs_unix.go | 7 + .../github.com/valyala/fasthttp/fs_windows.go | 18 + .../github.com/valyala/fasthttp/header.go | 1184 +- .../github.com/valyala/fasthttp/headers.go | 1 + .../valyala/fasthttp/headerscanner.go | 394 +- .../github.com/valyala/fasthttp/http.go | 479 +- .../github.com/valyala/fasthttp/ipv6.go | 6 +- .../github.com/valyala/fasthttp/lbclient.go | 2 +- .../github.com/valyala/fasthttp/methods.go | 1 + .../github.com/valyala/fasthttp/peripconn.go | 78 +- .../valyala/fasthttp/prefork/prefork.go | 10 +- .../fasthttp/reuseport/reuseport_error.go | 2 +- .../github.com/valyala/fasthttp/server.go | 379 +- .../valyala/fasthttp/stackless/func.go | 2 +- .../valyala/fasthttp/stackless/writer.go | 2 +- .../github.com/valyala/fasthttp/status.go | 12 +- .../github.com/valyala/fasthttp/stream.go | 2 +- .../github.com/valyala/fasthttp/streaming.go | 100 +- .../github.com/valyala/fasthttp/strings.go | 4 +- .../github.com/valyala/fasthttp/swar.go | 65 + .../github.com/valyala/fasthttp/tcpdialer.go | 9 +- .../valyala/fasthttp/tcplisten/tcplisten.go | 6 +- .../fasthttp/tcplisten/tcplisten_linux.go | 4 +- .../github.com/valyala/fasthttp/timer.go | 10 +- src/vendor/github.com/valyala/fasthttp/uri.go | 261 +- .../github.com/valyala/fasthttp/workerpool.go | 4 +- .../github.com/valyala/fasthttp/zstd.go | 130 +- src/vendor/go.yaml.in/yaml/v3/parserc.go | 178 +- src/vendor/go.yaml.in/yaml/v3/yamlh.go | 44 +- src/vendor/golang.org/x/crypto/acme/jws.go | 13 +- src/vendor/golang.org/x/crypto/acme/types.go | 9 +- src/vendor/golang.org/x/crypto/ocsp/ocsp.go | 17 +- src/vendor/golang.org/x/net/html/escape.go | 5 +- .../golang.org/x/sync/semaphore/semaphore.go | 9 +- src/vendor/golang.org/x/sys/cpu/cpu.go | 26 +- .../golang.org/x/sys/cpu/cpu_gc_riscv64.go | 11 + .../golang.org/x/sys/cpu/cpu_linux_ppc64x.go | 4 + .../golang.org/x/sys/cpu/cpu_linux_riscv64.go | 11 + .../golang.org/x/sys/cpu/cpu_netbsd_amd64.go | 47 + .../golang.org/x/sys/cpu/cpu_other_x86.go | 2 +- src/vendor/golang.org/x/sys/cpu/cpu_riscv64.s | 17 + .../golang.org/x/sys/cpu/cpu_sparc64.go | 12 + src/vendor/golang.org/x/sys/cpu/cpu_x86.go | 23 + .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 20 + .../golang.org/x/sys/unix/asm_linux_sparc64.s | 48 + .../golang.org/x/sys/unix/asm_zos_s390x.s | 190 +- src/vendor/golang.org/x/sys/unix/bpxsvc_zos.s | 18 +- .../golang.org/x/sys/unix/fcntl_darwin.go | 4 +- .../golang.org/x/sys/unix/ifreq_linux.go | 8 +- .../golang.org/x/sys/unix/ioctl_linux.go | 7 + src/vendor/golang.org/x/sys/unix/mkerrors.sh | 11 +- .../golang.org/x/sys/unix/ptrace_zos.go | 537 + .../x/sys/unix/ptrace_zos_singlestep.go | 425 + src/vendor/golang.org/x/sys/unix/syscall.go | 2 +- .../golang.org/x/sys/unix/syscall_bsd.go | 2 +- .../golang.org/x/sys/unix/syscall_darwin.go | 1 + .../golang.org/x/sys/unix/syscall_freebsd.go | 9 + .../golang.org/x/sys/unix/syscall_linux.go | 23 +- .../x/sys/unix/syscall_linux_sparc64.go | 6 +- .../golang.org/x/sys/unix/syscall_netbsd.go | 9 + .../golang.org/x/sys/unix/syscall_unix_gc.go | 2 +- .../x/sys/unix/syscall_unix_gc_ppc64x.go | 22 - .../x/sys/unix/syscall_zos_s390x.go | 4 - src/vendor/golang.org/x/sys/unix/xattr_bsd.go | 24 +- .../x/sys/unix/zerrors_darwin_amd64.go | 6 + .../x/sys/unix/zerrors_darwin_arm64.go | 6 + .../golang.org/x/sys/unix/zerrors_linux.go | 34 + .../x/sys/unix/zerrors_linux_386.go | 3 +- .../x/sys/unix/zerrors_linux_amd64.go | 3 +- .../x/sys/unix/zerrors_linux_arm.go | 3 +- .../x/sys/unix/zerrors_linux_arm64.go | 3 +- .../x/sys/unix/zerrors_linux_loong64.go | 3 +- .../x/sys/unix/zerrors_linux_mips.go | 3 +- .../x/sys/unix/zerrors_linux_mips64.go | 3 +- .../x/sys/unix/zerrors_linux_mips64le.go | 3 +- .../x/sys/unix/zerrors_linux_mipsle.go | 3 +- .../x/sys/unix/zerrors_linux_ppc.go | 3 +- .../x/sys/unix/zerrors_linux_ppc64.go | 3 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 3 +- .../x/sys/unix/zerrors_linux_riscv64.go | 3 +- .../x/sys/unix/zerrors_linux_s390x.go | 3 +- .../x/sys/unix/zerrors_linux_sparc64.go | 37 +- .../x/sys/unix/zsyscall_darwin_amd64.go | 11 + .../x/sys/unix/zsyscall_darwin_arm64.go | 11 + .../x/sys/unix/zsyscall_freebsd_386.go | 159 + .../x/sys/unix/zsyscall_freebsd_amd64.go | 159 + .../x/sys/unix/zsyscall_freebsd_arm.go | 159 + .../x/sys/unix/zsyscall_freebsd_arm64.go | 159 + .../x/sys/unix/zsyscall_freebsd_riscv64.go | 159 + .../golang.org/x/sys/unix/zsyscall_linux.go | 29 +- .../x/sys/unix/zsyscall_linux_sparc64.go | 6 +- .../x/sys/unix/zsyscall_netbsd_386.go | 159 + .../x/sys/unix/zsyscall_netbsd_amd64.go | 159 + .../x/sys/unix/zsyscall_netbsd_arm.go | 159 + .../x/sys/unix/zsyscall_netbsd_arm64.go | 159 + .../x/sys/unix/zsysnum_zos_s390x.go | 13 + .../golang.org/x/sys/unix/ztypes_linux.go | 151 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 38 +- .../x/sys/unix/ztypes_linux_amd64.go | 39 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 38 +- .../x/sys/unix/ztypes_linux_arm64.go | 39 +- .../x/sys/unix/ztypes_linux_loong64.go | 39 +- .../x/sys/unix/ztypes_linux_mips.go | 38 +- .../x/sys/unix/ztypes_linux_mips64.go | 39 +- .../x/sys/unix/ztypes_linux_mips64le.go | 39 +- .../x/sys/unix/ztypes_linux_mipsle.go | 38 +- .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 38 +- .../x/sys/unix/ztypes_linux_ppc64.go | 39 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 39 +- .../x/sys/unix/ztypes_linux_riscv64.go | 39 +- .../x/sys/unix/ztypes_linux_s390x.go | 39 +- .../x/sys/unix/ztypes_linux_sparc64.go | 47 +- .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 78 + .../golang.org/x/sys/windows/types_windows.go | 1 + .../x/sys/windows/types_windows_arm.go | 35 - .../x/text/encoding/japanese/iso2022jp.go | 10 + .../x/text/secure/precis/nickname.go | 17 +- .../x/text/secure/precis/profile.go | 8 +- .../golang.org/x/text/unicode/bidi/core.go | 5 +- .../x/text/unicode/norm/composition.go | 42 +- .../x/text/unicode/norm/forminfo.go | 24 +- .../x/text/unicode/norm/normalize.go | 5 +- .../x/text/unicode/norm/tables15.0.0.go | 1884 +- .../x/text/unicode/norm/tables17.0.0.go | 1924 +- .../x/text/unicode/norm/transform.go | 5 +- src/vendor/modules.txt | 72 +- 527 files changed, 111269 insertions(+), 272918 deletions(-) delete mode 100644 src/vendor/github.com/andybalholm/brotli/.gitignore delete mode 100644 src/vendor/github.com/andybalholm/brotli/README.md delete mode 100644 src/vendor/github.com/andybalholm/brotli/backward_references.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/backward_references_hq.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/bit_cost.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/bit_reader.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/bitwriter.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/block_splitter.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/block_splitter_command.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/block_splitter_distance.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/block_splitter_literal.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/brotli_bit_stream.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/cluster.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/cluster_command.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/cluster_distance.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/cluster_literal.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/command.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/compress_fragment.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/constants.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/context.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/decode.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/dictionary.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/dictionary_hash.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/encode.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/encoder.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/encoder_dict.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/encoder_fast.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/entropy_encode.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/entropy_encode_static.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/fast_log.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/find_match_length.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/LICENSE delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/README.md delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/gzip.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/huffman_code.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/token.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/flate/writer.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/h10.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/h5.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/h6.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/hash.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/hash_composite.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/hash_rolling.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/histogram.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/http.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/huffman.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/literal_cost.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/emitter.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/m0.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/m4.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/trio.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/zfast.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/matchfinder/zm.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/memory.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/metablock.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/metablock_command.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/metablock_distance.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/metablock_literal.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/params.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/platform.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/prefix.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/prefix_dec.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/quality.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/reader.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/ringbuffer.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/state.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/static_dict.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/static_dict_lut.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/symbol_list.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/transform.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/utf8_util.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/write_bits.go delete mode 100644 src/vendor/github.com/andybalholm/brotli/writer.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/README.md create mode 100644 src/vendor/github.com/gofiber/fiber/v3/appconfig.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/appconfig/appconfig.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/byterange/byterange.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/cookie/samesite.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/etag/etag.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/fieldname/fieldname.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/headerlist/headerlist.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/headerlookup/headerlookup.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/logtemplate/sanitize.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/mediatype/mediatype.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/origin/origin.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/paramdelim/paramdelim.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/quotedstring/quotedstring.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/internal/urlnorm/urlnorm.go delete mode 100644 src/vendor/github.com/gofiber/fiber/v3/middleware/cors/utils.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/router_filter.go create mode 100644 src/vendor/github.com/gofiber/fiber/v3/router_skip.go create mode 100644 src/vendor/github.com/gofiber/schema/floatfmt.go create mode 100644 src/vendor/github.com/gofiber/schema/values.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/control.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/cut.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/duration.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/headerkey.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/hostport.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/httpdate.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/ipparse.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/jsonstring.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/seq.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/LICENSE create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/ascii.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.s create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/ascii_other.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/block_align_amd64.h create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/byte_frequencies.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/cpu_amd64.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/cpu_other.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.s create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_class.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.s create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_other.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.s create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_other.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memchr_other.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/memmem.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/simd/simd.go create mode 100644 src/vendor/github.com/gofiber/utils/v2/url.go delete mode 100644 src/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go delete mode 100644 src/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go delete mode 100644 src/vendor/github.com/klauspost/compress/flate/regmask_amd64.go delete mode 100644 src/vendor/github.com/klauspost/compress/flate/regmask_other.go create mode 100644 src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.go create mode 100644 src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s create mode 100644 src/vendor/github.com/klauspost/compress/huff0/decompress_asm.go create mode 100644 src/vendor/github.com/klauspost/compress/internal/regmask/regmask.go create mode 100644 src/vendor/github.com/klauspost/compress/internal/regmask/regmask_386.go rename src/vendor/github.com/klauspost/compress/s2/{encode_amd64.go => encode_asm.go} (98%) create mode 100644 src/vendor/github.com/klauspost/compress/s2/encodeblock_arm64.s rename src/vendor/github.com/klauspost/compress/s2/{encodeblock_amd64.go => encodeblock_asm.go} (98%) create mode 100644 src/vendor/github.com/mattn/go-colorable/colorable_windows_palette.go rename src/vendor/github.com/mattn/go-isatty/{isatty_tcgets.go => isatty_tiocgwinsz.go} (62%) create mode 100644 src/vendor/github.com/molecule-man/go-brrr/.gitignore create mode 100644 src/vendor/github.com/molecule-man/go-brrr/.gitmodules create mode 100644 src/vendor/github.com/molecule-man/go-brrr/.golangci.yml create mode 100644 src/vendor/github.com/molecule-man/go-brrr/.pre-commit-config.yaml create mode 100644 src/vendor/github.com/molecule-man/go-brrr/CONTRIBUTING.md rename src/vendor/github.com/{andybalholm/brotli => molecule-man/go-brrr}/LICENSE (79%) create mode 100644 src/vendor/github.com/molecule-man/go-brrr/Makefile create mode 100644 src/vendor/github.com/molecule-man/go-brrr/README.md create mode 100644 src/vendor/github.com/molecule-man/go-brrr/bitreader.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/brotli.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/decode.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/decode_state.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/dictionary.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/doc.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/cmdlut.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/constants.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/context.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/dictionary.bin create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/dictionary.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/doc.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/huffman.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/core/transforms.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/arena.go rename src/vendor/github.com/{andybalholm/brotli/util.go => molecule-man/go-brrr/internal/encoder/assert.go} (81%) create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/backward_match.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/bitwriter.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/block_encoder.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/block_split.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/block_splitter.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/cluster.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/coderange.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/command.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/compound_dict.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/compress_fragment_fast.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/compress_fragment_two_pass.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/compressor.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/constants.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/context_model.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/distance_params.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/encode_state.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/encoder.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/entropy_static.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/fast_compressor.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/fastlog.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/fill.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/findblocks_kernel_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/findblocks_kernel_simd_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/findblocks_kernel_simd_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash10.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash2.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash2u16.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash3.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash3u16.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash4.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash40.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash41.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash42.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash4u16.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash5.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash54.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash5b.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash5b5.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash5b6u16.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash5b8.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash6.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash6b.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash6b5.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hash6b8.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/hasher_pool.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_add_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_add_simd_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_add_simd_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_total_count_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_total_count_simd_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/histogram_total_count_simd_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/huffman_block.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/huffman_encode.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/le_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/le_unsafe.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/literal_cost.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/log2.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/matchlen.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/matchlen_simd_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/matchlen_simd_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/matchlen_simd_other.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/metablock.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/population_cost.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefetch_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefetch_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefetch_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefix2mask_generic.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefix2mask_simd_amd64.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/prefix2mask_simd_amd64.s create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/ringbuffer.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/static_dict.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/static_dict_all.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/static_dict_lut.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/streaming_compressor.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/testseeder.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/zopfli.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/zopfli_cost_model.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/zopfli_hq.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/zopfli_node.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/internal/encoder/zopfli_shortest_path.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/output_chunks.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/reader.go create mode 100644 src/vendor/github.com/molecule-man/go-brrr/writer.go create mode 100644 src/vendor/github.com/tinylib/msgp/msgp/setof/json.go create mode 100644 src/vendor/github.com/valyala/fasthttp/fs_unix.go create mode 100644 src/vendor/github.com/valyala/fasthttp/fs_windows.go create mode 100644 src/vendor/github.com/valyala/fasthttp/swar.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_gc_riscv64.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_netbsd_amd64.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_riscv64.s create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_sparc64.go create mode 100644 src/vendor/golang.org/x/sys/unix/asm_linux_sparc64.s create mode 100644 src/vendor/golang.org/x/sys/unix/ptrace_zos.go create mode 100644 src/vendor/golang.org/x/sys/unix/ptrace_zos_singlestep.go delete mode 100644 src/vendor/golang.org/x/sys/unix/syscall_unix_gc_ppc64x.go delete mode 100644 src/vendor/golang.org/x/sys/windows/types_windows_arm.go diff --git a/src/go.mod b/src/go.mod index 17c1a601..e7b1dd2c 100644 --- a/src/go.mod +++ b/src/go.mod @@ -1,6 +1,6 @@ module github.com/dechristopher/lio -go 1.25.7 +go 1.26.0 require ( github.com/a-h/templ v0.3.1020 @@ -8,7 +8,7 @@ require ( github.com/dechristopher/octad/v2 v2.1.0 github.com/go-webauthn/webauthn v0.17.4 github.com/gofiber/contrib/v3/websocket v1.2.2 - github.com/gofiber/fiber/v3 v3.4.0 + github.com/gofiber/fiber/v3 v3.6.0 github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.10.0 github.com/joho/godotenv v1.5.1 @@ -21,10 +21,10 @@ require ( github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef github.com/valyala/fastjson v1.6.10 - golang.org/x/crypto v0.54.0 + golang.org/x/crypto v0.57.0 golang.org/x/image v0.44.0 - golang.org/x/sync v0.22.0 - golang.org/x/text v0.40.0 + golang.org/x/sync v0.23.0 + golang.org/x/text v0.42.0 ) require ( @@ -33,38 +33,39 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/fasthttp/websocket v1.5.12 // indirect - github.com/fxamacker/cbor/v2 v2.9.2 // indirect + github.com/fxamacker/cbor/v2 v2.9.6 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/go-webauthn/x v0.2.6 // indirect - github.com/gofiber/schema v1.8.3 // indirect - github.com/gofiber/utils/v2 v2.2.0 // indirect + github.com/gofiber/schema v1.8.8 // indirect + github.com/gofiber/utils/v2 v2.6.1 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/google/go-tpm v0.9.8 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/klauspost/compress v1.19.1 // indirect + github.com/klauspost/compress v1.20.1 // indirect github.com/klauspost/cpuid/v2 v2.4.0 // indirect github.com/klauspost/crc32 v1.3.0 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.15 // indirect - github.com/mattn/go-isatty v0.0.23 // indirect + github.com/mattn/go-colorable v0.1.16 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect github.com/mfridman/interpolate v0.0.2 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect + github.com/molecule-man/go-brrr v1.2.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect github.com/rs/xid v1.6.0 // indirect github.com/savsgio/gotils v0.0.0-20250924091648-bce9a52d7761 // indirect github.com/sethvargo/go-retry v0.4.0 // indirect - github.com/tinylib/msgp v1.6.4 // indirect + github.com/tinylib/msgp v1.6.5 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.72.0 // indirect + github.com/valyala/fasthttp v1.75.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/xxh3 v1.1.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/net v0.57.0 // indirect - golang.org/x/sys v0.47.0 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect + golang.org/x/net v0.60.0 // indirect + golang.org/x/sys v0.49.0 // indirect gopkg.in/ini.v1 v1.67.3 // indirect ) diff --git a/src/go.sum b/src/go.sum index e463bac9..ea10790d 100644 --- a/src/go.sum +++ b/src/go.sum @@ -25,6 +25,8 @@ github.com/fasthttp/websocket v1.5.12 h1:e4RGPpWW2HTbL3zV0Y/t7g0ub294LkiuXXUuTOU github.com/fasthttp/websocket v1.5.12/go.mod h1:I+liyL7/4moHojiOgUOIKEWm9EIxHqxZChS+aMFltyg= github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/fxamacker/cbor/v2 v2.9.6 h1:NHZPxuUjJXQjX9itA785y/5NKSlI4HQ+S7noZsmI7hs= +github.com/fxamacker/cbor/v2 v2.9.6/go.mod h1:4EaZp6ClVunETjQ4GHmGNzysDK91Lr+r6Yz6tJqzVCw= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.17.4 h1:KFTSz3R2RYDiUn/0cDi3XTJgFenSG74eKTTHlqWhlxk= @@ -37,14 +39,20 @@ github.com/gofiber/contrib/v3/websocket v1.2.2 h1:kmoD+A0f4btoDSOnZJUHzJyBi1tQqL github.com/gofiber/contrib/v3/websocket v1.2.2/go.mod h1:H0kwFA9iXc5RJca4QqCjWwc2kIpuOGQSZJONqsxwWXI= github.com/gofiber/fiber/v3 v3.4.0 h1:F0aND4vwZF7dR7cbvSwFQQEpBU902XHKWxrLsFBkVqw= github.com/gofiber/fiber/v3 v3.4.0/go.mod h1:nAhJfdxUIJJph2tPWPmqWf8QDIN2iiqQiQf3lENZpdk= +github.com/gofiber/fiber/v3 v3.6.0 h1:dmu6zB1SSXINf1flhgMRVaIOQ08vaZaN8JYVSBJI3fI= +github.com/gofiber/fiber/v3 v3.6.0/go.mod h1:ce/ZWPbiMom+nAEkPv4+NPBEx8b9+MH3g2VV6nvEpgo= github.com/gofiber/schema v1.8.0 h1:NGsC9toPHmj8Xg4KpznuXBzNmHG6V5YV0tXKpKMcmis= github.com/gofiber/schema v1.8.0/go.mod h1:lmbXPQ8hvzXSLkdS2DS7pb4kpunC2Roh7Sj3HMjGfzA= github.com/gofiber/schema v1.8.3 h1:06ZedxIYjngzc0095PYy7uWnFnbRflWFpikvZH61fDc= github.com/gofiber/schema v1.8.3/go.mod h1:jWnnZdhcW1mHyV+VnfRxKJDPNcepJsTZ9RIWxrr32Ng= +github.com/gofiber/schema v1.8.8 h1:md5t65+Z9LttOuj7FdMcQ63D2+6GniT2ganLXwvTJM4= +github.com/gofiber/schema v1.8.8/go.mod h1:Hzf0L/fTPP1IwOAwKipKflm9C2722aebnSKJCMOgb1I= github.com/gofiber/utils/v2 v2.1.1 h1:kGnoGjwEnFW6w0x45W+kLlmMJvqBGkuUA4oMWKn/T/I= github.com/gofiber/utils/v2 v2.1.1/go.mod h1:DdOgEVwQTi8cou/AKWPqhXOR4fHGRVhA/rEWL3IXG7Q= github.com/gofiber/utils/v2 v2.2.0 h1:YSSmCzQponq/f9uSOg2HtXC5qK1Dmor0o6DqaQVz8GE= github.com/gofiber/utils/v2 v2.2.0/go.mod h1:Ieopk6sQh7rbhQ12aBNCJtJuG0gxAg0nz63sFCrrOmE= +github.com/gofiber/utils/v2 v2.6.1 h1:x3zsS/oUQz0ia2Zx8XXtG/7naR5a+/95FRO8mwQ5QQ4= +github.com/gofiber/utils/v2 v2.6.1/go.mod h1:tc9KqdRAQZRD/u0mN2d1ZHROGheSZv+0FcC9cg5OEdw= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -69,6 +77,8 @@ github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2o github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= +github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw= github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= @@ -82,10 +92,14 @@ github.com/looplab/fsm v1.0.3 h1:qtxBsa2onOs0qFOtkqwf5zE0uP0+Te+wlIvXctPKpcw= github.com/looplab/fsm v1.0.3/go.mod h1:PmD3fFvQEIsjMEfvZdrCDZ6y8VwKTwWNjlpEr6IKPO4= github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY= github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.16 h1:+2YjeAe7xP1OQbZW1jERPWWCDLlNqFNCvjiqGiAt84A= +github.com/mattn/go-colorable v0.1.16/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-isatty v0.0.23 h1:cYwCQTQf3HB6xUC+BtyCLZNr7IzbOmoZbmssVNzSyiQ= github.com/mattn/go-isatty v0.0.23/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= @@ -94,6 +108,8 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.2.1 h1:PfBfwvKB/MmqyN8Vb1G9voWisaM9OrLv+WwOvMwS9Dw= github.com/minio/minio-go/v7 v7.2.1/go.mod h1:EU9hENAStx/xXduNdrGO5e4X5vk19NtgB+RIPjZO8o0= +github.com/molecule-man/go-brrr v1.2.0 h1:dOJU45BC3Gc2WXoxAW0rgCAgVuu2gruAOGncfieA0Jw= +github.com/molecule-man/go-brrr v1.2.0/go.mod h1:7ybW6/7gA3oKY45jOfVNjSJDtrr6ea4tzbsTkjmQDC4= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= @@ -142,10 +158,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= +github.com/tinylib/msgp v1.6.5 h1:iAH6XTP7BpzErjBZlujJQXxA+GmRi2YWs6M4KdLtNbE= +github.com/tinylib/msgp v1.6.5/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.72.0 h1:R7kYdoWhn1ye1fVpP+cDHDJwYm3NkwLliwgzJ/Abg7M= github.com/valyala/fasthttp v1.72.0/go.mod h1:zsbLTYqcpIktdQytlVBwIjY9La5d6bs990nBxWg8efk= +github.com/valyala/fasthttp v1.75.0 h1:W3xrvNJHG60j2ZCjxpP8kkB+oPG8kh9/g1n4+3xUwNA= +github.com/valyala/fasthttp v1.75.0/go.mod h1:JiVkPRZU124PuPsreV/s9dZRgG2lRK7wNEikdQ0Rk4s= github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4= github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -164,24 +184,36 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= golang.org/x/image v0.44.0 h1:+tDekMZED9+LrtB3G5xzRggpVh9CARjZqROla3R3R+I= golang.org/x/image v0.44.0/go.mod h1:V8K3KE9KKKE+pLpQDOeN18w9oacNSvy1tDOirTu4xtY= golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o= golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec= golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= +golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= +golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= +golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/src/vendor/github.com/andybalholm/brotli/.gitignore b/src/vendor/github.com/andybalholm/brotli/.gitignore deleted file mode 100644 index 7fd17523..00000000 --- a/src/vendor/github.com/andybalholm/brotli/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cpu.out -brotli.test diff --git a/src/vendor/github.com/andybalholm/brotli/README.md b/src/vendor/github.com/andybalholm/brotli/README.md deleted file mode 100644 index 3494ec47..00000000 --- a/src/vendor/github.com/andybalholm/brotli/README.md +++ /dev/null @@ -1,19 +0,0 @@ -This package is a brotli compressor and decompressor implemented in Go. -It was translated from the reference implementation (https://github.com/google/brotli) -with the `c2go` tool at https://github.com/andybalholm/c2go. - -I am using it in production with https://github.com/andybalholm/redwood. - -API documentation is found at https://pkg.go.dev/github.com/andybalholm/brotli?tab=doc. - -## Roadmap - -I have been working on new compression algorithms (not translated from C) -in the matchfinder package. -You can use them with the NewWriterV2 function. -Currently they give better results than the old implementation -(at least for compressing my test file, Newton’s *Opticks*) -on levels 0 to 9. - -The new APIs are currently considered experimental, -and are not covered by any SemVer compatibility guarantees. diff --git a/src/vendor/github.com/andybalholm/brotli/backward_references.go b/src/vendor/github.com/andybalholm/brotli/backward_references.go deleted file mode 100644 index 008c054d..00000000 --- a/src/vendor/github.com/andybalholm/brotli/backward_references.go +++ /dev/null @@ -1,185 +0,0 @@ -package brotli - -import ( - "sync" -) - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Function to find backward reference copies. */ - -func computeDistanceCode(distance uint, max_distance uint, dist_cache []int) uint { - if distance <= max_distance { - var distance_plus_3 uint = distance + 3 - var offset0 uint = distance_plus_3 - uint(dist_cache[0]) - var offset1 uint = distance_plus_3 - uint(dist_cache[1]) - if distance == uint(dist_cache[0]) { - return 0 - } else if distance == uint(dist_cache[1]) { - return 1 - } else if offset0 < 7 { - return (0x9750468 >> (4 * offset0)) & 0xF - } else if offset1 < 7 { - return (0xFDB1ACE >> (4 * offset1)) & 0xF - } else if distance == uint(dist_cache[2]) { - return 2 - } else if distance == uint(dist_cache[3]) { - return 3 - } - } - - return distance + numDistanceShortCodes - 1 -} - -var hasherSearchResultPool sync.Pool - -func createBackwardReferences(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, hasher hasherHandle, dist_cache []int, last_insert_len *uint, commands *[]command, num_literals *uint) { - var max_backward_limit uint = maxBackwardLimit(params.lgwin) - var insert_length uint = *last_insert_len - var pos_end uint = position + num_bytes - var store_end uint - if num_bytes >= hasher.StoreLookahead() { - store_end = position + num_bytes - hasher.StoreLookahead() + 1 - } else { - store_end = position - } - var random_heuristics_window_size uint = literalSpreeLengthForSparseSearch(params) - var apply_random_heuristics uint = position + random_heuristics_window_size - var gap uint = 0 - /* Set maximum distance, see section 9.1. of the spec. */ - - const kMinScore uint = scoreBase + 100 - - /* For speed up heuristics for random data. */ - - /* Minimum score to accept a backward reference. */ - hasher.PrepareDistanceCache(dist_cache) - sr2, _ := hasherSearchResultPool.Get().(*hasherSearchResult) - if sr2 == nil { - sr2 = &hasherSearchResult{} - } - sr, _ := hasherSearchResultPool.Get().(*hasherSearchResult) - if sr == nil { - sr = &hasherSearchResult{} - } - - for position+hasher.HashTypeLength() < pos_end { - var max_length uint = pos_end - position - var max_distance uint = brotli_min_size_t(position, max_backward_limit) - sr.len = 0 - sr.len_code_delta = 0 - sr.distance = 0 - sr.score = kMinScore - hasher.FindLongestMatch(¶ms.dictionary, ringbuffer, ringbuffer_mask, dist_cache, position, max_length, max_distance, gap, params.dist.max_distance, sr) - if sr.score > kMinScore { - /* Found a match. Let's look for something even better ahead. */ - var delayed_backward_references_in_row int = 0 - max_length-- - for ; ; max_length-- { - var cost_diff_lazy uint = 175 - if params.quality < minQualityForExtensiveReferenceSearch { - sr2.len = brotli_min_size_t(sr.len-1, max_length) - } else { - sr2.len = 0 - } - sr2.len_code_delta = 0 - sr2.distance = 0 - sr2.score = kMinScore - max_distance = brotli_min_size_t(position+1, max_backward_limit) - hasher.FindLongestMatch(¶ms.dictionary, ringbuffer, ringbuffer_mask, dist_cache, position+1, max_length, max_distance, gap, params.dist.max_distance, sr2) - if sr2.score >= sr.score+cost_diff_lazy { - /* Ok, let's just write one byte for now and start a match from the - next byte. */ - position++ - - insert_length++ - *sr = *sr2 - delayed_backward_references_in_row++ - if delayed_backward_references_in_row < 4 && position+hasher.HashTypeLength() < pos_end { - continue - } - } - - break - } - - apply_random_heuristics = position + 2*sr.len + random_heuristics_window_size - max_distance = brotli_min_size_t(position, max_backward_limit) - { - /* The first 16 codes are special short-codes, - and the minimum offset is 1. */ - var distance_code uint = computeDistanceCode(sr.distance, max_distance+gap, dist_cache) - if (sr.distance <= (max_distance + gap)) && distance_code > 0 { - dist_cache[3] = dist_cache[2] - dist_cache[2] = dist_cache[1] - dist_cache[1] = dist_cache[0] - dist_cache[0] = int(sr.distance) - hasher.PrepareDistanceCache(dist_cache) - } - - *commands = append(*commands, makeCommand(¶ms.dist, insert_length, sr.len, sr.len_code_delta, distance_code)) - } - - *num_literals += insert_length - insert_length = 0 - /* Put the hash keys into the table, if there are enough bytes left. - Depending on the hasher implementation, it can push all positions - in the given range or only a subset of them. - Avoid hash poisoning with RLE data. */ - { - var range_start uint = position + 2 - var range_end uint = brotli_min_size_t(position+sr.len, store_end) - if sr.distance < sr.len>>2 { - range_start = brotli_min_size_t(range_end, brotli_max_size_t(range_start, position+sr.len-(sr.distance<<2))) - } - - hasher.StoreRange(ringbuffer, ringbuffer_mask, range_start, range_end) - } - - position += sr.len - } else { - insert_length++ - position++ - - /* If we have not seen matches for a long time, we can skip some - match lookups. Unsuccessful match lookups are very very expensive - and this kind of a heuristic speeds up compression quite - a lot. */ - if position > apply_random_heuristics { - /* Going through uncompressible data, jump. */ - if position > apply_random_heuristics+4*random_heuristics_window_size { - var kMargin uint = brotli_max_size_t(hasher.StoreLookahead()-1, 4) - /* It is quite a long time since we saw a copy, so we assume - that this data is not compressible, and store hashes less - often. Hashes of non compressible data are less likely to - turn out to be useful in the future, too, so we store less of - them to not to flood out the hash table of good compressible - data. */ - - var pos_jump uint = brotli_min_size_t(position+16, pos_end-kMargin) - for ; position < pos_jump; position += 4 { - hasher.Store(ringbuffer, ringbuffer_mask, position) - insert_length += 4 - } - } else { - var kMargin uint = brotli_max_size_t(hasher.StoreLookahead()-1, 2) - var pos_jump uint = brotli_min_size_t(position+8, pos_end-kMargin) - for ; position < pos_jump; position += 2 { - hasher.Store(ringbuffer, ringbuffer_mask, position) - insert_length += 2 - } - } - } - } - } - - insert_length += pos_end - position - *last_insert_len = insert_length - - hasherSearchResultPool.Put(sr) - hasherSearchResultPool.Put(sr2) -} diff --git a/src/vendor/github.com/andybalholm/brotli/backward_references_hq.go b/src/vendor/github.com/andybalholm/brotli/backward_references_hq.go deleted file mode 100644 index 21629c1c..00000000 --- a/src/vendor/github.com/andybalholm/brotli/backward_references_hq.go +++ /dev/null @@ -1,796 +0,0 @@ -package brotli - -import "math" - -type zopfliNode struct { - length uint32 - distance uint32 - dcode_insert_length uint32 - u struct { - cost float32 - next uint32 - shortcut uint32 - } -} - -const maxEffectiveDistanceAlphabetSize = 544 - -const kInfinity float32 = 1.7e38 /* ~= 2 ^ 127 */ - -var kDistanceCacheIndex = []uint32{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1} - -var kDistanceCacheOffset = []int{0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3} - -func initZopfliNodes(array []zopfliNode, length uint) { - var stub zopfliNode - var i uint - stub.length = 1 - stub.distance = 0 - stub.dcode_insert_length = 0 - stub.u.cost = kInfinity - for i = 0; i < length; i++ { - array[i] = stub - } -} - -func zopfliNodeCopyLength(self *zopfliNode) uint32 { - return self.length & 0x1FFFFFF -} - -func zopfliNodeLengthCode(self *zopfliNode) uint32 { - var modifier uint32 = self.length >> 25 - return zopfliNodeCopyLength(self) + 9 - modifier -} - -func zopfliNodeCopyDistance(self *zopfliNode) uint32 { - return self.distance -} - -func zopfliNodeDistanceCode(self *zopfliNode) uint32 { - var short_code uint32 = self.dcode_insert_length >> 27 - if short_code == 0 { - return zopfliNodeCopyDistance(self) + numDistanceShortCodes - 1 - } else { - return short_code - 1 - } -} - -func zopfliNodeCommandLength(self *zopfliNode) uint32 { - return zopfliNodeCopyLength(self) + (self.dcode_insert_length & 0x7FFFFFF) -} - -/* Histogram based cost model for zopflification. */ -type zopfliCostModel struct { - cost_cmd_ [numCommandSymbols]float32 - cost_dist_ []float32 - distance_histogram_size uint32 - literal_costs_ []float32 - min_cost_cmd_ float32 - num_bytes_ uint -} - -func initZopfliCostModel(self *zopfliCostModel, dist *distanceParams, num_bytes uint) { - var distance_histogram_size uint32 = dist.alphabet_size - if distance_histogram_size > maxEffectiveDistanceAlphabetSize { - distance_histogram_size = maxEffectiveDistanceAlphabetSize - } - - self.num_bytes_ = num_bytes - self.literal_costs_ = make([]float32, (num_bytes + 2)) - self.cost_dist_ = make([]float32, (dist.alphabet_size)) - self.distance_histogram_size = distance_histogram_size -} - -func cleanupZopfliCostModel(self *zopfliCostModel) { - self.literal_costs_ = nil - self.cost_dist_ = nil -} - -func setCost(histogram []uint32, histogram_size uint, literal_histogram bool, cost []float32) { - var sum uint = 0 - var missing_symbol_sum uint - var log2sum float32 - var missing_symbol_cost float32 - var i uint - for i = 0; i < histogram_size; i++ { - sum += uint(histogram[i]) - } - - log2sum = float32(fastLog2(sum)) - missing_symbol_sum = sum - if !literal_histogram { - for i = 0; i < histogram_size; i++ { - if histogram[i] == 0 { - missing_symbol_sum++ - } - } - } - - missing_symbol_cost = float32(fastLog2(missing_symbol_sum)) + 2 - for i = 0; i < histogram_size; i++ { - if histogram[i] == 0 { - cost[i] = missing_symbol_cost - continue - } - - /* Shannon bits for this symbol. */ - cost[i] = log2sum - float32(fastLog2(uint(histogram[i]))) - - /* Cannot be coded with less than 1 bit */ - if cost[i] < 1 { - cost[i] = 1 - } - } -} - -func zopfliCostModelSetFromCommands(self *zopfliCostModel, position uint, ringbuffer []byte, ringbuffer_mask uint, commands []command, last_insert_len uint) { - var histogram_literal [numLiteralSymbols]uint32 - var histogram_cmd [numCommandSymbols]uint32 - var histogram_dist [maxEffectiveDistanceAlphabetSize]uint32 - var cost_literal [numLiteralSymbols]float32 - var pos uint = position - last_insert_len - var min_cost_cmd float32 = kInfinity - var cost_cmd []float32 = self.cost_cmd_[:] - var literal_costs []float32 - - histogram_literal = [numLiteralSymbols]uint32{} - histogram_cmd = [numCommandSymbols]uint32{} - histogram_dist = [maxEffectiveDistanceAlphabetSize]uint32{} - - for i := range commands { - var inslength uint = uint(commands[i].insert_len_) - var copylength uint = uint(commandCopyLen(&commands[i])) - var distcode uint = uint(commands[i].dist_prefix_) & 0x3FF - var cmdcode uint = uint(commands[i].cmd_prefix_) - var j uint - - histogram_cmd[cmdcode]++ - if cmdcode >= 128 { - histogram_dist[distcode]++ - } - - for j = 0; j < inslength; j++ { - histogram_literal[ringbuffer[(pos+j)&ringbuffer_mask]]++ - } - - pos += inslength + copylength - } - - setCost(histogram_literal[:], numLiteralSymbols, true, cost_literal[:]) - setCost(histogram_cmd[:], numCommandSymbols, false, cost_cmd) - setCost(histogram_dist[:], uint(self.distance_histogram_size), false, self.cost_dist_) - - for i := 0; i < numCommandSymbols; i++ { - min_cost_cmd = brotli_min_float(min_cost_cmd, cost_cmd[i]) - } - - self.min_cost_cmd_ = min_cost_cmd - { - literal_costs = self.literal_costs_ - var literal_carry float32 = 0.0 - num_bytes := int(self.num_bytes_) - literal_costs[0] = 0.0 - for i := 0; i < num_bytes; i++ { - literal_carry += cost_literal[ringbuffer[(position+uint(i))&ringbuffer_mask]] - literal_costs[i+1] = literal_costs[i] + literal_carry - literal_carry -= literal_costs[i+1] - literal_costs[i] - } - } -} - -func zopfliCostModelSetFromLiteralCosts(self *zopfliCostModel, position uint, ringbuffer []byte, ringbuffer_mask uint) { - var literal_costs []float32 = self.literal_costs_ - var literal_carry float32 = 0.0 - var cost_dist []float32 = self.cost_dist_ - var cost_cmd []float32 = self.cost_cmd_[:] - var num_bytes uint = self.num_bytes_ - var i uint - estimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask, ringbuffer, literal_costs[1:]) - literal_costs[0] = 0.0 - for i = 0; i < num_bytes; i++ { - literal_carry += literal_costs[i+1] - literal_costs[i+1] = literal_costs[i] + literal_carry - literal_carry -= literal_costs[i+1] - literal_costs[i] - } - - for i = 0; i < numCommandSymbols; i++ { - cost_cmd[i] = float32(fastLog2(uint(11 + uint32(i)))) - } - - for i = 0; uint32(i) < self.distance_histogram_size; i++ { - cost_dist[i] = float32(fastLog2(uint(20 + uint32(i)))) - } - - self.min_cost_cmd_ = float32(fastLog2(11)) -} - -func zopfliCostModelGetCommandCost(self *zopfliCostModel, cmdcode uint16) float32 { - return self.cost_cmd_[cmdcode] -} - -func zopfliCostModelGetDistanceCost(self *zopfliCostModel, distcode uint) float32 { - return self.cost_dist_[distcode] -} - -func zopfliCostModelGetLiteralCosts(self *zopfliCostModel, from uint, to uint) float32 { - return self.literal_costs_[to] - self.literal_costs_[from] -} - -func zopfliCostModelGetMinCostCmd(self *zopfliCostModel) float32 { - return self.min_cost_cmd_ -} - -/* REQUIRES: len >= 2, start_pos <= pos */ -/* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */ -/* Maintains the "ZopfliNode array invariant". */ -func updateZopfliNode(nodes []zopfliNode, pos uint, start_pos uint, len uint, len_code uint, dist uint, short_code uint, cost float32) { - var next *zopfliNode = &nodes[pos+len] - next.length = uint32(len | (len+9-len_code)<<25) - next.distance = uint32(dist) - next.dcode_insert_length = uint32(short_code<<27 | (pos - start_pos)) - next.u.cost = cost -} - -type posData struct { - pos uint - distance_cache [4]int - costdiff float32 - cost float32 -} - -/* Maintains the smallest 8 cost difference together with their positions */ -type startPosQueue struct { - q_ [8]posData - idx_ uint -} - -func initStartPosQueue(self *startPosQueue) { - self.idx_ = 0 -} - -func startPosQueueSize(self *startPosQueue) uint { - return brotli_min_size_t(self.idx_, 8) -} - -func startPosQueuePush(self *startPosQueue, posdata *posData) { - var offset uint = ^(self.idx_) & 7 - self.idx_++ - var len uint = startPosQueueSize(self) - var i uint - var q []posData = self.q_[:] - q[offset] = *posdata - - /* Restore the sorted order. In the list of |len| items at most |len - 1| - adjacent element comparisons / swaps are required. */ - for i = 1; i < len; i++ { - if q[offset&7].costdiff > q[(offset+1)&7].costdiff { - var tmp posData = q[offset&7] - q[offset&7] = q[(offset+1)&7] - q[(offset+1)&7] = tmp - } - - offset++ - } -} - -func startPosQueueAt(self *startPosQueue, k uint) *posData { - return &self.q_[(k-self.idx_)&7] -} - -/* Returns the minimum possible copy length that can improve the cost of any */ -/* future position. */ -func computeMinimumCopyLength(start_cost float32, nodes []zopfliNode, num_bytes uint, pos uint) uint { - var min_cost float32 = start_cost - var len uint = 2 - var next_len_bucket uint = 4 - /* Compute the minimum possible cost of reaching any future position. */ - - var next_len_offset uint = 10 - for pos+len <= num_bytes && nodes[pos+len].u.cost <= min_cost { - /* We already reached (pos + len) with no more cost than the minimum - possible cost of reaching anything from this pos, so there is no point in - looking for lengths <= len. */ - len++ - - if len == next_len_offset { - /* We reached the next copy length code bucket, so we add one more - extra bit to the minimum cost. */ - min_cost += 1.0 - - next_len_offset += next_len_bucket - next_len_bucket *= 2 - } - } - - return uint(len) -} - -/* REQUIRES: nodes[pos].cost < kInfinity - REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ -func computeDistanceShortcut(block_start uint, pos uint, max_backward_limit uint, gap uint, nodes []zopfliNode) uint32 { - var clen uint = uint(zopfliNodeCopyLength(&nodes[pos])) - var ilen uint = uint(nodes[pos].dcode_insert_length & 0x7FFFFFF) - var dist uint = uint(zopfliNodeCopyDistance(&nodes[pos])) - - /* Since |block_start + pos| is the end position of the command, the copy part - starts from |block_start + pos - clen|. Distances that are greater than - this or greater than |max_backward_limit| + |gap| are static dictionary - references, and do not update the last distances. - Also distance code 0 (last distance) does not update the last distances. */ - if pos == 0 { - return 0 - } else if dist+clen <= block_start+pos+gap && dist <= max_backward_limit+gap && zopfliNodeDistanceCode(&nodes[pos]) > 0 { - return uint32(pos) - } else { - return nodes[pos-clen-ilen].u.shortcut - } -} - -/* Fills in dist_cache[0..3] with the last four distances (as defined by - Section 4. of the Spec) that would be used at (block_start + pos) if we - used the shortest path of commands from block_start, computed from - nodes[0..pos]. The last four distances at block_start are in - starting_dist_cache[0..3]. - REQUIRES: nodes[pos].cost < kInfinity - REQUIRES: nodes[0..pos] satisfies that "ZopfliNode array invariant". */ -func computeDistanceCache(pos uint, starting_dist_cache []int, nodes []zopfliNode, dist_cache []int) { - var idx int = 0 - var p uint = uint(nodes[pos].u.shortcut) - for idx < 4 && p > 0 { - var ilen uint = uint(nodes[p].dcode_insert_length & 0x7FFFFFF) - var clen uint = uint(zopfliNodeCopyLength(&nodes[p])) - var dist uint = uint(zopfliNodeCopyDistance(&nodes[p])) - dist_cache[idx] = int(dist) - idx++ - - /* Because of prerequisite, p >= clen + ilen >= 2. */ - p = uint(nodes[p-clen-ilen].u.shortcut) - } - - for ; idx < 4; idx++ { - dist_cache[idx] = starting_dist_cache[0] - starting_dist_cache = starting_dist_cache[1:] - } -} - -/* Maintains "ZopfliNode array invariant" and pushes node to the queue, if it - is eligible. */ -func evaluateNode(block_start uint, pos uint, max_backward_limit uint, gap uint, starting_dist_cache []int, model *zopfliCostModel, queue *startPosQueue, nodes []zopfliNode) { - /* Save cost, because ComputeDistanceCache invalidates it. */ - var node_cost float32 = nodes[pos].u.cost - nodes[pos].u.shortcut = computeDistanceShortcut(block_start, pos, max_backward_limit, gap, nodes) - if node_cost <= zopfliCostModelGetLiteralCosts(model, 0, pos) { - var posdata posData - posdata.pos = pos - posdata.cost = node_cost - posdata.costdiff = node_cost - zopfliCostModelGetLiteralCosts(model, 0, pos) - computeDistanceCache(pos, starting_dist_cache, nodes, posdata.distance_cache[:]) - startPosQueuePush(queue, &posdata) - } -} - -/* Returns longest copy length. */ -func updateNodes(num_bytes uint, block_start uint, pos uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, max_backward_limit uint, starting_dist_cache []int, num_matches uint, matches []backwardMatch, model *zopfliCostModel, queue *startPosQueue, nodes []zopfliNode) uint { - var cur_ix uint = block_start + pos - var cur_ix_masked uint = cur_ix & ringbuffer_mask - var max_distance uint = brotli_min_size_t(cur_ix, max_backward_limit) - var max_len uint = num_bytes - pos - var max_zopfli_len uint = maxZopfliLen(params) - var max_iters uint = maxZopfliCandidates(params) - var min_len uint - var result uint = 0 - var k uint - var gap uint = 0 - - evaluateNode(block_start, pos, max_backward_limit, gap, starting_dist_cache, model, queue, nodes) - { - var posdata *posData = startPosQueueAt(queue, 0) - var min_cost float32 = (posdata.cost + zopfliCostModelGetMinCostCmd(model) + zopfliCostModelGetLiteralCosts(model, posdata.pos, pos)) - min_len = computeMinimumCopyLength(min_cost, nodes, num_bytes, pos) - } - - /* Go over the command starting positions in order of increasing cost - difference. */ - for k = 0; k < max_iters && k < startPosQueueSize(queue); k++ { - var posdata *posData = startPosQueueAt(queue, k) - var start uint = posdata.pos - var inscode uint16 = getInsertLengthCode(pos - start) - var start_costdiff float32 = posdata.costdiff - var base_cost float32 = start_costdiff + float32(getInsertExtra(inscode)) + zopfliCostModelGetLiteralCosts(model, 0, pos) - var best_len uint = min_len - 1 - var j uint = 0 - /* Look for last distance matches using the distance cache from this - starting position. */ - for ; j < numDistanceShortCodes && best_len < max_len; j++ { - var idx uint = uint(kDistanceCacheIndex[j]) - var backward uint = uint(posdata.distance_cache[idx] + kDistanceCacheOffset[j]) - var prev_ix uint = cur_ix - backward - var len uint = 0 - var continuation byte = ringbuffer[cur_ix_masked+best_len] - if cur_ix_masked+best_len > ringbuffer_mask { - break - } - - if backward > max_distance+gap { - /* Word dictionary -> ignore. */ - continue - } - - if backward <= max_distance { - /* Regular backward reference. */ - if prev_ix >= cur_ix { - continue - } - - prev_ix &= ringbuffer_mask - if prev_ix+best_len > ringbuffer_mask || continuation != ringbuffer[prev_ix+best_len] { - continue - } - - len = findMatchLengthWithLimit(ringbuffer[prev_ix:], ringbuffer[cur_ix_masked:], max_len) - } else { - continue - } - { - var dist_cost float32 = base_cost + zopfliCostModelGetDistanceCost(model, j) - var l uint - for l = best_len + 1; l <= len; l++ { - var copycode uint16 = getCopyLengthCode(l) - var cmdcode uint16 = combineLengthCodes(inscode, copycode, j == 0) - var tmp float32 - if cmdcode < 128 { - tmp = base_cost - } else { - tmp = dist_cost - } - var cost float32 = tmp + float32(getCopyExtra(copycode)) + zopfliCostModelGetCommandCost(model, cmdcode) - if cost < nodes[pos+l].u.cost { - updateZopfliNode(nodes, pos, start, l, l, backward, j+1, cost) - result = brotli_max_size_t(result, l) - } - - best_len = l - } - } - } - - /* At higher iterations look only for new last distance matches, since - looking only for new command start positions with the same distances - does not help much. */ - if k >= 2 { - continue - } - { - /* Loop through all possible copy lengths at this position. */ - var len uint = min_len - for j = 0; j < num_matches; j++ { - var match backwardMatch = matches[j] - var dist uint = uint(match.distance) - var is_dictionary_match bool = (dist > max_distance+gap) - var dist_code uint = dist + numDistanceShortCodes - 1 - var dist_symbol uint16 - var distextra uint32 - var distnumextra uint32 - var dist_cost float32 - var max_match_len uint - /* We already tried all possible last distance matches, so we can use - normal distance code here. */ - prefixEncodeCopyDistance(dist_code, uint(params.dist.num_direct_distance_codes), uint(params.dist.distance_postfix_bits), &dist_symbol, &distextra) - - distnumextra = uint32(dist_symbol) >> 10 - dist_cost = base_cost + float32(distnumextra) + zopfliCostModelGetDistanceCost(model, uint(dist_symbol)&0x3FF) - - /* Try all copy lengths up until the maximum copy length corresponding - to this distance. If the distance refers to the static dictionary, or - the maximum length is long enough, try only one maximum length. */ - max_match_len = backwardMatchLength(&match) - - if len < max_match_len && (is_dictionary_match || max_match_len > max_zopfli_len) { - len = max_match_len - } - - for ; len <= max_match_len; len++ { - var len_code uint - if is_dictionary_match { - len_code = backwardMatchLengthCode(&match) - } else { - len_code = len - } - var copycode uint16 = getCopyLengthCode(len_code) - var cmdcode uint16 = combineLengthCodes(inscode, copycode, false) - var cost float32 = dist_cost + float32(getCopyExtra(copycode)) + zopfliCostModelGetCommandCost(model, cmdcode) - if cost < nodes[pos+len].u.cost { - updateZopfliNode(nodes, pos, start, uint(len), len_code, dist, 0, cost) - if len > result { - result = len - } - } - } - } - } - } - - return result -} - -func computeShortestPathFromNodes(num_bytes uint, nodes []zopfliNode) uint { - var index uint = num_bytes - var num_commands uint = 0 - for nodes[index].dcode_insert_length&0x7FFFFFF == 0 && nodes[index].length == 1 { - index-- - } - nodes[index].u.next = math.MaxUint32 - for index != 0 { - var len uint = uint(zopfliNodeCommandLength(&nodes[index])) - index -= uint(len) - nodes[index].u.next = uint32(len) - num_commands++ - } - - return num_commands -} - -/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ -func zopfliCreateCommands(num_bytes uint, block_start uint, nodes []zopfliNode, dist_cache []int, last_insert_len *uint, params *encoderParams, commands *[]command, num_literals *uint) { - var max_backward_limit uint = maxBackwardLimit(params.lgwin) - var pos uint = 0 - var offset uint32 = nodes[0].u.next - var i uint - var gap uint = 0 - for i = 0; offset != math.MaxUint32; i++ { - var next *zopfliNode = &nodes[uint32(pos)+offset] - var copy_length uint = uint(zopfliNodeCopyLength(next)) - var insert_length uint = uint(next.dcode_insert_length & 0x7FFFFFF) - pos += insert_length - offset = next.u.next - if i == 0 { - insert_length += *last_insert_len - *last_insert_len = 0 - } - { - var distance uint = uint(zopfliNodeCopyDistance(next)) - var len_code uint = uint(zopfliNodeLengthCode(next)) - var max_distance uint = brotli_min_size_t(block_start+pos, max_backward_limit) - var is_dictionary bool = (distance > max_distance+gap) - var dist_code uint = uint(zopfliNodeDistanceCode(next)) - *commands = append(*commands, makeCommand(¶ms.dist, insert_length, copy_length, int(len_code)-int(copy_length), dist_code)) - - if !is_dictionary && dist_code > 0 { - dist_cache[3] = dist_cache[2] - dist_cache[2] = dist_cache[1] - dist_cache[1] = dist_cache[0] - dist_cache[0] = int(distance) - } - } - - *num_literals += insert_length - pos += copy_length - } - - *last_insert_len += num_bytes - pos -} - -func zopfliIterate(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, gap uint, dist_cache []int, model *zopfliCostModel, num_matches []uint32, matches []backwardMatch, nodes []zopfliNode) uint { - var max_backward_limit uint = maxBackwardLimit(params.lgwin) - var max_zopfli_len uint = maxZopfliLen(params) - var queue startPosQueue - var cur_match_pos uint = 0 - var i uint - nodes[0].length = 0 - nodes[0].u.cost = 0 - initStartPosQueue(&queue) - for i = 0; i+3 < num_bytes; i++ { - var skip uint = updateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask, params, max_backward_limit, dist_cache, uint(num_matches[i]), matches[cur_match_pos:], model, &queue, nodes) - if skip < longCopyQuickStep { - skip = 0 - } - cur_match_pos += uint(num_matches[i]) - if num_matches[i] == 1 && backwardMatchLength(&matches[cur_match_pos-1]) > max_zopfli_len { - skip = brotli_max_size_t(backwardMatchLength(&matches[cur_match_pos-1]), skip) - } - - if skip > 1 { - skip-- - for skip != 0 { - i++ - if i+3 >= num_bytes { - break - } - evaluateNode(position, i, max_backward_limit, gap, dist_cache, model, &queue, nodes) - cur_match_pos += uint(num_matches[i]) - skip-- - } - } - } - - return computeShortestPathFromNodes(num_bytes, nodes) -} - -/* Computes the shortest path of commands from position to at most - position + num_bytes. - - On return, path->size() is the number of commands found and path[i] is the - length of the i-th command (copy length plus insert length). - Note that the sum of the lengths of all commands can be less than num_bytes. - - On return, the nodes[0..num_bytes] array will have the following - "ZopfliNode array invariant": - For each i in [1..num_bytes], if nodes[i].cost < kInfinity, then - (1) nodes[i].copy_length() >= 2 - (2) nodes[i].command_length() <= i and - (3) nodes[i - nodes[i].command_length()].cost < kInfinity - - REQUIRES: nodes != nil and len(nodes) >= num_bytes + 1 */ -func zopfliComputeShortestPath(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, dist_cache []int, hasher *h10, nodes []zopfliNode) uint { - var max_backward_limit uint = maxBackwardLimit(params.lgwin) - var max_zopfli_len uint = maxZopfliLen(params) - var model zopfliCostModel - var queue startPosQueue - var matches [2 * (maxNumMatchesH10 + 64)]backwardMatch - var store_end uint - if num_bytes >= hasher.StoreLookahead() { - store_end = position + num_bytes - hasher.StoreLookahead() + 1 - } else { - store_end = position - } - var i uint - var gap uint = 0 - var lz_matches_offset uint = 0 - nodes[0].length = 0 - nodes[0].u.cost = 0 - initZopfliCostModel(&model, ¶ms.dist, num_bytes) - zopfliCostModelSetFromLiteralCosts(&model, position, ringbuffer, ringbuffer_mask) - initStartPosQueue(&queue) - for i = 0; i+hasher.HashTypeLength()-1 < num_bytes; i++ { - var pos uint = position + i - var max_distance uint = brotli_min_size_t(pos, max_backward_limit) - var skip uint - var num_matches uint - num_matches = findAllMatchesH10(hasher, ¶ms.dictionary, ringbuffer, ringbuffer_mask, pos, num_bytes-i, max_distance, gap, params, matches[lz_matches_offset:]) - if num_matches > 0 && backwardMatchLength(&matches[num_matches-1]) > max_zopfli_len { - matches[0] = matches[num_matches-1] - num_matches = 1 - } - - skip = updateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask, params, max_backward_limit, dist_cache, num_matches, matches[:], &model, &queue, nodes) - if skip < longCopyQuickStep { - skip = 0 - } - if num_matches == 1 && backwardMatchLength(&matches[0]) > max_zopfli_len { - skip = brotli_max_size_t(backwardMatchLength(&matches[0]), skip) - } - - if skip > 1 { - /* Add the tail of the copy to the hasher. */ - hasher.StoreRange(ringbuffer, ringbuffer_mask, pos+1, brotli_min_size_t(pos+skip, store_end)) - - skip-- - for skip != 0 { - i++ - if i+hasher.HashTypeLength()-1 >= num_bytes { - break - } - evaluateNode(position, i, max_backward_limit, gap, dist_cache, &model, &queue, nodes) - skip-- - } - } - } - - cleanupZopfliCostModel(&model) - return computeShortestPathFromNodes(num_bytes, nodes) -} - -func createZopfliBackwardReferences(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, hasher *h10, dist_cache []int, last_insert_len *uint, commands *[]command, num_literals *uint) { - var nodes []zopfliNode - nodes = make([]zopfliNode, (num_bytes + 1)) - initZopfliNodes(nodes, num_bytes+1) - zopfliComputeShortestPath(num_bytes, position, ringbuffer, ringbuffer_mask, params, dist_cache, hasher, nodes) - zopfliCreateCommands(num_bytes, position, nodes, dist_cache, last_insert_len, params, commands, num_literals) - nodes = nil -} - -func createHqZopfliBackwardReferences(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint, params *encoderParams, hasher hasherHandle, dist_cache []int, last_insert_len *uint, commands *[]command, num_literals *uint) { - var max_backward_limit uint = maxBackwardLimit(params.lgwin) - var num_matches []uint32 = make([]uint32, num_bytes) - var matches_size uint = 4 * num_bytes - var store_end uint - if num_bytes >= hasher.StoreLookahead() { - store_end = position + num_bytes - hasher.StoreLookahead() + 1 - } else { - store_end = position - } - var cur_match_pos uint = 0 - var i uint - var orig_num_literals uint - var orig_last_insert_len uint - var orig_dist_cache [4]int - var orig_num_commands int - var model zopfliCostModel - var nodes []zopfliNode - var matches []backwardMatch = make([]backwardMatch, matches_size) - var gap uint = 0 - var shadow_matches uint = 0 - var new_array []backwardMatch - for i = 0; i+hasher.HashTypeLength()-1 < num_bytes; i++ { - var pos uint = position + i - var max_distance uint = brotli_min_size_t(pos, max_backward_limit) - var max_length uint = num_bytes - i - var num_found_matches uint - var cur_match_end uint - var j uint - - /* Ensure that we have enough free slots. */ - if matches_size < cur_match_pos+maxNumMatchesH10+shadow_matches { - var new_size uint = matches_size - if new_size == 0 { - new_size = cur_match_pos + maxNumMatchesH10 + shadow_matches - } - - for new_size < cur_match_pos+maxNumMatchesH10+shadow_matches { - new_size *= 2 - } - - new_array = make([]backwardMatch, new_size) - if matches_size != 0 { - copy(new_array, matches[:matches_size]) - } - - matches = new_array - matches_size = new_size - } - - num_found_matches = findAllMatchesH10(hasher.(*h10), ¶ms.dictionary, ringbuffer, ringbuffer_mask, pos, max_length, max_distance, gap, params, matches[cur_match_pos+shadow_matches:]) - cur_match_end = cur_match_pos + num_found_matches - for j = cur_match_pos; j+1 < cur_match_end; j++ { - assert(backwardMatchLength(&matches[j]) <= backwardMatchLength(&matches[j+1])) - } - - num_matches[i] = uint32(num_found_matches) - if num_found_matches > 0 { - var match_len uint = backwardMatchLength(&matches[cur_match_end-1]) - if match_len > maxZopfliLenQuality11 { - var skip uint = match_len - 1 - matches[cur_match_pos] = matches[cur_match_end-1] - cur_match_pos++ - num_matches[i] = 1 - - /* Add the tail of the copy to the hasher. */ - hasher.StoreRange(ringbuffer, ringbuffer_mask, pos+1, brotli_min_size_t(pos+match_len, store_end)) - var pos uint = i - for i := 0; i < int(skip); i++ { - num_matches[pos+1:][i] = 0 - } - i += skip - } else { - cur_match_pos = cur_match_end - } - } - } - - orig_num_literals = *num_literals - orig_last_insert_len = *last_insert_len - copy(orig_dist_cache[:], dist_cache[:4]) - orig_num_commands = len(*commands) - nodes = make([]zopfliNode, (num_bytes + 1)) - initZopfliCostModel(&model, ¶ms.dist, num_bytes) - for i = 0; i < 2; i++ { - initZopfliNodes(nodes, num_bytes+1) - if i == 0 { - zopfliCostModelSetFromLiteralCosts(&model, position, ringbuffer, ringbuffer_mask) - } else { - zopfliCostModelSetFromCommands(&model, position, ringbuffer, ringbuffer_mask, (*commands)[orig_num_commands:], orig_last_insert_len) - } - - *commands = (*commands)[:orig_num_commands] - *num_literals = orig_num_literals - *last_insert_len = orig_last_insert_len - copy(dist_cache, orig_dist_cache[:4]) - zopfliIterate(num_bytes, position, ringbuffer, ringbuffer_mask, params, gap, dist_cache, &model, num_matches, matches, nodes) - zopfliCreateCommands(num_bytes, position, nodes, dist_cache, last_insert_len, params, commands, num_literals) - } - - cleanupZopfliCostModel(&model) - nodes = nil - matches = nil - num_matches = nil -} diff --git a/src/vendor/github.com/andybalholm/brotli/bit_cost.go b/src/vendor/github.com/andybalholm/brotli/bit_cost.go deleted file mode 100644 index 0005fc15..00000000 --- a/src/vendor/github.com/andybalholm/brotli/bit_cost.go +++ /dev/null @@ -1,436 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions to estimate the bit cost of Huffman trees. */ -func shannonEntropy(population []uint32, size uint, total *uint) float64 { - var sum uint = 0 - var retval float64 = 0 - var population_end []uint32 = population[size:] - var p uint - for -cap(population) < -cap(population_end) { - p = uint(population[0]) - population = population[1:] - sum += p - retval -= float64(p) * fastLog2(p) - } - - if sum != 0 { - retval += float64(sum) * fastLog2(sum) - } - *total = sum - return retval -} - -func bitsEntropy(population []uint32, size uint) float64 { - var sum uint - var retval float64 = shannonEntropy(population, size, &sum) - if retval < float64(sum) { - /* At least one bit per literal is needed. */ - retval = float64(sum) - } - - return retval -} - -const kOneSymbolHistogramCost float64 = 12 -const kTwoSymbolHistogramCost float64 = 20 -const kThreeSymbolHistogramCost float64 = 28 -const kFourSymbolHistogramCost float64 = 37 - -func populationCostLiteral(histogram *histogramLiteral) float64 { - var data_size uint = histogramDataSizeLiteral() - var count int = 0 - var s [5]uint - var bits float64 = 0.0 - var i uint - if histogram.total_count_ == 0 { - return kOneSymbolHistogramCost - } - - for i = 0; i < data_size; i++ { - if histogram.data_[i] > 0 { - s[count] = i - count++ - if count > 4 { - break - } - } - } - - if count == 1 { - return kOneSymbolHistogramCost - } - - if count == 2 { - return kTwoSymbolHistogramCost + float64(histogram.total_count_) - } - - if count == 3 { - var histo0 uint32 = histogram.data_[s[0]] - var histo1 uint32 = histogram.data_[s[1]] - var histo2 uint32 = histogram.data_[s[2]] - var histomax uint32 = brotli_max_uint32_t(histo0, brotli_max_uint32_t(histo1, histo2)) - return kThreeSymbolHistogramCost + 2*(float64(histo0)+float64(histo1)+float64(histo2)) - float64(histomax) - } - - if count == 4 { - var histo [4]uint32 - var h23 uint32 - var histomax uint32 - for i = 0; i < 4; i++ { - histo[i] = histogram.data_[s[i]] - } - - /* Sort */ - for i = 0; i < 4; i++ { - var j uint - for j = i + 1; j < 4; j++ { - if histo[j] > histo[i] { - var tmp uint32 = histo[j] - histo[j] = histo[i] - histo[i] = tmp - } - } - } - - h23 = histo[2] + histo[3] - histomax = brotli_max_uint32_t(h23, histo[0]) - return kFourSymbolHistogramCost + 3*float64(h23) + 2*(float64(histo[0])+float64(histo[1])) - float64(histomax) - } - { - var max_depth uint = 1 - var depth_histo = [codeLengthCodes]uint32{0} - /* In this loop we compute the entropy of the histogram and simultaneously - build a simplified histogram of the code length codes where we use the - zero repeat code 17, but we don't use the non-zero repeat code 16. */ - - var log2total float64 = fastLog2(histogram.total_count_) - for i = 0; i < data_size; { - if histogram.data_[i] > 0 { - var log2p float64 = log2total - fastLog2(uint(histogram.data_[i])) - /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = - = log2(total_count) - log2(count(symbol)) */ - - var depth uint = uint(log2p + 0.5) - /* Approximate the bit depth by round(-log2(P(symbol))) */ - bits += float64(histogram.data_[i]) * log2p - - if depth > 15 { - depth = 15 - } - - if depth > max_depth { - max_depth = depth - } - - depth_histo[depth]++ - i++ - } else { - var reps uint32 = 1 - /* Compute the run length of zeros and add the appropriate number of 0 - and 17 code length codes to the code length code histogram. */ - - var k uint - for k = i + 1; k < data_size && histogram.data_[k] == 0; k++ { - reps++ - } - - i += uint(reps) - if i == data_size { - /* Don't add any cost for the last zero run, since these are encoded - only implicitly. */ - break - } - - if reps < 3 { - depth_histo[0] += reps - } else { - reps -= 2 - for reps > 0 { - depth_histo[repeatZeroCodeLength]++ - - /* Add the 3 extra bits for the 17 code length code. */ - bits += 3 - - reps >>= 3 - } - } - } - } - - /* Add the estimated encoding cost of the code length code histogram. */ - bits += float64(18 + 2*max_depth) - - /* Add the entropy of the code length code histogram. */ - bits += bitsEntropy(depth_histo[:], codeLengthCodes) - } - - return bits -} - -func populationCostCommand(histogram *histogramCommand) float64 { - var data_size uint = histogramDataSizeCommand() - var count int = 0 - var s [5]uint - var bits float64 = 0.0 - var i uint - if histogram.total_count_ == 0 { - return kOneSymbolHistogramCost - } - - for i = 0; i < data_size; i++ { - if histogram.data_[i] > 0 { - s[count] = i - count++ - if count > 4 { - break - } - } - } - - if count == 1 { - return kOneSymbolHistogramCost - } - - if count == 2 { - return kTwoSymbolHistogramCost + float64(histogram.total_count_) - } - - if count == 3 { - var histo0 uint32 = histogram.data_[s[0]] - var histo1 uint32 = histogram.data_[s[1]] - var histo2 uint32 = histogram.data_[s[2]] - var histomax uint32 = brotli_max_uint32_t(histo0, brotli_max_uint32_t(histo1, histo2)) - return kThreeSymbolHistogramCost + 2*(float64(histo0)+float64(histo1)+float64(histo2)) - float64(histomax) - } - - if count == 4 { - var histo [4]uint32 - var h23 uint32 - var histomax uint32 - for i = 0; i < 4; i++ { - histo[i] = histogram.data_[s[i]] - } - - /* Sort */ - for i = 0; i < 4; i++ { - var j uint - for j = i + 1; j < 4; j++ { - if histo[j] > histo[i] { - var tmp uint32 = histo[j] - histo[j] = histo[i] - histo[i] = tmp - } - } - } - - h23 = histo[2] + histo[3] - histomax = brotli_max_uint32_t(h23, histo[0]) - return kFourSymbolHistogramCost + 3*float64(h23) + 2*(float64(histo[0])+float64(histo[1])) - float64(histomax) - } - { - var max_depth uint = 1 - var depth_histo = [codeLengthCodes]uint32{0} - /* In this loop we compute the entropy of the histogram and simultaneously - build a simplified histogram of the code length codes where we use the - zero repeat code 17, but we don't use the non-zero repeat code 16. */ - - var log2total float64 = fastLog2(histogram.total_count_) - for i = 0; i < data_size; { - if histogram.data_[i] > 0 { - var log2p float64 = log2total - fastLog2(uint(histogram.data_[i])) - /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = - = log2(total_count) - log2(count(symbol)) */ - - var depth uint = uint(log2p + 0.5) - /* Approximate the bit depth by round(-log2(P(symbol))) */ - bits += float64(histogram.data_[i]) * log2p - - if depth > 15 { - depth = 15 - } - - if depth > max_depth { - max_depth = depth - } - - depth_histo[depth]++ - i++ - } else { - var reps uint32 = 1 - /* Compute the run length of zeros and add the appropriate number of 0 - and 17 code length codes to the code length code histogram. */ - - var k uint - for k = i + 1; k < data_size && histogram.data_[k] == 0; k++ { - reps++ - } - - i += uint(reps) - if i == data_size { - /* Don't add any cost for the last zero run, since these are encoded - only implicitly. */ - break - } - - if reps < 3 { - depth_histo[0] += reps - } else { - reps -= 2 - for reps > 0 { - depth_histo[repeatZeroCodeLength]++ - - /* Add the 3 extra bits for the 17 code length code. */ - bits += 3 - - reps >>= 3 - } - } - } - } - - /* Add the estimated encoding cost of the code length code histogram. */ - bits += float64(18 + 2*max_depth) - - /* Add the entropy of the code length code histogram. */ - bits += bitsEntropy(depth_histo[:], codeLengthCodes) - } - - return bits -} - -func populationCostDistance(histogram *histogramDistance) float64 { - var data_size uint = histogramDataSizeDistance() - var count int = 0 - var s [5]uint - var bits float64 = 0.0 - var i uint - if histogram.total_count_ == 0 { - return kOneSymbolHistogramCost - } - - for i = 0; i < data_size; i++ { - if histogram.data_[i] > 0 { - s[count] = i - count++ - if count > 4 { - break - } - } - } - - if count == 1 { - return kOneSymbolHistogramCost - } - - if count == 2 { - return kTwoSymbolHistogramCost + float64(histogram.total_count_) - } - - if count == 3 { - var histo0 uint32 = histogram.data_[s[0]] - var histo1 uint32 = histogram.data_[s[1]] - var histo2 uint32 = histogram.data_[s[2]] - var histomax uint32 = brotli_max_uint32_t(histo0, brotli_max_uint32_t(histo1, histo2)) - return kThreeSymbolHistogramCost + 2*(float64(histo0)+float64(histo1)+float64(histo2)) - float64(histomax) - } - - if count == 4 { - var histo [4]uint32 - var h23 uint32 - var histomax uint32 - for i = 0; i < 4; i++ { - histo[i] = histogram.data_[s[i]] - } - - /* Sort */ - for i = 0; i < 4; i++ { - var j uint - for j = i + 1; j < 4; j++ { - if histo[j] > histo[i] { - var tmp uint32 = histo[j] - histo[j] = histo[i] - histo[i] = tmp - } - } - } - - h23 = histo[2] + histo[3] - histomax = brotli_max_uint32_t(h23, histo[0]) - return kFourSymbolHistogramCost + 3*float64(h23) + 2*(float64(histo[0])+float64(histo[1])) - float64(histomax) - } - { - var max_depth uint = 1 - var depth_histo = [codeLengthCodes]uint32{0} - /* In this loop we compute the entropy of the histogram and simultaneously - build a simplified histogram of the code length codes where we use the - zero repeat code 17, but we don't use the non-zero repeat code 16. */ - - var log2total float64 = fastLog2(histogram.total_count_) - for i = 0; i < data_size; { - if histogram.data_[i] > 0 { - var log2p float64 = log2total - fastLog2(uint(histogram.data_[i])) - /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) = - = log2(total_count) - log2(count(symbol)) */ - - var depth uint = uint(log2p + 0.5) - /* Approximate the bit depth by round(-log2(P(symbol))) */ - bits += float64(histogram.data_[i]) * log2p - - if depth > 15 { - depth = 15 - } - - if depth > max_depth { - max_depth = depth - } - - depth_histo[depth]++ - i++ - } else { - var reps uint32 = 1 - /* Compute the run length of zeros and add the appropriate number of 0 - and 17 code length codes to the code length code histogram. */ - - var k uint - for k = i + 1; k < data_size && histogram.data_[k] == 0; k++ { - reps++ - } - - i += uint(reps) - if i == data_size { - /* Don't add any cost for the last zero run, since these are encoded - only implicitly. */ - break - } - - if reps < 3 { - depth_histo[0] += reps - } else { - reps -= 2 - for reps > 0 { - depth_histo[repeatZeroCodeLength]++ - - /* Add the 3 extra bits for the 17 code length code. */ - bits += 3 - - reps >>= 3 - } - } - } - } - - /* Add the estimated encoding cost of the code length code histogram. */ - bits += float64(18 + 2*max_depth) - - /* Add the entropy of the code length code histogram. */ - bits += bitsEntropy(depth_histo[:], codeLengthCodes) - } - - return bits -} diff --git a/src/vendor/github.com/andybalholm/brotli/bit_reader.go b/src/vendor/github.com/andybalholm/brotli/bit_reader.go deleted file mode 100644 index fba8687c..00000000 --- a/src/vendor/github.com/andybalholm/brotli/bit_reader.go +++ /dev/null @@ -1,266 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Bit reading helpers */ - -const shortFillBitWindowRead = (8 >> 1) - -var kBitMask = [33]uint32{ - 0x00000000, - 0x00000001, - 0x00000003, - 0x00000007, - 0x0000000F, - 0x0000001F, - 0x0000003F, - 0x0000007F, - 0x000000FF, - 0x000001FF, - 0x000003FF, - 0x000007FF, - 0x00000FFF, - 0x00001FFF, - 0x00003FFF, - 0x00007FFF, - 0x0000FFFF, - 0x0001FFFF, - 0x0003FFFF, - 0x0007FFFF, - 0x000FFFFF, - 0x001FFFFF, - 0x003FFFFF, - 0x007FFFFF, - 0x00FFFFFF, - 0x01FFFFFF, - 0x03FFFFFF, - 0x07FFFFFF, - 0x0FFFFFFF, - 0x1FFFFFFF, - 0x3FFFFFFF, - 0x7FFFFFFF, - 0xFFFFFFFF, -} - -func bitMask(n uint32) uint32 { - return kBitMask[n] -} - -type bitReader struct { - val_ uint64 - bit_pos_ uint32 - input []byte - input_len uint - byte_pos uint -} - -type bitReaderState struct { - val_ uint64 - bit_pos_ uint32 - input []byte - input_len uint - byte_pos uint -} - -/* Initializes the BrotliBitReader fields. */ - -/* Ensures that accumulator is not empty. - May consume up to sizeof(brotli_reg_t) - 1 bytes of input. - Returns false if data is required but there is no input available. - For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned - reading. */ -func bitReaderSaveState(from *bitReader, to *bitReaderState) { - to.val_ = from.val_ - to.bit_pos_ = from.bit_pos_ - to.input = from.input - to.input_len = from.input_len - to.byte_pos = from.byte_pos -} - -func bitReaderRestoreState(to *bitReader, from *bitReaderState) { - to.val_ = from.val_ - to.bit_pos_ = from.bit_pos_ - to.input = from.input - to.input_len = from.input_len - to.byte_pos = from.byte_pos -} - -func getAvailableBits(br *bitReader) uint32 { - return 64 - br.bit_pos_ -} - -/* Returns amount of unread bytes the bit reader still has buffered from the - BrotliInput, including whole bytes in br->val_. */ -func getRemainingBytes(br *bitReader) uint { - return uint(uint32(br.input_len-br.byte_pos) + (getAvailableBits(br) >> 3)) -} - -/* Checks if there is at least |num| bytes left in the input ring-buffer - (excluding the bits remaining in br->val_). */ -func checkInputAmount(br *bitReader, num uint) bool { - return br.input_len-br.byte_pos >= num -} - -/* Guarantees that there are at least |n_bits| + 1 bits in accumulator. - Precondition: accumulator contains at least 1 bit. - |n_bits| should be in the range [1..24] for regular build. For portable - non-64-bit little-endian build only 16 bits are safe to request. */ -func fillBitWindow(br *bitReader, n_bits uint32) { - if br.bit_pos_ >= 32 { - br.val_ >>= 32 - br.bit_pos_ ^= 32 /* here same as -= 32 because of the if condition */ - br.val_ |= (uint64(binary.LittleEndian.Uint32(br.input[br.byte_pos:]))) << 32 - br.byte_pos += 4 - } -} - -/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no - more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */ -func fillBitWindow16(br *bitReader) { - fillBitWindow(br, 17) -} - -/* Tries to pull one byte of input to accumulator. - Returns false if there is no input available. */ -func pullByte(br *bitReader) bool { - if br.byte_pos == br.input_len { - return false - } - - br.val_ >>= 8 - br.val_ |= (uint64(br.input[br.byte_pos])) << 56 - br.bit_pos_ -= 8 - br.byte_pos++ - return true -} - -/* Returns currently available bits. - The number of valid bits could be calculated by BrotliGetAvailableBits. */ -func getBitsUnmasked(br *bitReader) uint64 { - return br.val_ >> br.bit_pos_ -} - -/* Like BrotliGetBits, but does not mask the result. - The result contains at least 16 valid bits. */ -func get16BitsUnmasked(br *bitReader) uint32 { - fillBitWindow(br, 16) - return uint32(getBitsUnmasked(br)) -} - -/* Returns the specified number of bits from |br| without advancing bit - position. */ -func getBits(br *bitReader, n_bits uint32) uint32 { - fillBitWindow(br, n_bits) - return uint32(getBitsUnmasked(br)) & bitMask(n_bits) -} - -/* Tries to peek the specified amount of bits. Returns false, if there - is not enough input. */ -func safeGetBits(br *bitReader, n_bits uint32, val *uint32) bool { - for getAvailableBits(br) < n_bits { - if !pullByte(br) { - return false - } - } - - *val = uint32(getBitsUnmasked(br)) & bitMask(n_bits) - return true -} - -/* Advances the bit pos by |n_bits|. */ -func dropBits(br *bitReader, n_bits uint32) { - br.bit_pos_ += n_bits -} - -func bitReaderUnload(br *bitReader) { - var unused_bytes uint32 = getAvailableBits(br) >> 3 - var unused_bits uint32 = unused_bytes << 3 - br.byte_pos -= uint(unused_bytes) - if unused_bits == 64 { - br.val_ = 0 - } else { - br.val_ <<= unused_bits - } - - br.bit_pos_ += unused_bits -} - -/* Reads the specified number of bits from |br| and advances the bit pos. - Precondition: accumulator MUST contain at least |n_bits|. */ -func takeBits(br *bitReader, n_bits uint32, val *uint32) { - *val = uint32(getBitsUnmasked(br)) & bitMask(n_bits) - dropBits(br, n_bits) -} - -/* Reads the specified number of bits from |br| and advances the bit pos. - Assumes that there is enough input to perform BrotliFillBitWindow. */ -func readBits(br *bitReader, n_bits uint32) uint32 { - var val uint32 - fillBitWindow(br, n_bits) - takeBits(br, n_bits, &val) - return val -} - -/* Tries to read the specified amount of bits. Returns false, if there - is not enough input. |n_bits| MUST be positive. */ -func safeReadBits(br *bitReader, n_bits uint32, val *uint32) bool { - for getAvailableBits(br) < n_bits { - if !pullByte(br) { - return false - } - } - - takeBits(br, n_bits, val) - return true -} - -/* Advances the bit reader position to the next byte boundary and verifies - that any skipped bits are set to zero. */ -func bitReaderJumpToByteBoundary(br *bitReader) bool { - var pad_bits_count uint32 = getAvailableBits(br) & 0x7 - var pad_bits uint32 = 0 - if pad_bits_count != 0 { - takeBits(br, pad_bits_count, &pad_bits) - } - - return pad_bits == 0 -} - -/* Copies remaining input bytes stored in the bit reader to the output. Value - |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be - warmed up again after this. */ -func copyBytes(dest []byte, br *bitReader, num uint) { - for getAvailableBits(br) >= 8 && num > 0 { - dest[0] = byte(getBitsUnmasked(br)) - dropBits(br, 8) - dest = dest[1:] - num-- - } - - copy(dest, br.input[br.byte_pos:][:num]) - br.byte_pos += num -} - -func initBitReader(br *bitReader) { - br.val_ = 0 - br.bit_pos_ = 64 -} - -func warmupBitReader(br *bitReader) bool { - /* Fixing alignment after unaligned BrotliFillWindow would result accumulator - overflow. If unalignment is caused by BrotliSafeReadBits, then there is - enough space in accumulator to fix alignment. */ - if getAvailableBits(br) == 0 { - if !pullByte(br) { - return false - } - } - - return true -} diff --git a/src/vendor/github.com/andybalholm/brotli/bitwriter.go b/src/vendor/github.com/andybalholm/brotli/bitwriter.go deleted file mode 100644 index dfc60360..00000000 --- a/src/vendor/github.com/andybalholm/brotli/bitwriter.go +++ /dev/null @@ -1,56 +0,0 @@ -package brotli - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Write bits into a byte array. */ - -type bitWriter struct { - dst []byte - - // Data waiting to be written is the low nbits of bits. - bits uint64 - nbits uint -} - -func (w *bitWriter) writeBits(nb uint, b uint64) { - w.bits |= b << w.nbits - w.nbits += nb - if w.nbits >= 32 { - bits := w.bits - w.bits >>= 32 - w.nbits -= 32 - w.dst = append(w.dst, - byte(bits), - byte(bits>>8), - byte(bits>>16), - byte(bits>>24), - ) - } -} - -func (w *bitWriter) writeSingleBit(bit bool) { - if bit { - w.writeBits(1, 1) - } else { - w.writeBits(1, 0) - } -} - -func (w *bitWriter) jumpToByteBoundary() { - dst := w.dst - for w.nbits != 0 { - dst = append(dst, byte(w.bits)) - w.bits >>= 8 - if w.nbits > 8 { // Avoid underflow - w.nbits -= 8 - } else { - w.nbits = 0 - } - } - w.bits = 0 - w.dst = dst -} diff --git a/src/vendor/github.com/andybalholm/brotli/block_splitter.go b/src/vendor/github.com/andybalholm/brotli/block_splitter.go deleted file mode 100644 index 978a1314..00000000 --- a/src/vendor/github.com/andybalholm/brotli/block_splitter.go +++ /dev/null @@ -1,144 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Block split point selection utilities. */ - -type blockSplit struct { - num_types uint - num_blocks uint - types []byte - lengths []uint32 - types_alloc_size uint - lengths_alloc_size uint -} - -const ( - kMaxLiteralHistograms uint = 100 - kMaxCommandHistograms uint = 50 - kLiteralBlockSwitchCost float64 = 28.1 - kCommandBlockSwitchCost float64 = 13.5 - kDistanceBlockSwitchCost float64 = 14.6 - kLiteralStrideLength uint = 70 - kCommandStrideLength uint = 40 - kSymbolsPerLiteralHistogram uint = 544 - kSymbolsPerCommandHistogram uint = 530 - kSymbolsPerDistanceHistogram uint = 544 - kMinLengthForBlockSplitting uint = 128 - kIterMulForRefining uint = 2 - kMinItersForRefining uint = 100 -) - -func countLiterals(cmds []command) uint { - var total_length uint = 0 - /* Count how many we have. */ - - for i := range cmds { - total_length += uint(cmds[i].insert_len_) - } - - return total_length -} - -func copyLiteralsToByteArray(cmds []command, data []byte, offset uint, mask uint, literals []byte) { - var pos uint = 0 - var from_pos uint = offset & mask - for i := range cmds { - var insert_len uint = uint(cmds[i].insert_len_) - if from_pos+insert_len > mask { - var head_size uint = mask + 1 - from_pos - copy(literals[pos:], data[from_pos:][:head_size]) - from_pos = 0 - pos += head_size - insert_len -= head_size - } - - if insert_len > 0 { - copy(literals[pos:], data[from_pos:][:insert_len]) - pos += insert_len - } - - from_pos = uint((uint32(from_pos+insert_len) + commandCopyLen(&cmds[i])) & uint32(mask)) - } -} - -func myRand(seed *uint32) uint32 { - /* Initial seed should be 7. In this case, loop length is (1 << 29). */ - *seed *= 16807 - - return *seed -} - -func bitCost(count uint) float64 { - if count == 0 { - return -2.0 - } else { - return fastLog2(count) - } -} - -const histogramsPerBatch = 64 - -const clustersPerBatch = 16 - -func initBlockSplit(self *blockSplit) { - self.num_types = 0 - self.num_blocks = 0 - self.types = self.types[:0] - self.lengths = self.lengths[:0] - self.types_alloc_size = 0 - self.lengths_alloc_size = 0 -} - -func splitBlock(cmds []command, data []byte, pos uint, mask uint, params *encoderParams, literal_split *blockSplit, insert_and_copy_split *blockSplit, dist_split *blockSplit) { - { - var literals_count uint = countLiterals(cmds) - var literals []byte = make([]byte, literals_count) - - /* Create a continuous array of literals. */ - copyLiteralsToByteArray(cmds, data, pos, mask, literals) - - /* Create the block split on the array of literals. - Literal histograms have alphabet size 256. */ - splitByteVectorLiteral(literals, literals_count, kSymbolsPerLiteralHistogram, kMaxLiteralHistograms, kLiteralStrideLength, kLiteralBlockSwitchCost, params, literal_split) - - literals = nil - } - { - var insert_and_copy_codes []uint16 = make([]uint16, len(cmds)) - /* Compute prefix codes for commands. */ - - for i := range cmds { - insert_and_copy_codes[i] = cmds[i].cmd_prefix_ - } - - /* Create the block split on the array of command prefixes. */ - splitByteVectorCommand(insert_and_copy_codes, kSymbolsPerCommandHistogram, kMaxCommandHistograms, kCommandStrideLength, kCommandBlockSwitchCost, params, insert_and_copy_split) - - /* TODO: reuse for distances? */ - - insert_and_copy_codes = nil - } - { - var distance_prefixes []uint16 = make([]uint16, len(cmds)) - var j uint = 0 - /* Create a continuous array of distance prefixes. */ - - for i := range cmds { - var cmd *command = &cmds[i] - if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 { - distance_prefixes[j] = cmd.dist_prefix_ & 0x3FF - j++ - } - } - - /* Create the block split on the array of distance prefixes. */ - splitByteVectorDistance(distance_prefixes, j, kSymbolsPerDistanceHistogram, kMaxCommandHistograms, kCommandStrideLength, kDistanceBlockSwitchCost, params, dist_split) - - distance_prefixes = nil - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/block_splitter_command.go b/src/vendor/github.com/andybalholm/brotli/block_splitter_command.go deleted file mode 100644 index 9dec13e4..00000000 --- a/src/vendor/github.com/andybalholm/brotli/block_splitter_command.go +++ /dev/null @@ -1,434 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func initialEntropyCodesCommand(data []uint16, length uint, stride uint, num_histograms uint, histograms []histogramCommand) { - var seed uint32 = 7 - var block_length uint = length / num_histograms - var i uint - clearHistogramsCommand(histograms, num_histograms) - for i = 0; i < num_histograms; i++ { - var pos uint = length * i / num_histograms - if i != 0 { - pos += uint(myRand(&seed) % uint32(block_length)) - } - - if pos+stride >= length { - pos = length - stride - 1 - } - - histogramAddVectorCommand(&histograms[i], data[pos:], stride) - } -} - -func randomSampleCommand(seed *uint32, data []uint16, length uint, stride uint, sample *histogramCommand) { - var pos uint = 0 - if stride >= length { - stride = length - } else { - pos = uint(myRand(seed) % uint32(length-stride+1)) - } - - histogramAddVectorCommand(sample, data[pos:], stride) -} - -func refineEntropyCodesCommand(data []uint16, length uint, stride uint, num_histograms uint, histograms []histogramCommand) { - var iters uint = kIterMulForRefining*length/stride + kMinItersForRefining - var seed uint32 = 7 - var iter uint - iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms - for iter = 0; iter < iters; iter++ { - var sample histogramCommand - histogramClearCommand(&sample) - randomSampleCommand(&seed, data, length, stride, &sample) - histogramAddHistogramCommand(&histograms[iter%num_histograms], &sample) - } -} - -/* Assigns a block id from the range [0, num_histograms) to each data element - in data[0..length) and fills in block_id[0..length) with the assigned values. - Returns the number of blocks, i.e. one plus the number of block switches. */ -func findBlocksCommand(data []uint16, length uint, block_switch_bitcost float64, num_histograms uint, histograms []histogramCommand, insert_cost []float64, cost []float64, switch_signal []byte, block_id []byte) uint { - var data_size uint = histogramDataSizeCommand() - var bitmaplen uint = (num_histograms + 7) >> 3 - var num_blocks uint = 1 - var i uint - var j uint - assert(num_histograms <= 256) - if num_histograms <= 1 { - for i = 0; i < length; i++ { - block_id[i] = 0 - } - - return 1 - } - - for i := 0; i < int(data_size*num_histograms); i++ { - insert_cost[i] = 0 - } - for i = 0; i < num_histograms; i++ { - insert_cost[i] = fastLog2(uint(uint32(histograms[i].total_count_))) - } - - for i = data_size; i != 0; { - i-- - for j = 0; j < num_histograms; j++ { - insert_cost[i*num_histograms+j] = insert_cost[j] - bitCost(uint(histograms[j].data_[i])) - } - } - - for i := 0; i < int(num_histograms); i++ { - cost[i] = 0 - } - for i := 0; i < int(length*bitmaplen); i++ { - switch_signal[i] = 0 - } - - /* After each iteration of this loop, cost[k] will contain the difference - between the minimum cost of arriving at the current byte position using - entropy code k, and the minimum cost of arriving at the current byte - position. This difference is capped at the block switch cost, and if it - reaches block switch cost, it means that when we trace back from the last - position, we need to switch here. */ - for i = 0; i < length; i++ { - var byte_ix uint = i - var ix uint = byte_ix * bitmaplen - var insert_cost_ix uint = uint(data[byte_ix]) * num_histograms - var min_cost float64 = 1e99 - var block_switch_cost float64 = block_switch_bitcost - var k uint - for k = 0; k < num_histograms; k++ { - /* We are coding the symbol in data[byte_ix] with entropy code k. */ - cost[k] += insert_cost[insert_cost_ix+k] - - if cost[k] < min_cost { - min_cost = cost[k] - block_id[byte_ix] = byte(k) - } - } - - /* More blocks for the beginning. */ - if byte_ix < 2000 { - block_switch_cost *= 0.77 + 0.07*float64(byte_ix)/2000 - } - - for k = 0; k < num_histograms; k++ { - cost[k] -= min_cost - if cost[k] >= block_switch_cost { - var mask byte = byte(1 << (k & 7)) - cost[k] = block_switch_cost - assert(k>>3 < bitmaplen) - switch_signal[ix+(k>>3)] |= mask - /* Trace back from the last position and switch at the marked places. */ - } - } - } - { - var byte_ix uint = length - 1 - var ix uint = byte_ix * bitmaplen - var cur_id byte = block_id[byte_ix] - for byte_ix > 0 { - var mask byte = byte(1 << (cur_id & 7)) - assert(uint(cur_id)>>3 < bitmaplen) - byte_ix-- - ix -= bitmaplen - if switch_signal[ix+uint(cur_id>>3)]&mask != 0 { - if cur_id != block_id[byte_ix] { - cur_id = block_id[byte_ix] - num_blocks++ - } - } - - block_id[byte_ix] = cur_id - } - } - - return num_blocks -} - -var remapBlockIdsCommand_kInvalidId uint16 = 256 - -func remapBlockIdsCommand(block_ids []byte, length uint, new_id []uint16, num_histograms uint) uint { - var next_id uint16 = 0 - var i uint - for i = 0; i < num_histograms; i++ { - new_id[i] = remapBlockIdsCommand_kInvalidId - } - - for i = 0; i < length; i++ { - assert(uint(block_ids[i]) < num_histograms) - if new_id[block_ids[i]] == remapBlockIdsCommand_kInvalidId { - new_id[block_ids[i]] = next_id - next_id++ - } - } - - for i = 0; i < length; i++ { - block_ids[i] = byte(new_id[block_ids[i]]) - assert(uint(block_ids[i]) < num_histograms) - } - - assert(uint(next_id) <= num_histograms) - return uint(next_id) -} - -func buildBlockHistogramsCommand(data []uint16, length uint, block_ids []byte, num_histograms uint, histograms []histogramCommand) { - var i uint - clearHistogramsCommand(histograms, num_histograms) - for i = 0; i < length; i++ { - histogramAddCommand(&histograms[block_ids[i]], uint(data[i])) - } -} - -var clusterBlocksCommand_kInvalidIndex uint32 = math.MaxUint32 - -func clusterBlocksCommand(data []uint16, length uint, num_blocks uint, block_ids []byte, split *blockSplit) { - var histogram_symbols []uint32 = make([]uint32, num_blocks) - var block_lengths []uint32 = make([]uint32, num_blocks) - var expected_num_clusters uint = clustersPerBatch * (num_blocks + histogramsPerBatch - 1) / histogramsPerBatch - var all_histograms_size uint = 0 - var all_histograms_capacity uint = expected_num_clusters - var all_histograms []histogramCommand = make([]histogramCommand, all_histograms_capacity) - var cluster_size_size uint = 0 - var cluster_size_capacity uint = expected_num_clusters - var cluster_size []uint32 = make([]uint32, cluster_size_capacity) - var num_clusters uint = 0 - var histograms []histogramCommand = make([]histogramCommand, brotli_min_size_t(num_blocks, histogramsPerBatch)) - var max_num_pairs uint = histogramsPerBatch * histogramsPerBatch / 2 - var pairs_capacity uint = max_num_pairs + 1 - var pairs []histogramPair = make([]histogramPair, pairs_capacity) - var pos uint = 0 - var clusters []uint32 - var num_final_clusters uint - var new_index []uint32 - var i uint - var sizes = [histogramsPerBatch]uint32{0} - var new_clusters = [histogramsPerBatch]uint32{0} - var symbols = [histogramsPerBatch]uint32{0} - var remap = [histogramsPerBatch]uint32{0} - - for i := 0; i < int(num_blocks); i++ { - block_lengths[i] = 0 - } - { - var block_idx uint = 0 - for i = 0; i < length; i++ { - assert(block_idx < num_blocks) - block_lengths[block_idx]++ - if i+1 == length || block_ids[i] != block_ids[i+1] { - block_idx++ - } - } - - assert(block_idx == num_blocks) - } - - for i = 0; i < num_blocks; i += histogramsPerBatch { - var num_to_combine uint = brotli_min_size_t(num_blocks-i, histogramsPerBatch) - var num_new_clusters uint - var j uint - for j = 0; j < num_to_combine; j++ { - var k uint - histogramClearCommand(&histograms[j]) - for k = 0; uint32(k) < block_lengths[i+j]; k++ { - histogramAddCommand(&histograms[j], uint(data[pos])) - pos++ - } - - histograms[j].bit_cost_ = populationCostCommand(&histograms[j]) - new_clusters[j] = uint32(j) - symbols[j] = uint32(j) - sizes[j] = 1 - } - - num_new_clusters = histogramCombineCommand(histograms, sizes[:], symbols[:], new_clusters[:], []histogramPair(pairs), num_to_combine, num_to_combine, histogramsPerBatch, max_num_pairs) - if all_histograms_capacity < (all_histograms_size + num_new_clusters) { - var _new_size uint - if all_histograms_capacity == 0 { - _new_size = all_histograms_size + num_new_clusters - } else { - _new_size = all_histograms_capacity - } - var new_array []histogramCommand - for _new_size < (all_histograms_size + num_new_clusters) { - _new_size *= 2 - } - new_array = make([]histogramCommand, _new_size) - if all_histograms_capacity != 0 { - copy(new_array, all_histograms[:all_histograms_capacity]) - } - - all_histograms = new_array - all_histograms_capacity = _new_size - } - - brotli_ensure_capacity_uint32_t(&cluster_size, &cluster_size_capacity, cluster_size_size+num_new_clusters) - for j = 0; j < num_new_clusters; j++ { - all_histograms[all_histograms_size] = histograms[new_clusters[j]] - all_histograms_size++ - cluster_size[cluster_size_size] = sizes[new_clusters[j]] - cluster_size_size++ - remap[new_clusters[j]] = uint32(j) - } - - for j = 0; j < num_to_combine; j++ { - histogram_symbols[i+j] = uint32(num_clusters) + remap[symbols[j]] - } - - num_clusters += num_new_clusters - assert(num_clusters == cluster_size_size) - assert(num_clusters == all_histograms_size) - } - - histograms = nil - - max_num_pairs = brotli_min_size_t(64*num_clusters, (num_clusters/2)*num_clusters) - if pairs_capacity < max_num_pairs+1 { - pairs = nil - pairs = make([]histogramPair, (max_num_pairs + 1)) - } - - clusters = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - clusters[i] = uint32(i) - } - - num_final_clusters = histogramCombineCommand(all_histograms, cluster_size, histogram_symbols, clusters, pairs, num_clusters, num_blocks, maxNumberOfBlockTypes, max_num_pairs) - pairs = nil - cluster_size = nil - - new_index = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - new_index[i] = clusterBlocksCommand_kInvalidIndex - } - pos = 0 - { - var next_index uint32 = 0 - for i = 0; i < num_blocks; i++ { - var histo histogramCommand - var j uint - var best_out uint32 - var best_bits float64 - histogramClearCommand(&histo) - for j = 0; uint32(j) < block_lengths[i]; j++ { - histogramAddCommand(&histo, uint(data[pos])) - pos++ - } - - if i == 0 { - best_out = histogram_symbols[0] - } else { - best_out = histogram_symbols[i-1] - } - best_bits = histogramBitCostDistanceCommand(&histo, &all_histograms[best_out]) - for j = 0; j < num_final_clusters; j++ { - var cur_bits float64 = histogramBitCostDistanceCommand(&histo, &all_histograms[clusters[j]]) - if cur_bits < best_bits { - best_bits = cur_bits - best_out = clusters[j] - } - } - - histogram_symbols[i] = best_out - if new_index[best_out] == clusterBlocksCommand_kInvalidIndex { - new_index[best_out] = next_index - next_index++ - } - } - } - - clusters = nil - all_histograms = nil - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, num_blocks) - { - var cur_length uint32 = 0 - var block_idx uint = 0 - var max_type byte = 0 - for i = 0; i < num_blocks; i++ { - cur_length += block_lengths[i] - if i+1 == num_blocks || histogram_symbols[i] != histogram_symbols[i+1] { - var id byte = byte(new_index[histogram_symbols[i]]) - split.types[block_idx] = id - split.lengths[block_idx] = cur_length - max_type = brotli_max_uint8_t(max_type, id) - cur_length = 0 - block_idx++ - } - } - - split.num_blocks = block_idx - split.num_types = uint(max_type) + 1 - } - - new_index = nil - block_lengths = nil - histogram_symbols = nil -} - -func splitByteVectorCommand(data []uint16, literals_per_histogram uint, max_histograms uint, sampling_stride_length uint, block_switch_cost float64, params *encoderParams, split *blockSplit) { - length := uint(len(data)) - var data_size uint = histogramDataSizeCommand() - var num_histograms uint = length/literals_per_histogram + 1 - var histograms []histogramCommand - if num_histograms > max_histograms { - num_histograms = max_histograms - } - - if length == 0 { - split.num_types = 1 - return - } else if length < kMinLengthForBlockSplitting { - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, split.num_blocks+1) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, split.num_blocks+1) - split.num_types = 1 - split.types[split.num_blocks] = 0 - split.lengths[split.num_blocks] = uint32(length) - split.num_blocks++ - return - } - - histograms = make([]histogramCommand, num_histograms) - - /* Find good entropy codes. */ - initialEntropyCodesCommand(data, length, sampling_stride_length, num_histograms, histograms) - - refineEntropyCodesCommand(data, length, sampling_stride_length, num_histograms, histograms) - { - var block_ids []byte = make([]byte, length) - var num_blocks uint = 0 - var bitmaplen uint = (num_histograms + 7) >> 3 - var insert_cost []float64 = make([]float64, (data_size * num_histograms)) - var cost []float64 = make([]float64, num_histograms) - var switch_signal []byte = make([]byte, (length * bitmaplen)) - var new_id []uint16 = make([]uint16, num_histograms) - var iters uint - if params.quality < hqZopflificationQuality { - iters = 3 - } else { - iters = 10 - } - /* Find a good path through literals with the good entropy codes. */ - - var i uint - for i = 0; i < iters; i++ { - num_blocks = findBlocksCommand(data, length, block_switch_cost, num_histograms, histograms, insert_cost, cost, switch_signal, block_ids) - num_histograms = remapBlockIdsCommand(block_ids, length, new_id, num_histograms) - buildBlockHistogramsCommand(data, length, block_ids, num_histograms, histograms) - } - - insert_cost = nil - cost = nil - switch_signal = nil - new_id = nil - histograms = nil - clusterBlocksCommand(data, length, num_blocks, block_ids, split) - block_ids = nil - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/block_splitter_distance.go b/src/vendor/github.com/andybalholm/brotli/block_splitter_distance.go deleted file mode 100644 index 953530d5..00000000 --- a/src/vendor/github.com/andybalholm/brotli/block_splitter_distance.go +++ /dev/null @@ -1,433 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func initialEntropyCodesDistance(data []uint16, length uint, stride uint, num_histograms uint, histograms []histogramDistance) { - var seed uint32 = 7 - var block_length uint = length / num_histograms - var i uint - clearHistogramsDistance(histograms, num_histograms) - for i = 0; i < num_histograms; i++ { - var pos uint = length * i / num_histograms - if i != 0 { - pos += uint(myRand(&seed) % uint32(block_length)) - } - - if pos+stride >= length { - pos = length - stride - 1 - } - - histogramAddVectorDistance(&histograms[i], data[pos:], stride) - } -} - -func randomSampleDistance(seed *uint32, data []uint16, length uint, stride uint, sample *histogramDistance) { - var pos uint = 0 - if stride >= length { - stride = length - } else { - pos = uint(myRand(seed) % uint32(length-stride+1)) - } - - histogramAddVectorDistance(sample, data[pos:], stride) -} - -func refineEntropyCodesDistance(data []uint16, length uint, stride uint, num_histograms uint, histograms []histogramDistance) { - var iters uint = kIterMulForRefining*length/stride + kMinItersForRefining - var seed uint32 = 7 - var iter uint - iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms - for iter = 0; iter < iters; iter++ { - var sample histogramDistance - histogramClearDistance(&sample) - randomSampleDistance(&seed, data, length, stride, &sample) - histogramAddHistogramDistance(&histograms[iter%num_histograms], &sample) - } -} - -/* Assigns a block id from the range [0, num_histograms) to each data element - in data[0..length) and fills in block_id[0..length) with the assigned values. - Returns the number of blocks, i.e. one plus the number of block switches. */ -func findBlocksDistance(data []uint16, length uint, block_switch_bitcost float64, num_histograms uint, histograms []histogramDistance, insert_cost []float64, cost []float64, switch_signal []byte, block_id []byte) uint { - var data_size uint = histogramDataSizeDistance() - var bitmaplen uint = (num_histograms + 7) >> 3 - var num_blocks uint = 1 - var i uint - var j uint - assert(num_histograms <= 256) - if num_histograms <= 1 { - for i = 0; i < length; i++ { - block_id[i] = 0 - } - - return 1 - } - - for i := 0; i < int(data_size*num_histograms); i++ { - insert_cost[i] = 0 - } - for i = 0; i < num_histograms; i++ { - insert_cost[i] = fastLog2(uint(uint32(histograms[i].total_count_))) - } - - for i = data_size; i != 0; { - i-- - for j = 0; j < num_histograms; j++ { - insert_cost[i*num_histograms+j] = insert_cost[j] - bitCost(uint(histograms[j].data_[i])) - } - } - - for i := 0; i < int(num_histograms); i++ { - cost[i] = 0 - } - for i := 0; i < int(length*bitmaplen); i++ { - switch_signal[i] = 0 - } - - /* After each iteration of this loop, cost[k] will contain the difference - between the minimum cost of arriving at the current byte position using - entropy code k, and the minimum cost of arriving at the current byte - position. This difference is capped at the block switch cost, and if it - reaches block switch cost, it means that when we trace back from the last - position, we need to switch here. */ - for i = 0; i < length; i++ { - var byte_ix uint = i - var ix uint = byte_ix * bitmaplen - var insert_cost_ix uint = uint(data[byte_ix]) * num_histograms - var min_cost float64 = 1e99 - var block_switch_cost float64 = block_switch_bitcost - var k uint - for k = 0; k < num_histograms; k++ { - /* We are coding the symbol in data[byte_ix] with entropy code k. */ - cost[k] += insert_cost[insert_cost_ix+k] - - if cost[k] < min_cost { - min_cost = cost[k] - block_id[byte_ix] = byte(k) - } - } - - /* More blocks for the beginning. */ - if byte_ix < 2000 { - block_switch_cost *= 0.77 + 0.07*float64(byte_ix)/2000 - } - - for k = 0; k < num_histograms; k++ { - cost[k] -= min_cost - if cost[k] >= block_switch_cost { - var mask byte = byte(1 << (k & 7)) - cost[k] = block_switch_cost - assert(k>>3 < bitmaplen) - switch_signal[ix+(k>>3)] |= mask - /* Trace back from the last position and switch at the marked places. */ - } - } - } - { - var byte_ix uint = length - 1 - var ix uint = byte_ix * bitmaplen - var cur_id byte = block_id[byte_ix] - for byte_ix > 0 { - var mask byte = byte(1 << (cur_id & 7)) - assert(uint(cur_id)>>3 < bitmaplen) - byte_ix-- - ix -= bitmaplen - if switch_signal[ix+uint(cur_id>>3)]&mask != 0 { - if cur_id != block_id[byte_ix] { - cur_id = block_id[byte_ix] - num_blocks++ - } - } - - block_id[byte_ix] = cur_id - } - } - - return num_blocks -} - -var remapBlockIdsDistance_kInvalidId uint16 = 256 - -func remapBlockIdsDistance(block_ids []byte, length uint, new_id []uint16, num_histograms uint) uint { - var next_id uint16 = 0 - var i uint - for i = 0; i < num_histograms; i++ { - new_id[i] = remapBlockIdsDistance_kInvalidId - } - - for i = 0; i < length; i++ { - assert(uint(block_ids[i]) < num_histograms) - if new_id[block_ids[i]] == remapBlockIdsDistance_kInvalidId { - new_id[block_ids[i]] = next_id - next_id++ - } - } - - for i = 0; i < length; i++ { - block_ids[i] = byte(new_id[block_ids[i]]) - assert(uint(block_ids[i]) < num_histograms) - } - - assert(uint(next_id) <= num_histograms) - return uint(next_id) -} - -func buildBlockHistogramsDistance(data []uint16, length uint, block_ids []byte, num_histograms uint, histograms []histogramDistance) { - var i uint - clearHistogramsDistance(histograms, num_histograms) - for i = 0; i < length; i++ { - histogramAddDistance(&histograms[block_ids[i]], uint(data[i])) - } -} - -var clusterBlocksDistance_kInvalidIndex uint32 = math.MaxUint32 - -func clusterBlocksDistance(data []uint16, length uint, num_blocks uint, block_ids []byte, split *blockSplit) { - var histogram_symbols []uint32 = make([]uint32, num_blocks) - var block_lengths []uint32 = make([]uint32, num_blocks) - var expected_num_clusters uint = clustersPerBatch * (num_blocks + histogramsPerBatch - 1) / histogramsPerBatch - var all_histograms_size uint = 0 - var all_histograms_capacity uint = expected_num_clusters - var all_histograms []histogramDistance = make([]histogramDistance, all_histograms_capacity) - var cluster_size_size uint = 0 - var cluster_size_capacity uint = expected_num_clusters - var cluster_size []uint32 = make([]uint32, cluster_size_capacity) - var num_clusters uint = 0 - var histograms []histogramDistance = make([]histogramDistance, brotli_min_size_t(num_blocks, histogramsPerBatch)) - var max_num_pairs uint = histogramsPerBatch * histogramsPerBatch / 2 - var pairs_capacity uint = max_num_pairs + 1 - var pairs []histogramPair = make([]histogramPair, pairs_capacity) - var pos uint = 0 - var clusters []uint32 - var num_final_clusters uint - var new_index []uint32 - var i uint - var sizes = [histogramsPerBatch]uint32{0} - var new_clusters = [histogramsPerBatch]uint32{0} - var symbols = [histogramsPerBatch]uint32{0} - var remap = [histogramsPerBatch]uint32{0} - - for i := 0; i < int(num_blocks); i++ { - block_lengths[i] = 0 - } - { - var block_idx uint = 0 - for i = 0; i < length; i++ { - assert(block_idx < num_blocks) - block_lengths[block_idx]++ - if i+1 == length || block_ids[i] != block_ids[i+1] { - block_idx++ - } - } - - assert(block_idx == num_blocks) - } - - for i = 0; i < num_blocks; i += histogramsPerBatch { - var num_to_combine uint = brotli_min_size_t(num_blocks-i, histogramsPerBatch) - var num_new_clusters uint - var j uint - for j = 0; j < num_to_combine; j++ { - var k uint - histogramClearDistance(&histograms[j]) - for k = 0; uint32(k) < block_lengths[i+j]; k++ { - histogramAddDistance(&histograms[j], uint(data[pos])) - pos++ - } - - histograms[j].bit_cost_ = populationCostDistance(&histograms[j]) - new_clusters[j] = uint32(j) - symbols[j] = uint32(j) - sizes[j] = 1 - } - - num_new_clusters = histogramCombineDistance(histograms, sizes[:], symbols[:], new_clusters[:], []histogramPair(pairs), num_to_combine, num_to_combine, histogramsPerBatch, max_num_pairs) - if all_histograms_capacity < (all_histograms_size + num_new_clusters) { - var _new_size uint - if all_histograms_capacity == 0 { - _new_size = all_histograms_size + num_new_clusters - } else { - _new_size = all_histograms_capacity - } - var new_array []histogramDistance - for _new_size < (all_histograms_size + num_new_clusters) { - _new_size *= 2 - } - new_array = make([]histogramDistance, _new_size) - if all_histograms_capacity != 0 { - copy(new_array, all_histograms[:all_histograms_capacity]) - } - - all_histograms = new_array - all_histograms_capacity = _new_size - } - - brotli_ensure_capacity_uint32_t(&cluster_size, &cluster_size_capacity, cluster_size_size+num_new_clusters) - for j = 0; j < num_new_clusters; j++ { - all_histograms[all_histograms_size] = histograms[new_clusters[j]] - all_histograms_size++ - cluster_size[cluster_size_size] = sizes[new_clusters[j]] - cluster_size_size++ - remap[new_clusters[j]] = uint32(j) - } - - for j = 0; j < num_to_combine; j++ { - histogram_symbols[i+j] = uint32(num_clusters) + remap[symbols[j]] - } - - num_clusters += num_new_clusters - assert(num_clusters == cluster_size_size) - assert(num_clusters == all_histograms_size) - } - - histograms = nil - - max_num_pairs = brotli_min_size_t(64*num_clusters, (num_clusters/2)*num_clusters) - if pairs_capacity < max_num_pairs+1 { - pairs = nil - pairs = make([]histogramPair, (max_num_pairs + 1)) - } - - clusters = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - clusters[i] = uint32(i) - } - - num_final_clusters = histogramCombineDistance(all_histograms, cluster_size, histogram_symbols, clusters, pairs, num_clusters, num_blocks, maxNumberOfBlockTypes, max_num_pairs) - pairs = nil - cluster_size = nil - - new_index = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - new_index[i] = clusterBlocksDistance_kInvalidIndex - } - pos = 0 - { - var next_index uint32 = 0 - for i = 0; i < num_blocks; i++ { - var histo histogramDistance - var j uint - var best_out uint32 - var best_bits float64 - histogramClearDistance(&histo) - for j = 0; uint32(j) < block_lengths[i]; j++ { - histogramAddDistance(&histo, uint(data[pos])) - pos++ - } - - if i == 0 { - best_out = histogram_symbols[0] - } else { - best_out = histogram_symbols[i-1] - } - best_bits = histogramBitCostDistanceDistance(&histo, &all_histograms[best_out]) - for j = 0; j < num_final_clusters; j++ { - var cur_bits float64 = histogramBitCostDistanceDistance(&histo, &all_histograms[clusters[j]]) - if cur_bits < best_bits { - best_bits = cur_bits - best_out = clusters[j] - } - } - - histogram_symbols[i] = best_out - if new_index[best_out] == clusterBlocksDistance_kInvalidIndex { - new_index[best_out] = next_index - next_index++ - } - } - } - - clusters = nil - all_histograms = nil - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, num_blocks) - { - var cur_length uint32 = 0 - var block_idx uint = 0 - var max_type byte = 0 - for i = 0; i < num_blocks; i++ { - cur_length += block_lengths[i] - if i+1 == num_blocks || histogram_symbols[i] != histogram_symbols[i+1] { - var id byte = byte(new_index[histogram_symbols[i]]) - split.types[block_idx] = id - split.lengths[block_idx] = cur_length - max_type = brotli_max_uint8_t(max_type, id) - cur_length = 0 - block_idx++ - } - } - - split.num_blocks = block_idx - split.num_types = uint(max_type) + 1 - } - - new_index = nil - block_lengths = nil - histogram_symbols = nil -} - -func splitByteVectorDistance(data []uint16, length uint, literals_per_histogram uint, max_histograms uint, sampling_stride_length uint, block_switch_cost float64, params *encoderParams, split *blockSplit) { - var data_size uint = histogramDataSizeDistance() - var num_histograms uint = length/literals_per_histogram + 1 - var histograms []histogramDistance - if num_histograms > max_histograms { - num_histograms = max_histograms - } - - if length == 0 { - split.num_types = 1 - return - } else if length < kMinLengthForBlockSplitting { - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, split.num_blocks+1) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, split.num_blocks+1) - split.num_types = 1 - split.types[split.num_blocks] = 0 - split.lengths[split.num_blocks] = uint32(length) - split.num_blocks++ - return - } - - histograms = make([]histogramDistance, num_histograms) - - /* Find good entropy codes. */ - initialEntropyCodesDistance(data, length, sampling_stride_length, num_histograms, histograms) - - refineEntropyCodesDistance(data, length, sampling_stride_length, num_histograms, histograms) - { - var block_ids []byte = make([]byte, length) - var num_blocks uint = 0 - var bitmaplen uint = (num_histograms + 7) >> 3 - var insert_cost []float64 = make([]float64, (data_size * num_histograms)) - var cost []float64 = make([]float64, num_histograms) - var switch_signal []byte = make([]byte, (length * bitmaplen)) - var new_id []uint16 = make([]uint16, num_histograms) - var iters uint - if params.quality < hqZopflificationQuality { - iters = 3 - } else { - iters = 10 - } - /* Find a good path through literals with the good entropy codes. */ - - var i uint - for i = 0; i < iters; i++ { - num_blocks = findBlocksDistance(data, length, block_switch_cost, num_histograms, histograms, insert_cost, cost, switch_signal, block_ids) - num_histograms = remapBlockIdsDistance(block_ids, length, new_id, num_histograms) - buildBlockHistogramsDistance(data, length, block_ids, num_histograms, histograms) - } - - insert_cost = nil - cost = nil - switch_signal = nil - new_id = nil - histograms = nil - clusterBlocksDistance(data, length, num_blocks, block_ids, split) - block_ids = nil - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/block_splitter_literal.go b/src/vendor/github.com/andybalholm/brotli/block_splitter_literal.go deleted file mode 100644 index 1c895cf3..00000000 --- a/src/vendor/github.com/andybalholm/brotli/block_splitter_literal.go +++ /dev/null @@ -1,433 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func initialEntropyCodesLiteral(data []byte, length uint, stride uint, num_histograms uint, histograms []histogramLiteral) { - var seed uint32 = 7 - var block_length uint = length / num_histograms - var i uint - clearHistogramsLiteral(histograms, num_histograms) - for i = 0; i < num_histograms; i++ { - var pos uint = length * i / num_histograms - if i != 0 { - pos += uint(myRand(&seed) % uint32(block_length)) - } - - if pos+stride >= length { - pos = length - stride - 1 - } - - histogramAddVectorLiteral(&histograms[i], data[pos:], stride) - } -} - -func randomSampleLiteral(seed *uint32, data []byte, length uint, stride uint, sample *histogramLiteral) { - var pos uint = 0 - if stride >= length { - stride = length - } else { - pos = uint(myRand(seed) % uint32(length-stride+1)) - } - - histogramAddVectorLiteral(sample, data[pos:], stride) -} - -func refineEntropyCodesLiteral(data []byte, length uint, stride uint, num_histograms uint, histograms []histogramLiteral) { - var iters uint = kIterMulForRefining*length/stride + kMinItersForRefining - var seed uint32 = 7 - var iter uint - iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms - for iter = 0; iter < iters; iter++ { - var sample histogramLiteral - histogramClearLiteral(&sample) - randomSampleLiteral(&seed, data, length, stride, &sample) - histogramAddHistogramLiteral(&histograms[iter%num_histograms], &sample) - } -} - -/* Assigns a block id from the range [0, num_histograms) to each data element - in data[0..length) and fills in block_id[0..length) with the assigned values. - Returns the number of blocks, i.e. one plus the number of block switches. */ -func findBlocksLiteral(data []byte, length uint, block_switch_bitcost float64, num_histograms uint, histograms []histogramLiteral, insert_cost []float64, cost []float64, switch_signal []byte, block_id []byte) uint { - var data_size uint = histogramDataSizeLiteral() - var bitmaplen uint = (num_histograms + 7) >> 3 - var num_blocks uint = 1 - var i uint - var j uint - assert(num_histograms <= 256) - if num_histograms <= 1 { - for i = 0; i < length; i++ { - block_id[i] = 0 - } - - return 1 - } - - for i := 0; i < int(data_size*num_histograms); i++ { - insert_cost[i] = 0 - } - for i = 0; i < num_histograms; i++ { - insert_cost[i] = fastLog2(uint(uint32(histograms[i].total_count_))) - } - - for i = data_size; i != 0; { - i-- - for j = 0; j < num_histograms; j++ { - insert_cost[i*num_histograms+j] = insert_cost[j] - bitCost(uint(histograms[j].data_[i])) - } - } - - for i := 0; i < int(num_histograms); i++ { - cost[i] = 0 - } - for i := 0; i < int(length*bitmaplen); i++ { - switch_signal[i] = 0 - } - - /* After each iteration of this loop, cost[k] will contain the difference - between the minimum cost of arriving at the current byte position using - entropy code k, and the minimum cost of arriving at the current byte - position. This difference is capped at the block switch cost, and if it - reaches block switch cost, it means that when we trace back from the last - position, we need to switch here. */ - for i = 0; i < length; i++ { - var byte_ix uint = i - var ix uint = byte_ix * bitmaplen - var insert_cost_ix uint = uint(data[byte_ix]) * num_histograms - var min_cost float64 = 1e99 - var block_switch_cost float64 = block_switch_bitcost - var k uint - for k = 0; k < num_histograms; k++ { - /* We are coding the symbol in data[byte_ix] with entropy code k. */ - cost[k] += insert_cost[insert_cost_ix+k] - - if cost[k] < min_cost { - min_cost = cost[k] - block_id[byte_ix] = byte(k) - } - } - - /* More blocks for the beginning. */ - if byte_ix < 2000 { - block_switch_cost *= 0.77 + 0.07*float64(byte_ix)/2000 - } - - for k = 0; k < num_histograms; k++ { - cost[k] -= min_cost - if cost[k] >= block_switch_cost { - var mask byte = byte(1 << (k & 7)) - cost[k] = block_switch_cost - assert(k>>3 < bitmaplen) - switch_signal[ix+(k>>3)] |= mask - /* Trace back from the last position and switch at the marked places. */ - } - } - } - { - var byte_ix uint = length - 1 - var ix uint = byte_ix * bitmaplen - var cur_id byte = block_id[byte_ix] - for byte_ix > 0 { - var mask byte = byte(1 << (cur_id & 7)) - assert(uint(cur_id)>>3 < bitmaplen) - byte_ix-- - ix -= bitmaplen - if switch_signal[ix+uint(cur_id>>3)]&mask != 0 { - if cur_id != block_id[byte_ix] { - cur_id = block_id[byte_ix] - num_blocks++ - } - } - - block_id[byte_ix] = cur_id - } - } - - return num_blocks -} - -var remapBlockIdsLiteral_kInvalidId uint16 = 256 - -func remapBlockIdsLiteral(block_ids []byte, length uint, new_id []uint16, num_histograms uint) uint { - var next_id uint16 = 0 - var i uint - for i = 0; i < num_histograms; i++ { - new_id[i] = remapBlockIdsLiteral_kInvalidId - } - - for i = 0; i < length; i++ { - assert(uint(block_ids[i]) < num_histograms) - if new_id[block_ids[i]] == remapBlockIdsLiteral_kInvalidId { - new_id[block_ids[i]] = next_id - next_id++ - } - } - - for i = 0; i < length; i++ { - block_ids[i] = byte(new_id[block_ids[i]]) - assert(uint(block_ids[i]) < num_histograms) - } - - assert(uint(next_id) <= num_histograms) - return uint(next_id) -} - -func buildBlockHistogramsLiteral(data []byte, length uint, block_ids []byte, num_histograms uint, histograms []histogramLiteral) { - var i uint - clearHistogramsLiteral(histograms, num_histograms) - for i = 0; i < length; i++ { - histogramAddLiteral(&histograms[block_ids[i]], uint(data[i])) - } -} - -var clusterBlocksLiteral_kInvalidIndex uint32 = math.MaxUint32 - -func clusterBlocksLiteral(data []byte, length uint, num_blocks uint, block_ids []byte, split *blockSplit) { - var histogram_symbols []uint32 = make([]uint32, num_blocks) - var block_lengths []uint32 = make([]uint32, num_blocks) - var expected_num_clusters uint = clustersPerBatch * (num_blocks + histogramsPerBatch - 1) / histogramsPerBatch - var all_histograms_size uint = 0 - var all_histograms_capacity uint = expected_num_clusters - var all_histograms []histogramLiteral = make([]histogramLiteral, all_histograms_capacity) - var cluster_size_size uint = 0 - var cluster_size_capacity uint = expected_num_clusters - var cluster_size []uint32 = make([]uint32, cluster_size_capacity) - var num_clusters uint = 0 - var histograms []histogramLiteral = make([]histogramLiteral, brotli_min_size_t(num_blocks, histogramsPerBatch)) - var max_num_pairs uint = histogramsPerBatch * histogramsPerBatch / 2 - var pairs_capacity uint = max_num_pairs + 1 - var pairs []histogramPair = make([]histogramPair, pairs_capacity) - var pos uint = 0 - var clusters []uint32 - var num_final_clusters uint - var new_index []uint32 - var i uint - var sizes = [histogramsPerBatch]uint32{0} - var new_clusters = [histogramsPerBatch]uint32{0} - var symbols = [histogramsPerBatch]uint32{0} - var remap = [histogramsPerBatch]uint32{0} - - for i := 0; i < int(num_blocks); i++ { - block_lengths[i] = 0 - } - { - var block_idx uint = 0 - for i = 0; i < length; i++ { - assert(block_idx < num_blocks) - block_lengths[block_idx]++ - if i+1 == length || block_ids[i] != block_ids[i+1] { - block_idx++ - } - } - - assert(block_idx == num_blocks) - } - - for i = 0; i < num_blocks; i += histogramsPerBatch { - var num_to_combine uint = brotli_min_size_t(num_blocks-i, histogramsPerBatch) - var num_new_clusters uint - var j uint - for j = 0; j < num_to_combine; j++ { - var k uint - histogramClearLiteral(&histograms[j]) - for k = 0; uint32(k) < block_lengths[i+j]; k++ { - histogramAddLiteral(&histograms[j], uint(data[pos])) - pos++ - } - - histograms[j].bit_cost_ = populationCostLiteral(&histograms[j]) - new_clusters[j] = uint32(j) - symbols[j] = uint32(j) - sizes[j] = 1 - } - - num_new_clusters = histogramCombineLiteral(histograms, sizes[:], symbols[:], new_clusters[:], []histogramPair(pairs), num_to_combine, num_to_combine, histogramsPerBatch, max_num_pairs) - if all_histograms_capacity < (all_histograms_size + num_new_clusters) { - var _new_size uint - if all_histograms_capacity == 0 { - _new_size = all_histograms_size + num_new_clusters - } else { - _new_size = all_histograms_capacity - } - var new_array []histogramLiteral - for _new_size < (all_histograms_size + num_new_clusters) { - _new_size *= 2 - } - new_array = make([]histogramLiteral, _new_size) - if all_histograms_capacity != 0 { - copy(new_array, all_histograms[:all_histograms_capacity]) - } - - all_histograms = new_array - all_histograms_capacity = _new_size - } - - brotli_ensure_capacity_uint32_t(&cluster_size, &cluster_size_capacity, cluster_size_size+num_new_clusters) - for j = 0; j < num_new_clusters; j++ { - all_histograms[all_histograms_size] = histograms[new_clusters[j]] - all_histograms_size++ - cluster_size[cluster_size_size] = sizes[new_clusters[j]] - cluster_size_size++ - remap[new_clusters[j]] = uint32(j) - } - - for j = 0; j < num_to_combine; j++ { - histogram_symbols[i+j] = uint32(num_clusters) + remap[symbols[j]] - } - - num_clusters += num_new_clusters - assert(num_clusters == cluster_size_size) - assert(num_clusters == all_histograms_size) - } - - histograms = nil - - max_num_pairs = brotli_min_size_t(64*num_clusters, (num_clusters/2)*num_clusters) - if pairs_capacity < max_num_pairs+1 { - pairs = nil - pairs = make([]histogramPair, (max_num_pairs + 1)) - } - - clusters = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - clusters[i] = uint32(i) - } - - num_final_clusters = histogramCombineLiteral(all_histograms, cluster_size, histogram_symbols, clusters, pairs, num_clusters, num_blocks, maxNumberOfBlockTypes, max_num_pairs) - pairs = nil - cluster_size = nil - - new_index = make([]uint32, num_clusters) - for i = 0; i < num_clusters; i++ { - new_index[i] = clusterBlocksLiteral_kInvalidIndex - } - pos = 0 - { - var next_index uint32 = 0 - for i = 0; i < num_blocks; i++ { - var histo histogramLiteral - var j uint - var best_out uint32 - var best_bits float64 - histogramClearLiteral(&histo) - for j = 0; uint32(j) < block_lengths[i]; j++ { - histogramAddLiteral(&histo, uint(data[pos])) - pos++ - } - - if i == 0 { - best_out = histogram_symbols[0] - } else { - best_out = histogram_symbols[i-1] - } - best_bits = histogramBitCostDistanceLiteral(&histo, &all_histograms[best_out]) - for j = 0; j < num_final_clusters; j++ { - var cur_bits float64 = histogramBitCostDistanceLiteral(&histo, &all_histograms[clusters[j]]) - if cur_bits < best_bits { - best_bits = cur_bits - best_out = clusters[j] - } - } - - histogram_symbols[i] = best_out - if new_index[best_out] == clusterBlocksLiteral_kInvalidIndex { - new_index[best_out] = next_index - next_index++ - } - } - } - - clusters = nil - all_histograms = nil - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, num_blocks) - { - var cur_length uint32 = 0 - var block_idx uint = 0 - var max_type byte = 0 - for i = 0; i < num_blocks; i++ { - cur_length += block_lengths[i] - if i+1 == num_blocks || histogram_symbols[i] != histogram_symbols[i+1] { - var id byte = byte(new_index[histogram_symbols[i]]) - split.types[block_idx] = id - split.lengths[block_idx] = cur_length - max_type = brotli_max_uint8_t(max_type, id) - cur_length = 0 - block_idx++ - } - } - - split.num_blocks = block_idx - split.num_types = uint(max_type) + 1 - } - - new_index = nil - block_lengths = nil - histogram_symbols = nil -} - -func splitByteVectorLiteral(data []byte, length uint, literals_per_histogram uint, max_histograms uint, sampling_stride_length uint, block_switch_cost float64, params *encoderParams, split *blockSplit) { - var data_size uint = histogramDataSizeLiteral() - var num_histograms uint = length/literals_per_histogram + 1 - var histograms []histogramLiteral - if num_histograms > max_histograms { - num_histograms = max_histograms - } - - if length == 0 { - split.num_types = 1 - return - } else if length < kMinLengthForBlockSplitting { - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, split.num_blocks+1) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, split.num_blocks+1) - split.num_types = 1 - split.types[split.num_blocks] = 0 - split.lengths[split.num_blocks] = uint32(length) - split.num_blocks++ - return - } - - histograms = make([]histogramLiteral, num_histograms) - - /* Find good entropy codes. */ - initialEntropyCodesLiteral(data, length, sampling_stride_length, num_histograms, histograms) - - refineEntropyCodesLiteral(data, length, sampling_stride_length, num_histograms, histograms) - { - var block_ids []byte = make([]byte, length) - var num_blocks uint = 0 - var bitmaplen uint = (num_histograms + 7) >> 3 - var insert_cost []float64 = make([]float64, (data_size * num_histograms)) - var cost []float64 = make([]float64, num_histograms) - var switch_signal []byte = make([]byte, (length * bitmaplen)) - var new_id []uint16 = make([]uint16, num_histograms) - var iters uint - if params.quality < hqZopflificationQuality { - iters = 3 - } else { - iters = 10 - } - /* Find a good path through literals with the good entropy codes. */ - - var i uint - for i = 0; i < iters; i++ { - num_blocks = findBlocksLiteral(data, length, block_switch_cost, num_histograms, histograms, insert_cost, cost, switch_signal, block_ids) - num_histograms = remapBlockIdsLiteral(block_ids, length, new_id, num_histograms) - buildBlockHistogramsLiteral(data, length, block_ids, num_histograms, histograms) - } - - insert_cost = nil - cost = nil - switch_signal = nil - new_id = nil - histograms = nil - clusterBlocksLiteral(data, length, num_blocks, block_ids, split) - block_ids = nil - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/brotli_bit_stream.go b/src/vendor/github.com/andybalholm/brotli/brotli_bit_stream.go deleted file mode 100644 index d098d320..00000000 --- a/src/vendor/github.com/andybalholm/brotli/brotli_bit_stream.go +++ /dev/null @@ -1,1435 +0,0 @@ -package brotli - -import ( - "slices" - "sync" -) - -const maxHuffmanTreeSize = (2*numCommandSymbols + 1) - -/* -The maximum size of Huffman dictionary for distances assuming that - - NPOSTFIX = 0 and NDIRECT = 0. -*/ -const maxSimpleDistanceAlphabetSize = 140 - -/* -Represents the range of values belonging to a prefix code: - - [offset, offset + 2^nbits) -*/ -type prefixCodeRange struct { - offset uint32 - nbits uint32 -} - -var kBlockLengthPrefixCode = [numBlockLenSymbols]prefixCodeRange{ - prefixCodeRange{1, 2}, - prefixCodeRange{5, 2}, - prefixCodeRange{9, 2}, - prefixCodeRange{13, 2}, - prefixCodeRange{17, 3}, - prefixCodeRange{25, 3}, - prefixCodeRange{33, 3}, - prefixCodeRange{41, 3}, - prefixCodeRange{49, 4}, - prefixCodeRange{65, 4}, - prefixCodeRange{81, 4}, - prefixCodeRange{97, 4}, - prefixCodeRange{113, 5}, - prefixCodeRange{145, 5}, - prefixCodeRange{177, 5}, - prefixCodeRange{209, 5}, - prefixCodeRange{241, 6}, - prefixCodeRange{305, 6}, - prefixCodeRange{369, 7}, - prefixCodeRange{497, 8}, - prefixCodeRange{753, 9}, - prefixCodeRange{1265, 10}, - prefixCodeRange{2289, 11}, - prefixCodeRange{4337, 12}, - prefixCodeRange{8433, 13}, - prefixCodeRange{16625, 24}, -} - -func blockLengthPrefixCode(len uint32) uint32 { - var code uint32 - if len >= 177 { - if len >= 753 { - code = 20 - } else { - code = 14 - } - } else if len >= 41 { - code = 7 - } else { - code = 0 - } - for code < (numBlockLenSymbols-1) && len >= kBlockLengthPrefixCode[code+1].offset { - code++ - } - return code -} - -func getBlockLengthPrefixCode(len uint32, code *uint, n_extra *uint32, extra *uint32) { - *code = uint(blockLengthPrefixCode(uint32(len))) - *n_extra = kBlockLengthPrefixCode[*code].nbits - *extra = len - kBlockLengthPrefixCode[*code].offset -} - -type blockTypeCodeCalculator struct { - last_type uint - second_last_type uint -} - -func initBlockTypeCodeCalculator(self *blockTypeCodeCalculator) { - self.last_type = 1 - self.second_last_type = 0 -} - -func nextBlockTypeCode(calculator *blockTypeCodeCalculator, type_ byte) uint { - var type_code uint - if uint(type_) == calculator.last_type+1 { - type_code = 1 - } else if uint(type_) == calculator.second_last_type { - type_code = 0 - } else { - type_code = uint(type_) + 2 - } - calculator.second_last_type = calculator.last_type - calculator.last_type = uint(type_) - return type_code -} - -/* -|nibblesbits| represents the 2 bits to encode MNIBBLES (0-3) - - REQUIRES: length > 0 - REQUIRES: length <= (1 << 24) -*/ -func encodeMlen(length uint, bits *uint64, numbits *uint, nibblesbits *uint64) { - var lg uint - if length == 1 { - lg = 1 - } else { - lg = uint(log2FloorNonZero(uint(uint32(length-1)))) + 1 - } - var tmp uint - if lg < 16 { - tmp = 16 - } else { - tmp = (lg + 3) - } - var mnibbles uint = tmp / 4 - assert(length > 0) - assert(length <= 1<<24) - assert(lg <= 24) - *nibblesbits = uint64(mnibbles) - 4 - *numbits = mnibbles * 4 - *bits = uint64(length) - 1 -} - -func storeCommandExtra(cmd *command, storage_ix *uint, storage []byte) { - var copylen_code uint32 = commandCopyLenCode(cmd) - var inscode uint16 = getInsertLengthCode(uint(cmd.insert_len_)) - var copycode uint16 = getCopyLengthCode(uint(copylen_code)) - var insnumextra uint32 = getInsertExtra(inscode) - var insextraval uint64 = uint64(cmd.insert_len_) - uint64(getInsertBase(inscode)) - var copyextraval uint64 = uint64(copylen_code) - uint64(getCopyBase(copycode)) - var bits uint64 = copyextraval< 0 - REQUIRES: length <= (1 << 24) -*/ -func storeCompressedMetaBlockHeader(is_final_block bool, length uint, storage_ix *uint, storage []byte) { - var lenbits uint64 - var nlenbits uint - var nibblesbits uint64 - var is_final uint64 - if is_final_block { - is_final = 1 - } else { - is_final = 0 - } - - /* Write ISLAST bit. */ - writeBits(1, is_final, storage_ix, storage) - - /* Write ISEMPTY bit. */ - if is_final_block { - writeBits(1, 0, storage_ix, storage) - } - - encodeMlen(length, &lenbits, &nlenbits, &nibblesbits) - writeBits(2, nibblesbits, storage_ix, storage) - writeBits(nlenbits, lenbits, storage_ix, storage) - - if !is_final_block { - /* Write ISUNCOMPRESSED bit. */ - writeBits(1, 0, storage_ix, storage) - } -} - -/* -Stores the uncompressed meta-block header. - - REQUIRES: length > 0 - REQUIRES: length <= (1 << 24) -*/ -func storeUncompressedMetaBlockHeader(length uint, storage_ix *uint, storage []byte) { - var lenbits uint64 - var nlenbits uint - var nibblesbits uint64 - - /* Write ISLAST bit. - Uncompressed block cannot be the last one, so set to 0. */ - writeBits(1, 0, storage_ix, storage) - - encodeMlen(length, &lenbits, &nlenbits, &nibblesbits) - writeBits(2, nibblesbits, storage_ix, storage) - writeBits(nlenbits, lenbits, storage_ix, storage) - - /* Write ISUNCOMPRESSED bit. */ - writeBits(1, 1, storage_ix, storage) -} - -var storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder = [codeLengthCodes]byte{1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15} - -var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols = [6]byte{0, 7, 3, 2, 1, 15} -var storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths = [6]byte{2, 4, 3, 2, 2, 4} - -func storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes int, code_length_bitdepth []byte, storage_ix *uint, storage []byte) { - var skip_some uint = 0 - var codes_to_store uint = codeLengthCodes - /* The bit lengths of the Huffman code over the code length alphabet - are compressed with the following static Huffman code: - Symbol Code - ------ ---- - 0 00 - 1 1110 - 2 110 - 3 01 - 4 10 - 5 1111 */ - - /* Throw away trailing zeros: */ - if num_codes > 1 { - for ; codes_to_store > 0; codes_to_store-- { - if code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[codes_to_store-1]] != 0 { - break - } - } - } - - if code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[0]] == 0 && code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[1]] == 0 { - skip_some = 2 /* skips two. */ - if code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[2]] == 0 { - skip_some = 3 /* skips three. */ - } - } - - writeBits(2, uint64(skip_some), storage_ix, storage) - { - var i uint - for i = skip_some; i < codes_to_store; i++ { - var l uint = uint(code_length_bitdepth[storeHuffmanTreeOfHuffmanTreeToBitMask_kStorageOrder[i]]) - writeBits(uint(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeBitLengths[l]), uint64(storeHuffmanTreeOfHuffmanTreeToBitMask_kHuffmanBitLengthHuffmanCodeSymbols[l]), storage_ix, storage) - } - } -} - -func storeHuffmanTreeToBitMask(huffman_tree_size uint, huffman_tree []byte, huffman_tree_extra_bits []byte, code_length_bitdepth []byte, code_length_bitdepth_symbols []uint16, storage_ix *uint, storage []byte) { - var i uint - for i = 0; i < huffman_tree_size; i++ { - var ix uint = uint(huffman_tree[i]) - writeBits(uint(code_length_bitdepth[ix]), uint64(code_length_bitdepth_symbols[ix]), storage_ix, storage) - - /* Extra bits */ - switch ix { - case repeatPreviousCodeLength: - writeBits(2, uint64(huffman_tree_extra_bits[i]), storage_ix, storage) - - case repeatZeroCodeLength: - writeBits(3, uint64(huffman_tree_extra_bits[i]), storage_ix, storage) - } - } -} - -func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max_bits uint, storage_ix *uint, storage []byte) { - /* value of 1 indicates a simple Huffman code */ - writeBits(2, 1, storage_ix, storage) - - writeBits(2, uint64(num_symbols)-1, storage_ix, storage) /* NSYM - 1 */ - { - /* Sort */ - var i uint - for i = 0; i < num_symbols; i++ { - var j uint - for j = i + 1; j < num_symbols; j++ { - if depths[symbols[j]] < depths[symbols[i]] { - var tmp uint = symbols[j] - symbols[j] = symbols[i] - symbols[i] = tmp - } - } - } - } - - if num_symbols == 2 { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - } else if num_symbols == 3 { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[2]), storage_ix, storage) - } else { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[2]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[3]), storage_ix, storage) - - /* tree-select */ - var tmp int - if depths[symbols[0]] == 1 { - tmp = 1 - } else { - tmp = 0 - } - writeBits(1, uint64(tmp), storage_ix, storage) - } -} - -/* -num = alphabet size - - depths = symbol depths -*/ -func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, storage_ix *uint, storage []byte) { - var huffman_tree [numCommandSymbols]byte - var huffman_tree_extra_bits [numCommandSymbols]byte - var huffman_tree_size uint = 0 - var code_length_bitdepth = [codeLengthCodes]byte{0} - var code_length_bitdepth_symbols [codeLengthCodes]uint16 - var huffman_tree_histogram = [codeLengthCodes]uint32{0} - var i uint - var num_codes int = 0 - /* Write the Huffman tree into the brotli-representation. - The command alphabet is the largest, so this allocation will fit all - alphabets. */ - - var code uint = 0 - - assert(num <= numCommandSymbols) - - writeHuffmanTree(depths, num, &huffman_tree_size, huffman_tree[:], huffman_tree_extra_bits[:]) - - /* Calculate the statistics of the Huffman tree in brotli-representation. */ - for i = 0; i < huffman_tree_size; i++ { - huffman_tree_histogram[huffman_tree[i]]++ - } - - for i = 0; i < codeLengthCodes; i++ { - if huffman_tree_histogram[i] != 0 { - if num_codes == 0 { - code = i - num_codes = 1 - } else if num_codes == 1 { - num_codes = 2 - break - } - } - } - - /* Calculate another Huffman tree to use for compressing both the - earlier Huffman tree with. */ - createHuffmanTree(huffman_tree_histogram[:], codeLengthCodes, 5, tree, code_length_bitdepth[:]) - - convertBitDepthsToSymbols(code_length_bitdepth[:], codeLengthCodes, code_length_bitdepth_symbols[:]) - - /* Now, we have all the data, let's start storing it */ - storeHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth[:], storage_ix, storage) - - if num_codes == 1 { - code_length_bitdepth[code] = 0 - } - - /* Store the real Huffman tree now. */ - storeHuffmanTreeToBitMask(huffman_tree_size, huffman_tree[:], huffman_tree_extra_bits[:], code_length_bitdepth[:], code_length_bitdepth_symbols[:], storage_ix, storage) -} - -/* -Builds a Huffman tree from histogram[0:length] into depth[0:length] and - - bits[0:length] and stores the encoded tree to the bit stream. -*/ -func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabet_size uint, tree []huffmanTree, depth []byte, bits []uint16, storage_ix *uint, storage []byte) { - var count uint = 0 - var s4 = [4]uint{0} - var i uint - var max_bits uint = 0 - for i = 0; i < histogram_length; i++ { - if histogram[i] != 0 { - if count < 4 { - s4[count] = i - } else if count > 4 { - break - } - - count++ - } - } - { - var max_bits_counter uint = alphabet_size - 1 - for max_bits_counter != 0 { - max_bits_counter >>= 1 - max_bits++ - } - } - - if count <= 1 { - writeBits(4, 1, storage_ix, storage) - writeBits(max_bits, uint64(s4[0]), storage_ix, storage) - depth[s4[0]] = 0 - bits[s4[0]] = 0 - return - } - - for i := 0; i < int(histogram_length); i++ { - depth[i] = 0 - } - createHuffmanTree(histogram, histogram_length, 15, tree, depth) - convertBitDepthsToSymbols(depth, histogram_length, bits) - - if count <= 4 { - storeSimpleHuffmanTree(depth, s4[:], count, max_bits, storage_ix, storage) - } else { - storeHuffmanTree(depth, histogram_length, tree, storage_ix, storage) - } -} - -func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_bits uint, depth []byte, bits []uint16, storage_ix *uint, storage []byte) { - var count uint = 0 - var symbols = [4]uint{0} - var length uint = 0 - var total uint = histogram_total - for total != 0 { - if histogram[length] != 0 { - if count < 4 { - symbols[count] = length - } - - count++ - total -= uint(histogram[length]) - } - - length++ - } - - if count <= 1 { - writeBits(4, 1, storage_ix, storage) - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - depth[symbols[0]] = 0 - bits[symbols[0]] = 0 - return - } - - chooseBitDepths(histogram[:length], depth[:length], 14) - - convertBitDepthsToSymbols(depth, length, bits) - if count <= 4 { - var i uint - - /* value of 1 indicates a simple Huffman code */ - writeBits(2, 1, storage_ix, storage) - - writeBits(2, uint64(count)-1, storage_ix, storage) /* NSYM - 1 */ - - /* Sort */ - for i = 0; i < count; i++ { - var j uint - for j = i + 1; j < count; j++ { - if depth[symbols[j]] < depth[symbols[i]] { - var tmp uint = symbols[j] - symbols[j] = symbols[i] - symbols[i] = tmp - } - } - } - - if count == 2 { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - } else if count == 3 { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[2]), storage_ix, storage) - } else { - writeBits(max_bits, uint64(symbols[0]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[1]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[2]), storage_ix, storage) - writeBits(max_bits, uint64(symbols[3]), storage_ix, storage) - - /* tree-select */ - var tmp int - if depth[symbols[0]] == 1 { - tmp = 1 - } else { - tmp = 0 - } - writeBits(1, uint64(tmp), storage_ix, storage) - } - } else { - var previous_value byte = 8 - var i uint - - /* Complex Huffman Tree */ - storeStaticCodeLengthCode(storage_ix, storage) - - /* Actual RLE coding. */ - for i = 0; i < length; { - var value byte = depth[i] - var reps uint = 1 - var k uint - for k = i + 1; k < length && depth[k] == value; k++ { - reps++ - } - - i += reps - if value == 0 { - writeBits(uint(kZeroRepsDepth[reps]), kZeroRepsBits[reps], storage_ix, storage) - } else { - if previous_value != value { - writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]), storage_ix, storage) - reps-- - } - - if reps < 3 { - for reps != 0 { - reps-- - writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]), storage_ix, storage) - } - } else { - reps -= 3 - writeBits(uint(kNonZeroRepsDepth[reps]), kNonZeroRepsBits[reps], storage_ix, storage) - } - - previous_value = value - } - } - } -} - -type symbolAndCount struct { - symbol uint32 - count uint32 -} - -func chooseBitDepths(histogram []uint32, depth []byte, maxBits int) { - totalCodeSpace := 1 << maxBits - symbols := make([]symbolAndCount, 0, 704 /* static capacity so that it will be stack allocated */) - var totalCount uint32 = 0 - for i, n := range histogram { - if n != 0 { - symbols = append(symbols, symbolAndCount{ - symbol: uint32(i), - count: n, - }) - totalCount += n - } - } - slices.SortFunc(symbols, func(a, b symbolAndCount) int { - return int(b.count) - int(a.count) - }) - - // boundaries contains indexes into symbols such that (for example) - // boundaries[8] is the index of the first 8-bit symbol. - boundaries := make([]int, maxBits+1, 20 /* static capacity for stack allocation */) - - codeSpaceUsed := 0 - - // Assign initial boundaries conservatively, making sure no symbol uses more - // than its share of code space. - totalRatio := float64(totalCount) / float64(totalCodeSpace) - currentDepth := 1 - for i, symbol := range symbols { - for currentDepth < maxBits && float64(symbol.count)/float64(int(1)<<(maxBits-currentDepth)) < totalRatio { - currentDepth++ - boundaries[currentDepth] = i - } - codeSpaceUsed += 1 << (maxBits - currentDepth) - } - for i := currentDepth + 1; i <= maxBits; i++ { - boundaries[i] = len(symbols) - } - - // Move the boundaries till the code space is filled. - for codeSpaceUsed < totalCodeSpace { - available := totalCodeSpace - codeSpaceUsed - // Find the most efficient boundary to move, based on the ratio of how - // many times the symbol was used to how much code space will be consumed. - bestRatio := 0.0 - bestBoundary := 0 - for i := 2; i <= maxBits; i++ { - cost := 1 << (maxBits - i) // code space that would be used by moving this boundary - if cost > available { - continue - } - if boundaries[i] == len(symbols) { - continue - } - if i < maxBits && boundaries[i] == boundaries[i+1] { - continue - } - ratio := float64(symbols[boundaries[i]].count) / float64(cost) - if ratio > bestRatio { - bestRatio = ratio - bestBoundary = i - } - } - boundaries[bestBoundary]++ - codeSpaceUsed += 1 << (maxBits - bestBoundary) - } - - for i := range depth { - depth[i] = 0 - } - for i := 1; i < maxBits; i++ { - for j := boundaries[i]; j < boundaries[i+1]; j++ { - depth[symbols[j].symbol] = byte(i) - } - } - for j := boundaries[maxBits]; j < len(symbols); j++ { - depth[symbols[j].symbol] = byte(maxBits) - } -} - -func buildAndStoreHuffmanTreeFastBW(histogram []uint32, histogram_total uint, max_bits uint, depth []byte, bits []uint16, bw *bitWriter) { - var count uint = 0 - var symbols = [4]uint{0} - var length uint = 0 - var total uint = histogram_total - for total != 0 { - if histogram[length] != 0 { - if count < 4 { - symbols[count] = length - } - - count++ - total -= uint(histogram[length]) - } - - length++ - } - - if count <= 1 { - bw.writeBits(4, 1) - bw.writeBits(max_bits, uint64(symbols[0])) - depth[symbols[0]] = 0 - bits[symbols[0]] = 0 - return - } - - chooseBitDepths(histogram[:length], depth[:length], 14) - - convertBitDepthsToSymbols(depth, length, bits) - if count <= 4 { - var i uint - - /* value of 1 indicates a simple Huffman code */ - bw.writeBits(2, 1) - - bw.writeBits(2, uint64(count)-1) /* NSYM - 1 */ - - /* Sort */ - for i = 0; i < count; i++ { - var j uint - for j = i + 1; j < count; j++ { - if depth[symbols[j]] < depth[symbols[i]] { - var tmp uint = symbols[j] - symbols[j] = symbols[i] - symbols[i] = tmp - } - } - } - - if count == 2 { - bw.writeBits(max_bits, uint64(symbols[0])) - bw.writeBits(max_bits, uint64(symbols[1])) - } else if count == 3 { - bw.writeBits(max_bits, uint64(symbols[0])) - bw.writeBits(max_bits, uint64(symbols[1])) - bw.writeBits(max_bits, uint64(symbols[2])) - } else { - bw.writeBits(max_bits, uint64(symbols[0])) - bw.writeBits(max_bits, uint64(symbols[1])) - bw.writeBits(max_bits, uint64(symbols[2])) - bw.writeBits(max_bits, uint64(symbols[3])) - - /* tree-select */ - bw.writeSingleBit(depth[symbols[0]] == 1) - } - } else { - var previous_value byte = 8 - var i uint - - /* Complex Huffman Tree */ - storeStaticCodeLengthCodeBW(bw) - - /* Actual RLE coding. */ - for i = 0; i < length; { - var value byte = depth[i] - var reps uint = 1 - var k uint - for k = i + 1; k < length && depth[k] == value; k++ { - reps++ - } - - i += reps - if value == 0 { - bw.writeBits(uint(kZeroRepsDepth[reps]), kZeroRepsBits[reps]) - } else { - if previous_value != value { - bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value])) - reps-- - } - - if reps < 3 { - for reps != 0 { - reps-- - bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value])) - } - } else { - reps -= 3 - bw.writeBits(uint(kNonZeroRepsDepth[reps]), kNonZeroRepsBits[reps]) - } - - previous_value = value - } - } - } -} - -func indexOf(v []byte, v_size uint, value byte) uint { - var i uint = 0 - for ; i < v_size; i++ { - if v[i] == value { - return i - } - } - - return i -} - -func moveToFront(v []byte, index uint) { - var value byte = v[index] - var i uint - for i = index; i != 0; i-- { - v[i] = v[i-1] - } - - v[0] = value -} - -func moveToFrontTransform(v_in []uint32, v_size uint, v_out []uint32) { - var i uint - var mtf [256]byte - var max_value uint32 - if v_size == 0 { - return - } - - max_value = v_in[0] - for i = 1; i < v_size; i++ { - if v_in[i] > max_value { - max_value = v_in[i] - } - } - - assert(max_value < 256) - for i = 0; uint32(i) <= max_value; i++ { - mtf[i] = byte(i) - } - { - var mtf_size uint = uint(max_value + 1) - for i = 0; i < v_size; i++ { - var index uint = indexOf(mtf[:], mtf_size, byte(v_in[i])) - assert(index < mtf_size) - v_out[i] = uint32(index) - moveToFront(mtf[:], index) - } - } -} - -/* -Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of - - the run length plus extra bits (lower 9 bits is the prefix code and the rest - are the extra bits). Non-zero values in v[] are shifted by - *max_length_prefix. Will not create prefix codes bigger than the initial - value of *max_run_length_prefix. The prefix code of run length L is simply - Log2Floor(L) and the number of extra bits is the same as the prefix code. -*/ -func runLengthCodeZeros(in_size uint, v []uint32, out_size *uint, max_run_length_prefix *uint32) { - var max_reps uint32 = 0 - var i uint - var max_prefix uint32 - for i = 0; i < in_size; { - var reps uint32 = 0 - for ; i < in_size && v[i] != 0; i++ { - } - for ; i < in_size && v[i] == 0; i++ { - reps++ - } - - max_reps = brotli_max_uint32_t(reps, max_reps) - } - - if max_reps > 0 { - max_prefix = log2FloorNonZero(uint(max_reps)) - } else { - max_prefix = 0 - } - max_prefix = brotli_min_uint32_t(max_prefix, *max_run_length_prefix) - *max_run_length_prefix = max_prefix - *out_size = 0 - for i = 0; i < in_size; { - assert(*out_size <= i) - if v[i] != 0 { - v[*out_size] = v[i] + *max_run_length_prefix - i++ - (*out_size)++ - } else { - var reps uint32 = 1 - var k uint - for k = i + 1; k < in_size && v[k] == 0; k++ { - reps++ - } - - i += uint(reps) - for reps != 0 { - if reps < 2< 0) - writeSingleBit(use_rle, storage_ix, storage) - if use_rle { - writeBits(4, uint64(max_run_length_prefix)-1, storage_ix, storage) - } - } - - buildAndStoreHuffmanTree(histogram[:], uint(uint32(num_clusters)+max_run_length_prefix), uint(uint32(num_clusters)+max_run_length_prefix), tree, depths[:], bits[:], storage_ix, storage) - for i = 0; i < num_rle_symbols; i++ { - var rle_symbol uint32 = rle_symbols[i] & encodeContextMap_kSymbolMask - var extra_bits_val uint32 = rle_symbols[i] >> symbolBits - writeBits(uint(depths[rle_symbol]), uint64(bits[rle_symbol]), storage_ix, storage) - if rle_symbol > 0 && rle_symbol <= max_run_length_prefix { - writeBits(uint(rle_symbol), uint64(extra_bits_val), storage_ix, storage) - } - } - - writeBits(1, 1, storage_ix, storage) /* use move-to-front */ - rle_symbols = nil -} - -/* Stores the block switch command with index block_ix to the bit stream. */ -func storeBlockSwitch(code *blockSplitCode, block_len uint32, block_type byte, is_first_block bool, storage_ix *uint, storage []byte) { - var typecode uint = nextBlockTypeCode(&code.type_code_calculator, block_type) - var lencode uint - var len_nextra uint32 - var len_extra uint32 - if !is_first_block { - writeBits(uint(code.type_depths[typecode]), uint64(code.type_bits[typecode]), storage_ix, storage) - } - - getBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra) - - writeBits(uint(code.length_depths[lencode]), uint64(code.length_bits[lencode]), storage_ix, storage) - writeBits(uint(len_nextra), uint64(len_extra), storage_ix, storage) -} - -/* -Builds a BlockSplitCode data structure from the block split given by the - - vector of block types and block lengths and stores it to the bit stream. -*/ -func buildAndStoreBlockSplitCode(types []byte, lengths []uint32, num_blocks uint, num_types uint, tree []huffmanTree, code *blockSplitCode, storage_ix *uint, storage []byte) { - var type_histo [maxBlockTypeSymbols]uint32 - var length_histo [numBlockLenSymbols]uint32 - var i uint - var type_code_calculator blockTypeCodeCalculator - for i := 0; i < int(num_types+2); i++ { - type_histo[i] = 0 - } - length_histo = [numBlockLenSymbols]uint32{} - initBlockTypeCodeCalculator(&type_code_calculator) - for i = 0; i < num_blocks; i++ { - var type_code uint = nextBlockTypeCode(&type_code_calculator, types[i]) - if i != 0 { - type_histo[type_code]++ - } - length_histo[blockLengthPrefixCode(lengths[i])]++ - } - - storeVarLenUint8(num_types-1, storage_ix, storage) - if num_types > 1 { /* TODO: else? could StoreBlockSwitch occur? */ - buildAndStoreHuffmanTree(type_histo[0:], num_types+2, num_types+2, tree, code.type_depths[0:], code.type_bits[0:], storage_ix, storage) - buildAndStoreHuffmanTree(length_histo[0:], numBlockLenSymbols, numBlockLenSymbols, tree, code.length_depths[0:], code.length_bits[0:], storage_ix, storage) - storeBlockSwitch(code, lengths[0], types[0], true, storage_ix, storage) - } -} - -/* Stores a context map where the histogram type is always the block type. */ -func storeTrivialContextMap(num_types uint, context_bits uint, tree []huffmanTree, storage_ix *uint, storage []byte) { - storeVarLenUint8(num_types-1, storage_ix, storage) - if num_types > 1 { - var repeat_code uint = context_bits - 1 - var repeat_bits uint = (1 << repeat_code) - 1 - var alphabet_size uint = num_types + repeat_code - var histogram [maxContextMapSymbols]uint32 - var depths [maxContextMapSymbols]byte - var bits [maxContextMapSymbols]uint16 - var i uint - for i := 0; i < int(alphabet_size); i++ { - histogram[i] = 0 - } - - /* Write RLEMAX. */ - writeBits(1, 1, storage_ix, storage) - - writeBits(4, uint64(repeat_code)-1, storage_ix, storage) - histogram[repeat_code] = uint32(num_types) - histogram[0] = 1 - for i = context_bits; i < alphabet_size; i++ { - histogram[i] = 1 - } - - buildAndStoreHuffmanTree(histogram[:], alphabet_size, alphabet_size, tree, depths[:], bits[:], storage_ix, storage) - for i = 0; i < num_types; i++ { - var tmp uint - if i == 0 { - tmp = 0 - } else { - tmp = i + context_bits - 1 - } - var code uint = tmp - writeBits(uint(depths[code]), uint64(bits[code]), storage_ix, storage) - writeBits(uint(depths[repeat_code]), uint64(bits[repeat_code]), storage_ix, storage) - writeBits(repeat_code, uint64(repeat_bits), storage_ix, storage) - } - - /* Write IMTF (inverse-move-to-front) bit. */ - writeBits(1, 1, storage_ix, storage) - } -} - -/* Manages the encoding of one block category (literal, command or distance). */ -type blockEncoder struct { - histogram_length_ uint - num_block_types_ uint - block_types_ []byte - block_lengths_ []uint32 - num_blocks_ uint - block_split_code_ blockSplitCode - block_ix_ uint - block_len_ uint - entropy_ix_ uint - depths_ []byte - bits_ []uint16 -} - -var blockEncoderPool sync.Pool - -func getBlockEncoder(histogram_length uint, num_block_types uint, block_types []byte, block_lengths []uint32, num_blocks uint) *blockEncoder { - self, _ := blockEncoderPool.Get().(*blockEncoder) - - if self != nil { - self.block_ix_ = 0 - self.entropy_ix_ = 0 - self.depths_ = self.depths_[:0] - self.bits_ = self.bits_[:0] - } else { - self = &blockEncoder{} - } - - self.histogram_length_ = histogram_length - self.num_block_types_ = num_block_types - self.block_types_ = block_types - self.block_lengths_ = block_lengths - self.num_blocks_ = num_blocks - initBlockTypeCodeCalculator(&self.block_split_code_.type_code_calculator) - if num_blocks == 0 { - self.block_len_ = 0 - } else { - self.block_len_ = uint(block_lengths[0]) - } - - return self -} - -func cleanupBlockEncoder(self *blockEncoder) { - blockEncoderPool.Put(self) -} - -/* -Creates entropy codes of block lengths and block types and stores them - - to the bit stream. -*/ -func buildAndStoreBlockSwitchEntropyCodes(self *blockEncoder, tree []huffmanTree, storage_ix *uint, storage []byte) { - buildAndStoreBlockSplitCode(self.block_types_, self.block_lengths_, self.num_blocks_, self.num_block_types_, tree, &self.block_split_code_, storage_ix, storage) -} - -/* -Stores the next symbol with the entropy code of the current block type. - - Updates the block type and block length at block boundaries. -*/ -func storeSymbol(self *blockEncoder, symbol uint, storage_ix *uint, storage []byte) { - if self.block_len_ == 0 { - self.block_ix_++ - var block_ix uint = self.block_ix_ - var block_len uint32 = self.block_lengths_[block_ix] - var block_type byte = self.block_types_[block_ix] - self.block_len_ = uint(block_len) - self.entropy_ix_ = uint(block_type) * self.histogram_length_ - storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, storage_ix, storage) - } - - self.block_len_-- - { - var ix uint = self.entropy_ix_ + symbol - writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix]), storage_ix, storage) - } -} - -/* -Stores the next symbol with the entropy code of the current block type and - - context value. - Updates the block type and block length at block boundaries. -*/ -func storeSymbolWithContext(self *blockEncoder, symbol uint, context uint, context_map []uint32, storage_ix *uint, storage []byte, context_bits uint) { - if self.block_len_ == 0 { - self.block_ix_++ - var block_ix uint = self.block_ix_ - var block_len uint32 = self.block_lengths_[block_ix] - var block_type byte = self.block_types_[block_ix] - self.block_len_ = uint(block_len) - self.entropy_ix_ = uint(block_type) << context_bits - storeBlockSwitch(&self.block_split_code_, block_len, block_type, false, storage_ix, storage) - } - - self.block_len_-- - { - var histo_ix uint = uint(context_map[self.entropy_ix_+context]) - var ix uint = histo_ix*self.histogram_length_ + symbol - writeBits(uint(self.depths_[ix]), uint64(self.bits_[ix]), storage_ix, storage) - } -} - -func buildAndStoreEntropyCodesLiteral(self *blockEncoder, histograms []histogramLiteral, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) { - var table_size uint = histograms_size * self.histogram_length_ - if cap(self.depths_) < int(table_size) { - self.depths_ = make([]byte, table_size) - } else { - self.depths_ = self.depths_[:table_size] - } - if cap(self.bits_) < int(table_size) { - self.bits_ = make([]uint16, table_size) - } else { - self.bits_ = self.bits_[:table_size] - } - { - var i uint - for i = 0; i < histograms_size; i++ { - var ix uint = i * self.histogram_length_ - buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage) - } - } -} - -func buildAndStoreEntropyCodesCommand(self *blockEncoder, histograms []histogramCommand, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) { - var table_size uint = histograms_size * self.histogram_length_ - if cap(self.depths_) < int(table_size) { - self.depths_ = make([]byte, table_size) - } else { - self.depths_ = self.depths_[:table_size] - } - if cap(self.bits_) < int(table_size) { - self.bits_ = make([]uint16, table_size) - } else { - self.bits_ = self.bits_[:table_size] - } - { - var i uint - for i = 0; i < histograms_size; i++ { - var ix uint = i * self.histogram_length_ - buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage) - } - } -} - -func buildAndStoreEntropyCodesDistance(self *blockEncoder, histograms []histogramDistance, histograms_size uint, alphabet_size uint, tree []huffmanTree, storage_ix *uint, storage []byte) { - var table_size uint = histograms_size * self.histogram_length_ - if cap(self.depths_) < int(table_size) { - self.depths_ = make([]byte, table_size) - } else { - self.depths_ = self.depths_[:table_size] - } - if cap(self.bits_) < int(table_size) { - self.bits_ = make([]uint16, table_size) - } else { - self.bits_ = self.bits_[:table_size] - } - { - var i uint - for i = 0; i < histograms_size; i++ { - var ix uint = i * self.histogram_length_ - buildAndStoreHuffmanTree(histograms[i].data_[0:], self.histogram_length_, alphabet_size, tree, self.depths_[ix:], self.bits_[ix:], storage_ix, storage) - } - } -} - -func jumpToByteBoundary(storage_ix *uint, storage []byte) { - *storage_ix = (*storage_ix + 7) &^ 7 - storage[*storage_ix>>3] = 0 -} - -func storeMetaBlock(input []byte, start_pos uint, length uint, mask uint, prev_byte byte, prev_byte2 byte, is_last bool, params *encoderParams, literal_context_mode int, commands []command, mb *metaBlockSplit, storage_ix *uint, storage []byte) { - var pos uint = start_pos - var i uint - var num_distance_symbols uint32 = params.dist.alphabet_size - var num_effective_distance_symbols uint32 = num_distance_symbols - var tree []huffmanTree - var literal_context_lut contextLUT = getContextLUT(literal_context_mode) - var dist *distanceParams = ¶ms.dist - if params.large_window && num_effective_distance_symbols > numHistogramDistanceSymbols { - num_effective_distance_symbols = numHistogramDistanceSymbols - } - - storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage) - - tree = make([]huffmanTree, maxHuffmanTreeSize) - literal_enc := getBlockEncoder(numLiteralSymbols, mb.literal_split.num_types, mb.literal_split.types, mb.literal_split.lengths, mb.literal_split.num_blocks) - command_enc := getBlockEncoder(numCommandSymbols, mb.command_split.num_types, mb.command_split.types, mb.command_split.lengths, mb.command_split.num_blocks) - distance_enc := getBlockEncoder(uint(num_effective_distance_symbols), mb.distance_split.num_types, mb.distance_split.types, mb.distance_split.lengths, mb.distance_split.num_blocks) - - buildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage) - buildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage) - buildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage) - - writeBits(2, uint64(dist.distance_postfix_bits), storage_ix, storage) - writeBits(4, uint64(dist.num_direct_distance_codes)>>dist.distance_postfix_bits, storage_ix, storage) - for i = 0; i < mb.literal_split.num_types; i++ { - writeBits(2, uint64(literal_context_mode), storage_ix, storage) - } - - if mb.literal_context_map_size == 0 { - storeTrivialContextMap(mb.literal_histograms_size, literalContextBits, tree, storage_ix, storage) - } else { - encodeContextMap(mb.literal_context_map, mb.literal_context_map_size, mb.literal_histograms_size, tree, storage_ix, storage) - } - - if mb.distance_context_map_size == 0 { - storeTrivialContextMap(mb.distance_histograms_size, distanceContextBits, tree, storage_ix, storage) - } else { - encodeContextMap(mb.distance_context_map, mb.distance_context_map_size, mb.distance_histograms_size, tree, storage_ix, storage) - } - - buildAndStoreEntropyCodesLiteral(literal_enc, mb.literal_histograms, mb.literal_histograms_size, numLiteralSymbols, tree, storage_ix, storage) - buildAndStoreEntropyCodesCommand(command_enc, mb.command_histograms, mb.command_histograms_size, numCommandSymbols, tree, storage_ix, storage) - buildAndStoreEntropyCodesDistance(distance_enc, mb.distance_histograms, mb.distance_histograms_size, uint(num_distance_symbols), tree, storage_ix, storage) - tree = nil - - for _, cmd := range commands { - var cmd_code uint = uint(cmd.cmd_prefix_) - storeSymbol(command_enc, cmd_code, storage_ix, storage) - storeCommandExtra(&cmd, storage_ix, storage) - if mb.literal_context_map_size == 0 { - var j uint - for j = uint(cmd.insert_len_); j != 0; j-- { - storeSymbol(literal_enc, uint(input[pos&mask]), storage_ix, storage) - pos++ - } - } else { - var j uint - for j = uint(cmd.insert_len_); j != 0; j-- { - var context uint = uint(getContext(prev_byte, prev_byte2, literal_context_lut)) - var literal byte = input[pos&mask] - storeSymbolWithContext(literal_enc, uint(literal), context, mb.literal_context_map, storage_ix, storage, literalContextBits) - prev_byte2 = prev_byte - prev_byte = literal - pos++ - } - } - - pos += uint(commandCopyLen(&cmd)) - if commandCopyLen(&cmd) != 0 { - prev_byte2 = input[(pos-2)&mask] - prev_byte = input[(pos-1)&mask] - if cmd.cmd_prefix_ >= 128 { - var dist_code uint = uint(cmd.dist_prefix_) & 0x3FF - var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10 - var distextra uint64 = uint64(cmd.dist_extra_) - if mb.distance_context_map_size == 0 { - storeSymbol(distance_enc, dist_code, storage_ix, storage) - } else { - var context uint = uint(commandDistanceContext(&cmd)) - storeSymbolWithContext(distance_enc, dist_code, context, mb.distance_context_map, storage_ix, storage, distanceContextBits) - } - - writeBits(uint(distnumextra), distextra, storage_ix, storage) - } - } - } - - cleanupBlockEncoder(distance_enc) - cleanupBlockEncoder(command_enc) - cleanupBlockEncoder(literal_enc) - if is_last { - jumpToByteBoundary(storage_ix, storage) - } -} - -func buildHistograms(input []byte, start_pos uint, mask uint, commands []command, lit_histo *histogramLiteral, cmd_histo *histogramCommand, dist_histo *histogramDistance) { - var pos uint = start_pos - for _, cmd := range commands { - var j uint - histogramAddCommand(cmd_histo, uint(cmd.cmd_prefix_)) - for j = uint(cmd.insert_len_); j != 0; j-- { - histogramAddLiteral(lit_histo, uint(input[pos&mask])) - pos++ - } - - pos += uint(commandCopyLen(&cmd)) - if commandCopyLen(&cmd) != 0 && cmd.cmd_prefix_ >= 128 { - histogramAddDistance(dist_histo, uint(cmd.dist_prefix_)&0x3FF) - } - } -} - -func storeDataWithHuffmanCodes(input []byte, start_pos uint, mask uint, commands []command, lit_depth []byte, lit_bits []uint16, cmd_depth []byte, cmd_bits []uint16, dist_depth []byte, dist_bits []uint16, storage_ix *uint, storage []byte) { - var pos uint = start_pos - for _, cmd := range commands { - var cmd_code uint = uint(cmd.cmd_prefix_) - var j uint - writeBits(uint(cmd_depth[cmd_code]), uint64(cmd_bits[cmd_code]), storage_ix, storage) - storeCommandExtra(&cmd, storage_ix, storage) - for j = uint(cmd.insert_len_); j != 0; j-- { - var literal byte = input[pos&mask] - writeBits(uint(lit_depth[literal]), uint64(lit_bits[literal]), storage_ix, storage) - pos++ - } - - pos += uint(commandCopyLen(&cmd)) - if commandCopyLen(&cmd) != 0 && cmd.cmd_prefix_ >= 128 { - var dist_code uint = uint(cmd.dist_prefix_) & 0x3FF - var distnumextra uint32 = uint32(cmd.dist_prefix_) >> 10 - var distextra uint32 = cmd.dist_extra_ - writeBits(uint(dist_depth[dist_code]), uint64(dist_bits[dist_code]), storage_ix, storage) - writeBits(uint(distnumextra), uint64(distextra), storage_ix, storage) - } - } -} - -func storeMetaBlockTrivial(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, storage_ix *uint, storage []byte) { - var lit_histo histogramLiteral - var cmd_histo histogramCommand - var dist_histo histogramDistance - var lit_depth [numLiteralSymbols]byte - var lit_bits [numLiteralSymbols]uint16 - var cmd_depth [numCommandSymbols]byte - var cmd_bits [numCommandSymbols]uint16 - var dist_depth [maxSimpleDistanceAlphabetSize]byte - var dist_bits [maxSimpleDistanceAlphabetSize]uint16 - var tree []huffmanTree - var num_distance_symbols uint32 = params.dist.alphabet_size - - storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage) - - histogramClearLiteral(&lit_histo) - histogramClearCommand(&cmd_histo) - histogramClearDistance(&dist_histo) - - buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo) - - writeBits(13, 0, storage_ix, storage) - - tree = make([]huffmanTree, maxHuffmanTreeSize) - buildAndStoreHuffmanTree(lit_histo.data_[:], numLiteralSymbols, numLiteralSymbols, tree, lit_depth[:], lit_bits[:], storage_ix, storage) - buildAndStoreHuffmanTree(cmd_histo.data_[:], numCommandSymbols, numCommandSymbols, tree, cmd_depth[:], cmd_bits[:], storage_ix, storage) - buildAndStoreHuffmanTree(dist_histo.data_[:], maxSimpleDistanceAlphabetSize, uint(num_distance_symbols), tree, dist_depth[:], dist_bits[:], storage_ix, storage) - tree = nil - storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], storage_ix, storage) - if is_last { - jumpToByteBoundary(storage_ix, storage) - } -} - -func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is_last bool, params *encoderParams, commands []command, storage_ix *uint, storage []byte) { - var num_distance_symbols uint32 = params.dist.alphabet_size - var distance_alphabet_bits uint32 = log2FloorNonZero(uint(num_distance_symbols-1)) + 1 - - storeCompressedMetaBlockHeader(is_last, length, storage_ix, storage) - - writeBits(13, 0, storage_ix, storage) - - if len(commands) <= 128 { - var histogram = [numLiteralSymbols]uint32{0} - var pos uint = start_pos - var num_literals uint = 0 - var lit_depth [numLiteralSymbols]byte - var lit_bits [numLiteralSymbols]uint16 - for _, cmd := range commands { - var j uint - for j = uint(cmd.insert_len_); j != 0; j-- { - histogram[input[pos&mask]]++ - pos++ - } - - num_literals += uint(cmd.insert_len_) - pos += uint(commandCopyLen(&cmd)) - } - - buildAndStoreHuffmanTreeFast(histogram[:], num_literals, /* max_bits = */ - 8, lit_depth[:], lit_bits[:], storage_ix, storage) - - storeStaticCommandHuffmanTree(storage_ix, storage) - storeStaticDistanceHuffmanTree(storage_ix, storage) - storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], kStaticCommandCodeDepth[:], kStaticCommandCodeBits[:], kStaticDistanceCodeDepth[:], kStaticDistanceCodeBits[:], storage_ix, storage) - } else { - var lit_histo histogramLiteral - var cmd_histo histogramCommand - var dist_histo histogramDistance - var lit_depth [numLiteralSymbols]byte - var lit_bits [numLiteralSymbols]uint16 - var cmd_depth [numCommandSymbols]byte - var cmd_bits [numCommandSymbols]uint16 - var dist_depth [maxSimpleDistanceAlphabetSize]byte - var dist_bits [maxSimpleDistanceAlphabetSize]uint16 - histogramClearLiteral(&lit_histo) - histogramClearCommand(&cmd_histo) - histogramClearDistance(&dist_histo) - buildHistograms(input, start_pos, mask, commands, &lit_histo, &cmd_histo, &dist_histo) - buildAndStoreHuffmanTreeFast(lit_histo.data_[:], lit_histo.total_count_, /* max_bits = */ - 8, lit_depth[:], lit_bits[:], storage_ix, storage) - - buildAndStoreHuffmanTreeFast(cmd_histo.data_[:], cmd_histo.total_count_, /* max_bits = */ - 10, cmd_depth[:], cmd_bits[:], storage_ix, storage) - - buildAndStoreHuffmanTreeFast(dist_histo.data_[:], dist_histo.total_count_, /* max_bits = */ - uint(distance_alphabet_bits), dist_depth[:], dist_bits[:], storage_ix, storage) - - storeDataWithHuffmanCodes(input, start_pos, mask, commands, lit_depth[:], lit_bits[:], cmd_depth[:], cmd_bits[:], dist_depth[:], dist_bits[:], storage_ix, storage) - } - - if is_last { - jumpToByteBoundary(storage_ix, storage) - } -} - -/* -This is for storing uncompressed blocks (simple raw storage of - - bytes-as-bytes). -*/ -func storeUncompressedMetaBlock(is_final_block bool, input []byte, position uint, mask uint, len uint, storage_ix *uint, storage []byte) { - var masked_pos uint = position & mask - storeUncompressedMetaBlockHeader(uint(len), storage_ix, storage) - jumpToByteBoundary(storage_ix, storage) - - if masked_pos+len > mask+1 { - var len1 uint = mask + 1 - masked_pos - copy(storage[*storage_ix>>3:], input[masked_pos:][:len1]) - *storage_ix += len1 << 3 - len -= len1 - masked_pos = 0 - } - - copy(storage[*storage_ix>>3:], input[masked_pos:][:len]) - *storage_ix += uint(len << 3) - - /* We need to clear the next 4 bytes to continue to be - compatible with BrotliWriteBits. */ - writeBitsPrepareStorage(*storage_ix, storage) - - /* Since the uncompressed block itself may not be the final block, add an - empty one after this. */ - if is_final_block { - writeBits(1, 1, storage_ix, storage) /* islast */ - writeBits(1, 1, storage_ix, storage) /* isempty */ - jumpToByteBoundary(storage_ix, storage) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/cluster.go b/src/vendor/github.com/andybalholm/brotli/cluster.go deleted file mode 100644 index df8a3282..00000000 --- a/src/vendor/github.com/andybalholm/brotli/cluster.go +++ /dev/null @@ -1,30 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions for clustering similar histograms together. */ - -type histogramPair struct { - idx1 uint32 - idx2 uint32 - cost_combo float64 - cost_diff float64 -} - -func histogramPairIsLess(p1 *histogramPair, p2 *histogramPair) bool { - if p1.cost_diff != p2.cost_diff { - return p1.cost_diff > p2.cost_diff - } - - return (p1.idx2 - p1.idx1) > (p2.idx2 - p2.idx1) -} - -/* Returns entropy reduction of the context map when we combine two clusters. */ -func clusterCostDiff(size_a uint, size_b uint) float64 { - var size_c uint = size_a + size_b - return float64(size_a)*fastLog2(size_a) + float64(size_b)*fastLog2(size_b) - float64(size_c)*fastLog2(size_c) -} diff --git a/src/vendor/github.com/andybalholm/brotli/cluster_command.go b/src/vendor/github.com/andybalholm/brotli/cluster_command.go deleted file mode 100644 index 45b569bb..00000000 --- a/src/vendor/github.com/andybalholm/brotli/cluster_command.go +++ /dev/null @@ -1,164 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if - it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ -func compareAndPushToQueueCommand(out []histogramCommand, cluster_size []uint32, idx1 uint32, idx2 uint32, max_num_pairs uint, pairs []histogramPair, num_pairs *uint) { - var is_good_pair bool = false - var p histogramPair - p.idx2 = 0 - p.idx1 = p.idx2 - p.cost_combo = 0 - p.cost_diff = p.cost_combo - if idx1 == idx2 { - return - } - - if idx2 < idx1 { - var t uint32 = idx2 - idx2 = idx1 - idx1 = t - } - - p.idx1 = idx1 - p.idx2 = idx2 - p.cost_diff = 0.5 * clusterCostDiff(uint(cluster_size[idx1]), uint(cluster_size[idx2])) - p.cost_diff -= out[idx1].bit_cost_ - p.cost_diff -= out[idx2].bit_cost_ - - if out[idx1].total_count_ == 0 { - p.cost_combo = out[idx2].bit_cost_ - is_good_pair = true - } else if out[idx2].total_count_ == 0 { - p.cost_combo = out[idx1].bit_cost_ - is_good_pair = true - } else { - var threshold float64 - if *num_pairs == 0 { - threshold = 1e99 - } else { - threshold = brotli_max_double(0.0, pairs[0].cost_diff) - } - var combo histogramCommand = out[idx1] - var cost_combo float64 - histogramAddHistogramCommand(&combo, &out[idx2]) - cost_combo = populationCostCommand(&combo) - if cost_combo < threshold-p.cost_diff { - p.cost_combo = cost_combo - is_good_pair = true - } - } - - if is_good_pair { - p.cost_diff += p.cost_combo - if *num_pairs > 0 && histogramPairIsLess(&pairs[0], &p) { - /* Replace the top of the queue if needed. */ - if *num_pairs < max_num_pairs { - pairs[*num_pairs] = pairs[0] - (*num_pairs)++ - } - - pairs[0] = p - } else if *num_pairs < max_num_pairs { - pairs[*num_pairs] = p - (*num_pairs)++ - } - } -} - -func histogramCombineCommand(out []histogramCommand, cluster_size []uint32, symbols []uint32, clusters []uint32, pairs []histogramPair, num_clusters uint, symbols_size uint, max_clusters uint, max_num_pairs uint) uint { - var cost_diff_threshold float64 = 0.0 - var min_cluster_size uint = 1 - var num_pairs uint = 0 - { - /* We maintain a vector of histogram pairs, with the property that the pair - with the maximum bit cost reduction is the first. */ - var idx1 uint - for idx1 = 0; idx1 < num_clusters; idx1++ { - var idx2 uint - for idx2 = idx1 + 1; idx2 < num_clusters; idx2++ { - compareAndPushToQueueCommand(out, cluster_size, clusters[idx1], clusters[idx2], max_num_pairs, pairs[0:], &num_pairs) - } - } - } - - for num_clusters > min_cluster_size { - var best_idx1 uint32 - var best_idx2 uint32 - var i uint - if pairs[0].cost_diff >= cost_diff_threshold { - cost_diff_threshold = 1e99 - min_cluster_size = max_clusters - continue - } - - /* Take the best pair from the top of heap. */ - best_idx1 = pairs[0].idx1 - - best_idx2 = pairs[0].idx2 - histogramAddHistogramCommand(&out[best_idx1], &out[best_idx2]) - out[best_idx1].bit_cost_ = pairs[0].cost_combo - cluster_size[best_idx1] += cluster_size[best_idx2] - for i = 0; i < symbols_size; i++ { - if symbols[i] == best_idx2 { - symbols[i] = best_idx1 - } - } - - for i = 0; i < num_clusters; i++ { - if clusters[i] == best_idx2 { - copy(clusters[i:], clusters[i+1:][:num_clusters-i-1]) - break - } - } - - num_clusters-- - { - /* Remove pairs intersecting the just combined best pair. */ - var copy_to_idx uint = 0 - for i = 0; i < num_pairs; i++ { - var p *histogramPair = &pairs[i] - if p.idx1 == best_idx1 || p.idx2 == best_idx1 || p.idx1 == best_idx2 || p.idx2 == best_idx2 { - /* Remove invalid pair from the queue. */ - continue - } - - if histogramPairIsLess(&pairs[0], p) { - /* Replace the top of the queue if needed. */ - var front histogramPair = pairs[0] - pairs[0] = *p - pairs[copy_to_idx] = front - } else { - pairs[copy_to_idx] = *p - } - - copy_to_idx++ - } - - num_pairs = copy_to_idx - } - - /* Push new pairs formed with the combined histogram to the heap. */ - for i = 0; i < num_clusters; i++ { - compareAndPushToQueueCommand(out, cluster_size, best_idx1, clusters[i], max_num_pairs, pairs[0:], &num_pairs) - } - } - - return num_clusters -} - -/* What is the bit cost of moving histogram from cur_symbol to candidate. */ -func histogramBitCostDistanceCommand(histogram *histogramCommand, candidate *histogramCommand) float64 { - if histogram.total_count_ == 0 { - return 0.0 - } else { - var tmp histogramCommand = *histogram - histogramAddHistogramCommand(&tmp, candidate) - return populationCostCommand(&tmp) - candidate.bit_cost_ - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/cluster_distance.go b/src/vendor/github.com/andybalholm/brotli/cluster_distance.go deleted file mode 100644 index 1aaa86e6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/cluster_distance.go +++ /dev/null @@ -1,326 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if - it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ -func compareAndPushToQueueDistance(out []histogramDistance, cluster_size []uint32, idx1 uint32, idx2 uint32, max_num_pairs uint, pairs []histogramPair, num_pairs *uint) { - var is_good_pair bool = false - var p histogramPair - p.idx2 = 0 - p.idx1 = p.idx2 - p.cost_combo = 0 - p.cost_diff = p.cost_combo - if idx1 == idx2 { - return - } - - if idx2 < idx1 { - var t uint32 = idx2 - idx2 = idx1 - idx1 = t - } - - p.idx1 = idx1 - p.idx2 = idx2 - p.cost_diff = 0.5 * clusterCostDiff(uint(cluster_size[idx1]), uint(cluster_size[idx2])) - p.cost_diff -= out[idx1].bit_cost_ - p.cost_diff -= out[idx2].bit_cost_ - - if out[idx1].total_count_ == 0 { - p.cost_combo = out[idx2].bit_cost_ - is_good_pair = true - } else if out[idx2].total_count_ == 0 { - p.cost_combo = out[idx1].bit_cost_ - is_good_pair = true - } else { - var threshold float64 - if *num_pairs == 0 { - threshold = 1e99 - } else { - threshold = brotli_max_double(0.0, pairs[0].cost_diff) - } - var combo histogramDistance = out[idx1] - var cost_combo float64 - histogramAddHistogramDistance(&combo, &out[idx2]) - cost_combo = populationCostDistance(&combo) - if cost_combo < threshold-p.cost_diff { - p.cost_combo = cost_combo - is_good_pair = true - } - } - - if is_good_pair { - p.cost_diff += p.cost_combo - if *num_pairs > 0 && histogramPairIsLess(&pairs[0], &p) { - /* Replace the top of the queue if needed. */ - if *num_pairs < max_num_pairs { - pairs[*num_pairs] = pairs[0] - (*num_pairs)++ - } - - pairs[0] = p - } else if *num_pairs < max_num_pairs { - pairs[*num_pairs] = p - (*num_pairs)++ - } - } -} - -func histogramCombineDistance(out []histogramDistance, cluster_size []uint32, symbols []uint32, clusters []uint32, pairs []histogramPair, num_clusters uint, symbols_size uint, max_clusters uint, max_num_pairs uint) uint { - var cost_diff_threshold float64 = 0.0 - var min_cluster_size uint = 1 - var num_pairs uint = 0 - { - /* We maintain a vector of histogram pairs, with the property that the pair - with the maximum bit cost reduction is the first. */ - var idx1 uint - for idx1 = 0; idx1 < num_clusters; idx1++ { - var idx2 uint - for idx2 = idx1 + 1; idx2 < num_clusters; idx2++ { - compareAndPushToQueueDistance(out, cluster_size, clusters[idx1], clusters[idx2], max_num_pairs, pairs[0:], &num_pairs) - } - } - } - - for num_clusters > min_cluster_size { - var best_idx1 uint32 - var best_idx2 uint32 - var i uint - if pairs[0].cost_diff >= cost_diff_threshold { - cost_diff_threshold = 1e99 - min_cluster_size = max_clusters - continue - } - - /* Take the best pair from the top of heap. */ - best_idx1 = pairs[0].idx1 - - best_idx2 = pairs[0].idx2 - histogramAddHistogramDistance(&out[best_idx1], &out[best_idx2]) - out[best_idx1].bit_cost_ = pairs[0].cost_combo - cluster_size[best_idx1] += cluster_size[best_idx2] - for i = 0; i < symbols_size; i++ { - if symbols[i] == best_idx2 { - symbols[i] = best_idx1 - } - } - - for i = 0; i < num_clusters; i++ { - if clusters[i] == best_idx2 { - copy(clusters[i:], clusters[i+1:][:num_clusters-i-1]) - break - } - } - - num_clusters-- - { - /* Remove pairs intersecting the just combined best pair. */ - var copy_to_idx uint = 0 - for i = 0; i < num_pairs; i++ { - var p *histogramPair = &pairs[i] - if p.idx1 == best_idx1 || p.idx2 == best_idx1 || p.idx1 == best_idx2 || p.idx2 == best_idx2 { - /* Remove invalid pair from the queue. */ - continue - } - - if histogramPairIsLess(&pairs[0], p) { - /* Replace the top of the queue if needed. */ - var front histogramPair = pairs[0] - pairs[0] = *p - pairs[copy_to_idx] = front - } else { - pairs[copy_to_idx] = *p - } - - copy_to_idx++ - } - - num_pairs = copy_to_idx - } - - /* Push new pairs formed with the combined histogram to the heap. */ - for i = 0; i < num_clusters; i++ { - compareAndPushToQueueDistance(out, cluster_size, best_idx1, clusters[i], max_num_pairs, pairs[0:], &num_pairs) - } - } - - return num_clusters -} - -/* What is the bit cost of moving histogram from cur_symbol to candidate. */ -func histogramBitCostDistanceDistance(histogram *histogramDistance, candidate *histogramDistance) float64 { - if histogram.total_count_ == 0 { - return 0.0 - } else { - var tmp histogramDistance = *histogram - histogramAddHistogramDistance(&tmp, candidate) - return populationCostDistance(&tmp) - candidate.bit_cost_ - } -} - -/* Find the best 'out' histogram for each of the 'in' histograms. - When called, clusters[0..num_clusters) contains the unique values from - symbols[0..in_size), but this property is not preserved in this function. - Note: we assume that out[]->bit_cost_ is already up-to-date. */ -func histogramRemapDistance(in []histogramDistance, in_size uint, clusters []uint32, num_clusters uint, out []histogramDistance, symbols []uint32) { - var i uint - for i = 0; i < in_size; i++ { - var best_out uint32 - if i == 0 { - best_out = symbols[0] - } else { - best_out = symbols[i-1] - } - var best_bits float64 = histogramBitCostDistanceDistance(&in[i], &out[best_out]) - var j uint - for j = 0; j < num_clusters; j++ { - var cur_bits float64 = histogramBitCostDistanceDistance(&in[i], &out[clusters[j]]) - if cur_bits < best_bits { - best_bits = cur_bits - best_out = clusters[j] - } - } - - symbols[i] = best_out - } - - /* Recompute each out based on raw and symbols. */ - for i = 0; i < num_clusters; i++ { - histogramClearDistance(&out[clusters[i]]) - } - - for i = 0; i < in_size; i++ { - histogramAddHistogramDistance(&out[symbols[i]], &in[i]) - } -} - -/* Reorders elements of the out[0..length) array and changes values in - symbols[0..length) array in the following way: - * when called, symbols[] contains indexes into out[], and has N unique - values (possibly N < length) - * on return, symbols'[i] = f(symbols[i]) and - out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, - where f is a bijection between the range of symbols[] and [0..N), and - the first occurrences of values in symbols'[i] come in consecutive - increasing order. - Returns N, the number of unique values in symbols[]. */ - -var histogramReindexDistance_kInvalidIndex uint32 = math.MaxUint32 - -func histogramReindexDistance(out []histogramDistance, symbols []uint32, length uint) uint { - var new_index []uint32 = make([]uint32, length) - var next_index uint32 - var tmp []histogramDistance - var i uint - for i = 0; i < length; i++ { - new_index[i] = histogramReindexDistance_kInvalidIndex - } - - next_index = 0 - for i = 0; i < length; i++ { - if new_index[symbols[i]] == histogramReindexDistance_kInvalidIndex { - new_index[symbols[i]] = next_index - next_index++ - } - } - - /* TODO: by using idea of "cycle-sort" we can avoid allocation of - tmp and reduce the number of copying by the factor of 2. */ - tmp = make([]histogramDistance, next_index) - - next_index = 0 - for i = 0; i < length; i++ { - if new_index[symbols[i]] == next_index { - tmp[next_index] = out[symbols[i]] - next_index++ - } - - symbols[i] = new_index[symbols[i]] - } - - new_index = nil - for i = 0; uint32(i) < next_index; i++ { - out[i] = tmp[i] - } - - tmp = nil - return uint(next_index) -} - -func clusterHistogramsDistance(in []histogramDistance, in_size uint, max_histograms uint, out []histogramDistance, out_size *uint, histogram_symbols []uint32) { - var cluster_size []uint32 = make([]uint32, in_size) - var clusters []uint32 = make([]uint32, in_size) - var num_clusters uint = 0 - var max_input_histograms uint = 64 - var pairs_capacity uint = max_input_histograms * max_input_histograms / 2 - var pairs []histogramPair = make([]histogramPair, (pairs_capacity + 1)) - var i uint - - /* For the first pass of clustering, we allow all pairs. */ - for i = 0; i < in_size; i++ { - cluster_size[i] = 1 - } - - for i = 0; i < in_size; i++ { - out[i] = in[i] - out[i].bit_cost_ = populationCostDistance(&in[i]) - histogram_symbols[i] = uint32(i) - } - - for i = 0; i < in_size; i += max_input_histograms { - var num_to_combine uint = brotli_min_size_t(in_size-i, max_input_histograms) - var num_new_clusters uint - var j uint - for j = 0; j < num_to_combine; j++ { - clusters[num_clusters+j] = uint32(i + j) - } - - num_new_clusters = histogramCombineDistance(out, cluster_size, histogram_symbols[i:], clusters[num_clusters:], pairs, num_to_combine, num_to_combine, max_histograms, pairs_capacity) - num_clusters += num_new_clusters - } - { - /* For the second pass, we limit the total number of histogram pairs. - After this limit is reached, we only keep searching for the best pair. */ - var max_num_pairs uint = brotli_min_size_t(64*num_clusters, (num_clusters/2)*num_clusters) - if pairs_capacity < (max_num_pairs + 1) { - var _new_size uint - if pairs_capacity == 0 { - _new_size = max_num_pairs + 1 - } else { - _new_size = pairs_capacity - } - var new_array []histogramPair - for _new_size < (max_num_pairs + 1) { - _new_size *= 2 - } - new_array = make([]histogramPair, _new_size) - if pairs_capacity != 0 { - copy(new_array, pairs[:pairs_capacity]) - } - - pairs = new_array - pairs_capacity = _new_size - } - - /* Collapse similar histograms. */ - num_clusters = histogramCombineDistance(out, cluster_size, histogram_symbols, clusters, pairs, num_clusters, in_size, max_histograms, max_num_pairs) - } - - pairs = nil - cluster_size = nil - - /* Find the optimal map from original histograms to the final ones. */ - histogramRemapDistance(in, in_size, clusters, num_clusters, out, histogram_symbols) - - clusters = nil - - /* Convert the context map to a canonical form. */ - *out_size = histogramReindexDistance(out, histogram_symbols, in_size) -} diff --git a/src/vendor/github.com/andybalholm/brotli/cluster_literal.go b/src/vendor/github.com/andybalholm/brotli/cluster_literal.go deleted file mode 100644 index 6ba66f31..00000000 --- a/src/vendor/github.com/andybalholm/brotli/cluster_literal.go +++ /dev/null @@ -1,326 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if - it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */ -func compareAndPushToQueueLiteral(out []histogramLiteral, cluster_size []uint32, idx1 uint32, idx2 uint32, max_num_pairs uint, pairs []histogramPair, num_pairs *uint) { - var is_good_pair bool = false - var p histogramPair - p.idx2 = 0 - p.idx1 = p.idx2 - p.cost_combo = 0 - p.cost_diff = p.cost_combo - if idx1 == idx2 { - return - } - - if idx2 < idx1 { - var t uint32 = idx2 - idx2 = idx1 - idx1 = t - } - - p.idx1 = idx1 - p.idx2 = idx2 - p.cost_diff = 0.5 * clusterCostDiff(uint(cluster_size[idx1]), uint(cluster_size[idx2])) - p.cost_diff -= out[idx1].bit_cost_ - p.cost_diff -= out[idx2].bit_cost_ - - if out[idx1].total_count_ == 0 { - p.cost_combo = out[idx2].bit_cost_ - is_good_pair = true - } else if out[idx2].total_count_ == 0 { - p.cost_combo = out[idx1].bit_cost_ - is_good_pair = true - } else { - var threshold float64 - if *num_pairs == 0 { - threshold = 1e99 - } else { - threshold = brotli_max_double(0.0, pairs[0].cost_diff) - } - var combo histogramLiteral = out[idx1] - var cost_combo float64 - histogramAddHistogramLiteral(&combo, &out[idx2]) - cost_combo = populationCostLiteral(&combo) - if cost_combo < threshold-p.cost_diff { - p.cost_combo = cost_combo - is_good_pair = true - } - } - - if is_good_pair { - p.cost_diff += p.cost_combo - if *num_pairs > 0 && histogramPairIsLess(&pairs[0], &p) { - /* Replace the top of the queue if needed. */ - if *num_pairs < max_num_pairs { - pairs[*num_pairs] = pairs[0] - (*num_pairs)++ - } - - pairs[0] = p - } else if *num_pairs < max_num_pairs { - pairs[*num_pairs] = p - (*num_pairs)++ - } - } -} - -func histogramCombineLiteral(out []histogramLiteral, cluster_size []uint32, symbols []uint32, clusters []uint32, pairs []histogramPair, num_clusters uint, symbols_size uint, max_clusters uint, max_num_pairs uint) uint { - var cost_diff_threshold float64 = 0.0 - var min_cluster_size uint = 1 - var num_pairs uint = 0 - { - /* We maintain a vector of histogram pairs, with the property that the pair - with the maximum bit cost reduction is the first. */ - var idx1 uint - for idx1 = 0; idx1 < num_clusters; idx1++ { - var idx2 uint - for idx2 = idx1 + 1; idx2 < num_clusters; idx2++ { - compareAndPushToQueueLiteral(out, cluster_size, clusters[idx1], clusters[idx2], max_num_pairs, pairs[0:], &num_pairs) - } - } - } - - for num_clusters > min_cluster_size { - var best_idx1 uint32 - var best_idx2 uint32 - var i uint - if pairs[0].cost_diff >= cost_diff_threshold { - cost_diff_threshold = 1e99 - min_cluster_size = max_clusters - continue - } - - /* Take the best pair from the top of heap. */ - best_idx1 = pairs[0].idx1 - - best_idx2 = pairs[0].idx2 - histogramAddHistogramLiteral(&out[best_idx1], &out[best_idx2]) - out[best_idx1].bit_cost_ = pairs[0].cost_combo - cluster_size[best_idx1] += cluster_size[best_idx2] - for i = 0; i < symbols_size; i++ { - if symbols[i] == best_idx2 { - symbols[i] = best_idx1 - } - } - - for i = 0; i < num_clusters; i++ { - if clusters[i] == best_idx2 { - copy(clusters[i:], clusters[i+1:][:num_clusters-i-1]) - break - } - } - - num_clusters-- - { - /* Remove pairs intersecting the just combined best pair. */ - var copy_to_idx uint = 0 - for i = 0; i < num_pairs; i++ { - var p *histogramPair = &pairs[i] - if p.idx1 == best_idx1 || p.idx2 == best_idx1 || p.idx1 == best_idx2 || p.idx2 == best_idx2 { - /* Remove invalid pair from the queue. */ - continue - } - - if histogramPairIsLess(&pairs[0], p) { - /* Replace the top of the queue if needed. */ - var front histogramPair = pairs[0] - pairs[0] = *p - pairs[copy_to_idx] = front - } else { - pairs[copy_to_idx] = *p - } - - copy_to_idx++ - } - - num_pairs = copy_to_idx - } - - /* Push new pairs formed with the combined histogram to the heap. */ - for i = 0; i < num_clusters; i++ { - compareAndPushToQueueLiteral(out, cluster_size, best_idx1, clusters[i], max_num_pairs, pairs[0:], &num_pairs) - } - } - - return num_clusters -} - -/* What is the bit cost of moving histogram from cur_symbol to candidate. */ -func histogramBitCostDistanceLiteral(histogram *histogramLiteral, candidate *histogramLiteral) float64 { - if histogram.total_count_ == 0 { - return 0.0 - } else { - var tmp histogramLiteral = *histogram - histogramAddHistogramLiteral(&tmp, candidate) - return populationCostLiteral(&tmp) - candidate.bit_cost_ - } -} - -/* Find the best 'out' histogram for each of the 'in' histograms. - When called, clusters[0..num_clusters) contains the unique values from - symbols[0..in_size), but this property is not preserved in this function. - Note: we assume that out[]->bit_cost_ is already up-to-date. */ -func histogramRemapLiteral(in []histogramLiteral, in_size uint, clusters []uint32, num_clusters uint, out []histogramLiteral, symbols []uint32) { - var i uint - for i = 0; i < in_size; i++ { - var best_out uint32 - if i == 0 { - best_out = symbols[0] - } else { - best_out = symbols[i-1] - } - var best_bits float64 = histogramBitCostDistanceLiteral(&in[i], &out[best_out]) - var j uint - for j = 0; j < num_clusters; j++ { - var cur_bits float64 = histogramBitCostDistanceLiteral(&in[i], &out[clusters[j]]) - if cur_bits < best_bits { - best_bits = cur_bits - best_out = clusters[j] - } - } - - symbols[i] = best_out - } - - /* Recompute each out based on raw and symbols. */ - for i = 0; i < num_clusters; i++ { - histogramClearLiteral(&out[clusters[i]]) - } - - for i = 0; i < in_size; i++ { - histogramAddHistogramLiteral(&out[symbols[i]], &in[i]) - } -} - -/* Reorders elements of the out[0..length) array and changes values in - symbols[0..length) array in the following way: - * when called, symbols[] contains indexes into out[], and has N unique - values (possibly N < length) - * on return, symbols'[i] = f(symbols[i]) and - out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length, - where f is a bijection between the range of symbols[] and [0..N), and - the first occurrences of values in symbols'[i] come in consecutive - increasing order. - Returns N, the number of unique values in symbols[]. */ - -var histogramReindexLiteral_kInvalidIndex uint32 = math.MaxUint32 - -func histogramReindexLiteral(out []histogramLiteral, symbols []uint32, length uint) uint { - var new_index []uint32 = make([]uint32, length) - var next_index uint32 - var tmp []histogramLiteral - var i uint - for i = 0; i < length; i++ { - new_index[i] = histogramReindexLiteral_kInvalidIndex - } - - next_index = 0 - for i = 0; i < length; i++ { - if new_index[symbols[i]] == histogramReindexLiteral_kInvalidIndex { - new_index[symbols[i]] = next_index - next_index++ - } - } - - /* TODO: by using idea of "cycle-sort" we can avoid allocation of - tmp and reduce the number of copying by the factor of 2. */ - tmp = make([]histogramLiteral, next_index) - - next_index = 0 - for i = 0; i < length; i++ { - if new_index[symbols[i]] == next_index { - tmp[next_index] = out[symbols[i]] - next_index++ - } - - symbols[i] = new_index[symbols[i]] - } - - new_index = nil - for i = 0; uint32(i) < next_index; i++ { - out[i] = tmp[i] - } - - tmp = nil - return uint(next_index) -} - -func clusterHistogramsLiteral(in []histogramLiteral, in_size uint, max_histograms uint, out []histogramLiteral, out_size *uint, histogram_symbols []uint32) { - var cluster_size []uint32 = make([]uint32, in_size) - var clusters []uint32 = make([]uint32, in_size) - var num_clusters uint = 0 - var max_input_histograms uint = 64 - var pairs_capacity uint = max_input_histograms * max_input_histograms / 2 - var pairs []histogramPair = make([]histogramPair, (pairs_capacity + 1)) - var i uint - - /* For the first pass of clustering, we allow all pairs. */ - for i = 0; i < in_size; i++ { - cluster_size[i] = 1 - } - - for i = 0; i < in_size; i++ { - out[i] = in[i] - out[i].bit_cost_ = populationCostLiteral(&in[i]) - histogram_symbols[i] = uint32(i) - } - - for i = 0; i < in_size; i += max_input_histograms { - var num_to_combine uint = brotli_min_size_t(in_size-i, max_input_histograms) - var num_new_clusters uint - var j uint - for j = 0; j < num_to_combine; j++ { - clusters[num_clusters+j] = uint32(i + j) - } - - num_new_clusters = histogramCombineLiteral(out, cluster_size, histogram_symbols[i:], clusters[num_clusters:], pairs, num_to_combine, num_to_combine, max_histograms, pairs_capacity) - num_clusters += num_new_clusters - } - { - /* For the second pass, we limit the total number of histogram pairs. - After this limit is reached, we only keep searching for the best pair. */ - var max_num_pairs uint = brotli_min_size_t(64*num_clusters, (num_clusters/2)*num_clusters) - if pairs_capacity < (max_num_pairs + 1) { - var _new_size uint - if pairs_capacity == 0 { - _new_size = max_num_pairs + 1 - } else { - _new_size = pairs_capacity - } - var new_array []histogramPair - for _new_size < (max_num_pairs + 1) { - _new_size *= 2 - } - new_array = make([]histogramPair, _new_size) - if pairs_capacity != 0 { - copy(new_array, pairs[:pairs_capacity]) - } - - pairs = new_array - pairs_capacity = _new_size - } - - /* Collapse similar histograms. */ - num_clusters = histogramCombineLiteral(out, cluster_size, histogram_symbols, clusters, pairs, num_clusters, in_size, max_histograms, max_num_pairs) - } - - pairs = nil - cluster_size = nil - - /* Find the optimal map from original histograms to the final ones. */ - histogramRemapLiteral(in, in_size, clusters, num_clusters, out, histogram_symbols) - - clusters = nil - - /* Convert the context map to a canonical form. */ - *out_size = histogramReindexLiteral(out, histogram_symbols, in_size) -} diff --git a/src/vendor/github.com/andybalholm/brotli/command.go b/src/vendor/github.com/andybalholm/brotli/command.go deleted file mode 100644 index b1662a55..00000000 --- a/src/vendor/github.com/andybalholm/brotli/command.go +++ /dev/null @@ -1,254 +0,0 @@ -package brotli - -var kInsBase = []uint32{ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 8, - 10, - 14, - 18, - 26, - 34, - 50, - 66, - 98, - 130, - 194, - 322, - 578, - 1090, - 2114, - 6210, - 22594, -} - -var kInsExtra = []uint32{ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 7, - 8, - 9, - 10, - 12, - 14, - 24, -} - -var kCopyBase = []uint32{ - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 12, - 14, - 18, - 22, - 30, - 38, - 54, - 70, - 102, - 134, - 198, - 326, - 582, - 1094, - 2118, -} - -var kCopyExtra = []uint32{ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 7, - 8, - 9, - 10, - 24, -} - -func getInsertLengthCode(insertlen uint) uint16 { - if insertlen < 6 { - return uint16(insertlen) - } else if insertlen < 130 { - var nbits uint32 = log2FloorNonZero(insertlen-2) - 1 - return uint16((nbits << 1) + uint32((insertlen-2)>>nbits) + 2) - } else if insertlen < 2114 { - return uint16(log2FloorNonZero(insertlen-66) + 10) - } else if insertlen < 6210 { - return 21 - } else if insertlen < 22594 { - return 22 - } else { - return 23 - } -} - -func getCopyLengthCode(copylen uint) uint16 { - if copylen < 10 { - return uint16(copylen - 2) - } else if copylen < 134 { - var nbits uint32 = log2FloorNonZero(copylen-6) - 1 - return uint16((nbits << 1) + uint32((copylen-6)>>nbits) + 4) - } else if copylen < 2118 { - return uint16(log2FloorNonZero(copylen-70) + 12) - } else { - return 23 - } -} - -func combineLengthCodes(inscode uint16, copycode uint16, use_last_distance bool) uint16 { - var bits64 uint16 = uint16(copycode&0x7 | (inscode&0x7)<<3) - if use_last_distance && inscode < 8 && copycode < 16 { - if copycode < 8 { - return bits64 - } else { - return bits64 | 64 - } - } else { - /* Specification: 5 Encoding of ... (last table) */ - /* offset = 2 * index, where index is in range [0..8] */ - var offset uint32 = 2 * ((uint32(copycode) >> 3) + 3*(uint32(inscode)>>3)) - - /* All values in specification are K * 64, - where K = [2, 3, 6, 4, 5, 8, 7, 9, 10], - i + 1 = [1, 2, 3, 4, 5, 6, 7, 8, 9], - K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1, 2] = D. - All values in D require only 2 bits to encode. - Magic constant is shifted 6 bits left, to avoid final multiplication. */ - offset = (offset << 5) + 0x40 + ((0x520D40 >> offset) & 0xC0) - - return uint16(offset | uint32(bits64)) - } -} - -func getLengthCode(insertlen uint, copylen uint, use_last_distance bool, code *uint16) { - var inscode uint16 = getInsertLengthCode(insertlen) - var copycode uint16 = getCopyLengthCode(copylen) - *code = combineLengthCodes(inscode, copycode, use_last_distance) -} - -func getInsertBase(inscode uint16) uint32 { - return kInsBase[inscode] -} - -func getInsertExtra(inscode uint16) uint32 { - return kInsExtra[inscode] -} - -func getCopyBase(copycode uint16) uint32 { - return kCopyBase[copycode] -} - -func getCopyExtra(copycode uint16) uint32 { - return kCopyExtra[copycode] -} - -type command struct { - insert_len_ uint32 - copy_len_ uint32 - dist_extra_ uint32 - cmd_prefix_ uint16 - dist_prefix_ uint16 -} - -/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */ -func makeCommand(dist *distanceParams, insertlen uint, copylen uint, copylen_code_delta int, distance_code uint) (cmd command) { - /* Don't rely on signed int representation, use honest casts. */ - var delta uint32 = uint32(byte(int8(copylen_code_delta))) - cmd.insert_len_ = uint32(insertlen) - cmd.copy_len_ = uint32(uint32(copylen) | delta<<25) - - /* The distance prefix and extra bits are stored in this Command as if - npostfix and ndirect were 0, they are only recomputed later after the - clustering if needed. */ - prefixEncodeCopyDistance(distance_code, uint(dist.num_direct_distance_codes), uint(dist.distance_postfix_bits), &cmd.dist_prefix_, &cmd.dist_extra_) - getLengthCode(insertlen, uint(int(copylen)+copylen_code_delta), (cmd.dist_prefix_&0x3FF == 0), &cmd.cmd_prefix_) - - return cmd -} - -func makeInsertCommand(insertlen uint) (cmd command) { - cmd.insert_len_ = uint32(insertlen) - cmd.copy_len_ = 4 << 25 - cmd.dist_extra_ = 0 - cmd.dist_prefix_ = numDistanceShortCodes - getLengthCode(insertlen, 4, false, &cmd.cmd_prefix_) - return cmd -} - -func commandRestoreDistanceCode(self *command, dist *distanceParams) uint32 { - if uint32(self.dist_prefix_&0x3FF) < numDistanceShortCodes+dist.num_direct_distance_codes { - return uint32(self.dist_prefix_) & 0x3FF - } else { - var dcode uint32 = uint32(self.dist_prefix_) & 0x3FF - var nbits uint32 = uint32(self.dist_prefix_) >> 10 - var extra uint32 = self.dist_extra_ - var postfix_mask uint32 = (1 << dist.distance_postfix_bits) - 1 - var hcode uint32 = (dcode - dist.num_direct_distance_codes - numDistanceShortCodes) >> dist.distance_postfix_bits - var lcode uint32 = (dcode - dist.num_direct_distance_codes - numDistanceShortCodes) & postfix_mask - var offset uint32 = ((2 + (hcode & 1)) << nbits) - 4 - return ((offset + extra) << dist.distance_postfix_bits) + lcode + dist.num_direct_distance_codes + numDistanceShortCodes - } -} - -func commandDistanceContext(self *command) uint32 { - var r uint32 = uint32(self.cmd_prefix_) >> 6 - var c uint32 = uint32(self.cmd_prefix_) & 7 - if (r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2) { - return c - } - - return 3 -} - -func commandCopyLen(self *command) uint32 { - return self.copy_len_ & 0x1FFFFFF -} - -func commandCopyLenCode(self *command) uint32 { - var modifier uint32 = self.copy_len_ >> 25 - var delta int32 = int32(int8(byte(modifier | (modifier&0x40)<<1))) - return uint32(int32(self.copy_len_&0x1FFFFFF) + delta) -} diff --git a/src/vendor/github.com/andybalholm/brotli/compress_fragment.go b/src/vendor/github.com/andybalholm/brotli/compress_fragment.go deleted file mode 100644 index c9bd0577..00000000 --- a/src/vendor/github.com/andybalholm/brotli/compress_fragment.go +++ /dev/null @@ -1,834 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Function for fast encoding of an input fragment, independently from the input - history. This function uses one-pass processing: when we find a backward - match, we immediately emit the corresponding command and literal codes to - the bit stream. - - Adapted from the CompressFragment() function in - https://github.com/google/snappy/blob/master/snappy.cc */ - -const maxDistance_compress_fragment = 262128 - -func hash5(p []byte, shift uint) uint32 { - var h uint64 = (binary.LittleEndian.Uint64(p) << 24) * uint64(kHashMul32) - return uint32(h >> shift) -} - -func hashBytesAtOffset5(v uint64, offset int, shift uint) uint32 { - assert(offset >= 0) - assert(offset <= 3) - { - var h uint64 = ((v >> uint(8*offset)) << 24) * uint64(kHashMul32) - return uint32(h >> shift) - } -} - -func isMatch5(p1 []byte, p2 []byte) bool { - return binary.LittleEndian.Uint32(p1) == binary.LittleEndian.Uint32(p2) && - p1[4] == p2[4] -} - -/* Builds a literal prefix code into "depths" and "bits" based on the statistics - of the "input" string and stores it into the bit stream. - Note that the prefix code here is built from the pre-LZ77 input, therefore - we can only approximate the statistics of the actual literal stream. - Moreover, for long inputs we build a histogram from a sample of the input - and thus have to assign a non-zero depth for each literal. - Returns estimated compression ratio millibytes/char for encoding given input - with generated code. */ -func buildAndStoreLiteralPrefixCode(input []byte, input_size uint, depths []byte, bits []uint16, storage_ix *uint, storage []byte) uint { - var histogram = [256]uint32{0} - var histogram_total uint - var i uint - if input_size < 1<<15 { - for i = 0; i < input_size; i++ { - histogram[input[i]]++ - } - - histogram_total = input_size - for i = 0; i < 256; i++ { - /* We weigh the first 11 samples with weight 3 to account for the - balancing effect of the LZ77 phase on the histogram. */ - var adjust uint32 = 2 * brotli_min_uint32_t(histogram[i], 11) - histogram[i] += adjust - histogram_total += uint(adjust) - } - } else { - const kSampleRate uint = 29 - for i = 0; i < input_size; i += kSampleRate { - histogram[input[i]]++ - } - - histogram_total = (input_size + kSampleRate - 1) / kSampleRate - for i = 0; i < 256; i++ { - /* We add 1 to each population count to avoid 0 bit depths (since this is - only a sample and we don't know if the symbol appears or not), and we - weigh the first 11 samples with weight 3 to account for the balancing - effect of the LZ77 phase on the histogram (more frequent symbols are - more likely to be in backward references instead as literals). */ - var adjust uint32 = 1 + 2*brotli_min_uint32_t(histogram[i], 11) - histogram[i] += adjust - histogram_total += uint(adjust) - } - } - - buildAndStoreHuffmanTreeFast(histogram[:], histogram_total, /* max_bits = */ - 8, depths, bits, storage_ix, storage) - { - var literal_ratio uint = 0 - for i = 0; i < 256; i++ { - if histogram[i] != 0 { - literal_ratio += uint(histogram[i] * uint32(depths[i])) - } - } - - /* Estimated encoding ratio, millibytes per symbol. */ - return (literal_ratio * 125) / histogram_total - } -} - -/* Builds a command and distance prefix code (each 64 symbols) into "depth" and - "bits" based on "histogram" and stores it into the bit stream. */ -func buildAndStoreCommandPrefixCode1(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) { - var tree [129]huffmanTree - var cmd_depth = [numCommandSymbols]byte{0} - /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ - - var cmd_bits [64]uint16 - - createHuffmanTree(histogram, 64, 15, tree[:], depth) - createHuffmanTree(histogram[64:], 64, 14, tree[:], depth[64:]) - - /* We have to jump through a few hoops here in order to compute - the command bits because the symbols are in a different order than in - the full alphabet. This looks complicated, but having the symbols - in this order in the command bits saves a few branches in the Emit* - functions. */ - copy(cmd_depth[:], depth[:24]) - - copy(cmd_depth[24:][:], depth[40:][:8]) - copy(cmd_depth[32:][:], depth[24:][:8]) - copy(cmd_depth[40:][:], depth[48:][:8]) - copy(cmd_depth[48:][:], depth[32:][:8]) - copy(cmd_depth[56:][:], depth[56:][:8]) - convertBitDepthsToSymbols(cmd_depth[:], 64, cmd_bits[:]) - copy(bits, cmd_bits[:24]) - copy(bits[24:], cmd_bits[32:][:8]) - copy(bits[32:], cmd_bits[48:][:8]) - copy(bits[40:], cmd_bits[24:][:8]) - copy(bits[48:], cmd_bits[40:][:8]) - copy(bits[56:], cmd_bits[56:][:8]) - convertBitDepthsToSymbols(depth[64:], 64, bits[64:]) - { - /* Create the bit length array for the full command alphabet. */ - var i uint - for i := 0; i < int(64); i++ { - cmd_depth[i] = 0 - } /* only 64 first values were used */ - copy(cmd_depth[:], depth[:8]) - copy(cmd_depth[64:][:], depth[8:][:8]) - copy(cmd_depth[128:][:], depth[16:][:8]) - copy(cmd_depth[192:][:], depth[24:][:8]) - copy(cmd_depth[384:][:], depth[32:][:8]) - for i = 0; i < 8; i++ { - cmd_depth[128+8*i] = depth[40+i] - cmd_depth[256+8*i] = depth[48+i] - cmd_depth[448+8*i] = depth[56+i] - } - - storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], storage_ix, storage) - } - - storeHuffmanTree(depth[64:], 64, tree[:], storage_ix, storage) -} - -/* REQUIRES: insertlen < 6210 */ -func emitInsertLen1(insertlen uint, depth []byte, bits []uint16, histo []uint32, storage_ix *uint, storage []byte) { - if insertlen < 6 { - var code uint = insertlen + 40 - writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage) - histo[code]++ - } else if insertlen < 130 { - var tail uint = insertlen - 2 - var nbits uint32 = log2FloorNonZero(tail) - 1 - var prefix uint = tail >> nbits - var inscode uint = uint((nbits << 1) + uint32(prefix) + 42) - writeBits(uint(depth[inscode]), uint64(bits[inscode]), storage_ix, storage) - writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<> nbits - var code uint = uint((nbits << 1) + uint32(prefix) + 20) - writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage) - writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<> nbits - var code uint = uint((nbits << 1) + uint32(prefix) + 4) - writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage) - writeBits(uint(nbits), uint64(tail)-(uint64(prefix)<> 5) + 30 - writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage) - writeBits(5, uint64(tail)&31, storage_ix, storage) - writeBits(uint(depth[64]), uint64(bits[64]), storage_ix, storage) - histo[code]++ - histo[64]++ - } else if copylen < 2120 { - var tail uint = copylen - 72 - var nbits uint32 = log2FloorNonZero(tail) - var code uint = uint(nbits + 28) - writeBits(uint(depth[code]), uint64(bits[code]), storage_ix, storage) - writeBits(uint(nbits), uint64(tail)-(uint64(uint(1))<> nbits) & 1 - var offset uint = (2 + prefix) << nbits - var distcode uint = uint(2*(nbits-1) + uint32(prefix) + 80) - writeBits(uint(depth[distcode]), uint64(bits[distcode]), storage_ix, storage) - writeBits(uint(nbits), uint64(d)-uint64(offset), storage_ix, storage) - histo[distcode]++ -} - -func emitLiterals(input []byte, len uint, depth []byte, bits []uint16, storage_ix *uint, storage []byte) { - var j uint - for j = 0; j < len; j++ { - var lit byte = input[j] - writeBits(uint(depth[lit]), uint64(bits[lit]), storage_ix, storage) - } -} - -/* REQUIRES: len <= 1 << 24. */ -func storeMetaBlockHeader1(len uint, is_uncompressed bool, storage_ix *uint, storage []byte) { - var nibbles uint = 6 - - /* ISLAST */ - writeBits(1, 0, storage_ix, storage) - - if len <= 1<<16 { - nibbles = 4 - } else if len <= 1<<20 { - nibbles = 5 - } - - writeBits(2, uint64(nibbles)-4, storage_ix, storage) - writeBits(nibbles*4, uint64(len)-1, storage_ix, storage) - - /* ISUNCOMPRESSED */ - writeSingleBit(is_uncompressed, storage_ix, storage) -} - -func updateBits(n_bits uint, bits uint32, pos uint, array []byte) { - for n_bits > 0 { - var byte_pos uint = pos >> 3 - var n_unchanged_bits uint = pos & 7 - var n_changed_bits uint = brotli_min_size_t(n_bits, 8-n_unchanged_bits) - var total_bits uint = n_unchanged_bits + n_changed_bits - var mask uint32 = (^((1 << total_bits) - 1)) | ((1 << n_unchanged_bits) - 1) - var unchanged_bits uint32 = uint32(array[byte_pos]) & mask - var changed_bits uint32 = bits & ((1 << n_changed_bits) - 1) - array[byte_pos] = byte(changed_bits<>= n_changed_bits - pos += n_changed_bits - } -} - -func rewindBitPosition1(new_storage_ix uint, storage_ix *uint, storage []byte) { - var bitpos uint = new_storage_ix & 7 - var mask uint = (1 << bitpos) - 1 - storage[new_storage_ix>>3] &= byte(mask) - *storage_ix = new_storage_ix -} - -var shouldMergeBlock_kSampleRate uint = 43 - -func shouldMergeBlock(data []byte, len uint, depths []byte) bool { - var histo = [256]uint{0} - var i uint - for i = 0; i < len; i += shouldMergeBlock_kSampleRate { - histo[data[i]]++ - } - { - var total uint = (len + shouldMergeBlock_kSampleRate - 1) / shouldMergeBlock_kSampleRate - var r float64 = (fastLog2(total)+0.5)*float64(total) + 200 - for i = 0; i < 256; i++ { - r -= float64(histo[i]) * (float64(depths[i]) + fastLog2(histo[i])) - } - - return r >= 0.0 - } -} - -func shouldUseUncompressedMode(metablock_start []byte, next_emit []byte, insertlen uint, literal_ratio uint) bool { - var compressed uint = uint(-cap(next_emit) + cap(metablock_start)) - if compressed*50 > insertlen { - return false - } else { - return literal_ratio > 980 - } -} - -func emitUncompressedMetaBlock1(begin []byte, end []byte, storage_ix_start uint, storage_ix *uint, storage []byte) { - var len uint = uint(-cap(end) + cap(begin)) - rewindBitPosition1(storage_ix_start, storage_ix, storage) - storeMetaBlockHeader1(uint(len), true, storage_ix, storage) - *storage_ix = (*storage_ix + 7) &^ 7 - copy(storage[*storage_ix>>3:], begin[:len]) - *storage_ix += uint(len << 3) - storage[*storage_ix>>3] = 0 -} - -var kCmdHistoSeed = [128]uint32{ - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 0, - 0, - 0, - 0, -} - -var compressFragmentFastImpl_kFirstBlockSize uint = 3 << 15 -var compressFragmentFastImpl_kMergeBlockSize uint = 1 << 16 - -func compressFragmentFastImpl(in []byte, input_size uint, is_last bool, table []int, table_bits uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, storage_ix *uint, storage []byte) { - var cmd_histo [128]uint32 - var ip_end int - var next_emit int = 0 - var base_ip int = 0 - var input int = 0 - const kInputMarginBytes uint = windowGap - const kMinMatchLen uint = 5 - var metablock_start int = input - var block_size uint = brotli_min_size_t(input_size, compressFragmentFastImpl_kFirstBlockSize) - var total_block_size uint = block_size - var mlen_storage_ix uint = *storage_ix + 3 - var lit_depth [256]byte - var lit_bits [256]uint16 - var literal_ratio uint - var ip int - var last_distance int - var shift uint = 64 - table_bits - - /* "next_emit" is a pointer to the first byte that is not covered by a - previous copy. Bytes between "next_emit" and the start of the next copy or - the end of the input will be emitted as literal bytes. */ - - /* Save the start of the first block for position and distance computations. - */ - - /* Save the bit position of the MLEN field of the meta-block header, so that - we can update it later if we decide to extend this meta-block. */ - storeMetaBlockHeader1(block_size, false, storage_ix, storage) - - /* No block splits, no contexts. */ - writeBits(13, 0, storage_ix, storage) - - literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], storage_ix, storage) - { - /* Store the pre-compressed command and distance prefix codes. */ - var i uint - for i = 0; i+7 < *cmd_code_numbits; i += 8 { - writeBits(8, uint64(cmd_code[i>>3]), storage_ix, storage) - } - } - - writeBits(*cmd_code_numbits&7, uint64(cmd_code[*cmd_code_numbits>>3]), storage_ix, storage) - - /* Initialize the command and distance histograms. We will gather - statistics of command and distance codes during the processing - of this block and use it to update the command and distance - prefix codes for the next block. */ -emit_commands: - copy(cmd_histo[:], kCmdHistoSeed[:]) - - /* "ip" is the input pointer. */ - ip = input - - last_distance = -1 - ip_end = int(uint(input) + block_size) - - if block_size >= kInputMarginBytes { - var len_limit uint = brotli_min_size_t(block_size-kMinMatchLen, input_size-kInputMarginBytes) - var ip_limit int = int(uint(input) + len_limit) - /* For the last block, we need to keep a 16 bytes margin so that we can be - sure that all distances are at most window size - 16. - For all other blocks, we only need to keep a margin of 5 bytes so that - we don't go over the block size with a copy. */ - - var next_hash uint32 - ip++ - for next_hash = hash5(in[ip:], shift); ; { - var skip uint32 = 32 - var next_ip int = ip - /* Step 1: Scan forward in the input looking for a 5-byte-long match. - If we get close to exhausting the input then goto emit_remainder. - - Heuristic match skipping: If 32 bytes are scanned with no matches - found, start looking only at every other byte. If 32 more bytes are - scanned, look at every third byte, etc.. When a match is found, - immediately go back to looking at every byte. This is a small loss - (~5% performance, ~0.1% density) for compressible data due to more - bookkeeping, but for non-compressible data (such as JPEG) it's a huge - win since the compressor quickly "realizes" the data is incompressible - and doesn't bother looking for matches everywhere. - - The "skip" variable keeps track of how many bytes there are since the - last match; dividing it by 32 (i.e. right-shifting by five) gives the - number of bytes to move ahead for each iteration. */ - - var candidate int - assert(next_emit < ip) - - trawl: - for { - var hash uint32 = next_hash - var bytes_between_hash_lookups uint32 = skip >> 5 - skip++ - assert(hash == hash5(in[next_ip:], shift)) - ip = next_ip - next_ip = int(uint32(ip) + bytes_between_hash_lookups) - if next_ip > ip_limit { - goto emit_remainder - } - - next_hash = hash5(in[next_ip:], shift) - candidate = ip - last_distance - if isMatch5(in[ip:], in[candidate:]) { - if candidate < ip { - table[hash] = int(ip - base_ip) - break - } - } - - candidate = base_ip + table[hash] - assert(candidate >= base_ip) - assert(candidate < ip) - - table[hash] = int(ip - base_ip) - if isMatch5(in[ip:], in[candidate:]) { - break - } - } - - /* Check copy distance. If candidate is not feasible, continue search. - Checking is done outside of hot loop to reduce overhead. */ - if ip-candidate > maxDistance_compress_fragment { - goto trawl - } - - /* Step 2: Emit the found match together with the literal bytes from - "next_emit" to the bit stream, and then see if we can find a next match - immediately afterwards. Repeat until we find no match for the input - without emitting some literal bytes. */ - { - var base int = ip - /* > 0 */ - var matched uint = 5 + findMatchLengthWithLimit(in[candidate+5:], in[ip+5:], uint(ip_end-ip)-5) - var distance int = int(base - candidate) - /* We have a 5-byte match at ip, and we need to emit bytes in - [next_emit, ip). */ - - var insert uint = uint(base - next_emit) - ip += int(matched) - if insert < 6210 { - emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - } else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) { - emitUncompressedMetaBlock1(in[metablock_start:], in[base:], mlen_storage_ix-3, storage_ix, storage) - input_size -= uint(base - input) - input = base - next_emit = input - goto next_block - } else { - emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - } - - emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage) - if distance == last_distance { - writeBits(uint(cmd_depth[64]), uint64(cmd_bits[64]), storage_ix, storage) - cmd_histo[64]++ - } else { - emitDistance1(uint(distance), cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - last_distance = distance - } - - emitCopyLenLastDistance1(matched, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - - next_emit = ip - if ip >= ip_limit { - goto emit_remainder - } - - /* We could immediately start working at ip now, but to improve - compression we first update "table" with the hashes of some positions - within the last copy. */ - { - var input_bytes uint64 = binary.LittleEndian.Uint64(in[ip-3:]) - var prev_hash uint32 = hashBytesAtOffset5(input_bytes, 0, shift) - var cur_hash uint32 = hashBytesAtOffset5(input_bytes, 3, shift) - table[prev_hash] = int(ip - base_ip - 3) - prev_hash = hashBytesAtOffset5(input_bytes, 1, shift) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset5(input_bytes, 2, shift) - table[prev_hash] = int(ip - base_ip - 1) - - candidate = base_ip + table[cur_hash] - table[cur_hash] = int(ip - base_ip) - } - } - - for isMatch5(in[ip:], in[candidate:]) { - var base int = ip - /* We have a 5-byte match at ip, and no need to emit any literal bytes - prior to ip. */ - - var matched uint = 5 + findMatchLengthWithLimit(in[candidate+5:], in[ip+5:], uint(ip_end-ip)-5) - if ip-candidate > maxDistance_compress_fragment { - break - } - ip += int(matched) - last_distance = int(base - candidate) /* > 0 */ - emitCopyLen1(matched, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - emitDistance1(uint(last_distance), cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - - next_emit = ip - if ip >= ip_limit { - goto emit_remainder - } - - /* We could immediately start working at ip now, but to improve - compression we first update "table" with the hashes of some positions - within the last copy. */ - { - var input_bytes uint64 = binary.LittleEndian.Uint64(in[ip-3:]) - var prev_hash uint32 = hashBytesAtOffset5(input_bytes, 0, shift) - var cur_hash uint32 = hashBytesAtOffset5(input_bytes, 3, shift) - table[prev_hash] = int(ip - base_ip - 3) - prev_hash = hashBytesAtOffset5(input_bytes, 1, shift) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset5(input_bytes, 2, shift) - table[prev_hash] = int(ip - base_ip - 1) - - candidate = base_ip + table[cur_hash] - table[cur_hash] = int(ip - base_ip) - } - } - - ip++ - next_hash = hash5(in[ip:], shift) - } - } - -emit_remainder: - assert(next_emit <= ip_end) - input += int(block_size) - input_size -= block_size - block_size = brotli_min_size_t(input_size, compressFragmentFastImpl_kMergeBlockSize) - - /* Decide if we want to continue this meta-block instead of emitting the - last insert-only command. */ - if input_size > 0 && total_block_size+block_size <= 1<<20 && shouldMergeBlock(in[input:], block_size, lit_depth[:]) { - assert(total_block_size > 1<<16) - - /* Update the size of the current meta-block and continue emitting commands. - We can do this because the current size and the new size both have 5 - nibbles. */ - total_block_size += block_size - - updateBits(20, uint32(total_block_size-1), mlen_storage_ix, storage) - goto emit_commands - } - - /* Emit the remaining bytes as literals. */ - if next_emit < ip_end { - var insert uint = uint(ip_end - next_emit) - if insert < 6210 { - emitInsertLen1(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage) - } else if shouldUseUncompressedMode(in[metablock_start:], in[next_emit:], insert, literal_ratio) { - emitUncompressedMetaBlock1(in[metablock_start:], in[ip_end:], mlen_storage_ix-3, storage_ix, storage) - } else { - emitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo[:], storage_ix, storage) - emitLiterals(in[next_emit:], insert, lit_depth[:], lit_bits[:], storage_ix, storage) - } - } - - next_emit = ip_end - - /* If we have more data, write a new meta-block header and prefix codes and - then continue emitting commands. */ -next_block: - if input_size > 0 { - metablock_start = input - block_size = brotli_min_size_t(input_size, compressFragmentFastImpl_kFirstBlockSize) - total_block_size = block_size - - /* Save the bit position of the MLEN field of the meta-block header, so that - we can update it later if we decide to extend this meta-block. */ - mlen_storage_ix = *storage_ix + 3 - - storeMetaBlockHeader1(block_size, false, storage_ix, storage) - - /* No block splits, no contexts. */ - writeBits(13, 0, storage_ix, storage) - - literal_ratio = buildAndStoreLiteralPrefixCode(in[input:], block_size, lit_depth[:], lit_bits[:], storage_ix, storage) - buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, storage_ix, storage) - goto emit_commands - } - - if !is_last { - /* If this is not the last block, update the command and distance prefix - codes for the next block and store the compressed forms. */ - cmd_code[0] = 0 - - *cmd_code_numbits = 0 - buildAndStoreCommandPrefixCode1(cmd_histo[:], cmd_depth, cmd_bits, cmd_code_numbits, cmd_code) - } -} - -/* Compresses "input" string to the "*storage" buffer as one or more complete - meta-blocks, and updates the "*storage_ix" bit position. - - If "is_last" is 1, emits an additional empty last meta-block. - - "cmd_depth" and "cmd_bits" contain the command and distance prefix codes - (see comment in encode.h) used for the encoding of this input fragment. - If "is_last" is 0, they are updated to reflect the statistics - of this input fragment, to be used for the encoding of the next fragment. - - "*cmd_code_numbits" is the number of bits of the compressed representation - of the command and distance prefix codes, and "cmd_code" is an array of - at least "(*cmd_code_numbits + 7) >> 3" size that contains the compressed - command and distance prefix codes. If "is_last" is 0, these are also - updated to represent the updated "cmd_depth" and "cmd_bits". - - REQUIRES: "input_size" is greater than zero, or "is_last" is 1. - REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). - REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. - REQUIRES: "table_size" is an odd (9, 11, 13, 15) power of two - OUTPUT: maximal copy distance <= |input_size| - OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */ -func compressFragmentFast(input []byte, input_size uint, is_last bool, table []int, table_size uint, cmd_depth []byte, cmd_bits []uint16, cmd_code_numbits *uint, cmd_code []byte, storage_ix *uint, storage []byte) { - var initial_storage_ix uint = *storage_ix - var table_bits uint = uint(log2FloorNonZero(table_size)) - - if input_size == 0 { - assert(is_last) - writeBits(1, 1, storage_ix, storage) /* islast */ - writeBits(1, 1, storage_ix, storage) /* isempty */ - *storage_ix = (*storage_ix + 7) &^ 7 - return - } - - compressFragmentFastImpl(input, input_size, is_last, table, table_bits, cmd_depth, cmd_bits, cmd_code_numbits, cmd_code, storage_ix, storage) - - /* If output is larger than single uncompressed block, rewrite it. */ - if *storage_ix-initial_storage_ix > 31+(input_size<<3) { - emitUncompressedMetaBlock1(input, input[input_size:], initial_storage_ix, storage_ix, storage) - } - - if is_last { - writeBits(1, 1, storage_ix, storage) /* islast */ - writeBits(1, 1, storage_ix, storage) /* isempty */ - *storage_ix = (*storage_ix + 7) &^ 7 - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go b/src/vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go deleted file mode 100644 index c5c663a5..00000000 --- a/src/vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go +++ /dev/null @@ -1,775 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Function for fast encoding of an input fragment, independently from the input - history. This function uses two-pass processing: in the first pass we save - the found backward matches and literal bytes into a buffer, and in the - second pass we emit them into the bit stream using prefix codes built based - on the actual command and literal byte histograms. */ - -const kCompressFragmentTwoPassBlockSize uint = 1 << 17 - -func hash1(p []byte, shift uint, length uint) uint32 { - var h uint64 = (binary.LittleEndian.Uint64(p) << ((8 - length) * 8)) * uint64(kHashMul32) - return uint32(h >> shift) -} - -func hashBytesAtOffset(v uint64, offset uint, shift uint, length uint) uint32 { - assert(offset <= 8-length) - { - var h uint64 = ((v >> (8 * offset)) << ((8 - length) * 8)) * uint64(kHashMul32) - return uint32(h >> shift) - } -} - -func isMatch1(p1 []byte, p2 []byte, length uint) bool { - if binary.LittleEndian.Uint32(p1) != binary.LittleEndian.Uint32(p2) { - return false - } - if length == 4 { - return true - } - return p1[4] == p2[4] && p1[5] == p2[5] -} - -/* -Builds a command and distance prefix code (each 64 symbols) into "depth" and - - "bits" based on "histogram" and stores it into the bit stream. -*/ -func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) { - var tree [129]huffmanTree - var cmd_depth = [numCommandSymbols]byte{0} - /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */ - - var cmd_bits [64]uint16 - createHuffmanTree(histogram, 64, 15, tree[:], depth) - createHuffmanTree(histogram[64:], 64, 14, tree[:], depth[64:]) - - /* We have to jump through a few hoops here in order to compute - the command bits because the symbols are in a different order than in - the full alphabet. This looks complicated, but having the symbols - in this order in the command bits saves a few branches in the Emit* - functions. */ - copy(cmd_depth[:], depth[24:][:24]) - - copy(cmd_depth[24:][:], depth[:8]) - copy(cmd_depth[32:][:], depth[48:][:8]) - copy(cmd_depth[40:][:], depth[8:][:8]) - copy(cmd_depth[48:][:], depth[56:][:8]) - copy(cmd_depth[56:][:], depth[16:][:8]) - convertBitDepthsToSymbols(cmd_depth[:], 64, cmd_bits[:]) - copy(bits, cmd_bits[24:][:8]) - copy(bits[8:], cmd_bits[40:][:8]) - copy(bits[16:], cmd_bits[56:][:8]) - copy(bits[24:], cmd_bits[:24]) - copy(bits[48:], cmd_bits[32:][:8]) - copy(bits[56:], cmd_bits[48:][:8]) - convertBitDepthsToSymbols(depth[64:], 64, bits[64:]) - { - /* Create the bit length array for the full command alphabet. */ - var i uint - for i := 0; i < int(64); i++ { - cmd_depth[i] = 0 - } /* only 64 first values were used */ - copy(cmd_depth[:], depth[24:][:8]) - copy(cmd_depth[64:][:], depth[32:][:8]) - copy(cmd_depth[128:][:], depth[40:][:8]) - copy(cmd_depth[192:][:], depth[48:][:8]) - copy(cmd_depth[384:][:], depth[56:][:8]) - for i = 0; i < 8; i++ { - cmd_depth[128+8*i] = depth[i] - cmd_depth[256+8*i] = depth[8+i] - cmd_depth[448+8*i] = depth[16+i] - } - - storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], storage_ix, storage) - } - - storeHuffmanTree(depth[64:], 64, tree[:], storage_ix, storage) -} - -func emitInsertLen(insertlen uint32, commands *[]uint32) { - if insertlen < 6 { - (*commands)[0] = insertlen - } else if insertlen < 130 { - var tail uint32 = insertlen - 2 - var nbits uint32 = log2FloorNonZero(uint(tail)) - 1 - var prefix uint32 = tail >> nbits - var inscode uint32 = (nbits << 1) + prefix + 2 - var extra uint32 = tail - (prefix << nbits) - (*commands)[0] = inscode | extra<<8 - } else if insertlen < 2114 { - var tail uint32 = insertlen - 66 - var nbits uint32 = log2FloorNonZero(uint(tail)) - var code uint32 = nbits + 10 - var extra uint32 = tail - (1 << nbits) - (*commands)[0] = code | extra<<8 - } else if insertlen < 6210 { - var extra uint32 = insertlen - 2114 - (*commands)[0] = 21 | extra<<8 - } else if insertlen < 22594 { - var extra uint32 = insertlen - 6210 - (*commands)[0] = 22 | extra<<8 - } else { - var extra uint32 = insertlen - 22594 - (*commands)[0] = 23 | extra<<8 - } - - *commands = (*commands)[1:] -} - -func emitCopyLen(copylen uint, commands *[]uint32) { - if copylen < 10 { - (*commands)[0] = uint32(copylen + 38) - } else if copylen < 134 { - var tail uint = copylen - 6 - var nbits uint = uint(log2FloorNonZero(tail) - 1) - var prefix uint = tail >> nbits - var code uint = (nbits << 1) + prefix + 44 - var extra uint = tail - (prefix << nbits) - (*commands)[0] = uint32(code | extra<<8) - } else if copylen < 2118 { - var tail uint = copylen - 70 - var nbits uint = uint(log2FloorNonZero(tail)) - var code uint = nbits + 52 - var extra uint = tail - (uint(1) << nbits) - (*commands)[0] = uint32(code | extra<<8) - } else { - var extra uint = copylen - 2118 - (*commands)[0] = uint32(63 | extra<<8) - } - - *commands = (*commands)[1:] -} - -func emitCopyLenLastDistance(copylen uint, commands *[]uint32) { - if copylen < 12 { - (*commands)[0] = uint32(copylen + 20) - *commands = (*commands)[1:] - } else if copylen < 72 { - var tail uint = copylen - 8 - var nbits uint = uint(log2FloorNonZero(tail) - 1) - var prefix uint = tail >> nbits - var code uint = (nbits << 1) + prefix + 28 - var extra uint = tail - (prefix << nbits) - (*commands)[0] = uint32(code | extra<<8) - *commands = (*commands)[1:] - } else if copylen < 136 { - var tail uint = copylen - 8 - var code uint = (tail >> 5) + 54 - var extra uint = tail & 31 - (*commands)[0] = uint32(code | extra<<8) - *commands = (*commands)[1:] - (*commands)[0] = 64 - *commands = (*commands)[1:] - } else if copylen < 2120 { - var tail uint = copylen - 72 - var nbits uint = uint(log2FloorNonZero(tail)) - var code uint = nbits + 52 - var extra uint = tail - (uint(1) << nbits) - (*commands)[0] = uint32(code | extra<<8) - *commands = (*commands)[1:] - (*commands)[0] = 64 - *commands = (*commands)[1:] - } else { - var extra uint = copylen - 2120 - (*commands)[0] = uint32(63 | extra<<8) - *commands = (*commands)[1:] - (*commands)[0] = 64 - *commands = (*commands)[1:] - } -} - -func emitDistance(distance uint32, commands *[]uint32) { - var d uint32 = distance + 3 - var nbits uint32 = log2FloorNonZero(uint(d)) - 1 - var prefix uint32 = (d >> nbits) & 1 - var offset uint32 = (2 + prefix) << nbits - var distcode uint32 = 2*(nbits-1) + prefix + 80 - var extra uint32 = d - offset - (*commands)[0] = distcode | extra<<8 - *commands = (*commands)[1:] -} - -/* REQUIRES: len <= 1 << 24. */ -func storeMetaBlockHeader(len uint, is_uncompressed bool, storage_ix *uint, storage []byte) { - var nibbles uint = 6 - - /* ISLAST */ - writeBits(1, 0, storage_ix, storage) - - if len <= 1<<16 { - nibbles = 4 - } else if len <= 1<<20 { - nibbles = 5 - } - - writeBits(2, uint64(nibbles)-4, storage_ix, storage) - writeBits(nibbles*4, uint64(len)-1, storage_ix, storage) - - /* ISUNCOMPRESSED */ - writeSingleBit(is_uncompressed, storage_ix, storage) -} - -func storeMetaBlockHeaderBW(len uint, is_uncompressed bool, bw *bitWriter) { - var nibbles uint = 6 - - /* ISLAST */ - bw.writeBits(1, 0) - - if len <= 1<<16 { - nibbles = 4 - } else if len <= 1<<20 { - nibbles = 5 - } else if len > 1<<24 { - panic("metablock too long") - } - - bw.writeBits(2, uint64(nibbles)-4) - bw.writeBits(nibbles*4, uint64(len)-1) - - /* ISUNCOMPRESSED */ - bw.writeSingleBit(is_uncompressed) -} - -func createCommands(input []byte, block_size uint, input_size uint, base_ip_ptr []byte, table []int, table_bits uint, min_match uint, literals *[]byte, commands *[]uint32) { - var ip int = 0 - var shift uint = 64 - table_bits - var ip_end int = int(block_size) - var base_ip int = -cap(base_ip_ptr) + cap(input) - var next_emit int = 0 - var last_distance int = -1 - /* "ip" is the input pointer. */ - - const kInputMarginBytes uint = windowGap - - /* "next_emit" is a pointer to the first byte that is not covered by a - previous copy. Bytes between "next_emit" and the start of the next copy or - the end of the input will be emitted as literal bytes. */ - if block_size >= kInputMarginBytes { - var len_limit uint = brotli_min_size_t(block_size-min_match, input_size-kInputMarginBytes) - var ip_limit int = int(len_limit) - /* For the last block, we need to keep a 16 bytes margin so that we can be - sure that all distances are at most window size - 16. - For all other blocks, we only need to keep a margin of 5 bytes so that - we don't go over the block size with a copy. */ - - var next_hash uint32 - ip++ - for next_hash = hash1(input[ip:], shift, min_match); ; { - var skip uint32 = 32 - var next_ip int = ip - /* Step 1: Scan forward in the input looking for a 6-byte-long match. - If we get close to exhausting the input then goto emit_remainder. - - Heuristic match skipping: If 32 bytes are scanned with no matches - found, start looking only at every other byte. If 32 more bytes are - scanned, look at every third byte, etc.. When a match is found, - immediately go back to looking at every byte. This is a small loss - (~5% performance, ~0.1% density) for compressible data due to more - bookkeeping, but for non-compressible data (such as JPEG) it's a huge - win since the compressor quickly "realizes" the data is incompressible - and doesn't bother looking for matches everywhere. - - The "skip" variable keeps track of how many bytes there are since the - last match; dividing it by 32 (ie. right-shifting by five) gives the - number of bytes to move ahead for each iteration. */ - - var candidate int - - assert(next_emit < ip) - - trawl: - for { - var hash uint32 = next_hash - var bytes_between_hash_lookups uint32 = skip >> 5 - skip++ - ip = next_ip - assert(hash == hash1(input[ip:], shift, min_match)) - next_ip = int(uint32(ip) + bytes_between_hash_lookups) - if next_ip > ip_limit { - goto emit_remainder - } - - next_hash = hash1(input[next_ip:], shift, min_match) - candidate = ip - last_distance - if isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) { - if candidate < ip { - table[hash] = int(ip - base_ip) - break - } - } - - candidate = base_ip + table[hash] - assert(candidate >= base_ip) - assert(candidate < ip) - - table[hash] = int(ip - base_ip) - if isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) { - break - } - } - - /* Check copy distance. If candidate is not feasible, continue search. - Checking is done outside of hot loop to reduce overhead. */ - if ip-candidate > maxDistance_compress_fragment { - goto trawl - } - - /* Step 2: Emit the found match together with the literal bytes from - "next_emit", and then see if we can find a next match immediately - afterwards. Repeat until we find no match for the input - without emitting some literal bytes. */ - { - var base int = ip - /* > 0 */ - var matched uint = min_match + findMatchLengthWithLimit(base_ip_ptr[uint(candidate-base_ip)+min_match:], input[uint(ip)+min_match:], uint(ip_end-ip)-min_match) - var distance int = int(base - candidate) - /* We have a 6-byte match at ip, and we need to emit bytes in - [next_emit, ip). */ - - var insert int = int(base - next_emit) - ip += int(matched) - emitInsertLen(uint32(insert), commands) - copy(*literals, input[next_emit:][:uint(insert)]) - *literals = (*literals)[insert:] - if distance == last_distance { - (*commands)[0] = 64 - *commands = (*commands)[1:] - } else { - emitDistance(uint32(distance), commands) - last_distance = distance - } - - emitCopyLenLastDistance(matched, commands) - - next_emit = ip - if ip >= ip_limit { - goto emit_remainder - } - { - var input_bytes uint64 - var cur_hash uint32 - /* We could immediately start working at ip now, but to improve - compression we first update "table" with the hashes of some - positions within the last copy. */ - - var prev_hash uint32 - if min_match == 4 { - input_bytes = binary.LittleEndian.Uint64(input[ip-3:]) - cur_hash = hashBytesAtOffset(input_bytes, 3, shift, min_match) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 3) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 1) - } else { - input_bytes = binary.LittleEndian.Uint64(input[ip-5:]) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 5) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 4) - prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match) - table[prev_hash] = int(ip - base_ip - 3) - input_bytes = binary.LittleEndian.Uint64(input[ip-2:]) - cur_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 1) - } - - candidate = base_ip + table[cur_hash] - table[cur_hash] = int(ip - base_ip) - } - } - - for ip-candidate <= maxDistance_compress_fragment && isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) { - var base int = ip - /* We have a 6-byte match at ip, and no need to emit any - literal bytes prior to ip. */ - - var matched uint = min_match + findMatchLengthWithLimit(base_ip_ptr[uint(candidate-base_ip)+min_match:], input[uint(ip)+min_match:], uint(ip_end-ip)-min_match) - ip += int(matched) - last_distance = int(base - candidate) /* > 0 */ - emitCopyLen(matched, commands) - emitDistance(uint32(last_distance), commands) - - next_emit = ip - if ip >= ip_limit { - goto emit_remainder - } - { - var input_bytes uint64 - var cur_hash uint32 - /* We could immediately start working at ip now, but to improve - compression we first update "table" with the hashes of some - positions within the last copy. */ - - var prev_hash uint32 - if min_match == 4 { - input_bytes = binary.LittleEndian.Uint64(input[ip-3:]) - cur_hash = hashBytesAtOffset(input_bytes, 3, shift, min_match) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 3) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match) - table[prev_hash] = int(ip - base_ip - 1) - } else { - input_bytes = binary.LittleEndian.Uint64(input[ip-5:]) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 5) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 4) - prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match) - table[prev_hash] = int(ip - base_ip - 3) - input_bytes = binary.LittleEndian.Uint64(input[ip-2:]) - cur_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match) - prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match) - table[prev_hash] = int(ip - base_ip - 2) - prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match) - table[prev_hash] = int(ip - base_ip - 1) - } - - candidate = base_ip + table[cur_hash] - table[cur_hash] = int(ip - base_ip) - } - } - - ip++ - next_hash = hash1(input[ip:], shift, min_match) - } - } - -emit_remainder: - assert(next_emit <= ip_end) - - /* Emit the remaining bytes as literals. */ - if next_emit < ip_end { - var insert uint32 = uint32(ip_end - next_emit) - emitInsertLen(insert, commands) - copy(*literals, input[next_emit:][:insert]) - *literals = (*literals)[insert:] - } -} - -var storeCommands_kNumExtraBits = [128]uint32{ - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 7, - 8, - 9, - 10, - 12, - 14, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 7, - 8, - 9, - 10, - 24, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 2, - 2, - 3, - 3, - 4, - 4, - 5, - 5, - 6, - 6, - 7, - 7, - 8, - 8, - 9, - 9, - 10, - 10, - 11, - 11, - 12, - 12, - 13, - 13, - 14, - 14, - 15, - 15, - 16, - 16, - 17, - 17, - 18, - 18, - 19, - 19, - 20, - 20, - 21, - 21, - 22, - 22, - 23, - 23, - 24, - 24, -} -var storeCommands_kInsertOffset = [24]uint32{ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 8, - 10, - 14, - 18, - 26, - 34, - 50, - 66, - 98, - 130, - 194, - 322, - 578, - 1090, - 2114, - 6210, - 22594, -} - -func storeCommands(literals []byte, num_literals uint, commands []uint32, num_commands uint, storage_ix *uint, storage []byte) { - var lit_depths [256]byte - var lit_bits [256]uint16 - var lit_histo = [256]uint32{0} - var cmd_depths = [128]byte{0} - var cmd_bits = [128]uint16{0} - var cmd_histo = [128]uint32{0} - var i uint - for i = 0; i < num_literals; i++ { - lit_histo[literals[i]]++ - } - - buildAndStoreHuffmanTreeFast(lit_histo[:], num_literals, /* max_bits = */ - 8, lit_depths[:], lit_bits[:], storage_ix, storage) - - for i = 0; i < num_commands; i++ { - var code uint32 = commands[i] & 0xFF - assert(code < 128) - cmd_histo[code]++ - } - - cmd_histo[1] += 1 - cmd_histo[2] += 1 - cmd_histo[64] += 1 - cmd_histo[84] += 1 - buildAndStoreCommandPrefixCode(cmd_histo[:], cmd_depths[:], cmd_bits[:], storage_ix, storage) - - for i = 0; i < num_commands; i++ { - var cmd uint32 = commands[i] - var code uint32 = cmd & 0xFF - var extra uint32 = cmd >> 8 - assert(code < 128) - writeBits(uint(cmd_depths[code]), uint64(cmd_bits[code]), storage_ix, storage) - writeBits(uint(storeCommands_kNumExtraBits[code]), uint64(extra), storage_ix, storage) - if code < 24 { - var insert uint32 = storeCommands_kInsertOffset[code] + extra - var j uint32 - for j = 0; j < insert; j++ { - var lit byte = literals[0] - writeBits(uint(lit_depths[lit]), uint64(lit_bits[lit]), storage_ix, storage) - literals = literals[1:] - } - } - } -} - -/* Acceptable loss for uncompressible speedup is 2% */ -const minRatio = 0.98 - -const sampleRate = 43 - -func shouldCompress(input []byte, input_size uint, num_literals uint) bool { - var corpus_size float64 = float64(input_size) - if float64(num_literals) < minRatio*corpus_size { - return true - } else { - var literal_histo = [256]uint32{0} - var max_total_bit_cost float64 = corpus_size * 8 * minRatio / sampleRate - var i uint - for i = 0; i < input_size; i += sampleRate { - literal_histo[input[i]]++ - } - - return bitsEntropy(literal_histo[:], 256) < max_total_bit_cost - } -} - -func rewindBitPosition(new_storage_ix uint, storage_ix *uint, storage []byte) { - var bitpos uint = new_storage_ix & 7 - var mask uint = (1 << bitpos) - 1 - storage[new_storage_ix>>3] &= byte(mask) - *storage_ix = new_storage_ix -} - -func emitUncompressedMetaBlock(input []byte, input_size uint, storage_ix *uint, storage []byte) { - storeMetaBlockHeader(input_size, true, storage_ix, storage) - *storage_ix = (*storage_ix + 7) &^ 7 - copy(storage[*storage_ix>>3:], input[:input_size]) - *storage_ix += input_size << 3 - storage[*storage_ix>>3] = 0 -} - -func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_bits uint, min_match uint, storage_ix *uint, storage []byte) { - /* Save the start of the first block for position and distance computations. - */ - var base_ip []byte = input - - for input_size > 0 { - var block_size uint = brotli_min_size_t(input_size, kCompressFragmentTwoPassBlockSize) - var commands []uint32 = command_buf - var literals []byte = literal_buf - var num_literals uint - createCommands(input, block_size, input_size, base_ip, table, table_bits, min_match, &literals, &commands) - num_literals = uint(-cap(literals) + cap(literal_buf)) - if shouldCompress(input, block_size, num_literals) { - var num_commands uint = uint(-cap(commands) + cap(command_buf)) - storeMetaBlockHeader(block_size, false, storage_ix, storage) - - /* No block splits, no contexts. */ - writeBits(13, 0, storage_ix, storage) - - storeCommands(literal_buf, num_literals, command_buf, num_commands, storage_ix, storage) - } else { - /* Since we did not find many backward references and the entropy of - the data is close to 8 bits, we can simply emit an uncompressed block. - This makes compression speed of uncompressible data about 3x faster. */ - emitUncompressedMetaBlock(input, block_size, storage_ix, storage) - } - - input = input[block_size:] - input_size -= block_size - } -} - -/* -Compresses "input" string to the "*storage" buffer as one or more complete - - meta-blocks, and updates the "*storage_ix" bit position. - - If "is_last" is 1, emits an additional empty last meta-block. - - REQUIRES: "input_size" is greater than zero, or "is_last" is 1. - REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24). - REQUIRES: "command_buf" and "literal_buf" point to at least - kCompressFragmentTwoPassBlockSize long arrays. - REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero. - REQUIRES: "table_size" is a power of two - OUTPUT: maximal copy distance <= |input_size| - OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) -*/ -func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_size uint, storage_ix *uint, storage []byte) { - var initial_storage_ix uint = *storage_ix - var table_bits uint = uint(log2FloorNonZero(table_size)) - var min_match uint - if table_bits <= 15 { - min_match = 4 - } else { - min_match = 6 - } - compressFragmentTwoPassImpl(input, input_size, is_last, command_buf, literal_buf, table, table_bits, min_match, storage_ix, storage) - - /* If output is larger than single uncompressed block, rewrite it. */ - if *storage_ix-initial_storage_ix > 31+(input_size<<3) { - rewindBitPosition(initial_storage_ix, storage_ix, storage) - emitUncompressedMetaBlock(input, input_size, storage_ix, storage) - } - - if is_last { - writeBits(1, 1, storage_ix, storage) /* islast */ - writeBits(1, 1, storage_ix, storage) /* isempty */ - *storage_ix = (*storage_ix + 7) &^ 7 - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/constants.go b/src/vendor/github.com/andybalholm/brotli/constants.go deleted file mode 100644 index a880dff7..00000000 --- a/src/vendor/github.com/andybalholm/brotli/constants.go +++ /dev/null @@ -1,77 +0,0 @@ -package brotli - -/* Copyright 2016 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Specification: 7.3. Encoding of the context map */ -const contextMapMaxRle = 16 - -/* Specification: 2. Compressed representation overview */ -const maxNumberOfBlockTypes = 256 - -/* Specification: 3.3. Alphabet sizes: insert-and-copy length */ -const numLiteralSymbols = 256 - -const numCommandSymbols = 704 - -const numBlockLenSymbols = 26 - -const maxContextMapSymbols = (maxNumberOfBlockTypes + contextMapMaxRle) - -const maxBlockTypeSymbols = (maxNumberOfBlockTypes + 2) - -/* Specification: 3.5. Complex prefix codes */ -const repeatPreviousCodeLength = 16 - -const repeatZeroCodeLength = 17 - -const codeLengthCodes = (repeatZeroCodeLength + 1) - -/* "code length of 8 is repeated" */ -const initialRepeatedCodeLength = 8 - -/* "Large Window Brotli" */ -const largeMaxDistanceBits = 62 - -const largeMinWbits = 10 - -const largeMaxWbits = 30 - -/* Specification: 4. Encoding of distances */ -const numDistanceShortCodes = 16 - -const maxNpostfix = 3 - -const maxNdirect = 120 - -const maxDistanceBits = 24 - -func distanceAlphabetSize(NPOSTFIX uint, NDIRECT uint, MAXNBITS uint) uint { - return numDistanceShortCodes + NDIRECT + uint(MAXNBITS<<(NPOSTFIX+1)) -} - -/* numDistanceSymbols == 1128 */ -const numDistanceSymbols = 1128 - -const maxDistance = 0x3FFFFFC - -const maxAllowedDistance = 0x7FFFFFFC - -/* 7.1. Context modes and context ID lookup for literals */ -/* "context IDs for literals are in the range of 0..63" */ -const literalContextBits = 6 - -/* 7.2. Context ID for distances */ -const distanceContextBits = 2 - -/* 9.1. Format of the Stream Header */ -/* Number of slack bytes for window size. Don't confuse - with BROTLI_NUM_DISTANCE_SHORT_CODES. */ -const windowGap = 16 - -func maxBackwardLimit(W uint) uint { - return (uint(1) << W) - windowGap -} diff --git a/src/vendor/github.com/andybalholm/brotli/context.go b/src/vendor/github.com/andybalholm/brotli/context.go deleted file mode 100644 index 884ff8a2..00000000 --- a/src/vendor/github.com/andybalholm/brotli/context.go +++ /dev/null @@ -1,2176 +0,0 @@ -package brotli - -/* Lookup table to map the previous two bytes to a context id. - -There are four different context modeling modes defined here: - contextLSB6: context id is the least significant 6 bits of the last byte, - contextMSB6: context id is the most significant 6 bits of the last byte, - contextUTF8: second-order context model tuned for UTF8-encoded text, - contextSigned: second-order context model tuned for signed integers. - -If |p1| and |p2| are the previous two bytes, and |mode| is current context -mode, we calculate the context as: - - context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256]. - -For contextUTF8 mode, if the previous two bytes are ASCII characters -(i.e. < 128), this will be equivalent to - - context = 4 * context1(p1) + context2(p2), - -where context1 is based on the previous byte in the following way: - - 0 : non-ASCII control - 1 : \t, \n, \r - 2 : space - 3 : other punctuation - 4 : " ' - 5 : % - 6 : ( < [ { - 7 : ) > ] } - 8 : , ; : - 9 : . - 10 : = - 11 : number - 12 : upper-case vowel - 13 : upper-case consonant - 14 : lower-case vowel - 15 : lower-case consonant - -and context2 is based on the second last byte: - - 0 : control, space - 1 : punctuation - 2 : upper-case letter, number - 3 : lower-case letter - -If the last byte is ASCII, and the second last byte is not (in a valid UTF8 -stream it will be a continuation byte, value between 128 and 191), the -context is the same as if the second last byte was an ASCII control or space. - -If the last byte is a UTF8 lead byte (value >= 192), then the next byte will -be a continuation byte and the context id is 2 or 3 depending on the LSB of -the last byte and to a lesser extent on the second last byte if it is ASCII. - -If the last byte is a UTF8 continuation byte, the second last byte can be: - - continuation byte: the next byte is probably ASCII or lead byte (assuming - 4-byte UTF8 characters are rare) and the context id is 0 or 1. - - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1 - - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3 - -The possible value combinations of the previous two bytes, the range of -context ids and the type of the next byte is summarized in the table below: - -|--------\-----------------------------------------------------------------| -| \ Last byte | -| Second \---------------------------------------------------------------| -| last byte \ ASCII | cont. byte | lead byte | -| \ (0-127) | (128-191) | (192-) | -|=============|===================|=====================|==================| -| ASCII | next: ASCII/lead | not valid | next: cont. | -| (0-127) | context: 4 - 63 | | context: 2 - 3 | -|-------------|-------------------|---------------------|------------------| -| cont. byte | next: ASCII/lead | next: ASCII/lead | next: cont. | -| (128-191) | context: 4 - 63 | context: 0 - 1 | context: 2 - 3 | -|-------------|-------------------|---------------------|------------------| -| lead byte | not valid | next: ASCII/lead | not valid | -| (192-207) | | context: 0 - 1 | | -|-------------|-------------------|---------------------|------------------| -| lead byte | not valid | next: cont. | not valid | -| (208-) | | context: 2 - 3 | | -|-------------|-------------------|---------------------|------------------| -*/ - -const ( - contextLSB6 = 0 - contextMSB6 = 1 - contextUTF8 = 2 - contextSigned = 3 -) - -/* Common context lookup table for all context modes. */ -var kContextLookup = [2048]byte{ - /* CONTEXT_LSB6, last byte. */ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32, - 33, - 34, - 35, - 36, - 37, - 38, - 39, - 40, - 41, - 42, - 43, - 44, - 45, - 46, - 47, - 48, - 49, - 50, - 51, - 52, - 53, - 54, - 55, - 56, - 57, - 58, - 59, - 60, - 61, - 62, - 63, - - /* CONTEXT_LSB6, second last byte, */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - /* CONTEXT_MSB6, last byte. */ - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 5, - 6, - 6, - 6, - 6, - 7, - 7, - 7, - 7, - 8, - 8, - 8, - 8, - 9, - 9, - 9, - 9, - 10, - 10, - 10, - 10, - 11, - 11, - 11, - 11, - 12, - 12, - 12, - 12, - 13, - 13, - 13, - 13, - 14, - 14, - 14, - 14, - 15, - 15, - 15, - 15, - 16, - 16, - 16, - 16, - 17, - 17, - 17, - 17, - 18, - 18, - 18, - 18, - 19, - 19, - 19, - 19, - 20, - 20, - 20, - 20, - 21, - 21, - 21, - 21, - 22, - 22, - 22, - 22, - 23, - 23, - 23, - 23, - 24, - 24, - 24, - 24, - 25, - 25, - 25, - 25, - 26, - 26, - 26, - 26, - 27, - 27, - 27, - 27, - 28, - 28, - 28, - 28, - 29, - 29, - 29, - 29, - 30, - 30, - 30, - 30, - 31, - 31, - 31, - 31, - 32, - 32, - 32, - 32, - 33, - 33, - 33, - 33, - 34, - 34, - 34, - 34, - 35, - 35, - 35, - 35, - 36, - 36, - 36, - 36, - 37, - 37, - 37, - 37, - 38, - 38, - 38, - 38, - 39, - 39, - 39, - 39, - 40, - 40, - 40, - 40, - 41, - 41, - 41, - 41, - 42, - 42, - 42, - 42, - 43, - 43, - 43, - 43, - 44, - 44, - 44, - 44, - 45, - 45, - 45, - 45, - 46, - 46, - 46, - 46, - 47, - 47, - 47, - 47, - 48, - 48, - 48, - 48, - 49, - 49, - 49, - 49, - 50, - 50, - 50, - 50, - 51, - 51, - 51, - 51, - 52, - 52, - 52, - 52, - 53, - 53, - 53, - 53, - 54, - 54, - 54, - 54, - 55, - 55, - 55, - 55, - 56, - 56, - 56, - 56, - 57, - 57, - 57, - 57, - 58, - 58, - 58, - 58, - 59, - 59, - 59, - 59, - 60, - 60, - 60, - 60, - 61, - 61, - 61, - 61, - 62, - 62, - 62, - 62, - 63, - 63, - 63, - 63, - - /* CONTEXT_MSB6, second last byte, */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - /* CONTEXT_UTF8, last byte. */ - /* ASCII range. */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4, - 4, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8, - 12, - 16, - 12, - 12, - 20, - 12, - 16, - 24, - 28, - 12, - 12, - 32, - 12, - 36, - 12, - 44, - 44, - 44, - 44, - 44, - 44, - 44, - 44, - 44, - 44, - 32, - 32, - 24, - 40, - 28, - 12, - 12, - 48, - 52, - 52, - 52, - 48, - 52, - 52, - 52, - 48, - 52, - 52, - 52, - 52, - 52, - 48, - 52, - 52, - 52, - 52, - 52, - 48, - 52, - 52, - 52, - 52, - 52, - 24, - 12, - 28, - 12, - 12, - 12, - 56, - 60, - 60, - 60, - 56, - 60, - 60, - 60, - 56, - 60, - 60, - 60, - 60, - 60, - 56, - 60, - 60, - 60, - 60, - 60, - 56, - 60, - 60, - 60, - 60, - 60, - 24, - 12, - 28, - 12, - 0, - - /* UTF8 continuation byte range. */ - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - 0, - 1, - - /* UTF8 lead byte range. */ - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - 2, - 3, - - /* CONTEXT_UTF8 second last byte. */ - /* ASCII range. */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 1, - 1, - 1, - 1, - 1, - 1, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 1, - 1, - 1, - 1, - 0, - - /* UTF8 continuation byte range. */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - - /* UTF8 lead byte range. */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - - /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */ - 0, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 16, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 40, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 56, - - /* CONTEXT_SIGNED, second last byte. */ - 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 2, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 3, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 4, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 5, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 7, -} - -type contextLUT []byte - -func getContextLUT(mode int) contextLUT { - return kContextLookup[mode<<9:] -} - -func getContext(p1 byte, p2 byte, lut contextLUT) byte { - return lut[p1] | lut[256+int(p2)] -} diff --git a/src/vendor/github.com/andybalholm/brotli/decode.go b/src/vendor/github.com/andybalholm/brotli/decode.go deleted file mode 100644 index 1a27c0a6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/decode.go +++ /dev/null @@ -1,2570 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -const ( - decoderResultError = 0 - decoderResultSuccess = 1 - decoderResultNeedsMoreInput = 2 - decoderResultNeedsMoreOutput = 3 -) - -/** - * Error code for detailed logging / production debugging. - * - * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE. - */ -const ( - decoderNoError = 0 - decoderSuccess = 1 - decoderNeedsMoreInput = 2 - decoderNeedsMoreOutput = 3 - decoderErrorFormatExuberantNibble = -1 - decoderErrorFormatReserved = -2 - decoderErrorFormatExuberantMetaNibble = -3 - decoderErrorFormatSimpleHuffmanAlphabet = -4 - decoderErrorFormatSimpleHuffmanSame = -5 - decoderErrorFormatClSpace = -6 - decoderErrorFormatHuffmanSpace = -7 - decoderErrorFormatContextMapRepeat = -8 - decoderErrorFormatBlockLength1 = -9 - decoderErrorFormatBlockLength2 = -10 - decoderErrorFormatTransform = -11 - decoderErrorFormatDictionary = -12 - decoderErrorFormatWindowBits = -13 - decoderErrorFormatPadding1 = -14 - decoderErrorFormatPadding2 = -15 - decoderErrorFormatDistance = -16 - decoderErrorDictionaryNotSet = -19 - decoderErrorInvalidArguments = -20 - decoderErrorAllocContextModes = -21 - decoderErrorAllocTreeGroups = -22 - decoderErrorAllocContextMap = -25 - decoderErrorAllocRingBuffer1 = -26 - decoderErrorAllocRingBuffer2 = -27 - decoderErrorAllocBlockTypeTrees = -30 - decoderErrorUnreachable = -31 -) - -const huffmanTableBits = 8 - -const huffmanTableMask = 0xFF - -/* We need the slack region for the following reasons: - - doing up to two 16-byte copies for fast backward copying - - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */ -const kRingBufferWriteAheadSlack uint32 = 42 - -var kCodeLengthCodeOrder = [codeLengthCodes]byte{1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15} - -/* Static prefix code for the complex code length code lengths. */ -var kCodeLengthPrefixLength = [16]byte{2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4} - -var kCodeLengthPrefixValue = [16]byte{0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5} - -/* Saves error code and converts it to BrotliDecoderResult. */ -func saveErrorCode(s *Reader, e int) int { - s.error_code = int(e) - switch e { - case decoderSuccess: - return decoderResultSuccess - - case decoderNeedsMoreInput: - return decoderResultNeedsMoreInput - - case decoderNeedsMoreOutput: - return decoderResultNeedsMoreOutput - - default: - return decoderResultError - } -} - -/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli". - Precondition: bit-reader accumulator has at least 8 bits. */ -func decodeWindowBits(s *Reader, br *bitReader) int { - var n uint32 - var large_window bool = s.large_window - s.large_window = false - takeBits(br, 1, &n) - if n == 0 { - s.window_bits = 16 - return decoderSuccess - } - - takeBits(br, 3, &n) - if n != 0 { - s.window_bits = 17 + n - return decoderSuccess - } - - takeBits(br, 3, &n) - if n == 1 { - if large_window { - takeBits(br, 1, &n) - if n == 1 { - return decoderErrorFormatWindowBits - } - - s.large_window = true - return decoderSuccess - } else { - return decoderErrorFormatWindowBits - } - } - - if n != 0 { - s.window_bits = 8 + n - return decoderSuccess - } - - s.window_bits = 17 - return decoderSuccess -} - -/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */ -func decodeVarLenUint8(s *Reader, br *bitReader, value *uint32) int { - var bits uint32 - switch s.substate_decode_uint8 { - case stateDecodeUint8None: - if !safeReadBits(br, 1, &bits) { - return decoderNeedsMoreInput - } - - if bits == 0 { - *value = 0 - return decoderSuccess - } - fallthrough - - /* Fall through. */ - case stateDecodeUint8Short: - if !safeReadBits(br, 3, &bits) { - s.substate_decode_uint8 = stateDecodeUint8Short - return decoderNeedsMoreInput - } - - if bits == 0 { - *value = 1 - s.substate_decode_uint8 = stateDecodeUint8None - return decoderSuccess - } - - /* Use output value as a temporary storage. It MUST be persisted. */ - *value = bits - fallthrough - - /* Fall through. */ - case stateDecodeUint8Long: - if !safeReadBits(br, *value, &bits) { - s.substate_decode_uint8 = stateDecodeUint8Long - return decoderNeedsMoreInput - } - - *value = (1 << *value) + bits - s.substate_decode_uint8 = stateDecodeUint8None - return decoderSuccess - - default: - return decoderErrorUnreachable - } -} - -/* Decodes a metablock length and flags by reading 2 - 31 bits. */ -func decodeMetaBlockLength(s *Reader, br *bitReader) int { - var bits uint32 - var i int - for { - switch s.substate_metablock_header { - case stateMetablockHeaderNone: - if !safeReadBits(br, 1, &bits) { - return decoderNeedsMoreInput - } - - if bits != 0 { - s.is_last_metablock = 1 - } else { - s.is_last_metablock = 0 - } - s.meta_block_remaining_len = 0 - s.is_uncompressed = 0 - s.is_metadata = 0 - if s.is_last_metablock == 0 { - s.substate_metablock_header = stateMetablockHeaderNibbles - break - } - - s.substate_metablock_header = stateMetablockHeaderEmpty - fallthrough - - /* Fall through. */ - case stateMetablockHeaderEmpty: - if !safeReadBits(br, 1, &bits) { - return decoderNeedsMoreInput - } - - if bits != 0 { - s.substate_metablock_header = stateMetablockHeaderNone - return decoderSuccess - } - - s.substate_metablock_header = stateMetablockHeaderNibbles - fallthrough - - /* Fall through. */ - case stateMetablockHeaderNibbles: - if !safeReadBits(br, 2, &bits) { - return decoderNeedsMoreInput - } - - s.size_nibbles = uint(byte(bits + 4)) - s.loop_counter = 0 - if bits == 3 { - s.is_metadata = 1 - s.substate_metablock_header = stateMetablockHeaderReserved - break - } - - s.substate_metablock_header = stateMetablockHeaderSize - fallthrough - - /* Fall through. */ - case stateMetablockHeaderSize: - i = s.loop_counter - - for ; i < int(s.size_nibbles); i++ { - if !safeReadBits(br, 4, &bits) { - s.loop_counter = i - return decoderNeedsMoreInput - } - - if uint(i+1) == s.size_nibbles && s.size_nibbles > 4 && bits == 0 { - return decoderErrorFormatExuberantNibble - } - - s.meta_block_remaining_len |= int(bits << uint(i*4)) - } - - s.substate_metablock_header = stateMetablockHeaderUncompressed - fallthrough - - /* Fall through. */ - case stateMetablockHeaderUncompressed: - if s.is_last_metablock == 0 { - if !safeReadBits(br, 1, &bits) { - return decoderNeedsMoreInput - } - - if bits != 0 { - s.is_uncompressed = 1 - } else { - s.is_uncompressed = 0 - } - } - - s.meta_block_remaining_len++ - s.substate_metablock_header = stateMetablockHeaderNone - return decoderSuccess - - case stateMetablockHeaderReserved: - if !safeReadBits(br, 1, &bits) { - return decoderNeedsMoreInput - } - - if bits != 0 { - return decoderErrorFormatReserved - } - - s.substate_metablock_header = stateMetablockHeaderBytes - fallthrough - - /* Fall through. */ - case stateMetablockHeaderBytes: - if !safeReadBits(br, 2, &bits) { - return decoderNeedsMoreInput - } - - if bits == 0 { - s.substate_metablock_header = stateMetablockHeaderNone - return decoderSuccess - } - - s.size_nibbles = uint(byte(bits)) - s.substate_metablock_header = stateMetablockHeaderMetadata - fallthrough - - /* Fall through. */ - case stateMetablockHeaderMetadata: - i = s.loop_counter - - for ; i < int(s.size_nibbles); i++ { - if !safeReadBits(br, 8, &bits) { - s.loop_counter = i - return decoderNeedsMoreInput - } - - if uint(i+1) == s.size_nibbles && s.size_nibbles > 1 && bits == 0 { - return decoderErrorFormatExuberantMetaNibble - } - - s.meta_block_remaining_len |= int(bits << uint(i*8)) - } - - s.meta_block_remaining_len++ - s.substate_metablock_header = stateMetablockHeaderNone - return decoderSuccess - - default: - return decoderErrorUnreachable - } - } -} - -/* Decodes the Huffman code. - This method doesn't read data from the bit reader, BUT drops the amount of - bits that correspond to the decoded symbol. - bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */ -func decodeSymbol(bits uint32, table []huffmanCode, br *bitReader) uint32 { - table = table[bits&huffmanTableMask:] - if table[0].bits > huffmanTableBits { - var nbits uint32 = uint32(table[0].bits) - huffmanTableBits - dropBits(br, huffmanTableBits) - table = table[uint32(table[0].value)+((bits>>huffmanTableBits)&bitMask(nbits)):] - } - - dropBits(br, uint32(table[0].bits)) - return uint32(table[0].value) -} - -/* Reads and decodes the next Huffman code from bit-stream. - This method peeks 16 bits of input and drops 0 - 15 of them. */ -func readSymbol(table []huffmanCode, br *bitReader) uint32 { - return decodeSymbol(get16BitsUnmasked(br), table, br) -} - -/* Same as DecodeSymbol, but it is known that there is less than 15 bits of - input are currently available. */ -func safeDecodeSymbol(table []huffmanCode, br *bitReader, result *uint32) bool { - var val uint32 - var available_bits uint32 = getAvailableBits(br) - if available_bits == 0 { - if table[0].bits == 0 { - *result = uint32(table[0].value) - return true - } - - return false /* No valid bits at all. */ - } - - val = uint32(getBitsUnmasked(br)) - table = table[val&huffmanTableMask:] - if table[0].bits <= huffmanTableBits { - if uint32(table[0].bits) <= available_bits { - dropBits(br, uint32(table[0].bits)) - *result = uint32(table[0].value) - return true - } else { - return false /* Not enough bits for the first level. */ - } - } - - if available_bits <= huffmanTableBits { - return false /* Not enough bits to move to the second level. */ - } - - /* Speculatively drop HUFFMAN_TABLE_BITS. */ - val = (val & bitMask(uint32(table[0].bits))) >> huffmanTableBits - - available_bits -= huffmanTableBits - table = table[uint32(table[0].value)+val:] - if available_bits < uint32(table[0].bits) { - return false /* Not enough bits for the second level. */ - } - - dropBits(br, huffmanTableBits+uint32(table[0].bits)) - *result = uint32(table[0].value) - return true -} - -func safeReadSymbol(table []huffmanCode, br *bitReader, result *uint32) bool { - var val uint32 - if safeGetBits(br, 15, &val) { - *result = decodeSymbol(val, table, br) - return true - } - - return safeDecodeSymbol(table, br, result) -} - -/* Makes a look-up in first level Huffman table. Peeks 8 bits. */ -func preloadSymbol(safe int, table []huffmanCode, br *bitReader, bits *uint32, value *uint32) { - if safe != 0 { - return - } - - table = table[getBits(br, huffmanTableBits):] - *bits = uint32(table[0].bits) - *value = uint32(table[0].value) -} - -/* Decodes the next Huffman code using data prepared by PreloadSymbol. - Reads 0 - 15 bits. Also peeks 8 following bits. */ -func readPreloadedSymbol(table []huffmanCode, br *bitReader, bits *uint32, value *uint32) uint32 { - var result uint32 = *value - var ext []huffmanCode - if *bits > huffmanTableBits { - var val uint32 = get16BitsUnmasked(br) - ext = table[val&huffmanTableMask:][*value:] - var mask uint32 = bitMask((*bits - huffmanTableBits)) - dropBits(br, huffmanTableBits) - ext = ext[(val>>huffmanTableBits)&mask:] - dropBits(br, uint32(ext[0].bits)) - result = uint32(ext[0].value) - } else { - dropBits(br, *bits) - } - - preloadSymbol(0, table, br, bits, value) - return result -} - -func log2Floor(x uint32) uint32 { - var result uint32 = 0 - for x != 0 { - x >>= 1 - result++ - } - - return result -} - -/* Reads (s->symbol + 1) symbols. - Totally 1..4 symbols are read, 1..11 bits each. - The list of symbols MUST NOT contain duplicates. */ -func readSimpleHuffmanSymbols(alphabet_size uint32, max_symbol uint32, s *Reader) int { - var br *bitReader = &s.br - var max_bits uint32 = log2Floor(alphabet_size - 1) - var i uint32 = s.sub_loop_counter - /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */ - - var num_symbols uint32 = s.symbol - for i <= num_symbols { - var v uint32 - if !safeReadBits(br, max_bits, &v) { - s.sub_loop_counter = i - s.substate_huffman = stateHuffmanSimpleRead - return decoderNeedsMoreInput - } - - if v >= max_symbol { - return decoderErrorFormatSimpleHuffmanAlphabet - } - - s.symbols_lists_array[i] = uint16(v) - i++ - } - - for i = 0; i < num_symbols; i++ { - var k uint32 = i + 1 - for ; k <= num_symbols; k++ { - if s.symbols_lists_array[i] == s.symbols_lists_array[k] { - return decoderErrorFormatSimpleHuffmanSame - } - } - } - - return decoderSuccess -} - -/* Process single decoded symbol code length: - A) reset the repeat variable - B) remember code length (if it is not 0) - C) extend corresponding index-chain - D) reduce the Huffman space - E) update the histogram */ -func processSingleCodeLength(code_len uint32, symbol *uint32, repeat *uint32, space *uint32, prev_code_len *uint32, symbol_lists symbolList, code_length_histo []uint16, next_symbol []int) { - *repeat = 0 - if code_len != 0 { /* code_len == 1..15 */ - symbolListPut(symbol_lists, next_symbol[code_len], uint16(*symbol)) - next_symbol[code_len] = int(*symbol) - *prev_code_len = code_len - *space -= 32768 >> code_len - code_length_histo[code_len]++ - } - - (*symbol)++ -} - -/* Process repeated symbol code length. - A) Check if it is the extension of previous repeat sequence; if the decoded - value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new - symbol-skip - B) Update repeat variable - C) Check if operation is feasible (fits alphabet) - D) For each symbol do the same operations as in ProcessSingleCodeLength - - PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or - code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */ -func processRepeatedCodeLength(code_len uint32, repeat_delta uint32, alphabet_size uint32, symbol *uint32, repeat *uint32, space *uint32, prev_code_len *uint32, repeat_code_len *uint32, symbol_lists symbolList, code_length_histo []uint16, next_symbol []int) { - var old_repeat uint32 /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */ /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */ - var extra_bits uint32 = 3 - var new_len uint32 = 0 - if code_len == repeatPreviousCodeLength { - new_len = *prev_code_len - extra_bits = 2 - } - - if *repeat_code_len != new_len { - *repeat = 0 - *repeat_code_len = new_len - } - - old_repeat = *repeat - if *repeat > 0 { - *repeat -= 2 - *repeat <<= extra_bits - } - - *repeat += repeat_delta + 3 - repeat_delta = *repeat - old_repeat - if *symbol+repeat_delta > alphabet_size { - *symbol = alphabet_size - *space = 0xFFFFF - return - } - - if *repeat_code_len != 0 { - var last uint = uint(*symbol + repeat_delta) - var next int = next_symbol[*repeat_code_len] - for { - symbolListPut(symbol_lists, next, uint16(*symbol)) - next = int(*symbol) - (*symbol)++ - if (*symbol) == uint32(last) { - break - } - } - - next_symbol[*repeat_code_len] = next - *space -= repeat_delta << (15 - *repeat_code_len) - code_length_histo[*repeat_code_len] = uint16(uint32(code_length_histo[*repeat_code_len]) + repeat_delta) - } else { - *symbol += repeat_delta - } -} - -/* Reads and decodes symbol codelengths. */ -func readSymbolCodeLengths(alphabet_size uint32, s *Reader) int { - var br *bitReader = &s.br - var symbol uint32 = s.symbol - var repeat uint32 = s.repeat - var space uint32 = s.space - var prev_code_len uint32 = s.prev_code_len - var repeat_code_len uint32 = s.repeat_code_len - var symbol_lists symbolList = s.symbol_lists - var code_length_histo []uint16 = s.code_length_histo[:] - var next_symbol []int = s.next_symbol[:] - if !warmupBitReader(br) { - return decoderNeedsMoreInput - } - var p []huffmanCode - for symbol < alphabet_size && space > 0 { - p = s.table[:] - var code_len uint32 - if !checkInputAmount(br, shortFillBitWindowRead) { - s.symbol = symbol - s.repeat = repeat - s.prev_code_len = prev_code_len - s.repeat_code_len = repeat_code_len - s.space = space - return decoderNeedsMoreInput - } - - fillBitWindow16(br) - p = p[getBitsUnmasked(br)&uint64(bitMask(huffmanMaxCodeLengthCodeLength)):] - dropBits(br, uint32(p[0].bits)) /* Use 1..5 bits. */ - code_len = uint32(p[0].value) /* code_len == 0..17 */ - if code_len < repeatPreviousCodeLength { - processSingleCodeLength(code_len, &symbol, &repeat, &space, &prev_code_len, symbol_lists, code_length_histo, next_symbol) /* code_len == 16..17, extra_bits == 2..3 */ - } else { - var extra_bits uint32 - if code_len == repeatPreviousCodeLength { - extra_bits = 2 - } else { - extra_bits = 3 - } - var repeat_delta uint32 = uint32(getBitsUnmasked(br)) & bitMask(extra_bits) - dropBits(br, extra_bits) - processRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &symbol, &repeat, &space, &prev_code_len, &repeat_code_len, symbol_lists, code_length_histo, next_symbol) - } - } - - s.space = space - return decoderSuccess -} - -func safeReadSymbolCodeLengths(alphabet_size uint32, s *Reader) int { - var br *bitReader = &s.br - var get_byte bool = false - var p []huffmanCode - for s.symbol < alphabet_size && s.space > 0 { - p = s.table[:] - var code_len uint32 - var available_bits uint32 - var bits uint32 = 0 - if get_byte && !pullByte(br) { - return decoderNeedsMoreInput - } - get_byte = false - available_bits = getAvailableBits(br) - if available_bits != 0 { - bits = uint32(getBitsUnmasked(br)) - } - - p = p[bits&bitMask(huffmanMaxCodeLengthCodeLength):] - if uint32(p[0].bits) > available_bits { - get_byte = true - continue - } - - code_len = uint32(p[0].value) /* code_len == 0..17 */ - if code_len < repeatPreviousCodeLength { - dropBits(br, uint32(p[0].bits)) - processSingleCodeLength(code_len, &s.symbol, &s.repeat, &s.space, &s.prev_code_len, s.symbol_lists, s.code_length_histo[:], s.next_symbol[:]) /* code_len == 16..17, extra_bits == 2..3 */ - } else { - var extra_bits uint32 = code_len - 14 - var repeat_delta uint32 = (bits >> p[0].bits) & bitMask(extra_bits) - if available_bits < uint32(p[0].bits)+extra_bits { - get_byte = true - continue - } - - dropBits(br, uint32(p[0].bits)+extra_bits) - processRepeatedCodeLength(code_len, repeat_delta, alphabet_size, &s.symbol, &s.repeat, &s.space, &s.prev_code_len, &s.repeat_code_len, s.symbol_lists, s.code_length_histo[:], s.next_symbol[:]) - } - } - - return decoderSuccess -} - -/* Reads and decodes 15..18 codes using static prefix code. - Each code is 2..4 bits long. In total 30..72 bits are used. */ -func readCodeLengthCodeLengths(s *Reader) int { - var br *bitReader = &s.br - var num_codes uint32 = s.repeat - var space uint32 = s.space - var i uint32 = s.sub_loop_counter - for ; i < codeLengthCodes; i++ { - var code_len_idx byte = kCodeLengthCodeOrder[i] - var ix uint32 - var v uint32 - if !safeGetBits(br, 4, &ix) { - var available_bits uint32 = getAvailableBits(br) - if available_bits != 0 { - ix = uint32(getBitsUnmasked(br) & 0xF) - } else { - ix = 0 - } - - if uint32(kCodeLengthPrefixLength[ix]) > available_bits { - s.sub_loop_counter = i - s.repeat = num_codes - s.space = space - s.substate_huffman = stateHuffmanComplex - return decoderNeedsMoreInput - } - } - - v = uint32(kCodeLengthPrefixValue[ix]) - dropBits(br, uint32(kCodeLengthPrefixLength[ix])) - s.code_length_code_lengths[code_len_idx] = byte(v) - if v != 0 { - space = space - (32 >> v) - num_codes++ - s.code_length_histo[v]++ - if space-1 >= 32 { - /* space is 0 or wrapped around. */ - break - } - } - } - - if num_codes != 1 && space != 0 { - return decoderErrorFormatClSpace - } - - return decoderSuccess -} - -/* Decodes the Huffman tables. - There are 2 scenarios: - A) Huffman code contains only few symbols (1..4). Those symbols are read - directly; their code lengths are defined by the number of symbols. - For this scenario 4 - 49 bits will be read. - - B) 2-phase decoding: - B.1) Small Huffman table is decoded; it is specified with code lengths - encoded with predefined entropy code. 32 - 74 bits are used. - B.2) Decoded table is used to decode code lengths of symbols in resulting - Huffman table. In worst case 3520 bits are read. */ -func readHuffmanCode(alphabet_size uint32, max_symbol uint32, table []huffmanCode, opt_table_size *uint32, s *Reader) int { - var br *bitReader = &s.br - - /* Unnecessary masking, but might be good for safety. */ - alphabet_size &= 0x7FF - - /* State machine. */ - for { - switch s.substate_huffman { - case stateHuffmanNone: - if !safeReadBits(br, 2, &s.sub_loop_counter) { - return decoderNeedsMoreInput - } - - /* The value is used as follows: - 1 for simple code; - 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ - if s.sub_loop_counter != 1 { - s.space = 32 - s.repeat = 0 /* num_codes */ - var i int - for i = 0; i <= huffmanMaxCodeLengthCodeLength; i++ { - s.code_length_histo[i] = 0 - } - - for i = 0; i < codeLengthCodes; i++ { - s.code_length_code_lengths[i] = 0 - } - - s.substate_huffman = stateHuffmanComplex - continue - } - fallthrough - - /* Read symbols, codes & code lengths directly. */ - case stateHuffmanSimpleSize: - if !safeReadBits(br, 2, &s.symbol) { /* num_symbols */ - s.substate_huffman = stateHuffmanSimpleSize - return decoderNeedsMoreInput - } - - s.sub_loop_counter = 0 - fallthrough - - case stateHuffmanSimpleRead: - { - var result int = readSimpleHuffmanSymbols(alphabet_size, max_symbol, s) - if result != decoderSuccess { - return result - } - } - fallthrough - - case stateHuffmanSimpleBuild: - var table_size uint32 - if s.symbol == 3 { - var bits uint32 - if !safeReadBits(br, 1, &bits) { - s.substate_huffman = stateHuffmanSimpleBuild - return decoderNeedsMoreInput - } - - s.symbol += bits - } - - table_size = buildSimpleHuffmanTable(table, huffmanTableBits, s.symbols_lists_array[:], s.symbol) - if opt_table_size != nil { - *opt_table_size = table_size - } - - s.substate_huffman = stateHuffmanNone - return decoderSuccess - - /* Decode Huffman-coded code lengths. */ - case stateHuffmanComplex: - { - var i uint32 - var result int = readCodeLengthCodeLengths(s) - if result != decoderSuccess { - return result - } - - buildCodeLengthsHuffmanTable(s.table[:], s.code_length_code_lengths[:], s.code_length_histo[:]) - for i = 0; i < 16; i++ { - s.code_length_histo[i] = 0 - } - - for i = 0; i <= huffmanMaxCodeLength; i++ { - s.next_symbol[i] = int(i) - (huffmanMaxCodeLength + 1) - symbolListPut(s.symbol_lists, s.next_symbol[i], 0xFFFF) - } - - s.symbol = 0 - s.prev_code_len = initialRepeatedCodeLength - s.repeat = 0 - s.repeat_code_len = 0 - s.space = 32768 - s.substate_huffman = stateHuffmanLengthSymbols - } - fallthrough - - case stateHuffmanLengthSymbols: - var table_size uint32 - var result int = readSymbolCodeLengths(max_symbol, s) - if result == decoderNeedsMoreInput { - result = safeReadSymbolCodeLengths(max_symbol, s) - } - - if result != decoderSuccess { - return result - } - - if s.space != 0 { - return decoderErrorFormatHuffmanSpace - } - - table_size = buildHuffmanTable(table, huffmanTableBits, s.symbol_lists, s.code_length_histo[:]) - if opt_table_size != nil { - *opt_table_size = table_size - } - - s.substate_huffman = stateHuffmanNone - return decoderSuccess - - default: - return decoderErrorUnreachable - } - } -} - -/* Decodes a block length by reading 3..39 bits. */ -func readBlockLength(table []huffmanCode, br *bitReader) uint32 { - var code uint32 - var nbits uint32 - code = readSymbol(table, br) - nbits = kBlockLengthPrefixCode[code].nbits /* nbits == 2..24 */ - return kBlockLengthPrefixCode[code].offset + readBits(br, nbits) -} - -/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then - reading can't be continued with ReadBlockLength. */ -func safeReadBlockLength(s *Reader, result *uint32, table []huffmanCode, br *bitReader) bool { - var index uint32 - if s.substate_read_block_length == stateReadBlockLengthNone { - if !safeReadSymbol(table, br, &index) { - return false - } - } else { - index = s.block_length_index - } - { - var bits uint32 /* nbits == 2..24 */ - var nbits uint32 = kBlockLengthPrefixCode[index].nbits - if !safeReadBits(br, nbits, &bits) { - s.block_length_index = index - s.substate_read_block_length = stateReadBlockLengthSuffix - return false - } - - *result = kBlockLengthPrefixCode[index].offset + bits - s.substate_read_block_length = stateReadBlockLengthNone - return true - } -} - -/* Transform: - 1) initialize list L with values 0, 1,... 255 - 2) For each input element X: - 2.1) let Y = L[X] - 2.2) remove X-th element from L - 2.3) prepend Y to L - 2.4) append Y to output - - In most cases max(Y) <= 7, so most of L remains intact. - To reduce the cost of initialization, we reuse L, remember the upper bound - of Y values, and reinitialize only first elements in L. - - Most of input values are 0 and 1. To reduce number of branches, we replace - inner for loop with do-while. */ -func inverseMoveToFrontTransform(v []byte, v_len uint32, state *Reader) { - var mtf [256]byte - var i int - for i = 1; i < 256; i++ { - mtf[i] = byte(i) - } - var mtf_1 byte - - /* Transform the input. */ - for i = 0; uint32(i) < v_len; i++ { - var index int = int(v[i]) - var value byte = mtf[index] - v[i] = value - mtf_1 = value - for index >= 1 { - index-- - mtf[index+1] = mtf[index] - } - - mtf[0] = mtf_1 - } -} - -/* Decodes a series of Huffman table using ReadHuffmanCode function. */ -func huffmanTreeGroupDecode(group *huffmanTreeGroup, s *Reader) int { - if s.substate_tree_group != stateTreeGroupLoop { - s.next = group.codes - s.htree_index = 0 - s.substate_tree_group = stateTreeGroupLoop - } - - for s.htree_index < int(group.num_htrees) { - var table_size uint32 - var result int = readHuffmanCode(uint32(group.alphabet_size), uint32(group.max_symbol), s.next, &table_size, s) - if result != decoderSuccess { - return result - } - group.htrees[s.htree_index] = s.next - s.next = s.next[table_size:] - s.htree_index++ - } - - s.substate_tree_group = stateTreeGroupNone - return decoderSuccess -} - -/* Decodes a context map. - Decoding is done in 4 phases: - 1) Read auxiliary information (6..16 bits) and allocate memory. - In case of trivial context map, decoding is finished at this phase. - 2) Decode Huffman table using ReadHuffmanCode function. - This table will be used for reading context map items. - 3) Read context map items; "0" values could be run-length encoded. - 4) Optionally, apply InverseMoveToFront transform to the resulting map. */ -func decodeContextMap(context_map_size uint32, num_htrees *uint32, context_map_arg *[]byte, s *Reader) int { - var br *bitReader = &s.br - var result int = decoderSuccess - - switch int(s.substate_context_map) { - case stateContextMapNone: - result = decodeVarLenUint8(s, br, num_htrees) - if result != decoderSuccess { - return result - } - - (*num_htrees)++ - s.context_index = 0 - *context_map_arg = make([]byte, uint(context_map_size)) - if *context_map_arg == nil { - return decoderErrorAllocContextMap - } - - if *num_htrees <= 1 { - for i := 0; i < int(context_map_size); i++ { - (*context_map_arg)[i] = 0 - } - return decoderSuccess - } - - s.substate_context_map = stateContextMapReadPrefix - fallthrough - /* Fall through. */ - case stateContextMapReadPrefix: - { - var bits uint32 - - /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe - to peek 4 bits ahead. */ - if !safeGetBits(br, 5, &bits) { - return decoderNeedsMoreInput - } - - if bits&1 != 0 { /* Use RLE for zeros. */ - s.max_run_length_prefix = (bits >> 1) + 1 - dropBits(br, 5) - } else { - s.max_run_length_prefix = 0 - dropBits(br, 1) - } - - s.substate_context_map = stateContextMapHuffman - } - fallthrough - - /* Fall through. */ - case stateContextMapHuffman: - { - var alphabet_size uint32 = *num_htrees + s.max_run_length_prefix - result = readHuffmanCode(alphabet_size, alphabet_size, s.context_map_table[:], nil, s) - if result != decoderSuccess { - return result - } - s.code = 0xFFFF - s.substate_context_map = stateContextMapDecode - } - fallthrough - - /* Fall through. */ - case stateContextMapDecode: - { - var context_index uint32 = s.context_index - var max_run_length_prefix uint32 = s.max_run_length_prefix - var context_map []byte = *context_map_arg - var code uint32 = s.code - var skip_preamble bool = (code != 0xFFFF) - for context_index < context_map_size || skip_preamble { - if !skip_preamble { - if !safeReadSymbol(s.context_map_table[:], br, &code) { - s.code = 0xFFFF - s.context_index = context_index - return decoderNeedsMoreInput - } - - if code == 0 { - context_map[context_index] = 0 - context_index++ - continue - } - - if code > max_run_length_prefix { - context_map[context_index] = byte(code - max_run_length_prefix) - context_index++ - continue - } - } else { - skip_preamble = false - } - - /* RLE sub-stage. */ - { - var reps uint32 - if !safeReadBits(br, code, &reps) { - s.code = code - s.context_index = context_index - return decoderNeedsMoreInput - } - - reps += 1 << code - if context_index+reps > context_map_size { - return decoderErrorFormatContextMapRepeat - } - - for { - context_map[context_index] = 0 - context_index++ - reps-- - if reps == 0 { - break - } - } - } - } - } - fallthrough - - case stateContextMapTransform: - var bits uint32 - if !safeReadBits(br, 1, &bits) { - s.substate_context_map = stateContextMapTransform - return decoderNeedsMoreInput - } - - if bits != 0 { - inverseMoveToFrontTransform(*context_map_arg, context_map_size, s) - } - - s.substate_context_map = stateContextMapNone - return decoderSuccess - - default: - return decoderErrorUnreachable - } -} - -/* Decodes a command or literal and updates block type ring-buffer. - Reads 3..54 bits. */ -func decodeBlockTypeAndLength(safe int, s *Reader, tree_type int) bool { - var max_block_type uint32 = s.num_block_types[tree_type] - type_tree := s.block_type_trees[tree_type*huffmanMaxSize258:] - len_tree := s.block_len_trees[tree_type*huffmanMaxSize26:] - var br *bitReader = &s.br - var ringbuffer []uint32 = s.block_type_rb[tree_type*2:] - var block_type uint32 - if max_block_type <= 1 { - return false - } - - /* Read 0..15 + 3..39 bits. */ - if safe == 0 { - block_type = readSymbol(type_tree, br) - s.block_length[tree_type] = readBlockLength(len_tree, br) - } else { - var memento bitReaderState - bitReaderSaveState(br, &memento) - if !safeReadSymbol(type_tree, br, &block_type) { - return false - } - if !safeReadBlockLength(s, &s.block_length[tree_type], len_tree, br) { - s.substate_read_block_length = stateReadBlockLengthNone - bitReaderRestoreState(br, &memento) - return false - } - } - - if block_type == 1 { - block_type = ringbuffer[1] + 1 - } else if block_type == 0 { - block_type = ringbuffer[0] - } else { - block_type -= 2 - } - - if block_type >= max_block_type { - block_type -= max_block_type - } - - ringbuffer[0] = ringbuffer[1] - ringbuffer[1] = block_type - return true -} - -func detectTrivialLiteralBlockTypes(s *Reader) { - var i uint - for i = 0; i < 8; i++ { - s.trivial_literal_contexts[i] = 0 - } - for i = 0; uint32(i) < s.num_block_types[0]; i++ { - var offset uint = i << literalContextBits - var error uint = 0 - var sample uint = uint(s.context_map[offset]) - var j uint - for j = 0; j < 1<>5] |= 1 << (i & 31) - } - } -} - -func prepareLiteralDecoding(s *Reader) { - var context_mode byte - var trivial uint - var block_type uint32 = s.block_type_rb[1] - var context_offset uint32 = block_type << literalContextBits - s.context_map_slice = s.context_map[context_offset:] - trivial = uint(s.trivial_literal_contexts[block_type>>5]) - s.trivial_literal_context = int((trivial >> (block_type & 31)) & 1) - s.literal_htree = []huffmanCode(s.literal_hgroup.htrees[s.context_map_slice[0]]) - context_mode = s.context_modes[block_type] & 3 - s.context_lookup = getContextLUT(int(context_mode)) -} - -/* Decodes the block type and updates the state for literal context. - Reads 3..54 bits. */ -func decodeLiteralBlockSwitchInternal(safe int, s *Reader) bool { - if !decodeBlockTypeAndLength(safe, s, 0) { - return false - } - - prepareLiteralDecoding(s) - return true -} - -func decodeLiteralBlockSwitch(s *Reader) { - decodeLiteralBlockSwitchInternal(0, s) -} - -func safeDecodeLiteralBlockSwitch(s *Reader) bool { - return decodeLiteralBlockSwitchInternal(1, s) -} - -/* Block switch for insert/copy length. - Reads 3..54 bits. */ -func decodeCommandBlockSwitchInternal(safe int, s *Reader) bool { - if !decodeBlockTypeAndLength(safe, s, 1) { - return false - } - - s.htree_command = []huffmanCode(s.insert_copy_hgroup.htrees[s.block_type_rb[3]]) - return true -} - -func decodeCommandBlockSwitch(s *Reader) { - decodeCommandBlockSwitchInternal(0, s) -} - -func safeDecodeCommandBlockSwitch(s *Reader) bool { - return decodeCommandBlockSwitchInternal(1, s) -} - -/* Block switch for distance codes. - Reads 3..54 bits. */ -func decodeDistanceBlockSwitchInternal(safe int, s *Reader) bool { - if !decodeBlockTypeAndLength(safe, s, 2) { - return false - } - - s.dist_context_map_slice = s.dist_context_map[s.block_type_rb[5]< s.ringbuffer_size { - pos = uint(s.ringbuffer_size) - } else { - pos = uint(s.pos) - } - var partial_pos_rb uint = (s.rb_roundtrips * uint(s.ringbuffer_size)) + pos - return partial_pos_rb - s.partial_pos_out -} - -/* Dumps output. - Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push - and either ring-buffer is as big as window size, or |force| is true. */ -func writeRingBuffer(s *Reader, available_out *uint, next_out *[]byte, total_out *uint, force bool) int { - start := s.ringbuffer[s.partial_pos_out&uint(s.ringbuffer_mask):] - var to_write uint = unwrittenBytes(s, true) - var num_written uint = *available_out - if num_written > to_write { - num_written = to_write - } - - if s.meta_block_remaining_len < 0 { - return decoderErrorFormatBlockLength1 - } - - if next_out != nil && *next_out == nil { - *next_out = start - } else { - if next_out != nil { - copy(*next_out, start[:num_written]) - *next_out = (*next_out)[num_written:] - } - } - - *available_out -= num_written - s.partial_pos_out += num_written - if total_out != nil { - *total_out = s.partial_pos_out - } - - if num_written < to_write { - if s.ringbuffer_size == 1<= s.ringbuffer_size { - s.pos -= s.ringbuffer_size - s.rb_roundtrips++ - if uint(s.pos) != 0 { - s.should_wrap_ringbuffer = 1 - } else { - s.should_wrap_ringbuffer = 0 - } - } - - return decoderSuccess -} - -func wrapRingBuffer(s *Reader) { - if s.should_wrap_ringbuffer != 0 { - copy(s.ringbuffer, s.ringbuffer_end[:uint(s.pos)]) - s.should_wrap_ringbuffer = 0 - } -} - -/* Allocates ring-buffer. - - s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before - this function is called. - - Last two bytes of ring-buffer are initialized to 0, so context calculation - could be done uniformly for the first two and all other positions. */ -func ensureRingBuffer(s *Reader) bool { - var old_ringbuffer []byte - if s.ringbuffer_size == s.new_ringbuffer_size { - return true - } - spaceNeeded := int(s.new_ringbuffer_size) + int(kRingBufferWriteAheadSlack) - if len(s.ringbuffer) < spaceNeeded { - old_ringbuffer = s.ringbuffer - s.ringbuffer = make([]byte, spaceNeeded) - } - - s.ringbuffer[s.new_ringbuffer_size-2] = 0 - s.ringbuffer[s.new_ringbuffer_size-1] = 0 - - if old_ringbuffer != nil { - copy(s.ringbuffer, old_ringbuffer[:uint(s.pos)]) - } - - s.ringbuffer_size = s.new_ringbuffer_size - s.ringbuffer_mask = s.new_ringbuffer_size - 1 - s.ringbuffer_end = s.ringbuffer[s.ringbuffer_size:] - - return true -} - -func copyUncompressedBlockToOutput(available_out *uint, next_out *[]byte, total_out *uint, s *Reader) int { - /* TODO: avoid allocation for single uncompressed block. */ - if !ensureRingBuffer(s) { - return decoderErrorAllocRingBuffer1 - } - - /* State machine */ - for { - switch s.substate_uncompressed { - case stateUncompressedNone: - { - var nbytes int = int(getRemainingBytes(&s.br)) - if nbytes > s.meta_block_remaining_len { - nbytes = s.meta_block_remaining_len - } - - if s.pos+nbytes > s.ringbuffer_size { - nbytes = s.ringbuffer_size - s.pos - } - - /* Copy remaining bytes from s->br.buf_ to ring-buffer. */ - copyBytes(s.ringbuffer[s.pos:], &s.br, uint(nbytes)) - - s.pos += nbytes - s.meta_block_remaining_len -= nbytes - if s.pos < 1<>1 >= min_size { - new_ringbuffer_size >>= 1 - } - } - - s.new_ringbuffer_size = new_ringbuffer_size -} - -/* Reads 1..256 2-bit context modes. */ -func readContextModes(s *Reader) int { - var br *bitReader = &s.br - var i int = s.loop_counter - - for i < int(s.num_block_types[0]) { - var bits uint32 - if !safeReadBits(br, 2, &bits) { - s.loop_counter = i - return decoderNeedsMoreInput - } - - s.context_modes[i] = byte(bits) - i++ - } - - return decoderSuccess -} - -func takeDistanceFromRingBuffer(s *Reader) { - if s.distance_code == 0 { - s.dist_rb_idx-- - s.distance_code = s.dist_rb[s.dist_rb_idx&3] - - /* Compensate double distance-ring-buffer roll for dictionary items. */ - s.distance_context = 1 - } else { - var distance_code int = s.distance_code << 1 - const kDistanceShortCodeIndexOffset uint32 = 0xAAAFFF1B - const kDistanceShortCodeValueOffset uint32 = 0xFA5FA500 - var v int = (s.dist_rb_idx + int(kDistanceShortCodeIndexOffset>>uint(distance_code))) & 0x3 - /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: - 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */ - - /* kDistanceShortCodeValueOffset has 2-bit values from LSB: - -0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */ - s.distance_code = s.dist_rb[v] - - v = int(kDistanceShortCodeValueOffset>>uint(distance_code)) & 0x3 - if distance_code&0x3 != 0 { - s.distance_code += v - } else { - s.distance_code -= v - if s.distance_code <= 0 { - /* A huge distance will cause a () soon. - This is a little faster than failing here. */ - s.distance_code = 0x7FFFFFFF - } - } - } -} - -func safeReadBitsMaybeZero(br *bitReader, n_bits uint32, val *uint32) bool { - if n_bits != 0 { - return safeReadBits(br, n_bits, val) - } else { - *val = 0 - return true - } -} - -/* Precondition: s->distance_code < 0. */ -func readDistanceInternal(safe int, s *Reader, br *bitReader) bool { - var distval int - var memento bitReaderState - var distance_tree []huffmanCode = []huffmanCode(s.distance_hgroup.htrees[s.dist_htree_index]) - if safe == 0 { - s.distance_code = int(readSymbol(distance_tree, br)) - } else { - var code uint32 - bitReaderSaveState(br, &memento) - if !safeReadSymbol(distance_tree, br, &code) { - return false - } - - s.distance_code = int(code) - } - - /* Convert the distance code to the actual distance by possibly - looking up past distances from the s->ringbuffer. */ - s.distance_context = 0 - - if s.distance_code&^0xF == 0 { - takeDistanceFromRingBuffer(s) - s.block_length[2]-- - return true - } - - distval = s.distance_code - int(s.num_direct_distance_codes) - if distval >= 0 { - var nbits uint32 - var postfix int - var offset int - if safe == 0 && (s.distance_postfix_bits == 0) { - nbits = (uint32(distval) >> 1) + 1 - offset = ((2 + (distval & 1)) << nbits) - 4 - s.distance_code = int(s.num_direct_distance_codes) + offset + int(readBits(br, nbits)) - } else { - /* This branch also works well when s->distance_postfix_bits == 0. */ - var bits uint32 - postfix = distval & s.distance_postfix_mask - distval >>= s.distance_postfix_bits - nbits = (uint32(distval) >> 1) + 1 - if safe != 0 { - if !safeReadBitsMaybeZero(br, nbits, &bits) { - s.distance_code = -1 /* Restore precondition. */ - bitReaderRestoreState(br, &memento) - return false - } - } else { - bits = readBits(br, nbits) - } - - offset = ((2 + (distval & 1)) << nbits) - 4 - s.distance_code = int(s.num_direct_distance_codes) + ((offset + int(bits)) << s.distance_postfix_bits) + postfix - } - } - - s.distance_code = s.distance_code - numDistanceShortCodes + 1 - s.block_length[2]-- - return true -} - -func readDistance(s *Reader, br *bitReader) { - readDistanceInternal(0, s, br) -} - -func safeReadDistance(s *Reader, br *bitReader) bool { - return readDistanceInternal(1, s, br) -} - -func readCommandInternal(safe int, s *Reader, br *bitReader, insert_length *int) bool { - var cmd_code uint32 - var insert_len_extra uint32 = 0 - var copy_length uint32 - var v cmdLutElement - var memento bitReaderState - if safe == 0 { - cmd_code = readSymbol(s.htree_command, br) - } else { - bitReaderSaveState(br, &memento) - if !safeReadSymbol(s.htree_command, br, &cmd_code) { - return false - } - } - - v = kCmdLut[cmd_code] - s.distance_code = int(v.distance_code) - s.distance_context = int(v.context) - s.dist_htree_index = s.dist_context_map_slice[s.distance_context] - *insert_length = int(v.insert_len_offset) - if safe == 0 { - if v.insert_len_extra_bits != 0 { - insert_len_extra = readBits(br, uint32(v.insert_len_extra_bits)) - } - - copy_length = readBits(br, uint32(v.copy_len_extra_bits)) - } else { - if !safeReadBitsMaybeZero(br, uint32(v.insert_len_extra_bits), &insert_len_extra) || !safeReadBitsMaybeZero(br, uint32(v.copy_len_extra_bits), ©_length) { - bitReaderRestoreState(br, &memento) - return false - } - } - - s.copy_length = int(copy_length) + int(v.copy_len_offset) - s.block_length[1]-- - *insert_length += int(insert_len_extra) - return true -} - -func readCommand(s *Reader, br *bitReader, insert_length *int) { - readCommandInternal(0, s, br, insert_length) -} - -func safeReadCommand(s *Reader, br *bitReader, insert_length *int) bool { - return readCommandInternal(1, s, br, insert_length) -} - -func checkInputAmountMaybeSafe(safe int, br *bitReader, num uint) bool { - if safe != 0 { - return true - } - - return checkInputAmount(br, num) -} - -func processCommandsInternal(safe int, s *Reader) int { - var pos int = s.pos - var i int = s.loop_counter - var result int = decoderSuccess - var br *bitReader = &s.br - var hc []huffmanCode - - if !checkInputAmountMaybeSafe(safe, br, 28) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - if safe == 0 { - warmupBitReader(br) - } - - /* Jump into state machine. */ - if s.state == stateCommandBegin { - goto CommandBegin - } else if s.state == stateCommandInner { - goto CommandInner - } else if s.state == stateCommandPostDecodeLiterals { - goto CommandPostDecodeLiterals - } else if s.state == stateCommandPostWrapCopy { - goto CommandPostWrapCopy - } else { - return decoderErrorUnreachable - } - -CommandBegin: - if safe != 0 { - s.state = stateCommandBegin - } - - if !checkInputAmountMaybeSafe(safe, br, 28) { /* 156 bits + 7 bytes */ - s.state = stateCommandBegin - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - if s.block_length[1] == 0 { - if safe != 0 { - if !safeDecodeCommandBlockSwitch(s) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - decodeCommandBlockSwitch(s) - } - - goto CommandBegin - } - - /* Read the insert/copy length in the command. */ - if safe != 0 { - if !safeReadCommand(s, br, &i) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - readCommand(s, br, &i) - } - - if i == 0 { - goto CommandPostDecodeLiterals - } - - s.meta_block_remaining_len -= i - -CommandInner: - if safe != 0 { - s.state = stateCommandInner - } - - /* Read the literals in the command. */ - if s.trivial_literal_context != 0 { - var bits uint32 - var value uint32 - preloadSymbol(safe, s.literal_htree, br, &bits, &value) - for { - if !checkInputAmountMaybeSafe(safe, br, 28) { /* 162 bits + 7 bytes */ - s.state = stateCommandInner - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - if s.block_length[0] == 0 { - if safe != 0 { - if !safeDecodeLiteralBlockSwitch(s) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - decodeLiteralBlockSwitch(s) - } - - preloadSymbol(safe, s.literal_htree, br, &bits, &value) - if s.trivial_literal_context == 0 { - goto CommandInner - } - } - - if safe == 0 { - s.ringbuffer[pos] = byte(readPreloadedSymbol(s.literal_htree, br, &bits, &value)) - } else { - var literal uint32 - if !safeReadSymbol(s.literal_htree, br, &literal) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - s.ringbuffer[pos] = byte(literal) - } - - s.block_length[0]-- - pos++ - if pos == s.ringbuffer_size { - s.state = stateCommandInnerWrite - i-- - goto saveStateAndReturn - } - i-- - if i == 0 { - break - } - } - } else { - var p1 byte = s.ringbuffer[(pos-1)&s.ringbuffer_mask] - var p2 byte = s.ringbuffer[(pos-2)&s.ringbuffer_mask] - for { - var context byte - if !checkInputAmountMaybeSafe(safe, br, 28) { /* 162 bits + 7 bytes */ - s.state = stateCommandInner - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - if s.block_length[0] == 0 { - if safe != 0 { - if !safeDecodeLiteralBlockSwitch(s) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - decodeLiteralBlockSwitch(s) - } - - if s.trivial_literal_context != 0 { - goto CommandInner - } - } - - context = getContext(p1, p2, s.context_lookup) - hc = []huffmanCode(s.literal_hgroup.htrees[s.context_map_slice[context]]) - p2 = p1 - if safe == 0 { - p1 = byte(readSymbol(hc, br)) - } else { - var literal uint32 - if !safeReadSymbol(hc, br, &literal) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - - p1 = byte(literal) - } - - s.ringbuffer[pos] = p1 - s.block_length[0]-- - pos++ - if pos == s.ringbuffer_size { - s.state = stateCommandInnerWrite - i-- - goto saveStateAndReturn - } - i-- - if i == 0 { - break - } - } - } - - if s.meta_block_remaining_len <= 0 { - s.state = stateMetablockDone - goto saveStateAndReturn - } - -CommandPostDecodeLiterals: - if safe != 0 { - s.state = stateCommandPostDecodeLiterals - } - - if s.distance_code >= 0 { - /* Implicit distance case. */ - if s.distance_code != 0 { - s.distance_context = 0 - } else { - s.distance_context = 1 - } - - s.dist_rb_idx-- - s.distance_code = s.dist_rb[s.dist_rb_idx&3] - } else { - /* Read distance code in the command, unless it was implicitly zero. */ - if s.block_length[2] == 0 { - if safe != 0 { - if !safeDecodeDistanceBlockSwitch(s) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - decodeDistanceBlockSwitch(s) - } - } - - if safe != 0 { - if !safeReadDistance(s, br) { - result = decoderNeedsMoreInput - goto saveStateAndReturn - } - } else { - readDistance(s, br) - } - } - - if s.max_distance != s.max_backward_distance { - if pos < s.max_backward_distance { - s.max_distance = pos - } else { - s.max_distance = s.max_backward_distance - } - } - - i = s.copy_length - - /* Apply copy of LZ77 back-reference, or static dictionary reference if - the distance is larger than the max LZ77 distance */ - if s.distance_code > s.max_distance { - /* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC. - With this choice, no signed overflow can occur after decoding - a special distance code (e.g., after adding 3 to the last distance). */ - if s.distance_code > maxAllowedDistance { - return decoderErrorFormatDistance - } - - if i >= minDictionaryWordLength && i <= maxDictionaryWordLength { - var address int = s.distance_code - s.max_distance - 1 - var words *dictionary = s.dictionary - var trans *transforms = s.transforms - var offset int = int(s.dictionary.offsets_by_length[i]) - var shift uint32 = uint32(s.dictionary.size_bits_by_length[i]) - var mask int = int(bitMask(shift)) - var word_idx int = address & mask - var transform_idx int = address >> shift - - /* Compensate double distance-ring-buffer roll. */ - s.dist_rb_idx += s.distance_context - - offset += word_idx * i - if words.data == nil { - return decoderErrorDictionaryNotSet - } - - if transform_idx < int(trans.num_transforms) { - word := words.data[offset:] - var len int = i - if transform_idx == int(trans.cutOffTransforms[0]) { - copy(s.ringbuffer[pos:], word[:uint(len)]) - } else { - len = transformDictionaryWord(s.ringbuffer[pos:], word, int(len), trans, transform_idx) - } - - pos += int(len) - s.meta_block_remaining_len -= int(len) - if pos >= s.ringbuffer_size { - s.state = stateCommandPostWrite1 - goto saveStateAndReturn - } - } else { - return decoderErrorFormatTransform - } - } else { - return decoderErrorFormatDictionary - } - } else { - var src_start int = (pos - s.distance_code) & s.ringbuffer_mask - copy_dst := s.ringbuffer[pos:] - copy_src := s.ringbuffer[src_start:] - var dst_end int = pos + i - var src_end int = src_start + i - - /* Update the recent distances cache. */ - s.dist_rb[s.dist_rb_idx&3] = s.distance_code - - s.dist_rb_idx++ - s.meta_block_remaining_len -= i - - /* There are 32+ bytes of slack in the ring-buffer allocation. - Also, we have 16 short codes, that make these 16 bytes irrelevant - in the ring-buffer. Let's copy over them as a first guess. */ - copy(copy_dst, copy_src[:16]) - - if src_end > pos && dst_end > src_start { - /* Regions intersect. */ - goto CommandPostWrapCopy - } - - if dst_end >= s.ringbuffer_size || src_end >= s.ringbuffer_size { - /* At least one region wraps. */ - goto CommandPostWrapCopy - } - - pos += i - if i > 16 { - if i > 32 { - copy(copy_dst[16:], copy_src[16:][:uint(i-16)]) - } else { - /* This branch covers about 45% cases. - Fixed size short copy allows more compiler optimizations. */ - copy(copy_dst[16:], copy_src[16:][:16]) - } - } - } - - if s.meta_block_remaining_len <= 0 { - /* Next metablock, if any. */ - s.state = stateMetablockDone - - goto saveStateAndReturn - } else { - goto CommandBegin - } -CommandPostWrapCopy: - { - var wrap_guard int = s.ringbuffer_size - pos - for { - i-- - if i < 0 { - break - } - s.ringbuffer[pos] = s.ringbuffer[(pos-s.distance_code)&s.ringbuffer_mask] - pos++ - wrap_guard-- - if wrap_guard == 0 { - s.state = stateCommandPostWrite2 - goto saveStateAndReturn - } - } - } - - if s.meta_block_remaining_len <= 0 { - /* Next metablock, if any. */ - s.state = stateMetablockDone - - goto saveStateAndReturn - } else { - goto CommandBegin - } - -saveStateAndReturn: - s.pos = pos - s.loop_counter = i - return result -} - -func processCommands(s *Reader) int { - return processCommandsInternal(0, s) -} - -func safeProcessCommands(s *Reader) int { - return processCommandsInternal(1, s) -} - -/* Returns the maximum number of distance symbols which can only represent - distances not exceeding BROTLI_MAX_ALLOWED_DISTANCE. */ - -var maxDistanceSymbol_bound = [maxNpostfix + 1]uint32{0, 4, 12, 28} -var maxDistanceSymbol_diff = [maxNpostfix + 1]uint32{73, 126, 228, 424} - -func maxDistanceSymbol(ndirect uint32, npostfix uint32) uint32 { - var postfix uint32 = 1 << npostfix - if ndirect < maxDistanceSymbol_bound[npostfix] { - return ndirect + maxDistanceSymbol_diff[npostfix] + postfix - } else if ndirect > maxDistanceSymbol_bound[npostfix]+postfix { - return ndirect + maxDistanceSymbol_diff[npostfix] - } else { - return maxDistanceSymbol_bound[npostfix] + maxDistanceSymbol_diff[npostfix] + postfix - } -} - -/* Invariant: input stream is never overconsumed: - - invalid input implies that the whole stream is invalid -> any amount of - input could be read and discarded - - when result is "needs more input", then at least one more byte is REQUIRED - to complete decoding; all input data MUST be consumed by decoder, so - client could swap the input buffer - - when result is "needs more output" decoder MUST ensure that it doesn't - hold more than 7 bits in bit reader; this saves client from swapping input - buffer ahead of time - - when result is "success" decoder MUST return all unused data back to input - buffer; this is possible because the invariant is held on enter */ -func decoderDecompressStream(s *Reader, available_in *uint, next_in *[]byte, available_out *uint, next_out *[]byte) int { - var result int = decoderSuccess - var br *bitReader = &s.br - - /* Do not try to process further in a case of unrecoverable error. */ - if int(s.error_code) < 0 { - return decoderResultError - } - - if *available_out != 0 && (next_out == nil || *next_out == nil) { - return saveErrorCode(s, decoderErrorInvalidArguments) - } - - if *available_out == 0 { - next_out = nil - } - if s.buffer_length == 0 { /* Just connect bit reader to input stream. */ - br.input_len = *available_in - br.input = *next_in - br.byte_pos = 0 - } else { - /* At least one byte of input is required. More than one byte of input may - be required to complete the transaction -> reading more data must be - done in a loop -> do it in a main loop. */ - result = decoderNeedsMoreInput - - br.input = s.buffer.u8[:] - br.byte_pos = 0 - } - - /* State machine */ - for { - if result != decoderSuccess { - /* Error, needs more input/output. */ - if result == decoderNeedsMoreInput { - if s.ringbuffer != nil { /* Pro-actively push output. */ - var intermediate_result int = writeRingBuffer(s, available_out, next_out, nil, true) - - /* WriteRingBuffer checks s->meta_block_remaining_len validity. */ - if int(intermediate_result) < 0 { - result = intermediate_result - break - } - } - - if s.buffer_length != 0 { /* Used with internal buffer. */ - if br.byte_pos == br.input_len { - /* Successfully finished read transaction. - Accumulator contains less than 8 bits, because internal buffer - is expanded byte-by-byte until it is enough to complete read. */ - s.buffer_length = 0 - - /* Switch to input stream and restart. */ - result = decoderSuccess - - br.input_len = *available_in - br.input = *next_in - br.byte_pos = 0 - continue - } else if *available_in != 0 { - /* Not enough data in buffer, but can take one more byte from - input stream. */ - result = decoderSuccess - - s.buffer.u8[s.buffer_length] = (*next_in)[0] - s.buffer_length++ - br.input_len = uint(s.buffer_length) - *next_in = (*next_in)[1:] - (*available_in)-- - - /* Retry with more data in buffer. */ - continue - } - - /* Can't finish reading and no more input. */ - break - /* Input stream doesn't contain enough input. */ - } else { - /* Copy tail to internal buffer and return. */ - *next_in = br.input[br.byte_pos:] - - *available_in = br.input_len - br.byte_pos - for *available_in != 0 { - s.buffer.u8[s.buffer_length] = (*next_in)[0] - s.buffer_length++ - *next_in = (*next_in)[1:] - (*available_in)-- - } - - break - } - } - - /* Unreachable. */ - - /* Fail or needs more output. */ - if s.buffer_length != 0 { - /* Just consumed the buffered input and produced some output. Otherwise - it would result in "needs more input". Reset internal buffer. */ - s.buffer_length = 0 - } else { - /* Using input stream in last iteration. When decoder switches to input - stream it has less than 8 bits in accumulator, so it is safe to - return unused accumulator bits there. */ - bitReaderUnload(br) - - *available_in = br.input_len - br.byte_pos - *next_in = br.input[br.byte_pos:] - } - - break - } - - switch s.state { - /* Prepare to the first read. */ - case stateUninited: - if !warmupBitReader(br) { - result = decoderNeedsMoreInput - break - } - - /* Decode window size. */ - result = decodeWindowBits(s, br) /* Reads 1..8 bits. */ - if result != decoderSuccess { - break - } - - if s.large_window { - s.state = stateLargeWindowBits - break - } - - s.state = stateInitialize - - case stateLargeWindowBits: - if !safeReadBits(br, 6, &s.window_bits) { - result = decoderNeedsMoreInput - break - } - - if s.window_bits < largeMinWbits || s.window_bits > largeMaxWbits { - result = decoderErrorFormatWindowBits - break - } - - s.state = stateInitialize - fallthrough - - /* Maximum distance, see section 9.1. of the spec. */ - /* Fall through. */ - case stateInitialize: - s.max_backward_distance = (1 << s.window_bits) - windowGap - - if s.block_type_trees == nil { - /* Allocate memory for both block_type_trees and block_len_trees. */ - s.block_type_trees = make([]huffmanCode, (3 * (huffmanMaxSize258 + huffmanMaxSize26))) - } - - s.block_len_trees = s.block_type_trees[3*huffmanMaxSize258:] - - s.state = stateMetablockBegin - fallthrough - - /* Fall through. */ - case stateMetablockBegin: - decoderStateMetablockBegin(s) - - s.state = stateMetablockHeader - fallthrough - - /* Fall through. */ - case stateMetablockHeader: - result = decodeMetaBlockLength(s, br) - /* Reads 2 - 31 bits. */ - if result != decoderSuccess { - break - } - - if s.is_metadata != 0 || s.is_uncompressed != 0 { - if !bitReaderJumpToByteBoundary(br) { - result = decoderErrorFormatPadding1 - break - } - } - - if s.is_metadata != 0 { - s.state = stateMetadata - break - } - - if s.meta_block_remaining_len == 0 { - s.state = stateMetablockDone - break - } - - calculateRingBufferSize(s) - if s.is_uncompressed != 0 { - s.state = stateUncompressed - break - } - - s.loop_counter = 0 - s.state = stateHuffmanCode0 - - case stateUncompressed: - result = copyUncompressedBlockToOutput(available_out, next_out, nil, s) - if result == decoderSuccess { - s.state = stateMetablockDone - } - - case stateMetadata: - for ; s.meta_block_remaining_len > 0; s.meta_block_remaining_len-- { - var bits uint32 - - /* Read one byte and ignore it. */ - if !safeReadBits(br, 8, &bits) { - result = decoderNeedsMoreInput - break - } - } - - if result == decoderSuccess { - s.state = stateMetablockDone - } - - case stateHuffmanCode0: - if s.loop_counter >= 3 { - s.state = stateMetablockHeader2 - break - } - - /* Reads 1..11 bits. */ - result = decodeVarLenUint8(s, br, &s.num_block_types[s.loop_counter]) - - if result != decoderSuccess { - break - } - - s.num_block_types[s.loop_counter]++ - if s.num_block_types[s.loop_counter] < 2 { - s.loop_counter++ - break - } - - s.state = stateHuffmanCode1 - fallthrough - - case stateHuffmanCode1: - { - var alphabet_size uint32 = s.num_block_types[s.loop_counter] + 2 - var tree_offset int = s.loop_counter * huffmanMaxSize258 - result = readHuffmanCode(alphabet_size, alphabet_size, s.block_type_trees[tree_offset:], nil, s) - if result != decoderSuccess { - break - } - s.state = stateHuffmanCode2 - } - fallthrough - - case stateHuffmanCode2: - { - var alphabet_size uint32 = numBlockLenSymbols - var tree_offset int = s.loop_counter * huffmanMaxSize26 - result = readHuffmanCode(alphabet_size, alphabet_size, s.block_len_trees[tree_offset:], nil, s) - if result != decoderSuccess { - break - } - s.state = stateHuffmanCode3 - } - fallthrough - - case stateHuffmanCode3: - var tree_offset int = s.loop_counter * huffmanMaxSize26 - if !safeReadBlockLength(s, &s.block_length[s.loop_counter], s.block_len_trees[tree_offset:], br) { - result = decoderNeedsMoreInput - break - } - - s.loop_counter++ - s.state = stateHuffmanCode0 - - case stateMetablockHeader2: - { - var bits uint32 - if !safeReadBits(br, 6, &bits) { - result = decoderNeedsMoreInput - break - } - - s.distance_postfix_bits = bits & bitMask(2) - bits >>= 2 - s.num_direct_distance_codes = numDistanceShortCodes + (bits << s.distance_postfix_bits) - s.distance_postfix_mask = int(bitMask(s.distance_postfix_bits)) - s.context_modes = make([]byte, uint(s.num_block_types[0])) - if s.context_modes == nil { - result = decoderErrorAllocContextModes - break - } - - s.loop_counter = 0 - s.state = stateContextModes - } - fallthrough - - case stateContextModes: - result = readContextModes(s) - - if result != decoderSuccess { - break - } - - s.state = stateContextMap1 - fallthrough - - case stateContextMap1: - result = decodeContextMap(s.num_block_types[0]<= 3 { - prepareLiteralDecoding(s) - s.dist_context_map_slice = s.dist_context_map - s.htree_command = []huffmanCode(s.insert_copy_hgroup.htrees[0]) - if !ensureRingBuffer(s) { - result = decoderErrorAllocRingBuffer2 - break - } - - s.state = stateCommandBegin - } - - case stateCommandBegin, stateCommandInner, stateCommandPostDecodeLiterals, stateCommandPostWrapCopy: - result = processCommands(s) - - if result == decoderNeedsMoreInput { - result = safeProcessCommands(s) - } - - case stateCommandInnerWrite, stateCommandPostWrite1, stateCommandPostWrite2: - result = writeRingBuffer(s, available_out, next_out, nil, false) - - if result != decoderSuccess { - break - } - - wrapRingBuffer(s) - if s.ringbuffer_size == 1<= uint64(block_size) { - return 0 - } - return block_size - uint(delta) -} - -/* Wraps 64-bit input position to 32-bit ring-buffer position preserving - "not-a-first-lap" feature. */ -func wrapPosition(position uint64) uint32 { - var result uint32 = uint32(position) - var gb uint64 = position >> 30 - if gb > 2 { - /* Wrap every 2GiB; The first 3GB are continuous. */ - result = result&((1<<30)-1) | (uint32((gb-1)&1)+1)<<30 - } - - return result -} - -func (s *Writer) getStorage(size int) []byte { - if len(s.storage) < size { - s.storage = make([]byte, size) - } - - return s.storage -} - -func hashTableSize(max_table_size uint, input_size uint) uint { - var htsize uint = 256 - for htsize < max_table_size && htsize < input_size { - htsize <<= 1 - } - - return htsize -} - -func getHashTable(s *Writer, quality int, input_size uint, table_size *uint) []int { - var max_table_size uint = maxHashTableSize(quality) - var htsize uint = hashTableSize(max_table_size, input_size) - /* Use smaller hash table when input.size() is smaller, since we - fill the table, incurring O(hash table size) overhead for - compression, and if the input is short, we won't need that - many hash table entries anyway. */ - - var table []int - assert(max_table_size >= 256) - if quality == fastOnePassCompressionQuality { - /* Only odd shifts are supported by fast-one-pass. */ - if htsize&0xAAAAA == 0 { - htsize <<= 1 - } - } - - if htsize <= uint(len(s.small_table_)) { - table = s.small_table_[:] - } else { - if htsize > s.large_table_size_ { - s.large_table_size_ = htsize - s.large_table_ = nil - s.large_table_ = make([]int, htsize) - } - - table = s.large_table_ - } - - *table_size = htsize - for i := 0; i < int(htsize); i++ { - table[i] = 0 - } - return table -} - -func encodeWindowBits(lgwin int, large_window bool, last_bytes *uint16, last_bytes_bits *byte) { - if large_window { - *last_bytes = uint16((lgwin&0x3F)<<8 | 0x11) - *last_bytes_bits = 14 - } else { - if lgwin == 16 { - *last_bytes = 0 - *last_bytes_bits = 1 - } else if lgwin == 17 { - *last_bytes = 1 - *last_bytes_bits = 7 - } else if lgwin > 17 { - *last_bytes = uint16((lgwin-17)<<1 | 0x01) - *last_bytes_bits = 4 - } else { - *last_bytes = uint16((lgwin-8)<<4 | 0x01) - *last_bytes_bits = 7 - } - } -} - -/* Decide about the context map based on the ability of the prediction - ability of the previous byte UTF8-prefix on the next byte. The - prediction ability is calculated as Shannon entropy. Here we need - Shannon entropy instead of 'BitsEntropy' since the prefix will be - encoded with the remaining 6 bits of the following byte, and - BitsEntropy will assume that symbol to be stored alone using Huffman - coding. */ - -var kStaticContextMapContinuation = [64]uint32{ - 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} -var kStaticContextMapSimpleUTF8 = [64]uint32{ - 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -} - -func chooseContextMap(quality int, bigram_histo []uint32, num_literal_contexts *uint, literal_context_map *[]uint32) { - var monogram_histo = [3]uint32{0} - var two_prefix_histo = [6]uint32{0} - var total uint - var i uint - var dummy uint - var entropy [4]float64 - for i = 0; i < 9; i++ { - monogram_histo[i%3] += bigram_histo[i] - two_prefix_histo[i%6] += bigram_histo[i] - } - - entropy[1] = shannonEntropy(monogram_histo[:], 3, &dummy) - entropy[2] = (shannonEntropy(two_prefix_histo[:], 3, &dummy) + shannonEntropy(two_prefix_histo[3:], 3, &dummy)) - entropy[3] = 0 - for i = 0; i < 3; i++ { - entropy[3] += shannonEntropy(bigram_histo[3*i:], 3, &dummy) - } - - total = uint(monogram_histo[0] + monogram_histo[1] + monogram_histo[2]) - assert(total != 0) - entropy[0] = 1.0 / float64(total) - entropy[1] *= entropy[0] - entropy[2] *= entropy[0] - entropy[3] *= entropy[0] - - if quality < minQualityForHqContextModeling { - /* 3 context models is a bit slower, don't use it at lower qualities. */ - entropy[3] = entropy[1] * 10 - } - - /* If expected savings by symbol are less than 0.2 bits, skip the - context modeling -- in exchange for faster decoding speed. */ - if entropy[1]-entropy[2] < 0.2 && entropy[1]-entropy[3] < 0.2 { - *num_literal_contexts = 1 - } else if entropy[2]-entropy[3] < 0.02 { - *num_literal_contexts = 2 - *literal_context_map = kStaticContextMapSimpleUTF8[:] - } else { - *num_literal_contexts = 3 - *literal_context_map = kStaticContextMapContinuation[:] - } -} - -/* Decide if we want to use a more complex static context map containing 13 - context values, based on the entropy reduction of histograms over the - first 5 bits of literals. */ - -var kStaticContextMapComplexUTF8 = [64]uint32{ - 11, 11, 12, 12, /* 0 special */ - 0, 0, 0, 0, /* 4 lf */ - 1, 1, 9, 9, /* 8 space */ - 2, 2, 2, 2, /* !, first after space/lf and after something else. */ - 1, 1, 1, 1, /* " */ - 8, 3, 3, 3, /* % */ - 1, 1, 1, 1, /* ({[ */ - 2, 2, 2, 2, /* }]) */ - 8, 4, 4, 4, /* :; */ - 8, 7, 4, 4, /* . */ - 8, 0, 0, 0, /* > */ - 3, 3, 3, 3, /* [0..9] */ - 5, 5, 10, 5, /* [A-Z] */ - 5, 5, 10, 5, - 6, 6, 6, 6, /* [a-z] */ - 6, 6, 6, 6, -} - -func shouldUseComplexStaticContextMap(input []byte, start_pos uint, length uint, mask uint, quality int, size_hint uint, num_literal_contexts *uint, literal_context_map *[]uint32) bool { - /* Try the more complex static context map only for long data. */ - if size_hint < 1<<20 { - return false - } else { - var end_pos uint = start_pos + length - var combined_histo = [32]uint32{0} - var context_histo = [13][32]uint32{[32]uint32{0}} - var total uint32 = 0 - var entropy [3]float64 - var dummy uint - var i uint - var utf8_lut contextLUT = getContextLUT(contextUTF8) - /* To make entropy calculations faster and to fit on the stack, we collect - histograms over the 5 most significant bits of literals. One histogram - without context and 13 additional histograms for each context value. */ - for ; start_pos+64 <= end_pos; start_pos += 4096 { - var stride_end_pos uint = start_pos + 64 - var prev2 byte = input[start_pos&mask] - var prev1 byte = input[(start_pos+1)&mask] - var pos uint - - /* To make the analysis of the data faster we only examine 64 byte long - strides at every 4kB intervals. */ - for pos = start_pos + 2; pos < stride_end_pos; pos++ { - var literal byte = input[pos&mask] - var context byte = byte(kStaticContextMapComplexUTF8[getContext(prev1, prev2, utf8_lut)]) - total++ - combined_histo[literal>>3]++ - context_histo[context][literal>>3]++ - prev2 = prev1 - prev1 = literal - } - } - - entropy[1] = shannonEntropy(combined_histo[:], 32, &dummy) - entropy[2] = 0 - for i = 0; i < 13; i++ { - entropy[2] += shannonEntropy(context_histo[i][0:], 32, &dummy) - } - - entropy[0] = 1.0 / float64(total) - entropy[1] *= entropy[0] - entropy[2] *= entropy[0] - - /* The triggering heuristics below were tuned by compressing the individual - files of the silesia corpus. If we skip this kind of context modeling - for not very well compressible input (i.e. entropy using context modeling - is 60% of maximal entropy) or if expected savings by symbol are less - than 0.2 bits, then in every case when it triggers, the final compression - ratio is improved. Note however that this heuristics might be too strict - for some cases and could be tuned further. */ - if entropy[2] > 3.0 || entropy[1]-entropy[2] < 0.2 { - return false - } else { - *num_literal_contexts = 13 - *literal_context_map = kStaticContextMapComplexUTF8[:] - return true - } - } -} - -func decideOverLiteralContextModeling(input []byte, start_pos uint, length uint, mask uint, quality int, size_hint uint, num_literal_contexts *uint, literal_context_map *[]uint32) { - if quality < minQualityForContextModeling || length < 64 { - return - } else if shouldUseComplexStaticContextMap(input, start_pos, length, mask, quality, size_hint, num_literal_contexts, literal_context_map) { - } else /* Context map was already set, nothing else to do. */ - { - var end_pos uint = start_pos + length - /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of - UTF8 data faster we only examine 64 byte long strides at every 4kB - intervals. */ - - var bigram_prefix_histo = [9]uint32{0} - for ; start_pos+64 <= end_pos; start_pos += 4096 { - var lut = [4]int{0, 0, 1, 2} - var stride_end_pos uint = start_pos + 64 - var prev int = lut[input[start_pos&mask]>>6] * 3 - var pos uint - for pos = start_pos + 1; pos < stride_end_pos; pos++ { - var literal byte = input[pos&mask] - bigram_prefix_histo[prev+lut[literal>>6]]++ - prev = lut[literal>>6] * 3 - } - } - - chooseContextMap(quality, bigram_prefix_histo[0:], num_literal_contexts, literal_context_map) - } -} - -func shouldCompress_encode(data []byte, mask uint, last_flush_pos uint64, bytes uint, num_literals uint, num_commands uint) bool { - /* TODO: find more precise minimal block overhead. */ - if bytes <= 2 { - return false - } - if num_commands < (bytes>>8)+2 { - if float64(num_literals) > 0.99*float64(bytes) { - var literal_histo = [256]uint32{0} - const kSampleRate uint32 = 13 - const kMinEntropy float64 = 7.92 - var bit_cost_threshold float64 = float64(bytes) * kMinEntropy / float64(kSampleRate) - var t uint = uint((uint32(bytes) + kSampleRate - 1) / kSampleRate) - var pos uint32 = uint32(last_flush_pos) - var i uint - for i = 0; i < t; i++ { - literal_histo[data[pos&uint32(mask)]]++ - pos += kSampleRate - } - - if bitsEntropy(literal_histo[:], 256) > bit_cost_threshold { - return false - } - } - } - - return true -} - -/* Chooses the literal context mode for a metablock */ -func chooseContextMode(params *encoderParams, data []byte, pos uint, mask uint, length uint) int { - /* We only do the computation for the option of something else than - CONTEXT_UTF8 for the highest qualities */ - if params.quality >= minQualityForHqBlockSplitting && !isMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio) { - return contextSigned - } - - return contextUTF8 -} - -func writeMetaBlockInternal(data []byte, mask uint, last_flush_pos uint64, bytes uint, is_last bool, literal_context_mode int, params *encoderParams, prev_byte byte, prev_byte2 byte, num_literals uint, commands []command, saved_dist_cache []int, dist_cache []int, storage_ix *uint, storage []byte) { - var wrapped_last_flush_pos uint32 = wrapPosition(last_flush_pos) - var last_bytes uint16 - var last_bytes_bits byte - var literal_context_lut contextLUT = getContextLUT(literal_context_mode) - var block_params encoderParams = *params - - if bytes == 0 { - /* Write the ISLAST and ISEMPTY bits. */ - writeBits(2, 3, storage_ix, storage) - - *storage_ix = (*storage_ix + 7) &^ 7 - return - } - - if !shouldCompress_encode(data, mask, last_flush_pos, bytes, num_literals, uint(len(commands))) { - /* Restore the distance cache, as its last update by - CreateBackwardReferences is now unused. */ - copy(dist_cache, saved_dist_cache[:4]) - - storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, storage_ix, storage) - return - } - - assert(*storage_ix <= 14) - last_bytes = uint16(storage[1])<<8 | uint16(storage[0]) - last_bytes_bits = byte(*storage_ix) - if params.quality <= maxQualityForStaticEntropyCodes { - storeMetaBlockFast(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, storage_ix, storage) - } else if params.quality < minQualityForBlockSplit { - storeMetaBlockTrivial(data, uint(wrapped_last_flush_pos), bytes, mask, is_last, params, commands, storage_ix, storage) - } else { - mb := getMetaBlockSplit() - if params.quality < minQualityForHqBlockSplitting { - var num_literal_contexts uint = 1 - var literal_context_map []uint32 = nil - if !params.disable_literal_context_modeling { - decideOverLiteralContextModeling(data, uint(wrapped_last_flush_pos), bytes, mask, params.quality, params.size_hint, &num_literal_contexts, &literal_context_map) - } - - buildMetaBlockGreedy(data, uint(wrapped_last_flush_pos), mask, prev_byte, prev_byte2, literal_context_lut, num_literal_contexts, literal_context_map, commands, mb) - } else { - buildMetaBlock(data, uint(wrapped_last_flush_pos), mask, &block_params, prev_byte, prev_byte2, commands, literal_context_mode, mb) - } - - if params.quality >= minQualityForOptimizeHistograms { - /* The number of distance symbols effectively used for distance - histograms. It might be less than distance alphabet size - for "Large Window Brotli" (32-bit). */ - var num_effective_dist_codes uint32 = block_params.dist.alphabet_size - if num_effective_dist_codes > numHistogramDistanceSymbols { - num_effective_dist_codes = numHistogramDistanceSymbols - } - - optimizeHistograms(num_effective_dist_codes, mb) - } - - storeMetaBlock(data, uint(wrapped_last_flush_pos), bytes, mask, prev_byte, prev_byte2, is_last, &block_params, literal_context_mode, commands, mb, storage_ix, storage) - freeMetaBlockSplit(mb) - } - - if bytes+4 < *storage_ix>>3 { - /* Restore the distance cache and last byte. */ - copy(dist_cache, saved_dist_cache[:4]) - - storage[0] = byte(last_bytes) - storage[1] = byte(last_bytes >> 8) - *storage_ix = uint(last_bytes_bits) - storeUncompressedMetaBlock(is_last, data, uint(wrapped_last_flush_pos), mask, bytes, storage_ix, storage) - } -} - -func chooseDistanceParams(params *encoderParams) { - var distance_postfix_bits uint32 = 0 - var num_direct_distance_codes uint32 = 0 - - if params.quality >= minQualityForNonzeroDistanceParams { - var ndirect_msb uint32 - if params.mode == modeFont { - distance_postfix_bits = 1 - num_direct_distance_codes = 12 - } else { - distance_postfix_bits = params.dist.distance_postfix_bits - num_direct_distance_codes = params.dist.num_direct_distance_codes - } - - ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F - if distance_postfix_bits > maxNpostfix || num_direct_distance_codes > maxNdirect || ndirect_msb<>25)), (last_command.dist_prefix_&0x3FF == 0), &last_command.cmd_prefix_) - } -} - -/* - Processes the accumulated input data and writes - the new output meta-block to s.dest, if one has been - created (otherwise the processed input data is buffered internally). - If |is_last| or |force_flush| is true, an output meta-block is - always created. However, until |is_last| is true encoder may retain up - to 7 bits of the last byte of output. To force encoder to dump the remaining - bits use WriteMetadata() to append an empty meta-data block. - Returns false if the size of the input data is larger than - input_block_size(). -*/ -func encodeData(s *Writer, is_last bool, force_flush bool) bool { - var delta uint64 = unprocessedInputSize(s) - var bytes uint32 = uint32(delta) - var wrapped_last_processed_pos uint32 = wrapPosition(s.last_processed_pos_) - var data []byte - var mask uint32 - var literal_context_mode int - - data = s.ringbuffer_.buffer_ - mask = s.ringbuffer_.mask_ - - /* Adding more blocks after "last" block is forbidden. */ - if s.is_last_block_emitted_ { - return false - } - if is_last { - s.is_last_block_emitted_ = true - } - - if delta > uint64(inputBlockSize(s)) { - return false - } - - if s.params.quality == fastTwoPassCompressionQuality { - if s.command_buf_ == nil || cap(s.command_buf_) < int(kCompressFragmentTwoPassBlockSize) { - s.command_buf_ = make([]uint32, kCompressFragmentTwoPassBlockSize) - s.literal_buf_ = make([]byte, kCompressFragmentTwoPassBlockSize) - } else { - s.command_buf_ = s.command_buf_[:kCompressFragmentTwoPassBlockSize] - s.literal_buf_ = s.literal_buf_[:kCompressFragmentTwoPassBlockSize] - } - } - - if s.params.quality == fastOnePassCompressionQuality || s.params.quality == fastTwoPassCompressionQuality { - var storage []byte - var storage_ix uint = uint(s.last_bytes_bits_) - var table_size uint - var table []int - - if delta == 0 && !is_last { - /* We have no new input data and we don't have to finish the stream, so - nothing to do. */ - return true - } - - storage = s.getStorage(int(2*bytes + 503)) - storage[0] = byte(s.last_bytes_) - storage[1] = byte(s.last_bytes_ >> 8) - table = getHashTable(s, s.params.quality, uint(bytes), &table_size) - if s.params.quality == fastOnePassCompressionQuality { - compressFragmentFast(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &storage_ix, storage) - } else { - compressFragmentTwoPass(data[wrapped_last_processed_pos&mask:], uint(bytes), is_last, s.command_buf_, s.literal_buf_, table, table_size, &storage_ix, storage) - } - - s.last_bytes_ = uint16(storage[storage_ix>>3]) - s.last_bytes_bits_ = byte(storage_ix & 7) - updateLastProcessedPos(s) - s.writeOutput(storage[:storage_ix>>3]) - return true - } - { - /* Theoretical max number of commands is 1 per 2 bytes. */ - newsize := len(s.commands) + int(bytes)/2 + 1 - if newsize > cap(s.commands) { - /* Reserve a bit more memory to allow merging with a next block - without reallocation: that would impact speed. */ - newsize += int(bytes/4) + 16 - - new_commands := make([]command, len(s.commands), newsize) - if s.commands != nil { - copy(new_commands, s.commands) - } - - s.commands = new_commands - } - } - - initOrStitchToPreviousBlock(&s.hasher_, data, uint(mask), &s.params, uint(wrapped_last_processed_pos), uint(bytes), is_last) - - literal_context_mode = chooseContextMode(&s.params, data, uint(wrapPosition(s.last_flush_pos_)), uint(mask), uint(s.input_pos_-s.last_flush_pos_)) - - if len(s.commands) != 0 && s.last_insert_len_ == 0 { - extendLastCommand(s, &bytes, &wrapped_last_processed_pos) - } - - if s.params.quality == zopflificationQuality { - assert(s.params.hasher.type_ == 10) - createZopfliBackwardReferences(uint(bytes), uint(wrapped_last_processed_pos), data, uint(mask), &s.params, s.hasher_.(*h10), s.dist_cache_[:], &s.last_insert_len_, &s.commands, &s.num_literals_) - } else if s.params.quality == hqZopflificationQuality { - assert(s.params.hasher.type_ == 10) - createHqZopfliBackwardReferences(uint(bytes), uint(wrapped_last_processed_pos), data, uint(mask), &s.params, s.hasher_, s.dist_cache_[:], &s.last_insert_len_, &s.commands, &s.num_literals_) - } else { - createBackwardReferences(uint(bytes), uint(wrapped_last_processed_pos), data, uint(mask), &s.params, s.hasher_, s.dist_cache_[:], &s.last_insert_len_, &s.commands, &s.num_literals_) - } - { - var max_length uint = maxMetablockSize(&s.params) - var max_literals uint = max_length / 8 - max_commands := int(max_length / 8) - var processed_bytes uint = uint(s.input_pos_ - s.last_flush_pos_) - var next_input_fits_metablock bool = (processed_bytes+inputBlockSize(s) <= max_length) - var should_flush bool = (s.params.quality < minQualityForBlockSplit && s.num_literals_+uint(len(s.commands)) >= maxNumDelayedSymbols) - /* If maximal possible additional block doesn't fit metablock, flush now. */ - /* TODO: Postpone decision until next block arrives? */ - - /* If block splitting is not used, then flush as soon as there is some - amount of commands / literals produced. */ - if !is_last && !force_flush && !should_flush && next_input_fits_metablock && s.num_literals_ < max_literals && len(s.commands) < max_commands { - /* Merge with next input block. Everything will happen later. */ - if updateLastProcessedPos(s) { - hasherReset(s.hasher_) - } - - return true - } - } - - /* Create the last insert-only command. */ - if s.last_insert_len_ > 0 { - s.commands = append(s.commands, makeInsertCommand(s.last_insert_len_)) - s.num_literals_ += s.last_insert_len_ - s.last_insert_len_ = 0 - } - - if !is_last && s.input_pos_ == s.last_flush_pos_ { - /* We have no new input data and we don't have to finish the stream, so - nothing to do. */ - return true - } - - assert(s.input_pos_ >= s.last_flush_pos_) - assert(s.input_pos_ > s.last_flush_pos_ || is_last) - assert(s.input_pos_-s.last_flush_pos_ <= 1<<24) - { - var metablock_size uint32 = uint32(s.input_pos_ - s.last_flush_pos_) - var storage []byte = s.getStorage(int(2*metablock_size + 503)) - var storage_ix uint = uint(s.last_bytes_bits_) - storage[0] = byte(s.last_bytes_) - storage[1] = byte(s.last_bytes_ >> 8) - writeMetaBlockInternal(data, uint(mask), s.last_flush_pos_, uint(metablock_size), is_last, literal_context_mode, &s.params, s.prev_byte_, s.prev_byte2_, s.num_literals_, s.commands, s.saved_dist_cache_[:], s.dist_cache_[:], &storage_ix, storage) - s.last_bytes_ = uint16(storage[storage_ix>>3]) - s.last_bytes_bits_ = byte(storage_ix & 7) - s.last_flush_pos_ = s.input_pos_ - if updateLastProcessedPos(s) { - hasherReset(s.hasher_) - } - - if s.last_flush_pos_ > 0 { - s.prev_byte_ = data[(uint32(s.last_flush_pos_)-1)&mask] - } - - if s.last_flush_pos_ > 1 { - s.prev_byte2_ = data[uint32(s.last_flush_pos_-2)&mask] - } - - s.commands = s.commands[:0] - s.num_literals_ = 0 - - /* Save the state of the distance cache in case we need to restore it for - emitting an uncompressed block. */ - copy(s.saved_dist_cache_[:], s.dist_cache_[:]) - - s.writeOutput(storage[:storage_ix>>3]) - return true - } -} - -/* Dumps remaining output bits and metadata header to |header|. - Returns number of produced bytes. - REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long. - REQUIRED: |block_size| <= (1 << 24). */ -func writeMetadataHeader(s *Writer, block_size uint, header []byte) uint { - storage_ix := uint(s.last_bytes_bits_) - header[0] = byte(s.last_bytes_) - header[1] = byte(s.last_bytes_ >> 8) - s.last_bytes_ = 0 - s.last_bytes_bits_ = 0 - - writeBits(1, 0, &storage_ix, header) - writeBits(2, 3, &storage_ix, header) - writeBits(1, 0, &storage_ix, header) - if block_size == 0 { - writeBits(2, 0, &storage_ix, header) - } else { - var nbits uint32 - if block_size == 1 { - nbits = 0 - } else { - nbits = log2FloorNonZero(uint(uint32(block_size)-1)) + 1 - } - var nbytes uint32 = (nbits + 7) / 8 - writeBits(2, uint64(nbytes), &storage_ix, header) - writeBits(uint(8*nbytes), uint64(block_size)-1, &storage_ix, header) - } - - return (storage_ix + 7) >> 3 -} - -func injectBytePaddingBlock(s *Writer) { - var seal uint32 = uint32(s.last_bytes_) - var seal_bits uint = uint(s.last_bytes_bits_) - s.last_bytes_ = 0 - s.last_bytes_bits_ = 0 - - /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */ - seal |= 0x6 << seal_bits - - seal_bits += 6 - - destination := s.tiny_buf_.u8[:] - - destination[0] = byte(seal) - if seal_bits > 8 { - destination[1] = byte(seal >> 8) - } - if seal_bits > 16 { - destination[2] = byte(seal >> 16) - } - s.writeOutput(destination[:(seal_bits+7)>>3]) -} - -func checkFlushComplete(s *Writer) { - if s.stream_state_ == streamFlushRequested && s.err == nil { - s.stream_state_ = streamProcessing - } -} - -func encoderCompressStreamFast(s *Writer, op int, available_in *uint, next_in *[]byte) bool { - var block_size_limit uint = uint(1) << s.params.lgwin - var buf_size uint = brotli_min_size_t(kCompressFragmentTwoPassBlockSize, brotli_min_size_t(*available_in, block_size_limit)) - var command_buf []uint32 = nil - var literal_buf []byte = nil - if s.params.quality != fastOnePassCompressionQuality && s.params.quality != fastTwoPassCompressionQuality { - return false - } - - if s.params.quality == fastTwoPassCompressionQuality { - if s.command_buf_ == nil || cap(s.command_buf_) < int(buf_size) { - s.command_buf_ = make([]uint32, buf_size) - s.literal_buf_ = make([]byte, buf_size) - } else { - s.command_buf_ = s.command_buf_[:buf_size] - s.literal_buf_ = s.literal_buf_[:buf_size] - } - - command_buf = s.command_buf_ - literal_buf = s.literal_buf_ - } - - for { - if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 { - injectBytePaddingBlock(s) - continue - } - - /* Compress block only when stream is not - finished, there is no pending flush request, and there is either - additional input or pending operation. */ - if s.stream_state_ == streamProcessing && (*available_in != 0 || op != int(operationProcess)) { - var block_size uint = brotli_min_size_t(block_size_limit, *available_in) - var is_last bool = (*available_in == block_size) && (op == int(operationFinish)) - var force_flush bool = (*available_in == block_size) && (op == int(operationFlush)) - var max_out_size uint = 2*block_size + 503 - var storage []byte = nil - var storage_ix uint = uint(s.last_bytes_bits_) - var table_size uint - var table []int - - if force_flush && block_size == 0 { - s.stream_state_ = streamFlushRequested - continue - } - - storage = s.getStorage(int(max_out_size)) - - storage[0] = byte(s.last_bytes_) - storage[1] = byte(s.last_bytes_ >> 8) - table = getHashTable(s, s.params.quality, block_size, &table_size) - - if s.params.quality == fastOnePassCompressionQuality { - compressFragmentFast(*next_in, block_size, is_last, table, table_size, s.cmd_depths_[:], s.cmd_bits_[:], &s.cmd_code_numbits_, s.cmd_code_[:], &storage_ix, storage) - } else { - compressFragmentTwoPass(*next_in, block_size, is_last, command_buf, literal_buf, table, table_size, &storage_ix, storage) - } - - *next_in = (*next_in)[block_size:] - *available_in -= block_size - var out_bytes uint = storage_ix >> 3 - s.writeOutput(storage[:out_bytes]) - - s.last_bytes_ = uint16(storage[storage_ix>>3]) - s.last_bytes_bits_ = byte(storage_ix & 7) - - if force_flush { - s.stream_state_ = streamFlushRequested - } - if is_last { - s.stream_state_ = streamFinished - } - continue - } - - break - } - - checkFlushComplete(s) - return true -} - -func processMetadata(s *Writer, available_in *uint, next_in *[]byte) bool { - if *available_in > 1<<24 { - return false - } - - /* Switch to metadata block workflow, if required. */ - if s.stream_state_ == streamProcessing { - s.remaining_metadata_bytes_ = uint32(*available_in) - s.stream_state_ = streamMetadataHead - } - - if s.stream_state_ != streamMetadataHead && s.stream_state_ != streamMetadataBody { - return false - } - - for { - if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 { - injectBytePaddingBlock(s) - continue - } - - if s.input_pos_ != s.last_flush_pos_ { - var result bool = encodeData(s, false, true) - if !result { - return false - } - continue - } - - if s.stream_state_ == streamMetadataHead { - n := writeMetadataHeader(s, uint(s.remaining_metadata_bytes_), s.tiny_buf_.u8[:]) - s.writeOutput(s.tiny_buf_.u8[:n]) - s.stream_state_ = streamMetadataBody - continue - } else { - /* Exit workflow only when there is no more input and no more output. - Otherwise client may continue producing empty metadata blocks. */ - if s.remaining_metadata_bytes_ == 0 { - s.remaining_metadata_bytes_ = math.MaxUint32 - s.stream_state_ = streamProcessing - break - } - - /* This guarantees progress in "TakeOutput" workflow. */ - var c uint32 = brotli_min_uint32_t(s.remaining_metadata_bytes_, 16) - copy(s.tiny_buf_.u8[:], (*next_in)[:c]) - *next_in = (*next_in)[c:] - *available_in -= uint(c) - s.remaining_metadata_bytes_ -= c - s.writeOutput(s.tiny_buf_.u8[:c]) - - continue - } - } - - return true -} - -func updateSizeHint(s *Writer, available_in uint) { - if s.params.size_hint == 0 { - var delta uint64 = unprocessedInputSize(s) - var tail uint64 = uint64(available_in) - var limit uint32 = 1 << 30 - var total uint32 - if (delta >= uint64(limit)) || (tail >= uint64(limit)) || ((delta + tail) >= uint64(limit)) { - total = limit - } else { - total = uint32(delta + tail) - } - - s.params.size_hint = uint(total) - } -} - -func encoderCompressStream(s *Writer, op int, available_in *uint, next_in *[]byte) bool { - if !ensureInitialized(s) { - return false - } - - /* Unfinished metadata block; check requirements. */ - if s.remaining_metadata_bytes_ != math.MaxUint32 { - if uint32(*available_in) != s.remaining_metadata_bytes_ { - return false - } - if op != int(operationEmitMetadata) { - return false - } - } - - if op == int(operationEmitMetadata) { - updateSizeHint(s, 0) /* First data metablock might be emitted here. */ - return processMetadata(s, available_in, next_in) - } - - if s.stream_state_ == streamMetadataHead || s.stream_state_ == streamMetadataBody { - return false - } - - if s.stream_state_ != streamProcessing && *available_in != 0 { - return false - } - - if s.params.quality == fastOnePassCompressionQuality || s.params.quality == fastTwoPassCompressionQuality { - return encoderCompressStreamFast(s, op, available_in, next_in) - } - - for { - var remaining_block_size uint = remainingInputBlockSize(s) - - if remaining_block_size != 0 && *available_in != 0 { - var copy_input_size uint = brotli_min_size_t(remaining_block_size, *available_in) - copyInputToRingBuffer(s, copy_input_size, *next_in) - *next_in = (*next_in)[copy_input_size:] - *available_in -= copy_input_size - continue - } - - if s.stream_state_ == streamFlushRequested && s.last_bytes_bits_ != 0 { - injectBytePaddingBlock(s) - continue - } - - /* Compress data only when stream is not - finished and there is no pending flush request. */ - if s.stream_state_ == streamProcessing { - if remaining_block_size == 0 || op != int(operationProcess) { - var is_last bool = ((*available_in == 0) && op == int(operationFinish)) - var force_flush bool = ((*available_in == 0) && op == int(operationFlush)) - var result bool - updateSizeHint(s, *available_in) - result = encodeData(s, is_last, force_flush) - if !result { - return false - } - if force_flush { - s.stream_state_ = streamFlushRequested - } - if is_last { - s.stream_state_ = streamFinished - } - continue - } - } - - break - } - - checkFlushComplete(s) - return true -} - -func (w *Writer) writeOutput(data []byte) { - if w.err != nil { - return - } - - _, w.err = w.dst.Write(data) - if w.err == nil { - checkFlushComplete(w) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/encoder.go b/src/vendor/github.com/andybalholm/brotli/encoder.go deleted file mode 100644 index cd541b35..00000000 --- a/src/vendor/github.com/andybalholm/brotli/encoder.go +++ /dev/null @@ -1,177 +0,0 @@ -package brotli - -import "github.com/andybalholm/brotli/matchfinder" - -// An Encoder implements the matchfinder.Encoder interface, writing in Brotli format. -type Encoder struct { - wroteHeader bool - bw bitWriter - distCache []distanceCode -} - -func (e *Encoder) Reset() { - e.wroteHeader = false - e.bw = bitWriter{} -} - -func (e *Encoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte { - e.bw.dst = dst - if !e.wroteHeader { - e.bw.writeBits(4, 15) - e.wroteHeader = true - } - - if len(src) == 0 { - if lastBlock { - e.bw.writeBits(2, 3) // islast + isempty - e.bw.jumpToByteBoundary() - return e.bw.dst - } - return dst - } - - var literalHisto [256]uint32 - var commandHisto [704]uint32 - var distanceHisto [64]uint32 - literalCount := 0 - commandCount := 0 - distanceCount := 0 - - if len(e.distCache) < len(matches) { - e.distCache = make([]distanceCode, len(matches)) - } - - // first pass: build the histograms - pos := 0 - - // d is the ring buffer of the last 4 distances. - d := [4]int{-10, -10, -10, -10} - for i, m := range matches { - if m.Unmatched > 0 { - for _, c := range src[pos : pos+m.Unmatched] { - literalHisto[c]++ - } - literalCount += m.Unmatched - } - - insertCode := getInsertLengthCode(uint(m.Unmatched)) - copyCode := getCopyLengthCode(uint(m.Length)) - if m.Length == 0 { - // If the stream ends with unmatched bytes, we need a dummy copy length. - copyCode = 2 - } - command := combineLengthCodes(insertCode, copyCode, i > 0 && m.Distance == matches[i-1].Distance) - commandHisto[command]++ - commandCount++ - - if command >= 128 && m.Length != 0 { - var distCode distanceCode - switch m.Distance { - case d[3]: - distCode.code = 0 - case d[2]: - distCode.code = 1 - case d[1]: - distCode.code = 2 - case d[0]: - distCode.code = 3 - case d[3] - 1: - distCode.code = 4 - case d[3] + 1: - distCode.code = 5 - case d[3] - 2: - distCode.code = 6 - case d[3] + 2: - distCode.code = 7 - case d[3] - 3: - distCode.code = 8 - case d[3] + 3: - distCode.code = 9 - - // In my testing, codes 10–15 actually reduced the compression ratio. - - default: - distCode = getDistanceCode(m.Distance) - } - e.distCache[i] = distCode - distanceHisto[distCode.code]++ - distanceCount++ - if distCode.code != 0 { - d[0], d[1], d[2], d[3] = d[1], d[2], d[3], m.Distance - } - } - - pos += m.Unmatched + m.Length - } - - storeMetaBlockHeaderBW(uint(len(src)), false, &e.bw) - e.bw.writeBits(13, 0) - - var literalDepths [256]byte - var literalBits [256]uint16 - buildAndStoreHuffmanTreeFastBW(literalHisto[:], uint(literalCount), 8, literalDepths[:], literalBits[:], &e.bw) - - var commandDepths [704]byte - var commandBits [704]uint16 - buildAndStoreHuffmanTreeFastBW(commandHisto[:], uint(commandCount), 10, commandDepths[:], commandBits[:], &e.bw) - - var distanceDepths [64]byte - var distanceBits [64]uint16 - buildAndStoreHuffmanTreeFastBW(distanceHisto[:], uint(distanceCount), 6, distanceDepths[:], distanceBits[:], &e.bw) - - pos = 0 - for i, m := range matches { - insertCode := getInsertLengthCode(uint(m.Unmatched)) - copyCode := getCopyLengthCode(uint(m.Length)) - if m.Length == 0 { - // If the stream ends with unmatched bytes, we need a dummy copy length. - copyCode = 2 - } - command := combineLengthCodes(insertCode, copyCode, i > 0 && m.Distance == matches[i-1].Distance) - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - if kInsExtra[insertCode] > 0 { - e.bw.writeBits(uint(kInsExtra[insertCode]), uint64(m.Unmatched)-uint64(kInsBase[insertCode])) - } - if kCopyExtra[copyCode] > 0 { - e.bw.writeBits(uint(kCopyExtra[copyCode]), uint64(m.Length)-uint64(kCopyBase[copyCode])) - } - - if m.Unmatched > 0 { - for _, c := range src[pos : pos+m.Unmatched] { - e.bw.writeBits(uint(literalDepths[c]), uint64(literalBits[c])) - } - } - - if command >= 128 && m.Length != 0 { - distCode := e.distCache[i] - e.bw.writeBits(uint(distanceDepths[distCode.code]), uint64(distanceBits[distCode.code])) - if distCode.nExtra > 0 { - e.bw.writeBits(distCode.nExtra, distCode.extraBits) - } - } - - pos += m.Unmatched + m.Length - } - - if lastBlock { - e.bw.writeBits(2, 3) // islast + isempty - e.bw.jumpToByteBoundary() - } - return e.bw.dst -} - -type distanceCode struct { - code int - nExtra uint - extraBits uint64 -} - -func getDistanceCode(distance int) distanceCode { - d := distance + 3 - nbits := log2FloorNonZero(uint(d)) - 1 - prefix := (d >> nbits) & 1 - offset := (2 + prefix) << nbits - distcode := int(2*(nbits-1)) + prefix + 16 - extra := d - offset - return distanceCode{distcode, uint(nbits), uint64(extra)} -} diff --git a/src/vendor/github.com/andybalholm/brotli/encoder_dict.go b/src/vendor/github.com/andybalholm/brotli/encoder_dict.go deleted file mode 100644 index 55c051c6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/encoder_dict.go +++ /dev/null @@ -1,22 +0,0 @@ -package brotli - -/* Dictionary data (words and transforms) for 1 possible context */ -type encoderDictionary struct { - words *dictionary - cutoffTransformsCount uint32 - cutoffTransforms uint64 - hash_table []uint16 - buckets []uint16 - dict_words []dictWord -} - -func initEncoderDictionary(dict *encoderDictionary) { - dict.words = getDictionary() - - dict.hash_table = kStaticDictionaryHash[:] - dict.buckets = kStaticDictionaryBuckets[:] - dict.dict_words = kStaticDictionaryWords[:] - - dict.cutoffTransformsCount = kCutoffTransformsCount - dict.cutoffTransforms = kCutoffTransforms -} diff --git a/src/vendor/github.com/andybalholm/brotli/encoder_fast.go b/src/vendor/github.com/andybalholm/brotli/encoder_fast.go deleted file mode 100644 index 36a41737..00000000 --- a/src/vendor/github.com/andybalholm/brotli/encoder_fast.go +++ /dev/null @@ -1,197 +0,0 @@ -package brotli - -import ( - "math" - - "github.com/andybalholm/brotli/matchfinder" -) - -func gaussianProbability(x, mean, stdDev float64) float64 { - return math.Exp(-(x-mean)*(x-mean)/(2*stdDev*stdDev)) / math.Sqrt(2*math.Pi*stdDev*stdDev) -} - -// A FastEncoder implements the matchfinder.Encoder interface, writing in Brotli -// format. It uses a simplified encoding (like level 0 in the reference -// implementation) to save time. -type FastEncoder struct { - wroteHeader bool - bw bitWriter - commandHisto [704]uint32 - distanceHisto [64]uint32 -} - -func (e *FastEncoder) Reset() { - e.wroteHeader = false - e.bw = bitWriter{} -} - -func (e *FastEncoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte { - e.bw.dst = dst - if !e.wroteHeader { - e.bw.writeBits(4, 15) - e.wroteHeader = true - - // Fill the histograms with default statistics. - - // For the command codes we're using for insert lengths (insert + 2-byte copy), - // fill the histogram with a Zipf-squared distribution. - for i := range 24 { - e.commandHisto[combineLengthCodes(uint16(i), 0, false)] = uint32(2000 / (i + 1) / (i + 1)) - } - - // For the command codes we're using for copy lengths (0 insert + copy - // (length - 2), with repeat distance), - // fill the histogram with Zipf distribution starting at code 1 (match length 5), - // but a smaller frequency for code 0. - e.commandHisto[combineLengthCodes(0, 0, true)] = 50 - for i := 1; i < 24; i++ { - e.commandHisto[combineLengthCodes(0, uint16(i), i < 16)] = uint32(800 / i) - } - - // Fill in the combined codes for short insert and copy lengths. - for insertCode := range 6 { - copyCode := 2 - e.commandHisto[128+insertCode<<3+copyCode] = uint32(100 / (insertCode + 1) / (insertCode + 1) / copyCode) - for copyCode := 3; copyCode < 8; copyCode++ { - e.commandHisto[128+insertCode<<3+copyCode] = uint32(343 / (insertCode + 1) / (insertCode + 1) / copyCode) - } - } - - // Fill e.distanceHisto with a normal distribution. - e.distanceHisto[0] = 100 - for i := 16; i < 64; i++ { - e.distanceHisto[i] = max(uint32(gaussianProbability(float64(i), 32, 8)*10000), 1) - } - } - - if len(src) == 0 { - if lastBlock { - e.bw.writeBits(2, 3) // islast + isempty - e.bw.jumpToByteBoundary() - return e.bw.dst - } - return dst - } - - var literalHisto [256]uint32 - for _, c := range src { - literalHisto[c]++ - } - - storeMetaBlockHeaderBW(uint(len(src)), false, &e.bw) - e.bw.writeBits(13, 0) - - var literalDepths [256]byte - var literalBits [256]uint16 - buildAndStoreHuffmanTreeFastBW(literalHisto[:], uint(len(src)), 8, literalDepths[:], literalBits[:], &e.bw) - - var commandDepths [704]byte - var commandBits [704]uint16 - commandCount := 0 - for _, n := range e.commandHisto { - commandCount += int(n) - } - buildAndStoreHuffmanTreeFastBW(e.commandHisto[:], uint(commandCount), 10, commandDepths[:], commandBits[:], &e.bw) - - var distanceDepths [64]byte - var distanceBits [64]uint16 - distanceCount := 0 - for _, n := range e.distanceHisto { - distanceCount += int(n) - } - buildAndStoreHuffmanTreeFastBW(e.distanceHisto[:], uint(distanceCount), 6, distanceDepths[:], distanceBits[:], &e.bw) - - // Reset the statistics, starting with a count of 1 for each symbol we might use. - for i := range 24 { - e.commandHisto[combineLengthCodes(uint16(i), 0, false)] = 1 - } - for i := range 24 { - e.commandHisto[combineLengthCodes(0, uint16(i), i < 16)] = 1 - } - for insertCode := range 6 { - for copyCode := 2; copyCode < 8; copyCode++ { - e.commandHisto[128+insertCode<<3+copyCode] = 1 - } - } - e.distanceHisto[0] = 1 - for i := 16; i < 64; i++ { - e.distanceHisto[i] = 1 - } - - pos := 0 - for i, m := range matches { - lengthFinished := false - // Write a command with the appropriate insert length, and a copy length of 2. - if m.Unmatched < 6 { - var command int - if m.Length < 10 && m.Length != 0 { - // We can use a combined insert/copy code with no extra bits. - command = m.Unmatched<<3 + m.Length - 2 + 128 - lengthFinished = true - } else { - command = m.Unmatched<<3 + 128 - } - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - e.commandHisto[command]++ - } else { - insertCode := getInsertLengthCode(uint(m.Unmatched)) - command := combineLengthCodes(insertCode, 0, false) - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - e.bw.writeBits(uint(kInsExtra[insertCode]), uint64(m.Unmatched)-uint64(kInsBase[insertCode])) - e.commandHisto[command]++ - } - - // Write the literals, if any. - if m.Unmatched > 0 { - for _, c := range src[pos : pos+m.Unmatched] { - e.bw.writeBits(uint(literalDepths[c]), uint64(literalBits[c])) - } - } - - if m.Length != 0 { - // Write the distance code. - var distCode distanceCode - if i == 0 || m.Distance != matches[i-1].Distance { - distCode = getDistanceCode(m.Distance) - } - e.bw.writeBits(uint(distanceDepths[distCode.code]), uint64(distanceBits[distCode.code])) - if distCode.nExtra > 0 { - e.bw.writeBits(distCode.nExtra, distCode.extraBits) - } - e.distanceHisto[distCode.code]++ - - // Write a command for the remainder of the match (after the first two bytes - // from before), using the previous distance. - switch { - case lengthFinished: - // We don't need to finish the length. - case m.Length < 12: - command := m.Length - 4 - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - e.commandHisto[command]++ - case m.Length < 72: - copyCode := getCopyLengthCode(uint(m.Length - 2)) - command := combineLengthCodes(0, copyCode, true) - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - e.bw.writeBits(uint(kCopyExtra[copyCode]), uint64(m.Length-2)-uint64(kCopyBase[copyCode])) - e.commandHisto[command]++ - default: - copyCode := getCopyLengthCode(uint(m.Length - 2)) - command := combineLengthCodes(0, copyCode, false) - e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command])) - e.bw.writeBits(uint(kCopyExtra[copyCode]), uint64(m.Length-2)-uint64(kCopyBase[copyCode])) - e.bw.writeBits(uint(distanceDepths[0]), uint64(distanceBits[0])) - e.commandHisto[command]++ - e.distanceHisto[0]++ - } - } - - pos += m.Unmatched + m.Length - } - - if lastBlock { - e.bw.writeBits(2, 3) // islast + isempty - e.bw.jumpToByteBoundary() - } - return e.bw.dst -} diff --git a/src/vendor/github.com/andybalholm/brotli/entropy_encode.go b/src/vendor/github.com/andybalholm/brotli/entropy_encode.go deleted file mode 100644 index 3f469a3d..00000000 --- a/src/vendor/github.com/andybalholm/brotli/entropy_encode.go +++ /dev/null @@ -1,592 +0,0 @@ -package brotli - -import "math" - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Entropy encoding (Huffman) utilities. */ - -/* A node of a Huffman tree. */ -type huffmanTree struct { - total_count_ uint32 - index_left_ int16 - index_right_or_value_ int16 -} - -func initHuffmanTree(self *huffmanTree, count uint32, left int16, right int16) { - self.total_count_ = count - self.index_left_ = left - self.index_right_or_value_ = right -} - -/* Input size optimized Shell sort. */ -type huffmanTreeComparator func(huffmanTree, huffmanTree) bool - -var sortHuffmanTreeItems_gaps = []uint{132, 57, 23, 10, 4, 1} - -func sortHuffmanTreeItems(items []huffmanTree, n uint, comparator huffmanTreeComparator) { - if n < 13 { - /* Insertion sort. */ - var i uint - for i = 1; i < n; i++ { - var tmp huffmanTree = items[i] - var k uint = i - var j uint = i - 1 - for comparator(tmp, items[j]) { - items[k] = items[j] - k = j - if j == 0 { - break - } - j-- - } - - items[k] = tmp - } - - return - } else { - var g int - if n < 57 { - g = 2 - } else { - g = 0 - } - for ; g < 6; g++ { - var gap uint = sortHuffmanTreeItems_gaps[g] - var i uint - for i = gap; i < n; i++ { - var j uint = i - var tmp huffmanTree = items[i] - for ; j >= gap && comparator(tmp, items[j-gap]); j -= gap { - items[j] = items[j-gap] - } - - items[j] = tmp - } - } - } -} - -/* Returns 1 if assignment of depths succeeded, otherwise 0. */ -func setDepth(p0 int, pool []huffmanTree, depth []byte, max_depth int) bool { - var stack [16]int - var level int = 0 - var p int = p0 - assert(max_depth <= 15) - stack[0] = -1 - for { - if pool[p].index_left_ >= 0 { - level++ - if level > max_depth { - return false - } - stack[level] = int(pool[p].index_right_or_value_) - p = int(pool[p].index_left_) - continue - } else { - depth[pool[p].index_right_or_value_] = byte(level) - } - - for level >= 0 && stack[level] == -1 { - level-- - } - if level < 0 { - return true - } - p = stack[level] - stack[level] = -1 - } -} - -/* Sort the root nodes, least popular first. */ -func sortHuffmanTree(v0 huffmanTree, v1 huffmanTree) bool { - if v0.total_count_ != v1.total_count_ { - return v0.total_count_ < v1.total_count_ - } - - return v0.index_right_or_value_ > v1.index_right_or_value_ -} - -/* This function will create a Huffman tree. - - The catch here is that the tree cannot be arbitrarily deep. - Brotli specifies a maximum depth of 15 bits for "code trees" - and 7 bits for "code length code trees." - - count_limit is the value that is to be faked as the minimum value - and this minimum value is raised until the tree matches the - maximum length requirement. - - This algorithm is not of excellent performance for very long data blocks, - especially when population counts are longer than 2**tree_limit, but - we are not planning to use this with extremely long blocks. - - See http://en.wikipedia.org/wiki/Huffman_coding */ -func createHuffmanTree(data []uint32, length uint, tree_limit int, tree []huffmanTree, depth []byte) { - var count_limit uint32 - var sentinel huffmanTree - initHuffmanTree(&sentinel, math.MaxUint32, -1, -1) - - /* For block sizes below 64 kB, we never need to do a second iteration - of this loop. Probably all of our block sizes will be smaller than - that, so this loop is mostly of academic interest. If we actually - would need this, we would be better off with the Katajainen algorithm. */ - for count_limit = 1; ; count_limit *= 2 { - var n uint = 0 - var i uint - var j uint - var k uint - for i = length; i != 0; { - i-- - if data[i] != 0 { - var count uint32 = brotli_max_uint32_t(data[i], count_limit) - initHuffmanTree(&tree[n], count, -1, int16(i)) - n++ - } - } - - if n == 1 { - depth[tree[0].index_right_or_value_] = 1 /* Only one element. */ - break - } - - sortHuffmanTreeItems(tree, n, huffmanTreeComparator(sortHuffmanTree)) - - /* The nodes are: - [0, n): the sorted leaf nodes that we start with. - [n]: we add a sentinel here. - [n + 1, 2n): new parent nodes are added here, starting from - (n+1). These are naturally in ascending order. - [2n]: we add a sentinel at the end as well. - There will be (2n+1) elements at the end. */ - tree[n] = sentinel - - tree[n+1] = sentinel - - i = 0 /* Points to the next leaf node. */ - j = n + 1 /* Points to the next non-leaf node. */ - for k = n - 1; k != 0; k-- { - var left uint - var right uint - if tree[i].total_count_ <= tree[j].total_count_ { - left = i - i++ - } else { - left = j - j++ - } - - if tree[i].total_count_ <= tree[j].total_count_ { - right = i - i++ - } else { - right = j - j++ - } - { - /* The sentinel node becomes the parent node. */ - var j_end uint = 2*n - k - tree[j_end].total_count_ = tree[left].total_count_ + tree[right].total_count_ - tree[j_end].index_left_ = int16(left) - tree[j_end].index_right_or_value_ = int16(right) - - /* Add back the last sentinel node. */ - tree[j_end+1] = sentinel - } - } - - if setDepth(int(2*n-1), tree[0:], depth, tree_limit) { - /* We need to pack the Huffman tree in tree_limit bits. If this was not - successful, add fake entities to the lowest values and retry. */ - break - } - } -} - -func reverse(v []byte, start uint, end uint) { - end-- - for start < end { - var tmp byte = v[start] - v[start] = v[end] - v[end] = tmp - start++ - end-- - } -} - -func writeHuffmanTreeRepetitions(previous_value byte, value byte, repetitions uint, tree_size *uint, tree []byte, extra_bits_data []byte) { - assert(repetitions > 0) - if previous_value != value { - tree[*tree_size] = value - extra_bits_data[*tree_size] = 0 - (*tree_size)++ - repetitions-- - } - - if repetitions == 7 { - tree[*tree_size] = value - extra_bits_data[*tree_size] = 0 - (*tree_size)++ - repetitions-- - } - - if repetitions < 3 { - var i uint - for i = 0; i < repetitions; i++ { - tree[*tree_size] = value - extra_bits_data[*tree_size] = 0 - (*tree_size)++ - } - } else { - var start uint = *tree_size - repetitions -= 3 - for { - tree[*tree_size] = repeatPreviousCodeLength - extra_bits_data[*tree_size] = byte(repetitions & 0x3) - (*tree_size)++ - repetitions >>= 2 - if repetitions == 0 { - break - } - - repetitions-- - } - - reverse(tree, start, *tree_size) - reverse(extra_bits_data, start, *tree_size) - } -} - -func writeHuffmanTreeRepetitionsZeros(repetitions uint, tree_size *uint, tree []byte, extra_bits_data []byte) { - if repetitions == 11 { - tree[*tree_size] = 0 - extra_bits_data[*tree_size] = 0 - (*tree_size)++ - repetitions-- - } - - if repetitions < 3 { - var i uint - for i = 0; i < repetitions; i++ { - tree[*tree_size] = 0 - extra_bits_data[*tree_size] = 0 - (*tree_size)++ - } - } else { - var start uint = *tree_size - repetitions -= 3 - for { - tree[*tree_size] = repeatZeroCodeLength - extra_bits_data[*tree_size] = byte(repetitions & 0x7) - (*tree_size)++ - repetitions >>= 3 - if repetitions == 0 { - break - } - - repetitions-- - } - - reverse(tree, start, *tree_size) - reverse(extra_bits_data, start, *tree_size) - } -} - -/* Change the population counts in a way that the consequent - Huffman tree compression, especially its RLE-part will be more - likely to compress this data more efficiently. - - length contains the size of the histogram. - counts contains the population counts. - good_for_rle is a buffer of at least length size */ -func optimizeHuffmanCountsForRLE(length uint, counts []uint32, good_for_rle []byte) { - var nonzero_count uint = 0 - var stride uint - var limit uint - var sum uint - var streak_limit uint = 1240 - var i uint - /* Let's make the Huffman code more compatible with RLE encoding. */ - for i = 0; i < length; i++ { - if counts[i] != 0 { - nonzero_count++ - } - } - - if nonzero_count < 16 { - return - } - - for length != 0 && counts[length-1] == 0 { - length-- - } - - if length == 0 { - return /* All zeros. */ - } - - /* Now counts[0..length - 1] does not have trailing zeros. */ - { - var nonzeros uint = 0 - var smallest_nonzero uint32 = 1 << 30 - for i = 0; i < length; i++ { - if counts[i] != 0 { - nonzeros++ - if smallest_nonzero > counts[i] { - smallest_nonzero = counts[i] - } - } - } - - if nonzeros < 5 { - /* Small histogram will model it well. */ - return - } - - if smallest_nonzero < 4 { - var zeros uint = length - nonzeros - if zeros < 6 { - for i = 1; i < length-1; i++ { - if counts[i-1] != 0 && counts[i] == 0 && counts[i+1] != 0 { - counts[i] = 1 - } - } - } - } - - if nonzeros < 28 { - return - } - } - - /* 2) Let's mark all population counts that already can be encoded - with an RLE code. */ - for i := 0; i < int(length); i++ { - good_for_rle[i] = 0 - } - { - var symbol uint32 = counts[0] - /* Let's not spoil any of the existing good RLE codes. - Mark any seq of 0's that is longer as 5 as a good_for_rle. - Mark any seq of non-0's that is longer as 7 as a good_for_rle. */ - - var step uint = 0 - for i = 0; i <= length; i++ { - if i == length || counts[i] != symbol { - if (symbol == 0 && step >= 5) || (symbol != 0 && step >= 7) { - var k uint - for k = 0; k < step; k++ { - good_for_rle[i-k-1] = 1 - } - } - - step = 1 - if i != length { - symbol = counts[i] - } - } else { - step++ - } - } - } - - /* 3) Let's replace those population counts that lead to more RLE codes. - Math here is in 24.8 fixed point representation. */ - stride = 0 - - limit = uint(256*(counts[0]+counts[1]+counts[2])/3 + 420) - sum = 0 - for i = 0; i <= length; i++ { - if i == length || good_for_rle[i] != 0 || (i != 0 && good_for_rle[i-1] != 0) || (256*counts[i]-uint32(limit)+uint32(streak_limit)) >= uint32(2*streak_limit) { - if stride >= 4 || (stride >= 3 && sum == 0) { - var k uint - var count uint = (sum + stride/2) / stride - /* The stride must end, collapse what we have, if we have enough (4). */ - if count == 0 { - count = 1 - } - - if sum == 0 { - /* Don't make an all zeros stride to be upgraded to ones. */ - count = 0 - } - - for k = 0; k < stride; k++ { - /* We don't want to change value at counts[i], - that is already belonging to the next stride. Thus - 1. */ - counts[i-k-1] = uint32(count) - } - } - - stride = 0 - sum = 0 - if i < length-2 { - /* All interesting strides have a count of at least 4, */ - /* at least when non-zeros. */ - limit = uint(256*(counts[i]+counts[i+1]+counts[i+2])/3 + 420) - } else if i < length { - limit = uint(256 * counts[i]) - } else { - limit = 0 - } - } - - stride++ - if i != length { - sum += uint(counts[i]) - if stride >= 4 { - limit = (256*sum + stride/2) / stride - } - - if stride == 4 { - limit += 120 - } - } - } -} - -func decideOverRLEUse(depth []byte, length uint, use_rle_for_non_zero *bool, use_rle_for_zero *bool) { - var total_reps_zero uint = 0 - var total_reps_non_zero uint = 0 - var count_reps_zero uint = 1 - var count_reps_non_zero uint = 1 - var i uint - for i = 0; i < length; { - var value byte = depth[i] - var reps uint = 1 - var k uint - for k = i + 1; k < length && depth[k] == value; k++ { - reps++ - } - - if reps >= 3 && value == 0 { - total_reps_zero += reps - count_reps_zero++ - } - - if reps >= 4 && value != 0 { - total_reps_non_zero += reps - count_reps_non_zero++ - } - - i += reps - } - - *use_rle_for_non_zero = total_reps_non_zero > count_reps_non_zero*2 - *use_rle_for_zero = total_reps_zero > count_reps_zero*2 -} - -/* Write a Huffman tree from bit depths into the bit-stream representation - of a Huffman tree. The generated Huffman tree is to be compressed once - more using a Huffman tree */ -func writeHuffmanTree(depth []byte, length uint, tree_size *uint, tree []byte, extra_bits_data []byte) { - var previous_value byte = initialRepeatedCodeLength - var i uint - var use_rle_for_non_zero bool = false - var use_rle_for_zero bool = false - var new_length uint = length - /* Throw away trailing zeros. */ - for i = 0; i < length; i++ { - if depth[length-i-1] == 0 { - new_length-- - } else { - break - } - } - - /* First gather statistics on if it is a good idea to do RLE. */ - if length > 50 { - /* Find RLE coding for longer codes. - Shorter codes seem not to benefit from RLE. */ - decideOverRLEUse(depth, new_length, &use_rle_for_non_zero, &use_rle_for_zero) - } - - /* Actual RLE coding. */ - for i = 0; i < new_length; { - var value byte = depth[i] - var reps uint = 1 - if (value != 0 && use_rle_for_non_zero) || (value == 0 && use_rle_for_zero) { - var k uint - for k = i + 1; k < new_length && depth[k] == value; k++ { - reps++ - } - } - - if value == 0 { - writeHuffmanTreeRepetitionsZeros(reps, tree_size, tree, extra_bits_data) - } else { - writeHuffmanTreeRepetitions(previous_value, value, reps, tree_size, tree, extra_bits_data) - previous_value = value - } - - i += reps - } -} - -var reverseBits_kLut = [16]uint{ - 0x00, - 0x08, - 0x04, - 0x0C, - 0x02, - 0x0A, - 0x06, - 0x0E, - 0x01, - 0x09, - 0x05, - 0x0D, - 0x03, - 0x0B, - 0x07, - 0x0F, -} - -func reverseBits(num_bits uint, bits uint16) uint16 { - var retval uint = reverseBits_kLut[bits&0x0F] - var i uint - for i = 4; i < num_bits; i += 4 { - retval <<= 4 - bits = uint16(bits >> 4) - retval |= reverseBits_kLut[bits&0x0F] - } - - retval >>= ((0 - num_bits) & 0x03) - return uint16(retval) -} - -/* 0..15 are values for bits */ -const maxHuffmanBits = 16 - -/* Get the actual bit values for a tree of bit depths. */ -func convertBitDepthsToSymbols(depth []byte, len uint, bits []uint16) { - var bl_count = [maxHuffmanBits]uint16{0} - var next_code [maxHuffmanBits]uint16 - var i uint - /* In Brotli, all bit depths are [1..15] - 0 bit depth means that the symbol does not exist. */ - - var code int = 0 - for i = 0; i < len; i++ { - bl_count[depth[i]]++ - } - - bl_count[0] = 0 - next_code[0] = 0 - for i = 1; i < maxHuffmanBits; i++ { - code = (code + int(bl_count[i-1])) << 1 - next_code[i] = uint16(code) - } - - for i = 0; i < len; i++ { - if depth[i] != 0 { - bits[i] = reverseBits(uint(depth[i]), next_code[depth[i]]) - next_code[depth[i]]++ - } - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/entropy_encode_static.go b/src/vendor/github.com/andybalholm/brotli/entropy_encode_static.go deleted file mode 100644 index 294aff4f..00000000 --- a/src/vendor/github.com/andybalholm/brotli/entropy_encode_static.go +++ /dev/null @@ -1,4399 +0,0 @@ -package brotli - -var kCodeLengthDepth = [18]byte{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4} - -var kStaticCommandCodeDepth = [numCommandSymbols]byte{ - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 9, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, - 11, -} - -var kStaticDistanceCodeDepth = [64]byte{ - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, - 6, -} - -var kCodeLengthBits = [18]uint32{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7} - -func storeStaticCodeLengthCode(storage_ix *uint, storage []byte) { - writeBits(40, 0x0000FF55555554, storage_ix, storage) -} - -func storeStaticCodeLengthCodeBW(bw *bitWriter) { - bw.writeBits(32, 0x55555554) - bw.writeBits(8, 0xFF) -} - -var kZeroRepsBits = [numCommandSymbols]uint64{ - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000007, - 0x00000017, - 0x00000027, - 0x00000037, - 0x00000047, - 0x00000057, - 0x00000067, - 0x00000077, - 0x00000770, - 0x00000b87, - 0x00001387, - 0x00001b87, - 0x00002387, - 0x00002b87, - 0x00003387, - 0x00003b87, - 0x00000397, - 0x00000b97, - 0x00001397, - 0x00001b97, - 0x00002397, - 0x00002b97, - 0x00003397, - 0x00003b97, - 0x000003a7, - 0x00000ba7, - 0x000013a7, - 0x00001ba7, - 0x000023a7, - 0x00002ba7, - 0x000033a7, - 0x00003ba7, - 0x000003b7, - 0x00000bb7, - 0x000013b7, - 0x00001bb7, - 0x000023b7, - 0x00002bb7, - 0x000033b7, - 0x00003bb7, - 0x000003c7, - 0x00000bc7, - 0x000013c7, - 0x00001bc7, - 0x000023c7, - 0x00002bc7, - 0x000033c7, - 0x00003bc7, - 0x000003d7, - 0x00000bd7, - 0x000013d7, - 0x00001bd7, - 0x000023d7, - 0x00002bd7, - 0x000033d7, - 0x00003bd7, - 0x000003e7, - 0x00000be7, - 0x000013e7, - 0x00001be7, - 0x000023e7, - 0x00002be7, - 0x000033e7, - 0x00003be7, - 0x000003f7, - 0x00000bf7, - 0x000013f7, - 0x00001bf7, - 0x000023f7, - 0x00002bf7, - 0x000033f7, - 0x00003bf7, - 0x0001c387, - 0x0005c387, - 0x0009c387, - 0x000dc387, - 0x0011c387, - 0x0015c387, - 0x0019c387, - 0x001dc387, - 0x0001cb87, - 0x0005cb87, - 0x0009cb87, - 0x000dcb87, - 0x0011cb87, - 0x0015cb87, - 0x0019cb87, - 0x001dcb87, - 0x0001d387, - 0x0005d387, - 0x0009d387, - 0x000dd387, - 0x0011d387, - 0x0015d387, - 0x0019d387, - 0x001dd387, - 0x0001db87, - 0x0005db87, - 0x0009db87, - 0x000ddb87, - 0x0011db87, - 0x0015db87, - 0x0019db87, - 0x001ddb87, - 0x0001e387, - 0x0005e387, - 0x0009e387, - 0x000de387, - 0x0011e387, - 0x0015e387, - 0x0019e387, - 0x001de387, - 0x0001eb87, - 0x0005eb87, - 0x0009eb87, - 0x000deb87, - 0x0011eb87, - 0x0015eb87, - 0x0019eb87, - 0x001deb87, - 0x0001f387, - 0x0005f387, - 0x0009f387, - 0x000df387, - 0x0011f387, - 0x0015f387, - 0x0019f387, - 0x001df387, - 0x0001fb87, - 0x0005fb87, - 0x0009fb87, - 0x000dfb87, - 0x0011fb87, - 0x0015fb87, - 0x0019fb87, - 0x001dfb87, - 0x0001c397, - 0x0005c397, - 0x0009c397, - 0x000dc397, - 0x0011c397, - 0x0015c397, - 0x0019c397, - 0x001dc397, - 0x0001cb97, - 0x0005cb97, - 0x0009cb97, - 0x000dcb97, - 0x0011cb97, - 0x0015cb97, - 0x0019cb97, - 0x001dcb97, - 0x0001d397, - 0x0005d397, - 0x0009d397, - 0x000dd397, - 0x0011d397, - 0x0015d397, - 0x0019d397, - 0x001dd397, - 0x0001db97, - 0x0005db97, - 0x0009db97, - 0x000ddb97, - 0x0011db97, - 0x0015db97, - 0x0019db97, - 0x001ddb97, - 0x0001e397, - 0x0005e397, - 0x0009e397, - 0x000de397, - 0x0011e397, - 0x0015e397, - 0x0019e397, - 0x001de397, - 0x0001eb97, - 0x0005eb97, - 0x0009eb97, - 0x000deb97, - 0x0011eb97, - 0x0015eb97, - 0x0019eb97, - 0x001deb97, - 0x0001f397, - 0x0005f397, - 0x0009f397, - 0x000df397, - 0x0011f397, - 0x0015f397, - 0x0019f397, - 0x001df397, - 0x0001fb97, - 0x0005fb97, - 0x0009fb97, - 0x000dfb97, - 0x0011fb97, - 0x0015fb97, - 0x0019fb97, - 0x001dfb97, - 0x0001c3a7, - 0x0005c3a7, - 0x0009c3a7, - 0x000dc3a7, - 0x0011c3a7, - 0x0015c3a7, - 0x0019c3a7, - 0x001dc3a7, - 0x0001cba7, - 0x0005cba7, - 0x0009cba7, - 0x000dcba7, - 0x0011cba7, - 0x0015cba7, - 0x0019cba7, - 0x001dcba7, - 0x0001d3a7, - 0x0005d3a7, - 0x0009d3a7, - 0x000dd3a7, - 0x0011d3a7, - 0x0015d3a7, - 0x0019d3a7, - 0x001dd3a7, - 0x0001dba7, - 0x0005dba7, - 0x0009dba7, - 0x000ddba7, - 0x0011dba7, - 0x0015dba7, - 0x0019dba7, - 0x001ddba7, - 0x0001e3a7, - 0x0005e3a7, - 0x0009e3a7, - 0x000de3a7, - 0x0011e3a7, - 0x0015e3a7, - 0x0019e3a7, - 0x001de3a7, - 0x0001eba7, - 0x0005eba7, - 0x0009eba7, - 0x000deba7, - 0x0011eba7, - 0x0015eba7, - 0x0019eba7, - 0x001deba7, - 0x0001f3a7, - 0x0005f3a7, - 0x0009f3a7, - 0x000df3a7, - 0x0011f3a7, - 0x0015f3a7, - 0x0019f3a7, - 0x001df3a7, - 0x0001fba7, - 0x0005fba7, - 0x0009fba7, - 0x000dfba7, - 0x0011fba7, - 0x0015fba7, - 0x0019fba7, - 0x001dfba7, - 0x0001c3b7, - 0x0005c3b7, - 0x0009c3b7, - 0x000dc3b7, - 0x0011c3b7, - 0x0015c3b7, - 0x0019c3b7, - 0x001dc3b7, - 0x0001cbb7, - 0x0005cbb7, - 0x0009cbb7, - 0x000dcbb7, - 0x0011cbb7, - 0x0015cbb7, - 0x0019cbb7, - 0x001dcbb7, - 0x0001d3b7, - 0x0005d3b7, - 0x0009d3b7, - 0x000dd3b7, - 0x0011d3b7, - 0x0015d3b7, - 0x0019d3b7, - 0x001dd3b7, - 0x0001dbb7, - 0x0005dbb7, - 0x0009dbb7, - 0x000ddbb7, - 0x0011dbb7, - 0x0015dbb7, - 0x0019dbb7, - 0x001ddbb7, - 0x0001e3b7, - 0x0005e3b7, - 0x0009e3b7, - 0x000de3b7, - 0x0011e3b7, - 0x0015e3b7, - 0x0019e3b7, - 0x001de3b7, - 0x0001ebb7, - 0x0005ebb7, - 0x0009ebb7, - 0x000debb7, - 0x0011ebb7, - 0x0015ebb7, - 0x0019ebb7, - 0x001debb7, - 0x0001f3b7, - 0x0005f3b7, - 0x0009f3b7, - 0x000df3b7, - 0x0011f3b7, - 0x0015f3b7, - 0x0019f3b7, - 0x001df3b7, - 0x0001fbb7, - 0x0005fbb7, - 0x0009fbb7, - 0x000dfbb7, - 0x0011fbb7, - 0x0015fbb7, - 0x0019fbb7, - 0x001dfbb7, - 0x0001c3c7, - 0x0005c3c7, - 0x0009c3c7, - 0x000dc3c7, - 0x0011c3c7, - 0x0015c3c7, - 0x0019c3c7, - 0x001dc3c7, - 0x0001cbc7, - 0x0005cbc7, - 0x0009cbc7, - 0x000dcbc7, - 0x0011cbc7, - 0x0015cbc7, - 0x0019cbc7, - 0x001dcbc7, - 0x0001d3c7, - 0x0005d3c7, - 0x0009d3c7, - 0x000dd3c7, - 0x0011d3c7, - 0x0015d3c7, - 0x0019d3c7, - 0x001dd3c7, - 0x0001dbc7, - 0x0005dbc7, - 0x0009dbc7, - 0x000ddbc7, - 0x0011dbc7, - 0x0015dbc7, - 0x0019dbc7, - 0x001ddbc7, - 0x0001e3c7, - 0x0005e3c7, - 0x0009e3c7, - 0x000de3c7, - 0x0011e3c7, - 0x0015e3c7, - 0x0019e3c7, - 0x001de3c7, - 0x0001ebc7, - 0x0005ebc7, - 0x0009ebc7, - 0x000debc7, - 0x0011ebc7, - 0x0015ebc7, - 0x0019ebc7, - 0x001debc7, - 0x0001f3c7, - 0x0005f3c7, - 0x0009f3c7, - 0x000df3c7, - 0x0011f3c7, - 0x0015f3c7, - 0x0019f3c7, - 0x001df3c7, - 0x0001fbc7, - 0x0005fbc7, - 0x0009fbc7, - 0x000dfbc7, - 0x0011fbc7, - 0x0015fbc7, - 0x0019fbc7, - 0x001dfbc7, - 0x0001c3d7, - 0x0005c3d7, - 0x0009c3d7, - 0x000dc3d7, - 0x0011c3d7, - 0x0015c3d7, - 0x0019c3d7, - 0x001dc3d7, - 0x0001cbd7, - 0x0005cbd7, - 0x0009cbd7, - 0x000dcbd7, - 0x0011cbd7, - 0x0015cbd7, - 0x0019cbd7, - 0x001dcbd7, - 0x0001d3d7, - 0x0005d3d7, - 0x0009d3d7, - 0x000dd3d7, - 0x0011d3d7, - 0x0015d3d7, - 0x0019d3d7, - 0x001dd3d7, - 0x0001dbd7, - 0x0005dbd7, - 0x0009dbd7, - 0x000ddbd7, - 0x0011dbd7, - 0x0015dbd7, - 0x0019dbd7, - 0x001ddbd7, - 0x0001e3d7, - 0x0005e3d7, - 0x0009e3d7, - 0x000de3d7, - 0x0011e3d7, - 0x0015e3d7, - 0x0019e3d7, - 0x001de3d7, - 0x0001ebd7, - 0x0005ebd7, - 0x0009ebd7, - 0x000debd7, - 0x0011ebd7, - 0x0015ebd7, - 0x0019ebd7, - 0x001debd7, - 0x0001f3d7, - 0x0005f3d7, - 0x0009f3d7, - 0x000df3d7, - 0x0011f3d7, - 0x0015f3d7, - 0x0019f3d7, - 0x001df3d7, - 0x0001fbd7, - 0x0005fbd7, - 0x0009fbd7, - 0x000dfbd7, - 0x0011fbd7, - 0x0015fbd7, - 0x0019fbd7, - 0x001dfbd7, - 0x0001c3e7, - 0x0005c3e7, - 0x0009c3e7, - 0x000dc3e7, - 0x0011c3e7, - 0x0015c3e7, - 0x0019c3e7, - 0x001dc3e7, - 0x0001cbe7, - 0x0005cbe7, - 0x0009cbe7, - 0x000dcbe7, - 0x0011cbe7, - 0x0015cbe7, - 0x0019cbe7, - 0x001dcbe7, - 0x0001d3e7, - 0x0005d3e7, - 0x0009d3e7, - 0x000dd3e7, - 0x0011d3e7, - 0x0015d3e7, - 0x0019d3e7, - 0x001dd3e7, - 0x0001dbe7, - 0x0005dbe7, - 0x0009dbe7, - 0x000ddbe7, - 0x0011dbe7, - 0x0015dbe7, - 0x0019dbe7, - 0x001ddbe7, - 0x0001e3e7, - 0x0005e3e7, - 0x0009e3e7, - 0x000de3e7, - 0x0011e3e7, - 0x0015e3e7, - 0x0019e3e7, - 0x001de3e7, - 0x0001ebe7, - 0x0005ebe7, - 0x0009ebe7, - 0x000debe7, - 0x0011ebe7, - 0x0015ebe7, - 0x0019ebe7, - 0x001debe7, - 0x0001f3e7, - 0x0005f3e7, - 0x0009f3e7, - 0x000df3e7, - 0x0011f3e7, - 0x0015f3e7, - 0x0019f3e7, - 0x001df3e7, - 0x0001fbe7, - 0x0005fbe7, - 0x0009fbe7, - 0x000dfbe7, - 0x0011fbe7, - 0x0015fbe7, - 0x0019fbe7, - 0x001dfbe7, - 0x0001c3f7, - 0x0005c3f7, - 0x0009c3f7, - 0x000dc3f7, - 0x0011c3f7, - 0x0015c3f7, - 0x0019c3f7, - 0x001dc3f7, - 0x0001cbf7, - 0x0005cbf7, - 0x0009cbf7, - 0x000dcbf7, - 0x0011cbf7, - 0x0015cbf7, - 0x0019cbf7, - 0x001dcbf7, - 0x0001d3f7, - 0x0005d3f7, - 0x0009d3f7, - 0x000dd3f7, - 0x0011d3f7, - 0x0015d3f7, - 0x0019d3f7, - 0x001dd3f7, - 0x0001dbf7, - 0x0005dbf7, - 0x0009dbf7, - 0x000ddbf7, - 0x0011dbf7, - 0x0015dbf7, - 0x0019dbf7, - 0x001ddbf7, - 0x0001e3f7, - 0x0005e3f7, - 0x0009e3f7, - 0x000de3f7, - 0x0011e3f7, - 0x0015e3f7, - 0x0019e3f7, - 0x001de3f7, - 0x0001ebf7, - 0x0005ebf7, - 0x0009ebf7, - 0x000debf7, - 0x0011ebf7, - 0x0015ebf7, - 0x0019ebf7, - 0x001debf7, - 0x0001f3f7, - 0x0005f3f7, - 0x0009f3f7, - 0x000df3f7, - 0x0011f3f7, - 0x0015f3f7, - 0x0019f3f7, - 0x001df3f7, - 0x0001fbf7, - 0x0005fbf7, - 0x0009fbf7, - 0x000dfbf7, - 0x0011fbf7, - 0x0015fbf7, - 0x0019fbf7, - 0x001dfbf7, - 0x00e1c387, - 0x02e1c387, - 0x04e1c387, - 0x06e1c387, - 0x08e1c387, - 0x0ae1c387, - 0x0ce1c387, - 0x0ee1c387, - 0x00e5c387, - 0x02e5c387, - 0x04e5c387, - 0x06e5c387, - 0x08e5c387, - 0x0ae5c387, - 0x0ce5c387, - 0x0ee5c387, - 0x00e9c387, - 0x02e9c387, - 0x04e9c387, - 0x06e9c387, - 0x08e9c387, - 0x0ae9c387, - 0x0ce9c387, - 0x0ee9c387, - 0x00edc387, - 0x02edc387, - 0x04edc387, - 0x06edc387, - 0x08edc387, - 0x0aedc387, - 0x0cedc387, - 0x0eedc387, - 0x00f1c387, - 0x02f1c387, - 0x04f1c387, - 0x06f1c387, - 0x08f1c387, - 0x0af1c387, - 0x0cf1c387, - 0x0ef1c387, - 0x00f5c387, - 0x02f5c387, - 0x04f5c387, - 0x06f5c387, - 0x08f5c387, - 0x0af5c387, - 0x0cf5c387, - 0x0ef5c387, - 0x00f9c387, - 0x02f9c387, - 0x04f9c387, - 0x06f9c387, - 0x08f9c387, - 0x0af9c387, - 0x0cf9c387, - 0x0ef9c387, - 0x00fdc387, - 0x02fdc387, - 0x04fdc387, - 0x06fdc387, - 0x08fdc387, - 0x0afdc387, - 0x0cfdc387, - 0x0efdc387, - 0x00e1cb87, - 0x02e1cb87, - 0x04e1cb87, - 0x06e1cb87, - 0x08e1cb87, - 0x0ae1cb87, - 0x0ce1cb87, - 0x0ee1cb87, - 0x00e5cb87, - 0x02e5cb87, - 0x04e5cb87, - 0x06e5cb87, - 0x08e5cb87, - 0x0ae5cb87, - 0x0ce5cb87, - 0x0ee5cb87, - 0x00e9cb87, - 0x02e9cb87, - 0x04e9cb87, - 0x06e9cb87, - 0x08e9cb87, - 0x0ae9cb87, - 0x0ce9cb87, - 0x0ee9cb87, - 0x00edcb87, - 0x02edcb87, - 0x04edcb87, - 0x06edcb87, - 0x08edcb87, - 0x0aedcb87, - 0x0cedcb87, - 0x0eedcb87, - 0x00f1cb87, - 0x02f1cb87, - 0x04f1cb87, - 0x06f1cb87, - 0x08f1cb87, - 0x0af1cb87, - 0x0cf1cb87, - 0x0ef1cb87, - 0x00f5cb87, - 0x02f5cb87, - 0x04f5cb87, - 0x06f5cb87, - 0x08f5cb87, - 0x0af5cb87, - 0x0cf5cb87, - 0x0ef5cb87, - 0x00f9cb87, - 0x02f9cb87, - 0x04f9cb87, - 0x06f9cb87, - 0x08f9cb87, -} - -var kZeroRepsDepth = [numCommandSymbols]uint32{ - 0, - 4, - 8, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 7, - 11, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 14, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 21, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, - 28, -} - -var kNonZeroRepsBits = [numCommandSymbols]uint64{ - 0x0000000b, - 0x0000001b, - 0x0000002b, - 0x0000003b, - 0x000002cb, - 0x000006cb, - 0x00000acb, - 0x00000ecb, - 0x000002db, - 0x000006db, - 0x00000adb, - 0x00000edb, - 0x000002eb, - 0x000006eb, - 0x00000aeb, - 0x00000eeb, - 0x000002fb, - 0x000006fb, - 0x00000afb, - 0x00000efb, - 0x0000b2cb, - 0x0001b2cb, - 0x0002b2cb, - 0x0003b2cb, - 0x0000b6cb, - 0x0001b6cb, - 0x0002b6cb, - 0x0003b6cb, - 0x0000bacb, - 0x0001bacb, - 0x0002bacb, - 0x0003bacb, - 0x0000becb, - 0x0001becb, - 0x0002becb, - 0x0003becb, - 0x0000b2db, - 0x0001b2db, - 0x0002b2db, - 0x0003b2db, - 0x0000b6db, - 0x0001b6db, - 0x0002b6db, - 0x0003b6db, - 0x0000badb, - 0x0001badb, - 0x0002badb, - 0x0003badb, - 0x0000bedb, - 0x0001bedb, - 0x0002bedb, - 0x0003bedb, - 0x0000b2eb, - 0x0001b2eb, - 0x0002b2eb, - 0x0003b2eb, - 0x0000b6eb, - 0x0001b6eb, - 0x0002b6eb, - 0x0003b6eb, - 0x0000baeb, - 0x0001baeb, - 0x0002baeb, - 0x0003baeb, - 0x0000beeb, - 0x0001beeb, - 0x0002beeb, - 0x0003beeb, - 0x0000b2fb, - 0x0001b2fb, - 0x0002b2fb, - 0x0003b2fb, - 0x0000b6fb, - 0x0001b6fb, - 0x0002b6fb, - 0x0003b6fb, - 0x0000bafb, - 0x0001bafb, - 0x0002bafb, - 0x0003bafb, - 0x0000befb, - 0x0001befb, - 0x0002befb, - 0x0003befb, - 0x002cb2cb, - 0x006cb2cb, - 0x00acb2cb, - 0x00ecb2cb, - 0x002db2cb, - 0x006db2cb, - 0x00adb2cb, - 0x00edb2cb, - 0x002eb2cb, - 0x006eb2cb, - 0x00aeb2cb, - 0x00eeb2cb, - 0x002fb2cb, - 0x006fb2cb, - 0x00afb2cb, - 0x00efb2cb, - 0x002cb6cb, - 0x006cb6cb, - 0x00acb6cb, - 0x00ecb6cb, - 0x002db6cb, - 0x006db6cb, - 0x00adb6cb, - 0x00edb6cb, - 0x002eb6cb, - 0x006eb6cb, - 0x00aeb6cb, - 0x00eeb6cb, - 0x002fb6cb, - 0x006fb6cb, - 0x00afb6cb, - 0x00efb6cb, - 0x002cbacb, - 0x006cbacb, - 0x00acbacb, - 0x00ecbacb, - 0x002dbacb, - 0x006dbacb, - 0x00adbacb, - 0x00edbacb, - 0x002ebacb, - 0x006ebacb, - 0x00aebacb, - 0x00eebacb, - 0x002fbacb, - 0x006fbacb, - 0x00afbacb, - 0x00efbacb, - 0x002cbecb, - 0x006cbecb, - 0x00acbecb, - 0x00ecbecb, - 0x002dbecb, - 0x006dbecb, - 0x00adbecb, - 0x00edbecb, - 0x002ebecb, - 0x006ebecb, - 0x00aebecb, - 0x00eebecb, - 0x002fbecb, - 0x006fbecb, - 0x00afbecb, - 0x00efbecb, - 0x002cb2db, - 0x006cb2db, - 0x00acb2db, - 0x00ecb2db, - 0x002db2db, - 0x006db2db, - 0x00adb2db, - 0x00edb2db, - 0x002eb2db, - 0x006eb2db, - 0x00aeb2db, - 0x00eeb2db, - 0x002fb2db, - 0x006fb2db, - 0x00afb2db, - 0x00efb2db, - 0x002cb6db, - 0x006cb6db, - 0x00acb6db, - 0x00ecb6db, - 0x002db6db, - 0x006db6db, - 0x00adb6db, - 0x00edb6db, - 0x002eb6db, - 0x006eb6db, - 0x00aeb6db, - 0x00eeb6db, - 0x002fb6db, - 0x006fb6db, - 0x00afb6db, - 0x00efb6db, - 0x002cbadb, - 0x006cbadb, - 0x00acbadb, - 0x00ecbadb, - 0x002dbadb, - 0x006dbadb, - 0x00adbadb, - 0x00edbadb, - 0x002ebadb, - 0x006ebadb, - 0x00aebadb, - 0x00eebadb, - 0x002fbadb, - 0x006fbadb, - 0x00afbadb, - 0x00efbadb, - 0x002cbedb, - 0x006cbedb, - 0x00acbedb, - 0x00ecbedb, - 0x002dbedb, - 0x006dbedb, - 0x00adbedb, - 0x00edbedb, - 0x002ebedb, - 0x006ebedb, - 0x00aebedb, - 0x00eebedb, - 0x002fbedb, - 0x006fbedb, - 0x00afbedb, - 0x00efbedb, - 0x002cb2eb, - 0x006cb2eb, - 0x00acb2eb, - 0x00ecb2eb, - 0x002db2eb, - 0x006db2eb, - 0x00adb2eb, - 0x00edb2eb, - 0x002eb2eb, - 0x006eb2eb, - 0x00aeb2eb, - 0x00eeb2eb, - 0x002fb2eb, - 0x006fb2eb, - 0x00afb2eb, - 0x00efb2eb, - 0x002cb6eb, - 0x006cb6eb, - 0x00acb6eb, - 0x00ecb6eb, - 0x002db6eb, - 0x006db6eb, - 0x00adb6eb, - 0x00edb6eb, - 0x002eb6eb, - 0x006eb6eb, - 0x00aeb6eb, - 0x00eeb6eb, - 0x002fb6eb, - 0x006fb6eb, - 0x00afb6eb, - 0x00efb6eb, - 0x002cbaeb, - 0x006cbaeb, - 0x00acbaeb, - 0x00ecbaeb, - 0x002dbaeb, - 0x006dbaeb, - 0x00adbaeb, - 0x00edbaeb, - 0x002ebaeb, - 0x006ebaeb, - 0x00aebaeb, - 0x00eebaeb, - 0x002fbaeb, - 0x006fbaeb, - 0x00afbaeb, - 0x00efbaeb, - 0x002cbeeb, - 0x006cbeeb, - 0x00acbeeb, - 0x00ecbeeb, - 0x002dbeeb, - 0x006dbeeb, - 0x00adbeeb, - 0x00edbeeb, - 0x002ebeeb, - 0x006ebeeb, - 0x00aebeeb, - 0x00eebeeb, - 0x002fbeeb, - 0x006fbeeb, - 0x00afbeeb, - 0x00efbeeb, - 0x002cb2fb, - 0x006cb2fb, - 0x00acb2fb, - 0x00ecb2fb, - 0x002db2fb, - 0x006db2fb, - 0x00adb2fb, - 0x00edb2fb, - 0x002eb2fb, - 0x006eb2fb, - 0x00aeb2fb, - 0x00eeb2fb, - 0x002fb2fb, - 0x006fb2fb, - 0x00afb2fb, - 0x00efb2fb, - 0x002cb6fb, - 0x006cb6fb, - 0x00acb6fb, - 0x00ecb6fb, - 0x002db6fb, - 0x006db6fb, - 0x00adb6fb, - 0x00edb6fb, - 0x002eb6fb, - 0x006eb6fb, - 0x00aeb6fb, - 0x00eeb6fb, - 0x002fb6fb, - 0x006fb6fb, - 0x00afb6fb, - 0x00efb6fb, - 0x002cbafb, - 0x006cbafb, - 0x00acbafb, - 0x00ecbafb, - 0x002dbafb, - 0x006dbafb, - 0x00adbafb, - 0x00edbafb, - 0x002ebafb, - 0x006ebafb, - 0x00aebafb, - 0x00eebafb, - 0x002fbafb, - 0x006fbafb, - 0x00afbafb, - 0x00efbafb, - 0x002cbefb, - 0x006cbefb, - 0x00acbefb, - 0x00ecbefb, - 0x002dbefb, - 0x006dbefb, - 0x00adbefb, - 0x00edbefb, - 0x002ebefb, - 0x006ebefb, - 0x00aebefb, - 0x00eebefb, - 0x002fbefb, - 0x006fbefb, - 0x00afbefb, - 0x00efbefb, - 0x0b2cb2cb, - 0x1b2cb2cb, - 0x2b2cb2cb, - 0x3b2cb2cb, - 0x0b6cb2cb, - 0x1b6cb2cb, - 0x2b6cb2cb, - 0x3b6cb2cb, - 0x0bacb2cb, - 0x1bacb2cb, - 0x2bacb2cb, - 0x3bacb2cb, - 0x0becb2cb, - 0x1becb2cb, - 0x2becb2cb, - 0x3becb2cb, - 0x0b2db2cb, - 0x1b2db2cb, - 0x2b2db2cb, - 0x3b2db2cb, - 0x0b6db2cb, - 0x1b6db2cb, - 0x2b6db2cb, - 0x3b6db2cb, - 0x0badb2cb, - 0x1badb2cb, - 0x2badb2cb, - 0x3badb2cb, - 0x0bedb2cb, - 0x1bedb2cb, - 0x2bedb2cb, - 0x3bedb2cb, - 0x0b2eb2cb, - 0x1b2eb2cb, - 0x2b2eb2cb, - 0x3b2eb2cb, - 0x0b6eb2cb, - 0x1b6eb2cb, - 0x2b6eb2cb, - 0x3b6eb2cb, - 0x0baeb2cb, - 0x1baeb2cb, - 0x2baeb2cb, - 0x3baeb2cb, - 0x0beeb2cb, - 0x1beeb2cb, - 0x2beeb2cb, - 0x3beeb2cb, - 0x0b2fb2cb, - 0x1b2fb2cb, - 0x2b2fb2cb, - 0x3b2fb2cb, - 0x0b6fb2cb, - 0x1b6fb2cb, - 0x2b6fb2cb, - 0x3b6fb2cb, - 0x0bafb2cb, - 0x1bafb2cb, - 0x2bafb2cb, - 0x3bafb2cb, - 0x0befb2cb, - 0x1befb2cb, - 0x2befb2cb, - 0x3befb2cb, - 0x0b2cb6cb, - 0x1b2cb6cb, - 0x2b2cb6cb, - 0x3b2cb6cb, - 0x0b6cb6cb, - 0x1b6cb6cb, - 0x2b6cb6cb, - 0x3b6cb6cb, - 0x0bacb6cb, - 0x1bacb6cb, - 0x2bacb6cb, - 0x3bacb6cb, - 0x0becb6cb, - 0x1becb6cb, - 0x2becb6cb, - 0x3becb6cb, - 0x0b2db6cb, - 0x1b2db6cb, - 0x2b2db6cb, - 0x3b2db6cb, - 0x0b6db6cb, - 0x1b6db6cb, - 0x2b6db6cb, - 0x3b6db6cb, - 0x0badb6cb, - 0x1badb6cb, - 0x2badb6cb, - 0x3badb6cb, - 0x0bedb6cb, - 0x1bedb6cb, - 0x2bedb6cb, - 0x3bedb6cb, - 0x0b2eb6cb, - 0x1b2eb6cb, - 0x2b2eb6cb, - 0x3b2eb6cb, - 0x0b6eb6cb, - 0x1b6eb6cb, - 0x2b6eb6cb, - 0x3b6eb6cb, - 0x0baeb6cb, - 0x1baeb6cb, - 0x2baeb6cb, - 0x3baeb6cb, - 0x0beeb6cb, - 0x1beeb6cb, - 0x2beeb6cb, - 0x3beeb6cb, - 0x0b2fb6cb, - 0x1b2fb6cb, - 0x2b2fb6cb, - 0x3b2fb6cb, - 0x0b6fb6cb, - 0x1b6fb6cb, - 0x2b6fb6cb, - 0x3b6fb6cb, - 0x0bafb6cb, - 0x1bafb6cb, - 0x2bafb6cb, - 0x3bafb6cb, - 0x0befb6cb, - 0x1befb6cb, - 0x2befb6cb, - 0x3befb6cb, - 0x0b2cbacb, - 0x1b2cbacb, - 0x2b2cbacb, - 0x3b2cbacb, - 0x0b6cbacb, - 0x1b6cbacb, - 0x2b6cbacb, - 0x3b6cbacb, - 0x0bacbacb, - 0x1bacbacb, - 0x2bacbacb, - 0x3bacbacb, - 0x0becbacb, - 0x1becbacb, - 0x2becbacb, - 0x3becbacb, - 0x0b2dbacb, - 0x1b2dbacb, - 0x2b2dbacb, - 0x3b2dbacb, - 0x0b6dbacb, - 0x1b6dbacb, - 0x2b6dbacb, - 0x3b6dbacb, - 0x0badbacb, - 0x1badbacb, - 0x2badbacb, - 0x3badbacb, - 0x0bedbacb, - 0x1bedbacb, - 0x2bedbacb, - 0x3bedbacb, - 0x0b2ebacb, - 0x1b2ebacb, - 0x2b2ebacb, - 0x3b2ebacb, - 0x0b6ebacb, - 0x1b6ebacb, - 0x2b6ebacb, - 0x3b6ebacb, - 0x0baebacb, - 0x1baebacb, - 0x2baebacb, - 0x3baebacb, - 0x0beebacb, - 0x1beebacb, - 0x2beebacb, - 0x3beebacb, - 0x0b2fbacb, - 0x1b2fbacb, - 0x2b2fbacb, - 0x3b2fbacb, - 0x0b6fbacb, - 0x1b6fbacb, - 0x2b6fbacb, - 0x3b6fbacb, - 0x0bafbacb, - 0x1bafbacb, - 0x2bafbacb, - 0x3bafbacb, - 0x0befbacb, - 0x1befbacb, - 0x2befbacb, - 0x3befbacb, - 0x0b2cbecb, - 0x1b2cbecb, - 0x2b2cbecb, - 0x3b2cbecb, - 0x0b6cbecb, - 0x1b6cbecb, - 0x2b6cbecb, - 0x3b6cbecb, - 0x0bacbecb, - 0x1bacbecb, - 0x2bacbecb, - 0x3bacbecb, - 0x0becbecb, - 0x1becbecb, - 0x2becbecb, - 0x3becbecb, - 0x0b2dbecb, - 0x1b2dbecb, - 0x2b2dbecb, - 0x3b2dbecb, - 0x0b6dbecb, - 0x1b6dbecb, - 0x2b6dbecb, - 0x3b6dbecb, - 0x0badbecb, - 0x1badbecb, - 0x2badbecb, - 0x3badbecb, - 0x0bedbecb, - 0x1bedbecb, - 0x2bedbecb, - 0x3bedbecb, - 0x0b2ebecb, - 0x1b2ebecb, - 0x2b2ebecb, - 0x3b2ebecb, - 0x0b6ebecb, - 0x1b6ebecb, - 0x2b6ebecb, - 0x3b6ebecb, - 0x0baebecb, - 0x1baebecb, - 0x2baebecb, - 0x3baebecb, - 0x0beebecb, - 0x1beebecb, - 0x2beebecb, - 0x3beebecb, - 0x0b2fbecb, - 0x1b2fbecb, - 0x2b2fbecb, - 0x3b2fbecb, - 0x0b6fbecb, - 0x1b6fbecb, - 0x2b6fbecb, - 0x3b6fbecb, - 0x0bafbecb, - 0x1bafbecb, - 0x2bafbecb, - 0x3bafbecb, - 0x0befbecb, - 0x1befbecb, - 0x2befbecb, - 0x3befbecb, - 0x0b2cb2db, - 0x1b2cb2db, - 0x2b2cb2db, - 0x3b2cb2db, - 0x0b6cb2db, - 0x1b6cb2db, - 0x2b6cb2db, - 0x3b6cb2db, - 0x0bacb2db, - 0x1bacb2db, - 0x2bacb2db, - 0x3bacb2db, - 0x0becb2db, - 0x1becb2db, - 0x2becb2db, - 0x3becb2db, - 0x0b2db2db, - 0x1b2db2db, - 0x2b2db2db, - 0x3b2db2db, - 0x0b6db2db, - 0x1b6db2db, - 0x2b6db2db, - 0x3b6db2db, - 0x0badb2db, - 0x1badb2db, - 0x2badb2db, - 0x3badb2db, - 0x0bedb2db, - 0x1bedb2db, - 0x2bedb2db, - 0x3bedb2db, - 0x0b2eb2db, - 0x1b2eb2db, - 0x2b2eb2db, - 0x3b2eb2db, - 0x0b6eb2db, - 0x1b6eb2db, - 0x2b6eb2db, - 0x3b6eb2db, - 0x0baeb2db, - 0x1baeb2db, - 0x2baeb2db, - 0x3baeb2db, - 0x0beeb2db, - 0x1beeb2db, - 0x2beeb2db, - 0x3beeb2db, - 0x0b2fb2db, - 0x1b2fb2db, - 0x2b2fb2db, - 0x3b2fb2db, - 0x0b6fb2db, - 0x1b6fb2db, - 0x2b6fb2db, - 0x3b6fb2db, - 0x0bafb2db, - 0x1bafb2db, - 0x2bafb2db, - 0x3bafb2db, - 0x0befb2db, - 0x1befb2db, - 0x2befb2db, - 0x3befb2db, - 0x0b2cb6db, - 0x1b2cb6db, - 0x2b2cb6db, - 0x3b2cb6db, - 0x0b6cb6db, - 0x1b6cb6db, - 0x2b6cb6db, - 0x3b6cb6db, - 0x0bacb6db, - 0x1bacb6db, - 0x2bacb6db, - 0x3bacb6db, - 0x0becb6db, - 0x1becb6db, - 0x2becb6db, - 0x3becb6db, - 0x0b2db6db, - 0x1b2db6db, - 0x2b2db6db, - 0x3b2db6db, - 0x0b6db6db, - 0x1b6db6db, - 0x2b6db6db, - 0x3b6db6db, - 0x0badb6db, - 0x1badb6db, - 0x2badb6db, - 0x3badb6db, - 0x0bedb6db, - 0x1bedb6db, - 0x2bedb6db, - 0x3bedb6db, - 0x0b2eb6db, - 0x1b2eb6db, - 0x2b2eb6db, - 0x3b2eb6db, - 0x0b6eb6db, - 0x1b6eb6db, - 0x2b6eb6db, - 0x3b6eb6db, - 0x0baeb6db, - 0x1baeb6db, - 0x2baeb6db, - 0x3baeb6db, -} - -var kNonZeroRepsDepth = [numCommandSymbols]uint32{ - 6, - 6, - 6, - 6, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 12, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 18, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 24, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, - 30, -} - -var kStaticCommandCodeBits = [numCommandSymbols]uint16{ - 0, - 256, - 128, - 384, - 64, - 320, - 192, - 448, - 32, - 288, - 160, - 416, - 96, - 352, - 224, - 480, - 16, - 272, - 144, - 400, - 80, - 336, - 208, - 464, - 48, - 304, - 176, - 432, - 112, - 368, - 240, - 496, - 8, - 264, - 136, - 392, - 72, - 328, - 200, - 456, - 40, - 296, - 168, - 424, - 104, - 360, - 232, - 488, - 24, - 280, - 152, - 408, - 88, - 344, - 216, - 472, - 56, - 312, - 184, - 440, - 120, - 376, - 248, - 504, - 4, - 260, - 132, - 388, - 68, - 324, - 196, - 452, - 36, - 292, - 164, - 420, - 100, - 356, - 228, - 484, - 20, - 276, - 148, - 404, - 84, - 340, - 212, - 468, - 52, - 308, - 180, - 436, - 116, - 372, - 244, - 500, - 12, - 268, - 140, - 396, - 76, - 332, - 204, - 460, - 44, - 300, - 172, - 428, - 108, - 364, - 236, - 492, - 28, - 284, - 156, - 412, - 92, - 348, - 220, - 476, - 60, - 316, - 188, - 444, - 124, - 380, - 252, - 508, - 2, - 258, - 130, - 386, - 66, - 322, - 194, - 450, - 34, - 290, - 162, - 418, - 98, - 354, - 226, - 482, - 18, - 274, - 146, - 402, - 82, - 338, - 210, - 466, - 50, - 306, - 178, - 434, - 114, - 370, - 242, - 498, - 10, - 266, - 138, - 394, - 74, - 330, - 202, - 458, - 42, - 298, - 170, - 426, - 106, - 362, - 234, - 490, - 26, - 282, - 154, - 410, - 90, - 346, - 218, - 474, - 58, - 314, - 186, - 442, - 122, - 378, - 250, - 506, - 6, - 262, - 134, - 390, - 70, - 326, - 198, - 454, - 38, - 294, - 166, - 422, - 102, - 358, - 230, - 486, - 22, - 278, - 150, - 406, - 86, - 342, - 214, - 470, - 54, - 310, - 182, - 438, - 118, - 374, - 246, - 502, - 14, - 270, - 142, - 398, - 78, - 334, - 206, - 462, - 46, - 302, - 174, - 430, - 110, - 366, - 238, - 494, - 30, - 286, - 158, - 414, - 94, - 350, - 222, - 478, - 62, - 318, - 190, - 446, - 126, - 382, - 254, - 510, - 1, - 257, - 129, - 385, - 65, - 321, - 193, - 449, - 33, - 289, - 161, - 417, - 97, - 353, - 225, - 481, - 17, - 273, - 145, - 401, - 81, - 337, - 209, - 465, - 49, - 305, - 177, - 433, - 113, - 369, - 241, - 497, - 9, - 265, - 137, - 393, - 73, - 329, - 201, - 457, - 41, - 297, - 169, - 425, - 105, - 361, - 233, - 489, - 25, - 281, - 153, - 409, - 89, - 345, - 217, - 473, - 57, - 313, - 185, - 441, - 121, - 377, - 249, - 505, - 5, - 261, - 133, - 389, - 69, - 325, - 197, - 453, - 37, - 293, - 165, - 421, - 101, - 357, - 229, - 485, - 21, - 277, - 149, - 405, - 85, - 341, - 213, - 469, - 53, - 309, - 181, - 437, - 117, - 373, - 245, - 501, - 13, - 269, - 141, - 397, - 77, - 333, - 205, - 461, - 45, - 301, - 173, - 429, - 109, - 365, - 237, - 493, - 29, - 285, - 157, - 413, - 93, - 349, - 221, - 477, - 61, - 317, - 189, - 445, - 125, - 381, - 253, - 509, - 3, - 259, - 131, - 387, - 67, - 323, - 195, - 451, - 35, - 291, - 163, - 419, - 99, - 355, - 227, - 483, - 19, - 275, - 147, - 403, - 83, - 339, - 211, - 467, - 51, - 307, - 179, - 435, - 115, - 371, - 243, - 499, - 11, - 267, - 139, - 395, - 75, - 331, - 203, - 459, - 43, - 299, - 171, - 427, - 107, - 363, - 235, - 491, - 27, - 283, - 155, - 411, - 91, - 347, - 219, - 475, - 59, - 315, - 187, - 443, - 123, - 379, - 251, - 507, - 7, - 1031, - 519, - 1543, - 263, - 1287, - 775, - 1799, - 135, - 1159, - 647, - 1671, - 391, - 1415, - 903, - 1927, - 71, - 1095, - 583, - 1607, - 327, - 1351, - 839, - 1863, - 199, - 1223, - 711, - 1735, - 455, - 1479, - 967, - 1991, - 39, - 1063, - 551, - 1575, - 295, - 1319, - 807, - 1831, - 167, - 1191, - 679, - 1703, - 423, - 1447, - 935, - 1959, - 103, - 1127, - 615, - 1639, - 359, - 1383, - 871, - 1895, - 231, - 1255, - 743, - 1767, - 487, - 1511, - 999, - 2023, - 23, - 1047, - 535, - 1559, - 279, - 1303, - 791, - 1815, - 151, - 1175, - 663, - 1687, - 407, - 1431, - 919, - 1943, - 87, - 1111, - 599, - 1623, - 343, - 1367, - 855, - 1879, - 215, - 1239, - 727, - 1751, - 471, - 1495, - 983, - 2007, - 55, - 1079, - 567, - 1591, - 311, - 1335, - 823, - 1847, - 183, - 1207, - 695, - 1719, - 439, - 1463, - 951, - 1975, - 119, - 1143, - 631, - 1655, - 375, - 1399, - 887, - 1911, - 247, - 1271, - 759, - 1783, - 503, - 1527, - 1015, - 2039, - 15, - 1039, - 527, - 1551, - 271, - 1295, - 783, - 1807, - 143, - 1167, - 655, - 1679, - 399, - 1423, - 911, - 1935, - 79, - 1103, - 591, - 1615, - 335, - 1359, - 847, - 1871, - 207, - 1231, - 719, - 1743, - 463, - 1487, - 975, - 1999, - 47, - 1071, - 559, - 1583, - 303, - 1327, - 815, - 1839, - 175, - 1199, - 687, - 1711, - 431, - 1455, - 943, - 1967, - 111, - 1135, - 623, - 1647, - 367, - 1391, - 879, - 1903, - 239, - 1263, - 751, - 1775, - 495, - 1519, - 1007, - 2031, - 31, - 1055, - 543, - 1567, - 287, - 1311, - 799, - 1823, - 159, - 1183, - 671, - 1695, - 415, - 1439, - 927, - 1951, - 95, - 1119, - 607, - 1631, - 351, - 1375, - 863, - 1887, - 223, - 1247, - 735, - 1759, - 479, - 1503, - 991, - 2015, - 63, - 1087, - 575, - 1599, - 319, - 1343, - 831, - 1855, - 191, - 1215, - 703, - 1727, - 447, - 1471, - 959, - 1983, - 127, - 1151, - 639, - 1663, - 383, - 1407, - 895, - 1919, - 255, - 1279, - 767, - 1791, - 511, - 1535, - 1023, - 2047, -} - -func storeStaticCommandHuffmanTree(storage_ix *uint, storage []byte) { - writeBits(56, 0x92624416307003, storage_ix, storage) - writeBits(3, 0x00000000, storage_ix, storage) -} - -var kStaticDistanceCodeBits = [64]uint16{ - 0, - 32, - 16, - 48, - 8, - 40, - 24, - 56, - 4, - 36, - 20, - 52, - 12, - 44, - 28, - 60, - 2, - 34, - 18, - 50, - 10, - 42, - 26, - 58, - 6, - 38, - 22, - 54, - 14, - 46, - 30, - 62, - 1, - 33, - 17, - 49, - 9, - 41, - 25, - 57, - 5, - 37, - 21, - 53, - 13, - 45, - 29, - 61, - 3, - 35, - 19, - 51, - 11, - 43, - 27, - 59, - 7, - 39, - 23, - 55, - 15, - 47, - 31, - 63, -} - -func storeStaticDistanceHuffmanTree(storage_ix *uint, storage []byte) { - writeBits(28, 0x0369DC03, storage_ix, storage) -} diff --git a/src/vendor/github.com/andybalholm/brotli/fast_log.go b/src/vendor/github.com/andybalholm/brotli/fast_log.go deleted file mode 100644 index 9d6607f7..00000000 --- a/src/vendor/github.com/andybalholm/brotli/fast_log.go +++ /dev/null @@ -1,290 +0,0 @@ -package brotli - -import ( - "math" - "math/bits" -) - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Utilities for fast computation of logarithms. */ - -func log2FloorNonZero(n uint) uint32 { - return uint32(bits.Len(n)) - 1 -} - -/* A lookup table for small values of log2(int) to be used in entropy - computation. - - ", ".join(["%.16ff" % x for x in [0.0]+[log2(x) for x in range(1, 256)]]) */ -var kLog2Table = []float32{ - 0.0000000000000000, - 0.0000000000000000, - 1.0000000000000000, - 1.5849625007211563, - 2.0000000000000000, - 2.3219280948873622, - 2.5849625007211561, - 2.8073549220576042, - 3.0000000000000000, - 3.1699250014423126, - 3.3219280948873626, - 3.4594316186372978, - 3.5849625007211565, - 3.7004397181410922, - 3.8073549220576037, - 3.9068905956085187, - 4.0000000000000000, - 4.0874628412503400, - 4.1699250014423122, - 4.2479275134435852, - 4.3219280948873626, - 4.3923174227787607, - 4.4594316186372973, - 4.5235619560570131, - 4.5849625007211570, - 4.6438561897747244, - 4.7004397181410926, - 4.7548875021634691, - 4.8073549220576037, - 4.8579809951275728, - 4.9068905956085187, - 4.9541963103868758, - 5.0000000000000000, - 5.0443941193584534, - 5.0874628412503400, - 5.1292830169449664, - 5.1699250014423122, - 5.2094533656289501, - 5.2479275134435852, - 5.2854022188622487, - 5.3219280948873626, - 5.3575520046180838, - 5.3923174227787607, - 5.4262647547020979, - 5.4594316186372973, - 5.4918530963296748, - 5.5235619560570131, - 5.5545888516776376, - 5.5849625007211570, - 5.6147098441152083, - 5.6438561897747244, - 5.6724253419714961, - 5.7004397181410926, - 5.7279204545631996, - 5.7548875021634691, - 5.7813597135246599, - 5.8073549220576046, - 5.8328900141647422, - 5.8579809951275719, - 5.8826430493618416, - 5.9068905956085187, - 5.9307373375628867, - 5.9541963103868758, - 5.9772799234999168, - 6.0000000000000000, - 6.0223678130284544, - 6.0443941193584534, - 6.0660891904577721, - 6.0874628412503400, - 6.1085244567781700, - 6.1292830169449672, - 6.1497471195046822, - 6.1699250014423122, - 6.1898245588800176, - 6.2094533656289510, - 6.2288186904958804, - 6.2479275134435861, - 6.2667865406949019, - 6.2854022188622487, - 6.3037807481771031, - 6.3219280948873617, - 6.3398500028846252, - 6.3575520046180847, - 6.3750394313469254, - 6.3923174227787598, - 6.4093909361377026, - 6.4262647547020979, - 6.4429434958487288, - 6.4594316186372982, - 6.4757334309663976, - 6.4918530963296748, - 6.5077946401986964, - 6.5235619560570131, - 6.5391588111080319, - 6.5545888516776376, - 6.5698556083309478, - 6.5849625007211561, - 6.5999128421871278, - 6.6147098441152092, - 6.6293566200796095, - 6.6438561897747253, - 6.6582114827517955, - 6.6724253419714952, - 6.6865005271832185, - 6.7004397181410917, - 6.7142455176661224, - 6.7279204545631988, - 6.7414669864011465, - 6.7548875021634691, - 6.7681843247769260, - 6.7813597135246599, - 6.7944158663501062, - 6.8073549220576037, - 6.8201789624151887, - 6.8328900141647422, - 6.8454900509443757, - 6.8579809951275719, - 6.8703647195834048, - 6.8826430493618416, - 6.8948177633079437, - 6.9068905956085187, - 6.9188632372745955, - 6.9307373375628867, - 6.9425145053392399, - 6.9541963103868758, - 6.9657842846620879, - 6.9772799234999168, - 6.9886846867721664, - 7.0000000000000000, - 7.0112272554232540, - 7.0223678130284544, - 7.0334230015374501, - 7.0443941193584534, - 7.0552824355011898, - 7.0660891904577721, - 7.0768155970508317, - 7.0874628412503400, - 7.0980320829605272, - 7.1085244567781700, - 7.1189410727235076, - 7.1292830169449664, - 7.1395513523987937, - 7.1497471195046822, - 7.1598713367783891, - 7.1699250014423130, - 7.1799090900149345, - 7.1898245588800176, - 7.1996723448363644, - 7.2094533656289492, - 7.2191685204621621, - 7.2288186904958804, - 7.2384047393250794, - 7.2479275134435861, - 7.2573878426926521, - 7.2667865406949019, - 7.2761244052742384, - 7.2854022188622487, - 7.2946207488916270, - 7.3037807481771031, - 7.3128829552843557, - 7.3219280948873617, - 7.3309168781146177, - 7.3398500028846243, - 7.3487281542310781, - 7.3575520046180847, - 7.3663222142458151, - 7.3750394313469254, - 7.3837042924740528, - 7.3923174227787607, - 7.4008794362821844, - 7.4093909361377026, - 7.4178525148858991, - 7.4262647547020979, - 7.4346282276367255, - 7.4429434958487288, - 7.4512111118323299, - 7.4594316186372973, - 7.4676055500829976, - 7.4757334309663976, - 7.4838157772642564, - 7.4918530963296748, - 7.4998458870832057, - 7.5077946401986964, - 7.5156998382840436, - 7.5235619560570131, - 7.5313814605163119, - 7.5391588111080319, - 7.5468944598876373, - 7.5545888516776376, - 7.5622424242210728, - 7.5698556083309478, - 7.5774288280357487, - 7.5849625007211561, - 7.5924570372680806, - 7.5999128421871278, - 7.6073303137496113, - 7.6147098441152075, - 7.6220518194563764, - 7.6293566200796095, - 7.6366246205436488, - 7.6438561897747244, - 7.6510516911789290, - 7.6582114827517955, - 7.6653359171851765, - 7.6724253419714952, - 7.6794800995054464, - 7.6865005271832185, - 7.6934869574993252, - 7.7004397181410926, - 7.7073591320808825, - 7.7142455176661224, - 7.7210991887071856, - 7.7279204545631996, - 7.7347096202258392, - 7.7414669864011465, - 7.7481928495894596, - 7.7548875021634691, - 7.7615512324444795, - 7.7681843247769260, - 7.7747870596011737, - 7.7813597135246608, - 7.7879025593914317, - 7.7944158663501062, - 7.8008998999203047, - 7.8073549220576037, - 7.8137811912170374, - 7.8201789624151887, - 7.8265484872909159, - 7.8328900141647422, - 7.8392037880969445, - 7.8454900509443757, - 7.8517490414160571, - 7.8579809951275719, - 7.8641861446542798, - 7.8703647195834048, - 7.8765169465650002, - 7.8826430493618425, - 7.8887432488982601, - 7.8948177633079446, - 7.9008668079807496, - 7.9068905956085187, - 7.9128893362299619, - 7.9188632372745955, - 7.9248125036057813, - 7.9307373375628867, - 7.9366379390025719, - 7.9425145053392399, - 7.9483672315846778, - 7.9541963103868758, - 7.9600019320680806, - 7.9657842846620870, - 7.9715435539507720, - 7.9772799234999168, - 7.9829935746943104, - 7.9886846867721664, - 7.9943534368588578, -} - -/* Faster logarithm for small integers, with the property of log2(0) == 0. */ -func fastLog2(v uint) float64 { - if v < uint(len(kLog2Table)) { - return float64(kLog2Table[v]) - } - - return math.Log2(float64(v)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/find_match_length.go b/src/vendor/github.com/andybalholm/brotli/find_match_length.go deleted file mode 100644 index b46f88e8..00000000 --- a/src/vendor/github.com/andybalholm/brotli/find_match_length.go +++ /dev/null @@ -1,45 +0,0 @@ -package brotli - -import ( - "encoding/binary" - "math/bits" - "runtime" -) - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Function to find maximal matching prefixes of strings. */ -func findMatchLengthWithLimit(s1 []byte, s2 []byte, limit uint) uint { - var matched uint = 0 - _, _ = s1[limit-1], s2[limit-1] // bounds check - switch runtime.GOARCH { - case "amd64", "arm64": - // Compare 8 bytes at at time. - for matched+8 <= limit { - w1 := binary.LittleEndian.Uint64(s1[matched:]) - w2 := binary.LittleEndian.Uint64(s2[matched:]) - if w1 != w2 { - return matched + uint(bits.TrailingZeros64(w1^w2)>>3) - } - matched += 8 - } - case "386": - // Compare 4 bytes at at time. - for matched+4 <= limit { - w1 := binary.LittleEndian.Uint32(s1[matched:]) - w2 := binary.LittleEndian.Uint32(s2[matched:]) - if w1 != w2 { - return matched + uint(bits.TrailingZeros32(w1^w2)>>3) - } - matched += 4 - } - } - for matched < limit && s1[matched] == s2[matched] { - matched++ - } - return matched -} diff --git a/src/vendor/github.com/andybalholm/brotli/flate/LICENSE b/src/vendor/github.com/andybalholm/brotli/flate/LICENSE deleted file mode 100644 index 6a66aea5..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/vendor/github.com/andybalholm/brotli/flate/README.md b/src/vendor/github.com/andybalholm/brotli/flate/README.md deleted file mode 100644 index 0603ba1f..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This package is a flate/gzip compressor that reuses the matchfinder package that I’ve been developing for brotli. -It is copied and adapted from the standard library compress/flate package. diff --git a/src/vendor/github.com/andybalholm/brotli/flate/gzip.go b/src/vendor/github.com/andybalholm/brotli/flate/gzip.go deleted file mode 100644 index 16c62871..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/gzip.go +++ /dev/null @@ -1,65 +0,0 @@ -package flate - -import ( - "hash/crc32" - "time" - - "github.com/andybalholm/brotli/matchfinder" -) - -func NewGZIPEncoder() matchfinder.Encoder { - return &gzipEncoder{ - f: NewEncoder(), - } -} - -type gzipEncoder struct { - f matchfinder.Encoder - length uint32 - crc uint32 - wroteHeader bool -} - -func (g *gzipEncoder) Reset() { - g.f.Reset() - g.length = 0 - g.crc = 0 - g.wroteHeader = false -} - -func appendUint32(dst []byte, n uint32) []byte { - return append(dst, - byte(n), - byte(n>>8), - byte(n>>16), - byte(n>>24), - ) -} - -func (g *gzipEncoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte { - if !g.wroteHeader { - dst = append(dst, - 0x1f, 0x8b, // magic number - 8, // CM = flate - 0, // FLG - ) - dst = appendUint32(dst, uint32(time.Now().Unix())) - dst = append(dst, - 0, // XFL - 255, // OS (unspecified) - ) - g.wroteHeader = true - } - - dst = g.f.Encode(dst, src, matches, lastBlock) - - g.length += uint32(len(src)) - g.crc = crc32.Update(g.crc, crc32.IEEETable, src) - - if lastBlock { - dst = appendUint32(dst, g.crc) - dst = appendUint32(dst, g.length) - } - - return dst -} diff --git a/src/vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go b/src/vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go deleted file mode 100644 index c60dfd44..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/huffman_bit_writer.go +++ /dev/null @@ -1,517 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flate - -import ( - "github.com/andybalholm/brotli/matchfinder" -) - -const ( - // The largest offset code. - offsetCodeCount = 30 - - // The special code used to mark the end of a block. - endBlockMarker = 256 - - // The first length code. - lengthCodesStart = 257 - - // The number of codegen codes. - codegenCodeCount = 19 - badCode = 255 - - maxNumLit = 286 - maxStoreBlockSize = 65535 - baseMatchLength = 3 // The smallest match length per the RFC section 3.2.5 - baseMatchOffset = 1 // The smallest match offset -) - -// The number of extra bits needed by length code X - LENGTH_CODES_START. -var lengthExtraBits = []int8{ - /* 257 */ 0, 0, 0, - /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, - /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, - /* 280 */ 4, 5, 5, 5, 5, 0, -} - -// The length indicated by length code X - LENGTH_CODES_START. -var lengthBase = []int{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, - 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, - 64, 80, 96, 112, 128, 160, 192, 224, 255, -} - -// offset code word extra bits. -var offsetExtraBits = []int8{ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, - 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, - 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, -} - -var offsetBase = []int{ - 0x000000, 0x000001, 0x000002, 0x000003, 0x000004, - 0x000006, 0x000008, 0x00000c, 0x000010, 0x000018, - 0x000020, 0x000030, 0x000040, 0x000060, 0x000080, - 0x0000c0, 0x000100, 0x000180, 0x000200, 0x000300, - 0x000400, 0x000600, 0x000800, 0x000c00, 0x001000, - 0x001800, 0x002000, 0x003000, 0x004000, 0x006000, -} - -// The odd order in which the codegen code sizes are written. -var codegenOrder = []uint32{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15} - -type huffmanBitWriter struct { - dst []byte - - // Data waiting to be written is the low nbits of bits. - bits uint64 - nbits uint - codegenFreq [codegenCodeCount]int32 - literalFreq []int32 - offsetFreq []int32 - codegen []uint8 - literalEncoding *huffmanEncoder - offsetEncoding *huffmanEncoder - codegenEncoding *huffmanEncoder -} - -func NewEncoder() matchfinder.Encoder { - return &huffmanBitWriter{ - literalFreq: make([]int32, maxNumLit), - offsetFreq: make([]int32, offsetCodeCount), - codegen: make([]uint8, maxNumLit+offsetCodeCount+1), - literalEncoding: newHuffmanEncoder(maxNumLit), - codegenEncoding: newHuffmanEncoder(codegenCodeCount), - offsetEncoding: newHuffmanEncoder(offsetCodeCount), - } -} - -func (w *huffmanBitWriter) Reset() { - w.bits, w.nbits = 0, 0 -} - -func (w *huffmanBitWriter) flush() { - dst := w.dst - for w.nbits != 0 { - dst = append(dst, byte(w.bits)) - w.bits >>= 8 - if w.nbits > 8 { // Avoid underflow - w.nbits -= 8 - } else { - w.nbits = 0 - } - } - w.bits = 0 - w.dst = dst -} - -func (w *huffmanBitWriter) writeBits(b int32, nb uint) { - w.bits |= uint64(b) << w.nbits - w.nbits += nb - if w.nbits >= 48 { - bits := w.bits - w.bits >>= 48 - w.nbits -= 48 - w.dst = append(w.dst, - byte(bits), - byte(bits>>8), - byte(bits>>16), - byte(bits>>24), - byte(bits>>32), - byte(bits>>40), - ) - } -} - -func (w *huffmanBitWriter) writeBytes(bytes []byte) { - if w.nbits&7 != 0 { - panic("writeBytes with unfinished bits") - } - for w.nbits != 0 { - w.dst = append(w.dst, byte(w.bits)) - w.bits >>= 8 - w.nbits -= 8 - } - w.dst = append(w.dst, bytes...) -} - -// RFC 1951 3.2.7 specifies a special run-length encoding for specifying -// the literal and offset lengths arrays (which are concatenated into a single -// array). This method generates that run-length encoding. -// -// The result is written into the codegen array, and the frequencies -// of each code is written into the codegenFreq array. -// Codes 0-15 are single byte codes. Codes 16-18 are followed by additional -// information. Code badCode is an end marker -// -// numLiterals The number of literals in literalEncoding -// numOffsets The number of offsets in offsetEncoding -// litenc, offenc The literal and offset encoder to use -func (w *huffmanBitWriter) generateCodegen(numLiterals int, numOffsets int, litEnc, offEnc *huffmanEncoder) { - for i := range w.codegenFreq { - w.codegenFreq[i] = 0 - } - // Note that we are using codegen both as a temporary variable for holding - // a copy of the frequencies, and as the place where we put the result. - // This is fine because the output is always shorter than the input used - // so far. - codegen := w.codegen // cache - // Copy the concatenated code sizes to codegen. Put a marker at the end. - cgnl := codegen[:numLiterals] - for i := range cgnl { - cgnl[i] = uint8(litEnc.codes[i].len) - } - - cgnl = codegen[numLiterals : numLiterals+numOffsets] - for i := range cgnl { - cgnl[i] = uint8(offEnc.codes[i].len) - } - codegen[numLiterals+numOffsets] = badCode - - size := codegen[0] - count := 1 - outIndex := 0 - for inIndex := 1; size != badCode; inIndex++ { - // INVARIANT: We have seen "count" copies of size that have not yet - // had output generated for them. - nextSize := codegen[inIndex] - if nextSize == size { - count++ - continue - } - // We need to generate codegen indicating "count" of size. - if size != 0 { - codegen[outIndex] = size - outIndex++ - w.codegenFreq[size]++ - count-- - for count >= 3 { - n := 6 - if n > count { - n = count - } - codegen[outIndex] = 16 - outIndex++ - codegen[outIndex] = uint8(n - 3) - outIndex++ - w.codegenFreq[16]++ - count -= n - } - } else { - for count >= 11 { - n := 138 - if n > count { - n = count - } - codegen[outIndex] = 18 - outIndex++ - codegen[outIndex] = uint8(n - 11) - outIndex++ - w.codegenFreq[18]++ - count -= n - } - if count >= 3 { - // count >= 3 && count <= 10 - codegen[outIndex] = 17 - outIndex++ - codegen[outIndex] = uint8(count - 3) - outIndex++ - w.codegenFreq[17]++ - count = 0 - } - } - count-- - for ; count >= 0; count-- { - codegen[outIndex] = size - outIndex++ - w.codegenFreq[size]++ - } - // Set up invariant for next time through the loop. - size = nextSize - count = 1 - } - // Marker indicating the end of the codegen. - codegen[outIndex] = badCode -} - -// dynamicSize returns the size of dynamically encoded data in bits. -func (w *huffmanBitWriter) dynamicSize(litEnc, offEnc *huffmanEncoder, extraBits int) (size, numCodegens int) { - numCodegens = len(w.codegenFreq) - for numCodegens > 4 && w.codegenFreq[codegenOrder[numCodegens-1]] == 0 { - numCodegens-- - } - header := 3 + 5 + 5 + 4 + (3 * numCodegens) + - w.codegenEncoding.bitLength(w.codegenFreq[:]) + - int(w.codegenFreq[16])*2 + - int(w.codegenFreq[17])*3 + - int(w.codegenFreq[18])*7 - size = header + - litEnc.bitLength(w.literalFreq) + - offEnc.bitLength(w.offsetFreq) + - extraBits - - return size, numCodegens -} - -// fixedSize returns the size of dynamically encoded data in bits. -func (w *huffmanBitWriter) fixedSize(extraBits int) int { - return 3 + - fixedLiteralEncoding.bitLength(w.literalFreq) + - fixedOffsetEncoding.bitLength(w.offsetFreq) + - extraBits -} - -// storedSize calculates the stored size, including header. -// The function returns the size in bits and whether the block -// fits inside a single block. -func (w *huffmanBitWriter) storedSize(in []byte) (int, bool) { - if in == nil { - return 0, false - } - if len(in) <= maxStoreBlockSize { - return (len(in) + 5) * 8, true - } - return 0, false -} - -func (w *huffmanBitWriter) writeCode(c hcode) { - w.bits |= uint64(c.code) << w.nbits - w.nbits += uint(c.len) - if w.nbits >= 48 { - bits := w.bits - w.bits >>= 48 - w.nbits -= 48 - w.dst = append(w.dst, - byte(bits), - byte(bits>>8), - byte(bits>>16), - byte(bits>>24), - byte(bits>>32), - byte(bits>>40), - ) - } -} - -// Write the header of a dynamic Huffman block to the output stream. -// -// numLiterals The number of literals specified in codegen -// numOffsets The number of offsets specified in codegen -// numCodegens The number of codegens used in codegen -func (w *huffmanBitWriter) writeDynamicHeader(numLiterals int, numOffsets int, numCodegens int, isEof bool) { - var firstBits int32 = 4 - if isEof { - firstBits = 5 - } - w.writeBits(firstBits, 3) - w.writeBits(int32(numLiterals-257), 5) - w.writeBits(int32(numOffsets-1), 5) - w.writeBits(int32(numCodegens-4), 4) - - for i := 0; i < numCodegens; i++ { - value := uint(w.codegenEncoding.codes[codegenOrder[i]].len) - w.writeBits(int32(value), 3) - } - - i := 0 - for { - var codeWord int = int(w.codegen[i]) - i++ - if codeWord == badCode { - break - } - w.writeCode(w.codegenEncoding.codes[uint32(codeWord)]) - - switch codeWord { - case 16: - w.writeBits(int32(w.codegen[i]), 2) - i++ - case 17: - w.writeBits(int32(w.codegen[i]), 3) - i++ - case 18: - w.writeBits(int32(w.codegen[i]), 7) - i++ - } - } -} - -func (w *huffmanBitWriter) writeStoredHeader(length int, isEof bool) { - var flag int32 - if isEof { - flag = 1 - } - w.writeBits(flag, 3) - w.flush() - w.writeBits(int32(length), 16) - w.writeBits(int32(^uint16(length)), 16) -} - -func (w *huffmanBitWriter) writeFixedHeader(isEof bool) { - // Indicate that we are a fixed Huffman block - var value int32 = 2 - if isEof { - value = 3 - } - w.writeBits(value, 3) -} - -// writeBlock will write a block of tokens with the smallest encoding. -func (w *huffmanBitWriter) writeBlock(matches []matchfinder.Match, eof bool, input []byte) { - numLiterals, numOffsets := w.makeStatistics(matches, input) - - var extraBits int - storedSize, storable := w.storedSize(input) - if storable { - // We only bother calculating the costs of the extra bits required by - // the length of offset fields (which will be the same for both fixed - // and dynamic encoding), if we need to compare those two encodings - // against stored encoding. - for lengthCode := lengthCodesStart + 8; lengthCode < numLiterals; lengthCode++ { - // First eight length codes have extra size = 0. - extraBits += int(w.literalFreq[lengthCode]) * int(lengthExtraBits[lengthCode-lengthCodesStart]) - } - for offsetCode := 4; offsetCode < numOffsets; offsetCode++ { - // First four offset codes have extra size = 0. - extraBits += int(w.offsetFreq[offsetCode]) * int(offsetExtraBits[offsetCode]) - } - } - - // Figure out smallest code. - // Fixed Huffman baseline. - var literalEncoding = fixedLiteralEncoding - var offsetEncoding = fixedOffsetEncoding - var size = w.fixedSize(extraBits) - - // Dynamic Huffman? - var numCodegens int - - // Generate codegen and codegenFrequencies, which indicates how to encode - // the literalEncoding and the offsetEncoding. - w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding) - w.codegenEncoding.generate(w.codegenFreq[:], 7) - dynamicSize, numCodegens := w.dynamicSize(w.literalEncoding, w.offsetEncoding, extraBits) - - if dynamicSize < size { - size = dynamicSize - literalEncoding = w.literalEncoding - offsetEncoding = w.offsetEncoding - } - - // Stored bytes? - if storable && storedSize < size { - w.writeStoredHeader(len(input), eof) - w.writeBytes(input) - return - } - - // Huffman. - if literalEncoding == fixedLiteralEncoding { - w.writeFixedHeader(eof) - } else { - w.writeDynamicHeader(numLiterals, numOffsets, numCodegens, eof) - } - - // Write the tokens. - w.writeTokens(matches, input, literalEncoding.codes, offsetEncoding.codes) - w.writeCode(literalEncoding.codes[endBlockMarker]) -} - -// makeStatistics indexes a slice of tokens, and updates -// literalFreq and offsetFreq, and generates literalEncoding -// and offsetEncoding. -// The number of literal and offset tokens is returned. -func (w *huffmanBitWriter) makeStatistics(matches []matchfinder.Match, input []byte) (numLiterals, numOffsets int) { - for i := range w.literalFreq { - w.literalFreq[i] = 0 - } - for i := range w.offsetFreq { - w.offsetFreq[i] = 0 - } - - pos := 0 - for _, m := range matches { - for _, c := range input[pos : pos+m.Unmatched] { - w.literalFreq[c]++ - } - pos += m.Unmatched - - if m.Length == 0 { - continue - } - w.literalFreq[lengthCodesStart+lengthCode(m.Length)]++ - w.offsetFreq[offsetCode(m.Distance)]++ - pos += m.Length - } - w.literalFreq[endBlockMarker]++ - - // get the number of literals - numLiterals = len(w.literalFreq) - for w.literalFreq[numLiterals-1] == 0 { - numLiterals-- - } - // get the number of offsets - numOffsets = len(w.offsetFreq) - for numOffsets > 0 && w.offsetFreq[numOffsets-1] == 0 { - numOffsets-- - } - if numOffsets == 0 { - // We haven't found a single match. If we want to go with the dynamic encoding, - // we should count at least one offset to be sure that the offset huffman tree could be encoded. - w.offsetFreq[0] = 1 - numOffsets = 1 - } - w.literalEncoding.generate(w.literalFreq, 15) - w.offsetEncoding.generate(w.offsetFreq, 15) - return -} - -// writeTokens writes a slice of tokens to the output. -// codes for literal and offset encoding must be supplied. -func (w *huffmanBitWriter) writeTokens(matches []matchfinder.Match, input []byte, leCodes, oeCodes []hcode) { - pos := 0 - for _, m := range matches { - for _, c := range input[pos : pos+m.Unmatched] { - w.writeCode(leCodes[c]) - } - pos += m.Unmatched - - // Write the length - length := m.Length - if length == 0 { - continue - } - lengthCode := lengthCode(length) - w.writeCode(leCodes[lengthCode+lengthCodesStart]) - extraLengthBits := uint(lengthExtraBits[lengthCode]) - if extraLengthBits > 0 { - extraLength := int32(length - baseMatchLength - lengthBase[lengthCode]) - w.writeBits(extraLength, extraLengthBits) - } - - // Write the offset - offset := m.Distance - offsetCode := offsetCode(offset) - w.writeCode(oeCodes[offsetCode]) - extraOffsetBits := uint(offsetExtraBits[offsetCode]) - if extraOffsetBits > 0 { - extraOffset := int32(offset - baseMatchOffset - offsetBase[offsetCode]) - w.writeBits(extraOffset, extraOffsetBits) - } - pos += m.Length - } -} - -func (w *huffmanBitWriter) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte { - w.dst = dst - - w.writeBlock(matches, lastBlock, src) - if lastBlock { - w.flush() - } - - dst = w.dst - w.dst = nil - return dst -} diff --git a/src/vendor/github.com/andybalholm/brotli/flate/huffman_code.go b/src/vendor/github.com/andybalholm/brotli/flate/huffman_code.go deleted file mode 100644 index 1d73f47d..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/huffman_code.go +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flate - -import ( - "math" - "math/bits" - "sort" -) - -// hcode is a huffman code with a bit code and bit length. -type hcode struct { - code, len uint16 -} - -type huffmanEncoder struct { - codes []hcode - freqcache []literalNode - bitCount [17]int32 - lns byLiteral // stored to avoid repeated allocation in generate - lfs byFreq // stored to avoid repeated allocation in generate -} - -type literalNode struct { - literal uint16 - freq int32 -} - -// A levelInfo describes the state of the constructed tree for a given depth. -type levelInfo struct { - // Our level. for better printing - level int32 - - // The frequency of the last node at this level - lastFreq int32 - - // The frequency of the next character to add to this level - nextCharFreq int32 - - // The frequency of the next pair (from level below) to add to this level. - // Only valid if the "needed" value of the next lower level is 0. - nextPairFreq int32 - - // The number of chains remaining to generate for this level before moving - // up to the next level - needed int32 -} - -// set sets the code and length of an hcode. -func (h *hcode) set(code uint16, length uint16) { - h.len = length - h.code = code -} - -func maxNode() literalNode { return literalNode{math.MaxUint16, math.MaxInt32} } - -func newHuffmanEncoder(size int) *huffmanEncoder { - return &huffmanEncoder{codes: make([]hcode, size)} -} - -// Generates a HuffmanCode corresponding to the fixed literal table -func generateFixedLiteralEncoding() *huffmanEncoder { - h := newHuffmanEncoder(maxNumLit) - codes := h.codes - var ch uint16 - for ch = 0; ch < maxNumLit; ch++ { - var bits uint16 - var size uint16 - switch { - case ch < 144: - // size 8, 000110000 .. 10111111 - bits = ch + 48 - size = 8 - case ch < 256: - // size 9, 110010000 .. 111111111 - bits = ch + 400 - 144 - size = 9 - case ch < 280: - // size 7, 0000000 .. 0010111 - bits = ch - 256 - size = 7 - default: - // size 8, 11000000 .. 11000111 - bits = ch + 192 - 280 - size = 8 - } - codes[ch] = hcode{code: reverseBits(bits, byte(size)), len: size} - } - return h -} - -func generateFixedOffsetEncoding() *huffmanEncoder { - h := newHuffmanEncoder(30) - codes := h.codes - for ch := range codes { - codes[ch] = hcode{code: reverseBits(uint16(ch), 5), len: 5} - } - return h -} - -var fixedLiteralEncoding *huffmanEncoder = generateFixedLiteralEncoding() -var fixedOffsetEncoding *huffmanEncoder = generateFixedOffsetEncoding() - -func (h *huffmanEncoder) bitLength(freq []int32) int { - var total int - for i, f := range freq { - if f != 0 { - total += int(f) * int(h.codes[i].len) - } - } - return total -} - -const maxBitsLimit = 16 - -// Return the number of literals assigned to each bit size in the Huffman encoding -// -// This method is only called when list.length >= 3 -// The cases of 0, 1, and 2 literals are handled by special case code. -// -// list An array of the literals with non-zero frequencies -// and their associated frequencies. The array is in order of increasing -// frequency, and has as its last element a special element with frequency -// MaxInt32 -// maxBits The maximum number of bits that should be used to encode any literal. -// Must be less than 16. -// return An integer array in which array[i] indicates the number of literals -// that should be encoded in i bits. -func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { - if maxBits >= maxBitsLimit { - panic("flate: maxBits too large") - } - n := int32(len(list)) - list = list[0 : n+1] - list[n] = maxNode() - - // The tree can't have greater depth than n - 1, no matter what. This - // saves a little bit of work in some small cases - if maxBits > n-1 { - maxBits = n - 1 - } - - // Create information about each of the levels. - // A bogus "Level 0" whose sole purpose is so that - // level1.prev.needed==0. This makes level1.nextPairFreq - // be a legitimate value that never gets chosen. - var levels [maxBitsLimit]levelInfo - // leafCounts[i] counts the number of literals at the left - // of ancestors of the rightmost node at level i. - // leafCounts[i][j] is the number of literals at the left - // of the level j ancestor. - var leafCounts [maxBitsLimit][maxBitsLimit]int32 - - for level := int32(1); level <= maxBits; level++ { - // For every level, the first two items are the first two characters. - // We initialize the levels as if we had already figured this out. - levels[level] = levelInfo{ - level: level, - lastFreq: list[1].freq, - nextCharFreq: list[2].freq, - nextPairFreq: list[0].freq + list[1].freq, - } - leafCounts[level][level] = 2 - if level == 1 { - levels[level].nextPairFreq = math.MaxInt32 - } - } - - // We need a total of 2*n - 2 items at top level and have already generated 2. - levels[maxBits].needed = 2*n - 4 - - level := maxBits - for { - l := &levels[level] - if l.nextPairFreq == math.MaxInt32 && l.nextCharFreq == math.MaxInt32 { - // We've run out of both leafs and pairs. - // End all calculations for this level. - // To make sure we never come back to this level or any lower level, - // set nextPairFreq impossibly large. - l.needed = 0 - levels[level+1].nextPairFreq = math.MaxInt32 - level++ - continue - } - - prevFreq := l.lastFreq - if l.nextCharFreq < l.nextPairFreq { - // The next item on this row is a leaf node. - n := leafCounts[level][level] + 1 - l.lastFreq = l.nextCharFreq - // Lower leafCounts are the same of the previous node. - leafCounts[level][level] = n - l.nextCharFreq = list[n].freq - } else { - // The next item on this row is a pair from the previous row. - // nextPairFreq isn't valid until we generate two - // more values in the level below - l.lastFreq = l.nextPairFreq - // Take leaf counts from the lower level, except counts[level] remains the same. - copy(leafCounts[level][:level], leafCounts[level-1][:level]) - levels[l.level-1].needed = 2 - } - - if l.needed--; l.needed == 0 { - // We've done everything we need to do for this level. - // Continue calculating one level up. Fill in nextPairFreq - // of that level with the sum of the two nodes we've just calculated on - // this level. - if l.level == maxBits { - // All done! - break - } - levels[l.level+1].nextPairFreq = prevFreq + l.lastFreq - level++ - } else { - // If we stole from below, move down temporarily to replenish it. - for levels[level-1].needed > 0 { - level-- - } - } - } - - // Somethings is wrong if at the end, the top level is null or hasn't used - // all of the leaves. - if leafCounts[maxBits][maxBits] != n { - panic("leafCounts[maxBits][maxBits] != n") - } - - bitCount := h.bitCount[:maxBits+1] - bits := 1 - counts := &leafCounts[maxBits] - for level := maxBits; level > 0; level-- { - // chain.leafCount gives the number of literals requiring at least "bits" - // bits to encode. - bitCount[bits] = counts[level] - counts[level-1] - bits++ - } - return bitCount -} - -// Look at the leaves and assign them a bit count and an encoding as specified -// in RFC 1951 3.2.2 -func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) { - code := uint16(0) - for n, bits := range bitCount { - code <<= 1 - if n == 0 || bits == 0 { - continue - } - // The literals list[len(list)-bits] .. list[len(list)-bits] - // are encoded using "bits" bits, and get the values - // code, code + 1, .... The code values are - // assigned in literal order (not frequency order). - chunk := list[len(list)-int(bits):] - - h.lns.sort(chunk) - for _, node := range chunk { - h.codes[node.literal] = hcode{code: reverseBits(code, uint8(n)), len: uint16(n)} - code++ - } - list = list[0 : len(list)-int(bits)] - } -} - -// Update this Huffman Code object to be the minimum code for the specified frequency count. -// -// freq An array of frequencies, in which frequency[i] gives the frequency of literal i. -// maxBits The maximum number of bits to use for any literal. -func (h *huffmanEncoder) generate(freq []int32, maxBits int32) { - if h.freqcache == nil { - // Allocate a reusable buffer with the longest possible frequency table. - // Possible lengths are codegenCodeCount, offsetCodeCount and maxNumLit. - // The largest of these is maxNumLit, so we allocate for that case. - h.freqcache = make([]literalNode, maxNumLit+1) - } - list := h.freqcache[:len(freq)+1] - // Number of non-zero literals - count := 0 - // Set list to be the set of all non-zero literals and their frequencies - for i, f := range freq { - if f != 0 { - list[count] = literalNode{uint16(i), f} - count++ - } else { - list[count] = literalNode{} - h.codes[i].len = 0 - } - } - list[len(freq)] = literalNode{} - - list = list[:count] - if count <= 2 { - // Handle the small cases here, because they are awkward for the general case code. With - // two or fewer literals, everything has bit length 1. - for i, node := range list { - // "list" is in order of increasing literal value. - h.codes[node.literal].set(uint16(i), 1) - } - return - } - h.lfs.sort(list) - - // Get the number of literals for each bit count - bitCount := h.bitCounts(list, maxBits) - // And do the assignment - h.assignEncodingAndSize(bitCount, list) -} - -type byLiteral []literalNode - -func (s *byLiteral) sort(a []literalNode) { - *s = byLiteral(a) - sort.Sort(s) -} - -func (s byLiteral) Len() int { return len(s) } - -func (s byLiteral) Less(i, j int) bool { - return s[i].literal < s[j].literal -} - -func (s byLiteral) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -type byFreq []literalNode - -func (s *byFreq) sort(a []literalNode) { - *s = byFreq(a) - sort.Sort(s) -} - -func (s byFreq) Len() int { return len(s) } - -func (s byFreq) Less(i, j int) bool { - if s[i].freq == s[j].freq { - return s[i].literal < s[j].literal - } - return s[i].freq < s[j].freq -} - -func (s byFreq) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func reverseBits(number uint16, bitLength byte) uint16 { - return bits.Reverse16(number << (16 - bitLength)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/flate/token.go b/src/vendor/github.com/andybalholm/brotli/flate/token.go deleted file mode 100644 index 415b1b5e..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/token.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flate - -import "log" - -// The length code for length X (MIN_MATCH_LENGTH <= X <= MAX_MATCH_LENGTH) -// is lengthCodes[length - MIN_MATCH_LENGTH] -var lengthCodes = [...]uint32{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, - 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, - 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, - 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, - 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, - 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, - 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 28, -} - -var offsetCodes = [...]uint32{ - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -} - -func lengthCode(len int) uint32 { - if len > 258 { - panic("match too long") - } - return lengthCodes[len-baseMatchLength] -} - -// Returns the offset code corresponding to a specific offset -func offsetCode(off int) uint32 { - if off > 32768 { - log.Println(off) - panic("match distance too high") - } - off -= baseMatchOffset - if off < len(offsetCodes) { - return offsetCodes[off] - } - if off>>7 < len(offsetCodes) { - return offsetCodes[off>>7] + 14 - } - return offsetCodes[off>>14] + 28 -} diff --git a/src/vendor/github.com/andybalholm/brotli/flate/writer.go b/src/vendor/github.com/andybalholm/brotli/flate/writer.go deleted file mode 100644 index 1e49d489..00000000 --- a/src/vendor/github.com/andybalholm/brotli/flate/writer.go +++ /dev/null @@ -1,66 +0,0 @@ -package flate - -import ( - "io" - - "github.com/andybalholm/brotli/matchfinder" -) - -// NewWriter returns a new matchfinder.Writer that compresses data at the given level, -// in flate encoding. Levels 1–9 are available; levels outside this range will -// be replaced with the closest level available. -func NewWriter(w io.Writer, level int) *matchfinder.Writer { - return newWriter(w, level, NewEncoder()) -} - -// NewGZIPWriter returns a new matchfinder.Writer that compresses data at the given -// level, in gzip encoding. Levels 1–9 are available; levels outside this range -// will be replaced by the closest level available. -func NewGZIPWriter(w io.Writer, level int) *matchfinder.Writer { - return newWriter(w, level, NewGZIPEncoder()) -} - -func newWriter(w io.Writer, level int, e matchfinder.Encoder) *matchfinder.Writer { - var mf matchfinder.MatchFinder - if level < 2 { - mf = &matchfinder.ZFast{MaxDistance: 1 << 15} - } else if level == 2 { - mf = &matchfinder.ZDFast{MaxDistance: 1 << 15} - } else if level == 3 { - mf = &matchfinder.ZM{MaxDistance: 1 << 15} - } else if level == 4 { - mf = &matchfinder.Trio{MaxDistance: 1 << 15} - } else if level < 8 { - chainLen := 32 - switch level { - case 5: - chainLen = 8 - case 6: - chainLen = 16 - } - mf = &matchfinder.M4{ - MaxDistance: 1 << 15, - ChainLength: chainLen, - HashLen: 5, - DistanceBitCost: 66, - } - } else { - chainLen := 32 - hashLen := 5 - if level == 8 { - chainLen = 4 - } - mf = &matchfinder.Pathfinder{ - MaxDistance: 1 << 15, - ChainLength: chainLen, - HashLen: hashLen, - } - } - - return &matchfinder.Writer{ - Dest: w, - MatchFinder: mf, - Encoder: e, - BlockSize: 1 << 16, - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/h10.go b/src/vendor/github.com/andybalholm/brotli/h10.go deleted file mode 100644 index 5662fbbb..00000000 --- a/src/vendor/github.com/andybalholm/brotli/h10.go +++ /dev/null @@ -1,287 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2016 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func (*h10) HashTypeLength() uint { - return 4 -} - -func (*h10) StoreLookahead() uint { - return 128 -} - -func hashBytesH10(data []byte) uint32 { - var h uint32 = binary.LittleEndian.Uint32(data) * kHashMul32 - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return h >> (32 - 17) -} - -/* A (forgetful) hash table where each hash bucket contains a binary tree of - sequences whose first 4 bytes share the same hash code. - Each sequence is 128 long and is identified by its starting - position in the input data. The binary tree is sorted by the lexicographic - order of the sequences, and it is also a max-heap with respect to the - starting positions. */ -type h10 struct { - hasherCommon - window_mask_ uint - buckets_ [1 << 17]uint32 - invalid_pos_ uint32 - forest []uint32 -} - -func (h *h10) Initialize(params *encoderParams) { - h.window_mask_ = (1 << params.lgwin) - 1 - h.invalid_pos_ = uint32(0 - h.window_mask_) - var num_nodes uint = uint(1) << params.lgwin - h.forest = make([]uint32, 2*num_nodes) -} - -func (h *h10) Prepare(one_shot bool, input_size uint, data []byte) { - var invalid_pos uint32 = h.invalid_pos_ - var i uint32 - for i = 0; i < 1<<17; i++ { - h.buckets_[i] = invalid_pos - } -} - -func leftChildIndexH10(self *h10, pos uint) uint { - return 2 * (pos & self.window_mask_) -} - -func rightChildIndexH10(self *h10, pos uint) uint { - return 2*(pos&self.window_mask_) + 1 -} - -/* Stores the hash of the next 4 bytes and in a single tree-traversal, the - hash bucket's binary tree is searched for matches and is re-rooted at the - current position. - - If less than 128 data is available, the hash bucket of the - current position is searched for matches, but the state of the hash table - is not changed, since we can not know the final sorting order of the - current (incomplete) sequence. - - This function must be called with increasing cur_ix positions. */ -func storeAndFindMatchesH10(self *h10, data []byte, cur_ix uint, ring_buffer_mask uint, max_length uint, max_backward uint, best_len *uint, matches []backwardMatch) []backwardMatch { - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var max_comp_len uint = brotli_min_size_t(max_length, 128) - var should_reroot_tree bool = (max_length >= 128) - var key uint32 = hashBytesH10(data[cur_ix_masked:]) - var forest []uint32 = self.forest - var prev_ix uint = uint(self.buckets_[key]) - var node_left uint = leftChildIndexH10(self, cur_ix) - var node_right uint = rightChildIndexH10(self, cur_ix) - var best_len_left uint = 0 - var best_len_right uint = 0 - var depth_remaining uint - /* The forest index of the rightmost node of the left subtree of the new - root, updated as we traverse and re-root the tree of the hash bucket. */ - - /* The forest index of the leftmost node of the right subtree of the new - root, updated as we traverse and re-root the tree of the hash bucket. */ - - /* The match length of the rightmost node of the left subtree of the new - root, updated as we traverse and re-root the tree of the hash bucket. */ - - /* The match length of the leftmost node of the right subtree of the new - root, updated as we traverse and re-root the tree of the hash bucket. */ - if should_reroot_tree { - self.buckets_[key] = uint32(cur_ix) - } - - for depth_remaining = 64; ; depth_remaining-- { - var backward uint = cur_ix - prev_ix - var prev_ix_masked uint = prev_ix & ring_buffer_mask - if backward == 0 || backward > max_backward || depth_remaining == 0 { - if should_reroot_tree { - forest[node_left] = self.invalid_pos_ - forest[node_right] = self.invalid_pos_ - } - - break - } - { - var cur_len uint = brotli_min_size_t(best_len_left, best_len_right) - var len uint - assert(cur_len <= 128) - len = cur_len + findMatchLengthWithLimit(data[cur_ix_masked+cur_len:], data[prev_ix_masked+cur_len:], max_length-cur_len) - if matches != nil && len > *best_len { - *best_len = uint(len) - initBackwardMatch(&matches[0], backward, uint(len)) - matches = matches[1:] - } - - if len >= max_comp_len { - if should_reroot_tree { - forest[node_left] = forest[leftChildIndexH10(self, prev_ix)] - forest[node_right] = forest[rightChildIndexH10(self, prev_ix)] - } - - break - } - - if data[cur_ix_masked+len] > data[prev_ix_masked+len] { - best_len_left = uint(len) - if should_reroot_tree { - forest[node_left] = uint32(prev_ix) - } - - node_left = rightChildIndexH10(self, prev_ix) - prev_ix = uint(forest[node_left]) - } else { - best_len_right = uint(len) - if should_reroot_tree { - forest[node_right] = uint32(prev_ix) - } - - node_right = leftChildIndexH10(self, prev_ix) - prev_ix = uint(forest[node_right]) - } - } - } - - return matches -} - -/* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the - length of max_length and stores the position cur_ix in the hash table. - - Sets *num_matches to the number of matches found, and stores the found - matches in matches[0] to matches[*num_matches - 1]. The matches will be - sorted by strictly increasing length and (non-strictly) increasing - distance. */ -func findAllMatchesH10(handle *h10, dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, cur_ix uint, max_length uint, max_backward uint, gap uint, params *encoderParams, matches []backwardMatch) uint { - var orig_matches []backwardMatch = matches - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var best_len uint = 1 - var short_match_max_backward uint - if params.quality != hqZopflificationQuality { - short_match_max_backward = 16 - } else { - short_match_max_backward = 64 - } - var stop uint = cur_ix - short_match_max_backward - var dict_matches [maxStaticDictionaryMatchLen + 1]uint32 - var i uint - if cur_ix < short_match_max_backward { - stop = 0 - } - for i = cur_ix - 1; i > stop && best_len <= 2; i-- { - var prev_ix uint = i - var backward uint = cur_ix - prev_ix - if backward > max_backward { - break - } - - prev_ix &= ring_buffer_mask - if data[cur_ix_masked] != data[prev_ix] || data[cur_ix_masked+1] != data[prev_ix+1] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len > best_len { - best_len = uint(len) - initBackwardMatch(&matches[0], backward, uint(len)) - matches = matches[1:] - } - } - } - - if best_len < max_length { - matches = storeAndFindMatchesH10(handle, data, cur_ix, ring_buffer_mask, max_length, max_backward, &best_len, matches) - } - - for i = 0; i <= maxStaticDictionaryMatchLen; i++ { - dict_matches[i] = kInvalidMatch - } - { - var minlen uint = brotli_max_size_t(4, best_len+1) - if findAllStaticDictionaryMatches(dictionary, data[cur_ix_masked:], minlen, max_length, dict_matches[0:]) { - var maxlen uint = brotli_min_size_t(maxStaticDictionaryMatchLen, max_length) - var l uint - for l = minlen; l <= maxlen; l++ { - var dict_id uint32 = dict_matches[l] - if dict_id < kInvalidMatch { - var distance uint = max_backward + gap + uint(dict_id>>5) + 1 - if distance <= params.dist.max_distance { - initDictionaryBackwardMatch(&matches[0], distance, l, uint(dict_id&31)) - matches = matches[1:] - } - } - } - } - } - - return uint(-cap(matches) + cap(orig_matches)) -} - -/* Stores the hash of the next 4 bytes and re-roots the binary tree at the - current sequence, without returning any matches. - REQUIRES: ix + 128 <= end-of-current-block */ -func (h *h10) Store(data []byte, mask uint, ix uint) { - var max_backward uint = h.window_mask_ - windowGap + 1 - /* Maximum distance is window size - 16, see section 9.1. of the spec. */ - storeAndFindMatchesH10(h, data, ix, mask, 128, max_backward, nil, nil) -} - -func (h *h10) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) { - var i uint = ix_start - var j uint = ix_start - if ix_start+63 <= ix_end { - i = ix_end - 63 - } - - if ix_start+512 <= i { - for ; j < i; j += 8 { - h.Store(data, mask, j) - } - } - - for ; i < ix_end; i++ { - h.Store(data, mask, i) - } -} - -func (h *h10) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint) { - if num_bytes >= h.HashTypeLength()-1 && position >= 128 { - var i_start uint = position - 128 + 1 - var i_end uint = brotli_min_size_t(position, i_start+num_bytes) - /* Store the last `128 - 1` positions in the hasher. - These could not be calculated before, since they require knowledge - of both the previous and the current block. */ - - var i uint - for i = i_start; i < i_end; i++ { - /* Maximum distance is window size - 16, see section 9.1. of the spec. - Furthermore, we have to make sure that we don't look further back - from the start of the next block than the window size, otherwise we - could access already overwritten areas of the ring-buffer. */ - var max_backward uint = h.window_mask_ - brotli_max_size_t(windowGap-1, position-i) - - /* We know that i + 128 <= position + num_bytes, i.e. the - end of the current block and that we have at least - 128 tail in the ring-buffer. */ - storeAndFindMatchesH10(h, ringbuffer, i, ringbuffer_mask, 128, max_backward, nil, nil) - } - } -} - -/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */ -const maxNumMatchesH10 = 128 - -func (*h10) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - panic("unimplemented") -} - -func (*h10) PrepareDistanceCache(distance_cache []int) { - panic("unimplemented") -} diff --git a/src/vendor/github.com/andybalholm/brotli/h5.go b/src/vendor/github.com/andybalholm/brotli/h5.go deleted file mode 100644 index f391b73f..00000000 --- a/src/vendor/github.com/andybalholm/brotli/h5.go +++ /dev/null @@ -1,214 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A (forgetful) hash table to the data seen by the compressor, to - help create backward references to previous data. - - This is a hash map of fixed size (bucket_size_) to a ring buffer of - fixed size (block_size_). The ring buffer contains the last block_size_ - index positions of the given hash key in the compressed data. */ -func (*h5) HashTypeLength() uint { - return 4 -} - -func (*h5) StoreLookahead() uint { - return 4 -} - -/* HashBytes is the function that chooses the bucket to place the address in. */ -func hashBytesH5(data []byte, shift int) uint32 { - var h uint32 = binary.LittleEndian.Uint32(data) * kHashMul32 - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return uint32(h >> uint(shift)) -} - -type h5 struct { - hasherCommon - bucket_size_ uint - block_size_ uint - hash_shift_ int - block_mask_ uint32 - num []uint16 - buckets []uint32 -} - -func (h *h5) Initialize(params *encoderParams) { - h.hash_shift_ = 32 - h.params.bucket_bits - h.bucket_size_ = uint(1) << uint(h.params.bucket_bits) - h.block_size_ = uint(1) << uint(h.params.block_bits) - h.block_mask_ = uint32(h.block_size_ - 1) - h.num = make([]uint16, h.bucket_size_) - h.buckets = make([]uint32, h.block_size_*h.bucket_size_) -} - -func (h *h5) Prepare(one_shot bool, input_size uint, data []byte) { - var num []uint16 = h.num - var partial_prepare_threshold uint = h.bucket_size_ >> 6 - /* Partial preparation is 100 times slower (per socket). */ - if one_shot && input_size <= partial_prepare_threshold { - var i uint - for i = 0; i < input_size; i++ { - var key uint32 = hashBytesH5(data[i:], h.hash_shift_) - num[key] = 0 - } - } else { - for i := 0; i < int(h.bucket_size_); i++ { - num[i] = 0 - } - } -} - -/* Look at 4 bytes at &data[ix & mask]. - Compute a hash from these, and store the value of ix at that position. */ -func (h *h5) Store(data []byte, mask uint, ix uint) { - var num []uint16 = h.num - var key uint32 = hashBytesH5(data[ix&mask:], h.hash_shift_) - var minor_ix uint = uint(num[key]) & uint(h.block_mask_) - var offset uint = minor_ix + uint(key<= h.HashTypeLength()-1 && position >= 3 { - /* Prepare the hashes for three last bytes of the last write. - These could not be calculated before, since they require knowledge - of both the previous and the current block. */ - h.Store(ringbuffer, ringbuffer_mask, position-3) - h.Store(ringbuffer, ringbuffer_mask, position-2) - h.Store(ringbuffer, ringbuffer_mask, position-1) - } -} - -func (h *h5) PrepareDistanceCache(distance_cache []int) { - prepareDistanceCache(distance_cache, h.params.num_last_distances_to_check) -} - -/* Find a longest backward match of &data[cur_ix] up to the length of - max_length and stores the position cur_ix in the hash table. - - REQUIRES: PrepareDistanceCacheH5 must be invoked for current distance cache - values; if this method is invoked repeatedly with the same distance - cache values, it is enough to invoke PrepareDistanceCacheH5 once. - - Does not look for matches longer than max_length. - Does not look for matches further away than max_backward. - Writes the best match into |out|. - |out|->score is updated only if a better match is found. */ -func (h *h5) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - var num []uint16 = h.num - var buckets []uint32 = h.buckets - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var min_score uint = out.score - var best_score uint = out.score - var best_len uint = out.len - var i uint - var bucket []uint32 - /* Don't accept a short copy from far away. */ - out.len = 0 - - out.len_code_delta = 0 - - /* Try last distance first. */ - for i = 0; i < uint(h.params.num_last_distances_to_check); i++ { - var backward uint = uint(distance_cache[i]) - var prev_ix uint = uint(cur_ix - backward) - if prev_ix >= cur_ix { - continue - } - - if backward > max_backward { - continue - } - - prev_ix &= ring_buffer_mask - - if cur_ix_masked+best_len > ring_buffer_mask || prev_ix+best_len > ring_buffer_mask || data[cur_ix_masked+best_len] != data[prev_ix+best_len] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 3 || (len == 2 && i < 2) { - /* Comparing for >= 2 does not change the semantics, but just saves for - a few unnecessary binary logarithms in backward reference score, - since we are not interested in such short matches. */ - var score uint = backwardReferenceScoreUsingLastDistance(uint(len)) - if best_score < score { - if i != 0 { - score -= backwardReferencePenaltyUsingLastDistance(i) - } - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - } - { - var key uint32 = hashBytesH5(data[cur_ix_masked:], h.hash_shift_) - bucket = buckets[key< h.block_size_ { - down = uint(num[key]) - h.block_size_ - } else { - down = 0 - } - for i = uint(num[key]); i > down; { - var prev_ix uint - i-- - prev_ix = uint(bucket[uint32(i)&h.block_mask_]) - var backward uint = cur_ix - prev_ix - if backward > max_backward { - break - } - - prev_ix &= ring_buffer_mask - if cur_ix_masked+best_len > ring_buffer_mask || prev_ix+best_len > ring_buffer_mask || data[cur_ix_masked+best_len] != data[prev_ix+best_len] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - /* Comparing for >= 3 does not change the semantics, but just saves - for a few unnecessary binary logarithms in backward reference - score, since we are not interested in such short matches. */ - var score uint = backwardReferenceScore(uint(len), backward) - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - - bucket[uint32(num[key])&h.block_mask_] = uint32(cur_ix) - num[key]++ - } - - if min_score == out.score { - searchInStaticDictionary(dictionary, h, data[cur_ix_masked:], max_length, max_backward+gap, max_distance, out, false) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/h6.go b/src/vendor/github.com/andybalholm/brotli/h6.go deleted file mode 100644 index 80bb224a..00000000 --- a/src/vendor/github.com/andybalholm/brotli/h6.go +++ /dev/null @@ -1,216 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A (forgetful) hash table to the data seen by the compressor, to - help create backward references to previous data. - - This is a hash map of fixed size (bucket_size_) to a ring buffer of - fixed size (block_size_). The ring buffer contains the last block_size_ - index positions of the given hash key in the compressed data. */ -func (*h6) HashTypeLength() uint { - return 8 -} - -func (*h6) StoreLookahead() uint { - return 8 -} - -/* HashBytes is the function that chooses the bucket to place the address in. */ -func hashBytesH6(data []byte, mask uint64, shift int) uint32 { - var h uint64 = (binary.LittleEndian.Uint64(data) & mask) * kHashMul64Long - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return uint32(h >> uint(shift)) -} - -type h6 struct { - hasherCommon - bucket_size_ uint - block_size_ uint - hash_shift_ int - hash_mask_ uint64 - block_mask_ uint32 - num []uint16 - buckets []uint32 -} - -func (h *h6) Initialize(params *encoderParams) { - h.hash_shift_ = 64 - h.params.bucket_bits - h.hash_mask_ = (^(uint64(0))) >> uint(64-8*h.params.hash_len) - h.bucket_size_ = uint(1) << uint(h.params.bucket_bits) - h.block_size_ = uint(1) << uint(h.params.block_bits) - h.block_mask_ = uint32(h.block_size_ - 1) - h.num = make([]uint16, h.bucket_size_) - h.buckets = make([]uint32, h.block_size_*h.bucket_size_) -} - -func (h *h6) Prepare(one_shot bool, input_size uint, data []byte) { - var num []uint16 = h.num - var partial_prepare_threshold uint = h.bucket_size_ >> 6 - /* Partial preparation is 100 times slower (per socket). */ - if one_shot && input_size <= partial_prepare_threshold { - var i uint - for i = 0; i < input_size; i++ { - var key uint32 = hashBytesH6(data[i:], h.hash_mask_, h.hash_shift_) - num[key] = 0 - } - } else { - for i := 0; i < int(h.bucket_size_); i++ { - num[i] = 0 - } - } -} - -/* Look at 4 bytes at &data[ix & mask]. - Compute a hash from these, and store the value of ix at that position. */ -func (h *h6) Store(data []byte, mask uint, ix uint) { - var num []uint16 = h.num - var key uint32 = hashBytesH6(data[ix&mask:], h.hash_mask_, h.hash_shift_) - var minor_ix uint = uint(num[key]) & uint(h.block_mask_) - var offset uint = minor_ix + uint(key<= h.HashTypeLength()-1 && position >= 3 { - /* Prepare the hashes for three last bytes of the last write. - These could not be calculated before, since they require knowledge - of both the previous and the current block. */ - h.Store(ringbuffer, ringbuffer_mask, position-3) - h.Store(ringbuffer, ringbuffer_mask, position-2) - h.Store(ringbuffer, ringbuffer_mask, position-1) - } -} - -func (h *h6) PrepareDistanceCache(distance_cache []int) { - prepareDistanceCache(distance_cache, h.params.num_last_distances_to_check) -} - -/* Find a longest backward match of &data[cur_ix] up to the length of - max_length and stores the position cur_ix in the hash table. - - REQUIRES: PrepareDistanceCacheH6 must be invoked for current distance cache - values; if this method is invoked repeatedly with the same distance - cache values, it is enough to invoke PrepareDistanceCacheH6 once. - - Does not look for matches longer than max_length. - Does not look for matches further away than max_backward. - Writes the best match into |out|. - |out|->score is updated only if a better match is found. */ -func (h *h6) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - var num []uint16 = h.num - var buckets []uint32 = h.buckets - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var min_score uint = out.score - var best_score uint = out.score - var best_len uint = out.len - var i uint - var bucket []uint32 - /* Don't accept a short copy from far away. */ - out.len = 0 - - out.len_code_delta = 0 - - /* Try last distance first. */ - for i = 0; i < uint(h.params.num_last_distances_to_check); i++ { - var backward uint = uint(distance_cache[i]) - var prev_ix uint = uint(cur_ix - backward) - if prev_ix >= cur_ix { - continue - } - - if backward > max_backward { - continue - } - - prev_ix &= ring_buffer_mask - - if cur_ix_masked+best_len > ring_buffer_mask || prev_ix+best_len > ring_buffer_mask || data[cur_ix_masked+best_len] != data[prev_ix+best_len] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 3 || (len == 2 && i < 2) { - /* Comparing for >= 2 does not change the semantics, but just saves for - a few unnecessary binary logarithms in backward reference score, - since we are not interested in such short matches. */ - var score uint = backwardReferenceScoreUsingLastDistance(uint(len)) - if best_score < score { - if i != 0 { - score -= backwardReferencePenaltyUsingLastDistance(i) - } - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - } - { - var key uint32 = hashBytesH6(data[cur_ix_masked:], h.hash_mask_, h.hash_shift_) - bucket = buckets[key< h.block_size_ { - down = uint(num[key]) - h.block_size_ - } else { - down = 0 - } - for i = uint(num[key]); i > down; { - var prev_ix uint - i-- - prev_ix = uint(bucket[uint32(i)&h.block_mask_]) - var backward uint = cur_ix - prev_ix - if backward > max_backward { - break - } - - prev_ix &= ring_buffer_mask - if cur_ix_masked+best_len > ring_buffer_mask || prev_ix+best_len > ring_buffer_mask || data[cur_ix_masked+best_len] != data[prev_ix+best_len] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - /* Comparing for >= 3 does not change the semantics, but just saves - for a few unnecessary binary logarithms in backward reference - score, since we are not interested in such short matches. */ - var score uint = backwardReferenceScore(uint(len), backward) - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - - bucket[uint32(num[key])&h.block_mask_] = uint32(cur_ix) - num[key]++ - } - - if min_score == out.score { - searchInStaticDictionary(dictionary, h, data[cur_ix_masked:], max_length, max_backward+gap, max_distance, out, false) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/hash.go b/src/vendor/github.com/andybalholm/brotli/hash.go deleted file mode 100644 index 00f812e8..00000000 --- a/src/vendor/github.com/andybalholm/brotli/hash.go +++ /dev/null @@ -1,342 +0,0 @@ -package brotli - -import ( - "encoding/binary" - "fmt" -) - -type hasherCommon struct { - params hasherParams - is_prepared_ bool - dict_num_lookups uint - dict_num_matches uint -} - -func (h *hasherCommon) Common() *hasherCommon { - return h -} - -type hasherHandle interface { - Common() *hasherCommon - Initialize(params *encoderParams) - Prepare(one_shot bool, input_size uint, data []byte) - StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint) - HashTypeLength() uint - StoreLookahead() uint - PrepareDistanceCache(distance_cache []int) - FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) - StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) - Store(data []byte, mask uint, ix uint) -} - -const kCutoffTransformsCount uint32 = 10 - -/* 0, 12, 27, 23, 42, 63, 56, 48, 59, 64 */ -/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */ -const kCutoffTransforms uint64 = 0x071B520ADA2D3200 - -type hasherSearchResult struct { - len uint - distance uint - score uint - len_code_delta int -} - -/* kHashMul32 multiplier has these properties: - * The multiplier must be odd. Otherwise we may lose the highest bit. - * No long streaks of ones or zeros. - * There is no effort to ensure that it is a prime, the oddity is enough - for this use. - * The number has been tuned heuristically against compression benchmarks. */ -const kHashMul32 uint32 = 0x1E35A7BD - -const kHashMul64 uint64 = 0x1E35A7BD1E35A7BD - -const kHashMul64Long uint64 = 0x1FE35A7BD3579BD3 - -func hash14(data []byte) uint32 { - var h uint32 = binary.LittleEndian.Uint32(data) * kHashMul32 - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return h >> (32 - 14) -} - -func prepareDistanceCache(distance_cache []int, num_distances int) { - if num_distances > 4 { - var last_distance int = distance_cache[0] - distance_cache[4] = last_distance - 1 - distance_cache[5] = last_distance + 1 - distance_cache[6] = last_distance - 2 - distance_cache[7] = last_distance + 2 - distance_cache[8] = last_distance - 3 - distance_cache[9] = last_distance + 3 - if num_distances > 10 { - var next_last_distance int = distance_cache[1] - distance_cache[10] = next_last_distance - 1 - distance_cache[11] = next_last_distance + 1 - distance_cache[12] = next_last_distance - 2 - distance_cache[13] = next_last_distance + 2 - distance_cache[14] = next_last_distance - 3 - distance_cache[15] = next_last_distance + 3 - } - } -} - -const literalByteScore = 135 - -const distanceBitPenalty = 30 - -/* Score must be positive after applying maximal penalty. */ -const scoreBase = (distanceBitPenalty * 8 * 8) - -/* Usually, we always choose the longest backward reference. This function - allows for the exception of that rule. - - If we choose a backward reference that is further away, it will - usually be coded with more bits. We approximate this by assuming - log2(distance). If the distance can be expressed in terms of the - last four distances, we use some heuristic constants to estimate - the bits cost. For the first up to four literals we use the bit - cost of the literals from the literal cost model, after that we - use the average bit cost of the cost model. - - This function is used to sometimes discard a longer backward reference - when it is not much longer and the bit cost for encoding it is more - than the saved literals. - - backward_reference_offset MUST be positive. */ -func backwardReferenceScore(copy_length uint, backward_reference_offset uint) uint { - return scoreBase + literalByteScore*uint(copy_length) - distanceBitPenalty*uint(log2FloorNonZero(backward_reference_offset)) -} - -func backwardReferenceScoreUsingLastDistance(copy_length uint) uint { - return literalByteScore*uint(copy_length) + scoreBase + 15 -} - -func backwardReferencePenaltyUsingLastDistance(distance_short_code uint) uint { - return uint(39) + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE) -} - -func testStaticDictionaryItem(dictionary *encoderDictionary, item uint, data []byte, max_length uint, max_backward uint, max_distance uint, out *hasherSearchResult) bool { - var len uint - var word_idx uint - var offset uint - var matchlen uint - var backward uint - var score uint - len = item & 0x1F - word_idx = item >> 5 - offset = uint(dictionary.words.offsets_by_length[len]) + len*word_idx - if len > max_length { - return false - } - - matchlen = findMatchLengthWithLimit(data, dictionary.words.data[offset:], uint(len)) - if matchlen+uint(dictionary.cutoffTransformsCount) <= len || matchlen == 0 { - return false - } - { - var cut uint = len - matchlen - var transform_id uint = (cut << 2) + uint((dictionary.cutoffTransforms>>(cut*6))&0x3F) - backward = max_backward + 1 + word_idx + (transform_id << dictionary.words.size_bits_by_length[len]) - } - - if backward > max_distance { - return false - } - - score = backwardReferenceScore(matchlen, backward) - if score < out.score { - return false - } - - out.len = matchlen - out.len_code_delta = int(len) - int(matchlen) - out.distance = backward - out.score = score - return true -} - -func searchInStaticDictionary(dictionary *encoderDictionary, handle hasherHandle, data []byte, max_length uint, max_backward uint, max_distance uint, out *hasherSearchResult, shallow bool) { - var key uint - var i uint - var self *hasherCommon = handle.Common() - if self.dict_num_matches < self.dict_num_lookups>>7 { - return - } - - key = uint(hash14(data) << 1) - for i = 0; ; (func() { i++; key++ })() { - var tmp uint - if shallow { - tmp = 1 - } else { - tmp = 2 - } - if i >= tmp { - break - } - var item uint = uint(dictionary.hash_table[key]) - self.dict_num_lookups++ - if item != 0 { - var item_matches bool = testStaticDictionaryItem(dictionary, item, data, max_length, max_backward, max_distance, out) - if item_matches { - self.dict_num_matches++ - } - } - } -} - -type backwardMatch struct { - distance uint32 - length_and_code uint32 -} - -func initBackwardMatch(self *backwardMatch, dist uint, len uint) { - self.distance = uint32(dist) - self.length_and_code = uint32(len << 5) -} - -func initDictionaryBackwardMatch(self *backwardMatch, dist uint, len uint, len_code uint) { - self.distance = uint32(dist) - var tmp uint - if len == len_code { - tmp = 0 - } else { - tmp = len_code - } - self.length_and_code = uint32(len<<5 | tmp) -} - -func backwardMatchLength(self *backwardMatch) uint { - return uint(self.length_and_code >> 5) -} - -func backwardMatchLengthCode(self *backwardMatch) uint { - var code uint = uint(self.length_and_code) & 31 - if code != 0 { - return code - } else { - return backwardMatchLength(self) - } -} - -func hasherReset(handle hasherHandle) { - if handle == nil { - return - } - handle.Common().is_prepared_ = false -} - -func newHasher(typ int) hasherHandle { - switch typ { - case 2: - return &hashLongestMatchQuickly{ - bucketBits: 16, - bucketSweep: 1, - hashLen: 5, - useDictionary: true, - } - case 3: - return &hashLongestMatchQuickly{ - bucketBits: 16, - bucketSweep: 2, - hashLen: 5, - useDictionary: false, - } - case 4: - return &hashLongestMatchQuickly{ - bucketBits: 17, - bucketSweep: 4, - hashLen: 5, - useDictionary: true, - } - case 5: - return new(h5) - case 6: - return new(h6) - case 10: - return new(h10) - case 35: - return &hashComposite{ - ha: newHasher(3), - hb: &hashRolling{jump: 4}, - } - case 40: - return &hashForgetfulChain{ - bucketBits: 15, - numBanks: 1, - bankBits: 16, - numLastDistancesToCheck: 4, - } - case 41: - return &hashForgetfulChain{ - bucketBits: 15, - numBanks: 1, - bankBits: 16, - numLastDistancesToCheck: 10, - } - case 42: - return &hashForgetfulChain{ - bucketBits: 15, - numBanks: 512, - bankBits: 9, - numLastDistancesToCheck: 16, - } - case 54: - return &hashLongestMatchQuickly{ - bucketBits: 20, - bucketSweep: 4, - hashLen: 7, - useDictionary: false, - } - case 55: - return &hashComposite{ - ha: newHasher(54), - hb: &hashRolling{jump: 4}, - } - case 65: - return &hashComposite{ - ha: newHasher(6), - hb: &hashRolling{jump: 1}, - } - } - - panic(fmt.Sprintf("unknown hasher type: %d", typ)) -} - -func hasherSetup(handle *hasherHandle, params *encoderParams, data []byte, position uint, input_size uint, is_last bool) { - var self hasherHandle = nil - var common *hasherCommon = nil - var one_shot bool = (position == 0 && is_last) - if *handle == nil { - chooseHasher(params, ¶ms.hasher) - self = newHasher(params.hasher.type_) - - *handle = self - common = self.Common() - common.params = params.hasher - self.Initialize(params) - } - - self = *handle - common = self.Common() - if !common.is_prepared_ { - self.Prepare(one_shot, input_size, data) - - if position == 0 { - common.dict_num_lookups = 0 - common.dict_num_matches = 0 - } - - common.is_prepared_ = true - } -} - -func initOrStitchToPreviousBlock(handle *hasherHandle, data []byte, mask uint, params *encoderParams, position uint, input_size uint, is_last bool) { - var self hasherHandle - hasherSetup(handle, params, data, position, input_size, is_last) - self = *handle - self.StitchToPreviousBlock(input_size, position, data, mask) -} diff --git a/src/vendor/github.com/andybalholm/brotli/hash_composite.go b/src/vendor/github.com/andybalholm/brotli/hash_composite.go deleted file mode 100644 index a65fe2e6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/hash_composite.go +++ /dev/null @@ -1,93 +0,0 @@ -package brotli - -/* Copyright 2018 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func (h *hashComposite) HashTypeLength() uint { - var a uint = h.ha.HashTypeLength() - var b uint = h.hb.HashTypeLength() - if a > b { - return a - } else { - return b - } -} - -func (h *hashComposite) StoreLookahead() uint { - var a uint = h.ha.StoreLookahead() - var b uint = h.hb.StoreLookahead() - if a > b { - return a - } else { - return b - } -} - -/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A - and HASHER_B. */ -type hashComposite struct { - hasherCommon - ha hasherHandle - hb hasherHandle - params *encoderParams -} - -func (h *hashComposite) Initialize(params *encoderParams) { - h.params = params -} - -/* TODO: Initialize of the hashers is defered to Prepare (and params - remembered here) because we don't get the one_shot and input_size params - here that are needed to know the memory size of them. Instead provide - those params to all hashers InitializehashComposite */ -func (h *hashComposite) Prepare(one_shot bool, input_size uint, data []byte) { - if h.ha == nil { - var common_a *hasherCommon - var common_b *hasherCommon - - common_a = h.ha.Common() - common_a.params = h.params.hasher - common_a.is_prepared_ = false - common_a.dict_num_lookups = 0 - common_a.dict_num_matches = 0 - h.ha.Initialize(h.params) - - common_b = h.hb.Common() - common_b.params = h.params.hasher - common_b.is_prepared_ = false - common_b.dict_num_lookups = 0 - common_b.dict_num_matches = 0 - h.hb.Initialize(h.params) - } - - h.ha.Prepare(one_shot, input_size, data) - h.hb.Prepare(one_shot, input_size, data) -} - -func (h *hashComposite) Store(data []byte, mask uint, ix uint) { - h.ha.Store(data, mask, ix) - h.hb.Store(data, mask, ix) -} - -func (h *hashComposite) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) { - h.ha.StoreRange(data, mask, ix_start, ix_end) - h.hb.StoreRange(data, mask, ix_start, ix_end) -} - -func (h *hashComposite) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ring_buffer_mask uint) { - h.ha.StitchToPreviousBlock(num_bytes, position, ringbuffer, ring_buffer_mask) - h.hb.StitchToPreviousBlock(num_bytes, position, ringbuffer, ring_buffer_mask) -} - -func (h *hashComposite) PrepareDistanceCache(distance_cache []int) { - h.ha.PrepareDistanceCache(distance_cache) - h.hb.PrepareDistanceCache(distance_cache) -} - -func (h *hashComposite) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - h.ha.FindLongestMatch(dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out) - h.hb.FindLongestMatch(dictionary, data, ring_buffer_mask, distance_cache, cur_ix, max_length, max_backward, gap, max_distance, out) -} diff --git a/src/vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go b/src/vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go deleted file mode 100644 index 306e46d3..00000000 --- a/src/vendor/github.com/andybalholm/brotli/hash_forgetful_chain.go +++ /dev/null @@ -1,252 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2016 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func (*hashForgetfulChain) HashTypeLength() uint { - return 4 -} - -func (*hashForgetfulChain) StoreLookahead() uint { - return 4 -} - -/* HashBytes is the function that chooses the bucket to place the address in.*/ -func (h *hashForgetfulChain) HashBytes(data []byte) uint { - var hash uint32 = binary.LittleEndian.Uint32(data) * kHashMul32 - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return uint(hash >> (32 - h.bucketBits)) -} - -type slot struct { - delta uint16 - next uint16 -} - -/* A (forgetful) hash table to the data seen by the compressor, to - help create backward references to previous data. - - Hashes are stored in chains which are bucketed to groups. Group of chains - share a storage "bank". When more than "bank size" chain nodes are added, - oldest nodes are replaced; this way several chains may share a tail. */ -type hashForgetfulChain struct { - hasherCommon - - bucketBits uint - numBanks uint - bankBits uint - numLastDistancesToCheck int - - addr []uint32 - head []uint16 - tiny_hash [65536]byte - banks [][]slot - free_slot_idx []uint16 - max_hops uint -} - -func (h *hashForgetfulChain) Initialize(params *encoderParams) { - var q uint - if params.quality > 6 { - q = 7 - } else { - q = 8 - } - h.max_hops = q << uint(params.quality-4) - - bankSize := 1 << h.bankBits - bucketSize := 1 << h.bucketBits - - h.addr = make([]uint32, bucketSize) - h.head = make([]uint16, bucketSize) - h.banks = make([][]slot, h.numBanks) - for i := range h.banks { - h.banks[i] = make([]slot, bankSize) - } - h.free_slot_idx = make([]uint16, h.numBanks) -} - -func (h *hashForgetfulChain) Prepare(one_shot bool, input_size uint, data []byte) { - var partial_prepare_threshold uint = (1 << h.bucketBits) >> 6 - /* Partial preparation is 100 times slower (per socket). */ - if one_shot && input_size <= partial_prepare_threshold { - var i uint - for i = 0; i < input_size; i++ { - var bucket uint = h.HashBytes(data[i:]) - - /* See InitEmpty comment. */ - h.addr[bucket] = 0xCCCCCCCC - - h.head[bucket] = 0xCCCC - } - } else { - /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position - processed by hasher never reaches 3GB + 64M; this makes all new chains - to be terminated after the first node. */ - for i := range h.addr { - h.addr[i] = 0xCCCCCCCC - } - - for i := range h.head { - h.head[i] = 0 - } - } - - h.tiny_hash = [65536]byte{} - for i := range h.free_slot_idx { - h.free_slot_idx[i] = 0 - } -} - -/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend - node to corresponding chain; also update tiny_hash for current position. */ -func (h *hashForgetfulChain) Store(data []byte, mask uint, ix uint) { - var key uint = h.HashBytes(data[ix&mask:]) - var bank uint = key & (h.numBanks - 1) - idx := uint(h.free_slot_idx[bank]) & ((1 << h.bankBits) - 1) - h.free_slot_idx[bank]++ - var delta uint = ix - uint(h.addr[key]) - h.tiny_hash[uint16(ix)] = byte(key) - if delta > 0xFFFF { - delta = 0xFFFF - } - h.banks[bank][idx].delta = uint16(delta) - h.banks[bank][idx].next = h.head[key] - h.addr[key] = uint32(ix) - h.head[key] = uint16(idx) -} - -func (h *hashForgetfulChain) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) { - var i uint - for i = ix_start; i < ix_end; i++ { - h.Store(data, mask, i) - } -} - -func (h *hashForgetfulChain) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ring_buffer_mask uint) { - if num_bytes >= h.HashTypeLength()-1 && position >= 3 { - /* Prepare the hashes for three last bytes of the last write. - These could not be calculated before, since they require knowledge - of both the previous and the current block. */ - h.Store(ringbuffer, ring_buffer_mask, position-3) - h.Store(ringbuffer, ring_buffer_mask, position-2) - h.Store(ringbuffer, ring_buffer_mask, position-1) - } -} - -func (h *hashForgetfulChain) PrepareDistanceCache(distance_cache []int) { - prepareDistanceCache(distance_cache, h.numLastDistancesToCheck) -} - -/* Find a longest backward match of &data[cur_ix] up to the length of - max_length and stores the position cur_ix in the hash table. - - REQUIRES: PrepareDistanceCachehashForgetfulChain must be invoked for current distance cache - values; if this method is invoked repeatedly with the same distance - cache values, it is enough to invoke PrepareDistanceCachehashForgetfulChain once. - - Does not look for matches longer than max_length. - Does not look for matches further away than max_backward. - Writes the best match into |out|. - |out|->score is updated only if a better match is found. */ -func (h *hashForgetfulChain) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var min_score uint = out.score - var best_score uint = out.score - var best_len uint = out.len - var key uint = h.HashBytes(data[cur_ix_masked:]) - var tiny_hash byte = byte(key) - /* Don't accept a short copy from far away. */ - out.len = 0 - - out.len_code_delta = 0 - - /* Try last distance first. */ - for i := 0; i < h.numLastDistancesToCheck; i++ { - var backward uint = uint(distance_cache[i]) - var prev_ix uint = (cur_ix - backward) - - /* For distance code 0 we want to consider 2-byte matches. */ - if i > 0 && h.tiny_hash[uint16(prev_ix)] != tiny_hash { - continue - } - if prev_ix >= cur_ix || backward > max_backward { - continue - } - - prev_ix &= ring_buffer_mask - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 2 { - var score uint = backwardReferenceScoreUsingLastDistance(uint(len)) - if best_score < score { - if i != 0 { - score -= backwardReferencePenaltyUsingLastDistance(uint(i)) - } - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - } - { - var bank uint = key & (h.numBanks - 1) - var backward uint = 0 - var hops uint = h.max_hops - var delta uint = cur_ix - uint(h.addr[key]) - var slot uint = uint(h.head[key]) - for { - tmp6 := hops - hops-- - if tmp6 == 0 { - break - } - var prev_ix uint - var last uint = slot - backward += delta - if backward > max_backward { - break - } - prev_ix = (cur_ix - backward) & ring_buffer_mask - slot = uint(h.banks[bank][last].next) - delta = uint(h.banks[bank][last].delta) - if cur_ix_masked+best_len > ring_buffer_mask || prev_ix+best_len > ring_buffer_mask || data[cur_ix_masked+best_len] != data[prev_ix+best_len] { - continue - } - { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - /* Comparing for >= 3 does not change the semantics, but just saves - for a few unnecessary binary logarithms in backward reference - score, since we are not interested in such short matches. */ - var score uint = backwardReferenceScore(uint(len), backward) - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = best_score - } - } - } - } - - h.Store(data, ring_buffer_mask, cur_ix) - } - - if out.score == min_score { - searchInStaticDictionary(dictionary, h, data[cur_ix_masked:], max_length, max_backward+gap, max_distance, out, false) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go b/src/vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go deleted file mode 100644 index 9375dc15..00000000 --- a/src/vendor/github.com/andybalholm/brotli/hash_longest_match_quickly.go +++ /dev/null @@ -1,214 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* For BUCKET_SWEEP == 1, enabling the dictionary lookup makes compression - a little faster (0.5% - 1%) and it compresses 0.15% better on small text - and HTML inputs. */ - -func (*hashLongestMatchQuickly) HashTypeLength() uint { - return 8 -} - -func (*hashLongestMatchQuickly) StoreLookahead() uint { - return 8 -} - -/* HashBytes is the function that chooses the bucket to place - the address in. The HashLongestMatch and hashLongestMatchQuickly - classes have separate, different implementations of hashing. */ -func (h *hashLongestMatchQuickly) HashBytes(data []byte) uint32 { - var hash uint64 = ((binary.LittleEndian.Uint64(data) << (64 - 8*h.hashLen)) * kHashMul64) - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return uint32(hash >> (64 - h.bucketBits)) -} - -/* A (forgetful) hash table to the data seen by the compressor, to - help create backward references to previous data. - - This is a hash map of fixed size (1 << 16). Starting from the - given index, 1 buckets are used to store values of a key. */ -type hashLongestMatchQuickly struct { - hasherCommon - - bucketBits uint - bucketSweep int - hashLen uint - useDictionary bool - - buckets []uint32 -} - -func (h *hashLongestMatchQuickly) Initialize(params *encoderParams) { - h.buckets = make([]uint32, 1<> 7 - /* Partial preparation is 100 times slower (per socket). */ - if one_shot && input_size <= partial_prepare_threshold { - var i uint - for i = 0; i < input_size; i++ { - var key uint32 = h.HashBytes(data[i:]) - for j := 0; j < h.bucketSweep; j++ { - h.buckets[key+uint32(j)] = 0 - } - } - } else { - /* It is not strictly necessary to fill this buffer here, but - not filling will make the results of the compression stochastic - (but correct). This is because random data would cause the - system to find accidentally good backward references here and there. */ - for i := range h.buckets { - h.buckets[i] = 0 - } - } -} - -/* Look at 5 bytes at &data[ix & mask]. - Compute a hash from these, and store the value somewhere within - [ix .. ix+3]. */ -func (h *hashLongestMatchQuickly) Store(data []byte, mask uint, ix uint) { - var key uint32 = h.HashBytes(data[ix&mask:]) - var off uint32 = uint32(ix>>3) % uint32(h.bucketSweep) - /* Wiggle the value with the bucket sweep range. */ - h.buckets[key+off] = uint32(ix) -} - -func (h *hashLongestMatchQuickly) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) { - var i uint - for i = ix_start; i < ix_end; i++ { - h.Store(data, mask, i) - } -} - -func (h *hashLongestMatchQuickly) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ringbuffer_mask uint) { - if num_bytes >= h.HashTypeLength()-1 && position >= 3 { - /* Prepare the hashes for three last bytes of the last write. - These could not be calculated before, since they require knowledge - of both the previous and the current block. */ - h.Store(ringbuffer, ringbuffer_mask, position-3) - h.Store(ringbuffer, ringbuffer_mask, position-2) - h.Store(ringbuffer, ringbuffer_mask, position-1) - } -} - -func (*hashLongestMatchQuickly) PrepareDistanceCache(distance_cache []int) { -} - -/* Find a longest backward match of &data[cur_ix & ring_buffer_mask] - up to the length of max_length and stores the position cur_ix in the - hash table. - - Does not look for matches longer than max_length. - Does not look for matches further away than max_backward. - Writes the best match into |out|. - |out|->score is updated only if a better match is found. */ -func (h *hashLongestMatchQuickly) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - var best_len_in uint = out.len - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var key uint32 = h.HashBytes(data[cur_ix_masked:]) - var compare_char int = int(data[cur_ix_masked+best_len_in]) - var min_score uint = out.score - var best_score uint = out.score - var best_len uint = best_len_in - var cached_backward uint = uint(distance_cache[0]) - var prev_ix uint = cur_ix - cached_backward - var bucket []uint32 - out.len_code_delta = 0 - if prev_ix < cur_ix { - prev_ix &= uint(uint32(ring_buffer_mask)) - if compare_char == int(data[prev_ix+best_len]) { - var len uint = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - var score uint = backwardReferenceScoreUsingLastDistance(uint(len)) - if best_score < score { - best_score = score - best_len = uint(len) - out.len = uint(len) - out.distance = cached_backward - out.score = best_score - compare_char = int(data[cur_ix_masked+best_len]) - if h.bucketSweep == 1 { - h.buckets[key] = uint32(cur_ix) - return - } - } - } - } - } - - if h.bucketSweep == 1 { - var backward uint - var len uint - - /* Only one to look for, don't bother to prepare for a loop. */ - prev_ix = uint(h.buckets[key]) - - h.buckets[key] = uint32(cur_ix) - backward = cur_ix - prev_ix - prev_ix &= uint(uint32(ring_buffer_mask)) - if compare_char != int(data[prev_ix+best_len_in]) { - return - } - - if backward == 0 || backward > max_backward { - return - } - - len = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - var score uint = backwardReferenceScore(uint(len), backward) - if best_score < score { - out.len = uint(len) - out.distance = backward - out.score = score - return - } - } - } else { - bucket = h.buckets[key:] - var i int - prev_ix = uint(bucket[0]) - bucket = bucket[1:] - for i = 0; i < h.bucketSweep; (func() { i++; tmp3 := bucket; bucket = bucket[1:]; prev_ix = uint(tmp3[0]) })() { - var backward uint = cur_ix - prev_ix - var len uint - prev_ix &= uint(uint32(ring_buffer_mask)) - if compare_char != int(data[prev_ix+best_len]) { - continue - } - - if backward == 0 || backward > max_backward { - continue - } - - len = findMatchLengthWithLimit(data[prev_ix:], data[cur_ix_masked:], max_length) - if len >= 4 { - var score uint = backwardReferenceScore(uint(len), backward) - if best_score < score { - best_score = score - best_len = uint(len) - out.len = best_len - out.distance = backward - out.score = score - compare_char = int(data[cur_ix_masked+best_len]) - } - } - } - } - - if h.useDictionary && min_score == out.score { - searchInStaticDictionary(dictionary, h, data[cur_ix_masked:], max_length, max_backward+gap, max_distance, out, true) - } - - h.buckets[key+uint32((cur_ix>>3)%uint(h.bucketSweep))] = uint32(cur_ix) -} diff --git a/src/vendor/github.com/andybalholm/brotli/hash_rolling.go b/src/vendor/github.com/andybalholm/brotli/hash_rolling.go deleted file mode 100644 index 6630fc07..00000000 --- a/src/vendor/github.com/andybalholm/brotli/hash_rolling.go +++ /dev/null @@ -1,168 +0,0 @@ -package brotli - -/* Copyright 2018 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* NOTE: this hasher does not search in the dictionary. It is used as - backup-hasher, the main hasher already searches in it. */ - -const kRollingHashMul32 uint32 = 69069 - -const kInvalidPosHashRolling uint32 = 0xffffffff - -/* This hasher uses a longer forward length, but returning a higher value here - will hurt compression by the main hasher when combined with a composite - hasher. The hasher tests for forward itself instead. */ -func (*hashRolling) HashTypeLength() uint { - return 4 -} - -func (*hashRolling) StoreLookahead() uint { - return 4 -} - -/* Computes a code from a single byte. A lookup table of 256 values could be - used, but simply adding 1 works about as good. */ -func (*hashRolling) HashByte(b byte) uint32 { - return uint32(b) + 1 -} - -func (h *hashRolling) HashRollingFunctionInitial(state uint32, add byte, factor uint32) uint32 { - return uint32(factor*state + h.HashByte(add)) -} - -func (h *hashRolling) HashRollingFunction(state uint32, add byte, rem byte, factor uint32, factor_remove uint32) uint32 { - return uint32(factor*state + h.HashByte(add) - factor_remove*h.HashByte(rem)) -} - -/* Rolling hash for long distance long string matches. Stores one position - per bucket, bucket key is computed over a long region. */ -type hashRolling struct { - hasherCommon - - jump int - - state uint32 - table []uint32 - next_ix uint - factor uint32 - factor_remove uint32 -} - -func (h *hashRolling) Initialize(params *encoderParams) { - h.state = 0 - h.next_ix = 0 - - h.factor = kRollingHashMul32 - - /* Compute the factor of the oldest byte to remove: factor**steps modulo - 0xffffffff (the multiplications rely on 32-bit overflow) */ - h.factor_remove = 1 - - for i := 0; i < 32; i += h.jump { - h.factor_remove *= h.factor - } - - h.table = make([]uint32, 16777216) - for i := 0; i < 16777216; i++ { - h.table[i] = kInvalidPosHashRolling - } -} - -func (h *hashRolling) Prepare(one_shot bool, input_size uint, data []byte) { - /* Too small size, cannot use this hasher. */ - if input_size < 32 { - return - } - h.state = 0 - for i := 0; i < 32; i += h.jump { - h.state = h.HashRollingFunctionInitial(h.state, data[i], h.factor) - } -} - -func (*hashRolling) Store(data []byte, mask uint, ix uint) { -} - -func (*hashRolling) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) { -} - -func (h *hashRolling) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ring_buffer_mask uint) { - var position_masked uint - /* In this case we must re-initialize the hasher from scratch from the - current position. */ - - var available uint = num_bytes - if position&uint(h.jump-1) != 0 { - var diff uint = uint(h.jump) - (position & uint(h.jump-1)) - if diff > available { - available = 0 - } else { - available = available - diff - } - position += diff - } - - position_masked = position & ring_buffer_mask - - /* wrapping around ringbuffer not handled. */ - if available > ring_buffer_mask-position_masked { - available = ring_buffer_mask - position_masked - } - - h.Prepare(false, available, ringbuffer[position&ring_buffer_mask:]) - h.next_ix = position -} - -func (*hashRolling) PrepareDistanceCache(distance_cache []int) { -} - -func (h *hashRolling) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) { - var cur_ix_masked uint = cur_ix & ring_buffer_mask - var pos uint = h.next_ix - - if cur_ix&uint(h.jump-1) != 0 { - return - } - - /* Not enough lookahead */ - if max_length < 32 { - return - } - - for pos = h.next_ix; pos <= cur_ix; pos += uint(h.jump) { - var code uint32 = h.state & ((16777216 * 64) - 1) - var rem byte = data[pos&ring_buffer_mask] - var add byte = data[(pos+32)&ring_buffer_mask] - var found_ix uint = uint(kInvalidPosHashRolling) - - h.state = h.HashRollingFunction(h.state, add, rem, h.factor, h.factor_remove) - - if code < 16777216 { - found_ix = uint(h.table[code]) - h.table[code] = uint32(pos) - if pos == cur_ix && uint32(found_ix) != kInvalidPosHashRolling { - /* The cast to 32-bit makes backward distances up to 4GB work even - if cur_ix is above 4GB, despite using 32-bit values in the table. */ - var backward uint = uint(uint32(cur_ix - found_ix)) - if backward <= max_backward { - var found_ix_masked uint = found_ix & ring_buffer_mask - var len uint = findMatchLengthWithLimit(data[found_ix_masked:], data[cur_ix_masked:], max_length) - if len >= 4 && len > out.len { - var score uint = backwardReferenceScore(uint(len), backward) - if score > out.score { - out.len = uint(len) - out.distance = backward - out.score = score - out.len_code_delta = 0 - } - } - } - } - } - } - - h.next_ix = cur_ix + uint(h.jump) -} diff --git a/src/vendor/github.com/andybalholm/brotli/histogram.go b/src/vendor/github.com/andybalholm/brotli/histogram.go deleted file mode 100644 index 0346622b..00000000 --- a/src/vendor/github.com/andybalholm/brotli/histogram.go +++ /dev/null @@ -1,226 +0,0 @@ -package brotli - -import "math" - -/* The distance symbols effectively used by "Large Window Brotli" (32-bit). */ -const numHistogramDistanceSymbols = 544 - -type histogramLiteral struct { - data_ [numLiteralSymbols]uint32 - total_count_ uint - bit_cost_ float64 -} - -func histogramClearLiteral(self *histogramLiteral) { - self.data_ = [numLiteralSymbols]uint32{} - self.total_count_ = 0 - self.bit_cost_ = math.MaxFloat64 -} - -func clearHistogramsLiteral(array []histogramLiteral, length uint) { - var i uint - for i = 0; i < length; i++ { - histogramClearLiteral(&array[i:][0]) - } -} - -func histogramAddLiteral(self *histogramLiteral, val uint) { - self.data_[val]++ - self.total_count_++ -} - -func histogramAddVectorLiteral(self *histogramLiteral, p []byte, n uint) { - self.total_count_ += n - n += 1 - for { - n-- - if n == 0 { - break - } - self.data_[p[0]]++ - p = p[1:] - } -} - -func histogramAddHistogramLiteral(self *histogramLiteral, v *histogramLiteral) { - var i uint - self.total_count_ += v.total_count_ - for i = 0; i < numLiteralSymbols; i++ { - self.data_[i] += v.data_[i] - } -} - -func histogramDataSizeLiteral() uint { - return numLiteralSymbols -} - -type histogramCommand struct { - data_ [numCommandSymbols]uint32 - total_count_ uint - bit_cost_ float64 -} - -func histogramClearCommand(self *histogramCommand) { - self.data_ = [numCommandSymbols]uint32{} - self.total_count_ = 0 - self.bit_cost_ = math.MaxFloat64 -} - -func clearHistogramsCommand(array []histogramCommand, length uint) { - var i uint - for i = 0; i < length; i++ { - histogramClearCommand(&array[i:][0]) - } -} - -func histogramAddCommand(self *histogramCommand, val uint) { - self.data_[val]++ - self.total_count_++ -} - -func histogramAddVectorCommand(self *histogramCommand, p []uint16, n uint) { - self.total_count_ += n - n += 1 - for { - n-- - if n == 0 { - break - } - self.data_[p[0]]++ - p = p[1:] - } -} - -func histogramAddHistogramCommand(self *histogramCommand, v *histogramCommand) { - var i uint - self.total_count_ += v.total_count_ - for i = 0; i < numCommandSymbols; i++ { - self.data_[i] += v.data_[i] - } -} - -func histogramDataSizeCommand() uint { - return numCommandSymbols -} - -type histogramDistance struct { - data_ [numDistanceSymbols]uint32 - total_count_ uint - bit_cost_ float64 -} - -func histogramClearDistance(self *histogramDistance) { - self.data_ = [numDistanceSymbols]uint32{} - self.total_count_ = 0 - self.bit_cost_ = math.MaxFloat64 -} - -func clearHistogramsDistance(array []histogramDistance, length uint) { - var i uint - for i = 0; i < length; i++ { - histogramClearDistance(&array[i:][0]) - } -} - -func histogramAddDistance(self *histogramDistance, val uint) { - self.data_[val]++ - self.total_count_++ -} - -func histogramAddVectorDistance(self *histogramDistance, p []uint16, n uint) { - self.total_count_ += n - n += 1 - for { - n-- - if n == 0 { - break - } - self.data_[p[0]]++ - p = p[1:] - } -} - -func histogramAddHistogramDistance(self *histogramDistance, v *histogramDistance) { - var i uint - self.total_count_ += v.total_count_ - for i = 0; i < numDistanceSymbols; i++ { - self.data_[i] += v.data_[i] - } -} - -func histogramDataSizeDistance() uint { - return numDistanceSymbols -} - -type blockSplitIterator struct { - split_ *blockSplit - idx_ uint - type_ uint - length_ uint -} - -func initBlockSplitIterator(self *blockSplitIterator, split *blockSplit) { - self.split_ = split - self.idx_ = 0 - self.type_ = 0 - if len(split.lengths) > 0 { - self.length_ = uint(split.lengths[0]) - } else { - self.length_ = 0 - } -} - -func blockSplitIteratorNext(self *blockSplitIterator) { - if self.length_ == 0 { - self.idx_++ - self.type_ = uint(self.split_.types[self.idx_]) - self.length_ = uint(self.split_.lengths[self.idx_]) - } - - self.length_-- -} - -func buildHistogramsWithContext(cmds []command, literal_split *blockSplit, insert_and_copy_split *blockSplit, dist_split *blockSplit, ringbuffer []byte, start_pos uint, mask uint, prev_byte byte, prev_byte2 byte, context_modes []int, literal_histograms []histogramLiteral, insert_and_copy_histograms []histogramCommand, copy_dist_histograms []histogramDistance) { - var pos uint = start_pos - var literal_it blockSplitIterator - var insert_and_copy_it blockSplitIterator - var dist_it blockSplitIterator - - initBlockSplitIterator(&literal_it, literal_split) - initBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split) - initBlockSplitIterator(&dist_it, dist_split) - for i := range cmds { - var cmd *command = &cmds[i] - var j uint - blockSplitIteratorNext(&insert_and_copy_it) - histogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], uint(cmd.cmd_prefix_)) - - /* TODO: unwrap iterator blocks. */ - for j = uint(cmd.insert_len_); j != 0; j-- { - var context uint - blockSplitIteratorNext(&literal_it) - context = literal_it.type_ - if context_modes != nil { - var lut contextLUT = getContextLUT(context_modes[context]) - context = (context << literalContextBits) + uint(getContext(prev_byte, prev_byte2, lut)) - } - - histogramAddLiteral(&literal_histograms[context], uint(ringbuffer[pos&mask])) - prev_byte2 = prev_byte - prev_byte = ringbuffer[pos&mask] - pos++ - } - - pos += uint(commandCopyLen(cmd)) - if commandCopyLen(cmd) != 0 { - prev_byte2 = ringbuffer[(pos-2)&mask] - prev_byte = ringbuffer[(pos-1)&mask] - if cmd.cmd_prefix_ >= 128 { - var context uint - blockSplitIteratorNext(&dist_it) - context = uint(uint32(dist_it.type_< bestQ && - (spec.Value == "*" || spec.Value == offer) { - bestQ = spec.Q - bestOffer = offer - } - } - } - if bestQ == 0 { - bestOffer = "" - } - return bestOffer -} - -// acceptSpec describes an Accept* header. -type acceptSpec struct { - Value string - Q float64 -} - -// parseAccept parses Accept* headers. -func parseAccept(header http.Header, key string) (specs []acceptSpec) { -loop: - for _, s := range header[key] { - for { - var spec acceptSpec - spec.Value, s = expectTokenSlash(s) - if spec.Value == "" { - continue loop - } - spec.Q = 1.0 - s = skipSpace(s) - if strings.HasPrefix(s, ";") { - s = skipSpace(s[1:]) - if !strings.HasPrefix(s, "q=") { - continue loop - } - spec.Q, s = expectQuality(s[2:]) - if spec.Q < 0.0 { - continue loop - } - } - specs = append(specs, spec) - s = skipSpace(s) - if !strings.HasPrefix(s, ",") { - continue loop - } - s = skipSpace(s[1:]) - } - } - return -} - -func skipSpace(s string) (rest string) { - i := 0 - for ; i < len(s); i++ { - if octetTypes[s[i]]&isSpace == 0 { - break - } - } - return s[i:] -} - -func expectTokenSlash(s string) (token, rest string) { - i := 0 - for ; i < len(s); i++ { - b := s[i] - if (octetTypes[b]&isToken == 0) && b != '/' { - break - } - } - return s[:i], s[i:] -} - -func expectQuality(s string) (q float64, rest string) { - switch { - case len(s) == 0: - return -1, "" - case s[0] == '0': - q = 0 - case s[0] == '1': - q = 1 - default: - return -1, "" - } - s = s[1:] - if !strings.HasPrefix(s, ".") { - return q, s - } - s = s[1:] - i := 0 - n := 0 - d := 1 - for ; i < len(s); i++ { - b := s[i] - if b < '0' || b > '9' { - break - } - n = n*10 + int(b) - '0' - d *= 10 - } - return q + float64(n)/float64(d), s[i:] -} - -// Octet types from RFC 2616. -var octetTypes [256]octetType - -type octetType byte - -const ( - isToken octetType = 1 << iota - isSpace -) - -func init() { - // OCTET = - // CHAR = - // CTL = - // CR = - // LF = - // SP = - // HT = - // <"> = - // CRLF = CR LF - // LWS = [CRLF] 1*( SP | HT ) - // TEXT = - // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT - // token = 1* - // qdtext = > - - for c := 0; c < 256; c++ { - var t octetType - isCtl := c <= 31 || c == 127 - isChar := 0 <= c && c <= 127 - isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) - if strings.ContainsRune(" \t\r\n", rune(c)) { - t |= isSpace - } - if isChar && !isCtl && !isSeparator { - t |= isToken - } - octetTypes[c] = t - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/huffman.go b/src/vendor/github.com/andybalholm/brotli/huffman.go deleted file mode 100644 index 182f3d2a..00000000 --- a/src/vendor/github.com/andybalholm/brotli/huffman.go +++ /dev/null @@ -1,653 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Utilities for building Huffman decoding tables. */ - -const huffmanMaxCodeLength = 15 - -/* Maximum possible Huffman table size for an alphabet size of (index * 32), - max code length 15 and root table bits 8. */ -var kMaxHuffmanTableSize = []uint16{ - 256, - 402, - 436, - 468, - 500, - 534, - 566, - 598, - 630, - 662, - 694, - 726, - 758, - 790, - 822, - 854, - 886, - 920, - 952, - 984, - 1016, - 1048, - 1080, - 1112, - 1144, - 1176, - 1208, - 1240, - 1272, - 1304, - 1336, - 1368, - 1400, - 1432, - 1464, - 1496, - 1528, -} - -/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */ -const huffmanMaxSize26 = 396 - -/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */ -const huffmanMaxSize258 = 632 - -/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */ -const huffmanMaxSize272 = 646 - -const huffmanMaxCodeLengthCodeLength = 5 - -/* Do not create this struct directly - use the ConstructHuffmanCode - * constructor below! */ -type huffmanCode struct { - bits byte - value uint16 -} - -func constructHuffmanCode(bits byte, value uint16) huffmanCode { - var h huffmanCode - h.bits = bits - h.value = value - return h -} - -/* Builds Huffman lookup table assuming code lengths are in symbol order. */ - -/* Builds Huffman lookup table assuming code lengths are in symbol order. - Returns size of resulting table. */ - -/* Builds a simple Huffman table. The |num_symbols| parameter is to be - interpreted as follows: 0 means 1 symbol, 1 means 2 symbols, - 2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2], - 4 means 4 symbols with lengths [1, 2, 3, 3]. */ - -/* Contains a collection of Huffman trees with the same alphabet size. */ -/* max_symbol is needed due to simple codes since log2(alphabet_size) could be - greater than log2(max_symbol). */ -type huffmanTreeGroup struct { - htrees [][]huffmanCode - codes []huffmanCode - alphabet_size uint16 - max_symbol uint16 - num_htrees uint16 -} - -const reverseBitsMax = 8 - -const reverseBitsBase = 0 - -var kReverseBits = [1 << reverseBitsMax]byte{ - 0x00, - 0x80, - 0x40, - 0xC0, - 0x20, - 0xA0, - 0x60, - 0xE0, - 0x10, - 0x90, - 0x50, - 0xD0, - 0x30, - 0xB0, - 0x70, - 0xF0, - 0x08, - 0x88, - 0x48, - 0xC8, - 0x28, - 0xA8, - 0x68, - 0xE8, - 0x18, - 0x98, - 0x58, - 0xD8, - 0x38, - 0xB8, - 0x78, - 0xF8, - 0x04, - 0x84, - 0x44, - 0xC4, - 0x24, - 0xA4, - 0x64, - 0xE4, - 0x14, - 0x94, - 0x54, - 0xD4, - 0x34, - 0xB4, - 0x74, - 0xF4, - 0x0C, - 0x8C, - 0x4C, - 0xCC, - 0x2C, - 0xAC, - 0x6C, - 0xEC, - 0x1C, - 0x9C, - 0x5C, - 0xDC, - 0x3C, - 0xBC, - 0x7C, - 0xFC, - 0x02, - 0x82, - 0x42, - 0xC2, - 0x22, - 0xA2, - 0x62, - 0xE2, - 0x12, - 0x92, - 0x52, - 0xD2, - 0x32, - 0xB2, - 0x72, - 0xF2, - 0x0A, - 0x8A, - 0x4A, - 0xCA, - 0x2A, - 0xAA, - 0x6A, - 0xEA, - 0x1A, - 0x9A, - 0x5A, - 0xDA, - 0x3A, - 0xBA, - 0x7A, - 0xFA, - 0x06, - 0x86, - 0x46, - 0xC6, - 0x26, - 0xA6, - 0x66, - 0xE6, - 0x16, - 0x96, - 0x56, - 0xD6, - 0x36, - 0xB6, - 0x76, - 0xF6, - 0x0E, - 0x8E, - 0x4E, - 0xCE, - 0x2E, - 0xAE, - 0x6E, - 0xEE, - 0x1E, - 0x9E, - 0x5E, - 0xDE, - 0x3E, - 0xBE, - 0x7E, - 0xFE, - 0x01, - 0x81, - 0x41, - 0xC1, - 0x21, - 0xA1, - 0x61, - 0xE1, - 0x11, - 0x91, - 0x51, - 0xD1, - 0x31, - 0xB1, - 0x71, - 0xF1, - 0x09, - 0x89, - 0x49, - 0xC9, - 0x29, - 0xA9, - 0x69, - 0xE9, - 0x19, - 0x99, - 0x59, - 0xD9, - 0x39, - 0xB9, - 0x79, - 0xF9, - 0x05, - 0x85, - 0x45, - 0xC5, - 0x25, - 0xA5, - 0x65, - 0xE5, - 0x15, - 0x95, - 0x55, - 0xD5, - 0x35, - 0xB5, - 0x75, - 0xF5, - 0x0D, - 0x8D, - 0x4D, - 0xCD, - 0x2D, - 0xAD, - 0x6D, - 0xED, - 0x1D, - 0x9D, - 0x5D, - 0xDD, - 0x3D, - 0xBD, - 0x7D, - 0xFD, - 0x03, - 0x83, - 0x43, - 0xC3, - 0x23, - 0xA3, - 0x63, - 0xE3, - 0x13, - 0x93, - 0x53, - 0xD3, - 0x33, - 0xB3, - 0x73, - 0xF3, - 0x0B, - 0x8B, - 0x4B, - 0xCB, - 0x2B, - 0xAB, - 0x6B, - 0xEB, - 0x1B, - 0x9B, - 0x5B, - 0xDB, - 0x3B, - 0xBB, - 0x7B, - 0xFB, - 0x07, - 0x87, - 0x47, - 0xC7, - 0x27, - 0xA7, - 0x67, - 0xE7, - 0x17, - 0x97, - 0x57, - 0xD7, - 0x37, - 0xB7, - 0x77, - 0xF7, - 0x0F, - 0x8F, - 0x4F, - 0xCF, - 0x2F, - 0xAF, - 0x6F, - 0xEF, - 0x1F, - 0x9F, - 0x5F, - 0xDF, - 0x3F, - 0xBF, - 0x7F, - 0xFF, -} - -const reverseBitsLowest = (uint64(1) << (reverseBitsMax - 1 + reverseBitsBase)) - -/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX), - where reverse(value, len) is the bit-wise reversal of the len least - significant bits of value. */ -func reverseBits8(num uint64) uint64 { - return uint64(kReverseBits[num]) -} - -/* Stores code in table[0], table[step], table[2*step], ..., table[end] */ -/* Assumes that end is an integer multiple of step */ -func replicateValue(table []huffmanCode, step int, end int, code huffmanCode) { - for { - end -= step - table[end] = code - if end <= 0 { - break - } - } -} - -/* Returns the table width of the next 2nd level table. |count| is the histogram - of bit lengths for the remaining symbols, |len| is the code length of the - next processed symbol. */ -func nextTableBitSize(count []uint16, len int, root_bits int) int { - var left int = 1 << uint(len-root_bits) - for len < huffmanMaxCodeLength { - left -= int(count[len]) - if left <= 0 { - break - } - len++ - left <<= 1 - } - - return len - root_bits -} - -func buildCodeLengthsHuffmanTable(table []huffmanCode, code_lengths []byte, count []uint16) { - var code huffmanCode /* current table entry */ /* symbol index in original or sorted table */ /* prefix code */ /* prefix code addend */ /* step size to replicate values in current table */ /* size of current table */ /* symbols sorted by code length */ - var symbol int - var key uint64 - var key_step uint64 - var step int - var table_size int - var sorted [codeLengthCodes]int - var offset [huffmanMaxCodeLengthCodeLength + 1]int - var bits int - var bits_count int - /* offsets in sorted table for each length */ - assert(huffmanMaxCodeLengthCodeLength <= reverseBitsMax) - - /* Generate offsets into sorted symbol table by code length. */ - symbol = -1 - - bits = 1 - var i int - for i = 0; i < huffmanMaxCodeLengthCodeLength; i++ { - symbol += int(count[bits]) - offset[bits] = symbol - bits++ - } - - /* Symbols with code length 0 are placed after all other symbols. */ - offset[0] = codeLengthCodes - 1 - - /* Sort symbols by length, by symbol order within each length. */ - symbol = codeLengthCodes - - for { - var i int - for i = 0; i < 6; i++ { - symbol-- - sorted[offset[code_lengths[symbol]]] = symbol - offset[code_lengths[symbol]]-- - } - if symbol == 0 { - break - } - } - - table_size = 1 << huffmanMaxCodeLengthCodeLength - - /* Special case: all symbols but one have 0 code length. */ - if offset[0] == 0 { - code = constructHuffmanCode(0, uint16(sorted[0])) - for key = 0; key < uint64(table_size); key++ { - table[key] = code - } - - return - } - - /* Fill in table. */ - key = 0 - - key_step = reverseBitsLowest - symbol = 0 - bits = 1 - step = 2 - for { - for bits_count = int(count[bits]); bits_count != 0; bits_count-- { - code = constructHuffmanCode(byte(bits), uint16(sorted[symbol])) - symbol++ - replicateValue(table[reverseBits8(key):], step, table_size, code) - key += key_step - } - - step <<= 1 - key_step >>= 1 - bits++ - if bits > huffmanMaxCodeLengthCodeLength { - break - } - } -} - -func buildHuffmanTable(root_table []huffmanCode, root_bits int, symbol_lists symbolList, count []uint16) uint32 { - var code huffmanCode /* current table entry */ /* next available space in table */ /* current code length */ /* symbol index in original or sorted table */ /* prefix code */ /* prefix code addend */ /* 2nd level table prefix code */ /* 2nd level table prefix code addend */ /* step size to replicate values in current table */ /* key length of current table */ /* size of current table */ /* sum of root table size and 2nd level table sizes */ - var table []huffmanCode - var len int - var symbol int - var key uint64 - var key_step uint64 - var sub_key uint64 - var sub_key_step uint64 - var step int - var table_bits int - var table_size int - var total_size int - var max_length int = -1 - var bits int - var bits_count int - - assert(root_bits <= reverseBitsMax) - assert(huffmanMaxCodeLength-root_bits <= reverseBitsMax) - - for symbolListGet(symbol_lists, max_length) == 0xFFFF { - max_length-- - } - max_length += huffmanMaxCodeLength + 1 - - table = root_table - table_bits = root_bits - table_size = 1 << uint(table_bits) - total_size = table_size - - /* Fill in the root table. Reduce the table size to if possible, - and create the repetitions by memcpy. */ - if table_bits > max_length { - table_bits = max_length - table_size = 1 << uint(table_bits) - } - - key = 0 - key_step = reverseBitsLowest - bits = 1 - step = 2 - for { - symbol = bits - (huffmanMaxCodeLength + 1) - for bits_count = int(count[bits]); bits_count != 0; bits_count-- { - symbol = int(symbolListGet(symbol_lists, symbol)) - code = constructHuffmanCode(byte(bits), uint16(symbol)) - replicateValue(table[reverseBits8(key):], step, table_size, code) - key += key_step - } - - step <<= 1 - key_step >>= 1 - bits++ - if bits > table_bits { - break - } - } - - /* If root_bits != table_bits then replicate to fill the remaining slots. */ - for total_size != table_size { - copy(table[table_size:], table[:uint(table_size)]) - table_size <<= 1 - } - - /* Fill in 2nd level tables and add pointers to root table. */ - key_step = reverseBitsLowest >> uint(root_bits-1) - - sub_key = reverseBitsLowest << 1 - sub_key_step = reverseBitsLowest - len = root_bits + 1 - step = 2 - for ; len <= max_length; len++ { - symbol = len - (huffmanMaxCodeLength + 1) - for ; count[len] != 0; count[len]-- { - if sub_key == reverseBitsLowest<<1 { - table = table[table_size:] - table_bits = nextTableBitSize(count, int(len), root_bits) - table_size = 1 << uint(table_bits) - total_size += table_size - sub_key = reverseBits8(key) - key += key_step - root_table[sub_key] = constructHuffmanCode(byte(table_bits+root_bits), uint16(uint64(uint(-cap(table)+cap(root_table)))-sub_key)) - sub_key = 0 - } - - symbol = int(symbolListGet(symbol_lists, symbol)) - code = constructHuffmanCode(byte(len-root_bits), uint16(symbol)) - replicateValue(table[reverseBits8(sub_key):], step, table_size, code) - sub_key += sub_key_step - } - - step <<= 1 - sub_key_step >>= 1 - } - - return uint32(total_size) -} - -func buildSimpleHuffmanTable(table []huffmanCode, root_bits int, val []uint16, num_symbols uint32) uint32 { - var table_size uint32 = 1 - var goal_size uint32 = 1 << uint(root_bits) - switch num_symbols { - case 0: - table[0] = constructHuffmanCode(0, val[0]) - - case 1: - if val[1] > val[0] { - table[0] = constructHuffmanCode(1, val[0]) - table[1] = constructHuffmanCode(1, val[1]) - } else { - table[0] = constructHuffmanCode(1, val[1]) - table[1] = constructHuffmanCode(1, val[0]) - } - - table_size = 2 - - case 2: - table[0] = constructHuffmanCode(1, val[0]) - table[2] = constructHuffmanCode(1, val[0]) - if val[2] > val[1] { - table[1] = constructHuffmanCode(2, val[1]) - table[3] = constructHuffmanCode(2, val[2]) - } else { - table[1] = constructHuffmanCode(2, val[2]) - table[3] = constructHuffmanCode(2, val[1]) - } - - table_size = 4 - - case 3: - var i int - var k int - for i = 0; i < 3; i++ { - for k = i + 1; k < 4; k++ { - if val[k] < val[i] { - var t uint16 = val[k] - val[k] = val[i] - val[i] = t - } - } - } - - table[0] = constructHuffmanCode(2, val[0]) - table[2] = constructHuffmanCode(2, val[1]) - table[1] = constructHuffmanCode(2, val[2]) - table[3] = constructHuffmanCode(2, val[3]) - table_size = 4 - - case 4: - if val[3] < val[2] { - var t uint16 = val[3] - val[3] = val[2] - val[2] = t - } - - table[0] = constructHuffmanCode(1, val[0]) - table[1] = constructHuffmanCode(2, val[1]) - table[2] = constructHuffmanCode(1, val[0]) - table[3] = constructHuffmanCode(3, val[2]) - table[4] = constructHuffmanCode(1, val[0]) - table[5] = constructHuffmanCode(2, val[1]) - table[6] = constructHuffmanCode(1, val[0]) - table[7] = constructHuffmanCode(3, val[3]) - table_size = 8 - } - - for table_size != goal_size { - copy(table[table_size:], table[:uint(table_size)]) - table_size <<= 1 - } - - return goal_size -} diff --git a/src/vendor/github.com/andybalholm/brotli/literal_cost.go b/src/vendor/github.com/andybalholm/brotli/literal_cost.go deleted file mode 100644 index 5a9ace94..00000000 --- a/src/vendor/github.com/andybalholm/brotli/literal_cost.go +++ /dev/null @@ -1,182 +0,0 @@ -package brotli - -func utf8Position(last uint, c uint, clamp uint) uint { - if c < 128 { - return 0 /* Next one is the 'Byte 1' again. */ - } else if c >= 192 { /* Next one is the 'Byte 2' of utf-8 encoding. */ - return brotli_min_size_t(1, clamp) - } else { - /* Let's decide over the last byte if this ends the sequence. */ - if last < 0xE0 { - return 0 /* Completed two or three byte coding. */ /* Next one is the 'Byte 3' of utf-8 encoding. */ - } else { - return brotli_min_size_t(2, clamp) - } - } -} - -func decideMultiByteStatsLevel(pos uint, len uint, mask uint, data []byte) uint { - var counts = [3]uint{0} /* should be 2, but 1 compresses better. */ - var max_utf8 uint = 1 - var last_c uint = 0 - var i uint - for i = 0; i < len; i++ { - var c uint = uint(data[(pos+i)&mask]) - counts[utf8Position(last_c, c, 2)]++ - last_c = c - } - - if counts[2] < 500 { - max_utf8 = 1 - } - - if counts[1]+counts[2] < 25 { - max_utf8 = 0 - } - - return max_utf8 -} - -func estimateBitCostsForLiteralsUTF8(pos uint, len uint, mask uint, data []byte, cost []float32) { - var max_utf8 uint = decideMultiByteStatsLevel(pos, uint(len), mask, data) - /* Bootstrap histograms. */ - var histogram = [3][256]uint{[256]uint{0}} - var window_half uint = 495 - var in_window uint = brotli_min_size_t(window_half, uint(len)) - var in_window_utf8 = [3]uint{0} - /* max_utf8 is 0 (normal ASCII single byte modeling), - 1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */ - - var i uint - { - var last_c uint = 0 - var utf8_pos uint = 0 - for i = 0; i < in_window; i++ { - var c uint = uint(data[(pos+i)&mask]) - histogram[utf8_pos][c]++ - in_window_utf8[utf8_pos]++ - utf8_pos = utf8Position(last_c, c, max_utf8) - last_c = c - } - } - - /* Compute bit costs with sliding window. */ - for i = 0; i < len; i++ { - if i >= window_half { - var c uint - var last_c uint - if i < window_half+1 { - c = 0 - } else { - c = uint(data[(pos+i-window_half-1)&mask]) - } - if i < window_half+2 { - last_c = 0 - } else { - last_c = uint(data[(pos+i-window_half-2)&mask]) - } - /* Remove a byte in the past. */ - - var utf8_pos2 uint = utf8Position(last_c, c, max_utf8) - histogram[utf8_pos2][data[(pos+i-window_half)&mask]]-- - in_window_utf8[utf8_pos2]-- - } - - if i+window_half < len { - var c uint = uint(data[(pos+i+window_half-1)&mask]) - var last_c uint = uint(data[(pos+i+window_half-2)&mask]) - /* Add a byte in the future. */ - - var utf8_pos2 uint = utf8Position(last_c, c, max_utf8) - histogram[utf8_pos2][data[(pos+i+window_half)&mask]]++ - in_window_utf8[utf8_pos2]++ - } - { - var c uint - var last_c uint - if i < 1 { - c = 0 - } else { - c = uint(data[(pos+i-1)&mask]) - } - if i < 2 { - last_c = 0 - } else { - last_c = uint(data[(pos+i-2)&mask]) - } - var utf8_pos uint = utf8Position(last_c, c, max_utf8) - var masked_pos uint = (pos + i) & mask - var histo uint = histogram[utf8_pos][data[masked_pos]] - var lit_cost float64 - if histo == 0 { - histo = 1 - } - - lit_cost = fastLog2(in_window_utf8[utf8_pos]) - fastLog2(histo) - lit_cost += 0.02905 - if lit_cost < 1.0 { - lit_cost *= 0.5 - lit_cost += 0.5 - } - - /* Make the first bytes more expensive -- seems to help, not sure why. - Perhaps because the entropy source is changing its properties - rapidly in the beginning of the file, perhaps because the beginning - of the data is a statistical "anomaly". */ - if i < 2000 { - lit_cost += 0.7 - (float64(2000-i) / 2000.0 * 0.35) - } - - cost[i] = float32(lit_cost) - } - } -} - -func estimateBitCostsForLiterals(pos uint, len uint, mask uint, data []byte, cost []float32) { - if isMostlyUTF8(data, pos, mask, uint(len), kMinUTF8Ratio) { - estimateBitCostsForLiteralsUTF8(pos, uint(len), mask, data, cost) - return - } else { - var histogram = [256]uint{0} - var window_half uint = 2000 - var in_window uint = brotli_min_size_t(window_half, uint(len)) - var i uint - /* Bootstrap histogram. */ - for i = 0; i < in_window; i++ { - histogram[data[(pos+i)&mask]]++ - } - - /* Compute bit costs with sliding window. */ - for i = 0; i < len; i++ { - var histo uint - if i >= window_half { - /* Remove a byte in the past. */ - histogram[data[(pos+i-window_half)&mask]]-- - - in_window-- - } - - if i+window_half < len { - /* Add a byte in the future. */ - histogram[data[(pos+i+window_half)&mask]]++ - - in_window++ - } - - histo = histogram[data[(pos+i)&mask]] - if histo == 0 { - histo = 1 - } - { - var lit_cost float64 = fastLog2(in_window) - fastLog2(histo) - lit_cost += 0.029 - if lit_cost < 1.0 { - lit_cost *= 0.5 - lit_cost += 0.5 - } - - cost[i] = float32(lit_cost) - } - } - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go deleted file mode 100644 index bdafbd64..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain1.go +++ /dev/null @@ -1,212 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" - "math/bits" - "slices" -) - -const ( - bargain1TableBits = 18 - bargain1TableSize = 1 << bargain1TableBits -) - -// Bargain1 is a MatchFinder that attempts to find the encoding with the lowest -// "bit cost", using 1 hash length (6). -type Bargain1 struct { - MaxDistance int - - // Skip is whether to look for matches at every other byte instead of every - // byte (to increase speed but decrease compression). - Skip bool - - history []byte - table6 [bargain1TableSize]tableEntry - - // holding onto buffers to reduce allocations: - - arrivals []arrival - matches []Match -} - -func (z *Bargain1) Reset() { - z.table6 = [bargain1TableSize]tableEntry{} - z.history = z.history[:0] -} - -func (z *Bargain1) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - var histogram [256]uint32 - for _, b := range src { - histogram[b]++ - } - var byteCost [256]float32 - for b, n := range histogram { - cost := max(math.Log2(float64(len(src))/float64(n)), 1) - byteCost[b] = float32(cost) - } - - // Each element in arrivals corresponds to the position just after - // the corresponding byte in src. - arrivals := z.arrivals - if len(arrivals) < len(src) { - arrivals = make([]arrival, len(src)) - z.arrivals = arrivals - } else { - arrivals = arrivals[:len(src)] - for i := range arrivals { - arrivals[i] = arrival{} - } - } - - if len(z.history) > z.MaxDistance*2 { - delta := len(z.history) - z.MaxDistance - copy(z.history, z.history[delta:]) - z.history = z.history[:z.MaxDistance] - - for i := range z.table6 { - v := z.table6[i].offset - v -= int32(delta) - if v < 0 { - z.table6[i] = tableEntry{} - } else { - z.table6[i].offset = v - } - } - } - - historyLen := len(z.history) - z.history = append(z.history, src...) - src = z.history - - addMatch := func(m absoluteMatch, unmatched int, repeat bool) { - var startCost float32 - if m.Start > historyLen { - startCost = arrivals[m.Start-historyLen-1].cost - } - insertCost := float32(bits.Len(uint(unmatched))) - var distanceCost float32 - if !repeat { - distanceCost = float32(bits.Len(uint(m.Start - m.Match))) - } - cost := startCost + baseMatchCost + insertCost + distanceCost - for j := m.End; j >= m.Start+3; j-- { - a := &arrivals[j-historyLen-1] - if a.cost > 0 && a.cost <= cost { - break - } - *a = arrival{ - length: uint32(j - m.Start), - distance: uint32(m.Start - m.Match), - cost: cost, - } - } - } - - var nextOverlapSearch int - - for i := historyLen; i < len(src); i++ { - var arrivedHere arrival - if i > historyLen { - arrivedHere = arrivals[i-historyLen-1] - } - - unmatched := 0 - if arrivedHere.distance == 0 { - unmatched = int(arrivedHere.length) - } - prevDistance := 0 - if unmatched != 0 && i-unmatched > historyLen { - prevDistance = int(arrivals[i-historyLen-1-unmatched].distance) - } - - literalCost := byteCost[src[i]] - nextArrival := &arrivals[i-historyLen] - if nextArrival.cost == 0 || arrivedHere.cost+literalCost < nextArrival.cost { - *nextArrival = arrival{ - cost: arrivedHere.cost + literalCost, - length: uint32(unmatched + 1), - } - } - - if i > len(src)-8 { - // There's no room to check hashes. - continue - } - - cv := binary.LittleEndian.Uint64(src[i:]) - nextHash6 := z.hash6(cv) - candidate6 := z.table6[nextHash6] - - entry := tableEntry{offset: int32(i), val: uint32(cv)} - z.table6[nextHash6] = entry - - // Look for a repeat match, unless there is no previous distance, or a match at - // that distance has already been found. - if prevDistance != 0 && prevDistance != int(arrivals[i-historyLen-1+4].distance) { - repIndex := i - prevDistance - if repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv) { - // We have a repeat of the previous match distance. - m := extendMatch2(src, i, repIndex, i) - addMatch(m, unmatched, true) - } - } - - if z.Skip && i%2 != 0 { - continue - } - - nextByteIsUnmatched := arrivals[i-historyLen-1+1].distance == 0 - - if unmatched > 0 || i >= nextOverlapSearch || nextByteIsUnmatched { - if int(candidate6.offset) < i && i-int(candidate6.offset) < z.MaxDistance && uint32(cv) == candidate6.val && - binary.LittleEndian.Uint32(src[candidate6.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate6.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-4) - } - } - } - - // We've found the shortest path; now walk it backward and store the matches. - matches := z.matches[:0] - i := len(arrivals) - 1 - for i >= 0 { - a := arrivals[i] - if a.distance > 0 { - matches = append(matches, Match{ - Length: int(a.length), - Distance: int(a.distance), - }) - i -= int(a.length) - } else { - if len(matches) == 0 { - matches = append(matches, Match{}) - } - matches[len(matches)-1].Unmatched = int(a.length) - i -= int(a.length) - } - } - z.matches = matches - - slices.Reverse(matches) - - return append(dst, matches...) -} - -func (z *Bargain1) hash6(u uint64) uint32 { - return uint32(((u << 16) * 227718039650203) >> (64 - bargain1TableBits)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go deleted file mode 100644 index 020a0003..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain2.go +++ /dev/null @@ -1,248 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" - "math/bits" - "slices" -) - -const ( - bargain2TableBits = 18 - bargain2TableSize = 1 << bargain2TableBits -) - -// Bargain2 is a MatchFinder that attempts to find the encoding with the lowest -// "bit cost", using 2 hash lengths (5 and 8). -type Bargain2 struct { - MaxDistance int - - // Skip is whether to look for matches at every other byte instead of every - // byte (to increase speed but decrease compression). - Skip bool - - history []byte - table5 [bargain2TableSize]tableEntry - table8 [bargain2TableSize]tableEntry - - // holding onto buffers to reduce allocations: - - arrivals []arrival - matches []Match -} - -func (z *Bargain2) Reset() { - z.table5 = [bargain2TableSize]tableEntry{} - z.table8 = [bargain2TableSize]tableEntry{} - z.history = z.history[:0] -} - -func (z *Bargain2) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - var histogram [256]uint32 - for _, b := range src { - histogram[b]++ - } - var byteCost [256]float32 - for b, n := range histogram { - cost := max(math.Log2(float64(len(src))/float64(n)), 1) - byteCost[b] = float32(cost) - } - - // Each element in arrivals corresponds to the position just after - // the corresponding byte in src. - arrivals := z.arrivals - if len(arrivals) < len(src) { - arrivals = make([]arrival, len(src)) - z.arrivals = arrivals - } else { - arrivals = arrivals[:len(src)] - for i := range arrivals { - arrivals[i] = arrival{} - } - } - - if len(z.history) > z.MaxDistance*2 { - delta := len(z.history) - z.MaxDistance - copy(z.history, z.history[delta:]) - z.history = z.history[:z.MaxDistance] - - for i := range z.table5 { - v := z.table5[i].offset - v -= int32(delta) - if v < 0 { - z.table5[i] = tableEntry{} - } else { - z.table5[i].offset = v - } - } - for i := range z.table8 { - v := z.table8[i].offset - v -= int32(delta) - if v < 0 { - z.table8[i] = tableEntry{} - } else { - z.table8[i].offset = v - } - } - } - - historyLen := len(z.history) - z.history = append(z.history, src...) - src = z.history - - addMatch := func(m absoluteMatch, unmatched int, repeat bool) { - var startCost float32 - if m.Start > historyLen { - startCost = arrivals[m.Start-historyLen-1].cost - } - insertCost := float32(bits.Len(uint(unmatched))) - var distanceCost float32 - if !repeat { - distanceCost = float32(bits.Len(uint(m.Start - m.Match))) - } - cost := startCost + baseMatchCost + insertCost + distanceCost - for j := m.End; j >= m.Start+3; j-- { - a := &arrivals[j-historyLen-1] - if a.cost > 0 && a.cost <= cost { - break - } - *a = arrival{ - length: uint32(j - m.Start), - distance: uint32(m.Start - m.Match), - cost: cost, - } - } - } - - var nextOverlapSearch int - - for i := historyLen; i < len(src); i++ { - var arrivedHere arrival - if i > historyLen { - arrivedHere = arrivals[i-historyLen-1] - } - - unmatched := 0 - if arrivedHere.distance == 0 { - unmatched = int(arrivedHere.length) - } - prevDistance := 0 - if unmatched != 0 && i-unmatched > historyLen { - prevDistance = int(arrivals[i-historyLen-1-unmatched].distance) - } - - literalCost := byteCost[src[i]] - nextArrival := &arrivals[i-historyLen] - if nextArrival.cost == 0 || arrivedHere.cost+literalCost < nextArrival.cost { - *nextArrival = arrival{ - cost: arrivedHere.cost + literalCost, - length: uint32(unmatched + 1), - } - } - - if i > len(src)-8 { - // There's no room to check hashes. - continue - } - - cv := binary.LittleEndian.Uint64(src[i:]) - nextHash5 := z.hash5(cv) - nextHash8 := z.hash8(cv) - candidate5 := z.table5[nextHash5] - candidate8 := z.table8[nextHash8] - - entry := tableEntry{offset: int32(i), val: uint32(cv)} - z.table5[nextHash5] = entry - z.table8[nextHash8] = entry - - // Look for a repeat match, unless there is no previous distance, or a match at - // that distance has already been found. - if prevDistance != 0 && prevDistance != int(arrivals[i-historyLen-1+4].distance) { - repIndex := i - prevDistance - if repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv) { - // We have a repeat of the previous match distance. - m := extendMatch2(src, i, repIndex, i) - addMatch(m, unmatched, true) - } - } - - if z.Skip { - if i%2 != 0 { - continue - } - } - - nextByteIsUnmatched := arrivals[i-historyLen-1+1].distance == 0 - - if unmatched > 0 || i >= nextOverlapSearch || nextByteIsUnmatched { - if int(candidate5.offset) < i && i-int(candidate5.offset) < z.MaxDistance && uint32(cv) == candidate5.val && - binary.LittleEndian.Uint32(src[candidate5.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate5.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-6) - } - - if int(candidate8.offset) < i && i-int(candidate8.offset) < z.MaxDistance && uint32(cv) == candidate8.val && - binary.LittleEndian.Uint32(src[candidate8.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate8.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-6) - } - } - } - - // We've found the shortest path; now walk it backward and store the matches. - matches := z.matches[:0] - i := len(arrivals) - 1 - for i >= 0 { - a := arrivals[i] - if a.distance > 0 { - matches = append(matches, Match{ - Length: int(a.length), - Distance: int(a.distance), - }) - i -= int(a.length) - } else { - if len(matches) == 0 { - matches = append(matches, Match{}) - } - matches[len(matches)-1].Unmatched = int(a.length) - i -= int(a.length) - } - } - z.matches = matches - - slices.Reverse(matches) - - return append(dst, matches...) -} - -func (z *Bargain2) hash5(u uint64) uint32 { - return uint32(((u << 24) * 889523592379) >> (64 - bargain2TableBits)) -} - -func (z *Bargain2) hash8(u uint64) uint32 { - return uint32((u * 0xcf1bbcdcb7a56463) >> (64 - bargain2TableBits)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go deleted file mode 100644 index 24acd1ca..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/bargain3.go +++ /dev/null @@ -1,278 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" - "math/bits" - "slices" -) - -// Bargain3 is a MatchFinder that attempts to find the encoding with the lowest -// "bit cost", using 3 hash lengths (5, 8, and 12). -type Bargain3 struct { - MaxDistance int - - // Skip is whether to look for matches at every other byte instead of every - // byte (to increase speed but decrease compression). - Skip bool - - history []byte - table5 [1 << 17]tableEntry - table8 [1 << 18]tableEntry - table12 [1 << 19]tableEntry - - // holding onto buffers to reduce allocations: - - arrivals []arrival - matches []Match -} - -func (z *Bargain3) Reset() { - z.table5 = [len(z.table5)]tableEntry{} - z.table8 = [len(z.table8)]tableEntry{} - z.table12 = [len(z.table12)]tableEntry{} - z.history = z.history[:0] -} - -func (z *Bargain3) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - var histogram [256]uint32 - for _, b := range src { - histogram[b]++ - } - var byteCost [256]float32 - for b, n := range histogram { - cost := max(math.Log2(float64(len(src))/float64(n)), 1) - byteCost[b] = float32(cost) - } - - // Each element in arrivals corresponds to the position just after - // the corresponding byte in src. - arrivals := z.arrivals - if len(arrivals) < len(src) { - arrivals = make([]arrival, len(src)) - z.arrivals = arrivals - } else { - arrivals = arrivals[:len(src)] - for i := range arrivals { - arrivals[i] = arrival{} - } - } - - if len(z.history) > z.MaxDistance*2 { - delta := len(z.history) - z.MaxDistance - copy(z.history, z.history[delta:]) - z.history = z.history[:z.MaxDistance] - - for i := range z.table5 { - v := z.table5[i].offset - v -= int32(delta) - if v < 0 { - z.table5[i] = tableEntry{} - } else { - z.table5[i].offset = v - } - } - for i := range z.table8 { - v := z.table8[i].offset - v -= int32(delta) - if v < 0 { - z.table8[i] = tableEntry{} - } else { - z.table8[i].offset = v - } - } - for i := range z.table12 { - v := z.table12[i].offset - v -= int32(delta) - if v < 0 { - z.table12[i] = tableEntry{} - } else { - z.table12[i].offset = v - } - } - } - - historyLen := len(z.history) - z.history = append(z.history, src...) - src = z.history - - addMatch := func(m absoluteMatch, unmatched int, repeat bool) { - var startCost float32 - if m.Start > historyLen { - startCost = arrivals[m.Start-historyLen-1].cost - } - insertCost := float32(bits.Len(uint(unmatched))) - var distanceCost float32 - if !repeat { - distanceCost = float32(bits.Len(uint(m.Start - m.Match))) - } - cost := startCost + baseMatchCost + insertCost + distanceCost - for j := m.End; j >= m.Start+3; j-- { - a := &arrivals[j-historyLen-1] - if a.cost > 0 && a.cost <= cost { - break - } - *a = arrival{ - length: uint32(j - m.Start), - distance: uint32(m.Start - m.Match), - cost: cost, - } - } - } - - var nextOverlapSearch int - - for i := historyLen; i < len(src); i++ { - var arrivedHere arrival - if i > historyLen { - arrivedHere = arrivals[i-historyLen-1] - } - - unmatched := 0 - if arrivedHere.distance == 0 { - unmatched = int(arrivedHere.length) - } - prevDistance := 0 - if unmatched != 0 && i-unmatched > historyLen { - prevDistance = int(arrivals[i-historyLen-1-unmatched].distance) - } - - literalCost := byteCost[src[i]] - nextArrival := &arrivals[i-historyLen] - if nextArrival.cost == 0 || arrivedHere.cost+literalCost < nextArrival.cost { - *nextArrival = arrival{ - cost: arrivedHere.cost + literalCost, - length: uint32(unmatched + 1), - } - } - - if i > len(src)-12 { - // There's no room to check hashes. - continue - } - - cv := binary.LittleEndian.Uint64(src[i:]) - extra := binary.LittleEndian.Uint32(src[i+8:]) - nextHash5 := z.hash5(cv) - nextHash8 := z.hash8(cv) - nextHash12 := z.hash12(cv, extra) - candidate5 := z.table5[nextHash5] - candidate8 := z.table8[nextHash8] - candidate12 := z.table12[nextHash12] - - entry := tableEntry{offset: int32(i), val: uint32(cv)} - z.table5[nextHash5] = entry - z.table8[nextHash8] = entry - z.table12[nextHash12] = entry - - // Look for a repeat match, unless there is no previous distance, or a match at - // that distance has already been found. - if prevDistance != 0 && prevDistance != int(arrivals[i-historyLen-1+4].distance) { - repIndex := i - prevDistance - if repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv) { - // We have a repeat of the previous match distance. - m := extendMatch2(src, i, repIndex, i) - addMatch(m, unmatched, true) - } - } - - if z.Skip { - if i%2 != 0 { - continue - } - } - - nextByteIsUnmatched := arrivals[i-historyLen-1+1].distance == 0 - - if unmatched > 0 || i >= nextOverlapSearch || nextByteIsUnmatched { - if int(candidate5.offset) < i && i-int(candidate5.offset) < z.MaxDistance && uint32(cv) == candidate5.val && - binary.LittleEndian.Uint32(src[candidate5.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate5.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-6) - } - - if int(candidate8.offset) < i && i-int(candidate8.offset) < z.MaxDistance && uint32(cv) == candidate8.val && - binary.LittleEndian.Uint32(src[candidate8.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate8.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-6) - } - - if int(candidate12.offset) < i && i-int(candidate12.offset) < z.MaxDistance && uint32(cv) == candidate12.val && - binary.LittleEndian.Uint32(src[candidate12.offset:]) == uint32(cv) { - m := extendMatch2(src, i, int(candidate12.offset), historyLen) - delta := i - m.Start - if delta == 0 { - addMatch(m, unmatched, false) - } else { - // The match was extended backwards. Add it with and without the extra. - addMatch(m, max(unmatched-delta, 0), false) - m.Start += delta - m.Match += delta - addMatch(m, unmatched, false) - } - nextOverlapSearch = max(nextOverlapSearch, m.Start+1, m.End-6) - } - } - } - - // We've found the shortest path; now walk it backward and store the matches. - matches := z.matches[:0] - i := len(arrivals) - 1 - for i >= 0 { - a := arrivals[i] - if a.distance > 0 { - matches = append(matches, Match{ - Length: int(a.length), - Distance: int(a.distance), - }) - i -= int(a.length) - } else { - if len(matches) == 0 { - matches = append(matches, Match{}) - } - matches[len(matches)-1].Unmatched = int(a.length) - i -= int(a.length) - } - } - z.matches = matches - - slices.Reverse(matches) - - return append(dst, matches...) -} - -func (z *Bargain3) hash5(u uint64) uint32 { - return uint32(((u << 24) * 889523592379) >> (64 - 17)) -} - -func (z *Bargain3) hash8(u uint64) uint32 { - return uint32((u * 0xcf1bbcdcb7a56463) >> (64 - 18)) -} - -func (z *Bargain3) hash12(u uint64, e uint32) uint32 { - return uint32((u*0xcf1bbcdcb7a56463 + uint64(e)*(2654435761<<32)) >> (64 - 19)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/emitter.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/emitter.go deleted file mode 100644 index 507d1cae..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/emitter.go +++ /dev/null @@ -1,34 +0,0 @@ -package matchfinder - -// An absoluteMatch is like a Match, but it stores indexes into the byte -// stream instead of lengths. -type absoluteMatch struct { - // Start is the index of the first byte. - Start int - - // End is the index of the byte after the last byte - // (so that End - Start = Length). - End int - - // Match is the index of the previous data that matches - // (Start - Match = Distance). - Match int -} - -// A matchEmitter manages the output of matches for a MatchFinder. -type matchEmitter struct { - // Dst is the destination slice that Matches are added to. - Dst []Match - - // NextEmit is the index of the next byte to emit. - NextEmit int -} - -func (e *matchEmitter) emit(m absoluteMatch) { - e.Dst = append(e.Dst, Match{ - Unmatched: m.Start - e.NextEmit, - Length: m.End - m.Start, - Distance: m.Start - m.Match, - }) - e.NextEmit = m.End -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/m0.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/m0.go deleted file mode 100644 index a37e3b46..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/m0.go +++ /dev/null @@ -1,175 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" -) - -// M0 is an implementation of the MatchFinder interface based -// on the algorithm used by snappy, but modified to be more like the algorithm -// used by compression level 0 of the brotli reference implementation. -// -// It has a maximum block size of 65536 bytes. -type M0 struct { - // Lazy turns on "lazy matching," for higher compression but less speed. - Lazy bool - - MaxDistance int - MaxLength int -} - -func (M0) Reset() {} - -const ( - m0HashLen = 5 - - m0TableBits = 16 - m0TableSize = 1 << m0TableBits - m0Shift = 32 - m0TableBits - // m0TableMask is redundant, but helps the compiler eliminate bounds - // checks. - m0TableMask = m0TableSize - 1 -) - -func (m M0) hash(data uint64) uint64 { - hash := (data << (64 - 8*m0HashLen)) * hashMul64 - return hash >> (64 - m0TableBits) -} - -// FindMatches looks for matches in src, appends them to dst, and returns dst. -// src must not be longer than 65536 bytes. -func (m M0) FindMatches(dst []Match, src []byte) []Match { - const inputMargin = 16 - 1 - const minNonLiteralBlockSize = 1 + 1 + inputMargin - - if len(src) < minNonLiteralBlockSize { - dst = append(dst, Match{ - Unmatched: len(src), - }) - return dst - } - if len(src) > 65536 { - panic("block too long") - } - - var table [m0TableSize]uint16 - - // sLimit is when to stop looking for offset/length copies. The inputMargin - // lets us use a fast path for emitLiteral in the main loop, while we are - // looking for copies. - sLimit := len(src) - inputMargin - - // nextEmit is where in src the next emitLiteral should start from. - nextEmit := 0 - - // The encoded form must start with a literal, as there are no previous - // bytes to copy, so we start looking for hash matches at s == 1. - s := 1 - nextHash := m.hash(binary.LittleEndian.Uint64(src[s:])) - - for { - // Copied from the C++ snappy implementation: - // - // Heuristic match skipping: If 32 bytes are scanned with no matches - // found, start looking only at every other byte. If 32 more bytes are - // scanned (or skipped), look at every third byte, etc.. When a match - // is found, immediately go back to looking at every byte. This is a - // small loss (~5% performance, ~0.1% density) for compressible data - // due to more bookkeeping, but for non-compressible data (such as - // JPEG) it's a huge win since the compressor quickly "realizes" the - // data is incompressible and doesn't bother looking for matches - // everywhere. - // - // The "skip" variable keeps track of how many bytes there are since - // the last match; dividing it by 32 (ie. right-shifting by five) gives - // the number of bytes to move ahead for each iteration. - skip := 32 - - nextS := s - candidate := 0 - for { - s = nextS - bytesBetweenHashLookups := skip >> 5 - nextS = s + bytesBetweenHashLookups - skip += bytesBetweenHashLookups - if nextS > sLimit { - goto emitRemainder - } - candidate = int(table[nextHash&m0TableMask]) - table[nextHash&m0TableMask] = uint16(s) - nextHash = m.hash(binary.LittleEndian.Uint64(src[nextS:])) - if m.MaxDistance != 0 && s-candidate > m.MaxDistance { - continue - } - if binary.LittleEndian.Uint32(src[s:]) == binary.LittleEndian.Uint32(src[candidate:]) { - break - } - } - - // Invariant: we have a 4-byte match at s. - base := s - s = extendMatch(src, candidate+4, s+4) - - origBase := base - if m.Lazy && base+1 < sLimit { - newBase := base + 1 - h := m.hash(binary.LittleEndian.Uint64(src[newBase:])) - newCandidate := int(table[h&m0TableMask]) - table[h&m0TableMask] = uint16(newBase) - okDistance := true - if m.MaxDistance != 0 && newBase-newCandidate > m.MaxDistance { - okDistance = false - } - if okDistance && binary.LittleEndian.Uint32(src[newBase:]) == binary.LittleEndian.Uint32(src[newCandidate:]) { - newS := extendMatch(src, newCandidate+4, newBase+4) - if newS-newBase > s-base+1 { - s = newS - base = newBase - candidate = newCandidate - } - } - } - - if m.MaxLength != 0 && s-base > m.MaxLength { - s = base + m.MaxLength - } - dst = append(dst, Match{ - Unmatched: base - nextEmit, - Length: s - base, - Distance: base - candidate, - }) - nextEmit = s - if s >= sLimit { - goto emitRemainder - } - - if m.Lazy { - // If lazy matching is enabled, we update the hash table for - // every byte in the match. - for i := origBase + 2; i < s-3; i++ { - x := binary.LittleEndian.Uint64(src[i:]) - table[m.hash(x)&m0TableMask] = uint16(i) - } - } else { - // We update the hash table only at base+1 - x := binary.LittleEndian.Uint64(src[base+1:]) - table[m.hash(x)&m0TableMask] = uint16(base + 1) - } - - // We could immediately start working at s now, but to improve - // compression we first update the hash table. - x := binary.LittleEndian.Uint64(src[s-3:]) - table[m.hash(x)&m0TableMask] = uint16(s - 3) - table[m.hash(x>>8)&m0TableMask] = uint16(s - 2) - prevHash := m.hash(x >> 16) - table[prevHash&m0TableMask] = uint16(s - 1) - nextHash = m.hash(x >> 24) - } - -emitRemainder: - if nextEmit < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - nextEmit, - }) - } - return dst -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/m4.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/m4.go deleted file mode 100644 index a92b92f6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/m4.go +++ /dev/null @@ -1,339 +0,0 @@ -package matchfinder - -import ( - "bytes" - "encoding/binary" - "math/bits" - "runtime" -) - -// M4 is an implementation of the MatchFinder -// interface that uses a hash table to find matches, -// optional match chains, -// and the advanced parsing technique from -// https://fastcompression.blogspot.com/2011/12/advanced-parsing-strategies.html. -type M4 struct { - // MaxDistance is the maximum distance (in bytes) to look back for - // a match. The default is 65535. - MaxDistance int - - // MinLength is the length of the shortest match to return. - // The default is 4. - MinLength int - - // HashLen is the number of bytes to use to calculate the hashes. - // The maximum is 8 and the default is 6. - HashLen int - - // TableBits is the number of bits in the hash table indexes. - // The default is 17 (128K entries). - TableBits int - - // ChainLength is how many entries to search on the "match chain" of older - // locations with the same hash as the current location. - ChainLength int - - // DistanceBitCost is used when comparing two matches to see - // which is better. The comparison is primarily based on the length - // of the matches, but it can also take the distance into account, - // in terms of the number of bits needed to represent the distance. - // One byte of length is given a score of 256, so 32 (256/8) would - // be a reasonable first guess for the value of one bit. - // (The default is 0, which bases the comparison solely on length.) - DistanceBitCost int - - table []uint32 - chain []uint32 - - history []byte -} - -func (q *M4) Reset() { - for i := range q.table { - q.table[i] = 0 - } - q.history = q.history[:0] - q.chain = q.chain[:0] -} - -func (q *M4) score(m absoluteMatch) int { - return (m.End-m.Start)*256 + (bits.LeadingZeros32(uint32(m.Start-m.Match))-32)*q.DistanceBitCost -} - -func (q *M4) FindMatches(dst []Match, src []byte) []Match { - if q.MaxDistance == 0 { - q.MaxDistance = 65535 - } - if q.MinLength == 0 { - q.MinLength = 4 - } - if q.HashLen == 0 { - q.HashLen = 6 - } - if q.TableBits == 0 { - q.TableBits = 17 - } - if len(q.table) < 1< q.MaxDistance*2 { - // Trim down the history buffer. - delta := len(q.history) - q.MaxDistance - copy(q.history, q.history[delta:]) - q.history = q.history[:q.MaxDistance] - if q.ChainLength > 0 { - copy(q.chain, q.chain[delta:]) - q.chain = q.chain[:q.MaxDistance] - } - - for i, v := range q.table { - newV := int(v) - delta - if newV < 0 { - newV = 0 - } - q.table[i] = uint32(newV) - } - } - - // Append src to the history buffer. - e.NextEmit = len(q.history) - q.history = append(q.history, src...) - if q.ChainLength > 0 { - q.chain = append(q.chain, make([]uint32, len(src))...) - } - src = q.history - - // matches stores the matches that have been found but not emitted, - // in reverse order. (matches[0] is the most recent one.) - var matches [3]absoluteMatch - for i := e.NextEmit; i < len(src)-7; i++ { - if matches[0] != (absoluteMatch{}) && i >= matches[0].End { - // We have found some matches, and we're far enough along that we probably - // won't find overlapping matches, so we might as well emit them. - if matches[1] != (absoluteMatch{}) { - if matches[1].End > matches[0].Start { - matches[1].End = matches[0].Start - } - if matches[1].End-matches[1].Start >= q.MinLength && q.score(matches[1]) > 0 { - e.emit(matches[1]) - } - } - e.emit(matches[0]) - matches = [3]absoluteMatch{} - } - - // Look for a repeat match one byte after the current position. - if matches[0] == (absoluteMatch{}) && len(e.Dst) > 0 { - prevDistance := e.Dst[len(e.Dst)-1].Distance - if binary.LittleEndian.Uint32(src[i+1:]) == binary.LittleEndian.Uint32(src[i+1-prevDistance:]) { - // We have a 4-byte match. - m := extendMatch2(src, i+1, i+1-prevDistance, e.NextEmit+1) - if m.End-m.Start >= q.MinLength { - matches[0] = m - } - } - } - - // Calculate and store the hash. - h := ((binary.LittleEndian.Uint64(src[i:]) & (1<<(8*q.HashLen) - 1)) * hashMul64) >> (64 - q.TableBits) - candidate := int(q.table[h]) - q.table[h] = uint32(i) - if q.ChainLength > 0 && candidate != 0 { - delta := i - candidate - q.chain[i] = uint32(delta) - } - - if i < matches[0].End && i != matches[0].End+2-q.HashLen { - continue - } - if candidate == 0 || i-candidate > q.MaxDistance { - continue - } - - // Look for a match. - var currentMatch absoluteMatch - - if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) { - m := extendMatch2(src, i, candidate, e.NextEmit) - if m.End-m.Start > q.MinLength && q.score(m) > 0 { - currentMatch = m - } - } - - for j := 0; j < q.ChainLength; j++ { - delta := q.chain[candidate] - if delta == 0 { - break - } - candidate -= int(delta) - if candidate <= 0 || i-candidate > q.MaxDistance { - break - } - if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) { - m := extendMatch2(src, i, candidate, e.NextEmit) - if m.End-m.Start > q.MinLength && q.score(m) > q.score(currentMatch) { - currentMatch = m - } - } - } - - if currentMatch.End-currentMatch.Start < q.MinLength { - continue - } - - overlapPenalty := 0 - if matches[0] != (absoluteMatch{}) { - overlapPenalty = 275 - if currentMatch.Start <= matches[1].End { - // This match would completely replace the previous match, - // so there is no penalty for overlap. - overlapPenalty = 0 - } - } - - if q.score(currentMatch) <= q.score(matches[0])+overlapPenalty { - continue - } - - matches = [3]absoluteMatch{ - currentMatch, - matches[0], - matches[1], - } - - if matches[2] == (absoluteMatch{}) { - continue - } - - // We have three matches, so it's time to emit one and/or eliminate one. - switch { - case matches[0].Start < matches[2].End: - // The first and third matches overlap; discard the one in between. - matches = [3]absoluteMatch{ - matches[0], - matches[2], - absoluteMatch{}, - } - - case matches[0].Start < matches[2].End+q.MinLength: - // The first and third matches don't overlap, but there's no room for - // another match between them. Emit the first match and discard the second. - e.emit(matches[2]) - matches = [3]absoluteMatch{ - matches[0], - absoluteMatch{}, - absoluteMatch{}, - } - - default: - // Emit the first match, shortening it if necessary to avoid overlap with the second. - if matches[2].End > matches[1].Start { - matches[2].End = matches[1].Start - if q.ChainLength > 0 && matches[2].End-matches[2].Start >= q.MinLength { - // Since the match length was trimmed, we may be able to find a closer match - // to replace it. - pos := matches[2].Start - for { - delta := int(q.chain[pos]) - if delta == 0 { - break - } - pos -= delta - if pos <= matches[2].Match { - break - } - if bytes.Equal(src[matches[2].Start:matches[2].End], src[pos:pos+matches[2].End-matches[2].Start]) { - matches[2].Match = pos - break - } - } - } - } - if matches[2].End-matches[2].Start >= q.MinLength && q.score(matches[2]) > 0 { - e.emit(matches[2]) - } - matches[2] = absoluteMatch{} - } - } - - // We've found all the matches now; emit the remaining ones. - if matches[1] != (absoluteMatch{}) { - if matches[1].End > matches[0].Start { - matches[1].End = matches[0].Start - } - if matches[1].End-matches[1].Start >= q.MinLength && q.score(matches[1]) > 0 { - e.emit(matches[1]) - } - } - if matches[0] != (absoluteMatch{}) { - e.emit(matches[0]) - } - - dst = e.Dst - if e.NextEmit < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - e.NextEmit, - }) - } - - return dst -} - -const hashMul64 = 0x1E35A7BD1E35A7BD - -// extendMatch returns the largest k such that k <= len(src) and that -// src[i:i+k-j] and src[j:k] have the same contents. -// -// It assumes that: -// -// 0 <= i && i < j && j <= len(src) -func extendMatch(src []byte, i, j int) int { - switch runtime.GOARCH { - case "amd64", "arm64": - // As long as we are 8 or more bytes before the end of src, we can load and - // compare 8 bytes at a time. If those 8 bytes are equal, repeat. - for j+8 < len(src) { - iBytes := binary.LittleEndian.Uint64(src[i:]) - jBytes := binary.LittleEndian.Uint64(src[j:]) - if iBytes != jBytes { - // If those 8 bytes were not equal, XOR the two 8 byte values, and return - // the index of the first byte that differs. The BSF instruction finds the - // least significant 1 bit, the amd64 architecture is little-endian, and - // the shift by 3 converts a bit index to a byte index. - return j + bits.TrailingZeros64(iBytes^jBytes)>>3 - } - i, j = i+8, j+8 - } - case "386": - // On a 32-bit CPU, we do it 4 bytes at a time. - for j+4 < len(src) { - iBytes := binary.LittleEndian.Uint32(src[i:]) - jBytes := binary.LittleEndian.Uint32(src[j:]) - if iBytes != jBytes { - return j + bits.TrailingZeros32(iBytes^jBytes)>>3 - } - i, j = i+4, j+4 - } - } - for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 { - } - return j -} - -// Given a 4-byte match at src[start] and src[candidate], extendMatch2 extends it -// upward as far as possible, and downward no farther than to min. -func extendMatch2(src []byte, start, candidate, min int) absoluteMatch { - end := extendMatch(src, candidate+4, start+4) - for start > min && candidate > 0 && src[start-1] == src[candidate-1] { - start-- - candidate-- - } - return absoluteMatch{ - Start: start, - End: end, - Match: candidate, - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go deleted file mode 100644 index f6bcfdb3..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go +++ /dev/null @@ -1,103 +0,0 @@ -// The matchfinder package defines reusable components for data compression. -// -// Many compression libraries have two main parts: -// - Something that looks for repeated sequences of bytes -// - An encoder for the compressed data format (often an entropy coder) -// -// Although these are logically two separate steps, the implementations are -// usually closely tied together. You can't use flate's matcher with snappy's -// encoder, for example. This package defines interfaces and an intermediate -// representation to allow mixing and matching compression components. -package matchfinder - -import "io" - -// A Match is the basic unit of LZ77 compression. -type Match struct { - Unmatched int // the number of unmatched bytes since the previous match - Length int // the number of bytes in the matched string; it may be 0 at the end of the input - Distance int // how far back in the stream to copy from -} - -// A MatchFinder performs the LZ77 stage of compression, looking for matches. -type MatchFinder interface { - // FindMatches looks for matches in src, appends them to dst, and returns dst. - FindMatches(dst []Match, src []byte) []Match - - // Reset clears any internal state, preparing the MatchFinder to be used with - // a new stream. - Reset() -} - -// An Encoder encodes the data in its final format. -type Encoder interface { - // Encode appends the encoded format of src to dst, using the match - // information from matches. - Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte - - // Reset clears any internal state, preparing the Encoder to be used with - // a new stream. - Reset() -} - -// A Writer uses MatchFinder and Encoder to write compressed data to Dest. -type Writer struct { - Dest io.Writer - MatchFinder MatchFinder - Encoder Encoder - - // BlockSize is the number of bytes to compress at a time. If it is zero, - // each Write operation will be treated as one block. - BlockSize int - - err error - inBuf []byte - outBuf []byte - matches []Match -} - -func (w *Writer) Write(p []byte) (n int, err error) { - if w.err != nil { - return 0, w.err - } - - if w.BlockSize == 0 { - return w.writeBlock(p, false) - } - - w.inBuf = append(w.inBuf, p...) - var pos int - for pos = 0; pos+w.BlockSize <= len(w.inBuf) && w.err == nil; pos += w.BlockSize { - w.writeBlock(w.inBuf[pos:pos+w.BlockSize], false) - } - if pos > 0 { - n := copy(w.inBuf, w.inBuf[pos:]) - w.inBuf = w.inBuf[:n] - } - - return len(p), w.err -} - -func (w *Writer) writeBlock(p []byte, lastBlock bool) (n int, err error) { - w.outBuf = w.outBuf[:0] - w.matches = w.MatchFinder.FindMatches(w.matches[:0], p) - w.outBuf = w.Encoder.Encode(w.outBuf, p, w.matches, lastBlock) - _, w.err = w.Dest.Write(w.outBuf) - return len(p), w.err -} - -func (w *Writer) Close() error { - w.writeBlock(w.inBuf, true) - w.inBuf = w.inBuf[:0] - return w.err -} - -func (w *Writer) Reset(newDest io.Writer) { - w.MatchFinder.Reset() - w.Encoder.Reset() - w.err = nil - w.inBuf = w.inBuf[:0] - w.outBuf = w.outBuf[:0] - w.matches = w.matches[:0] - w.Dest = newDest -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go deleted file mode 100644 index 2a12ab9d..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/pathfinder.go +++ /dev/null @@ -1,328 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" - "math/bits" - "slices" -) - -// Pathfinder is a MatchFinder that uses hash chains to find matches, and a -// shortest-path optimizer to choose which matches to use. -type Pathfinder struct { - // MaxDistance is the maximum distance (in bytes) to look back for - // a match. The default is 65535. - MaxDistance int - - // MinLength is the length of the shortest match to return. - // The default is 4. - MinLength int - - // HashLen is the number of bytes to use to calculate the hashes. - // The maximum is 8 and the default is 6. - HashLen int - - // TableBits is the number of bits in the hash table indexes. - // The default is 17 (128K entries). - TableBits int - - // ChainLength is how many entries to search on the "match chain" of older - // locations with the same hash as the current location. - ChainLength int - - table []uint32 - chain []uint32 - - history []byte - - // holding onto buffers to reduce allocations: - - arrivals []arrival - foundMatches []absoluteMatch - matches []Match -} - -func (q *Pathfinder) Reset() { - for i := range q.table { - q.table[i] = 0 - } - q.history = q.history[:0] - q.chain = q.chain[:0] -} - -// An arrival represents how we got to a certain byte position. -// The cost is the total cost to get there from the beginning of the block. -// If distance > 0, the arrival is with a match. -// If distance == 0, the arrival is with a run of literals. -type arrival struct { - length uint32 - distance uint32 - cost float32 -} - -const ( - baseMatchCost float32 = 4 -) - -func (q *Pathfinder) FindMatches(dst []Match, src []byte) []Match { - if q.MaxDistance == 0 { - q.MaxDistance = 65535 - } - if q.MinLength == 0 { - q.MinLength = 4 - } - if q.HashLen == 0 { - q.HashLen = 6 - } - if q.TableBits == 0 { - q.TableBits = 17 - } - if len(q.table) < 1< q.MaxDistance*2 { - // Trim down the history buffer. - delta := len(q.history) - q.MaxDistance - copy(q.history, q.history[delta:]) - q.history = q.history[:q.MaxDistance] - q.chain = q.chain[:q.MaxDistance] - - for i, v := range q.table { - newV := max(int(v)-delta, 0) - q.table[i] = uint32(newV) - } - } - - // Append src to the history buffer. - historyLen := len(q.history) - q.history = append(q.history, src...) - q.chain = append(q.chain, make([]uint32, len(src))...) - src = q.history - - // Calculate hashes and build the chain. - for i := historyLen; i < len(src)-7; i++ { - h := ((binary.LittleEndian.Uint64(src[i:]) & (1<<(8*q.HashLen) - 1)) * hashMul64) >> (64 - q.TableBits) - candidate := int(q.table[h]) - q.table[h] = uint32(i) - if candidate != 0 { - delta := i - candidate - q.chain[i] = uint32(delta) - } - } - - // Look for matches, and collect them in foundMatches. Later we'll figure out - // which ones to actually use. - foundMatches := q.foundMatches[:0] - var prevMatch absoluteMatch - i := historyLen - for i < len(src)-7 { - delta := q.chain[i] - if delta == 0 { - i++ - continue - } - candidate := i - int(delta) - if candidate <= 0 || i-candidate > q.MaxDistance { - i++ - continue - } - - var currentMatch absoluteMatch - - if i >= prevMatch.End && prevMatch != (absoluteMatch{}) { - // Look for a repeat match at i+1. - prevDistance := prevMatch.Start - prevMatch.Match - if binary.LittleEndian.Uint32(src[i+1:]) == binary.LittleEndian.Uint32(src[i+1-prevDistance:]) { - m := extendMatch2(src, i+1, i+1-prevDistance, i+1) - if m.End-m.Start > q.MinLength { - currentMatch = m - foundMatches = append(foundMatches, m) - } - } - } - - if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) { - m := extendMatch2(src, i, candidate, max(historyLen, prevMatch.Start)) - if m.End-m.Start > q.MinLength { - currentMatch = m - foundMatches = append(foundMatches, m) - } - } - - for range q.ChainLength { - delta := q.chain[candidate] - if delta == 0 { - break - } - candidate -= int(delta) - if candidate <= 0 || i-candidate > q.MaxDistance { - break - } - if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) { - m := extendMatch2(src, i, candidate, max(historyLen, prevMatch.Start)) - if m.End-m.Start > q.MinLength && m.End-m.Start > currentMatch.End-currentMatch.Start { - currentMatch = m - foundMatches = append(foundMatches, m) - } - } - } - - if i < prevMatch.End && currentMatch.End-currentMatch.Start <= prevMatch.End-prevMatch.Start { - // We were looking for an overlapping match, but we didn't find one longer - // than the previous match. So we'll go back to sequential search, - // starting right after the previous match. - i = prevMatch.End - continue - } - - if currentMatch == (absoluteMatch{}) { - // No match found. Continue with sequential search. - i++ - continue - } - - // We've found a match; now look for matches overlapping the end of it. - prevMatch = currentMatch - i = currentMatch.End + 2 - q.HashLen - } - - q.foundMatches = foundMatches - - slices.SortFunc(foundMatches, func(a, b absoluteMatch) int { return a.Start - b.Start }) - matchIndex := 0 - var pending absoluteMatch - - for i := historyLen; i < len(src); i++ { - var arrivedHere arrival - if i > historyLen { - arrivedHere = arrivals[i-historyLen-1] - } - - unmatched := 0 - if arrivedHere.distance == 0 { - unmatched = int(arrivedHere.length) - } - prevDistance := 0 - if i-unmatched > historyLen { - prevDistance = int(arrivals[i-historyLen-1-unmatched].distance) - } - - literalCost := byteCost[src[i]] - nextArrival := &arrivals[i-historyLen] - if nextArrival.cost == 0 || arrivedHere.cost+literalCost < nextArrival.cost { - *nextArrival = arrival{ - cost: arrivedHere.cost + literalCost, - length: uint32(unmatched + 1), - } - } - - for matchIndex < len(foundMatches) && foundMatches[matchIndex].Start == i { - m := foundMatches[matchIndex] - matchIndex++ - if m.End > pending.End { - pending = m - } - matchCost := baseMatchCost + float32(bits.Len(uint(unmatched))) - if m.Start-m.Match != prevDistance { - matchCost += float32(bits.Len(uint(m.Start - m.Match))) - } - for j := m.Start + q.MinLength; j <= m.End; j++ { - adjustedCost := matchCost - if j-m.Start < 6 { - // Matches shorter than 6 are comparatively rare, and therefore - // have longer codes. - adjustedCost += float32(6-(j-m.Start)) * 2 - } - a := &arrivals[j-historyLen-1] - if a.cost == 0 || arrivedHere.cost+adjustedCost < a.cost { - *a = arrival{ - length: uint32(j - m.Start), - distance: uint32(m.Start - m.Match), - cost: arrivedHere.cost + adjustedCost, - } - } - } - } - - // If a match from an earlier position extends far enough past the current - // position, try using the tail of it, starting from here. - if unmatched == 0 && pending.Start != i && pending.End >= i+q.MinLength && - !(arrivedHere.length != 0 && arrivedHere.distance == uint32(pending.Start-pending.Match)) { - matchCost := baseMatchCost + float32(bits.Len(uint(pending.Start-pending.Match))) - for j := i + q.MinLength; j <= pending.End; j++ { - adjustedCost := matchCost - if j-i < 6 { - // Matches shorter than 6 are comparatively rare, and therefore - // have longer codes. - adjustedCost += float32(6-(j-i)) * 2 - } - a := &arrivals[j-historyLen-1] - if a.cost == 0 || arrivedHere.cost+adjustedCost < a.cost { - *a = arrival{ - length: uint32(j - i), - distance: uint32(pending.Start - pending.Match), - cost: arrivedHere.cost + adjustedCost, - } - } - } - } - - delta := q.chain[i] - if delta == 0 { - continue - } - candidate := i - int(delta) - if candidate <= 0 || i-candidate > q.MaxDistance { - continue - } - } - - // We've found the shortest path; now walk it backward and store the matches. - matches := q.matches[:0] - i = len(arrivals) - 1 - for i >= 0 { - a := arrivals[i] - if a.distance > 0 { - matches = append(matches, Match{ - Length: int(a.length), - Distance: int(a.distance), - }) - i -= int(a.length) - } else { - if len(matches) == 0 { - matches = append(matches, Match{}) - } - matches[len(matches)-1].Unmatched = int(a.length) - i -= int(a.length) - } - } - q.matches = matches - - slices.Reverse(matches) - - return append(dst, matches...) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go deleted file mode 100644 index 75ecc590..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go +++ /dev/null @@ -1,53 +0,0 @@ -package matchfinder - -import "fmt" - -// A TextEncoder is an Encoder that produces a human-readable representation of -// the LZ77 compression. Matches are replaced with symbols. -type TextEncoder struct{} - -func (t TextEncoder) Reset() {} - -func (t TextEncoder) Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte { - pos := 0 - for _, m := range matches { - if m.Unmatched > 0 { - dst = append(dst, src[pos:pos+m.Unmatched]...) - pos += m.Unmatched - } - if m.Length > 0 { - dst = append(dst, []byte(fmt.Sprintf("<%d,%d>", m.Length, m.Distance))...) - pos += m.Length - } - } - if pos < len(src) { - dst = append(dst, src[pos:]...) - } - return dst -} - -// A NoMatchFinder implements MatchFinder, but doesn't find any matches. -// It can be used to implement the equivalent of the standard library flate package's -// HuffmanOnly setting. -type NoMatchFinder struct{} - -func (n NoMatchFinder) Reset() {} - -func (n NoMatchFinder) FindMatches(dst []Match, src []byte) []Match { - return append(dst, Match{ - Unmatched: len(src), - }) -} - -// AutoReset wraps a MatchFinder that can return references to data in previous -// blocks, and calls Reset before each block. It is useful for (e.g.) using a -// snappy Encoder with a MatchFinder designed for flate. (Snappy doesn't -// support references between blocks.) -type AutoReset struct { - MatchFinder -} - -func (a AutoReset) FindMatches(dst []Match, src []byte) []Match { - a.Reset() - return a.MatchFinder.FindMatches(dst, src) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/trio.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/trio.go deleted file mode 100644 index cb33e64a..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/trio.go +++ /dev/null @@ -1,326 +0,0 @@ -package matchfinder - -import "encoding/binary" - -// Trio is a MatchFinder that uses 3 different hash lengths, and -// overlap parsing. -type Trio struct { - MaxDistance int - history []byte - table5 [1 << 16]tableEntry - table8 [1 << 17]tableEntry - table12 [1 << 18]tableEntry -} - -func (z *Trio) Reset() { - z.table5 = [len(z.table5)]tableEntry{} - z.table8 = [len(z.table8)]tableEntry{} - z.table12 = [len(z.table12)]tableEntry{} - z.history = z.history[:0] -} - -func (z *Trio) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - if len(z.history) > z.MaxDistance*2 { - delta := len(z.history) - z.MaxDistance - copy(z.history, z.history[delta:]) - z.history = z.history[:z.MaxDistance] - - for i := range z.table5 { - v := z.table5[i].offset - v -= int32(delta) - if v < 0 { - z.table5[i] = tableEntry{} - } else { - z.table5[i].offset = v - } - } - for i := range z.table8 { - v := z.table8[i].offset - v -= int32(delta) - if v < 0 { - z.table8[i] = tableEntry{} - } else { - z.table8[i].offset = v - } - } - for i := range z.table12 { - v := z.table12[i].offset - v -= int32(delta) - if v < 0 { - z.table12[i] = tableEntry{} - } else { - z.table12[i].offset = v - } - } - } - - if len(src) < 20 { - return append(dst, Match{ - Unmatched: len(src), - }) - } - - e := matchEmitter{ - Dst: dst, - NextEmit: len(z.history), - } - z.history = append(z.history, src...) - src = z.history - - // matches stores the matches that have been found but not emitted, - // in reverse order. (matches[0] is the most recent one.) - var matches [3]absoluteMatch - - sLimit := int32(len(src)) - 14 - -mainLoop: - for { - // Search for a match, starting after the last match emitted. - s := int32(e.NextEmit) - if s > sLimit { - break mainLoop - } - - // t will contain the match offset when we find one. - var t int32 - var hashLengthFound int - - cv := binary.LittleEndian.Uint64(src[s:]) - extra := binary.LittleEndian.Uint32(src[s+8:]) - - for { - nextHash12 := z.hash12(cv, extra) - nextHash8 := z.hash8(cv) - nextHash5 := z.hash5(cv) - candidate12 := z.table12[nextHash12] - candidate8 := z.table8[nextHash8] - candidate5 := z.table5[nextHash5] - - entry := tableEntry{offset: s, val: uint32(cv)} - z.table12[nextHash12] = entry - z.table8[nextHash8] = entry - z.table5[nextHash5] = entry - - // Look for a repeat match one byte after the current position. - if len(e.Dst) > 0 { - prevDistance := int32(e.Dst[len(e.Dst)-1].Distance) - if prevDistance != 0 { - repIndex := s - prevDistance + 1 - if repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv>>8) { - // There is a repeated match at s+2. - s++ - t = repIndex - break - } - } - } - - if candidate12.offset < s && s-candidate12.offset < int32(z.MaxDistance) && uint32(cv) == candidate12.val && - binary.LittleEndian.Uint32(src[candidate12.offset:]) == uint32(cv) { - // There is a 12-byte match at s. - t = candidate12.offset - hashLengthFound = 12 - break - } - if candidate8.offset < s && s-candidate8.offset < int32(z.MaxDistance) && uint32(cv) == candidate8.val && - binary.LittleEndian.Uint32(src[candidate8.offset:]) == uint32(cv) { - t = candidate8.offset - hashLengthFound = 8 - break - } - if candidate5.offset < s && s-candidate5.offset < int32(z.MaxDistance) && uint32(cv) == candidate5.val && - binary.LittleEndian.Uint32(src[candidate5.offset:]) == uint32(cv) { - t = candidate5.offset - hashLengthFound = 5 - break - } - - s += 1 + ((s - int32(e.NextEmit)) >> 7) - if s > sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - extra = binary.LittleEndian.Uint32(src[s+8:]) - } - - if hashLengthFound != 0 && hashLengthFound < 12 { - // Look for a "lazy" match with a longer hash at s+1. - cv := binary.LittleEndian.Uint64(src[s+1:]) - extra := binary.LittleEndian.Uint32(src[s+9:]) - nextHash12 := z.hash12(cv, extra) - nextHash8 := z.hash8(cv) - candidate12 := z.table12[nextHash12] - candidate8 := z.table8[nextHash8] - coffset12 := s - candidate12.offset + 1 - coffset8 := s - candidate8.offset + 1 - entry := tableEntry{offset: s + 1, val: uint32(cv)} - z.table12[nextHash12] = entry - z.table8[nextHash8] = entry - if candidate12.offset < s+1 && coffset12 < int32(z.MaxDistance) && uint32(cv) == candidate12.val && - binary.LittleEndian.Uint32(src[candidate12.offset:]) == uint32(cv) { - t = candidate12.offset - s++ - } else if hashLengthFound < 8 && candidate8.offset < s+1 && coffset8 < int32(z.MaxDistance) && uint32(cv) == candidate8.val && - binary.LittleEndian.Uint32(src[candidate8.offset:]) == uint32(cv) { - t = candidate8.offset - s++ - } - } - - currentMatch := extendMatch2(src, int(s), int(t), e.NextEmit) - matches[0] = currentMatch - - index0 := s + 1 - - // We have a match in matches[0]. - // Now look for overlapping matches. - - for { - if matches[0].End > int(sLimit) { - break - } - s = int32(max(matches[0].Start+2, matches[0].End-10)) - - // Store some entries that haven't been indexed yet. - for index0 < s-1 { - cv0 := binary.LittleEndian.Uint64(src[index0:]) - extra0 := binary.LittleEndian.Uint32(src[index0+8:]) - te0 := tableEntry{offset: index0, val: uint32(cv0)} - z.table5[z.hash5(cv0)] = te0 - z.table8[z.hash8(cv0)] = te0 - z.table12[z.hash12(cv0, extra0)] = te0 - index0++ - } - - cv = binary.LittleEndian.Uint64(src[s:]) - extra = binary.LittleEndian.Uint32(src[s+8:]) - - nextHash12 := z.hash12(cv, extra) - nextHash8 := z.hash8(cv) - nextHash5 := z.hash5(cv) - candidate12 := z.table12[nextHash12] - candidate8 := z.table8[nextHash8] - - entry := tableEntry{offset: s, val: uint32(cv)} - z.table12[nextHash12] = entry - z.table8[nextHash8] = entry - z.table5[nextHash5] = entry - - t = -1 - if candidate12.offset < s && s-candidate12.offset < int32(z.MaxDistance) && uint32(cv) == candidate12.val && - binary.LittleEndian.Uint32(src[candidate12.offset:]) == uint32(cv) { - // There is a 12-byte match at s. - t = candidate12.offset - } else if candidate8.offset < s && s-candidate8.offset < int32(z.MaxDistance) && uint32(cv) == candidate8.val && - binary.LittleEndian.Uint32(src[candidate8.offset:]) == uint32(cv) { - // There is a long match at s. - t = candidate8.offset - } - - index0 = s + 1 - - if t == -1 { - // No overlapping match was found. - break - } - - newMatch := extendMatch2(src, int(s), int(t), e.NextEmit) - - if newMatch.End-newMatch.Start <= matches[0].End-matches[0].Start { - // The new match isn't longer than the old one, so we break out of the loop - // of looking for overlapping matches. - break - } - - matches = [3]absoluteMatch{ - newMatch, - matches[0], - matches[1], - } - - if matches[2] == (absoluteMatch{}) { - continue - } - - // We have three matches, so it's time to emit one and/or eliminate one. - switch { - case matches[0].Start < matches[2].End: - // The first and third matches overlap; discard the one in between. - matches = [3]absoluteMatch{ - matches[0], - matches[2], - {}, - } - - case matches[0].Start < matches[2].End+4: - // The first and third matches don't overlap, but there's no room for - // another match between them. Emit the first match and discard the second. - e.emit(matches[2]) - matches = [3]absoluteMatch{ - matches[0], - {}, - {}, - } - - default: - // Emit the first match, shortening it if necessary to avoid overlap with the second. - if matches[2].End > matches[1].Start { - matches[2].End = matches[1].Start - } - if matches[2].End-matches[2].Start >= 4 { - e.emit(matches[2]) - } - matches[2] = absoluteMatch{} - } - } - - // Store some entries up to the end of the last match. - for index0 < int32(matches[0].End) && index0 < sLimit { - cv0 := binary.LittleEndian.Uint64(src[index0:]) - extra0 := binary.LittleEndian.Uint32(src[index0+8:]) - te0 := tableEntry{offset: index0, val: uint32(cv0)} - z.table5[z.hash5(cv0)] = te0 - z.table8[z.hash8(cv0)] = te0 - z.table12[z.hash12(cv0, extra0)] = te0 - index0++ - } - - // We're done looking for overlapping matches; emit the ones we have. - - if matches[1] != (absoluteMatch{}) { - if matches[1].End > matches[0].Start { - matches[1].End = matches[0].Start - } - if matches[1].End-matches[1].Start >= 4 { - e.emit(matches[1]) - } - } - e.emit(matches[0]) - matches = [3]absoluteMatch{} - } - - dst = e.Dst - if e.NextEmit < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - e.NextEmit, - }) - } - - return dst -} - -func (z *Trio) hash5(u uint64) uint32 { - return uint32(((u << 24) * 889523592379) >> (64 - 16)) -} - -func (z *Trio) hash8(u uint64) uint32 { - return uint32((u * 0xcf1bbcdcb7a56463) >> (64 - 17)) -} - -func (z *Trio) hash12(u uint64, e uint32) uint32 { - return uint32((u*0xcf1bbcdcb7a56463 + uint64(e)*(2654435761<<32)) >> (64 - 18)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go deleted file mode 100644 index 6890409b..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/zdfast.go +++ /dev/null @@ -1,258 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" -) - -const ( - zdfastLongTableBits = 17 - zdfastLongTableSize = 1 << zdfastLongTableBits -) - -// ZDFast is a MatchFinder based on the "Default" setting in -// github.com/klauspost/compress/zstd. -type ZDFast struct { - MaxDistance int - - history []byte - // current is the offset at the start of history - current int32 - table [zfastTableSize]tableEntry - longTable [zdfastLongTableSize]tableEntry -} - -func (z *ZDFast) Reset() { - z.current = 0 - z.table = [zfastTableSize]tableEntry{} - z.longTable = [zdfastLongTableSize]tableEntry{} - z.history = z.history[:0] -} - -func (z *ZDFast) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - // Protect against overflow of current. - if int(z.current) >= int(math.MaxInt32)-2*z.MaxDistance-len(z.history) { - minOffset := z.current + int32(len(z.history)) - int32(z.MaxDistance) - for i := range z.table { - v := z.table[i].offset - if v < minOffset { - v = 0 - } else { - v = v - z.current + int32(z.MaxDistance) - } - z.table[i].offset = v - } - for i := range z.longTable { - v := z.longTable[i].offset - if v < minOffset { - v = 0 - } else { - v = v - z.current + int32(z.MaxDistance) - } - z.longTable[i].offset = v - } - z.current = int32(z.MaxDistance) - } - - if len(z.history)+len(src) > cap(z.history) { - // history doesn't have enough capacity to hold the new block. - if cap(z.history) == 0 { - historySize := max(2*z.MaxDistance, 1<<20, len(src)) - z.history = make([]byte, 0, historySize) - } else { - // Move down - offset := len(z.history) - z.MaxDistance - copy(z.history[:z.MaxDistance], z.history[offset:]) - z.current += int32(offset) - z.history = z.history[:z.MaxDistance] - } - } - s := int32(len(z.history)) - z.history = append(z.history, src...) - - if len(src) < 16 { - return append(dst, Match{ - Unmatched: len(src), - }) - } - - src = z.history - sLimit := int32(len(src)) - 10 - - const stepSize = 1 - - nextEmit := s - cv := binary.LittleEndian.Uint64(src[s:]) - var offset1, offset2 int32 - -mainLoop: - for { - // t will contain the match offset when we find one. - // When exiting the search loop, we have already checked 4 bytes. - var t int32 - - for { - nextHashL := z.hashLong(cv) - nextHashS := z.hashShort(cv) - candidateL := z.longTable[nextHashL] - candidateS := z.table[nextHashS] - - repIndex := s - offset1 + 1 - - entry := tableEntry{offset: s + z.current, val: uint32(cv)} - z.longTable[nextHashL] = entry - z.table[nextHashS] = entry - - if offset1 != 0 && repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv>>8) { - // There is a repeated match at s+1. - end := extendMatch(src, int(repIndex+4), int(s+5)) - start := s + 1 - for repIndex > 0 && start > nextEmit && src[repIndex-1] == src[start-1] { - repIndex-- - start-- - } - - dst = append(dst, Match{ - Unmatched: int(start - nextEmit), - Length: end - int(start), - Distance: int(start - repIndex), - }) - s = int32(end) - nextEmit = s - if s >= sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - continue - } - - coffsetL := s - (candidateL.offset - z.current) - coffsetS := s - (candidateS.offset - z.current) - if coffsetL < int32(z.MaxDistance) && uint32(cv) == candidateL.val { - t = candidateL.offset - z.current - if binary.LittleEndian.Uint32(src[t:]) == uint32(cv) { - // found a long match (likely at least 8 bytes) - break - } - } - if coffsetS < int32(z.MaxDistance) && uint32(cv) == candidateS.val { - t = candidateS.offset - z.current - if binary.LittleEndian.Uint32(src[t:]) != uint32(cv) { - goto noMatch - } - // Found a regular match. - // See if we can find a long match at s+1 - cv := binary.LittleEndian.Uint64(src[s+1:]) - nextHashL = z.hashLong(cv) - candidateL = z.longTable[nextHashL] - coffsetL = s - (candidateL.offset - z.current) + 1 - z.longTable[nextHashL] = tableEntry{offset: s + 1 + z.current, val: uint32(cv)} - if coffsetL < int32(z.MaxDistance) && uint32(cv) == candidateL.val { - t = candidateL.offset - z.current - if binary.LittleEndian.Uint32(src[t:]) == uint32(cv) { - // We found a long match at s+1, so we'll use that instead - // of the regular match at s. - s++ - break - } - } - - t = candidateS.offset - z.current - break - } - noMatch: - - s += stepSize + ((s - nextEmit) >> 7) - if s > sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - } - - // A 4-byte match has been found. We'll later see if more than - // 4 bytes. - offset2 = offset1 - offset1 = s - t - - end := extendMatch(src, int(t+4), int(s+4)) - for t > 0 && s > nextEmit && src[t-1] == src[s-1] { - s-- - t-- - } - - dst = append(dst, Match{ - Unmatched: int(s - nextEmit), - Length: end - int(s), - Distance: int(s - t), - }) - prevS := s - s = int32(end) - nextEmit = s - if s >= sLimit { - break mainLoop - } - - // Store some table entries near the start and end of the match. - index0 := prevS + 1 - index1 := s - 2 - cv0 := binary.LittleEndian.Uint64(src[index0:]) - cv1 := binary.LittleEndian.Uint64(src[index1:]) - te0 := tableEntry{offset: index0 + z.current, val: uint32(cv0)} - te1 := tableEntry{offset: index1 + z.current, val: uint32(cv1)} - z.longTable[z.hashLong(cv0)] = te0 - z.longTable[z.hashLong(cv1)] = te1 - cv0 >>= 8 - cv1 >>= 8 - te0.offset++ - te1.offset++ - te0.val = uint32(cv0) - te1.val = uint32(cv1) - z.table[z.hashShort(cv0)] = te0 - z.table[z.hashShort(cv1)] = te1 - - cv = binary.LittleEndian.Uint64(src[s:]) - - // Check offset 2 - if o2 := s - offset2; offset2 != 0 && binary.LittleEndian.Uint32(src[o2:]) == uint32(cv) { - end := extendMatch(src, int(o2+4), int(s+4)) - - // Store the hashes, since we have them. - nextHashS := z.hashShort(cv) - nextHashL := z.hashLong(cv) - entry := tableEntry{offset: s + z.current, val: uint32(cv)} - z.table[nextHashS] = entry - z.longTable[nextHashL] = entry - dst = append(dst, Match{ - Length: end - int(s), - Distance: int(offset2), - }) - s = int32(end) - nextEmit = s - offset1, offset2 = offset2, offset1 - if s >= sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - } - } - - if int(nextEmit) < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - int(nextEmit), - }) - } - - return dst -} - -func (z *ZDFast) hashShort(u uint64) uint32 { - return uint32(((u << 24) * 889523592379) >> (64 - zfastTableBits)) -} - -func (z *ZDFast) hashLong(u uint64) uint32 { - return uint32((u * 0xcf1bbcdcb7a56463) >> (64 - zdfastLongTableBits)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/zfast.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/zfast.go deleted file mode 100644 index 6f2ad8d0..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/zfast.go +++ /dev/null @@ -1,206 +0,0 @@ -package matchfinder - -import ( - "encoding/binary" - "math" -) - -type tableEntry struct { - val uint32 - offset int32 -} - -const ( - zfastTableBits = 15 - zfastTableSize = 1 << zfastTableBits - zfastHashLen = 6 - - prime6Bytes = 227718039650203 -) - -// ZFast is a MatchFinder based on the "Fastest" setting in -// github.com/klauspost/compress/zstd. -type ZFast struct { - MaxDistance int - - history []byte - // current is the offset at the start of history - current int32 - table [zfastTableSize]tableEntry -} - -func (z *ZFast) Reset() { - z.current = 0 - z.table = [zfastTableSize]tableEntry{} - z.history = z.history[:0] -} - -func (z *ZFast) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - // Protect against overflow of current. - if int(z.current) >= int(math.MaxInt32)-2*z.MaxDistance-len(z.history) { - minOffset := z.current + int32(len(z.history)) - int32(z.MaxDistance) - for i := range z.table { - v := z.table[i].offset - if v < minOffset { - v = 0 - } else { - v = v - z.current + int32(z.MaxDistance) - } - z.table[i].offset = v - } - z.current = int32(z.MaxDistance) - } - - if len(z.history)+len(src) > cap(z.history) { - // history doesn't have enough capacity to hold the new block. - if cap(z.history) == 0 { - historySize := max(2*z.MaxDistance, 1<<20, len(src)) - z.history = make([]byte, 0, historySize) - } else { - // Move down - offset := len(z.history) - z.MaxDistance - copy(z.history[:z.MaxDistance], z.history[offset:]) - z.current += int32(offset) - z.history = z.history[:z.MaxDistance] - } - } - s := int32(len(z.history)) - z.history = append(z.history, src...) - - if len(src) < 10 { - return append(dst, Match{ - Unmatched: len(src), - }) - } - - src = z.history - sLimit := int32(len(src)) - 8 - - const stepSize = 2 - - nextEmit := s - cv := binary.LittleEndian.Uint64(src[s:]) - var offset1, offset2 int32 - -mainLoop: - for { - // t will contain the match offset when we find one. - // When exiting the search loop, we have already checked 4 bytes. - var t int32 - - for { - nextHash := z.hash(cv) - nextHash2 := z.hash(cv >> 8) - candidate := z.table[nextHash] - candidate2 := z.table[nextHash2] - repIndex := s - offset1 + 2 - - z.table[nextHash] = tableEntry{offset: s + z.current, val: uint32(cv)} - z.table[nextHash2] = tableEntry{offset: s + z.current + 1, val: uint32(cv >> 8)} - - if offset1 != 0 && repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv>>16) { - // There is a repeated match at s+2. - end := extendMatch(src, int(repIndex+4), int(s+6)) - start := s + 2 - for repIndex > 0 && start > nextEmit && src[repIndex-1] == src[start-1] { - repIndex-- - start-- - } - dst = append(dst, Match{ - Unmatched: int(start - nextEmit), - Length: end - int(start), - Distance: int(start - repIndex), - }) - s = int32(end) - nextEmit = s - if s >= sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - continue - } - - coffset0 := s - (candidate.offset - z.current) - coffset1 := s - (candidate2.offset - z.current) + 1 - if coffset0 < int32(z.MaxDistance) && uint32(cv) == candidate.val { - t = candidate.offset - z.current - if binary.LittleEndian.Uint32(src[t:]) == uint32(cv) { - // found a regular match - break - } - } - if coffset1 < int32(z.MaxDistance) && uint32(cv>>8) == candidate2.val { - t = candidate2.offset - z.current - if binary.LittleEndian.Uint32(src[t:]) == uint32(cv>>8) { - s++ - break - } - } - - s += stepSize + ((s - nextEmit) >> 5) - if s > sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - } - - // A 4-byte match has been found. We'll later see if more than - // 4 bytes. - offset2 = offset1 - offset1 = s - t - - end := extendMatch(src, int(t+4), int(s+4)) - for t > 0 && s > nextEmit && src[t-1] == src[s-1] { - s-- - t-- - } - - dst = append(dst, Match{ - Unmatched: int(s - nextEmit), - Length: end - int(s), - Distance: int(s - t), - }) - s = int32(end) - nextEmit = s - if s >= sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - - // Check offset 2 - if o2 := s - offset2; offset2 != 0 && binary.LittleEndian.Uint32(src[o2:]) == uint32(cv) { - end := extendMatch(src, int(o2+4), int(s+4)) - - // Store the hash, since we have it. - nextHash := z.hash(cv) - z.table[nextHash] = tableEntry{offset: s + z.current, val: uint32(cv)} - dst = append(dst, Match{ - Length: end - int(s), - Distance: int(offset2), - }) - s = int32(end) - nextEmit = s - offset1, offset2 = offset2, offset1 - if s >= sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - } - } - - if int(nextEmit) < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - int(nextEmit), - }) - } - - return dst -} - -func (z *ZFast) hash(u uint64) uint32 { - return uint32(((u << 16) * prime6Bytes) >> (64 - zfastTableBits)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/matchfinder/zm.go b/src/vendor/github.com/andybalholm/brotli/matchfinder/zm.go deleted file mode 100644 index 59a920c3..00000000 --- a/src/vendor/github.com/andybalholm/brotli/matchfinder/zm.go +++ /dev/null @@ -1,301 +0,0 @@ -package matchfinder - -import "encoding/binary" - -const ( - zmTableBits = 15 - zmTableSize = 1 << zmTableBits - zmLongTableBits = 17 - zmLongTableSize = 1 << zmLongTableBits -) - -// ZM is a MatchFinder that combines the cache tables of ZDFast with the -// overlap-based parsing of M4. -type ZM struct { - MaxDistance int - history []byte - table [zmTableSize]tableEntry - longTable [zmLongTableSize]tableEntry -} - -func (z *ZM) Reset() { - z.table = [zmTableSize]tableEntry{} - z.longTable = [zmLongTableSize]tableEntry{} - z.history = z.history[:0] -} - -func (z *ZM) FindMatches(dst []Match, src []byte) []Match { - if z.MaxDistance == 0 { - z.MaxDistance = 1 << 16 - } - - if len(z.history) > z.MaxDistance*2 { - delta := len(z.history) - z.MaxDistance - copy(z.history, z.history[delta:]) - z.history = z.history[:z.MaxDistance] - - for i := range z.table { - v := z.table[i].offset - v -= int32(delta) - if v < 0 { - z.table[i] = tableEntry{} - } else { - z.table[i].offset = v - } - } - for i := range z.longTable { - v := z.longTable[i].offset - v -= int32(delta) - if v < 0 { - z.longTable[i] = tableEntry{} - } else { - z.longTable[i].offset = v - } - } - } - - if len(src) < 16 { - return append(dst, Match{ - Unmatched: len(src), - }) - } - - e := matchEmitter{ - Dst: dst, - NextEmit: len(z.history), - } - z.history = append(z.history, src...) - src = z.history - - // matches stores the matches that have been found but not emitted, - // in reverse order. (matches[0] is the most recent one.) - var matches [3]absoluteMatch - - sLimit := int32(len(src)) - 10 - -mainLoop: - for { - // Search for a match, starting after the last match emitted. - s := int32(e.NextEmit) - if s > sLimit { - break mainLoop - } - - // t will contain the match offset when we find one. - var t int32 - - cv := binary.LittleEndian.Uint64(src[s:]) - - for { - nextHashL := z.hashLong(cv) - nextHashS := z.hashShort(cv) - candidateL := z.longTable[nextHashL] - candidateS := z.table[nextHashS] - - entry := tableEntry{offset: s, val: uint32(cv)} - z.longTable[nextHashL] = entry - z.table[nextHashS] = entry - - // Look for a repeat match one byte after the current position. - if len(e.Dst) > 0 { - prevDistance := int32(e.Dst[len(e.Dst)-1].Distance) - if prevDistance != 0 { - repIndex := s - prevDistance + 1 - if repIndex >= 0 && binary.LittleEndian.Uint32(src[repIndex:]) == uint32(cv>>8) { - // There is a repeated match at s+2. - s++ - t = repIndex - break - } - } - } - - if candidateL.offset < s && s-candidateL.offset < int32(z.MaxDistance) && uint32(cv) == candidateL.val && - binary.LittleEndian.Uint32(src[candidateL.offset:]) == uint32(cv) { - // There is a long match at s. - t = candidateL.offset - break - } - if candidateS.offset < s && s-candidateS.offset < int32(z.MaxDistance) && uint32(cv) == candidateS.val && - binary.LittleEndian.Uint32(src[candidateS.offset:]) == uint32(cv) { - // There is a regular match at s. - // See if we can find a long match at s+1. - cv := binary.LittleEndian.Uint64(src[s+1:]) - nextHashL = z.hashLong(cv) - candidateL = z.longTable[nextHashL] - coffsetL := s - candidateL.offset + 1 - z.longTable[nextHashL] = tableEntry{offset: s + 1, val: uint32(cv)} - if candidateL.offset < s+1 && coffsetL < int32(z.MaxDistance) && uint32(cv) == candidateL.val && - binary.LittleEndian.Uint32(src[candidateL.offset:]) == uint32(cv) { - // We found a long match at s+1, so we'll use that instead - // of the regular match at s. - t = candidateL.offset - s++ - break - } - - t = candidateS.offset - break - } - - s += 1 + ((s - int32(e.NextEmit)) >> 7) - if s > sLimit { - break mainLoop - } - cv = binary.LittleEndian.Uint64(src[s:]) - } - - currentMatch := extendMatch2(src, int(s), int(t), e.NextEmit) - matches[0] = currentMatch - - // Store some table entries after s. - index0 := s + 1 - cv0 := binary.LittleEndian.Uint64(src[index0:]) - te0 := tableEntry{offset: index0, val: uint32(cv0)} - z.longTable[z.hashLong(cv0)] = te0 - cv0 >>= 8 - te0.offset++ - te0.val = uint32(cv0) - z.table[z.hashShort(cv0)] = te0 - - // We have a match in matches[0]. - // Now look for overlapping matches. - - for { - if matches[0].End > int(sLimit) { - break - } - s = int32(max(matches[0].Start+2, matches[0].End-6)) - cv = binary.LittleEndian.Uint64(src[s:]) - - nextHashL := z.hashLong(cv) - nextHashS := z.hashShort(cv) - candidateL := z.longTable[nextHashL] - candidateS := z.table[nextHashS] - - entry := tableEntry{offset: s, val: uint32(cv)} - z.longTable[nextHashL] = entry - z.table[nextHashS] = entry - - t = -1 - if candidateL.offset < s && s-candidateL.offset < int32(z.MaxDistance) && uint32(cv) == candidateL.val && - binary.LittleEndian.Uint32(src[candidateL.offset:]) == uint32(cv) { - // There is a long match at s. - t = candidateL.offset - } else if candidateS.offset < s && s-candidateS.offset < int32(z.MaxDistance) && uint32(cv) == candidateS.val && - binary.LittleEndian.Uint32(src[candidateS.offset:]) == uint32(cv) { - // There is a regular match at s. - t = candidateS.offset - // See if we can find a long match at s+1. - cv := binary.LittleEndian.Uint64(src[s+1:]) - nextHashL = z.hashLong(cv) - candidateL = z.longTable[nextHashL] - coffsetL := s - candidateL.offset + 1 - z.longTable[nextHashL] = tableEntry{offset: s + 1, val: uint32(cv)} - if candidateL.offset < s+1 && coffsetL < int32(z.MaxDistance) && uint32(cv) == candidateL.val && - binary.LittleEndian.Uint32(src[candidateL.offset:]) == uint32(cv) { - // We found a long match at s+1, so we'll use that instead - // of the regular match at s. - t = candidateL.offset - s++ - } - } - - if t == -1 { - // No overlapping match was found. - break - } - - newMatch := extendMatch2(src, int(s), int(t), e.NextEmit) - - if newMatch.End-newMatch.Start <= matches[0].End-matches[0].Start { - // The new match isn't longer than the old one, so we break out of the loop - // of looking for overlapping matches. - break - } - - matches = [3]absoluteMatch{ - newMatch, - matches[0], - matches[1], - } - - if matches[2] == (absoluteMatch{}) { - continue - } - - // We have three matches, so it's time to emit one and/or eliminate one. - switch { - case matches[0].Start < matches[2].End: - // The first and third matches overlap; discard the one in between. - matches = [3]absoluteMatch{ - matches[0], - matches[2], - {}, - } - - case matches[0].Start < matches[2].End+4: - // The first and third matches don't overlap, but there's no room for - // another match between them. Emit the first match and discard the second. - e.emit(matches[2]) - matches = [3]absoluteMatch{ - matches[0], - {}, - {}, - } - - default: - // Emit the first match, shortening it if necessary to avoid overlap with the second. - if matches[2].End > matches[1].Start { - matches[2].End = matches[1].Start - } - if matches[2].End-matches[2].Start >= 4 { - e.emit(matches[2]) - } - matches[2] = absoluteMatch{} - } - } - - // Store some table entries at the end of the last match. - index1 := int32(matches[0].End - 2) - if index1 < sLimit { - cv1 := binary.LittleEndian.Uint64(src[index1:]) - te1 := tableEntry{offset: index1, val: uint32(cv1)} - z.longTable[z.hashLong(cv1)] = te1 - cv1 >>= 8 - te1.offset++ - te1.val = uint32(cv1) - z.table[z.hashShort(cv1)] = te1 - } - - // We're done looking for overlapping matches; emit the ones we have. - - if matches[1] != (absoluteMatch{}) { - if matches[1].End > matches[0].Start { - matches[1].End = matches[0].Start - } - if matches[1].End-matches[1].Start >= 4 { - e.emit(matches[1]) - } - } - e.emit(matches[0]) - matches = [3]absoluteMatch{} - } - - dst = e.Dst - if e.NextEmit < len(src) { - dst = append(dst, Match{ - Unmatched: len(src) - e.NextEmit, - }) - } - - return dst -} - -func (z *ZM) hashShort(u uint64) uint32 { - return uint32(((u << 24) * 889523592379) >> (64 - zmTableBits)) -} - -func (z *ZM) hashLong(u uint64) uint32 { - return uint32((u * 0xcf1bbcdcb7a56463) >> (64 - zmLongTableBits)) -} diff --git a/src/vendor/github.com/andybalholm/brotli/memory.go b/src/vendor/github.com/andybalholm/brotli/memory.go deleted file mode 100644 index a07c7050..00000000 --- a/src/vendor/github.com/andybalholm/brotli/memory.go +++ /dev/null @@ -1,66 +0,0 @@ -package brotli - -/* Copyright 2016 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* -Dynamically grows array capacity to at least the requested size -T: data type -A: array -C: capacity -R: requested size -*/ -func brotli_ensure_capacity_uint8_t(a *[]byte, c *uint, r uint) { - if *c < r { - var new_size uint = *c - if new_size == 0 { - new_size = r - } - - for new_size < r { - new_size *= 2 - } - - if cap(*a) < int(new_size) { - var new_array []byte = make([]byte, new_size) - if *c != 0 { - copy(new_array, (*a)[:*c]) - } - - *a = new_array - } else { - *a = (*a)[:new_size] - } - - *c = new_size - } -} - -func brotli_ensure_capacity_uint32_t(a *[]uint32, c *uint, r uint) { - var new_array []uint32 - if *c < r { - var new_size uint = *c - if new_size == 0 { - new_size = r - } - - for new_size < r { - new_size *= 2 - } - - if cap(*a) < int(new_size) { - new_array = make([]uint32, new_size) - if *c != 0 { - copy(new_array, (*a)[:*c]) - } - - *a = new_array - } else { - *a = (*a)[:new_size] - } - *c = new_size - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/metablock.go b/src/vendor/github.com/andybalholm/brotli/metablock.go deleted file mode 100644 index 3014df8c..00000000 --- a/src/vendor/github.com/andybalholm/brotli/metablock.go +++ /dev/null @@ -1,574 +0,0 @@ -package brotli - -import ( - "sync" -) - -/* Copyright 2014 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Algorithms for distributing the literals and commands of a metablock between - block types and contexts. */ - -type metaBlockSplit struct { - literal_split blockSplit - command_split blockSplit - distance_split blockSplit - literal_context_map []uint32 - literal_context_map_size uint - distance_context_map []uint32 - distance_context_map_size uint - literal_histograms []histogramLiteral - literal_histograms_size uint - command_histograms []histogramCommand - command_histograms_size uint - distance_histograms []histogramDistance - distance_histograms_size uint -} - -var metaBlockPool sync.Pool - -func getMetaBlockSplit() *metaBlockSplit { - mb, _ := metaBlockPool.Get().(*metaBlockSplit) - - if mb == nil { - mb = &metaBlockSplit{} - } else { - initBlockSplit(&mb.literal_split) - initBlockSplit(&mb.command_split) - initBlockSplit(&mb.distance_split) - mb.literal_context_map = mb.literal_context_map[:0] - mb.literal_context_map_size = 0 - mb.distance_context_map = mb.distance_context_map[:0] - mb.distance_context_map_size = 0 - mb.literal_histograms = mb.literal_histograms[:0] - mb.command_histograms = mb.command_histograms[:0] - mb.distance_histograms = mb.distance_histograms[:0] - } - return mb -} - -func freeMetaBlockSplit(mb *metaBlockSplit) { - metaBlockPool.Put(mb) -} - -func initDistanceParams(params *encoderParams, npostfix uint32, ndirect uint32) { - var dist_params *distanceParams = ¶ms.dist - var alphabet_size uint32 - var max_distance uint32 - - dist_params.distance_postfix_bits = npostfix - dist_params.num_direct_distance_codes = ndirect - - alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), maxDistanceBits)) - max_distance = ndirect + (1 << (maxDistanceBits + npostfix + 2)) - (1 << (npostfix + 2)) - - if params.large_window { - var bound = [maxNpostfix + 1]uint32{0, 4, 12, 28} - var postfix uint32 = 1 << npostfix - alphabet_size = uint32(distanceAlphabetSize(uint(npostfix), uint(ndirect), largeMaxDistanceBits)) - - /* The maximum distance is set so that no distance symbol used can encode - a distance larger than BROTLI_MAX_ALLOWED_DISTANCE with all - its extra bits set. */ - if ndirect < bound[npostfix] { - max_distance = maxAllowedDistance - (bound[npostfix] - ndirect) - } else if ndirect >= bound[npostfix]+postfix { - max_distance = (3 << 29) - 4 + (ndirect - bound[npostfix]) - } else { - max_distance = maxAllowedDistance - } - } - - dist_params.alphabet_size = alphabet_size - dist_params.max_distance = uint(max_distance) -} - -func recomputeDistancePrefixes(cmds []command, orig_params *distanceParams, new_params *distanceParams) { - if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes { - return - } - - for i := range cmds { - var cmd *command = &cmds[i] - if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 { - prefixEncodeCopyDistance(uint(commandRestoreDistanceCode(cmd, orig_params)), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &cmd.dist_prefix_, &cmd.dist_extra_) - } - } -} - -func computeDistanceCost(cmds []command, orig_params *distanceParams, new_params *distanceParams, cost *float64) bool { - var equal_params bool = false - var dist_prefix uint16 - var dist_extra uint32 - var extra_bits float64 = 0.0 - var histo histogramDistance - histogramClearDistance(&histo) - - if orig_params.distance_postfix_bits == new_params.distance_postfix_bits && orig_params.num_direct_distance_codes == new_params.num_direct_distance_codes { - equal_params = true - } - - for i := range cmds { - cmd := &cmds[i] - if commandCopyLen(cmd) != 0 && cmd.cmd_prefix_ >= 128 { - if equal_params { - dist_prefix = cmd.dist_prefix_ - } else { - var distance uint32 = commandRestoreDistanceCode(cmd, orig_params) - if distance > uint32(new_params.max_distance) { - return false - } - - prefixEncodeCopyDistance(uint(distance), uint(new_params.num_direct_distance_codes), uint(new_params.distance_postfix_bits), &dist_prefix, &dist_extra) - } - - histogramAddDistance(&histo, uint(dist_prefix)&0x3FF) - extra_bits += float64(dist_prefix >> 10) - } - } - - *cost = populationCostDistance(&histo) + extra_bits - return true -} - -var buildMetaBlock_kMaxNumberOfHistograms uint = 256 - -func buildMetaBlock(ringbuffer []byte, pos uint, mask uint, params *encoderParams, prev_byte byte, prev_byte2 byte, cmds []command, literal_context_mode int, mb *metaBlockSplit) { - var distance_histograms []histogramDistance - var literal_histograms []histogramLiteral - var literal_context_modes []int = nil - var literal_histograms_size uint - var distance_histograms_size uint - var i uint - var literal_context_multiplier uint = 1 - var npostfix uint32 - var ndirect_msb uint32 = 0 - var check_orig bool = true - var best_dist_cost float64 = 1e99 - var orig_params encoderParams = *params - /* Histogram ids need to fit in one byte. */ - - var new_params encoderParams = *params - - for npostfix = 0; npostfix <= maxNpostfix; npostfix++ { - for ; ndirect_msb < 16; ndirect_msb++ { - var ndirect uint32 = ndirect_msb << npostfix - var skip bool - var dist_cost float64 - initDistanceParams(&new_params, npostfix, ndirect) - if npostfix == orig_params.dist.distance_postfix_bits && ndirect == orig_params.dist.num_direct_distance_codes { - check_orig = false - } - - skip = !computeDistanceCost(cmds, &orig_params.dist, &new_params.dist, &dist_cost) - if skip || (dist_cost > best_dist_cost) { - break - } - - best_dist_cost = dist_cost - params.dist = new_params.dist - } - - if ndirect_msb > 0 { - ndirect_msb-- - } - ndirect_msb /= 2 - } - - if check_orig { - var dist_cost float64 - computeDistanceCost(cmds, &orig_params.dist, &orig_params.dist, &dist_cost) - if dist_cost < best_dist_cost { - /* NB: currently unused; uncomment when more param tuning is added. */ - /* best_dist_cost = dist_cost; */ - params.dist = orig_params.dist - } - } - - recomputeDistancePrefixes(cmds, &orig_params.dist, ¶ms.dist) - - splitBlock(cmds, ringbuffer, pos, mask, params, &mb.literal_split, &mb.command_split, &mb.distance_split) - - if !params.disable_literal_context_modeling { - literal_context_multiplier = 1 << literalContextBits - literal_context_modes = make([]int, (mb.literal_split.num_types)) - for i = 0; i < mb.literal_split.num_types; i++ { - literal_context_modes[i] = literal_context_mode - } - } - - literal_histograms_size = mb.literal_split.num_types * literal_context_multiplier - literal_histograms = make([]histogramLiteral, literal_histograms_size) - clearHistogramsLiteral(literal_histograms, literal_histograms_size) - - distance_histograms_size = mb.distance_split.num_types << distanceContextBits - distance_histograms = make([]histogramDistance, distance_histograms_size) - clearHistogramsDistance(distance_histograms, distance_histograms_size) - - mb.command_histograms_size = mb.command_split.num_types - if cap(mb.command_histograms) < int(mb.command_histograms_size) { - mb.command_histograms = make([]histogramCommand, (mb.command_histograms_size)) - } else { - mb.command_histograms = mb.command_histograms[:mb.command_histograms_size] - } - clearHistogramsCommand(mb.command_histograms, mb.command_histograms_size) - - buildHistogramsWithContext(cmds, &mb.literal_split, &mb.command_split, &mb.distance_split, ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes, literal_histograms, mb.command_histograms, distance_histograms) - literal_context_modes = nil - - mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits - if cap(mb.literal_context_map) < int(mb.literal_context_map_size) { - mb.literal_context_map = make([]uint32, (mb.literal_context_map_size)) - } else { - mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size] - } - - mb.literal_histograms_size = mb.literal_context_map_size - if cap(mb.literal_histograms) < int(mb.literal_histograms_size) { - mb.literal_histograms = make([]histogramLiteral, (mb.literal_histograms_size)) - } else { - mb.literal_histograms = mb.literal_histograms[:mb.literal_histograms_size] - } - - clusterHistogramsLiteral(literal_histograms, literal_histograms_size, buildMetaBlock_kMaxNumberOfHistograms, mb.literal_histograms, &mb.literal_histograms_size, mb.literal_context_map) - literal_histograms = nil - - if params.disable_literal_context_modeling { - /* Distribute assignment to all contexts. */ - for i = mb.literal_split.num_types; i != 0; { - var j uint = 0 - i-- - for ; j < 1< 0 { - var entropy [maxStaticContexts]float64 - var combined_histo []histogramLiteral = make([]histogramLiteral, (2 * num_contexts)) - var combined_entropy [2 * maxStaticContexts]float64 - var diff = [2]float64{0.0} - /* Try merging the set of histograms for the current block type with the - respective set of histograms for the last and second last block types. - Decide over the split based on the total reduction of entropy across - all contexts. */ - - var i uint - for i = 0; i < num_contexts; i++ { - var curr_histo_ix uint = self.curr_histogram_ix_ + i - var j uint - entropy[i] = bitsEntropy(histograms[curr_histo_ix].data_[:], self.alphabet_size_) - for j = 0; j < 2; j++ { - var jx uint = j*num_contexts + i - var last_histogram_ix uint = self.last_histogram_ix_[j] + i - combined_histo[jx] = histograms[curr_histo_ix] - histogramAddHistogramLiteral(&combined_histo[jx], &histograms[last_histogram_ix]) - combined_entropy[jx] = bitsEntropy(combined_histo[jx].data_[0:], self.alphabet_size_) - diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx] - } - } - - if split.num_types < self.max_block_types_ && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ { - /* Create new block. */ - split.lengths[self.num_blocks_] = uint32(self.block_size_) - - split.types[self.num_blocks_] = byte(split.num_types) - self.last_histogram_ix_[1] = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = split.num_types * num_contexts - for i = 0; i < num_contexts; i++ { - last_entropy[num_contexts+i] = last_entropy[i] - last_entropy[i] = entropy[i] - } - - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_ += num_contexts - if self.curr_histogram_ix_ < *self.histograms_size_ { - clearHistogramsLiteral(self.histograms_[self.curr_histogram_ix_:], self.num_contexts_) - } - - self.block_size_ = 0 - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else if diff[1] < diff[0]-20.0 { - split.lengths[self.num_blocks_] = uint32(self.block_size_) - split.types[self.num_blocks_] = split.types[self.num_blocks_-2] - /* Combine this block with second last block. */ - - var tmp uint = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] - self.last_histogram_ix_[1] = tmp - for i = 0; i < num_contexts; i++ { - histograms[self.last_histogram_ix_[0]+i] = combined_histo[num_contexts+i] - last_entropy[num_contexts+i] = last_entropy[i] - last_entropy[i] = combined_entropy[num_contexts+i] - histogramClearLiteral(&histograms[self.curr_histogram_ix_+i]) - } - - self.num_blocks_++ - self.block_size_ = 0 - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else { - /* Combine this block with last block. */ - split.lengths[self.num_blocks_-1] += uint32(self.block_size_) - - for i = 0; i < num_contexts; i++ { - histograms[self.last_histogram_ix_[0]+i] = combined_histo[i] - last_entropy[i] = combined_entropy[i] - if split.num_types == 1 { - last_entropy[num_contexts+i] = last_entropy[i] - } - - histogramClearLiteral(&histograms[self.curr_histogram_ix_+i]) - } - - self.block_size_ = 0 - self.merge_last_count_++ - if self.merge_last_count_ > 1 { - self.target_block_size_ += self.min_block_size_ - } - } - - combined_histo = nil - } - - if is_final { - *self.histograms_size_ = split.num_types * num_contexts - split.num_blocks = self.num_blocks_ - } -} - -/* Adds the next symbol to the current block type and context. When the - current block reaches the target size, decides on merging the block. */ -func contextBlockSplitterAddSymbol(self *contextBlockSplitter, symbol uint, context uint) { - histogramAddLiteral(&self.histograms_[self.curr_histogram_ix_+context], symbol) - self.block_size_++ - if self.block_size_ == self.target_block_size_ { - contextBlockSplitterFinishBlock(self, false) /* is_final = */ - } -} - -func mapStaticContexts(num_contexts uint, static_context_map []uint32, mb *metaBlockSplit) { - var i uint - mb.literal_context_map_size = mb.literal_split.num_types << literalContextBits - if cap(mb.literal_context_map) < int(mb.literal_context_map_size) { - mb.literal_context_map = make([]uint32, (mb.literal_context_map_size)) - } else { - mb.literal_context_map = mb.literal_context_map[:mb.literal_context_map_size] - } - - for i = 0; i < mb.literal_split.num_types; i++ { - var offset uint32 = uint32(i * num_contexts) - var j uint - for j = 0; j < 1<= 128 { - blockSplitterAddSymbolDistance(&dist_blocks, uint(cmd.dist_prefix_)&0x3FF) - } - } - } - - if num_contexts == 1 { - blockSplitterFinishBlockLiteral(&lit_blocks.plain, true) /* is_final = */ - } else { - contextBlockSplitterFinishBlock(&lit_blocks.ctx, true) /* is_final = */ - } - - blockSplitterFinishBlockCommand(&cmd_blocks, true) /* is_final = */ - blockSplitterFinishBlockDistance(&dist_blocks, true) /* is_final = */ - - if num_contexts > 1 { - mapStaticContexts(num_contexts, static_context_map, mb) - } -} - -func buildMetaBlockGreedy(ringbuffer []byte, pos uint, mask uint, prev_byte byte, prev_byte2 byte, literal_context_lut contextLUT, num_contexts uint, static_context_map []uint32, commands []command, mb *metaBlockSplit) { - if num_contexts == 1 { - buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, 1, nil, commands, mb) - } else { - buildMetaBlockGreedyInternal(ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_lut, num_contexts, static_context_map, commands, mb) - } -} - -func optimizeHistograms(num_distance_codes uint32, mb *metaBlockSplit) { - var good_for_rle [numCommandSymbols]byte - var i uint - for i = 0; i < mb.literal_histograms_size; i++ { - optimizeHuffmanCountsForRLE(256, mb.literal_histograms[i].data_[:], good_for_rle[:]) - } - - for i = 0; i < mb.command_histograms_size; i++ { - optimizeHuffmanCountsForRLE(numCommandSymbols, mb.command_histograms[i].data_[:], good_for_rle[:]) - } - - for i = 0; i < mb.distance_histograms_size; i++ { - optimizeHuffmanCountsForRLE(uint(num_distance_codes), mb.distance_histograms[i].data_[:], good_for_rle[:]) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/metablock_command.go b/src/vendor/github.com/andybalholm/brotli/metablock_command.go deleted file mode 100644 index 46459723..00000000 --- a/src/vendor/github.com/andybalholm/brotli/metablock_command.go +++ /dev/null @@ -1,165 +0,0 @@ -package brotli - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Greedy block splitter for one block category (literal, command or distance). - */ -type blockSplitterCommand struct { - alphabet_size_ uint - min_block_size_ uint - split_threshold_ float64 - num_blocks_ uint - split_ *blockSplit - histograms_ []histogramCommand - histograms_size_ *uint - target_block_size_ uint - block_size_ uint - curr_histogram_ix_ uint - last_histogram_ix_ [2]uint - last_entropy_ [2]float64 - merge_last_count_ uint -} - -func initBlockSplitterCommand(self *blockSplitterCommand, alphabet_size uint, min_block_size uint, split_threshold float64, num_symbols uint, split *blockSplit, histograms *[]histogramCommand, histograms_size *uint) { - var max_num_blocks uint = num_symbols/min_block_size + 1 - var max_num_types uint = brotli_min_size_t(max_num_blocks, maxNumberOfBlockTypes+1) - /* We have to allocate one more histogram than the maximum number of block - types for the current histogram when the meta-block is too big. */ - self.alphabet_size_ = alphabet_size - - self.min_block_size_ = min_block_size - self.split_threshold_ = split_threshold - self.num_blocks_ = 0 - self.split_ = split - self.histograms_size_ = histograms_size - self.target_block_size_ = min_block_size - self.block_size_ = 0 - self.curr_histogram_ix_ = 0 - self.merge_last_count_ = 0 - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, max_num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, max_num_blocks) - self.split_.num_blocks = max_num_blocks - *histograms_size = max_num_types - if cap(*histograms) < int(*histograms_size) { - *histograms = make([]histogramCommand, (*histograms_size)) - } else { - *histograms = (*histograms)[:*histograms_size] - } - self.histograms_ = *histograms - - /* Clear only current histogram. */ - histogramClearCommand(&self.histograms_[0]) - - self.last_histogram_ix_[1] = 0 - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] -} - -/* Does either of three things: - (1) emits the current block with a new block type; - (2) emits the current block with the type of the second last block; - (3) merges the current block with the last block. */ -func blockSplitterFinishBlockCommand(self *blockSplitterCommand, is_final bool) { - var split *blockSplit = self.split_ - var last_entropy []float64 = self.last_entropy_[:] - var histograms []histogramCommand = self.histograms_ - self.block_size_ = brotli_max_size_t(self.block_size_, self.min_block_size_) - if self.num_blocks_ == 0 { - /* Create first block. */ - split.lengths[0] = uint32(self.block_size_) - - split.types[0] = 0 - last_entropy[0] = bitsEntropy(histograms[0].data_[:], self.alphabet_size_) - last_entropy[1] = last_entropy[0] - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearCommand(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - } else if self.block_size_ > 0 { - var entropy float64 = bitsEntropy(histograms[self.curr_histogram_ix_].data_[:], self.alphabet_size_) - var combined_histo [2]histogramCommand - var combined_entropy [2]float64 - var diff [2]float64 - var j uint - for j = 0; j < 2; j++ { - var last_histogram_ix uint = self.last_histogram_ix_[j] - combined_histo[j] = histograms[self.curr_histogram_ix_] - histogramAddHistogramCommand(&combined_histo[j], &histograms[last_histogram_ix]) - combined_entropy[j] = bitsEntropy(combined_histo[j].data_[0:], self.alphabet_size_) - diff[j] = combined_entropy[j] - entropy - last_entropy[j] - } - - if split.num_types < maxNumberOfBlockTypes && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ { - /* Create new block. */ - split.lengths[self.num_blocks_] = uint32(self.block_size_) - - split.types[self.num_blocks_] = byte(split.num_types) - self.last_histogram_ix_[1] = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = uint(byte(split.num_types)) - last_entropy[1] = last_entropy[0] - last_entropy[0] = entropy - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearCommand(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else if diff[1] < diff[0]-20.0 { - split.lengths[self.num_blocks_] = uint32(self.block_size_) - split.types[self.num_blocks_] = split.types[self.num_blocks_-2] - /* Combine this block with second last block. */ - - var tmp uint = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] - self.last_histogram_ix_[1] = tmp - histograms[self.last_histogram_ix_[0]] = combined_histo[1] - last_entropy[1] = last_entropy[0] - last_entropy[0] = combined_entropy[1] - self.num_blocks_++ - self.block_size_ = 0 - histogramClearCommand(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else { - /* Combine this block with last block. */ - split.lengths[self.num_blocks_-1] += uint32(self.block_size_) - - histograms[self.last_histogram_ix_[0]] = combined_histo[0] - last_entropy[0] = combined_entropy[0] - if split.num_types == 1 { - last_entropy[1] = last_entropy[0] - } - - self.block_size_ = 0 - histogramClearCommand(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_++ - if self.merge_last_count_ > 1 { - self.target_block_size_ += self.min_block_size_ - } - } - } - - if is_final { - *self.histograms_size_ = split.num_types - split.num_blocks = self.num_blocks_ - } -} - -/* Adds the next symbol to the current histogram. When the current histogram - reaches the target size, decides on merging the block. */ -func blockSplitterAddSymbolCommand(self *blockSplitterCommand, symbol uint) { - histogramAddCommand(&self.histograms_[self.curr_histogram_ix_], symbol) - self.block_size_++ - if self.block_size_ == self.target_block_size_ { - blockSplitterFinishBlockCommand(self, false) /* is_final = */ - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/metablock_distance.go b/src/vendor/github.com/andybalholm/brotli/metablock_distance.go deleted file mode 100644 index 90837294..00000000 --- a/src/vendor/github.com/andybalholm/brotli/metablock_distance.go +++ /dev/null @@ -1,165 +0,0 @@ -package brotli - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Greedy block splitter for one block category (literal, command or distance). - */ -type blockSplitterDistance struct { - alphabet_size_ uint - min_block_size_ uint - split_threshold_ float64 - num_blocks_ uint - split_ *blockSplit - histograms_ []histogramDistance - histograms_size_ *uint - target_block_size_ uint - block_size_ uint - curr_histogram_ix_ uint - last_histogram_ix_ [2]uint - last_entropy_ [2]float64 - merge_last_count_ uint -} - -func initBlockSplitterDistance(self *blockSplitterDistance, alphabet_size uint, min_block_size uint, split_threshold float64, num_symbols uint, split *blockSplit, histograms *[]histogramDistance, histograms_size *uint) { - var max_num_blocks uint = num_symbols/min_block_size + 1 - var max_num_types uint = brotli_min_size_t(max_num_blocks, maxNumberOfBlockTypes+1) - /* We have to allocate one more histogram than the maximum number of block - types for the current histogram when the meta-block is too big. */ - self.alphabet_size_ = alphabet_size - - self.min_block_size_ = min_block_size - self.split_threshold_ = split_threshold - self.num_blocks_ = 0 - self.split_ = split - self.histograms_size_ = histograms_size - self.target_block_size_ = min_block_size - self.block_size_ = 0 - self.curr_histogram_ix_ = 0 - self.merge_last_count_ = 0 - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, max_num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, max_num_blocks) - self.split_.num_blocks = max_num_blocks - *histograms_size = max_num_types - if cap(*histograms) < int(*histograms_size) { - *histograms = make([]histogramDistance, *histograms_size) - } else { - *histograms = (*histograms)[:*histograms_size] - } - self.histograms_ = *histograms - - /* Clear only current histogram. */ - histogramClearDistance(&self.histograms_[0]) - - self.last_histogram_ix_[1] = 0 - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] -} - -/* Does either of three things: - (1) emits the current block with a new block type; - (2) emits the current block with the type of the second last block; - (3) merges the current block with the last block. */ -func blockSplitterFinishBlockDistance(self *blockSplitterDistance, is_final bool) { - var split *blockSplit = self.split_ - var last_entropy []float64 = self.last_entropy_[:] - var histograms []histogramDistance = self.histograms_ - self.block_size_ = brotli_max_size_t(self.block_size_, self.min_block_size_) - if self.num_blocks_ == 0 { - /* Create first block. */ - split.lengths[0] = uint32(self.block_size_) - - split.types[0] = 0 - last_entropy[0] = bitsEntropy(histograms[0].data_[:], self.alphabet_size_) - last_entropy[1] = last_entropy[0] - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearDistance(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - } else if self.block_size_ > 0 { - var entropy float64 = bitsEntropy(histograms[self.curr_histogram_ix_].data_[:], self.alphabet_size_) - var combined_histo [2]histogramDistance - var combined_entropy [2]float64 - var diff [2]float64 - var j uint - for j = 0; j < 2; j++ { - var last_histogram_ix uint = self.last_histogram_ix_[j] - combined_histo[j] = histograms[self.curr_histogram_ix_] - histogramAddHistogramDistance(&combined_histo[j], &histograms[last_histogram_ix]) - combined_entropy[j] = bitsEntropy(combined_histo[j].data_[0:], self.alphabet_size_) - diff[j] = combined_entropy[j] - entropy - last_entropy[j] - } - - if split.num_types < maxNumberOfBlockTypes && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ { - /* Create new block. */ - split.lengths[self.num_blocks_] = uint32(self.block_size_) - - split.types[self.num_blocks_] = byte(split.num_types) - self.last_histogram_ix_[1] = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = uint(byte(split.num_types)) - last_entropy[1] = last_entropy[0] - last_entropy[0] = entropy - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearDistance(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else if diff[1] < diff[0]-20.0 { - split.lengths[self.num_blocks_] = uint32(self.block_size_) - split.types[self.num_blocks_] = split.types[self.num_blocks_-2] - /* Combine this block with second last block. */ - - var tmp uint = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] - self.last_histogram_ix_[1] = tmp - histograms[self.last_histogram_ix_[0]] = combined_histo[1] - last_entropy[1] = last_entropy[0] - last_entropy[0] = combined_entropy[1] - self.num_blocks_++ - self.block_size_ = 0 - histogramClearDistance(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else { - /* Combine this block with last block. */ - split.lengths[self.num_blocks_-1] += uint32(self.block_size_) - - histograms[self.last_histogram_ix_[0]] = combined_histo[0] - last_entropy[0] = combined_entropy[0] - if split.num_types == 1 { - last_entropy[1] = last_entropy[0] - } - - self.block_size_ = 0 - histogramClearDistance(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_++ - if self.merge_last_count_ > 1 { - self.target_block_size_ += self.min_block_size_ - } - } - } - - if is_final { - *self.histograms_size_ = split.num_types - split.num_blocks = self.num_blocks_ - } -} - -/* Adds the next symbol to the current histogram. When the current histogram - reaches the target size, decides on merging the block. */ -func blockSplitterAddSymbolDistance(self *blockSplitterDistance, symbol uint) { - histogramAddDistance(&self.histograms_[self.curr_histogram_ix_], symbol) - self.block_size_++ - if self.block_size_ == self.target_block_size_ { - blockSplitterFinishBlockDistance(self, false) /* is_final = */ - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/metablock_literal.go b/src/vendor/github.com/andybalholm/brotli/metablock_literal.go deleted file mode 100644 index 1c8b235b..00000000 --- a/src/vendor/github.com/andybalholm/brotli/metablock_literal.go +++ /dev/null @@ -1,165 +0,0 @@ -package brotli - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Greedy block splitter for one block category (literal, command or distance). - */ -type blockSplitterLiteral struct { - alphabet_size_ uint - min_block_size_ uint - split_threshold_ float64 - num_blocks_ uint - split_ *blockSplit - histograms_ []histogramLiteral - histograms_size_ *uint - target_block_size_ uint - block_size_ uint - curr_histogram_ix_ uint - last_histogram_ix_ [2]uint - last_entropy_ [2]float64 - merge_last_count_ uint -} - -func initBlockSplitterLiteral(self *blockSplitterLiteral, alphabet_size uint, min_block_size uint, split_threshold float64, num_symbols uint, split *blockSplit, histograms *[]histogramLiteral, histograms_size *uint) { - var max_num_blocks uint = num_symbols/min_block_size + 1 - var max_num_types uint = brotli_min_size_t(max_num_blocks, maxNumberOfBlockTypes+1) - /* We have to allocate one more histogram than the maximum number of block - types for the current histogram when the meta-block is too big. */ - self.alphabet_size_ = alphabet_size - - self.min_block_size_ = min_block_size - self.split_threshold_ = split_threshold - self.num_blocks_ = 0 - self.split_ = split - self.histograms_size_ = histograms_size - self.target_block_size_ = min_block_size - self.block_size_ = 0 - self.curr_histogram_ix_ = 0 - self.merge_last_count_ = 0 - brotli_ensure_capacity_uint8_t(&split.types, &split.types_alloc_size, max_num_blocks) - brotli_ensure_capacity_uint32_t(&split.lengths, &split.lengths_alloc_size, max_num_blocks) - self.split_.num_blocks = max_num_blocks - *histograms_size = max_num_types - if cap(*histograms) < int(*histograms_size) { - *histograms = make([]histogramLiteral, *histograms_size) - } else { - *histograms = (*histograms)[:*histograms_size] - } - self.histograms_ = *histograms - - /* Clear only current histogram. */ - histogramClearLiteral(&self.histograms_[0]) - - self.last_histogram_ix_[1] = 0 - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] -} - -/* Does either of three things: - (1) emits the current block with a new block type; - (2) emits the current block with the type of the second last block; - (3) merges the current block with the last block. */ -func blockSplitterFinishBlockLiteral(self *blockSplitterLiteral, is_final bool) { - var split *blockSplit = self.split_ - var last_entropy []float64 = self.last_entropy_[:] - var histograms []histogramLiteral = self.histograms_ - self.block_size_ = brotli_max_size_t(self.block_size_, self.min_block_size_) - if self.num_blocks_ == 0 { - /* Create first block. */ - split.lengths[0] = uint32(self.block_size_) - - split.types[0] = 0 - last_entropy[0] = bitsEntropy(histograms[0].data_[:], self.alphabet_size_) - last_entropy[1] = last_entropy[0] - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearLiteral(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - } else if self.block_size_ > 0 { - var entropy float64 = bitsEntropy(histograms[self.curr_histogram_ix_].data_[:], self.alphabet_size_) - var combined_histo [2]histogramLiteral - var combined_entropy [2]float64 - var diff [2]float64 - var j uint - for j = 0; j < 2; j++ { - var last_histogram_ix uint = self.last_histogram_ix_[j] - combined_histo[j] = histograms[self.curr_histogram_ix_] - histogramAddHistogramLiteral(&combined_histo[j], &histograms[last_histogram_ix]) - combined_entropy[j] = bitsEntropy(combined_histo[j].data_[0:], self.alphabet_size_) - diff[j] = combined_entropy[j] - entropy - last_entropy[j] - } - - if split.num_types < maxNumberOfBlockTypes && diff[0] > self.split_threshold_ && diff[1] > self.split_threshold_ { - /* Create new block. */ - split.lengths[self.num_blocks_] = uint32(self.block_size_) - - split.types[self.num_blocks_] = byte(split.num_types) - self.last_histogram_ix_[1] = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = uint(byte(split.num_types)) - last_entropy[1] = last_entropy[0] - last_entropy[0] = entropy - self.num_blocks_++ - split.num_types++ - self.curr_histogram_ix_++ - if self.curr_histogram_ix_ < *self.histograms_size_ { - histogramClearLiteral(&histograms[self.curr_histogram_ix_]) - } - self.block_size_ = 0 - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else if diff[1] < diff[0]-20.0 { - split.lengths[self.num_blocks_] = uint32(self.block_size_) - split.types[self.num_blocks_] = split.types[self.num_blocks_-2] - /* Combine this block with second last block. */ - - var tmp uint = self.last_histogram_ix_[0] - self.last_histogram_ix_[0] = self.last_histogram_ix_[1] - self.last_histogram_ix_[1] = tmp - histograms[self.last_histogram_ix_[0]] = combined_histo[1] - last_entropy[1] = last_entropy[0] - last_entropy[0] = combined_entropy[1] - self.num_blocks_++ - self.block_size_ = 0 - histogramClearLiteral(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_ = 0 - self.target_block_size_ = self.min_block_size_ - } else { - /* Combine this block with last block. */ - split.lengths[self.num_blocks_-1] += uint32(self.block_size_) - - histograms[self.last_histogram_ix_[0]] = combined_histo[0] - last_entropy[0] = combined_entropy[0] - if split.num_types == 1 { - last_entropy[1] = last_entropy[0] - } - - self.block_size_ = 0 - histogramClearLiteral(&histograms[self.curr_histogram_ix_]) - self.merge_last_count_++ - if self.merge_last_count_ > 1 { - self.target_block_size_ += self.min_block_size_ - } - } - } - - if is_final { - *self.histograms_size_ = split.num_types - split.num_blocks = self.num_blocks_ - } -} - -/* Adds the next symbol to the current histogram. When the current histogram - reaches the target size, decides on merging the block. */ -func blockSplitterAddSymbolLiteral(self *blockSplitterLiteral, symbol uint) { - histogramAddLiteral(&self.histograms_[self.curr_histogram_ix_], symbol) - self.block_size_++ - if self.block_size_ == self.target_block_size_ { - blockSplitterFinishBlockLiteral(self, false) /* is_final = */ - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/params.go b/src/vendor/github.com/andybalholm/brotli/params.go deleted file mode 100644 index 0a4c6875..00000000 --- a/src/vendor/github.com/andybalholm/brotli/params.go +++ /dev/null @@ -1,37 +0,0 @@ -package brotli - -/* Copyright 2017 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Parameters for the Brotli encoder with chosen quality levels. */ -type hasherParams struct { - type_ int - bucket_bits int - block_bits int - hash_len int - num_last_distances_to_check int -} - -type distanceParams struct { - distance_postfix_bits uint32 - num_direct_distance_codes uint32 - alphabet_size uint32 - max_distance uint -} - -/* Encoding parameters */ -type encoderParams struct { - mode int - quality int - lgwin uint - lgblock int - size_hint uint - disable_literal_context_modeling bool - large_window bool - hasher hasherParams - dist distanceParams - dictionary encoderDictionary -} diff --git a/src/vendor/github.com/andybalholm/brotli/platform.go b/src/vendor/github.com/andybalholm/brotli/platform.go deleted file mode 100644 index 4ebfb152..00000000 --- a/src/vendor/github.com/andybalholm/brotli/platform.go +++ /dev/null @@ -1,103 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -func brotli_min_double(a float64, b float64) float64 { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_double(a float64, b float64) float64 { - if a > b { - return a - } else { - return b - } -} - -func brotli_min_float(a float32, b float32) float32 { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_float(a float32, b float32) float32 { - if a > b { - return a - } else { - return b - } -} - -func brotli_min_int(a int, b int) int { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_int(a int, b int) int { - if a > b { - return a - } else { - return b - } -} - -func brotli_min_size_t(a uint, b uint) uint { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_size_t(a uint, b uint) uint { - if a > b { - return a - } else { - return b - } -} - -func brotli_min_uint32_t(a uint32, b uint32) uint32 { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_uint32_t(a uint32, b uint32) uint32 { - if a > b { - return a - } else { - return b - } -} - -func brotli_min_uint8_t(a byte, b byte) byte { - if a < b { - return a - } else { - return b - } -} - -func brotli_max_uint8_t(a byte, b byte) byte { - if a > b { - return a - } else { - return b - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/prefix.go b/src/vendor/github.com/andybalholm/brotli/prefix.go deleted file mode 100644 index 484df0d6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/prefix.go +++ /dev/null @@ -1,30 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Functions for encoding of integers into prefix codes the amount of extra - bits, and the actual values of the extra bits. */ - -/* Here distance_code is an intermediate code, i.e. one of the special codes or - the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */ -func prefixEncodeCopyDistance(distance_code uint, num_direct_codes uint, postfix_bits uint, code *uint16, extra_bits *uint32) { - if distance_code < numDistanceShortCodes+num_direct_codes { - *code = uint16(distance_code) - *extra_bits = 0 - return - } else { - var dist uint = (uint(1) << (postfix_bits + 2)) + (distance_code - numDistanceShortCodes - num_direct_codes) - var bucket uint = uint(log2FloorNonZero(dist) - 1) - var postfix_mask uint = (1 << postfix_bits) - 1 - var postfix uint = dist & postfix_mask - var prefix uint = (dist >> bucket) & 1 - var offset uint = (2 + prefix) << bucket - var nbits uint = bucket - postfix_bits - *code = uint16(nbits<<10 | (numDistanceShortCodes + num_direct_codes + ((2*(nbits-1) + prefix) << postfix_bits) + postfix)) - *extra_bits = uint32((dist - offset) >> postfix_bits) - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/prefix_dec.go b/src/vendor/github.com/andybalholm/brotli/prefix_dec.go deleted file mode 100644 index 183f0d53..00000000 --- a/src/vendor/github.com/andybalholm/brotli/prefix_dec.go +++ /dev/null @@ -1,723 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -type cmdLutElement struct { - insert_len_extra_bits byte - copy_len_extra_bits byte - distance_code int8 - context byte - insert_len_offset uint16 - copy_len_offset uint16 -} - -var kCmdLut = [numCommandSymbols]cmdLutElement{ - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0000, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0000, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0000, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0000, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0000, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0000, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0000, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0000, 0x0009}, - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0001, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0001, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0001, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0001, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0001, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0001, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0001, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0001, 0x0009}, - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0002, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0002, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0002, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0002, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0002, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0002, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0002, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0002, 0x0009}, - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0003, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0003, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0003, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0003, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0003, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0003, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0003, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0003, 0x0009}, - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0004, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0004, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0004, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0004, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0004, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0004, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0004, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0004, 0x0009}, - cmdLutElement{0x00, 0x00, 0, 0x00, 0x0005, 0x0002}, - cmdLutElement{0x00, 0x00, 0, 0x01, 0x0005, 0x0003}, - cmdLutElement{0x00, 0x00, 0, 0x02, 0x0005, 0x0004}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0005, 0x0005}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0005, 0x0006}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0005, 0x0007}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0005, 0x0008}, - cmdLutElement{0x00, 0x00, 0, 0x03, 0x0005, 0x0009}, - cmdLutElement{0x01, 0x00, 0, 0x00, 0x0006, 0x0002}, - cmdLutElement{0x01, 0x00, 0, 0x01, 0x0006, 0x0003}, - cmdLutElement{0x01, 0x00, 0, 0x02, 0x0006, 0x0004}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0006, 0x0005}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0006, 0x0006}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0006, 0x0007}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0006, 0x0008}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0006, 0x0009}, - cmdLutElement{0x01, 0x00, 0, 0x00, 0x0008, 0x0002}, - cmdLutElement{0x01, 0x00, 0, 0x01, 0x0008, 0x0003}, - cmdLutElement{0x01, 0x00, 0, 0x02, 0x0008, 0x0004}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0008, 0x0005}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0008, 0x0006}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0008, 0x0007}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0008, 0x0008}, - cmdLutElement{0x01, 0x00, 0, 0x03, 0x0008, 0x0009}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0000, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0000, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0000, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0000, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0000, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0000, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0000, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0000, 0x0036}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0001, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0001, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0001, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0001, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0001, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0001, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0001, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0001, 0x0036}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0002, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0002, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0002, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0002, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0002, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0002, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0002, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0002, 0x0036}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0003, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0003, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0003, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0003, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0003, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0003, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0003, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0003, 0x0036}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0004, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0004, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0004, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0004, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0004, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0004, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0004, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0004, 0x0036}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0005, 0x000a}, - cmdLutElement{0x00, 0x01, 0, 0x03, 0x0005, 0x000c}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0005, 0x000e}, - cmdLutElement{0x00, 0x02, 0, 0x03, 0x0005, 0x0012}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0005, 0x0016}, - cmdLutElement{0x00, 0x03, 0, 0x03, 0x0005, 0x001e}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0005, 0x0026}, - cmdLutElement{0x00, 0x04, 0, 0x03, 0x0005, 0x0036}, - cmdLutElement{0x01, 0x01, 0, 0x03, 0x0006, 0x000a}, - cmdLutElement{0x01, 0x01, 0, 0x03, 0x0006, 0x000c}, - cmdLutElement{0x01, 0x02, 0, 0x03, 0x0006, 0x000e}, - cmdLutElement{0x01, 0x02, 0, 0x03, 0x0006, 0x0012}, - cmdLutElement{0x01, 0x03, 0, 0x03, 0x0006, 0x0016}, - cmdLutElement{0x01, 0x03, 0, 0x03, 0x0006, 0x001e}, - cmdLutElement{0x01, 0x04, 0, 0x03, 0x0006, 0x0026}, - cmdLutElement{0x01, 0x04, 0, 0x03, 0x0006, 0x0036}, - cmdLutElement{0x01, 0x01, 0, 0x03, 0x0008, 0x000a}, - cmdLutElement{0x01, 0x01, 0, 0x03, 0x0008, 0x000c}, - cmdLutElement{0x01, 0x02, 0, 0x03, 0x0008, 0x000e}, - cmdLutElement{0x01, 0x02, 0, 0x03, 0x0008, 0x0012}, - cmdLutElement{0x01, 0x03, 0, 0x03, 0x0008, 0x0016}, - cmdLutElement{0x01, 0x03, 0, 0x03, 0x0008, 0x001e}, - cmdLutElement{0x01, 0x04, 0, 0x03, 0x0008, 0x0026}, - cmdLutElement{0x01, 0x04, 0, 0x03, 0x0008, 0x0036}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0000, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0000, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0000, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0000, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0000, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0000, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0000, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0000, 0x0009}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0001, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0001, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0001, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0001, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0001, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0001, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0001, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0001, 0x0009}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0002, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0002, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0002, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0002, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0002, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0002, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0002, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0002, 0x0009}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0003, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0003, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0003, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0003, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0003, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0003, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0003, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0003, 0x0009}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0004, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0004, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0004, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0004, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0004, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0004, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0004, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0004, 0x0009}, - cmdLutElement{0x00, 0x00, -1, 0x00, 0x0005, 0x0002}, - cmdLutElement{0x00, 0x00, -1, 0x01, 0x0005, 0x0003}, - cmdLutElement{0x00, 0x00, -1, 0x02, 0x0005, 0x0004}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0005, 0x0005}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0005, 0x0006}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0005, 0x0007}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0005, 0x0008}, - cmdLutElement{0x00, 0x00, -1, 0x03, 0x0005, 0x0009}, - cmdLutElement{0x01, 0x00, -1, 0x00, 0x0006, 0x0002}, - cmdLutElement{0x01, 0x00, -1, 0x01, 0x0006, 0x0003}, - cmdLutElement{0x01, 0x00, -1, 0x02, 0x0006, 0x0004}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0006, 0x0005}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0006, 0x0006}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0006, 0x0007}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0006, 0x0008}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0006, 0x0009}, - cmdLutElement{0x01, 0x00, -1, 0x00, 0x0008, 0x0002}, - cmdLutElement{0x01, 0x00, -1, 0x01, 0x0008, 0x0003}, - cmdLutElement{0x01, 0x00, -1, 0x02, 0x0008, 0x0004}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0008, 0x0005}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0008, 0x0006}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0008, 0x0007}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0008, 0x0008}, - cmdLutElement{0x01, 0x00, -1, 0x03, 0x0008, 0x0009}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0000, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0000, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0000, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0000, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0000, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0000, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0000, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0000, 0x0036}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0001, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0001, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0001, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0001, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0001, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0001, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0001, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0001, 0x0036}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0002, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0002, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0002, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0002, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0002, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0002, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0002, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0002, 0x0036}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0003, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0003, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0003, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0003, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0003, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0003, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0003, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0003, 0x0036}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0004, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0004, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0004, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0004, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0004, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0004, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0004, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0004, 0x0036}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0005, 0x000a}, - cmdLutElement{0x00, 0x01, -1, 0x03, 0x0005, 0x000c}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0005, 0x000e}, - cmdLutElement{0x00, 0x02, -1, 0x03, 0x0005, 0x0012}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0005, 0x0016}, - cmdLutElement{0x00, 0x03, -1, 0x03, 0x0005, 0x001e}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0005, 0x0026}, - cmdLutElement{0x00, 0x04, -1, 0x03, 0x0005, 0x0036}, - cmdLutElement{0x01, 0x01, -1, 0x03, 0x0006, 0x000a}, - cmdLutElement{0x01, 0x01, -1, 0x03, 0x0006, 0x000c}, - cmdLutElement{0x01, 0x02, -1, 0x03, 0x0006, 0x000e}, - cmdLutElement{0x01, 0x02, -1, 0x03, 0x0006, 0x0012}, - cmdLutElement{0x01, 0x03, -1, 0x03, 0x0006, 0x0016}, - cmdLutElement{0x01, 0x03, -1, 0x03, 0x0006, 0x001e}, - cmdLutElement{0x01, 0x04, -1, 0x03, 0x0006, 0x0026}, - cmdLutElement{0x01, 0x04, -1, 0x03, 0x0006, 0x0036}, - cmdLutElement{0x01, 0x01, -1, 0x03, 0x0008, 0x000a}, - cmdLutElement{0x01, 0x01, -1, 0x03, 0x0008, 0x000c}, - cmdLutElement{0x01, 0x02, -1, 0x03, 0x0008, 0x000e}, - cmdLutElement{0x01, 0x02, -1, 0x03, 0x0008, 0x0012}, - cmdLutElement{0x01, 0x03, -1, 0x03, 0x0008, 0x0016}, - cmdLutElement{0x01, 0x03, -1, 0x03, 0x0008, 0x001e}, - cmdLutElement{0x01, 0x04, -1, 0x03, 0x0008, 0x0026}, - cmdLutElement{0x01, 0x04, -1, 0x03, 0x0008, 0x0036}, - cmdLutElement{0x02, 0x00, -1, 0x00, 0x000a, 0x0002}, - cmdLutElement{0x02, 0x00, -1, 0x01, 0x000a, 0x0003}, - cmdLutElement{0x02, 0x00, -1, 0x02, 0x000a, 0x0004}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000a, 0x0005}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000a, 0x0006}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000a, 0x0007}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000a, 0x0008}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000a, 0x0009}, - cmdLutElement{0x02, 0x00, -1, 0x00, 0x000e, 0x0002}, - cmdLutElement{0x02, 0x00, -1, 0x01, 0x000e, 0x0003}, - cmdLutElement{0x02, 0x00, -1, 0x02, 0x000e, 0x0004}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000e, 0x0005}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000e, 0x0006}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000e, 0x0007}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000e, 0x0008}, - cmdLutElement{0x02, 0x00, -1, 0x03, 0x000e, 0x0009}, - cmdLutElement{0x03, 0x00, -1, 0x00, 0x0012, 0x0002}, - cmdLutElement{0x03, 0x00, -1, 0x01, 0x0012, 0x0003}, - cmdLutElement{0x03, 0x00, -1, 0x02, 0x0012, 0x0004}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x0012, 0x0005}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x0012, 0x0006}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x0012, 0x0007}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x0012, 0x0008}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x0012, 0x0009}, - cmdLutElement{0x03, 0x00, -1, 0x00, 0x001a, 0x0002}, - cmdLutElement{0x03, 0x00, -1, 0x01, 0x001a, 0x0003}, - cmdLutElement{0x03, 0x00, -1, 0x02, 0x001a, 0x0004}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x001a, 0x0005}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x001a, 0x0006}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x001a, 0x0007}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x001a, 0x0008}, - cmdLutElement{0x03, 0x00, -1, 0x03, 0x001a, 0x0009}, - cmdLutElement{0x04, 0x00, -1, 0x00, 0x0022, 0x0002}, - cmdLutElement{0x04, 0x00, -1, 0x01, 0x0022, 0x0003}, - cmdLutElement{0x04, 0x00, -1, 0x02, 0x0022, 0x0004}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0022, 0x0005}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0022, 0x0006}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0022, 0x0007}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0022, 0x0008}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0022, 0x0009}, - cmdLutElement{0x04, 0x00, -1, 0x00, 0x0032, 0x0002}, - cmdLutElement{0x04, 0x00, -1, 0x01, 0x0032, 0x0003}, - cmdLutElement{0x04, 0x00, -1, 0x02, 0x0032, 0x0004}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0032, 0x0005}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0032, 0x0006}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0032, 0x0007}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0032, 0x0008}, - cmdLutElement{0x04, 0x00, -1, 0x03, 0x0032, 0x0009}, - cmdLutElement{0x05, 0x00, -1, 0x00, 0x0042, 0x0002}, - cmdLutElement{0x05, 0x00, -1, 0x01, 0x0042, 0x0003}, - cmdLutElement{0x05, 0x00, -1, 0x02, 0x0042, 0x0004}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0042, 0x0005}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0042, 0x0006}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0042, 0x0007}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0042, 0x0008}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0042, 0x0009}, - cmdLutElement{0x05, 0x00, -1, 0x00, 0x0062, 0x0002}, - cmdLutElement{0x05, 0x00, -1, 0x01, 0x0062, 0x0003}, - cmdLutElement{0x05, 0x00, -1, 0x02, 0x0062, 0x0004}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0062, 0x0005}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0062, 0x0006}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0062, 0x0007}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0062, 0x0008}, - cmdLutElement{0x05, 0x00, -1, 0x03, 0x0062, 0x0009}, - cmdLutElement{0x02, 0x01, -1, 0x03, 0x000a, 0x000a}, - cmdLutElement{0x02, 0x01, -1, 0x03, 0x000a, 0x000c}, - cmdLutElement{0x02, 0x02, -1, 0x03, 0x000a, 0x000e}, - cmdLutElement{0x02, 0x02, -1, 0x03, 0x000a, 0x0012}, - cmdLutElement{0x02, 0x03, -1, 0x03, 0x000a, 0x0016}, - cmdLutElement{0x02, 0x03, -1, 0x03, 0x000a, 0x001e}, - cmdLutElement{0x02, 0x04, -1, 0x03, 0x000a, 0x0026}, - cmdLutElement{0x02, 0x04, -1, 0x03, 0x000a, 0x0036}, - cmdLutElement{0x02, 0x01, -1, 0x03, 0x000e, 0x000a}, - cmdLutElement{0x02, 0x01, -1, 0x03, 0x000e, 0x000c}, - cmdLutElement{0x02, 0x02, -1, 0x03, 0x000e, 0x000e}, - cmdLutElement{0x02, 0x02, -1, 0x03, 0x000e, 0x0012}, - cmdLutElement{0x02, 0x03, -1, 0x03, 0x000e, 0x0016}, - cmdLutElement{0x02, 0x03, -1, 0x03, 0x000e, 0x001e}, - cmdLutElement{0x02, 0x04, -1, 0x03, 0x000e, 0x0026}, - cmdLutElement{0x02, 0x04, -1, 0x03, 0x000e, 0x0036}, - cmdLutElement{0x03, 0x01, -1, 0x03, 0x0012, 0x000a}, - cmdLutElement{0x03, 0x01, -1, 0x03, 0x0012, 0x000c}, - cmdLutElement{0x03, 0x02, -1, 0x03, 0x0012, 0x000e}, - cmdLutElement{0x03, 0x02, -1, 0x03, 0x0012, 0x0012}, - cmdLutElement{0x03, 0x03, -1, 0x03, 0x0012, 0x0016}, - cmdLutElement{0x03, 0x03, -1, 0x03, 0x0012, 0x001e}, - cmdLutElement{0x03, 0x04, -1, 0x03, 0x0012, 0x0026}, - cmdLutElement{0x03, 0x04, -1, 0x03, 0x0012, 0x0036}, - cmdLutElement{0x03, 0x01, -1, 0x03, 0x001a, 0x000a}, - cmdLutElement{0x03, 0x01, -1, 0x03, 0x001a, 0x000c}, - cmdLutElement{0x03, 0x02, -1, 0x03, 0x001a, 0x000e}, - cmdLutElement{0x03, 0x02, -1, 0x03, 0x001a, 0x0012}, - cmdLutElement{0x03, 0x03, -1, 0x03, 0x001a, 0x0016}, - cmdLutElement{0x03, 0x03, -1, 0x03, 0x001a, 0x001e}, - cmdLutElement{0x03, 0x04, -1, 0x03, 0x001a, 0x0026}, - cmdLutElement{0x03, 0x04, -1, 0x03, 0x001a, 0x0036}, - cmdLutElement{0x04, 0x01, -1, 0x03, 0x0022, 0x000a}, - cmdLutElement{0x04, 0x01, -1, 0x03, 0x0022, 0x000c}, - cmdLutElement{0x04, 0x02, -1, 0x03, 0x0022, 0x000e}, - cmdLutElement{0x04, 0x02, -1, 0x03, 0x0022, 0x0012}, - cmdLutElement{0x04, 0x03, -1, 0x03, 0x0022, 0x0016}, - cmdLutElement{0x04, 0x03, -1, 0x03, 0x0022, 0x001e}, - cmdLutElement{0x04, 0x04, -1, 0x03, 0x0022, 0x0026}, - cmdLutElement{0x04, 0x04, -1, 0x03, 0x0022, 0x0036}, - cmdLutElement{0x04, 0x01, -1, 0x03, 0x0032, 0x000a}, - cmdLutElement{0x04, 0x01, -1, 0x03, 0x0032, 0x000c}, - cmdLutElement{0x04, 0x02, -1, 0x03, 0x0032, 0x000e}, - cmdLutElement{0x04, 0x02, -1, 0x03, 0x0032, 0x0012}, - cmdLutElement{0x04, 0x03, -1, 0x03, 0x0032, 0x0016}, - cmdLutElement{0x04, 0x03, -1, 0x03, 0x0032, 0x001e}, - cmdLutElement{0x04, 0x04, -1, 0x03, 0x0032, 0x0026}, - cmdLutElement{0x04, 0x04, -1, 0x03, 0x0032, 0x0036}, - cmdLutElement{0x05, 0x01, -1, 0x03, 0x0042, 0x000a}, - cmdLutElement{0x05, 0x01, -1, 0x03, 0x0042, 0x000c}, - cmdLutElement{0x05, 0x02, -1, 0x03, 0x0042, 0x000e}, - cmdLutElement{0x05, 0x02, -1, 0x03, 0x0042, 0x0012}, - cmdLutElement{0x05, 0x03, -1, 0x03, 0x0042, 0x0016}, - cmdLutElement{0x05, 0x03, -1, 0x03, 0x0042, 0x001e}, - cmdLutElement{0x05, 0x04, -1, 0x03, 0x0042, 0x0026}, - cmdLutElement{0x05, 0x04, -1, 0x03, 0x0042, 0x0036}, - cmdLutElement{0x05, 0x01, -1, 0x03, 0x0062, 0x000a}, - cmdLutElement{0x05, 0x01, -1, 0x03, 0x0062, 0x000c}, - cmdLutElement{0x05, 0x02, -1, 0x03, 0x0062, 0x000e}, - cmdLutElement{0x05, 0x02, -1, 0x03, 0x0062, 0x0012}, - cmdLutElement{0x05, 0x03, -1, 0x03, 0x0062, 0x0016}, - cmdLutElement{0x05, 0x03, -1, 0x03, 0x0062, 0x001e}, - cmdLutElement{0x05, 0x04, -1, 0x03, 0x0062, 0x0026}, - cmdLutElement{0x05, 0x04, -1, 0x03, 0x0062, 0x0036}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0000, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0000, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0000, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0000, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0000, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0000, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0000, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0000, 0x0846}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0001, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0001, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0001, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0001, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0001, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0001, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0001, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0001, 0x0846}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0002, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0002, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0002, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0002, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0002, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0002, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0002, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0002, 0x0846}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0003, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0003, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0003, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0003, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0003, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0003, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0003, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0003, 0x0846}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0004, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0004, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0004, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0004, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0004, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0004, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0004, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0004, 0x0846}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0005, 0x0046}, - cmdLutElement{0x00, 0x05, -1, 0x03, 0x0005, 0x0066}, - cmdLutElement{0x00, 0x06, -1, 0x03, 0x0005, 0x0086}, - cmdLutElement{0x00, 0x07, -1, 0x03, 0x0005, 0x00c6}, - cmdLutElement{0x00, 0x08, -1, 0x03, 0x0005, 0x0146}, - cmdLutElement{0x00, 0x09, -1, 0x03, 0x0005, 0x0246}, - cmdLutElement{0x00, 0x0a, -1, 0x03, 0x0005, 0x0446}, - cmdLutElement{0x00, 0x18, -1, 0x03, 0x0005, 0x0846}, - cmdLutElement{0x01, 0x05, -1, 0x03, 0x0006, 0x0046}, - cmdLutElement{0x01, 0x05, -1, 0x03, 0x0006, 0x0066}, - cmdLutElement{0x01, 0x06, -1, 0x03, 0x0006, 0x0086}, - cmdLutElement{0x01, 0x07, -1, 0x03, 0x0006, 0x00c6}, - cmdLutElement{0x01, 0x08, -1, 0x03, 0x0006, 0x0146}, - cmdLutElement{0x01, 0x09, -1, 0x03, 0x0006, 0x0246}, - cmdLutElement{0x01, 0x0a, -1, 0x03, 0x0006, 0x0446}, - cmdLutElement{0x01, 0x18, -1, 0x03, 0x0006, 0x0846}, - cmdLutElement{0x01, 0x05, -1, 0x03, 0x0008, 0x0046}, - cmdLutElement{0x01, 0x05, -1, 0x03, 0x0008, 0x0066}, - cmdLutElement{0x01, 0x06, -1, 0x03, 0x0008, 0x0086}, - cmdLutElement{0x01, 0x07, -1, 0x03, 0x0008, 0x00c6}, - cmdLutElement{0x01, 0x08, -1, 0x03, 0x0008, 0x0146}, - cmdLutElement{0x01, 0x09, -1, 0x03, 0x0008, 0x0246}, - cmdLutElement{0x01, 0x0a, -1, 0x03, 0x0008, 0x0446}, - cmdLutElement{0x01, 0x18, -1, 0x03, 0x0008, 0x0846}, - cmdLutElement{0x06, 0x00, -1, 0x00, 0x0082, 0x0002}, - cmdLutElement{0x06, 0x00, -1, 0x01, 0x0082, 0x0003}, - cmdLutElement{0x06, 0x00, -1, 0x02, 0x0082, 0x0004}, - cmdLutElement{0x06, 0x00, -1, 0x03, 0x0082, 0x0005}, - cmdLutElement{0x06, 0x00, -1, 0x03, 0x0082, 0x0006}, - cmdLutElement{0x06, 0x00, -1, 0x03, 0x0082, 0x0007}, - cmdLutElement{0x06, 0x00, -1, 0x03, 0x0082, 0x0008}, - cmdLutElement{0x06, 0x00, -1, 0x03, 0x0082, 0x0009}, - cmdLutElement{0x07, 0x00, -1, 0x00, 0x00c2, 0x0002}, - cmdLutElement{0x07, 0x00, -1, 0x01, 0x00c2, 0x0003}, - cmdLutElement{0x07, 0x00, -1, 0x02, 0x00c2, 0x0004}, - cmdLutElement{0x07, 0x00, -1, 0x03, 0x00c2, 0x0005}, - cmdLutElement{0x07, 0x00, -1, 0x03, 0x00c2, 0x0006}, - cmdLutElement{0x07, 0x00, -1, 0x03, 0x00c2, 0x0007}, - cmdLutElement{0x07, 0x00, -1, 0x03, 0x00c2, 0x0008}, - cmdLutElement{0x07, 0x00, -1, 0x03, 0x00c2, 0x0009}, - cmdLutElement{0x08, 0x00, -1, 0x00, 0x0142, 0x0002}, - cmdLutElement{0x08, 0x00, -1, 0x01, 0x0142, 0x0003}, - cmdLutElement{0x08, 0x00, -1, 0x02, 0x0142, 0x0004}, - cmdLutElement{0x08, 0x00, -1, 0x03, 0x0142, 0x0005}, - cmdLutElement{0x08, 0x00, -1, 0x03, 0x0142, 0x0006}, - cmdLutElement{0x08, 0x00, -1, 0x03, 0x0142, 0x0007}, - cmdLutElement{0x08, 0x00, -1, 0x03, 0x0142, 0x0008}, - cmdLutElement{0x08, 0x00, -1, 0x03, 0x0142, 0x0009}, - cmdLutElement{0x09, 0x00, -1, 0x00, 0x0242, 0x0002}, - cmdLutElement{0x09, 0x00, -1, 0x01, 0x0242, 0x0003}, - cmdLutElement{0x09, 0x00, -1, 0x02, 0x0242, 0x0004}, - cmdLutElement{0x09, 0x00, -1, 0x03, 0x0242, 0x0005}, - cmdLutElement{0x09, 0x00, -1, 0x03, 0x0242, 0x0006}, - cmdLutElement{0x09, 0x00, -1, 0x03, 0x0242, 0x0007}, - cmdLutElement{0x09, 0x00, -1, 0x03, 0x0242, 0x0008}, - cmdLutElement{0x09, 0x00, -1, 0x03, 0x0242, 0x0009}, - cmdLutElement{0x0a, 0x00, -1, 0x00, 0x0442, 0x0002}, - cmdLutElement{0x0a, 0x00, -1, 0x01, 0x0442, 0x0003}, - cmdLutElement{0x0a, 0x00, -1, 0x02, 0x0442, 0x0004}, - cmdLutElement{0x0a, 0x00, -1, 0x03, 0x0442, 0x0005}, - cmdLutElement{0x0a, 0x00, -1, 0x03, 0x0442, 0x0006}, - cmdLutElement{0x0a, 0x00, -1, 0x03, 0x0442, 0x0007}, - cmdLutElement{0x0a, 0x00, -1, 0x03, 0x0442, 0x0008}, - cmdLutElement{0x0a, 0x00, -1, 0x03, 0x0442, 0x0009}, - cmdLutElement{0x0c, 0x00, -1, 0x00, 0x0842, 0x0002}, - cmdLutElement{0x0c, 0x00, -1, 0x01, 0x0842, 0x0003}, - cmdLutElement{0x0c, 0x00, -1, 0x02, 0x0842, 0x0004}, - cmdLutElement{0x0c, 0x00, -1, 0x03, 0x0842, 0x0005}, - cmdLutElement{0x0c, 0x00, -1, 0x03, 0x0842, 0x0006}, - cmdLutElement{0x0c, 0x00, -1, 0x03, 0x0842, 0x0007}, - cmdLutElement{0x0c, 0x00, -1, 0x03, 0x0842, 0x0008}, - cmdLutElement{0x0c, 0x00, -1, 0x03, 0x0842, 0x0009}, - cmdLutElement{0x0e, 0x00, -1, 0x00, 0x1842, 0x0002}, - cmdLutElement{0x0e, 0x00, -1, 0x01, 0x1842, 0x0003}, - cmdLutElement{0x0e, 0x00, -1, 0x02, 0x1842, 0x0004}, - cmdLutElement{0x0e, 0x00, -1, 0x03, 0x1842, 0x0005}, - cmdLutElement{0x0e, 0x00, -1, 0x03, 0x1842, 0x0006}, - cmdLutElement{0x0e, 0x00, -1, 0x03, 0x1842, 0x0007}, - cmdLutElement{0x0e, 0x00, -1, 0x03, 0x1842, 0x0008}, - cmdLutElement{0x0e, 0x00, -1, 0x03, 0x1842, 0x0009}, - cmdLutElement{0x18, 0x00, -1, 0x00, 0x5842, 0x0002}, - cmdLutElement{0x18, 0x00, -1, 0x01, 0x5842, 0x0003}, - cmdLutElement{0x18, 0x00, -1, 0x02, 0x5842, 0x0004}, - cmdLutElement{0x18, 0x00, -1, 0x03, 0x5842, 0x0005}, - cmdLutElement{0x18, 0x00, -1, 0x03, 0x5842, 0x0006}, - cmdLutElement{0x18, 0x00, -1, 0x03, 0x5842, 0x0007}, - cmdLutElement{0x18, 0x00, -1, 0x03, 0x5842, 0x0008}, - cmdLutElement{0x18, 0x00, -1, 0x03, 0x5842, 0x0009}, - cmdLutElement{0x02, 0x05, -1, 0x03, 0x000a, 0x0046}, - cmdLutElement{0x02, 0x05, -1, 0x03, 0x000a, 0x0066}, - cmdLutElement{0x02, 0x06, -1, 0x03, 0x000a, 0x0086}, - cmdLutElement{0x02, 0x07, -1, 0x03, 0x000a, 0x00c6}, - cmdLutElement{0x02, 0x08, -1, 0x03, 0x000a, 0x0146}, - cmdLutElement{0x02, 0x09, -1, 0x03, 0x000a, 0x0246}, - cmdLutElement{0x02, 0x0a, -1, 0x03, 0x000a, 0x0446}, - cmdLutElement{0x02, 0x18, -1, 0x03, 0x000a, 0x0846}, - cmdLutElement{0x02, 0x05, -1, 0x03, 0x000e, 0x0046}, - cmdLutElement{0x02, 0x05, -1, 0x03, 0x000e, 0x0066}, - cmdLutElement{0x02, 0x06, -1, 0x03, 0x000e, 0x0086}, - cmdLutElement{0x02, 0x07, -1, 0x03, 0x000e, 0x00c6}, - cmdLutElement{0x02, 0x08, -1, 0x03, 0x000e, 0x0146}, - cmdLutElement{0x02, 0x09, -1, 0x03, 0x000e, 0x0246}, - cmdLutElement{0x02, 0x0a, -1, 0x03, 0x000e, 0x0446}, - cmdLutElement{0x02, 0x18, -1, 0x03, 0x000e, 0x0846}, - cmdLutElement{0x03, 0x05, -1, 0x03, 0x0012, 0x0046}, - cmdLutElement{0x03, 0x05, -1, 0x03, 0x0012, 0x0066}, - cmdLutElement{0x03, 0x06, -1, 0x03, 0x0012, 0x0086}, - cmdLutElement{0x03, 0x07, -1, 0x03, 0x0012, 0x00c6}, - cmdLutElement{0x03, 0x08, -1, 0x03, 0x0012, 0x0146}, - cmdLutElement{0x03, 0x09, -1, 0x03, 0x0012, 0x0246}, - cmdLutElement{0x03, 0x0a, -1, 0x03, 0x0012, 0x0446}, - cmdLutElement{0x03, 0x18, -1, 0x03, 0x0012, 0x0846}, - cmdLutElement{0x03, 0x05, -1, 0x03, 0x001a, 0x0046}, - cmdLutElement{0x03, 0x05, -1, 0x03, 0x001a, 0x0066}, - cmdLutElement{0x03, 0x06, -1, 0x03, 0x001a, 0x0086}, - cmdLutElement{0x03, 0x07, -1, 0x03, 0x001a, 0x00c6}, - cmdLutElement{0x03, 0x08, -1, 0x03, 0x001a, 0x0146}, - cmdLutElement{0x03, 0x09, -1, 0x03, 0x001a, 0x0246}, - cmdLutElement{0x03, 0x0a, -1, 0x03, 0x001a, 0x0446}, - cmdLutElement{0x03, 0x18, -1, 0x03, 0x001a, 0x0846}, - cmdLutElement{0x04, 0x05, -1, 0x03, 0x0022, 0x0046}, - cmdLutElement{0x04, 0x05, -1, 0x03, 0x0022, 0x0066}, - cmdLutElement{0x04, 0x06, -1, 0x03, 0x0022, 0x0086}, - cmdLutElement{0x04, 0x07, -1, 0x03, 0x0022, 0x00c6}, - cmdLutElement{0x04, 0x08, -1, 0x03, 0x0022, 0x0146}, - cmdLutElement{0x04, 0x09, -1, 0x03, 0x0022, 0x0246}, - cmdLutElement{0x04, 0x0a, -1, 0x03, 0x0022, 0x0446}, - cmdLutElement{0x04, 0x18, -1, 0x03, 0x0022, 0x0846}, - cmdLutElement{0x04, 0x05, -1, 0x03, 0x0032, 0x0046}, - cmdLutElement{0x04, 0x05, -1, 0x03, 0x0032, 0x0066}, - cmdLutElement{0x04, 0x06, -1, 0x03, 0x0032, 0x0086}, - cmdLutElement{0x04, 0x07, -1, 0x03, 0x0032, 0x00c6}, - cmdLutElement{0x04, 0x08, -1, 0x03, 0x0032, 0x0146}, - cmdLutElement{0x04, 0x09, -1, 0x03, 0x0032, 0x0246}, - cmdLutElement{0x04, 0x0a, -1, 0x03, 0x0032, 0x0446}, - cmdLutElement{0x04, 0x18, -1, 0x03, 0x0032, 0x0846}, - cmdLutElement{0x05, 0x05, -1, 0x03, 0x0042, 0x0046}, - cmdLutElement{0x05, 0x05, -1, 0x03, 0x0042, 0x0066}, - cmdLutElement{0x05, 0x06, -1, 0x03, 0x0042, 0x0086}, - cmdLutElement{0x05, 0x07, -1, 0x03, 0x0042, 0x00c6}, - cmdLutElement{0x05, 0x08, -1, 0x03, 0x0042, 0x0146}, - cmdLutElement{0x05, 0x09, -1, 0x03, 0x0042, 0x0246}, - cmdLutElement{0x05, 0x0a, -1, 0x03, 0x0042, 0x0446}, - cmdLutElement{0x05, 0x18, -1, 0x03, 0x0042, 0x0846}, - cmdLutElement{0x05, 0x05, -1, 0x03, 0x0062, 0x0046}, - cmdLutElement{0x05, 0x05, -1, 0x03, 0x0062, 0x0066}, - cmdLutElement{0x05, 0x06, -1, 0x03, 0x0062, 0x0086}, - cmdLutElement{0x05, 0x07, -1, 0x03, 0x0062, 0x00c6}, - cmdLutElement{0x05, 0x08, -1, 0x03, 0x0062, 0x0146}, - cmdLutElement{0x05, 0x09, -1, 0x03, 0x0062, 0x0246}, - cmdLutElement{0x05, 0x0a, -1, 0x03, 0x0062, 0x0446}, - cmdLutElement{0x05, 0x18, -1, 0x03, 0x0062, 0x0846}, - cmdLutElement{0x06, 0x01, -1, 0x03, 0x0082, 0x000a}, - cmdLutElement{0x06, 0x01, -1, 0x03, 0x0082, 0x000c}, - cmdLutElement{0x06, 0x02, -1, 0x03, 0x0082, 0x000e}, - cmdLutElement{0x06, 0x02, -1, 0x03, 0x0082, 0x0012}, - cmdLutElement{0x06, 0x03, -1, 0x03, 0x0082, 0x0016}, - cmdLutElement{0x06, 0x03, -1, 0x03, 0x0082, 0x001e}, - cmdLutElement{0x06, 0x04, -1, 0x03, 0x0082, 0x0026}, - cmdLutElement{0x06, 0x04, -1, 0x03, 0x0082, 0x0036}, - cmdLutElement{0x07, 0x01, -1, 0x03, 0x00c2, 0x000a}, - cmdLutElement{0x07, 0x01, -1, 0x03, 0x00c2, 0x000c}, - cmdLutElement{0x07, 0x02, -1, 0x03, 0x00c2, 0x000e}, - cmdLutElement{0x07, 0x02, -1, 0x03, 0x00c2, 0x0012}, - cmdLutElement{0x07, 0x03, -1, 0x03, 0x00c2, 0x0016}, - cmdLutElement{0x07, 0x03, -1, 0x03, 0x00c2, 0x001e}, - cmdLutElement{0x07, 0x04, -1, 0x03, 0x00c2, 0x0026}, - cmdLutElement{0x07, 0x04, -1, 0x03, 0x00c2, 0x0036}, - cmdLutElement{0x08, 0x01, -1, 0x03, 0x0142, 0x000a}, - cmdLutElement{0x08, 0x01, -1, 0x03, 0x0142, 0x000c}, - cmdLutElement{0x08, 0x02, -1, 0x03, 0x0142, 0x000e}, - cmdLutElement{0x08, 0x02, -1, 0x03, 0x0142, 0x0012}, - cmdLutElement{0x08, 0x03, -1, 0x03, 0x0142, 0x0016}, - cmdLutElement{0x08, 0x03, -1, 0x03, 0x0142, 0x001e}, - cmdLutElement{0x08, 0x04, -1, 0x03, 0x0142, 0x0026}, - cmdLutElement{0x08, 0x04, -1, 0x03, 0x0142, 0x0036}, - cmdLutElement{0x09, 0x01, -1, 0x03, 0x0242, 0x000a}, - cmdLutElement{0x09, 0x01, -1, 0x03, 0x0242, 0x000c}, - cmdLutElement{0x09, 0x02, -1, 0x03, 0x0242, 0x000e}, - cmdLutElement{0x09, 0x02, -1, 0x03, 0x0242, 0x0012}, - cmdLutElement{0x09, 0x03, -1, 0x03, 0x0242, 0x0016}, - cmdLutElement{0x09, 0x03, -1, 0x03, 0x0242, 0x001e}, - cmdLutElement{0x09, 0x04, -1, 0x03, 0x0242, 0x0026}, - cmdLutElement{0x09, 0x04, -1, 0x03, 0x0242, 0x0036}, - cmdLutElement{0x0a, 0x01, -1, 0x03, 0x0442, 0x000a}, - cmdLutElement{0x0a, 0x01, -1, 0x03, 0x0442, 0x000c}, - cmdLutElement{0x0a, 0x02, -1, 0x03, 0x0442, 0x000e}, - cmdLutElement{0x0a, 0x02, -1, 0x03, 0x0442, 0x0012}, - cmdLutElement{0x0a, 0x03, -1, 0x03, 0x0442, 0x0016}, - cmdLutElement{0x0a, 0x03, -1, 0x03, 0x0442, 0x001e}, - cmdLutElement{0x0a, 0x04, -1, 0x03, 0x0442, 0x0026}, - cmdLutElement{0x0a, 0x04, -1, 0x03, 0x0442, 0x0036}, - cmdLutElement{0x0c, 0x01, -1, 0x03, 0x0842, 0x000a}, - cmdLutElement{0x0c, 0x01, -1, 0x03, 0x0842, 0x000c}, - cmdLutElement{0x0c, 0x02, -1, 0x03, 0x0842, 0x000e}, - cmdLutElement{0x0c, 0x02, -1, 0x03, 0x0842, 0x0012}, - cmdLutElement{0x0c, 0x03, -1, 0x03, 0x0842, 0x0016}, - cmdLutElement{0x0c, 0x03, -1, 0x03, 0x0842, 0x001e}, - cmdLutElement{0x0c, 0x04, -1, 0x03, 0x0842, 0x0026}, - cmdLutElement{0x0c, 0x04, -1, 0x03, 0x0842, 0x0036}, - cmdLutElement{0x0e, 0x01, -1, 0x03, 0x1842, 0x000a}, - cmdLutElement{0x0e, 0x01, -1, 0x03, 0x1842, 0x000c}, - cmdLutElement{0x0e, 0x02, -1, 0x03, 0x1842, 0x000e}, - cmdLutElement{0x0e, 0x02, -1, 0x03, 0x1842, 0x0012}, - cmdLutElement{0x0e, 0x03, -1, 0x03, 0x1842, 0x0016}, - cmdLutElement{0x0e, 0x03, -1, 0x03, 0x1842, 0x001e}, - cmdLutElement{0x0e, 0x04, -1, 0x03, 0x1842, 0x0026}, - cmdLutElement{0x0e, 0x04, -1, 0x03, 0x1842, 0x0036}, - cmdLutElement{0x18, 0x01, -1, 0x03, 0x5842, 0x000a}, - cmdLutElement{0x18, 0x01, -1, 0x03, 0x5842, 0x000c}, - cmdLutElement{0x18, 0x02, -1, 0x03, 0x5842, 0x000e}, - cmdLutElement{0x18, 0x02, -1, 0x03, 0x5842, 0x0012}, - cmdLutElement{0x18, 0x03, -1, 0x03, 0x5842, 0x0016}, - cmdLutElement{0x18, 0x03, -1, 0x03, 0x5842, 0x001e}, - cmdLutElement{0x18, 0x04, -1, 0x03, 0x5842, 0x0026}, - cmdLutElement{0x18, 0x04, -1, 0x03, 0x5842, 0x0036}, - cmdLutElement{0x06, 0x05, -1, 0x03, 0x0082, 0x0046}, - cmdLutElement{0x06, 0x05, -1, 0x03, 0x0082, 0x0066}, - cmdLutElement{0x06, 0x06, -1, 0x03, 0x0082, 0x0086}, - cmdLutElement{0x06, 0x07, -1, 0x03, 0x0082, 0x00c6}, - cmdLutElement{0x06, 0x08, -1, 0x03, 0x0082, 0x0146}, - cmdLutElement{0x06, 0x09, -1, 0x03, 0x0082, 0x0246}, - cmdLutElement{0x06, 0x0a, -1, 0x03, 0x0082, 0x0446}, - cmdLutElement{0x06, 0x18, -1, 0x03, 0x0082, 0x0846}, - cmdLutElement{0x07, 0x05, -1, 0x03, 0x00c2, 0x0046}, - cmdLutElement{0x07, 0x05, -1, 0x03, 0x00c2, 0x0066}, - cmdLutElement{0x07, 0x06, -1, 0x03, 0x00c2, 0x0086}, - cmdLutElement{0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6}, - cmdLutElement{0x07, 0x08, -1, 0x03, 0x00c2, 0x0146}, - cmdLutElement{0x07, 0x09, -1, 0x03, 0x00c2, 0x0246}, - cmdLutElement{0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446}, - cmdLutElement{0x07, 0x18, -1, 0x03, 0x00c2, 0x0846}, - cmdLutElement{0x08, 0x05, -1, 0x03, 0x0142, 0x0046}, - cmdLutElement{0x08, 0x05, -1, 0x03, 0x0142, 0x0066}, - cmdLutElement{0x08, 0x06, -1, 0x03, 0x0142, 0x0086}, - cmdLutElement{0x08, 0x07, -1, 0x03, 0x0142, 0x00c6}, - cmdLutElement{0x08, 0x08, -1, 0x03, 0x0142, 0x0146}, - cmdLutElement{0x08, 0x09, -1, 0x03, 0x0142, 0x0246}, - cmdLutElement{0x08, 0x0a, -1, 0x03, 0x0142, 0x0446}, - cmdLutElement{0x08, 0x18, -1, 0x03, 0x0142, 0x0846}, - cmdLutElement{0x09, 0x05, -1, 0x03, 0x0242, 0x0046}, - cmdLutElement{0x09, 0x05, -1, 0x03, 0x0242, 0x0066}, - cmdLutElement{0x09, 0x06, -1, 0x03, 0x0242, 0x0086}, - cmdLutElement{0x09, 0x07, -1, 0x03, 0x0242, 0x00c6}, - cmdLutElement{0x09, 0x08, -1, 0x03, 0x0242, 0x0146}, - cmdLutElement{0x09, 0x09, -1, 0x03, 0x0242, 0x0246}, - cmdLutElement{0x09, 0x0a, -1, 0x03, 0x0242, 0x0446}, - cmdLutElement{0x09, 0x18, -1, 0x03, 0x0242, 0x0846}, - cmdLutElement{0x0a, 0x05, -1, 0x03, 0x0442, 0x0046}, - cmdLutElement{0x0a, 0x05, -1, 0x03, 0x0442, 0x0066}, - cmdLutElement{0x0a, 0x06, -1, 0x03, 0x0442, 0x0086}, - cmdLutElement{0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6}, - cmdLutElement{0x0a, 0x08, -1, 0x03, 0x0442, 0x0146}, - cmdLutElement{0x0a, 0x09, -1, 0x03, 0x0442, 0x0246}, - cmdLutElement{0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446}, - cmdLutElement{0x0a, 0x18, -1, 0x03, 0x0442, 0x0846}, - cmdLutElement{0x0c, 0x05, -1, 0x03, 0x0842, 0x0046}, - cmdLutElement{0x0c, 0x05, -1, 0x03, 0x0842, 0x0066}, - cmdLutElement{0x0c, 0x06, -1, 0x03, 0x0842, 0x0086}, - cmdLutElement{0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6}, - cmdLutElement{0x0c, 0x08, -1, 0x03, 0x0842, 0x0146}, - cmdLutElement{0x0c, 0x09, -1, 0x03, 0x0842, 0x0246}, - cmdLutElement{0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446}, - cmdLutElement{0x0c, 0x18, -1, 0x03, 0x0842, 0x0846}, - cmdLutElement{0x0e, 0x05, -1, 0x03, 0x1842, 0x0046}, - cmdLutElement{0x0e, 0x05, -1, 0x03, 0x1842, 0x0066}, - cmdLutElement{0x0e, 0x06, -1, 0x03, 0x1842, 0x0086}, - cmdLutElement{0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6}, - cmdLutElement{0x0e, 0x08, -1, 0x03, 0x1842, 0x0146}, - cmdLutElement{0x0e, 0x09, -1, 0x03, 0x1842, 0x0246}, - cmdLutElement{0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446}, - cmdLutElement{0x0e, 0x18, -1, 0x03, 0x1842, 0x0846}, - cmdLutElement{0x18, 0x05, -1, 0x03, 0x5842, 0x0046}, - cmdLutElement{0x18, 0x05, -1, 0x03, 0x5842, 0x0066}, - cmdLutElement{0x18, 0x06, -1, 0x03, 0x5842, 0x0086}, - cmdLutElement{0x18, 0x07, -1, 0x03, 0x5842, 0x00c6}, - cmdLutElement{0x18, 0x08, -1, 0x03, 0x5842, 0x0146}, - cmdLutElement{0x18, 0x09, -1, 0x03, 0x5842, 0x0246}, - cmdLutElement{0x18, 0x0a, -1, 0x03, 0x5842, 0x0446}, - cmdLutElement{0x18, 0x18, -1, 0x03, 0x5842, 0x0846}, -} diff --git a/src/vendor/github.com/andybalholm/brotli/quality.go b/src/vendor/github.com/andybalholm/brotli/quality.go deleted file mode 100644 index 49709a38..00000000 --- a/src/vendor/github.com/andybalholm/brotli/quality.go +++ /dev/null @@ -1,196 +0,0 @@ -package brotli - -const fastOnePassCompressionQuality = 0 - -const fastTwoPassCompressionQuality = 1 - -const zopflificationQuality = 10 - -const hqZopflificationQuality = 11 - -const maxQualityForStaticEntropyCodes = 2 - -const minQualityForBlockSplit = 4 - -const minQualityForNonzeroDistanceParams = 4 - -const minQualityForOptimizeHistograms = 4 - -const minQualityForExtensiveReferenceSearch = 5 - -const minQualityForContextModeling = 5 - -const minQualityForHqContextModeling = 7 - -const minQualityForHqBlockSplitting = 10 - -/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting, - so we buffer at most this much literals and commands. */ -const maxNumDelayedSymbols = 0x2FFF - -/* Returns hash-table size for quality levels 0 and 1. */ -func maxHashTableSize(quality int) uint { - if quality == fastOnePassCompressionQuality { - return 1 << 15 - } else { - return 1 << 17 - } -} - -/* The maximum length for which the zopflification uses distinct distances. */ -const maxZopfliLenQuality10 = 150 - -const maxZopfliLenQuality11 = 325 - -/* Do not thoroughly search when a long copy is found. */ -const longCopyQuickStep = 16384 - -func maxZopfliLen(params *encoderParams) uint { - if params.quality <= 10 { - return maxZopfliLenQuality10 - } else { - return maxZopfliLenQuality11 - } -} - -/* Number of best candidates to evaluate to expand Zopfli chain. */ -func maxZopfliCandidates(params *encoderParams) uint { - if params.quality <= 10 { - return 1 - } else { - return 5 - } -} - -func sanitizeParams(params *encoderParams) { - params.quality = brotli_min_int(maxQuality, brotli_max_int(minQuality, params.quality)) - if params.quality <= maxQualityForStaticEntropyCodes { - params.large_window = false - } - - if params.lgwin < minWindowBits { - params.lgwin = minWindowBits - } else { - var max_lgwin int - if params.large_window { - max_lgwin = largeMaxWindowBits - } else { - max_lgwin = maxWindowBits - } - if params.lgwin > uint(max_lgwin) { - params.lgwin = uint(max_lgwin) - } - } -} - -/* Returns optimized lg_block value. */ -func computeLgBlock(params *encoderParams) int { - var lgblock int = params.lgblock - if params.quality == fastOnePassCompressionQuality || params.quality == fastTwoPassCompressionQuality { - lgblock = int(params.lgwin) - } else if params.quality < minQualityForBlockSplit { - lgblock = 14 - } else if lgblock == 0 { - lgblock = 16 - if params.quality >= 9 && params.lgwin > uint(lgblock) { - lgblock = brotli_min_int(18, int(params.lgwin)) - } - } else { - lgblock = brotli_min_int(maxInputBlockBits, brotli_max_int(minInputBlockBits, lgblock)) - } - - return lgblock -} - -/* Returns log2 of the size of main ring buffer area. - Allocate at least lgwin + 1 bits for the ring buffer so that the newly - added block fits there completely and we still get lgwin bits and at least - read_block_size_bits + 1 bits because the copy tail length needs to be - smaller than ring-buffer size. */ -func computeRbBits(params *encoderParams) int { - return 1 + brotli_max_int(int(params.lgwin), params.lgblock) -} - -func maxMetablockSize(params *encoderParams) uint { - var bits int = brotli_min_int(computeRbBits(params), maxInputBlockBits) - return uint(1) << uint(bits) -} - -/* When searching for backward references and have not seen matches for a long - time, we can skip some match lookups. Unsuccessful match lookups are very - expensive and this kind of a heuristic speeds up compression quite a lot. - At first 8 byte strides are taken and every second byte is put to hasher. - After 4x more literals stride by 16 bytes, every put 4-th byte to hasher. - Applied only to qualities 2 to 9. */ -func literalSpreeLengthForSparseSearch(params *encoderParams) uint { - if params.quality < 9 { - return 64 - } else { - return 512 - } -} - -func chooseHasher(params *encoderParams, hparams *hasherParams) { - if params.quality > 9 { - hparams.type_ = 10 - } else if params.quality == 4 && params.size_hint >= 1<<20 { - hparams.type_ = 54 - } else if params.quality < 5 { - hparams.type_ = params.quality - } else if params.lgwin <= 16 { - if params.quality < 7 { - hparams.type_ = 40 - } else if params.quality < 9 { - hparams.type_ = 41 - } else { - hparams.type_ = 42 - } - } else if params.size_hint >= 1<<20 && params.lgwin >= 19 { - hparams.type_ = 6 - hparams.block_bits = params.quality - 1 - hparams.bucket_bits = 15 - hparams.hash_len = 5 - if params.quality < 7 { - hparams.num_last_distances_to_check = 4 - } else if params.quality < 9 { - hparams.num_last_distances_to_check = 10 - } else { - hparams.num_last_distances_to_check = 16 - } - } else { - hparams.type_ = 5 - hparams.block_bits = params.quality - 1 - if params.quality < 7 { - hparams.bucket_bits = 14 - } else { - hparams.bucket_bits = 15 - } - if params.quality < 7 { - hparams.num_last_distances_to_check = 4 - } else if params.quality < 9 { - hparams.num_last_distances_to_check = 10 - } else { - hparams.num_last_distances_to_check = 16 - } - } - - if params.lgwin > 24 { - /* Different hashers for large window brotli: not for qualities <= 2, - these are too fast for large window. Not for qualities >= 10: their - hasher already works well with large window. So the changes are: - H3 --> H35: for quality 3. - H54 --> H55: for quality 4 with size hint > 1MB - H6 --> H65: for qualities 5, 6, 7, 8, 9. */ - if hparams.type_ == 3 { - hparams.type_ = 35 - } - - if hparams.type_ == 54 { - hparams.type_ = 55 - } - - if hparams.type_ == 6 { - hparams.type_ = 65 - } - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/reader.go b/src/vendor/github.com/andybalholm/brotli/reader.go deleted file mode 100644 index d652f4a1..00000000 --- a/src/vendor/github.com/andybalholm/brotli/reader.go +++ /dev/null @@ -1,126 +0,0 @@ -package brotli - -import ( - "errors" - "io" -) - -type decodeError int - -func (err decodeError) Error() string { - return "brotli: " + string(decoderErrorString(int(err))) -} - -var errExcessiveInput = errors.New("brotli: excessive input") -var errInvalidState = errors.New("brotli: invalid state") - -// readBufSize is a "good" buffer size that avoids excessive round-trips -// between C and Go but doesn't waste too much memory on buffering. -// It is arbitrarily chosen to be equal to the constant used in io.Copy. -const readBufSize = 32 * 1024 - -// NewReader creates a new Reader reading the given reader. -func NewReader(src io.Reader) *Reader { - r := new(Reader) - r.Reset(src) - return r -} - -// Reset discards the Reader's state and makes it equivalent to the result of -// its original state from NewReader, but reading from src instead. -// This permits reusing a Reader rather than allocating a new one. -// Error is always nil -func (r *Reader) Reset(src io.Reader) error { - if r.error_code < 0 { - // There was an unrecoverable error, leaving the Reader's state - // undefined. Clear out everything but the buffers. - *r = Reader{ - buf: r.buf, - block_type_trees: r.block_type_trees, - literal_hgroup: huffmanTreeGroup{ - htrees: r.literal_hgroup.htrees, - codes: r.literal_hgroup.codes, - }, - distance_hgroup: huffmanTreeGroup{ - htrees: r.distance_hgroup.htrees, - codes: r.distance_hgroup.codes, - }, - insert_copy_hgroup: huffmanTreeGroup{ - htrees: r.insert_copy_hgroup.htrees, - codes: r.insert_copy_hgroup.codes, - }, - } - } - - decoderStateInit(r) - r.src = src - if r.buf == nil { - r.buf = make([]byte, readBufSize) - } - return nil -} - -func (r *Reader) Read(p []byte) (n int, err error) { - if !decoderHasMoreOutput(r) && len(r.in) == 0 { - m, readErr := r.src.Read(r.buf) - if m == 0 { - if readErr == io.EOF && r.state != stateDone { - readErr = io.ErrUnexpectedEOF - } - // If readErr is `nil`, we just proxy underlying stream behavior. - return 0, readErr - } - r.in = r.buf[:m] - } - - if len(p) == 0 { - return 0, nil - } - - for { - var written uint - in_len := uint(len(r.in)) - out_len := uint(len(p)) - in_remaining := in_len - out_remaining := out_len - result := decoderDecompressStream(r, &in_remaining, &r.in, &out_remaining, &p) - written = out_len - out_remaining - n = int(written) - - switch result { - case decoderResultSuccess: - if len(r.in) > 0 { - return n, errExcessiveInput - } - return n, nil - case decoderResultError: - return n, decodeError(decoderGetErrorCode(r)) - case decoderResultNeedsMoreOutput: - if n == 0 { - return 0, io.ErrShortBuffer - } - return n, nil - case decoderNeedsMoreInput: - } - - if len(r.in) != 0 { - return 0, errInvalidState - } - - // Calling r.src.Read may block. Don't block if we have data to return. - if n > 0 { - return n, nil - } - - // Top off the buffer. - encN, err := r.src.Read(r.buf) - if encN == 0 { - // Not enough data to complete decoding. - if err == io.EOF { - return 0, io.ErrUnexpectedEOF - } - return 0, err - } - r.in = r.buf[:encN] - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/ringbuffer.go b/src/vendor/github.com/andybalholm/brotli/ringbuffer.go deleted file mode 100644 index 1c8f86fe..00000000 --- a/src/vendor/github.com/andybalholm/brotli/ringbuffer.go +++ /dev/null @@ -1,134 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* A ringBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of - data in a circular manner: writing a byte writes it to: - `position() % (1 << window_bits)'. - For convenience, the ringBuffer array contains another copy of the - first `1 << tail_bits' bytes: - buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits), - and another copy of the last two bytes: - buffer_[-1] == buffer_[(1 << window_bits) - 1] and - buffer_[-2] == buffer_[(1 << window_bits) - 2]. */ -type ringBuffer struct { - size_ uint32 - mask_ uint32 - tail_size_ uint32 - total_size_ uint32 - cur_size_ uint32 - pos_ uint32 - data_ []byte - buffer_ []byte -} - -func ringBufferInit(rb *ringBuffer) { - rb.pos_ = 0 -} - -func ringBufferSetup(params *encoderParams, rb *ringBuffer) { - var window_bits int = computeRbBits(params) - var tail_bits int = params.lgblock - *(*uint32)(&rb.size_) = 1 << uint(window_bits) - *(*uint32)(&rb.mask_) = (1 << uint(window_bits)) - 1 - *(*uint32)(&rb.tail_size_) = 1 << uint(tail_bits) - *(*uint32)(&rb.total_size_) = rb.size_ + rb.tail_size_ -} - -const kSlackForEightByteHashingEverywhere uint = 7 - -/* Allocates or re-allocates data_ to the given length + plus some slack - region before and after. Fills the slack regions with zeros. */ -func ringBufferInitBuffer(buflen uint32, rb *ringBuffer) { - var new_data []byte - var i uint - size := 2 + int(buflen) + int(kSlackForEightByteHashingEverywhere) - if cap(rb.data_) < size { - new_data = make([]byte, size) - } else { - new_data = rb.data_[:size] - } - if rb.data_ != nil { - copy(new_data, rb.data_[:2+rb.cur_size_+uint32(kSlackForEightByteHashingEverywhere)]) - } - - rb.data_ = new_data - rb.cur_size_ = buflen - rb.buffer_ = rb.data_[2:] - rb.data_[1] = 0 - rb.data_[0] = rb.data_[1] - for i = 0; i < kSlackForEightByteHashingEverywhere; i++ { - rb.buffer_[rb.cur_size_+uint32(i)] = 0 - } -} - -func ringBufferWriteTail(bytes []byte, n uint, rb *ringBuffer) { - var masked_pos uint = uint(rb.pos_ & rb.mask_) - if uint32(masked_pos) < rb.tail_size_ { - /* Just fill the tail buffer with the beginning data. */ - var p uint = uint(rb.size_ + uint32(masked_pos)) - copy(rb.buffer_[p:], bytes[:brotli_min_size_t(n, uint(rb.tail_size_-uint32(masked_pos)))]) - } -} - -/* Push bytes into the ring buffer. */ -func ringBufferWrite(bytes []byte, n uint, rb *ringBuffer) { - if rb.pos_ == 0 && uint32(n) < rb.tail_size_ { - /* Special case for the first write: to process the first block, we don't - need to allocate the whole ring-buffer and we don't need the tail - either. However, we do this memory usage optimization only if the - first write is less than the tail size, which is also the input block - size, otherwise it is likely that other blocks will follow and we - will need to reallocate to the full size anyway. */ - rb.pos_ = uint32(n) - - ringBufferInitBuffer(rb.pos_, rb) - copy(rb.buffer_, bytes[:n]) - return - } - - if rb.cur_size_ < rb.total_size_ { - /* Lazily allocate the full buffer. */ - ringBufferInitBuffer(rb.total_size_, rb) - - /* Initialize the last two bytes to zero, so that we don't have to worry - later when we copy the last two bytes to the first two positions. */ - rb.buffer_[rb.size_-2] = 0 - - rb.buffer_[rb.size_-1] = 0 - } - { - var masked_pos uint = uint(rb.pos_ & rb.mask_) - - /* The length of the writes is limited so that we do not need to worry - about a write */ - ringBufferWriteTail(bytes, n, rb) - - if uint32(masked_pos+n) <= rb.size_ { - /* A single write fits. */ - copy(rb.buffer_[masked_pos:], bytes[:n]) - } else { - /* Split into two writes. - Copy into the end of the buffer, including the tail buffer. */ - copy(rb.buffer_[masked_pos:], bytes[:brotli_min_size_t(n, uint(rb.total_size_-uint32(masked_pos)))]) - - /* Copy into the beginning of the buffer */ - copy(rb.buffer_, bytes[rb.size_-uint32(masked_pos):][:uint32(n)-(rb.size_-uint32(masked_pos))]) - } - } - { - var not_first_lap bool = rb.pos_&(1<<31) != 0 - var rb_pos_mask uint32 = (1 << 31) - 1 - rb.data_[0] = rb.buffer_[rb.size_-2] - rb.data_[1] = rb.buffer_[rb.size_-1] - rb.pos_ = (rb.pos_ & rb_pos_mask) + uint32(uint32(n)&rb_pos_mask) - if not_first_lap { - /* Wrap, but preserve not-a-first-lap feature. */ - rb.pos_ |= 1 << 31 - } - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/state.go b/src/vendor/github.com/andybalholm/brotli/state.go deleted file mode 100644 index da26da44..00000000 --- a/src/vendor/github.com/andybalholm/brotli/state.go +++ /dev/null @@ -1,313 +0,0 @@ -package brotli - -import "io" - -/* Copyright 2015 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Brotli state for partial streaming decoding. */ -const ( - stateUninited = iota - stateLargeWindowBits - stateInitialize - stateMetablockBegin - stateMetablockHeader - stateMetablockHeader2 - stateContextModes - stateCommandBegin - stateCommandInner - stateCommandPostDecodeLiterals - stateCommandPostWrapCopy - stateUncompressed - stateMetadata - stateCommandInnerWrite - stateMetablockDone - stateCommandPostWrite1 - stateCommandPostWrite2 - stateHuffmanCode0 - stateHuffmanCode1 - stateHuffmanCode2 - stateHuffmanCode3 - stateContextMap1 - stateContextMap2 - stateTreeGroup - stateDone -) - -const ( - stateMetablockHeaderNone = iota - stateMetablockHeaderEmpty - stateMetablockHeaderNibbles - stateMetablockHeaderSize - stateMetablockHeaderUncompressed - stateMetablockHeaderReserved - stateMetablockHeaderBytes - stateMetablockHeaderMetadata -) - -const ( - stateUncompressedNone = iota - stateUncompressedWrite -) - -const ( - stateTreeGroupNone = iota - stateTreeGroupLoop -) - -const ( - stateContextMapNone = iota - stateContextMapReadPrefix - stateContextMapHuffman - stateContextMapDecode - stateContextMapTransform -) - -const ( - stateHuffmanNone = iota - stateHuffmanSimpleSize - stateHuffmanSimpleRead - stateHuffmanSimpleBuild - stateHuffmanComplex - stateHuffmanLengthSymbols -) - -const ( - stateDecodeUint8None = iota - stateDecodeUint8Short - stateDecodeUint8Long -) - -const ( - stateReadBlockLengthNone = iota - stateReadBlockLengthSuffix -) - -type Reader struct { - src io.Reader - buf []byte // scratch space for reading from src - in []byte // current chunk to decode; usually aliases buf - - state int - loop_counter int - br bitReader - buffer struct { - u64 uint64 - u8 [8]byte - } - buffer_length uint32 - pos int - max_backward_distance int - max_distance int - ringbuffer_size int - ringbuffer_mask int - dist_rb_idx int - dist_rb [4]int - error_code int - sub_loop_counter uint32 - ringbuffer []byte - ringbuffer_end []byte - htree_command []huffmanCode - context_lookup []byte - context_map_slice []byte - dist_context_map_slice []byte - literal_hgroup huffmanTreeGroup - insert_copy_hgroup huffmanTreeGroup - distance_hgroup huffmanTreeGroup - block_type_trees []huffmanCode - block_len_trees []huffmanCode - trivial_literal_context int - distance_context int - meta_block_remaining_len int - block_length_index uint32 - block_length [3]uint32 - num_block_types [3]uint32 - block_type_rb [6]uint32 - distance_postfix_bits uint32 - num_direct_distance_codes uint32 - distance_postfix_mask int - num_dist_htrees uint32 - dist_context_map []byte - literal_htree []huffmanCode - dist_htree_index byte - repeat_code_len uint32 - prev_code_len uint32 - copy_length int - distance_code int - rb_roundtrips uint - partial_pos_out uint - symbol uint32 - repeat uint32 - space uint32 - table [32]huffmanCode - symbol_lists symbolList - symbols_lists_array [huffmanMaxCodeLength + 1 + numCommandSymbols]uint16 - next_symbol [32]int - code_length_code_lengths [codeLengthCodes]byte - code_length_histo [16]uint16 - htree_index int - next []huffmanCode - context_index uint32 - max_run_length_prefix uint32 - code uint32 - context_map_table [huffmanMaxSize272]huffmanCode - substate_metablock_header int - substate_tree_group int - substate_context_map int - substate_uncompressed int - substate_huffman int - substate_decode_uint8 int - substate_read_block_length int - is_last_metablock uint - is_uncompressed uint - is_metadata uint - should_wrap_ringbuffer uint - canny_ringbuffer_allocation uint - large_window bool - size_nibbles uint - window_bits uint32 - new_ringbuffer_size int - num_literal_htrees uint32 - context_map []byte - context_modes []byte - dictionary *dictionary - transforms *transforms - trivial_literal_contexts [8]uint32 -} - -func decoderStateInit(s *Reader) bool { - s.error_code = 0 /* BROTLI_DECODER_NO_ERROR */ - - initBitReader(&s.br) - s.state = stateUninited - s.large_window = false - s.substate_metablock_header = stateMetablockHeaderNone - s.substate_tree_group = stateTreeGroupNone - s.substate_context_map = stateContextMapNone - s.substate_uncompressed = stateUncompressedNone - s.substate_huffman = stateHuffmanNone - s.substate_decode_uint8 = stateDecodeUint8None - s.substate_read_block_length = stateReadBlockLengthNone - - s.buffer_length = 0 - s.loop_counter = 0 - s.pos = 0 - s.rb_roundtrips = 0 - s.partial_pos_out = 0 - - clear(s.block_type_trees) - s.block_len_trees = nil - s.ringbuffer_size = 0 - s.new_ringbuffer_size = 0 - s.ringbuffer_mask = 0 - - s.context_map = nil - s.context_modes = nil - s.dist_context_map = nil - s.context_map_slice = nil - s.dist_context_map_slice = nil - - s.sub_loop_counter = 0 - - cleanupCodes(s) - cleanupHTrees(s) - - s.is_last_metablock = 0 - s.is_uncompressed = 0 - s.is_metadata = 0 - s.should_wrap_ringbuffer = 0 - s.canny_ringbuffer_allocation = 1 - - s.window_bits = 0 - s.max_distance = 0 - s.dist_rb[0] = 16 - s.dist_rb[1] = 15 - s.dist_rb[2] = 11 - s.dist_rb[3] = 4 - s.dist_rb_idx = 0 - - s.symbol_lists.storage = s.symbols_lists_array[:] - s.symbol_lists.offset = huffmanMaxCodeLength + 1 - - s.dictionary = getDictionary() - s.transforms = getTransforms() - - return true -} - -func decoderStateMetablockBegin(s *Reader) { - s.meta_block_remaining_len = 0 - s.block_length[0] = 1 << 24 - s.block_length[1] = 1 << 24 - s.block_length[2] = 1 << 24 - s.num_block_types[0] = 1 - s.num_block_types[1] = 1 - s.num_block_types[2] = 1 - s.block_type_rb[0] = 1 - s.block_type_rb[1] = 0 - s.block_type_rb[2] = 1 - s.block_type_rb[3] = 0 - s.block_type_rb[4] = 1 - s.block_type_rb[5] = 0 - s.context_map = nil - s.context_modes = nil - s.dist_context_map = nil - s.context_map_slice = nil - s.literal_htree = nil - s.dist_context_map_slice = nil - s.dist_htree_index = 0 - s.context_lookup = nil - - cleanupCodes(s) - cleanupHTrees(s) -} - -func decoderStateCleanupAfterMetablock(s *Reader) { - s.context_modes = nil - s.context_map = nil - s.dist_context_map = nil - cleanupHTrees(s) -} - -func decoderHuffmanTreeGroupInit(group *huffmanTreeGroup, alphabet_size uint32, max_symbol uint32, ntrees uint32) { - var max_table_size uint = uint(kMaxHuffmanTableSize[(alphabet_size+31)>>5]) - group.alphabet_size = uint16(alphabet_size) - group.max_symbol = uint16(max_symbol) - group.num_htrees = uint16(ntrees) - - makeCodesBuffer(group, uint(ntrees)*max_table_size) - makeTreesBuffer(group, ntrees) -} - -func makeTreesBuffer(group *huffmanTreeGroup, treesLen uint32) { - if cap(group.htrees) < int(treesLen) { - group.htrees = make([][]huffmanCode, treesLen) - return - } - - group.htrees = group.htrees[:treesLen] -} - -func makeCodesBuffer(group *huffmanTreeGroup, codesLen uint) { - if cap(group.codes) < int(codesLen) { - group.codes = make([]huffmanCode, codesLen) - return - } - - group.codes = group.codes[:codesLen] -} - -func cleanupCodes(s *Reader) { - clear(s.literal_hgroup.codes) - clear(s.insert_copy_hgroup.codes) - clear(s.distance_hgroup.codes) -} - -func cleanupHTrees(s *Reader) { - clear(s.literal_hgroup.htrees) - clear(s.insert_copy_hgroup.htrees) - clear(s.distance_hgroup.htrees) -} diff --git a/src/vendor/github.com/andybalholm/brotli/static_dict.go b/src/vendor/github.com/andybalholm/brotli/static_dict.go deleted file mode 100644 index bc05566d..00000000 --- a/src/vendor/github.com/andybalholm/brotli/static_dict.go +++ /dev/null @@ -1,662 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Class to model the static dictionary. */ - -const maxStaticDictionaryMatchLen = 37 - -const kInvalidMatch uint32 = 0xFFFFFFF - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ -func hash(data []byte) uint32 { - var h uint32 = binary.LittleEndian.Uint32(data) * kDictHashMul32 - - /* The higher bits contain more mixture from the multiplication, - so we take our results from there. */ - return h >> uint(32-kDictNumBits) -} - -func addMatch(distance uint, len uint, len_code uint, matches []uint32) { - var match uint32 = uint32((distance << 5) + len_code) - matches[len] = brotli_min_uint32_t(matches[len], match) -} - -func dictMatchLength(dict *dictionary, data []byte, id uint, len uint, maxlen uint) uint { - var offset uint = uint(dict.offsets_by_length[len]) + len*id - return findMatchLengthWithLimit(dict.data[offset:], data, brotli_min_size_t(uint(len), maxlen)) -} - -func isMatch(d *dictionary, w dictWord, data []byte, max_length uint) bool { - if uint(w.len) > max_length { - return false - } else { - var offset uint = uint(d.offsets_by_length[w.len]) + uint(w.len)*uint(w.idx) - var dict []byte = d.data[offset:] - if w.transform == 0 { - /* Match against base dictionary word. */ - return findMatchLengthWithLimit(dict, data, uint(w.len)) == uint(w.len) - } else if w.transform == 10 { - /* Match against uppercase first transform. - Note that there are only ASCII uppercase words in the lookup table. */ - return dict[0] >= 'a' && dict[0] <= 'z' && (dict[0]^32) == data[0] && findMatchLengthWithLimit(dict[1:], data[1:], uint(w.len)-1) == uint(w.len-1) - } else { - /* Match against uppercase all transform. - Note that there are only ASCII uppercase words in the lookup table. */ - var i uint - for i = 0; i < uint(w.len); i++ { - if dict[i] >= 'a' && dict[i] <= 'z' { - if (dict[i] ^ 32) != data[i] { - return false - } - } else { - if dict[i] != data[i] { - return false - } - } - } - - return true - } - } -} - -func findAllStaticDictionaryMatches(dict *encoderDictionary, data []byte, min_length uint, max_length uint, matches []uint32) bool { - var has_found_match bool = false - { - var offset uint = uint(dict.buckets[hash(data)]) - var end bool = offset == 0 - for !end { - w := dict.dict_words[offset] - offset++ - var l uint = uint(w.len) & 0x1F - var n uint = uint(1) << dict.words.size_bits_by_length[l] - var id uint = uint(w.idx) - end = !(w.len&0x80 == 0) - w.len = byte(l) - if w.transform == 0 { - var matchlen uint = dictMatchLength(dict.words, data, id, l, max_length) - var s []byte - var minlen uint - var maxlen uint - var len uint - - /* Transform "" + BROTLI_TRANSFORM_IDENTITY + "" */ - if matchlen == l { - addMatch(id, l, l, matches) - has_found_match = true - } - - /* Transforms "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "" and - "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "ing " */ - if matchlen >= l-1 { - addMatch(id+12*n, l-1, l, matches) - if l+2 < max_length && data[l-1] == 'i' && data[l] == 'n' && data[l+1] == 'g' && data[l+2] == ' ' { - addMatch(id+49*n, l+3, l, matches) - } - - has_found_match = true - } - - /* Transform "" + BROTLI_TRANSFORM_OMIT_LAST_# + "" (# = 2 .. 9) */ - minlen = min_length - - if l > 9 { - minlen = brotli_max_size_t(minlen, l-9) - } - maxlen = brotli_min_size_t(matchlen, l-2) - for len = minlen; len <= maxlen; len++ { - var cut uint = l - len - var transform_id uint = (cut << 2) + uint((dict.cutoffTransforms>>(cut*6))&0x3F) - addMatch(id+transform_id*n, uint(len), l, matches) - has_found_match = true - } - - if matchlen < l || l+6 >= max_length { - continue - } - - s = data[l:] - - /* Transforms "" + BROTLI_TRANSFORM_IDENTITY + */ - if s[0] == ' ' { - addMatch(id+n, l+1, l, matches) - if s[1] == 'a' { - if s[2] == ' ' { - addMatch(id+28*n, l+3, l, matches) - } else if s[2] == 's' { - if s[3] == ' ' { - addMatch(id+46*n, l+4, l, matches) - } - } else if s[2] == 't' { - if s[3] == ' ' { - addMatch(id+60*n, l+4, l, matches) - } - } else if s[2] == 'n' { - if s[3] == 'd' && s[4] == ' ' { - addMatch(id+10*n, l+5, l, matches) - } - } - } else if s[1] == 'b' { - if s[2] == 'y' && s[3] == ' ' { - addMatch(id+38*n, l+4, l, matches) - } - } else if s[1] == 'i' { - if s[2] == 'n' { - if s[3] == ' ' { - addMatch(id+16*n, l+4, l, matches) - } - } else if s[2] == 's' { - if s[3] == ' ' { - addMatch(id+47*n, l+4, l, matches) - } - } - } else if s[1] == 'f' { - if s[2] == 'o' { - if s[3] == 'r' && s[4] == ' ' { - addMatch(id+25*n, l+5, l, matches) - } - } else if s[2] == 'r' { - if s[3] == 'o' && s[4] == 'm' && s[5] == ' ' { - addMatch(id+37*n, l+6, l, matches) - } - } - } else if s[1] == 'o' { - if s[2] == 'f' { - if s[3] == ' ' { - addMatch(id+8*n, l+4, l, matches) - } - } else if s[2] == 'n' { - if s[3] == ' ' { - addMatch(id+45*n, l+4, l, matches) - } - } - } else if s[1] == 'n' { - if s[2] == 'o' && s[3] == 't' && s[4] == ' ' { - addMatch(id+80*n, l+5, l, matches) - } - } else if s[1] == 't' { - if s[2] == 'h' { - if s[3] == 'e' { - if s[4] == ' ' { - addMatch(id+5*n, l+5, l, matches) - } - } else if s[3] == 'a' { - if s[4] == 't' && s[5] == ' ' { - addMatch(id+29*n, l+6, l, matches) - } - } - } else if s[2] == 'o' { - if s[3] == ' ' { - addMatch(id+17*n, l+4, l, matches) - } - } - } else if s[1] == 'w' { - if s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ' { - addMatch(id+35*n, l+6, l, matches) - } - } - } else if s[0] == '"' { - addMatch(id+19*n, l+1, l, matches) - if s[1] == '>' { - addMatch(id+21*n, l+2, l, matches) - } - } else if s[0] == '.' { - addMatch(id+20*n, l+1, l, matches) - if s[1] == ' ' { - addMatch(id+31*n, l+2, l, matches) - if s[2] == 'T' && s[3] == 'h' { - if s[4] == 'e' { - if s[5] == ' ' { - addMatch(id+43*n, l+6, l, matches) - } - } else if s[4] == 'i' { - if s[5] == 's' && s[6] == ' ' { - addMatch(id+75*n, l+7, l, matches) - } - } - } - } - } else if s[0] == ',' { - addMatch(id+76*n, l+1, l, matches) - if s[1] == ' ' { - addMatch(id+14*n, l+2, l, matches) - } - } else if s[0] == '\n' { - addMatch(id+22*n, l+1, l, matches) - if s[1] == '\t' { - addMatch(id+50*n, l+2, l, matches) - } - } else if s[0] == ']' { - addMatch(id+24*n, l+1, l, matches) - } else if s[0] == '\'' { - addMatch(id+36*n, l+1, l, matches) - } else if s[0] == ':' { - addMatch(id+51*n, l+1, l, matches) - } else if s[0] == '(' { - addMatch(id+57*n, l+1, l, matches) - } else if s[0] == '=' { - if s[1] == '"' { - addMatch(id+70*n, l+2, l, matches) - } else if s[1] == '\'' { - addMatch(id+86*n, l+2, l, matches) - } - } else if s[0] == 'a' { - if s[1] == 'l' && s[2] == ' ' { - addMatch(id+84*n, l+3, l, matches) - } - } else if s[0] == 'e' { - if s[1] == 'd' { - if s[2] == ' ' { - addMatch(id+53*n, l+3, l, matches) - } - } else if s[1] == 'r' { - if s[2] == ' ' { - addMatch(id+82*n, l+3, l, matches) - } - } else if s[1] == 's' { - if s[2] == 't' && s[3] == ' ' { - addMatch(id+95*n, l+4, l, matches) - } - } - } else if s[0] == 'f' { - if s[1] == 'u' && s[2] == 'l' && s[3] == ' ' { - addMatch(id+90*n, l+4, l, matches) - } - } else if s[0] == 'i' { - if s[1] == 'v' { - if s[2] == 'e' && s[3] == ' ' { - addMatch(id+92*n, l+4, l, matches) - } - } else if s[1] == 'z' { - if s[2] == 'e' && s[3] == ' ' { - addMatch(id+100*n, l+4, l, matches) - } - } - } else if s[0] == 'l' { - if s[1] == 'e' { - if s[2] == 's' && s[3] == 's' && s[4] == ' ' { - addMatch(id+93*n, l+5, l, matches) - } - } else if s[1] == 'y' { - if s[2] == ' ' { - addMatch(id+61*n, l+3, l, matches) - } - } - } else if s[0] == 'o' { - if s[1] == 'u' && s[2] == 's' && s[3] == ' ' { - addMatch(id+106*n, l+4, l, matches) - } - } - } else { - var is_all_caps bool = (w.transform != transformUppercaseFirst) - /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and - is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) - transform. */ - - var s []byte - if !isMatch(dict.words, w, data, max_length) { - continue - } - - /* Transform "" + kUppercase{First,All} + "" */ - var tmp int - if is_all_caps { - tmp = 44 - } else { - tmp = 9 - } - addMatch(id+uint(tmp)*n, l, l, matches) - - has_found_match = true - if l+1 >= max_length { - continue - } - - /* Transforms "" + kUppercase{First,All} + */ - s = data[l:] - - if s[0] == ' ' { - var tmp int - if is_all_caps { - tmp = 68 - } else { - tmp = 4 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - } else if s[0] == '"' { - var tmp int - if is_all_caps { - tmp = 87 - } else { - tmp = 66 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - if s[1] == '>' { - var tmp int - if is_all_caps { - tmp = 97 - } else { - tmp = 69 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } - } else if s[0] == '.' { - var tmp int - if is_all_caps { - tmp = 101 - } else { - tmp = 79 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - if s[1] == ' ' { - var tmp int - if is_all_caps { - tmp = 114 - } else { - tmp = 88 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } - } else if s[0] == ',' { - var tmp int - if is_all_caps { - tmp = 112 - } else { - tmp = 99 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - if s[1] == ' ' { - var tmp int - if is_all_caps { - tmp = 107 - } else { - tmp = 58 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } - } else if s[0] == '\'' { - var tmp int - if is_all_caps { - tmp = 94 - } else { - tmp = 74 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - } else if s[0] == '(' { - var tmp int - if is_all_caps { - tmp = 113 - } else { - tmp = 78 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - } else if s[0] == '=' { - if s[1] == '"' { - var tmp int - if is_all_caps { - tmp = 105 - } else { - tmp = 104 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } else if s[1] == '\'' { - var tmp int - if is_all_caps { - tmp = 116 - } else { - tmp = 108 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } - } - } - } - } - - /* Transforms with prefixes " " and "." */ - if max_length >= 5 && (data[0] == ' ' || data[0] == '.') { - var is_space bool = (data[0] == ' ') - var offset uint = uint(dict.buckets[hash(data[1:])]) - var end bool = offset == 0 - for !end { - w := dict.dict_words[offset] - offset++ - var l uint = uint(w.len) & 0x1F - var n uint = uint(1) << dict.words.size_bits_by_length[l] - var id uint = uint(w.idx) - end = !(w.len&0x80 == 0) - w.len = byte(l) - if w.transform == 0 { - var s []byte - if !isMatch(dict.words, w, data[1:], max_length-1) { - continue - } - - /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + "" and - "." + BROTLI_TRANSFORM_IDENTITY + "" */ - var tmp int - if is_space { - tmp = 6 - } else { - tmp = 32 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - - has_found_match = true - if l+2 >= max_length { - continue - } - - /* Transforms " " + BROTLI_TRANSFORM_IDENTITY + and - "." + BROTLI_TRANSFORM_IDENTITY + - */ - s = data[l+1:] - - if s[0] == ' ' { - var tmp int - if is_space { - tmp = 2 - } else { - tmp = 77 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } else if s[0] == '(' { - var tmp int - if is_space { - tmp = 89 - } else { - tmp = 67 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } else if is_space { - if s[0] == ',' { - addMatch(id+103*n, l+2, l, matches) - if s[1] == ' ' { - addMatch(id+33*n, l+3, l, matches) - } - } else if s[0] == '.' { - addMatch(id+71*n, l+2, l, matches) - if s[1] == ' ' { - addMatch(id+52*n, l+3, l, matches) - } - } else if s[0] == '=' { - if s[1] == '"' { - addMatch(id+81*n, l+3, l, matches) - } else if s[1] == '\'' { - addMatch(id+98*n, l+3, l, matches) - } - } - } - } else if is_space { - var is_all_caps bool = (w.transform != transformUppercaseFirst) - /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and - is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL) - transform. */ - - var s []byte - if !isMatch(dict.words, w, data[1:], max_length-1) { - continue - } - - /* Transforms " " + kUppercase{First,All} + "" */ - var tmp int - if is_all_caps { - tmp = 85 - } else { - tmp = 30 - } - addMatch(id+uint(tmp)*n, l+1, l, matches) - - has_found_match = true - if l+2 >= max_length { - continue - } - - /* Transforms " " + kUppercase{First,All} + */ - s = data[l+1:] - - if s[0] == ' ' { - var tmp int - if is_all_caps { - tmp = 83 - } else { - tmp = 15 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - } else if s[0] == ',' { - if !is_all_caps { - addMatch(id+109*n, l+2, l, matches) - } - - if s[1] == ' ' { - var tmp int - if is_all_caps { - tmp = 111 - } else { - tmp = 65 - } - addMatch(id+uint(tmp)*n, l+3, l, matches) - } - } else if s[0] == '.' { - var tmp int - if is_all_caps { - tmp = 115 - } else { - tmp = 96 - } - addMatch(id+uint(tmp)*n, l+2, l, matches) - if s[1] == ' ' { - var tmp int - if is_all_caps { - tmp = 117 - } else { - tmp = 91 - } - addMatch(id+uint(tmp)*n, l+3, l, matches) - } - } else if s[0] == '=' { - if s[1] == '"' { - var tmp int - if is_all_caps { - tmp = 110 - } else { - tmp = 118 - } - addMatch(id+uint(tmp)*n, l+3, l, matches) - } else if s[1] == '\'' { - var tmp int - if is_all_caps { - tmp = 119 - } else { - tmp = 120 - } - addMatch(id+uint(tmp)*n, l+3, l, matches) - } - } - } - } - } - - if max_length >= 6 { - /* Transforms with prefixes "e ", "s ", ", " and "\xC2\xA0" */ - if (data[1] == ' ' && (data[0] == 'e' || data[0] == 's' || data[0] == ',')) || (data[0] == 0xC2 && data[1] == 0xA0) { - var offset uint = uint(dict.buckets[hash(data[2:])]) - var end bool = offset == 0 - for !end { - w := dict.dict_words[offset] - offset++ - var l uint = uint(w.len) & 0x1F - var n uint = uint(1) << dict.words.size_bits_by_length[l] - var id uint = uint(w.idx) - end = !(w.len&0x80 == 0) - w.len = byte(l) - if w.transform == 0 && isMatch(dict.words, w, data[2:], max_length-2) { - if data[0] == 0xC2 { - addMatch(id+102*n, l+2, l, matches) - has_found_match = true - } else if l+2 < max_length && data[l+2] == ' ' { - var t uint = 13 - if data[0] == 'e' { - t = 18 - } else if data[0] == 's' { - t = 7 - } - addMatch(id+t*n, l+3, l, matches) - has_found_match = true - } - } - } - } - } - - if max_length >= 9 { - /* Transforms with prefixes " the " and ".com/" */ - if (data[0] == ' ' && data[1] == 't' && data[2] == 'h' && data[3] == 'e' && data[4] == ' ') || (data[0] == '.' && data[1] == 'c' && data[2] == 'o' && data[3] == 'm' && data[4] == '/') { - var offset uint = uint(dict.buckets[hash(data[5:])]) - var end bool = offset == 0 - for !end { - w := dict.dict_words[offset] - offset++ - var l uint = uint(w.len) & 0x1F - var n uint = uint(1) << dict.words.size_bits_by_length[l] - var id uint = uint(w.idx) - end = !(w.len&0x80 == 0) - w.len = byte(l) - if w.transform == 0 && isMatch(dict.words, w, data[5:], max_length-5) { - var tmp int - if data[0] == ' ' { - tmp = 41 - } else { - tmp = 72 - } - addMatch(id+uint(tmp)*n, l+5, l, matches) - has_found_match = true - if l+5 < max_length { - var s []byte = data[l+5:] - if data[0] == ' ' { - if l+8 < max_length && s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ' { - addMatch(id+62*n, l+9, l, matches) - if l+12 < max_length && s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ' { - addMatch(id+73*n, l+13, l, matches) - } - } - } - } - } - } - } - } - - return has_found_match -} diff --git a/src/vendor/github.com/andybalholm/brotli/static_dict_lut.go b/src/vendor/github.com/andybalholm/brotli/static_dict_lut.go deleted file mode 100644 index b33963e9..00000000 --- a/src/vendor/github.com/andybalholm/brotli/static_dict_lut.go +++ /dev/null @@ -1,75094 +0,0 @@ -package brotli - -/* Copyright 2017 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Lookup table for static dictionary and transforms. */ - -type dictWord struct { - len byte - transform byte - idx uint16 -} - -const kDictNumBits int = 15 - -const kDictHashMul32 uint32 = 0x1E35A7BD - -var kStaticDictionaryBuckets = [32768]uint16{ - 1, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3, - 6, - 0, - 0, - 0, - 0, - 0, - 20, - 0, - 0, - 0, - 21, - 0, - 22, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23, - 0, - 0, - 25, - 0, - 29, - 0, - 53, - 0, - 0, - 0, - 0, - 0, - 0, - 55, - 0, - 0, - 0, - 0, - 0, - 0, - 61, - 76, - 0, - 0, - 0, - 94, - 0, - 0, - 0, - 0, - 0, - 0, - 96, - 0, - 97, - 0, - 98, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 99, - 101, - 106, - 108, - 0, - 0, - 0, - 0, - 0, - 110, - 0, - 111, - 112, - 0, - 113, - 118, - 124, - 0, - 0, - 0, - 0, - 0, - 125, - 128, - 0, - 0, - 0, - 0, - 129, - 0, - 0, - 131, - 0, - 0, - 0, - 0, - 0, - 0, - 132, - 0, - 0, - 135, - 0, - 0, - 0, - 137, - 0, - 0, - 0, - 0, - 0, - 138, - 139, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 142, - 143, - 144, - 0, - 0, - 0, - 0, - 0, - 145, - 0, - 0, - 0, - 146, - 149, - 151, - 152, - 0, - 0, - 153, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 154, - 0, - 0, - 0, - 0, - 0, - 0, - 155, - 0, - 0, - 0, - 0, - 160, - 182, - 0, - 0, - 0, - 0, - 0, - 0, - 183, - 0, - 0, - 0, - 188, - 189, - 0, - 0, - 192, - 0, - 0, - 0, - 0, - 0, - 0, - 194, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 197, - 202, - 209, - 0, - 0, - 210, - 0, - 224, - 0, - 0, - 0, - 225, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 231, - 0, - 0, - 0, - 232, - 0, - 240, - 0, - 0, - 242, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 244, - 0, - 0, - 0, - 246, - 0, - 0, - 249, - 251, - 253, - 0, - 0, - 0, - 0, - 0, - 258, - 0, - 0, - 261, - 263, - 0, - 0, - 0, - 267, - 0, - 0, - 268, - 0, - 269, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 271, - 0, - 0, - 0, - 0, - 0, - 0, - 272, - 0, - 273, - 0, - 277, - 0, - 278, - 286, - 0, - 0, - 0, - 0, - 287, - 0, - 289, - 290, - 291, - 0, - 0, - 0, - 295, - 0, - 0, - 296, - 297, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 298, - 0, - 0, - 0, - 299, - 0, - 0, - 305, - 0, - 324, - 0, - 0, - 0, - 0, - 0, - 327, - 0, - 328, - 329, - 0, - 0, - 0, - 0, - 336, - 0, - 0, - 340, - 0, - 341, - 342, - 343, - 0, - 0, - 346, - 0, - 348, - 0, - 0, - 0, - 0, - 0, - 0, - 349, - 351, - 0, - 0, - 355, - 0, - 363, - 0, - 364, - 0, - 368, - 369, - 0, - 370, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 372, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 373, - 0, - 375, - 0, - 0, - 0, - 0, - 376, - 377, - 0, - 0, - 394, - 395, - 396, - 0, - 0, - 398, - 0, - 0, - 0, - 0, - 400, - 0, - 0, - 408, - 0, - 0, - 0, - 0, - 420, - 0, - 0, - 0, - 0, - 0, - 0, - 421, - 0, - 0, - 422, - 423, - 0, - 0, - 429, - 435, - 436, - 442, - 0, - 0, - 443, - 0, - 444, - 445, - 453, - 456, - 0, - 457, - 0, - 0, - 0, - 0, - 0, - 458, - 0, - 0, - 0, - 459, - 0, - 0, - 0, - 460, - 0, - 462, - 463, - 465, - 0, - 0, - 0, - 0, - 0, - 0, - 466, - 469, - 0, - 0, - 0, - 0, - 0, - 0, - 470, - 0, - 0, - 0, - 474, - 0, - 476, - 0, - 0, - 0, - 0, - 483, - 0, - 485, - 0, - 0, - 0, - 486, - 0, - 0, - 488, - 491, - 492, - 0, - 0, - 497, - 499, - 500, - 0, - 501, - 0, - 0, - 0, - 505, - 0, - 0, - 506, - 0, - 0, - 0, - 507, - 0, - 0, - 0, - 509, - 0, - 0, - 0, - 0, - 511, - 512, - 519, - 0, - 0, - 0, - 0, - 0, - 0, - 529, - 530, - 0, - 0, - 0, - 534, - 0, - 0, - 0, - 0, - 543, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 553, - 0, - 0, - 0, - 0, - 557, - 560, - 0, - 0, - 0, - 0, - 0, - 0, - 561, - 0, - 564, - 0, - 0, - 0, - 0, - 0, - 0, - 565, - 566, - 0, - 575, - 0, - 619, - 0, - 620, - 0, - 0, - 623, - 624, - 0, - 0, - 0, - 625, - 0, - 0, - 626, - 627, - 0, - 0, - 628, - 0, - 0, - 0, - 0, - 630, - 0, - 631, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 641, - 0, - 0, - 0, - 0, - 643, - 656, - 668, - 0, - 0, - 0, - 673, - 0, - 0, - 0, - 674, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 682, - 0, - 687, - 0, - 690, - 0, - 693, - 699, - 700, - 0, - 0, - 0, - 0, - 0, - 0, - 704, - 705, - 0, - 0, - 0, - 0, - 707, - 710, - 0, - 711, - 0, - 0, - 0, - 0, - 726, - 0, - 0, - 729, - 0, - 0, - 0, - 730, - 731, - 0, - 0, - 0, - 0, - 0, - 752, - 0, - 0, - 0, - 762, - 0, - 763, - 0, - 0, - 767, - 0, - 0, - 0, - 770, - 774, - 0, - 0, - 775, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 776, - 0, - 0, - 0, - 777, - 783, - 0, - 0, - 0, - 785, - 788, - 0, - 0, - 0, - 0, - 790, - 0, - 0, - 0, - 793, - 0, - 0, - 0, - 0, - 794, - 0, - 0, - 804, - 819, - 821, - 0, - 827, - 0, - 0, - 0, - 834, - 0, - 0, - 835, - 0, - 0, - 0, - 841, - 0, - 844, - 0, - 850, - 851, - 859, - 0, - 860, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 874, - 0, - 876, - 0, - 877, - 890, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 893, - 894, - 898, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 899, - 0, - 0, - 0, - 900, - 904, - 906, - 0, - 0, - 0, - 907, - 0, - 908, - 909, - 0, - 910, - 0, - 0, - 0, - 0, - 911, - 0, - 0, - 0, - 0, - 0, - 916, - 0, - 0, - 0, - 922, - 925, - 0, - 930, - 0, - 934, - 0, - 0, - 0, - 0, - 0, - 943, - 0, - 0, - 944, - 0, - 953, - 954, - 0, - 0, - 0, - 0, - 0, - 0, - 955, - 0, - 962, - 963, - 0, - 0, - 976, - 0, - 0, - 977, - 978, - 979, - 980, - 0, - 981, - 0, - 0, - 0, - 0, - 984, - 0, - 0, - 985, - 0, - 0, - 987, - 989, - 991, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 992, - 0, - 0, - 0, - 993, - 0, - 0, - 0, - 0, - 0, - 0, - 996, - 0, - 0, - 0, - 1000, - 0, - 0, - 0, - 0, - 0, - 1002, - 0, - 0, - 0, - 0, - 1005, - 1007, - 0, - 0, - 0, - 1009, - 0, - 0, - 0, - 1010, - 0, - 0, - 0, - 0, - 0, - 0, - 1011, - 0, - 1012, - 0, - 0, - 0, - 0, - 1014, - 1016, - 0, - 0, - 0, - 1020, - 0, - 1021, - 0, - 0, - 0, - 0, - 1022, - 0, - 0, - 0, - 1024, - 0, - 0, - 0, - 0, - 0, - 0, - 1025, - 0, - 0, - 1026, - 1027, - 0, - 0, - 0, - 0, - 0, - 1031, - 0, - 1033, - 0, - 0, - 0, - 0, - 1034, - 0, - 0, - 0, - 1037, - 1040, - 0, - 0, - 0, - 1042, - 1043, - 0, - 0, - 1053, - 0, - 1054, - 0, - 0, - 1057, - 0, - 0, - 0, - 1058, - 0, - 0, - 1060, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1061, - 0, - 0, - 1062, - 0, - 0, - 0, - 0, - 1063, - 0, - 0, - 0, - 0, - 1064, - 0, - 0, - 0, - 0, - 0, - 1065, - 0, - 0, - 0, - 0, - 1066, - 1067, - 0, - 0, - 0, - 1069, - 1070, - 1072, - 0, - 0, - 0, - 0, - 0, - 0, - 1073, - 0, - 1075, - 0, - 0, - 0, - 0, - 0, - 0, - 1080, - 1084, - 0, - 0, - 0, - 0, - 1088, - 0, - 0, - 0, - 0, - 0, - 0, - 1094, - 0, - 1095, - 0, - 1107, - 0, - 0, - 0, - 1112, - 1114, - 0, - 1119, - 0, - 1122, - 0, - 0, - 1126, - 0, - 1129, - 0, - 1130, - 0, - 0, - 0, - 0, - 0, - 1132, - 0, - 0, - 0, - 0, - 0, - 0, - 1144, - 0, - 0, - 1145, - 1146, - 0, - 1148, - 1149, - 0, - 0, - 1150, - 1151, - 0, - 0, - 0, - 0, - 1152, - 0, - 1153, - 0, - 0, - 0, - 0, - 0, - 1154, - 0, - 1163, - 0, - 0, - 0, - 1164, - 0, - 0, - 0, - 0, - 0, - 1165, - 0, - 1167, - 0, - 1170, - 0, - 0, - 0, - 0, - 0, - 1171, - 1172, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1173, - 1175, - 1177, - 0, - 1186, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1195, - 0, - 0, - 1221, - 0, - 0, - 1224, - 0, - 0, - 1227, - 0, - 0, - 0, - 0, - 0, - 1228, - 1229, - 0, - 0, - 1230, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1231, - 0, - 0, - 0, - 1233, - 0, - 0, - 1243, - 1244, - 1246, - 1248, - 0, - 0, - 0, - 0, - 1254, - 1255, - 1258, - 1259, - 0, - 0, - 0, - 1260, - 0, - 0, - 1261, - 0, - 0, - 0, - 1262, - 1264, - 0, - 0, - 1265, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1266, - 0, - 1267, - 0, - 0, - 0, - 0, - 1273, - 1274, - 1276, - 1289, - 0, - 0, - 1291, - 1292, - 1293, - 0, - 0, - 1294, - 1295, - 1296, - 0, - 0, - 0, - 0, - 1302, - 0, - 1304, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1311, - 1312, - 0, - 1314, - 0, - 1316, - 1320, - 1321, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1322, - 1323, - 1324, - 0, - 1335, - 0, - 1336, - 0, - 0, - 0, - 0, - 1341, - 1342, - 0, - 1346, - 0, - 1357, - 0, - 0, - 0, - 1358, - 1360, - 0, - 0, - 0, - 0, - 0, - 0, - 1361, - 0, - 0, - 0, - 1362, - 1365, - 0, - 1366, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1379, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1386, - 0, - 1388, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1395, - 0, - 0, - 0, - 0, - 1403, - 0, - 1405, - 0, - 0, - 1407, - 0, - 0, - 0, - 0, - 0, - 1408, - 1409, - 0, - 1410, - 0, - 0, - 0, - 1412, - 1413, - 1416, - 0, - 0, - 1429, - 1451, - 0, - 0, - 1454, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1455, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1456, - 0, - 0, - 0, - 0, - 1459, - 1460, - 1461, - 1475, - 0, - 0, - 0, - 0, - 0, - 0, - 1477, - 0, - 1480, - 0, - 1481, - 0, - 0, - 1486, - 0, - 0, - 1495, - 0, - 0, - 0, - 1496, - 0, - 0, - 1498, - 1499, - 1501, - 1520, - 1521, - 0, - 0, - 0, - 1526, - 0, - 0, - 0, - 0, - 1528, - 1529, - 0, - 1533, - 1536, - 0, - 0, - 0, - 1537, - 1538, - 1549, - 0, - 1550, - 1558, - 1559, - 1572, - 0, - 1573, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1575, - 0, - 0, - 0, - 0, - 0, - 1579, - 0, - 1599, - 0, - 1603, - 0, - 1604, - 0, - 1605, - 0, - 0, - 0, - 0, - 0, - 1608, - 1610, - 0, - 0, - 0, - 0, - 1611, - 0, - 1615, - 0, - 1616, - 1618, - 0, - 1619, - 0, - 0, - 1622, - 0, - 0, - 0, - 0, - 1634, - 0, - 0, - 0, - 1635, - 0, - 0, - 0, - 1641, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1643, - 0, - 0, - 0, - 1650, - 0, - 0, - 1652, - 0, - 0, - 0, - 0, - 0, - 1653, - 0, - 0, - 0, - 1654, - 0, - 0, - 0, - 0, - 1655, - 0, - 1662, - 0, - 0, - 1663, - 1664, - 0, - 0, - 1668, - 0, - 0, - 1669, - 1670, - 0, - 1672, - 1673, - 0, - 0, - 0, - 0, - 0, - 1674, - 0, - 0, - 0, - 1675, - 1676, - 1680, - 0, - 1682, - 0, - 0, - 1687, - 0, - 0, - 0, - 0, - 0, - 1704, - 0, - 0, - 1705, - 0, - 0, - 1721, - 0, - 0, - 0, - 0, - 1734, - 1735, - 0, - 0, - 0, - 0, - 1737, - 0, - 0, - 0, - 0, - 1739, - 0, - 0, - 1740, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1741, - 1743, - 0, - 0, - 0, - 0, - 1745, - 0, - 0, - 0, - 1749, - 0, - 0, - 0, - 1751, - 0, - 0, - 0, - 0, - 0, - 0, - 1760, - 0, - 0, - 0, - 0, - 1765, - 0, - 0, - 0, - 0, - 0, - 1784, - 0, - 1785, - 1787, - 0, - 0, - 0, - 0, - 1788, - 1789, - 0, - 0, - 0, - 0, - 1790, - 1791, - 1793, - 0, - 1798, - 1799, - 0, - 0, - 0, - 0, - 1801, - 0, - 1803, - 1805, - 0, - 0, - 0, - 1806, - 1811, - 0, - 1812, - 1814, - 0, - 1821, - 0, - 0, - 0, - 0, - 0, - 1822, - 1833, - 0, - 0, - 0, - 0, - 0, - 0, - 1848, - 0, - 0, - 0, - 0, - 0, - 0, - 1857, - 0, - 0, - 0, - 1859, - 0, - 0, - 0, - 0, - 1861, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1866, - 0, - 1921, - 1925, - 0, - 0, - 0, - 1929, - 1930, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1931, - 0, - 0, - 0, - 0, - 1932, - 0, - 0, - 0, - 1934, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1946, - 0, - 0, - 1948, - 0, - 0, - 0, - 0, - 1950, - 0, - 1957, - 0, - 1958, - 0, - 0, - 0, - 0, - 0, - 1965, - 1967, - 0, - 0, - 0, - 0, - 1968, - 0, - 1969, - 0, - 1971, - 1972, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 1973, - 0, - 0, - 0, - 0, - 1975, - 0, - 0, - 0, - 0, - 1976, - 1979, - 0, - 1982, - 0, - 0, - 0, - 0, - 1984, - 1988, - 0, - 0, - 0, - 0, - 1990, - 2004, - 2008, - 0, - 0, - 0, - 2012, - 2013, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2015, - 0, - 2016, - 2017, - 0, - 0, - 0, - 0, - 2021, - 0, - 0, - 2025, - 0, - 0, - 0, - 0, - 0, - 2029, - 2036, - 2040, - 0, - 2042, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2043, - 0, - 0, - 0, - 0, - 0, - 2045, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2046, - 2047, - 0, - 2048, - 2049, - 0, - 2059, - 0, - 0, - 2063, - 0, - 2064, - 2065, - 0, - 0, - 2066, - 0, - 0, - 0, - 0, - 0, - 0, - 2069, - 0, - 0, - 0, - 0, - 2070, - 0, - 2071, - 0, - 2072, - 0, - 0, - 0, - 0, - 2080, - 2082, - 2083, - 0, - 0, - 0, - 0, - 0, - 2085, - 0, - 2086, - 2088, - 2089, - 2105, - 0, - 0, - 0, - 0, - 2107, - 0, - 0, - 2116, - 2117, - 0, - 2120, - 0, - 0, - 2122, - 0, - 0, - 0, - 0, - 0, - 2123, - 0, - 0, - 2125, - 2127, - 2128, - 0, - 0, - 0, - 2130, - 0, - 0, - 0, - 2137, - 2139, - 2140, - 2141, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2144, - 2145, - 0, - 0, - 2146, - 2149, - 0, - 0, - 0, - 0, - 2150, - 0, - 0, - 2151, - 2158, - 0, - 2159, - 0, - 2160, - 0, - 0, - 0, - 0, - 0, - 0, - 2161, - 2162, - 0, - 0, - 2194, - 2202, - 0, - 0, - 0, - 0, - 0, - 0, - 2205, - 2217, - 0, - 2220, - 0, - 2221, - 0, - 2222, - 2224, - 0, - 0, - 0, - 0, - 2237, - 0, - 0, - 0, - 0, - 0, - 2238, - 0, - 2239, - 2241, - 0, - 0, - 2242, - 0, - 0, - 0, - 0, - 0, - 2243, - 0, - 0, - 0, - 0, - 0, - 0, - 2252, - 0, - 0, - 2253, - 0, - 0, - 0, - 2257, - 2258, - 0, - 0, - 0, - 2260, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2262, - 0, - 2264, - 0, - 0, - 0, - 0, - 0, - 2269, - 2270, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2271, - 0, - 2273, - 0, - 0, - 0, - 0, - 2277, - 0, - 0, - 0, - 0, - 2278, - 0, - 0, - 0, - 0, - 2279, - 0, - 2280, - 0, - 2283, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2287, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2289, - 2290, - 0, - 0, - 0, - 0, - 2291, - 0, - 2292, - 0, - 0, - 0, - 2293, - 2295, - 2296, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2298, - 0, - 0, - 0, - 0, - 0, - 2303, - 0, - 2305, - 0, - 0, - 2306, - 0, - 2307, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2313, - 2314, - 2315, - 2316, - 0, - 0, - 2318, - 0, - 2319, - 0, - 2322, - 0, - 0, - 2323, - 0, - 2324, - 0, - 2326, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2335, - 0, - 2336, - 2338, - 2339, - 0, - 2340, - 0, - 0, - 0, - 2355, - 0, - 2375, - 0, - 2382, - 2386, - 0, - 2387, - 0, - 0, - 2394, - 0, - 0, - 0, - 0, - 2395, - 0, - 2397, - 0, - 0, - 0, - 0, - 0, - 2398, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2399, - 2402, - 2404, - 2408, - 2411, - 0, - 0, - 0, - 2413, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2415, - 0, - 0, - 2416, - 2417, - 2419, - 0, - 2420, - 0, - 0, - 0, - 0, - 0, - 2425, - 0, - 0, - 0, - 2426, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2427, - 2428, - 0, - 2429, - 0, - 0, - 2430, - 2434, - 0, - 2436, - 0, - 0, - 0, - 0, - 0, - 0, - 2441, - 2442, - 0, - 2445, - 0, - 0, - 2446, - 2457, - 0, - 2459, - 0, - 0, - 2462, - 0, - 2464, - 0, - 2477, - 0, - 2478, - 2486, - 0, - 0, - 0, - 2491, - 0, - 0, - 2493, - 0, - 0, - 2494, - 0, - 2495, - 0, - 2513, - 2523, - 0, - 0, - 0, - 0, - 2524, - 0, - 0, - 0, - 0, - 0, - 0, - 2528, - 2529, - 2530, - 0, - 0, - 2531, - 0, - 2533, - 0, - 0, - 2534, - 2535, - 0, - 2536, - 2537, - 0, - 2538, - 0, - 2539, - 2540, - 0, - 0, - 0, - 2545, - 2546, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2548, - 0, - 0, - 2549, - 0, - 2550, - 2555, - 0, - 0, - 0, - 0, - 0, - 2557, - 0, - 2560, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2561, - 0, - 2576, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2577, - 2578, - 0, - 0, - 0, - 2579, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2580, - 0, - 0, - 0, - 0, - 2581, - 0, - 0, - 0, - 0, - 2583, - 0, - 2584, - 0, - 2588, - 2590, - 0, - 0, - 0, - 2591, - 0, - 0, - 0, - 0, - 2593, - 2594, - 0, - 2595, - 0, - 2601, - 2602, - 0, - 0, - 2603, - 0, - 2605, - 0, - 0, - 0, - 2606, - 2607, - 2611, - 0, - 2615, - 0, - 0, - 0, - 2617, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2619, - 0, - 0, - 2620, - 0, - 0, - 0, - 2621, - 0, - 2623, - 0, - 2625, - 0, - 0, - 2628, - 2629, - 0, - 0, - 2635, - 2636, - 2637, - 0, - 0, - 2639, - 0, - 0, - 0, - 2642, - 0, - 0, - 0, - 0, - 2643, - 0, - 2644, - 0, - 2649, - 0, - 0, - 0, - 0, - 0, - 0, - 2655, - 2656, - 0, - 0, - 2657, - 0, - 0, - 0, - 0, - 0, - 2658, - 0, - 0, - 0, - 0, - 0, - 2659, - 0, - 0, - 0, - 0, - 2664, - 2685, - 0, - 2687, - 0, - 2688, - 0, - 0, - 2689, - 0, - 0, - 2694, - 0, - 2695, - 0, - 0, - 2698, - 0, - 2701, - 2706, - 0, - 0, - 0, - 2707, - 0, - 2709, - 2710, - 2711, - 0, - 0, - 0, - 2720, - 2730, - 2735, - 0, - 0, - 0, - 0, - 2738, - 2740, - 0, - 0, - 0, - 0, - 2747, - 0, - 0, - 0, - 0, - 0, - 0, - 2748, - 0, - 0, - 2749, - 0, - 0, - 0, - 0, - 0, - 2750, - 0, - 0, - 2752, - 2754, - 0, - 0, - 0, - 0, - 0, - 2758, - 0, - 0, - 0, - 0, - 2762, - 0, - 0, - 0, - 0, - 2763, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2764, - 2767, - 0, - 0, - 0, - 0, - 2768, - 0, - 0, - 2770, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2771, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2772, - 0, - 0, - 0, - 0, - 0, - 2773, - 2776, - 0, - 0, - 2783, - 0, - 0, - 2784, - 0, - 2789, - 0, - 2790, - 0, - 0, - 0, - 2792, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2793, - 2795, - 0, - 0, - 0, - 0, - 0, - 0, - 2796, - 0, - 0, - 0, - 0, - 0, - 0, - 2797, - 2799, - 0, - 0, - 0, - 0, - 2803, - 0, - 0, - 0, - 0, - 2806, - 0, - 2807, - 2808, - 2817, - 2819, - 0, - 0, - 0, - 0, - 0, - 2821, - 0, - 0, - 0, - 0, - 2822, - 2823, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2824, - 0, - 0, - 2828, - 0, - 2834, - 0, - 0, - 0, - 0, - 0, - 0, - 2836, - 0, - 2838, - 0, - 0, - 2839, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2841, - 0, - 0, - 0, - 2842, - 0, - 0, - 0, - 0, - 0, - 2843, - 2844, - 0, - 0, - 0, - 0, - 2846, - 0, - 0, - 2847, - 0, - 2849, - 0, - 2853, - 0, - 0, - 0, - 0, - 0, - 2857, - 0, - 0, - 0, - 0, - 2858, - 0, - 2859, - 0, - 0, - 2860, - 0, - 2862, - 2868, - 0, - 0, - 0, - 0, - 2875, - 0, - 2876, - 0, - 0, - 2877, - 2878, - 2884, - 2889, - 2890, - 0, - 0, - 2891, - 0, - 0, - 2892, - 0, - 0, - 0, - 2906, - 2912, - 0, - 2913, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2916, - 0, - 2934, - 0, - 0, - 0, - 0, - 0, - 2935, - 0, - 0, - 0, - 0, - 2939, - 0, - 2940, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2941, - 0, - 0, - 0, - 2946, - 0, - 2949, - 0, - 0, - 2950, - 2954, - 2955, - 0, - 0, - 0, - 2959, - 2961, - 0, - 0, - 2962, - 0, - 2963, - 0, - 0, - 0, - 0, - 0, - 0, - 2964, - 2965, - 2966, - 2967, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2969, - 0, - 0, - 0, - 0, - 0, - 2970, - 2975, - 0, - 2982, - 2983, - 2984, - 0, - 0, - 0, - 0, - 0, - 2989, - 0, - 0, - 2990, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2991, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 2998, - 0, - 3000, - 3001, - 0, - 0, - 3002, - 0, - 0, - 0, - 3003, - 0, - 0, - 3012, - 0, - 0, - 3022, - 0, - 0, - 3024, - 0, - 0, - 3025, - 3027, - 0, - 0, - 0, - 3030, - 0, - 0, - 0, - 0, - 3034, - 3035, - 0, - 0, - 3036, - 0, - 3039, - 0, - 3049, - 0, - 0, - 3050, - 0, - 0, - 0, - 0, - 0, - 0, - 3051, - 0, - 3053, - 0, - 0, - 0, - 0, - 3057, - 0, - 3058, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3063, - 0, - 0, - 3073, - 3074, - 3078, - 3079, - 0, - 3080, - 3086, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3087, - 0, - 3092, - 0, - 3095, - 0, - 3099, - 0, - 0, - 0, - 3100, - 0, - 3101, - 3102, - 0, - 3122, - 0, - 0, - 0, - 3124, - 0, - 3125, - 0, - 0, - 0, - 0, - 0, - 0, - 3132, - 3134, - 0, - 0, - 3136, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3147, - 0, - 0, - 3149, - 0, - 0, - 0, - 0, - 0, - 3150, - 3151, - 3152, - 0, - 0, - 0, - 0, - 3158, - 0, - 0, - 3160, - 0, - 0, - 3161, - 0, - 0, - 3162, - 0, - 3163, - 3166, - 3168, - 0, - 0, - 3169, - 3170, - 0, - 0, - 3171, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3182, - 0, - 3184, - 0, - 0, - 3188, - 0, - 0, - 3194, - 0, - 0, - 0, - 0, - 0, - 0, - 3204, - 0, - 0, - 0, - 0, - 3209, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3216, - 3217, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3219, - 0, - 0, - 3220, - 3222, - 0, - 3223, - 0, - 0, - 0, - 0, - 3224, - 0, - 3225, - 3226, - 0, - 3228, - 3233, - 0, - 3239, - 3241, - 3242, - 0, - 0, - 3251, - 3252, - 3253, - 3255, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3260, - 0, - 0, - 3261, - 0, - 0, - 0, - 3267, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3271, - 0, - 0, - 0, - 3278, - 0, - 3282, - 0, - 0, - 0, - 3284, - 0, - 0, - 0, - 3285, - 3286, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3287, - 3292, - 0, - 0, - 0, - 0, - 3294, - 3296, - 0, - 0, - 3299, - 3300, - 3301, - 0, - 3302, - 0, - 0, - 0, - 0, - 0, - 3304, - 3306, - 0, - 0, - 0, - 0, - 0, - 0, - 3308, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3311, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3312, - 3314, - 3315, - 0, - 3318, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3319, - 0, - 0, - 0, - 0, - 0, - 3321, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3322, - 0, - 0, - 3324, - 3325, - 0, - 0, - 3326, - 0, - 0, - 3328, - 3329, - 3331, - 0, - 0, - 3335, - 0, - 0, - 3337, - 0, - 3338, - 0, - 0, - 0, - 0, - 3343, - 3347, - 0, - 0, - 0, - 3348, - 0, - 0, - 3351, - 0, - 0, - 0, - 0, - 0, - 0, - 3354, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3355, - 0, - 0, - 3365, - 3366, - 3367, - 0, - 0, - 0, - 0, - 0, - 0, - 3368, - 3369, - 0, - 3370, - 0, - 0, - 3373, - 0, - 0, - 3376, - 0, - 0, - 3377, - 0, - 3379, - 3387, - 0, - 0, - 0, - 0, - 0, - 3390, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3402, - 0, - 3403, - 3436, - 3437, - 3439, - 0, - 0, - 3441, - 0, - 0, - 0, - 3442, - 0, - 0, - 3449, - 0, - 0, - 0, - 3450, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3451, - 0, - 0, - 3452, - 0, - 3453, - 3456, - 0, - 3457, - 0, - 0, - 3458, - 0, - 3459, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3460, - 0, - 0, - 3469, - 3470, - 0, - 0, - 3475, - 0, - 0, - 0, - 3480, - 3487, - 3489, - 0, - 3490, - 0, - 0, - 3491, - 3499, - 0, - 3500, - 0, - 0, - 3501, - 0, - 0, - 0, - 3502, - 0, - 3514, - 0, - 0, - 0, - 3516, - 3517, - 0, - 0, - 0, - 3518, - 0, - 0, - 0, - 0, - 3520, - 3521, - 3522, - 0, - 0, - 3526, - 3530, - 0, - 0, - 0, - 0, - 3531, - 0, - 0, - 0, - 0, - 3536, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3539, - 3541, - 0, - 0, - 3542, - 3544, - 0, - 3547, - 3548, - 0, - 0, - 3550, - 0, - 3553, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3554, - 0, - 3555, - 0, - 3558, - 0, - 3559, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3563, - 0, - 3581, - 0, - 0, - 0, - 3599, - 0, - 0, - 0, - 3600, - 0, - 3601, - 0, - 3602, - 3603, - 0, - 0, - 3606, - 3608, - 0, - 3610, - 3611, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3612, - 3616, - 3619, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3624, - 3628, - 0, - 3629, - 3634, - 3635, - 0, - 0, - 0, - 0, - 0, - 0, - 3636, - 0, - 3637, - 0, - 0, - 3638, - 3651, - 0, - 0, - 0, - 0, - 0, - 0, - 3652, - 3653, - 0, - 0, - 0, - 0, - 3656, - 3657, - 0, - 0, - 0, - 0, - 0, - 3658, - 0, - 0, - 0, - 0, - 3659, - 0, - 3661, - 3663, - 3664, - 0, - 3665, - 0, - 3692, - 0, - 0, - 0, - 3694, - 3696, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3698, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3700, - 0, - 0, - 3701, - 0, - 0, - 0, - 3708, - 3709, - 0, - 0, - 0, - 3711, - 3712, - 0, - 0, - 0, - 0, - 0, - 3723, - 0, - 3724, - 3725, - 0, - 0, - 3726, - 0, - 0, - 0, - 0, - 0, - 0, - 3728, - 3729, - 0, - 3734, - 3735, - 3737, - 0, - 0, - 0, - 3743, - 0, - 3745, - 0, - 0, - 3746, - 0, - 0, - 3747, - 3748, - 0, - 3757, - 0, - 3759, - 3766, - 3767, - 0, - 3768, - 0, - 0, - 0, - 0, - 3769, - 0, - 0, - 3771, - 0, - 3774, - 0, - 0, - 0, - 0, - 0, - 0, - 3775, - 0, - 0, - 0, - 0, - 0, - 0, - 3776, - 0, - 3777, - 3786, - 0, - 3788, - 3789, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3791, - 0, - 3811, - 0, - 0, - 0, - 0, - 0, - 3814, - 3815, - 3816, - 3820, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3821, - 0, - 0, - 3825, - 0, - 0, - 0, - 0, - 3835, - 0, - 0, - 3848, - 3849, - 0, - 0, - 0, - 0, - 3850, - 3851, - 3853, - 0, - 0, - 0, - 0, - 3859, - 0, - 3860, - 3862, - 0, - 0, - 0, - 0, - 0, - 3863, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3873, - 0, - 3874, - 0, - 3875, - 3886, - 0, - 3887, - 0, - 0, - 0, - 0, - 3892, - 3913, - 0, - 3914, - 0, - 0, - 0, - 3925, - 3931, - 0, - 0, - 0, - 0, - 3934, - 3941, - 3942, - 0, - 0, - 0, - 0, - 3943, - 0, - 0, - 0, - 3944, - 0, - 0, - 0, - 0, - 0, - 3945, - 0, - 3947, - 0, - 0, - 0, - 3956, - 3957, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3958, - 0, - 3959, - 3965, - 0, - 0, - 0, - 0, - 3966, - 0, - 0, - 0, - 3967, - 0, - 0, - 0, - 3968, - 3974, - 0, - 0, - 0, - 0, - 0, - 3975, - 3977, - 3978, - 0, - 0, - 0, - 0, - 3980, - 0, - 3985, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3986, - 4011, - 0, - 0, - 4017, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4018, - 0, - 0, - 0, - 0, - 4019, - 0, - 4023, - 0, - 0, - 0, - 4027, - 4028, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4031, - 4034, - 0, - 0, - 4035, - 4037, - 4039, - 4040, - 0, - 0, - 0, - 0, - 0, - 4059, - 0, - 4060, - 4061, - 0, - 4062, - 4063, - 4066, - 0, - 0, - 4072, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4088, - 0, - 0, - 0, - 0, - 0, - 4091, - 0, - 0, - 0, - 0, - 4094, - 4095, - 0, - 0, - 4096, - 0, - 0, - 0, - 0, - 0, - 4098, - 4099, - 0, - 0, - 0, - 4101, - 0, - 4104, - 0, - 0, - 0, - 4105, - 4108, - 0, - 4113, - 0, - 0, - 4115, - 4116, - 0, - 4126, - 0, - 0, - 4127, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4128, - 4132, - 4133, - 0, - 4134, - 0, - 0, - 0, - 4137, - 0, - 0, - 4141, - 0, - 0, - 0, - 0, - 4144, - 4146, - 4147, - 0, - 0, - 0, - 0, - 4148, - 0, - 0, - 4311, - 0, - 0, - 0, - 4314, - 4329, - 0, - 4331, - 4332, - 0, - 4333, - 0, - 4334, - 0, - 0, - 0, - 4335, - 0, - 4336, - 0, - 0, - 0, - 4337, - 0, - 0, - 0, - 4342, - 4345, - 4346, - 4350, - 0, - 4351, - 4352, - 0, - 4354, - 4355, - 0, - 0, - 4364, - 0, - 0, - 0, - 0, - 4369, - 0, - 0, - 0, - 4373, - 0, - 4374, - 0, - 0, - 0, - 0, - 4377, - 0, - 0, - 0, - 0, - 4378, - 0, - 0, - 0, - 4380, - 0, - 0, - 0, - 4381, - 4382, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4384, - 0, - 0, - 0, - 0, - 4385, - 0, - 0, - 0, - 4386, - 0, - 0, - 0, - 4391, - 4398, - 0, - 0, - 0, - 0, - 4407, - 4409, - 0, - 0, - 0, - 0, - 4410, - 0, - 0, - 4411, - 0, - 4414, - 4415, - 4418, - 0, - 4427, - 4428, - 4430, - 0, - 4431, - 0, - 4448, - 0, - 0, - 0, - 0, - 0, - 4449, - 0, - 0, - 0, - 4451, - 4452, - 0, - 4453, - 4454, - 0, - 4456, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4459, - 0, - 4463, - 0, - 0, - 0, - 0, - 0, - 4466, - 0, - 4467, - 0, - 4469, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4470, - 4471, - 0, - 4473, - 0, - 0, - 4475, - 0, - 0, - 0, - 0, - 4477, - 4478, - 0, - 0, - 0, - 4479, - 4481, - 0, - 4482, - 0, - 4484, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4486, - 0, - 0, - 4488, - 0, - 0, - 4497, - 0, - 4508, - 0, - 0, - 4510, - 4511, - 0, - 4520, - 4523, - 0, - 4524, - 0, - 4525, - 0, - 4527, - 0, - 0, - 4528, - 0, - 0, - 0, - 0, - 4530, - 0, - 4531, - 0, - 0, - 4532, - 0, - 0, - 0, - 4533, - 0, - 0, - 0, - 0, - 0, - 4535, - 0, - 0, - 0, - 4536, - 0, - 0, - 0, - 0, - 0, - 4541, - 4543, - 4544, - 4545, - 4547, - 0, - 4548, - 0, - 0, - 0, - 0, - 4550, - 4551, - 0, - 4553, - 0, - 0, - 0, - 0, - 4562, - 0, - 0, - 4571, - 0, - 0, - 0, - 4574, - 0, - 0, - 0, - 4575, - 0, - 4576, - 0, - 4577, - 0, - 0, - 0, - 4581, - 0, - 0, - 0, - 0, - 0, - 4582, - 0, - 0, - 4586, - 0, - 0, - 0, - 4588, - 0, - 0, - 4597, - 0, - 4598, - 0, - 0, - 0, - 0, - 4616, - 4617, - 0, - 4618, - 0, - 0, - 0, - 0, - 4619, - 0, - 4620, - 0, - 0, - 4621, - 0, - 4624, - 0, - 0, - 0, - 0, - 0, - 4625, - 0, - 0, - 0, - 0, - 4657, - 0, - 4659, - 0, - 4667, - 0, - 0, - 0, - 4668, - 4670, - 0, - 4672, - 0, - 0, - 0, - 0, - 0, - 4673, - 4676, - 0, - 0, - 0, - 0, - 4687, - 0, - 0, - 0, - 0, - 4697, - 0, - 0, - 0, - 0, - 4699, - 0, - 4701, - 0, - 0, - 0, - 0, - 4702, - 0, - 0, - 4706, - 0, - 0, - 4713, - 0, - 0, - 0, - 4714, - 4715, - 4716, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4717, - 0, - 0, - 4720, - 0, - 4721, - 4729, - 4735, - 0, - 0, - 0, - 4737, - 0, - 0, - 0, - 4739, - 0, - 0, - 0, - 4740, - 0, - 0, - 0, - 4741, - 0, - 0, - 0, - 0, - 0, - 4742, - 0, - 4745, - 4746, - 4747, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4748, - 0, - 0, - 0, - 4749, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4751, - 4786, - 0, - 4787, - 0, - 4788, - 4796, - 0, - 0, - 4797, - 4798, - 0, - 4799, - 4806, - 4807, - 0, - 0, - 0, - 0, - 4809, - 4810, - 0, - 0, - 0, - 0, - 0, - 0, - 4811, - 0, - 0, - 0, - 0, - 0, - 4812, - 0, - 4813, - 0, - 0, - 4815, - 0, - 4821, - 4822, - 0, - 0, - 0, - 0, - 4823, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4824, - 0, - 0, - 0, - 0, - 4826, - 0, - 0, - 0, - 4828, - 0, - 4829, - 0, - 0, - 0, - 4843, - 0, - 0, - 4847, - 0, - 4853, - 4855, - 4858, - 0, - 0, - 0, - 0, - 0, - 4859, - 0, - 4864, - 0, - 0, - 4879, - 0, - 0, - 0, - 0, - 4880, - 0, - 0, - 0, - 0, - 4881, - 0, - 4882, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4883, - 0, - 0, - 0, - 0, - 4884, - 0, - 0, - 0, - 0, - 0, - 4886, - 4887, - 4888, - 4894, - 4896, - 0, - 4902, - 0, - 0, - 4905, - 0, - 0, - 4915, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4916, - 4917, - 4919, - 4921, - 0, - 0, - 0, - 0, - 0, - 4926, - 0, - 0, - 0, - 0, - 4927, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4929, - 0, - 4930, - 4931, - 0, - 4938, - 0, - 4952, - 0, - 4953, - 4957, - 4960, - 4964, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5019, - 5020, - 5022, - 0, - 0, - 0, - 0, - 0, - 5023, - 0, - 0, - 0, - 5024, - 0, - 0, - 0, - 5025, - 0, - 0, - 0, - 0, - 5028, - 0, - 0, - 0, - 0, - 5029, - 5030, - 5031, - 0, - 5033, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5034, - 5035, - 0, - 5036, - 0, - 0, - 5037, - 0, - 0, - 0, - 0, - 5038, - 0, - 0, - 5039, - 0, - 0, - 0, - 5041, - 5042, - 0, - 0, - 0, - 0, - 5044, - 5049, - 5054, - 0, - 5055, - 0, - 5057, - 0, - 0, - 0, - 5060, - 0, - 0, - 0, - 0, - 0, - 5063, - 0, - 5064, - 5065, - 0, - 5067, - 0, - 0, - 0, - 5068, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5076, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5077, - 0, - 0, - 5078, - 5080, - 0, - 0, - 5083, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5085, - 0, - 0, - 0, - 0, - 0, - 0, - 5098, - 5099, - 5101, - 5105, - 5107, - 0, - 5108, - 0, - 5109, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5110, - 0, - 0, - 0, - 0, - 0, - 5117, - 5118, - 0, - 5121, - 0, - 5122, - 0, - 0, - 5130, - 0, - 0, - 0, - 5137, - 0, - 0, - 0, - 5148, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5151, - 5154, - 0, - 0, - 0, - 5155, - 0, - 0, - 5156, - 5159, - 5161, - 0, - 0, - 0, - 0, - 5162, - 0, - 0, - 0, - 0, - 5163, - 5164, - 0, - 5166, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5167, - 0, - 0, - 0, - 5172, - 0, - 0, - 0, - 0, - 0, - 0, - 5178, - 5179, - 0, - 0, - 5190, - 0, - 0, - 5191, - 5192, - 5194, - 0, - 0, - 5198, - 5201, - 0, - 0, - 0, - 0, - 0, - 5203, - 0, - 5206, - 5209, - 0, - 0, - 0, - 0, - 0, - 0, - 5213, - 0, - 5214, - 5216, - 0, - 0, - 0, - 0, - 0, - 5217, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5218, - 5219, - 0, - 5231, - 0, - 0, - 5244, - 5249, - 0, - 5254, - 0, - 5255, - 0, - 0, - 5257, - 0, - 0, - 0, - 0, - 0, - 5258, - 0, - 5260, - 5270, - 0, - 5277, - 0, - 0, - 0, - 0, - 0, - 0, - 5280, - 5281, - 5282, - 5283, - 0, - 0, - 0, - 0, - 0, - 5284, - 0, - 5285, - 0, - 0, - 0, - 0, - 0, - 5287, - 5288, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5289, - 5291, - 0, - 0, - 5294, - 0, - 0, - 5295, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5304, - 0, - 0, - 5306, - 5307, - 5308, - 0, - 5309, - 0, - 0, - 5310, - 0, - 0, - 0, - 0, - 5311, - 5312, - 0, - 5313, - 0, - 0, - 0, - 0, - 0, - 5316, - 0, - 0, - 0, - 5317, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5325, - 0, - 0, - 0, - 0, - 0, - 0, - 5326, - 0, - 5327, - 5329, - 0, - 5332, - 0, - 0, - 0, - 0, - 5338, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5340, - 0, - 0, - 5341, - 0, - 0, - 0, - 5342, - 0, - 5343, - 5344, - 0, - 0, - 5345, - 0, - 0, - 0, - 0, - 0, - 0, - 5347, - 5348, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5349, - 0, - 5350, - 0, - 5354, - 0, - 0, - 0, - 0, - 5358, - 0, - 0, - 5359, - 0, - 0, - 5361, - 0, - 0, - 5365, - 0, - 5367, - 0, - 5373, - 0, - 0, - 0, - 5379, - 0, - 0, - 0, - 5380, - 0, - 0, - 0, - 5382, - 0, - 5384, - 0, - 0, - 0, - 0, - 0, - 0, - 5385, - 0, - 0, - 0, - 0, - 5387, - 0, - 0, - 0, - 0, - 0, - 0, - 5388, - 5390, - 5393, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5396, - 0, - 0, - 0, - 0, - 5397, - 5402, - 0, - 0, - 0, - 0, - 0, - 5403, - 0, - 0, - 0, - 5404, - 5405, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5406, - 0, - 0, - 0, - 0, - 5410, - 0, - 0, - 5411, - 0, - 5415, - 0, - 0, - 0, - 0, - 5416, - 5434, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5438, - 0, - 5440, - 0, - 0, - 0, - 0, - 0, - 0, - 5441, - 5442, - 0, - 0, - 0, - 5443, - 5444, - 5447, - 0, - 0, - 5448, - 5449, - 5451, - 0, - 0, - 0, - 5456, - 5457, - 0, - 0, - 0, - 5459, - 0, - 0, - 0, - 5461, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5464, - 0, - 5466, - 0, - 0, - 5467, - 0, - 5470, - 0, - 0, - 5473, - 0, - 0, - 5474, - 0, - 0, - 5476, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5477, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5484, - 0, - 0, - 5485, - 5486, - 0, - 0, - 0, - 0, - 0, - 5488, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5489, - 0, - 0, - 0, - 0, - 0, - 5507, - 0, - 0, - 0, - 5510, - 0, - 5511, - 0, - 0, - 5512, - 0, - 0, - 0, - 5513, - 0, - 5515, - 0, - 0, - 5516, - 5517, - 0, - 5518, - 0, - 0, - 5522, - 0, - 0, - 0, - 0, - 0, - 5534, - 5535, - 0, - 0, - 5536, - 0, - 5538, - 0, - 0, - 5543, - 0, - 5544, - 0, - 0, - 5545, - 0, - 5547, - 0, - 5557, - 0, - 0, - 5558, - 0, - 5560, - 5567, - 0, - 0, - 0, - 0, - 5568, - 0, - 0, - 0, - 5571, - 5573, - 0, - 5574, - 0, - 5575, - 0, - 0, - 0, - 0, - 5577, - 0, - 0, - 5598, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5600, - 5609, - 0, - 0, - 0, - 0, - 5610, - 0, - 0, - 5612, - 0, - 5624, - 0, - 5625, - 0, - 0, - 0, - 5629, - 0, - 5641, - 0, - 5642, - 5643, - 0, - 0, - 0, - 0, - 0, - 0, - 5651, - 0, - 0, - 0, - 5652, - 5653, - 0, - 5661, - 5662, - 5678, - 0, - 5679, - 0, - 0, - 0, - 0, - 5685, - 5686, - 0, - 0, - 0, - 0, - 0, - 5690, - 5692, - 0, - 5703, - 0, - 0, - 0, - 0, - 0, - 5706, - 0, - 0, - 0, - 0, - 5707, - 0, - 0, - 0, - 0, - 0, - 0, - 5708, - 0, - 0, - 5709, - 0, - 5710, - 0, - 0, - 0, - 5712, - 0, - 5733, - 0, - 5734, - 5735, - 0, - 0, - 5744, - 5751, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5752, - 0, - 5754, - 0, - 0, - 0, - 0, - 0, - 0, - 5757, - 5758, - 0, - 5760, - 5761, - 0, - 0, - 0, - 0, - 5763, - 5764, - 5765, - 0, - 5766, - 0, - 5767, - 5768, - 0, - 5770, - 0, - 0, - 0, - 0, - 5776, - 5780, - 0, - 0, - 0, - 0, - 5782, - 0, - 0, - 0, - 0, - 5784, - 0, - 0, - 5788, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5797, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5799, - 0, - 0, - 5801, - 0, - 0, - 0, - 5811, - 0, - 0, - 0, - 0, - 0, - 0, - 5816, - 0, - 0, - 5827, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5830, - 5831, - 0, - 0, - 5832, - 0, - 0, - 5833, - 0, - 5835, - 5844, - 5845, - 0, - 5846, - 0, - 0, - 0, - 0, - 0, - 5850, - 0, - 0, - 0, - 0, - 0, - 5852, - 0, - 5855, - 5857, - 0, - 0, - 5859, - 0, - 5861, - 0, - 0, - 5863, - 0, - 5865, - 0, - 0, - 0, - 5873, - 5875, - 0, - 0, - 0, - 5877, - 0, - 5879, - 0, - 0, - 0, - 5888, - 0, - 0, - 5889, - 5891, - 0, - 5894, - 0, - 0, - 0, - 0, - 0, - 0, - 5895, - 0, - 5897, - 0, - 0, - 0, - 0, - 0, - 0, - 5907, - 0, - 5911, - 0, - 0, - 5912, - 0, - 5913, - 5922, - 5924, - 0, - 5927, - 5928, - 0, - 0, - 0, - 0, - 5929, - 5930, - 0, - 5933, - 0, - 0, - 0, - 0, - 5949, - 0, - 0, - 5951, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 5953, - 0, - 0, - 5954, - 0, - 5959, - 5960, - 5961, - 0, - 5964, - 0, - 0, - 0, - 5976, - 5978, - 5987, - 5990, - 0, - 0, - 0, - 0, - 0, - 5991, - 0, - 5992, - 0, - 0, - 0, - 5994, - 5995, - 0, - 0, - 5996, - 0, - 0, - 6001, - 6003, - 0, - 0, - 0, - 0, - 6007, - 0, - 0, - 0, - 0, - 0, - 6008, - 0, - 0, - 6009, - 0, - 6010, - 0, - 0, - 0, - 6011, - 6015, - 0, - 6017, - 0, - 6019, - 0, - 6023, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6025, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6026, - 0, - 6030, - 0, - 0, - 6032, - 0, - 0, - 0, - 6033, - 6038, - 6040, - 0, - 0, - 0, - 6041, - 6045, - 0, - 0, - 6046, - 0, - 0, - 6053, - 0, - 0, - 6054, - 0, - 6055, - 0, - 0, - 0, - 0, - 0, - 0, - 6057, - 0, - 6063, - 0, - 0, - 0, - 6064, - 0, - 6066, - 6071, - 6072, - 0, - 0, - 0, - 0, - 0, - 0, - 6075, - 6076, - 0, - 0, - 6077, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6078, - 6079, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6080, - 0, - 6083, - 0, - 0, - 0, - 0, - 0, - 6084, - 0, - 0, - 6088, - 0, - 6089, - 0, - 0, - 6093, - 6105, - 0, - 0, - 6107, - 0, - 6110, - 0, - 0, - 0, - 6111, - 6125, - 6126, - 0, - 0, - 0, - 6129, - 0, - 0, - 0, - 0, - 6130, - 0, - 0, - 0, - 6131, - 6134, - 0, - 0, - 0, - 0, - 0, - 0, - 6142, - 0, - 0, - 0, - 0, - 0, - 6144, - 0, - 0, - 6146, - 6151, - 6153, - 0, - 6156, - 0, - 6163, - 0, - 6180, - 6181, - 0, - 0, - 0, - 0, - 0, - 6182, - 0, - 0, - 0, - 0, - 6184, - 6195, - 0, - 0, - 6206, - 0, - 6208, - 0, - 0, - 6212, - 6213, - 6214, - 0, - 6215, - 0, - 0, - 0, - 6228, - 0, - 0, - 0, - 6234, - 0, - 0, - 0, - 0, - 0, - 0, - 6235, - 6240, - 0, - 6242, - 6243, - 6244, - 0, - 6250, - 6255, - 0, - 0, - 0, - 0, - 0, - 6257, - 0, - 0, - 0, - 6258, - 6278, - 0, - 6284, - 0, - 0, - 0, - 6285, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6286, - 0, - 0, - 0, - 6320, - 0, - 0, - 6322, - 6332, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6334, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6335, - 0, - 0, - 6337, - 0, - 6338, - 0, - 6339, - 6340, - 0, - 0, - 6356, - 6357, - 6369, - 0, - 0, - 0, - 6370, - 6371, - 6372, - 0, - 6373, - 0, - 0, - 0, - 0, - 0, - 6376, - 0, - 0, - 0, - 0, - 0, - 6382, - 6383, - 6384, - 0, - 0, - 0, - 0, - 6386, - 0, - 6389, - 6397, - 6400, - 6411, - 0, - 6414, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6415, - 6416, - 0, - 0, - 0, - 0, - 0, - 0, - 6417, - 0, - 0, - 0, - 0, - 6418, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6420, - 0, - 6421, - 6423, - 6425, - 0, - 6429, - 6430, - 0, - 6433, - 6438, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6439, - 6440, - 0, - 0, - 6441, - 0, - 0, - 6444, - 0, - 0, - 0, - 0, - 6446, - 0, - 0, - 0, - 0, - 6447, - 6448, - 0, - 0, - 6450, - 0, - 0, - 0, - 6454, - 0, - 0, - 6455, - 0, - 6461, - 0, - 0, - 0, - 0, - 0, - 0, - 6462, - 0, - 0, - 6463, - 0, - 6464, - 0, - 6465, - 6467, - 0, - 0, - 0, - 6468, - 0, - 6479, - 6480, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6481, - 0, - 0, - 6485, - 6487, - 0, - 0, - 0, - 0, - 0, - 0, - 6493, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6494, - 6495, - 6496, - 0, - 0, - 0, - 0, - 0, - 6498, - 0, - 0, - 0, - 6507, - 6508, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6511, - 6512, - 0, - 0, - 0, - 0, - 6513, - 0, - 0, - 0, - 6514, - 0, - 0, - 0, - 0, - 0, - 6516, - 0, - 0, - 6517, - 6518, - 0, - 0, - 0, - 6519, - 6520, - 6521, - 0, - 6523, - 0, - 0, - 0, - 0, - 6524, - 6528, - 0, - 6530, - 0, - 0, - 6532, - 0, - 6578, - 0, - 0, - 0, - 6583, - 0, - 6584, - 0, - 0, - 0, - 6587, - 0, - 0, - 0, - 6590, - 0, - 6591, - 0, - 0, - 0, - 0, - 0, - 6592, - 0, - 0, - 0, - 0, - 6593, - 6594, - 0, - 0, - 0, - 0, - 0, - 6599, - 6600, - 0, - 0, - 6601, - 6602, - 6604, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6608, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6610, - 6611, - 0, - 6615, - 0, - 6616, - 6618, - 6620, - 0, - 6637, - 0, - 0, - 0, - 0, - 6639, - 0, - 0, - 0, - 0, - 6641, - 0, - 6642, - 0, - 0, - 0, - 6647, - 0, - 6660, - 6663, - 0, - 6664, - 0, - 6666, - 6669, - 0, - 6675, - 6676, - 6677, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6678, - 0, - 0, - 0, - 6679, - 0, - 6680, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6693, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6704, - 6705, - 6706, - 0, - 0, - 6711, - 6713, - 0, - 0, - 0, - 0, - 0, - 6716, - 0, - 0, - 0, - 6717, - 0, - 6719, - 6724, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6725, - 6726, - 0, - 0, - 0, - 0, - 0, - 6728, - 6729, - 6735, - 0, - 6737, - 6742, - 0, - 0, - 6743, - 6750, - 0, - 6751, - 0, - 0, - 6752, - 6753, - 0, - 0, - 0, - 0, - 0, - 0, - 6754, - 0, - 0, - 0, - 0, - 0, - 6756, - 0, - 0, - 0, - 0, - 0, - 0, - 6763, - 0, - 0, - 6764, - 6765, - 0, - 0, - 0, - 6770, - 0, - 0, - 0, - 6776, - 6780, - 0, - 6781, - 0, - 0, - 0, - 6783, - 0, - 6784, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6785, - 0, - 0, - 0, - 6792, - 0, - 0, - 0, - 6793, - 0, - 0, - 6802, - 0, - 0, - 0, - 0, - 0, - 6803, - 0, - 0, - 0, - 6804, - 0, - 0, - 0, - 6812, - 0, - 0, - 6823, - 0, - 6824, - 6839, - 0, - 0, - 0, - 0, - 6852, - 0, - 0, - 6854, - 0, - 6856, - 6857, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6867, - 0, - 6868, - 6870, - 6872, - 0, - 0, - 0, - 6873, - 6874, - 0, - 0, - 0, - 0, - 0, - 6875, - 0, - 0, - 6877, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6878, - 0, - 0, - 0, - 6879, - 0, - 6880, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6887, - 0, - 6888, - 6891, - 6893, - 0, - 6895, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6899, - 0, - 0, - 0, - 0, - 6901, - 0, - 0, - 0, - 0, - 6910, - 0, - 6911, - 0, - 0, - 6912, - 0, - 0, - 6913, - 6914, - 0, - 0, - 0, - 6915, - 0, - 0, - 0, - 6916, - 6919, - 0, - 0, - 0, - 0, - 0, - 0, - 6924, - 0, - 6925, - 0, - 0, - 0, - 6926, - 6927, - 6928, - 0, - 6929, - 0, - 6930, - 0, - 0, - 6931, - 6935, - 0, - 6936, - 0, - 0, - 0, - 0, - 6939, - 6940, - 6941, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6942, - 6948, - 6949, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6952, - 6954, - 6963, - 6965, - 6966, - 0, - 0, - 6967, - 6968, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6969, - 0, - 0, - 6970, - 6979, - 0, - 0, - 6980, - 0, - 0, - 6983, - 0, - 0, - 0, - 0, - 0, - 6984, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6988, - 6990, - 6992, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6995, - 0, - 0, - 0, - 7012, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7019, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7021, - 0, - 0, - 7022, - 7023, - 7028, - 0, - 7030, - 7033, - 0, - 0, - 0, - 0, - 0, - 0, - 7038, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7039, - 0, - 0, - 0, - 0, - 0, - 7046, - 0, - 7047, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7048, - 7052, - 0, - 0, - 0, - 0, - 0, - 7054, - 0, - 7060, - 0, - 0, - 0, - 0, - 7061, - 0, - 7065, - 0, - 0, - 0, - 0, - 7067, - 7069, - 0, - 7070, - 7071, - 7072, - 0, - 0, - 7078, - 0, - 7080, - 7081, - 0, - 7083, - 0, - 0, - 0, - 7084, - 7087, - 7088, - 0, - 0, - 7090, - 0, - 7093, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7107, - 0, - 0, - 7108, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7110, - 0, - 7114, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7115, - 0, - 7116, - 0, - 0, - 0, - 0, - 0, - 7117, - 0, - 0, - 7118, - 0, - 0, - 7124, - 0, - 7125, - 0, - 0, - 7126, - 0, - 0, - 0, - 0, - 7128, - 0, - 0, - 0, - 0, - 0, - 7129, - 0, - 7130, - 0, - 7132, - 7133, - 0, - 0, - 7134, - 0, - 0, - 7139, - 0, - 7148, - 7150, - 0, - 0, - 0, - 0, - 7152, - 0, - 0, - 0, - 7153, - 7156, - 7157, - 0, - 0, - 0, - 0, - 0, - 7158, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7163, - 7165, - 7169, - 0, - 7171, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7172, - 0, - 7173, - 7181, - 0, - 0, - 0, - 0, - 0, - 7182, - 7185, - 0, - 0, - 0, - 0, - 7187, - 0, - 7201, - 7204, - 0, - 0, - 0, - 0, - 0, - 7206, - 7207, - 0, - 0, - 0, - 0, - 7211, - 7216, - 0, - 7218, - 0, - 0, - 0, - 0, - 7226, - 7228, - 7230, - 7232, - 7233, - 7235, - 7237, - 0, - 0, - 0, - 0, - 7238, - 7241, - 0, - 7242, - 0, - 0, - 7247, - 0, - 0, - 0, - 7266, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7289, - 0, - 0, - 7290, - 7291, - 0, - 0, - 7292, - 0, - 7297, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7300, - 0, - 7301, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7302, - 0, - 0, - 0, - 0, - 7305, - 0, - 0, - 0, - 0, - 7307, - 0, - 7308, - 0, - 7310, - 0, - 7335, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7337, - 0, - 7343, - 7347, - 0, - 0, - 0, - 0, - 0, - 7348, - 0, - 7349, - 7350, - 7352, - 7354, - 0, - 0, - 0, - 0, - 7357, - 0, - 7358, - 7366, - 0, - 7367, - 7368, - 0, - 0, - 7373, - 0, - 0, - 0, - 7374, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7376, - 0, - 0, - 0, - 7377, - 0, - 0, - 0, - 0, - 0, - 7378, - 0, - 7379, - 7380, - 0, - 0, - 0, - 0, - 0, - 7383, - 0, - 0, - 7386, - 0, - 0, - 0, - 0, - 7398, - 0, - 0, - 0, - 7399, - 7400, - 0, - 7401, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7402, - 0, - 0, - 0, - 0, - 0, - 7405, - 0, - 0, - 0, - 0, - 0, - 7406, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7421, - 7427, - 7429, - 0, - 0, - 0, - 7435, - 0, - 0, - 7436, - 0, - 0, - 0, - 7437, - 0, - 0, - 0, - 0, - 0, - 0, - 7438, - 7443, - 0, - 7446, - 0, - 7448, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7456, - 0, - 0, - 0, - 0, - 0, - 7457, - 0, - 0, - 7461, - 0, - 0, - 0, - 0, - 0, - 7462, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7463, - 7466, - 7472, - 0, - 7476, - 0, - 0, - 7490, - 0, - 7491, - 0, - 0, - 7493, - 0, - 0, - 0, - 7498, - 7499, - 0, - 0, - 7508, - 0, - 0, - 0, - 0, - 0, - 7512, - 0, - 0, - 0, - 7513, - 7514, - 7516, - 0, - 0, - 0, - 0, - 7518, - 0, - 0, - 7519, - 7521, - 7522, - 0, - 0, - 0, - 7526, - 0, - 0, - 7529, - 0, - 0, - 7531, - 0, - 7536, - 0, - 7538, - 0, - 7539, - 0, - 0, - 7541, - 7542, - 7546, - 0, - 0, - 0, - 0, - 0, - 7547, - 0, - 7548, - 0, - 0, - 0, - 0, - 0, - 7550, - 0, - 0, - 7552, - 7553, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7554, - 7563, - 0, - 7573, - 0, - 0, - 0, - 0, - 0, - 0, - 7574, - 7576, - 0, - 7578, - 7581, - 7583, - 0, - 0, - 0, - 7584, - 0, - 7587, - 0, - 0, - 0, - 0, - 0, - 7589, - 0, - 0, - 0, - 7594, - 0, - 0, - 7595, - 0, - 0, - 7600, - 7602, - 7610, - 0, - 0, - 0, - 0, - 0, - 7612, - 0, - 7613, - 7614, - 0, - 0, - 7615, - 0, - 0, - 7616, - 0, - 7620, - 0, - 7621, - 7622, - 0, - 7623, - 0, - 0, - 0, - 0, - 7626, - 0, - 0, - 0, - 0, - 7627, - 7629, - 7631, - 0, - 0, - 7633, - 0, - 0, - 0, - 0, - 0, - 7639, - 0, - 7640, - 7642, - 0, - 0, - 7643, - 0, - 0, - 0, - 0, - 7644, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7645, - 0, - 0, - 0, - 0, - 0, - 7661, - 7662, - 7663, - 7665, - 0, - 7666, - 0, - 7667, - 0, - 7684, - 7688, - 7690, - 0, - 7691, - 0, - 0, - 0, - 0, - 0, - 0, - 7692, - 0, - 0, - 7700, - 0, - 7707, - 0, - 7708, - 0, - 7709, - 0, - 7721, - 0, - 0, - 0, - 7722, - 0, - 7724, - 0, - 0, - 0, - 0, - 0, - 0, - 7729, - 7731, - 0, - 7732, - 0, - 7733, - 7735, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7739, - 0, - 0, - 7741, - 7745, - 0, - 7748, - 0, - 0, - 0, - 7751, - 0, - 0, - 0, - 7752, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7753, - 0, - 0, - 7756, - 0, - 7757, - 0, - 7759, - 0, - 7760, - 0, - 0, - 0, - 0, - 7761, - 7768, - 0, - 0, - 7769, - 0, - 0, - 7770, - 0, - 0, - 7771, - 0, - 0, - 7772, - 0, - 0, - 7773, - 0, - 0, - 0, - 0, - 0, - 7778, - 7783, - 0, - 0, - 0, - 0, - 0, - 7784, - 7785, - 0, - 7790, - 0, - 0, - 0, - 0, - 7792, - 0, - 7798, - 0, - 0, - 0, - 0, - 0, - 7799, - 0, - 7810, - 0, - 0, - 7813, - 0, - 7814, - 0, - 7816, - 0, - 7818, - 7824, - 7825, - 7826, - 0, - 7828, - 7830, - 0, - 0, - 0, - 7840, - 0, - 7842, - 0, - 7843, - 0, - 0, - 0, - 0, - 7844, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7846, - 0, - 0, - 0, - 0, - 0, - 7856, - 7857, - 7858, - 7862, - 0, - 7865, - 0, - 0, - 7866, - 0, - 0, - 7913, - 0, - 0, - 0, - 0, - 7914, - 0, - 0, - 7915, - 7917, - 7918, - 7919, - 0, - 7920, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7921, - 7922, - 0, - 7924, - 0, - 0, - 7925, - 0, - 0, - 7927, - 0, - 7930, - 7935, - 0, - 0, - 7937, - 0, - 0, - 0, - 0, - 0, - 0, - 7939, - 0, - 7940, - 0, - 0, - 0, - 0, - 0, - 7941, - 0, - 0, - 0, - 0, - 7945, - 0, - 0, - 0, - 0, - 7949, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7950, - 0, - 7953, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7968, - 0, - 0, - 0, - 0, - 7969, - 7972, - 7992, - 0, - 7993, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 7994, - 0, - 0, - 0, - 0, - 8007, - 8008, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8010, - 0, - 0, - 0, - 8012, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8018, - 0, - 8028, - 8029, - 0, - 0, - 8030, - 0, - 0, - 8032, - 8033, - 0, - 0, - 8034, - 8036, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8037, - 0, - 0, - 0, - 8043, - 8052, - 8059, - 8060, - 0, - 0, - 8061, - 0, - 0, - 0, - 8062, - 0, - 8063, - 0, - 8064, - 0, - 8066, - 8068, - 0, - 0, - 0, - 8080, - 8081, - 0, - 8089, - 0, - 0, - 0, - 0, - 0, - 8092, - 0, - 0, - 0, - 0, - 0, - 0, - 8093, - 8110, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8111, - 0, - 0, - 0, - 0, - 0, - 8112, - 8115, - 0, - 8117, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8120, - 8121, - 8122, - 8128, - 8129, - 8130, - 8131, - 0, - 0, - 8139, - 0, - 0, - 8144, - 0, - 0, - 0, - 0, - 8145, - 8146, - 8153, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8154, - 0, - 8157, - 8160, - 8162, - 0, - 8164, - 8165, - 0, - 0, - 0, - 0, - 8166, - 8167, - 0, - 0, - 8179, - 0, - 0, - 0, - 8185, - 0, - 0, - 0, - 8186, - 0, - 0, - 8187, - 0, - 0, - 0, - 8188, - 0, - 0, - 0, - 0, - 0, - 8204, - 0, - 0, - 0, - 0, - 8210, - 0, - 0, - 0, - 0, - 0, - 8213, - 0, - 8214, - 0, - 0, - 8215, - 0, - 0, - 0, - 0, - 0, - 0, - 8218, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8219, - 0, - 8221, - 0, - 0, - 8222, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8225, - 0, - 0, - 0, - 8233, - 0, - 0, - 8242, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8247, - 0, - 8248, - 8252, - 0, - 8256, - 8257, - 0, - 0, - 8261, - 0, - 8264, - 8265, - 0, - 0, - 0, - 0, - 8267, - 0, - 0, - 0, - 8269, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8270, - 0, - 0, - 0, - 8278, - 0, - 8279, - 8283, - 0, - 0, - 8285, - 8286, - 8289, - 8292, - 0, - 0, - 0, - 0, - 8293, - 8295, - 8299, - 8300, - 8301, - 0, - 0, - 0, - 0, - 0, - 0, - 8304, - 8307, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8321, - 0, - 0, - 0, - 8322, - 8323, - 8325, - 8326, - 8327, - 0, - 0, - 8332, - 8338, - 0, - 0, - 8340, - 0, - 0, - 0, - 0, - 0, - 8350, - 0, - 0, - 8351, - 0, - 8354, - 8355, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8360, - 8372, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8377, - 0, - 0, - 0, - 0, - 8380, - 0, - 0, - 0, - 8383, - 0, - 8384, - 0, - 0, - 0, - 0, - 8386, - 8392, - 0, - 0, - 8394, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8396, - 8397, - 0, - 8398, - 0, - 8399, - 0, - 0, - 0, - 0, - 0, - 8400, - 0, - 8401, - 8410, - 8411, - 0, - 8412, - 8413, - 8422, - 0, - 0, - 0, - 0, - 8423, - 0, - 0, - 0, - 0, - 8424, - 0, - 0, - 8425, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8441, - 8442, - 0, - 0, - 0, - 0, - 0, - 0, - 8443, - 0, - 0, - 8444, - 0, - 8447, - 0, - 0, - 0, - 0, - 8451, - 0, - 8458, - 0, - 8462, - 0, - 0, - 8468, - 0, - 8469, - 0, - 0, - 0, - 8470, - 0, - 8473, - 8479, - 8480, - 0, - 0, - 0, - 0, - 8481, - 8483, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8484, - 0, - 0, - 8490, - 0, - 0, - 0, - 0, - 0, - 0, - 8491, - 8493, - 8494, - 0, - 8528, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8530, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8534, - 8538, - 8540, - 0, - 0, - 8541, - 0, - 0, - 8545, - 0, - 8557, - 0, - 0, - 8569, - 8570, - 0, - 0, - 8571, - 8574, - 8575, - 8579, - 0, - 8583, - 0, - 0, - 0, - 0, - 8591, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8606, - 0, - 8607, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8608, - 0, - 0, - 8609, - 0, - 0, - 0, - 8610, - 0, - 0, - 0, - 8611, - 0, - 0, - 8613, - 8617, - 8621, - 0, - 0, - 8622, - 0, - 8623, - 0, - 8624, - 8625, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8637, - 8638, - 8639, - 8650, - 0, - 0, - 0, - 0, - 8652, - 8654, - 8655, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8656, - 0, - 0, - 0, - 0, - 0, - 8657, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8658, - 0, - 0, - 8659, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8660, - 0, - 0, - 0, - 0, - 0, - 0, - 8661, - 8663, - 8664, - 0, - 0, - 0, - 0, - 8665, - 0, - 8669, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8671, - 8674, - 0, - 8684, - 0, - 8686, - 0, - 0, - 0, - 8689, - 0, - 0, - 0, - 8690, - 0, - 8706, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8710, - 0, - 8711, - 8713, - 8714, - 8724, - 8727, - 8728, - 8733, - 8736, - 0, - 8737, - 8739, - 0, - 0, - 0, - 0, - 8742, - 8743, - 8745, - 8754, - 0, - 0, - 0, - 0, - 8756, - 0, - 0, - 0, - 0, - 0, - 0, - 8757, - 8760, - 0, - 0, - 0, - 0, - 0, - 8762, - 8763, - 8764, - 0, - 8766, - 8769, - 8770, - 8773, - 0, - 8774, - 0, - 8779, - 0, - 0, - 0, - 0, - 8780, - 0, - 0, - 8781, - 0, - 0, - 8783, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8784, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8785, - 0, - 0, - 0, - 0, - 8786, - 0, - 0, - 0, - 0, - 8788, - 8790, - 0, - 0, - 0, - 8803, - 0, - 8813, - 8814, - 0, - 0, - 0, - 0, - 0, - 8815, - 8816, - 0, - 0, - 0, - 0, - 8818, - 0, - 0, - 0, - 0, - 8822, - 8828, - 8829, - 0, - 8831, - 0, - 0, - 0, - 0, - 8833, - 0, - 0, - 0, - 8834, - 0, - 0, - 0, - 8835, - 0, - 8836, - 0, - 0, - 0, - 8837, - 0, - 0, - 0, - 0, - 0, - 0, - 8838, - 8839, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8840, - 0, - 0, - 0, - 8841, - 0, - 8842, - 0, - 0, - 0, - 8846, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8847, - 0, - 8848, - 0, - 0, - 8864, - 0, - 0, - 8866, - 0, - 0, - 8870, - 8872, - 0, - 0, - 8873, - 8874, - 0, - 0, - 0, - 0, - 0, - 0, - 8875, - 0, - 8876, - 0, - 0, - 0, - 0, - 8896, - 8900, - 0, - 0, - 0, - 0, - 8901, - 0, - 0, - 0, - 0, - 0, - 8904, - 0, - 8907, - 0, - 0, - 0, - 0, - 8911, - 8912, - 8913, - 0, - 0, - 0, - 8914, - 0, - 8915, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8916, - 0, - 0, - 0, - 8929, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 8930, - 0, - 8932, - 0, - 8943, - 0, - 0, - 0, - 8945, - 8947, - 0, - 0, - 0, - 0, - 8949, - 0, - 8950, - 0, - 8954, - 8957, - 0, - 0, - 8970, - 0, - 0, - 0, - 0, - 8971, - 0, - 8996, - 0, - 0, - 0, - 0, - 8997, - 9000, - 0, - 0, - 0, - 0, - 9001, - 9002, - 0, - 9004, - 9009, - 9024, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9027, - 9082, - 0, - 0, - 9083, - 9089, - 0, - 0, - 0, - 0, - 0, - 0, - 9090, - 0, - 0, - 0, - 9092, - 0, - 0, - 9093, - 0, - 9095, - 0, - 0, - 9096, - 9097, - 9101, - 9102, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9112, - 0, - 0, - 0, - 0, - 0, - 0, - 9114, - 0, - 0, - 9120, - 0, - 9121, - 9122, - 0, - 0, - 0, - 9123, - 9124, - 0, - 0, - 9125, - 0, - 0, - 9126, - 0, - 9127, - 0, - 0, - 9129, - 9131, - 0, - 0, - 0, - 9132, - 0, - 0, - 9136, - 0, - 9144, - 0, - 0, - 9148, - 0, - 0, - 0, - 0, - 0, - 0, - 9149, - 0, - 9152, - 9163, - 0, - 0, - 9165, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9166, - 0, - 9169, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9170, - 0, - 0, - 0, - 0, - 9172, - 0, - 9174, - 9175, - 9176, - 0, - 9177, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9186, - 0, - 9187, - 0, - 0, - 0, - 9188, - 9189, - 0, - 0, - 9190, - 0, - 0, - 0, - 0, - 9191, - 0, - 0, - 0, - 9193, - 0, - 0, - 0, - 0, - 9197, - 9198, - 0, - 0, - 0, - 9208, - 9211, - 0, - 0, - 0, - 0, - 9216, - 9217, - 0, - 9220, - 0, - 0, - 0, - 0, - 9221, - 9222, - 9223, - 0, - 9224, - 9225, - 0, - 0, - 9227, - 0, - 9228, - 9229, - 0, - 0, - 9230, - 0, - 9232, - 0, - 9233, - 0, - 0, - 0, - 0, - 0, - 9234, - 9235, - 0, - 0, - 9237, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9238, - 9240, - 0, - 0, - 9241, - 0, - 0, - 0, - 0, - 9244, - 0, - 0, - 0, - 0, - 9247, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9248, - 0, - 0, - 0, - 9249, - 0, - 0, - 0, - 0, - 0, - 9250, - 0, - 0, - 0, - 0, - 9251, - 0, - 0, - 9252, - 9255, - 0, - 0, - 0, - 9256, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9257, - 0, - 0, - 9258, - 0, - 0, - 0, - 0, - 0, - 0, - 9259, - 0, - 0, - 0, - 0, - 0, - 9262, - 9263, - 0, - 0, - 9265, - 9266, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9268, - 9271, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9273, - 0, - 0, - 0, - 9276, - 9277, - 9279, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9280, - 0, - 0, - 9293, - 0, - 0, - 0, - 0, - 0, - 9297, - 9301, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9308, - 9309, - 9313, - 9321, - 9322, - 0, - 9326, - 9327, - 0, - 0, - 9477, - 0, - 9479, - 0, - 0, - 0, - 0, - 9482, - 0, - 0, - 0, - 9483, - 0, - 9484, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9485, - 0, - 0, - 9486, - 0, - 0, - 0, - 9489, - 0, - 0, - 0, - 0, - 9490, - 9491, - 0, - 0, - 0, - 0, - 9493, - 0, - 9495, - 9496, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9500, - 0, - 9502, - 0, - 0, - 0, - 0, - 0, - 9504, - 9507, - 0, - 9509, - 0, - 9511, - 0, - 0, - 9513, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9515, - 0, - 0, - 0, - 0, - 0, - 0, - 9516, - 9517, - 0, - 0, - 0, - 0, - 9532, - 0, - 0, - 9533, - 0, - 0, - 9538, - 0, - 9539, - 9540, - 0, - 0, - 0, - 0, - 9541, - 0, - 0, - 0, - 9542, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9544, - 9545, - 0, - 9546, - 0, - 0, - 0, - 0, - 0, - 0, - 9547, - 9548, - 0, - 0, - 0, - 9550, - 0, - 9557, - 0, - 9558, - 0, - 9561, - 0, - 9563, - 9570, - 0, - 9572, - 9574, - 9575, - 0, - 0, - 0, - 9577, - 9592, - 0, - 0, - 9596, - 0, - 0, - 0, - 9598, - 0, - 9600, - 0, - 9601, - 0, - 0, - 0, - 0, - 0, - 0, - 9608, - 0, - 9638, - 9639, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9641, - 0, - 0, - 9643, - 9644, - 9645, - 9646, - 0, - 0, - 0, - 9648, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9650, - 9654, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9655, - 0, - 0, - 0, - 0, - 0, - 9656, - 0, - 9657, - 0, - 0, - 0, - 0, - 9658, - 0, - 0, - 9659, - 0, - 0, - 9664, - 0, - 0, - 9665, - 0, - 9667, - 9669, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9671, - 0, - 9673, - 9681, - 0, - 0, - 0, - 0, - 9682, - 9683, - 9684, - 0, - 0, - 0, - 0, - 9686, - 9698, - 0, - 0, - 9700, - 9701, - 9702, - 0, - 9703, - 9717, - 0, - 0, - 0, - 0, - 9718, - 0, - 9726, - 0, - 0, - 0, - 0, - 9727, - 0, - 0, - 0, - 9728, - 0, - 9742, - 0, - 9744, - 0, - 0, - 0, - 9750, - 0, - 9754, - 9755, - 0, - 0, - 0, - 0, - 0, - 9756, - 0, - 9757, - 9768, - 0, - 9769, - 0, - 0, - 0, - 9770, - 9771, - 0, - 9773, - 0, - 9774, - 0, - 9775, - 0, - 0, - 0, - 9776, - 9777, - 9784, - 0, - 0, - 0, - 9786, - 0, - 9789, - 0, - 0, - 0, - 0, - 9793, - 9794, - 0, - 0, - 0, - 9808, - 0, - 0, - 0, - 0, - 0, - 9811, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9812, - 0, - 9820, - 0, - 9823, - 0, - 9828, - 0, - 0, - 0, - 0, - 9830, - 0, - 0, - 9833, - 9836, - 0, - 0, - 0, - 9840, - 0, - 0, - 0, - 9841, - 0, - 0, - 9842, - 0, - 9845, - 0, - 0, - 0, - 9847, - 9848, - 0, - 0, - 9855, - 0, - 0, - 0, - 0, - 0, - 0, - 9856, - 9863, - 9865, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9866, - 9867, - 9868, - 9873, - 9875, - 0, - 0, - 0, - 0, - 0, - 0, - 9880, - 0, - 9886, - 0, - 0, - 0, - 9887, - 0, - 0, - 9891, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9906, - 9907, - 9908, - 0, - 0, - 0, - 9909, - 0, - 0, - 0, - 0, - 0, - 0, - 9910, - 0, - 0, - 0, - 0, - 9913, - 0, - 0, - 0, - 0, - 9914, - 0, - 0, - 0, - 0, - 0, - 9922, - 0, - 0, - 0, - 0, - 9923, - 9925, - 0, - 0, - 0, - 0, - 0, - 0, - 9930, - 0, - 0, - 0, - 9931, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9932, - 0, - 9939, - 0, - 0, - 9940, - 9962, - 9966, - 0, - 9969, - 9970, - 0, - 0, - 9974, - 0, - 9979, - 9981, - 9982, - 0, - 0, - 0, - 9985, - 0, - 0, - 0, - 0, - 0, - 0, - 9987, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 9988, - 9993, - 0, - 0, - 9994, - 0, - 0, - 0, - 9997, - 0, - 10004, - 0, - 0, - 0, - 0, - 0, - 10007, - 10019, - 10020, - 10022, - 0, - 0, - 0, - 10031, - 0, - 0, - 0, - 0, - 0, - 10032, - 0, - 0, - 10034, - 0, - 10036, - 0, - 0, - 0, - 0, - 10038, - 0, - 10039, - 10040, - 10041, - 10042, - 0, - 0, - 0, - 0, - 0, - 10043, - 0, - 0, - 0, - 0, - 0, - 10045, - 10054, - 0, - 0, - 0, - 0, - 10055, - 0, - 0, - 10057, - 10058, - 0, - 0, - 0, - 0, - 0, - 0, - 10059, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10060, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10063, - 0, - 10066, - 0, - 0, - 0, - 10070, - 0, - 10072, - 0, - 0, - 10076, - 10077, - 0, - 0, - 10084, - 0, - 10087, - 10090, - 10091, - 0, - 0, - 0, - 10094, - 10097, - 0, - 0, - 0, - 0, - 0, - 0, - 10098, - 0, - 0, - 0, - 0, - 0, - 0, - 10103, - 0, - 10104, - 0, - 10108, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10120, - 0, - 0, - 0, - 10122, - 0, - 0, - 10125, - 0, - 0, - 0, - 0, - 10127, - 10128, - 0, - 0, - 10134, - 0, - 10135, - 10136, - 0, - 10137, - 0, - 0, - 10147, - 0, - 10149, - 10150, - 0, - 0, - 10156, - 0, - 10158, - 10159, - 10160, - 10168, - 0, - 0, - 10171, - 0, - 10173, - 0, - 0, - 0, - 10176, - 0, - 0, - 0, - 0, - 10177, - 0, - 0, - 0, - 0, - 10178, - 0, - 0, - 0, - 0, - 10194, - 0, - 10202, - 0, - 0, - 10203, - 10204, - 0, - 10205, - 10206, - 0, - 10207, - 0, - 0, - 0, - 0, - 10209, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10213, - 0, - 0, - 0, - 0, - 0, - 0, - 10217, - 0, - 10229, - 0, - 10230, - 10231, - 0, - 0, - 10232, - 0, - 0, - 10237, - 10238, - 10244, - 0, - 0, - 0, - 0, - 0, - 10250, - 0, - 10252, - 0, - 0, - 0, - 0, - 0, - 0, - 10255, - 0, - 0, - 10257, - 0, - 0, - 0, - 0, - 0, - 0, - 10258, - 0, - 10259, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10260, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10284, - 10288, - 10289, - 0, - 0, - 0, - 10290, - 0, - 10296, - 0, - 0, - 0, - 0, - 0, - 10297, - 0, - 0, - 0, - 0, - 0, - 0, - 10298, - 0, - 0, - 0, - 0, - 10299, - 10303, - 0, - 0, - 0, - 0, - 0, - 10306, - 0, - 0, - 0, - 10307, - 0, - 10308, - 0, - 0, - 0, - 0, - 10311, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10315, - 10317, - 0, - 0, - 0, - 10318, - 10319, - 0, - 10321, - 0, - 10326, - 0, - 10328, - 0, - 0, - 0, - 0, - 10329, - 0, - 0, - 10331, - 0, - 10332, - 0, - 0, - 0, - 0, - 0, - 0, - 10334, - 0, - 0, - 10335, - 10338, - 0, - 0, - 0, - 0, - 0, - 10339, - 10349, - 0, - 0, - 0, - 0, - 0, - 0, - 10351, - 0, - 10353, - 0, - 0, - 0, - 0, - 0, - 0, - 10362, - 0, - 10368, - 0, - 10369, - 0, - 0, - 0, - 10372, - 10373, - 0, - 0, - 0, - 0, - 0, - 10374, - 0, - 0, - 0, - 10375, - 0, - 10376, - 0, - 0, - 10386, - 10388, - 10390, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10391, - 0, - 0, - 10392, - 10394, - 0, - 0, - 10396, - 0, - 10397, - 0, - 10403, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10404, - 0, - 10405, - 10410, - 0, - 0, - 10411, - 0, - 10412, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10421, - 10422, - 10423, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10425, - 0, - 0, - 10427, - 0, - 0, - 10430, - 0, - 0, - 0, - 0, - 0, - 10432, - 0, - 10433, - 10434, - 0, - 0, - 0, - 0, - 10436, - 10437, - 0, - 10438, - 0, - 10439, - 0, - 10444, - 10446, - 0, - 0, - 0, - 0, - 0, - 10448, - 0, - 0, - 0, - 0, - 0, - 10449, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10451, - 0, - 10453, - 0, - 0, - 0, - 10454, - 10457, - 0, - 0, - 10459, - 0, - 10469, - 0, - 0, - 0, - 0, - 0, - 10472, - 10481, - 0, - 0, - 0, - 0, - 0, - 10482, - 10483, - 0, - 10492, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10499, - 0, - 0, - 0, - 10502, - 0, - 0, - 10510, - 0, - 10521, - 10524, - 0, - 0, - 10525, - 10526, - 10528, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10530, - 0, - 0, - 0, - 0, - 10533, - 0, - 10534, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10535, - 10536, - 0, - 0, - 10544, - 0, - 10553, - 10556, - 0, - 10557, - 10559, - 0, - 0, - 0, - 0, - 0, - 10562, - 10563, - 10564, - 0, - 10565, - 0, - 0, - 0, - 10566, - 0, - 10567, - 0, - 0, - 0, - 0, - 10575, - 0, - 0, - 10576, - 0, - 10578, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10585, - 10586, - 10587, - 10589, - 0, - 10590, - 0, - 0, - 10594, - 0, - 0, - 0, - 0, - 0, - 10598, - 0, - 0, - 10601, - 0, - 0, - 0, - 10602, - 0, - 10603, - 0, - 10604, - 0, - 10605, - 0, - 0, - 10607, - 0, - 10626, - 0, - 10627, - 0, - 0, - 0, - 0, - 0, - 10629, - 10630, - 10631, - 0, - 0, - 0, - 10646, - 0, - 0, - 0, - 10647, - 0, - 10650, - 0, - 10651, - 0, - 0, - 0, - 10652, - 10653, - 10655, - 0, - 10658, - 0, - 0, - 10659, - 0, - 10667, - 0, - 0, - 0, - 0, - 10669, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10670, - 0, - 0, - 0, - 10671, - 0, - 0, - 0, - 0, - 10672, - 10673, - 0, - 10674, - 0, - 0, - 0, - 10676, - 0, - 0, - 0, - 0, - 0, - 0, - 10678, - 0, - 10682, - 0, - 0, - 10692, - 0, - 10697, - 0, - 0, - 0, - 0, - 10698, - 0, - 0, - 0, - 10700, - 0, - 0, - 0, - 0, - 0, - 10703, - 0, - 10704, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10705, - 0, - 10715, - 10718, - 10720, - 0, - 0, - 10722, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10723, - 0, - 0, - 0, - 0, - 10726, - 0, - 0, - 0, - 0, - 0, - 10727, - 10730, - 10743, - 0, - 0, - 0, - 0, - 0, - 0, - 10744, - 0, - 0, - 10745, - 0, - 0, - 0, - 0, - 0, - 0, - 10748, - 0, - 0, - 0, - 0, - 10750, - 0, - 0, - 10752, - 10753, - 0, - 0, - 0, - 10756, - 0, - 0, - 0, - 0, - 0, - 0, - 10758, - 0, - 0, - 0, - 10759, - 0, - 10769, - 0, - 0, - 10772, - 0, - 0, - 0, - 0, - 0, - 0, - 10773, - 0, - 0, - 0, - 10777, - 0, - 0, - 10779, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10780, - 10784, - 0, - 0, - 0, - 10789, - 0, - 0, - 0, - 10791, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10795, - 0, - 0, - 10796, - 0, - 10808, - 0, - 10809, - 0, - 0, - 0, - 10810, - 0, - 0, - 0, - 10812, - 0, - 0, - 10814, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10815, - 0, - 0, - 0, - 0, - 10816, - 10817, - 0, - 0, - 0, - 0, - 10819, - 0, - 10820, - 0, - 0, - 0, - 0, - 10821, - 10822, - 10823, - 0, - 10826, - 10849, - 0, - 0, - 0, - 0, - 10850, - 0, - 0, - 10852, - 0, - 10853, - 0, - 0, - 10856, - 0, - 0, - 10857, - 10858, - 10859, - 10860, - 0, - 0, - 0, - 0, - 0, - 0, - 10863, - 0, - 10866, - 10867, - 10872, - 10890, - 0, - 0, - 10891, - 10892, - 0, - 0, - 0, - 0, - 0, - 10893, - 0, - 0, - 0, - 10896, - 10899, - 0, - 0, - 10900, - 10902, - 0, - 0, - 0, - 0, - 0, - 10903, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10905, - 0, - 10906, - 0, - 0, - 0, - 0, - 10908, - 10911, - 0, - 10912, - 0, - 0, - 10916, - 0, - 0, - 0, - 0, - 0, - 10917, - 0, - 10918, - 0, - 0, - 0, - 10923, - 0, - 0, - 0, - 0, - 0, - 10924, - 0, - 0, - 10928, - 10929, - 0, - 0, - 10930, - 0, - 0, - 0, - 10932, - 0, - 0, - 0, - 0, - 10939, - 0, - 0, - 10945, - 0, - 0, - 0, - 10947, - 0, - 0, - 10948, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10958, - 0, - 10960, - 10962, - 0, - 0, - 10964, - 0, - 0, - 0, - 10966, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 10967, - 0, - 0, - 0, - 10968, - 0, - 0, - 0, - 10973, - 0, - 0, - 0, - 0, - 0, - 10975, - 0, - 0, - 0, - 10976, - 10978, - 0, - 0, - 10982, - 10984, - 10987, - 0, - 0, - 10988, - 0, - 10989, - 0, - 0, - 10991, - 0, - 0, - 0, - 0, - 10992, - 0, - 0, - 0, - 10993, - 0, - 10995, - 0, - 0, - 0, - 10996, - 10997, - 0, - 0, - 0, - 10998, - 0, - 10999, - 0, - 11001, - 0, - 0, - 0, - 0, - 0, - 0, - 11010, - 11012, - 0, - 11013, - 11016, - 11017, - 0, - 0, - 11019, - 11020, - 11021, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11022, - 0, - 0, - 11023, - 11029, - 0, - 0, - 0, - 0, - 11031, - 0, - 0, - 0, - 11034, - 0, - 0, - 0, - 0, - 11055, - 0, - 0, - 0, - 0, - 0, - 11056, - 11060, - 0, - 0, - 0, - 0, - 0, - 0, - 11061, - 0, - 0, - 11064, - 11065, - 0, - 11066, - 0, - 11069, - 0, - 11085, - 0, - 0, - 0, - 0, - 0, - 11086, - 0, - 0, - 0, - 11088, - 0, - 0, - 0, - 11094, - 0, - 0, - 0, - 11095, - 11096, - 0, - 0, - 0, - 0, - 0, - 0, - 11097, - 11098, - 0, - 0, - 0, - 0, - 0, - 0, - 11099, - 0, - 0, - 11102, - 11108, - 0, - 0, - 0, - 11109, - 0, - 11114, - 11119, - 0, - 11131, - 0, - 0, - 0, - 11142, - 0, - 0, - 11143, - 0, - 11146, - 0, - 11147, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11148, - 0, - 11149, - 11152, - 11153, - 11154, - 0, - 11156, - 0, - 11157, - 0, - 0, - 0, - 11158, - 0, - 0, - 11159, - 11160, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11163, - 0, - 0, - 11164, - 11166, - 0, - 0, - 0, - 11172, - 11174, - 0, - 0, - 0, - 11176, - 0, - 0, - 0, - 0, - 0, - 11182, - 11183, - 0, - 0, - 0, - 11184, - 11187, - 0, - 0, - 11188, - 11189, - 0, - 0, - 0, - 0, - 0, - 0, - 11194, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11200, - 11202, - 0, - 0, - 0, - 0, - 0, - 0, - 11203, - 0, - 11204, - 0, - 0, - 0, - 0, - 0, - 11205, - 0, - 0, - 0, - 11206, - 0, - 11207, - 0, - 0, - 11209, - 0, - 11211, - 0, - 11214, - 0, - 0, - 11231, - 0, - 0, - 0, - 11293, - 11295, - 0, - 0, - 11296, - 11297, - 11302, - 0, - 0, - 0, - 11307, - 0, - 0, - 0, - 0, - 11309, - 11310, - 0, - 11311, - 0, - 0, - 0, - 11313, - 0, - 11314, - 0, - 0, - 0, - 0, - 11334, - 0, - 11338, - 0, - 0, - 0, - 11339, - 0, - 0, - 0, - 0, - 0, - 11340, - 0, - 11341, - 11342, - 0, - 11344, - 0, - 11345, - 0, - 0, - 0, - 11348, - 11349, - 0, - 0, - 11350, - 0, - 0, - 0, - 11355, - 0, - 0, - 0, - 0, - 0, - 0, - 11356, - 0, - 11357, - 11370, - 0, - 0, - 11371, - 0, - 11374, - 11376, - 0, - 0, - 0, - 11377, - 0, - 0, - 11378, - 11383, - 0, - 11386, - 11399, - 0, - 11400, - 11406, - 0, - 0, - 0, - 11408, - 0, - 0, - 11409, - 11412, - 0, - 0, - 0, - 0, - 11417, - 0, - 0, - 0, - 11418, - 0, - 11421, - 0, - 11426, - 11429, - 0, - 0, - 0, - 0, - 0, - 11430, - 0, - 11437, - 0, - 11438, - 0, - 0, - 0, - 0, - 0, - 11440, - 11453, - 0, - 0, - 0, - 0, - 0, - 0, - 11454, - 0, - 0, - 0, - 0, - 11455, - 0, - 0, - 11456, - 11460, - 11461, - 11463, - 0, - 11469, - 0, - 11473, - 0, - 0, - 0, - 0, - 11474, - 0, - 0, - 0, - 11475, - 0, - 11476, - 11477, - 11480, - 0, - 0, - 0, - 0, - 11481, - 0, - 0, - 11484, - 0, - 0, - 11487, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11497, - 0, - 0, - 11502, - 0, - 11509, - 0, - 0, - 11510, - 11511, - 11513, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11515, - 0, - 0, - 0, - 0, - 11516, - 0, - 11520, - 11521, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11529, - 11530, - 11531, - 11534, - 0, - 0, - 11543, - 0, - 0, - 0, - 0, - 0, - 11547, - 0, - 11548, - 0, - 0, - 0, - 0, - 0, - 11552, - 11556, - 0, - 11557, - 0, - 0, - 11559, - 0, - 11560, - 0, - 0, - 0, - 0, - 0, - 0, - 11561, - 0, - 0, - 11563, - 11564, - 0, - 11565, - 0, - 0, - 0, - 0, - 11567, - 0, - 0, - 0, - 11569, - 0, - 11574, - 0, - 11575, - 0, - 0, - 0, - 11577, - 0, - 11578, - 0, - 0, - 0, - 11580, - 11581, - 0, - 0, - 0, - 11582, - 11584, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11587, - 0, - 11588, - 11591, - 0, - 11595, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11596, - 0, - 11597, - 0, - 0, - 0, - 0, - 11598, - 11601, - 0, - 0, - 0, - 11602, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11603, - 11604, - 0, - 11606, - 0, - 0, - 11608, - 0, - 0, - 0, - 0, - 11610, - 0, - 0, - 11611, - 0, - 0, - 0, - 0, - 11613, - 0, - 11622, - 0, - 0, - 0, - 11623, - 0, - 0, - 0, - 0, - 11625, - 0, - 0, - 11626, - 11627, - 11628, - 11630, - 0, - 0, - 0, - 0, - 0, - 0, - 11639, - 0, - 0, - 11646, - 0, - 11648, - 11649, - 0, - 11650, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11651, - 0, - 0, - 11652, - 11653, - 11656, - 0, - 0, - 11677, - 11679, - 0, - 0, - 0, - 0, - 11680, - 0, - 0, - 11681, - 0, - 11685, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11688, - 0, - 0, - 0, - 11716, - 0, - 11719, - 0, - 0, - 0, - 0, - 0, - 11721, - 0, - 0, - 11724, - 11743, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11745, - 11748, - 11750, - 0, - 0, - 0, - 0, - 0, - 11751, - 0, - 0, - 0, - 11752, - 11754, - 0, - 11755, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11759, - 0, - 0, - 0, - 0, - 0, - 0, - 11760, - 0, - 0, - 0, - 11761, - 0, - 0, - 0, - 0, - 0, - 0, - 11766, - 11767, - 0, - 11772, - 11773, - 0, - 11774, - 0, - 0, - 11775, - 0, - 11777, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11778, - 11780, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11783, - 0, - 11784, - 0, - 0, - 0, - 11785, - 0, - 0, - 0, - 11786, - 0, - 0, - 0, - 0, - 11788, - 0, - 0, - 11789, - 11791, - 11792, - 0, - 0, - 0, - 0, - 11795, - 11834, - 11835, - 11836, - 0, - 0, - 11837, - 0, - 0, - 0, - 11838, - 0, - 0, - 11846, - 11851, - 0, - 11852, - 0, - 11869, - 0, - 0, - 0, - 11871, - 0, - 0, - 0, - 11872, - 11874, - 0, - 0, - 0, - 0, - 0, - 0, - 11875, - 0, - 11876, - 11877, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11883, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11884, - 0, - 11885, - 0, - 11886, - 0, - 0, - 11887, - 0, - 11894, - 11895, - 11897, - 11909, - 11910, - 0, - 11912, - 11918, - 0, - 0, - 11920, - 0, - 11922, - 11924, - 11927, - 11928, - 0, - 0, - 0, - 0, - 11929, - 0, - 11934, - 0, - 0, - 0, - 0, - 0, - 11941, - 11943, - 11944, - 0, - 11945, - 0, - 0, - 0, - 0, - 11948, - 11949, - 0, - 0, - 0, - 0, - 11953, - 0, - 11954, - 0, - 11955, - 0, - 11956, - 0, - 0, - 0, - 0, - 0, - 11957, - 0, - 0, - 11959, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 11961, - 0, - 0, - 0, - 0, - 0, - 11978, - 0, - 0, - 0, - 11979, - 11980, - 11986, - 11987, - 0, - 11992, - 0, - 0, - 0, - 0, - 0, - 11993, - 0, - 0, - 0, - 11994, - 0, - 11999, - 12004, - 12005, - 12006, - 0, - 0, - 0, - 0, - 0, - 12011, - 0, - 0, - 12012, - 12014, - 0, - 0, - 12015, - 0, - 0, - 12019, - 12028, - 0, - 0, - 12029, - 0, - 0, - 12032, - 12033, - 0, - 0, - 0, - 0, - 12034, - 0, - 12041, - 12043, - 0, - 0, - 12044, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12046, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12054, - 12055, - 0, - 12056, - 0, - 0, - 0, - 12060, - 12064, - 0, - 0, - 0, - 0, - 0, - 12065, - 12067, - 12068, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12074, - 0, - 0, - 0, - 12075, - 12076, - 0, - 0, - 0, - 12079, - 0, - 12081, - 12086, - 12087, - 0, - 0, - 12088, - 0, - 0, - 0, - 0, - 12089, - 0, - 12092, - 0, - 0, - 0, - 0, - 12097, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12098, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12102, - 12103, - 12104, - 12111, - 0, - 0, - 12114, - 12116, - 0, - 0, - 0, - 12118, - 0, - 0, - 0, - 12119, - 12120, - 12128, - 0, - 0, - 0, - 0, - 12130, - 0, - 0, - 0, - 0, - 0, - 0, - 12131, - 0, - 0, - 0, - 12132, - 12134, - 0, - 0, - 0, - 0, - 12137, - 0, - 12139, - 0, - 12141, - 0, - 0, - 12142, - 0, - 0, - 0, - 12144, - 0, - 0, - 0, - 0, - 0, - 12145, - 0, - 12148, - 0, - 12153, - 0, - 0, - 0, - 0, - 12154, - 12171, - 12173, - 0, - 0, - 0, - 12175, - 0, - 0, - 0, - 0, - 12178, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12183, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12184, - 0, - 0, - 0, - 12186, - 0, - 0, - 0, - 0, - 0, - 12187, - 12188, - 0, - 0, - 12189, - 0, - 12196, - 0, - 12197, - 0, - 0, - 12198, - 0, - 12201, - 0, - 0, - 0, - 0, - 12203, - 0, - 12209, - 0, - 0, - 0, - 0, - 12210, - 12211, - 12212, - 12213, - 0, - 12217, - 12218, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12222, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12223, - 0, - 0, - 12229, - 0, - 0, - 0, - 0, - 12233, - 0, - 0, - 0, - 0, - 12234, - 0, - 0, - 12236, - 12242, - 0, - 0, - 0, - 12243, - 0, - 0, - 0, - 12244, - 12253, - 0, - 12254, - 12256, - 0, - 12257, - 0, - 0, - 12275, - 0, - 0, - 0, - 0, - 0, - 12277, - 0, - 0, - 0, - 0, - 0, - 12278, - 0, - 12289, - 0, - 0, - 12290, - 0, - 12292, - 12293, - 0, - 0, - 12294, - 0, - 12295, - 0, - 0, - 12296, - 0, - 12297, - 0, - 12298, - 0, - 0, - 0, - 0, - 12301, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12309, - 0, - 12338, - 12340, - 0, - 0, - 0, - 0, - 12341, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12342, - 12343, - 0, - 12344, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12345, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12346, - 0, - 0, - 0, - 0, - 12348, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12350, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12351, - 0, - 12355, - 12356, - 12357, - 0, - 0, - 12367, - 12370, - 12371, - 0, - 0, - 0, - 0, - 0, - 12372, - 12376, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12379, - 0, - 12382, - 0, - 12383, - 0, - 0, - 12384, - 0, - 0, - 0, - 0, - 12393, - 0, - 0, - 12394, - 0, - 0, - 0, - 0, - 12398, - 12403, - 0, - 0, - 12404, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12410, - 0, - 0, - 0, - 12411, - 0, - 0, - 0, - 12412, - 0, - 0, - 0, - 0, - 12420, - 0, - 12421, - 0, - 0, - 0, - 0, - 0, - 12423, - 0, - 12425, - 12429, - 0, - 0, - 0, - 12431, - 12432, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12434, - 0, - 0, - 0, - 0, - 0, - 12435, - 12436, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12437, - 0, - 0, - 0, - 0, - 0, - 12438, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12445, - 0, - 0, - 0, - 12450, - 12451, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12452, - 12475, - 0, - 0, - 12493, - 12494, - 0, - 0, - 0, - 12495, - 0, - 0, - 0, - 0, - 12496, - 12502, - 12509, - 0, - 0, - 0, - 0, - 12510, - 0, - 12512, - 12513, - 0, - 0, - 0, - 0, - 12514, - 0, - 0, - 0, - 12515, - 0, - 12520, - 0, - 0, - 0, - 12524, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12527, - 0, - 0, - 0, - 12528, - 0, - 0, - 0, - 12529, - 0, - 0, - 0, - 0, - 0, - 12530, - 0, - 12535, - 0, - 0, - 12536, - 0, - 12538, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12540, - 0, - 12548, - 0, - 0, - 0, - 0, - 0, - 12550, - 0, - 0, - 0, - 12551, - 12552, - 0, - 0, - 0, - 12554, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12555, - 0, - 0, - 12562, - 0, - 12565, - 0, - 12566, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12569, - 0, - 0, - 0, - 12571, - 12574, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12577, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12578, - 12579, - 12603, - 0, - 12608, - 0, - 0, - 12611, - 0, - 12612, - 0, - 12615, - 0, - 12625, - 0, - 0, - 0, - 0, - 12627, - 12646, - 0, - 12648, - 0, - 0, - 12657, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12670, - 0, - 0, - 12671, - 0, - 12673, - 12677, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12679, - 0, - 12681, - 0, - 12682, - 12693, - 0, - 12694, - 0, - 12697, - 0, - 12701, - 0, - 0, - 0, - 12703, - 12704, - 0, - 0, - 0, - 0, - 12707, - 12737, - 0, - 0, - 12739, - 0, - 0, - 12740, - 0, - 0, - 12742, - 12743, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12745, - 0, - 12746, - 12747, - 0, - 12748, - 0, - 0, - 12759, - 12767, - 0, - 0, - 0, - 0, - 12773, - 0, - 12774, - 12778, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12779, - 0, - 0, - 0, - 0, - 0, - 12780, - 12793, - 0, - 12824, - 0, - 12825, - 0, - 12836, - 0, - 0, - 0, - 0, - 12839, - 0, - 12842, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12843, - 12845, - 0, - 12846, - 0, - 0, - 0, - 0, - 12847, - 0, - 0, - 12850, - 12852, - 12853, - 0, - 0, - 0, - 12854, - 0, - 0, - 0, - 12855, - 0, - 12856, - 0, - 12858, - 0, - 0, - 12859, - 0, - 12862, - 0, - 12863, - 0, - 0, - 12866, - 0, - 12869, - 12872, - 12873, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12875, - 0, - 12877, - 0, - 0, - 12878, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12884, - 12885, - 12888, - 0, - 12889, - 0, - 0, - 0, - 0, - 12893, - 0, - 0, - 0, - 12895, - 12896, - 12898, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12902, - 0, - 12909, - 12910, - 0, - 12926, - 0, - 12928, - 0, - 0, - 0, - 12929, - 0, - 12930, - 0, - 0, - 0, - 0, - 12931, - 0, - 12932, - 12933, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12934, - 0, - 12942, - 0, - 0, - 0, - 0, - 12944, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12946, - 0, - 0, - 12948, - 0, - 0, - 12949, - 0, - 0, - 0, - 0, - 12950, - 0, - 0, - 0, - 0, - 12951, - 0, - 12952, - 0, - 12953, - 0, - 0, - 0, - 12954, - 12958, - 12959, - 0, - 0, - 0, - 0, - 0, - 12960, - 12964, - 0, - 0, - 0, - 0, - 0, - 12966, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 12970, - 0, - 12971, - 0, - 0, - 0, - 0, - 0, - 0, - 12972, - 0, - 0, - 12982, - 0, - 0, - 0, - 12984, - 12985, - 0, - 12986, - 12996, - 12997, - 13001, - 13002, - 0, - 0, - 0, - 0, - 13004, - 0, - 0, - 13005, - 0, - 0, - 13007, - 13009, - 0, - 13017, - 0, - 0, - 0, - 13020, - 0, - 13021, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13022, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13024, - 13027, - 0, - 0, - 0, - 0, - 0, - 13028, - 0, - 0, - 13029, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13032, - 0, - 13037, - 0, - 0, - 0, - 0, - 0, - 0, - 13040, - 0, - 0, - 13041, - 0, - 0, - 0, - 13043, - 13044, - 13046, - 0, - 0, - 0, - 0, - 13047, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13049, - 13054, - 0, - 13056, - 0, - 0, - 13060, - 13061, - 0, - 0, - 0, - 0, - 0, - 13067, - 0, - 0, - 13068, - 0, - 13071, - 0, - 0, - 0, - 0, - 0, - 13077, - 13078, - 0, - 0, - 0, - 0, - 0, - 13079, - 13080, - 13081, - 0, - 13082, - 0, - 0, - 0, - 13085, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13086, - 0, - 13087, - 13088, - 0, - 0, - 0, - 0, - 0, - 13094, - 0, - 13099, - 0, - 13100, - 0, - 0, - 0, - 13101, - 0, - 13125, - 13126, - 13128, - 13129, - 0, - 0, - 13130, - 0, - 13131, - 0, - 0, - 0, - 0, - 0, - 0, - 13134, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13150, - 0, - 13168, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13169, - 0, - 0, - 13170, - 0, - 0, - 0, - 0, - 13174, - 0, - 0, - 0, - 13176, - 0, - 0, - 0, - 0, - 0, - 13177, - 0, - 13178, - 13183, - 13187, - 0, - 0, - 0, - 13189, - 0, - 0, - 13190, - 0, - 0, - 13191, - 0, - 0, - 13206, - 0, - 0, - 0, - 13207, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13212, - 0, - 0, - 13219, - 13232, - 0, - 0, - 0, - 13241, - 0, - 13249, - 13253, - 0, - 0, - 0, - 0, - 0, - 13255, - 13259, - 0, - 13260, - 13261, - 0, - 13262, - 0, - 13272, - 0, - 0, - 0, - 0, - 13276, - 0, - 0, - 0, - 0, - 13277, - 13299, - 0, - 0, - 13301, - 13302, - 0, - 0, - 13303, - 0, - 0, - 13305, - 0, - 13310, - 0, - 0, - 0, - 13311, - 0, - 0, - 0, - 0, - 13325, - 0, - 13328, - 0, - 0, - 0, - 13329, - 0, - 0, - 0, - 0, - 0, - 0, - 13330, - 0, - 0, - 13331, - 0, - 13335, - 0, - 0, - 13342, - 0, - 0, - 0, - 0, - 0, - 13343, - 0, - 13354, - 0, - 13362, - 0, - 13366, - 13367, - 13369, - 0, - 0, - 13371, - 13372, - 0, - 13373, - 13374, - 0, - 13376, - 0, - 13380, - 13381, - 13386, - 0, - 13387, - 13388, - 0, - 13389, - 13391, - 13395, - 0, - 0, - 0, - 0, - 0, - 13401, - 13409, - 0, - 13410, - 0, - 0, - 0, - 0, - 13420, - 0, - 0, - 0, - 0, - 0, - 13422, - 0, - 0, - 0, - 0, - 13423, - 0, - 0, - 0, - 0, - 13425, - 0, - 0, - 0, - 0, - 0, - 13427, - 0, - 0, - 0, - 13428, - 0, - 0, - 13430, - 13438, - 0, - 13439, - 0, - 13445, - 0, - 13448, - 13449, - 0, - 0, - 0, - 0, - 0, - 0, - 13451, - 0, - 13457, - 0, - 0, - 0, - 0, - 13458, - 13459, - 0, - 13460, - 0, - 0, - 0, - 0, - 13464, - 13465, - 13466, - 13470, - 0, - 13471, - 13472, - 13474, - 13475, - 0, - 13476, - 0, - 0, - 13478, - 13479, - 0, - 13481, - 0, - 0, - 0, - 0, - 13487, - 0, - 13490, - 0, - 13493, - 0, - 0, - 13494, - 0, - 0, - 13495, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13496, - 13497, - 0, - 13500, - 0, - 0, - 13516, - 13522, - 0, - 0, - 13525, - 13528, - 0, - 0, - 0, - 13530, - 13535, - 0, - 13537, - 13539, - 0, - 13540, - 0, - 13543, - 0, - 13544, - 0, - 0, - 0, - 0, - 0, - 0, - 13545, - 0, - 0, - 0, - 0, - 0, - 0, - 13547, - 0, - 0, - 0, - 13549, - 13555, - 0, - 0, - 0, - 13556, - 13557, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13558, - 0, - 13563, - 0, - 0, - 0, - 0, - 13564, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13566, - 0, - 0, - 0, - 0, - 0, - 0, - 13569, - 0, - 0, - 13571, - 0, - 0, - 0, - 0, - 13573, - 0, - 0, - 0, - 0, - 0, - 0, - 13578, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13581, - 0, - 13586, - 0, - 13595, - 0, - 13600, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13601, - 13603, - 0, - 13604, - 13605, - 13606, - 13607, - 0, - 0, - 13617, - 13618, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13623, - 0, - 13625, - 13627, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13629, - 0, - 0, - 0, - 13634, - 0, - 0, - 0, - 13638, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13654, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13656, - 0, - 13659, - 0, - 0, - 13660, - 0, - 0, - 13662, - 0, - 0, - 0, - 13663, - 0, - 13664, - 0, - 0, - 0, - 0, - 0, - 13668, - 0, - 13669, - 13671, - 0, - 0, - 13672, - 0, - 0, - 0, - 0, - 0, - 0, - 13675, - 13685, - 0, - 13686, - 0, - 0, - 0, - 13687, - 0, - 0, - 0, - 13692, - 13694, - 13697, - 0, - 0, - 0, - 13702, - 0, - 0, - 0, - 0, - 0, - 13705, - 0, - 0, - 0, - 0, - 13707, - 0, - 0, - 0, - 13714, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13715, - 0, - 13716, - 13717, - 0, - 0, - 13719, - 13724, - 13730, - 13731, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13732, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13734, - 0, - 13736, - 0, - 0, - 13737, - 13738, - 13747, - 0, - 13751, - 0, - 0, - 13752, - 0, - 0, - 0, - 13753, - 0, - 13757, - 0, - 0, - 13762, - 13763, - 0, - 13764, - 13765, - 0, - 13766, - 0, - 0, - 13767, - 0, - 0, - 0, - 13768, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13769, - 0, - 0, - 13772, - 0, - 13775, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13776, - 13778, - 13787, - 0, - 0, - 0, - 13797, - 0, - 13798, - 0, - 13801, - 0, - 13804, - 13806, - 0, - 0, - 0, - 0, - 13816, - 13817, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13834, - 0, - 13836, - 0, - 0, - 13838, - 0, - 0, - 13839, - 0, - 13840, - 0, - 0, - 0, - 0, - 13842, - 0, - 0, - 0, - 0, - 0, - 0, - 13843, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13845, - 0, - 0, - 0, - 0, - 0, - 13858, - 0, - 0, - 13860, - 0, - 0, - 13861, - 0, - 0, - 13862, - 13863, - 0, - 13868, - 0, - 13869, - 13870, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13872, - 0, - 0, - 0, - 0, - 13873, - 13878, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13886, - 0, - 13888, - 13889, - 13890, - 0, - 0, - 13891, - 13894, - 0, - 13897, - 13899, - 13900, - 13904, - 0, - 0, - 13906, - 0, - 0, - 0, - 13909, - 0, - 0, - 0, - 13910, - 0, - 0, - 0, - 13911, - 0, - 0, - 0, - 0, - 0, - 13912, - 13917, - 0, - 0, - 0, - 0, - 13918, - 0, - 13919, - 0, - 0, - 13920, - 0, - 0, - 0, - 13921, - 0, - 0, - 13922, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13924, - 0, - 13927, - 0, - 0, - 0, - 0, - 0, - 13932, - 0, - 13933, - 0, - 13934, - 0, - 0, - 13935, - 0, - 13944, - 0, - 0, - 0, - 13954, - 0, - 0, - 13955, - 0, - 0, - 0, - 0, - 13956, - 0, - 13957, - 0, - 13967, - 13969, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 13970, - 13990, - 0, - 13991, - 13994, - 0, - 13995, - 0, - 0, - 0, - 0, - 13996, - 0, - 0, - 13999, - 0, - 0, - 0, - 14018, - 0, - 14019, - 0, - 14021, - 0, - 0, - 0, - 0, - 0, - 0, - 14041, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14043, - 0, - 0, - 0, - 0, - 14046, - 0, - 0, - 0, - 14048, - 14049, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14051, - 0, - 0, - 14052, - 14056, - 0, - 14063, - 0, - 14064, - 14066, - 0, - 0, - 14067, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14068, - 0, - 0, - 0, - 14072, - 0, - 14074, - 14075, - 0, - 14076, - 14079, - 14085, - 14086, - 14087, - 14093, - 0, - 0, - 0, - 0, - 14095, - 0, - 0, - 0, - 0, - 0, - 0, - 14096, - 14097, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14098, - 0, - 14102, - 0, - 0, - 0, - 0, - 0, - 14103, - 0, - 0, - 0, - 14104, - 0, - 0, - 14105, - 0, - 0, - 0, - 14107, - 14108, - 0, - 0, - 14109, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14117, - 0, - 0, - 0, - 0, - 14118, - 0, - 0, - 0, - 0, - 14119, - 0, - 0, - 14120, - 0, - 0, - 14121, - 0, - 14122, - 14127, - 0, - 14128, - 14136, - 0, - 0, - 14138, - 0, - 14140, - 0, - 0, - 0, - 14141, - 14142, - 0, - 0, - 0, - 0, - 14146, - 0, - 0, - 14149, - 0, - 14151, - 0, - 0, - 0, - 14152, - 0, - 0, - 14153, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14154, - 0, - 14156, - 14157, - 0, - 0, - 14159, - 0, - 14161, - 0, - 0, - 0, - 0, - 14162, - 0, - 0, - 0, - 0, - 0, - 0, - 14163, - 0, - 0, - 14173, - 0, - 0, - 0, - 0, - 0, - 0, - 14174, - 0, - 0, - 14176, - 0, - 0, - 14178, - 0, - 0, - 14179, - 14181, - 0, - 0, - 14182, - 14185, - 14187, - 0, - 14190, - 0, - 0, - 14197, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14198, - 0, - 0, - 0, - 0, - 0, - 0, - 14199, - 14200, - 0, - 0, - 0, - 14204, - 0, - 0, - 14208, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14231, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14234, - 0, - 0, - 14235, - 0, - 0, - 0, - 14240, - 14241, - 0, - 0, - 0, - 14246, - 0, - 0, - 0, - 14247, - 0, - 14250, - 0, - 0, - 14251, - 0, - 0, - 14254, - 0, - 0, - 14256, - 0, - 0, - 0, - 14260, - 0, - 14261, - 0, - 0, - 0, - 0, - 14262, - 14267, - 14269, - 0, - 0, - 14277, - 0, - 0, - 14278, - 0, - 14279, - 14282, - 0, - 0, - 0, - 14283, - 0, - 0, - 0, - 14284, - 14285, - 0, - 0, - 0, - 0, - 14286, - 0, - 0, - 0, - 14288, - 0, - 0, - 0, - 14289, - 0, - 14290, - 0, - 14293, - 14301, - 14302, - 14304, - 14305, - 0, - 14307, - 0, - 14308, - 14309, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14311, - 14312, - 0, - 0, - 14317, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14318, - 0, - 0, - 0, - 0, - 14320, - 0, - 0, - 0, - 0, - 14321, - 14322, - 0, - 0, - 0, - 0, - 0, - 14326, - 14329, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14330, - 14331, - 0, - 0, - 0, - 0, - 14332, - 0, - 0, - 0, - 14333, - 0, - 0, - 14337, - 14340, - 0, - 14341, - 0, - 0, - 14342, - 0, - 14345, - 14346, - 0, - 0, - 14347, - 0, - 14362, - 0, - 0, - 0, - 0, - 0, - 14364, - 14365, - 14371, - 0, - 14373, - 0, - 0, - 14374, - 0, - 14379, - 0, - 14400, - 0, - 0, - 0, - 0, - 0, - 14401, - 0, - 0, - 14405, - 0, - 14406, - 0, - 14408, - 14409, - 0, - 0, - 0, - 14417, - 0, - 0, - 14424, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14430, - 0, - 0, - 0, - 14431, - 0, - 0, - 14435, - 0, - 14440, - 0, - 0, - 0, - 0, - 0, - 0, - 14442, - 0, - 0, - 14443, - 0, - 0, - 0, - 0, - 0, - 14446, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14454, - 0, - 14457, - 0, - 14460, - 0, - 0, - 14466, - 0, - 0, - 0, - 0, - 0, - 14467, - 0, - 0, - 0, - 0, - 0, - 0, - 14469, - 0, - 14477, - 0, - 0, - 0, - 0, - 0, - 0, - 14478, - 14482, - 0, - 0, - 0, - 14483, - 0, - 0, - 0, - 14485, - 14486, - 0, - 0, - 0, - 14487, - 14488, - 14489, - 14492, - 14493, - 14494, - 14495, - 14496, - 14497, - 0, - 14499, - 0, - 14501, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14502, - 0, - 14507, - 14512, - 14513, - 14514, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14515, - 14526, - 14530, - 0, - 14537, - 0, - 14544, - 0, - 14547, - 0, - 0, - 14548, - 14550, - 14551, - 0, - 0, - 14552, - 0, - 0, - 0, - 14553, - 0, - 14554, - 0, - 0, - 0, - 0, - 14556, - 14564, - 0, - 0, - 14565, - 14566, - 0, - 0, - 0, - 0, - 0, - 0, - 14568, - 0, - 0, - 14569, - 0, - 0, - 0, - 14571, - 14576, - 0, - 0, - 14577, - 14578, - 14579, - 0, - 0, - 14580, - 0, - 0, - 0, - 0, - 14582, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14583, - 0, - 0, - 0, - 0, - 0, - 14587, - 0, - 14588, - 0, - 0, - 14600, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14601, - 0, - 0, - 14604, - 14605, - 14611, - 0, - 14613, - 0, - 0, - 0, - 0, - 14615, - 0, - 0, - 0, - 0, - 0, - 0, - 14627, - 0, - 14628, - 0, - 0, - 0, - 0, - 14631, - 0, - 14633, - 14634, - 0, - 0, - 0, - 0, - 14635, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14636, - 0, - 0, - 14639, - 14642, - 0, - 0, - 0, - 0, - 14644, - 0, - 0, - 0, - 0, - 14645, - 14646, - 0, - 14653, - 0, - 0, - 14654, - 0, - 14658, - 0, - 14661, - 0, - 0, - 0, - 14665, - 0, - 0, - 0, - 14668, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14669, - 0, - 0, - 14670, - 0, - 0, - 0, - 14680, - 0, - 0, - 14681, - 0, - 0, - 0, - 0, - 0, - 14682, - 14683, - 0, - 0, - 0, - 0, - 14686, - 0, - 0, - 0, - 0, - 14687, - 14697, - 0, - 0, - 0, - 0, - 14699, - 14705, - 14711, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14712, - 0, - 0, - 0, - 14713, - 0, - 0, - 0, - 0, - 14719, - 0, - 14720, - 14721, - 14726, - 0, - 0, - 0, - 14728, - 14729, - 0, - 0, - 0, - 0, - 14731, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14733, - 14736, - 14737, - 0, - 0, - 14740, - 14742, - 0, - 0, - 0, - 14744, - 14753, - 0, - 0, - 0, - 0, - 14755, - 14758, - 14760, - 0, - 0, - 0, - 0, - 0, - 14761, - 14762, - 14765, - 14771, - 0, - 14772, - 0, - 14773, - 14774, - 0, - 0, - 14775, - 0, - 0, - 14776, - 0, - 0, - 0, - 0, - 14777, - 0, - 14779, - 0, - 0, - 14782, - 0, - 0, - 14785, - 14786, - 14788, - 0, - 0, - 0, - 0, - 0, - 14795, - 0, - 0, - 0, - 0, - 0, - 0, - 14798, - 0, - 14803, - 14804, - 14806, - 0, - 0, - 0, - 14809, - 0, - 0, - 0, - 0, - 0, - 0, - 14810, - 0, - 0, - 0, - 0, - 14811, - 0, - 14812, - 0, - 0, - 0, - 0, - 0, - 14815, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14816, - 0, - 14818, - 0, - 0, - 0, - 0, - 0, - 0, - 14819, - 0, - 14820, - 0, - 14823, - 0, - 0, - 0, - 14824, - 0, - 0, - 14826, - 14827, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14830, - 0, - 0, - 0, - 0, - 0, - 14833, - 0, - 14845, - 0, - 0, - 0, - 0, - 0, - 14846, - 0, - 0, - 14847, - 14871, - 0, - 14873, - 0, - 14876, - 0, - 14877, - 14878, - 14880, - 0, - 0, - 0, - 0, - 0, - 14881, - 0, - 14882, - 14894, - 0, - 0, - 0, - 0, - 14895, - 0, - 14907, - 0, - 14908, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14911, - 0, - 0, - 0, - 0, - 14920, - 0, - 0, - 14931, - 0, - 14932, - 14934, - 14935, - 0, - 0, - 14936, - 0, - 14945, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 14947, - 0, - 0, - 14948, - 14949, - 14951, - 0, - 0, - 14952, - 0, - 0, - 0, - 14964, - 14973, - 0, - 0, - 14990, - 0, - 0, - 0, - 0, - 14995, - 0, - 0, - 14998, - 15001, - 0, - 0, - 15002, - 15020, - 0, - 0, - 0, - 0, - 0, - 0, - 15021, - 0, - 15022, - 0, - 0, - 0, - 0, - 15023, - 0, - 0, - 15025, - 15029, - 15033, - 0, - 0, - 0, - 15034, - 0, - 0, - 0, - 15035, - 0, - 0, - 0, - 0, - 0, - 15043, - 15044, - 0, - 0, - 0, - 15045, - 15046, - 15048, - 15050, - 0, - 15065, - 0, - 0, - 0, - 0, - 15066, - 0, - 0, - 15075, - 15082, - 15084, - 0, - 0, - 15085, - 15086, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15088, - 0, - 0, - 0, - 15089, - 0, - 0, - 0, - 0, - 15094, - 0, - 15096, - 0, - 15097, - 0, - 15100, - 0, - 0, - 15102, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15105, - 0, - 0, - 15106, - 0, - 15109, - 15113, - 0, - 0, - 0, - 15115, - 0, - 15118, - 0, - 0, - 0, - 0, - 0, - 0, - 15119, - 0, - 0, - 15120, - 0, - 0, - 0, - 0, - 0, - 15123, - 15129, - 0, - 0, - 0, - 15130, - 0, - 15131, - 0, - 0, - 15134, - 0, - 15135, - 0, - 0, - 0, - 15137, - 15138, - 0, - 0, - 0, - 0, - 0, - 0, - 15139, - 0, - 0, - 0, - 0, - 0, - 15140, - 0, - 0, - 15154, - 15162, - 0, - 15169, - 15170, - 0, - 15175, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15177, - 0, - 15178, - 15179, - 0, - 0, - 0, - 0, - 0, - 15183, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15185, - 15187, - 0, - 15194, - 15195, - 15196, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15204, - 0, - 0, - 0, - 0, - 15206, - 0, - 0, - 0, - 0, - 0, - 15207, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15213, - 0, - 15214, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15232, - 0, - 0, - 0, - 0, - 15234, - 0, - 15238, - 15240, - 0, - 15248, - 0, - 0, - 0, - 0, - 15250, - 15251, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15252, - 0, - 0, - 0, - 15255, - 15262, - 15266, - 0, - 0, - 0, - 15267, - 0, - 0, - 0, - 15277, - 15279, - 0, - 0, - 0, - 15280, - 15281, - 15282, - 0, - 0, - 0, - 0, - 0, - 15285, - 0, - 0, - 0, - 0, - 15289, - 0, - 0, - 15291, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15296, - 15297, - 0, - 0, - 15304, - 0, - 0, - 0, - 0, - 15306, - 0, - 0, - 0, - 0, - 0, - 0, - 15307, - 15308, - 0, - 15309, - 0, - 0, - 15311, - 0, - 0, - 15312, - 15313, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15314, - 15317, - 0, - 0, - 0, - 15318, - 15319, - 0, - 0, - 0, - 0, - 15320, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15321, - 0, - 0, - 0, - 0, - 0, - 15324, - 0, - 15325, - 15326, - 0, - 15330, - 0, - 0, - 0, - 0, - 15334, - 0, - 15335, - 0, - 15341, - 0, - 0, - 15342, - 0, - 0, - 15343, - 15344, - 0, - 0, - 0, - 0, - 15345, - 0, - 0, - 0, - 0, - 15347, - 0, - 0, - 15348, - 15349, - 15350, - 0, - 15356, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15357, - 0, - 15358, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15359, - 15360, - 15364, - 0, - 15380, - 0, - 0, - 0, - 0, - 0, - 15392, - 0, - 0, - 15393, - 0, - 15395, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15396, - 0, - 0, - 15397, - 15398, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15399, - 0, - 15400, - 0, - 0, - 0, - 15402, - 0, - 15405, - 15410, - 0, - 0, - 0, - 0, - 15411, - 0, - 0, - 0, - 15412, - 0, - 15416, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15428, - 0, - 15435, - 0, - 0, - 15438, - 0, - 0, - 0, - 0, - 15439, - 0, - 0, - 0, - 15440, - 0, - 0, - 0, - 15441, - 15449, - 15451, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15452, - 0, - 0, - 15455, - 0, - 0, - 0, - 15456, - 0, - 0, - 15458, - 0, - 15460, - 15461, - 0, - 0, - 0, - 0, - 0, - 15462, - 15464, - 0, - 15465, - 0, - 0, - 15466, - 0, - 0, - 15467, - 0, - 0, - 0, - 0, - 0, - 15468, - 0, - 0, - 0, - 0, - 15481, - 0, - 0, - 15484, - 0, - 15485, - 15486, - 0, - 0, - 0, - 15487, - 0, - 0, - 0, - 0, - 0, - 15488, - 0, - 15492, - 15498, - 0, - 0, - 0, - 15499, - 0, - 0, - 0, - 15500, - 0, - 15501, - 0, - 0, - 15512, - 0, - 15522, - 0, - 0, - 0, - 15524, - 0, - 15525, - 15526, - 0, - 0, - 15527, - 0, - 0, - 15545, - 15546, - 0, - 15548, - 15552, - 0, - 15553, - 0, - 0, - 0, - 15554, - 0, - 15555, - 0, - 15557, - 15565, - 15573, - 15577, - 15578, - 0, - 15582, - 0, - 15583, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15586, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15588, - 0, - 0, - 0, - 0, - 0, - 15589, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15593, - 15594, - 0, - 0, - 0, - 0, - 15595, - 0, - 0, - 0, - 0, - 0, - 0, - 15596, - 0, - 0, - 0, - 15597, - 0, - 0, - 0, - 0, - 15600, - 0, - 0, - 15601, - 0, - 0, - 0, - 0, - 15602, - 15603, - 0, - 0, - 0, - 0, - 0, - 0, - 15604, - 0, - 15609, - 0, - 0, - 15612, - 0, - 0, - 15613, - 0, - 0, - 15615, - 15617, - 15618, - 0, - 0, - 15620, - 0, - 15636, - 15637, - 0, - 0, - 15649, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15650, - 0, - 0, - 15651, - 0, - 0, - 0, - 15656, - 0, - 15658, - 0, - 0, - 0, - 15664, - 0, - 0, - 15665, - 0, - 0, - 15668, - 0, - 0, - 0, - 0, - 0, - 15669, - 0, - 0, - 15674, - 0, - 0, - 15675, - 0, - 0, - 0, - 0, - 15676, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15677, - 0, - 0, - 0, - 0, - 15678, - 0, - 0, - 0, - 0, - 0, - 15679, - 0, - 0, - 15681, - 0, - 15686, - 0, - 0, - 0, - 0, - 15687, - 0, - 15688, - 0, - 0, - 15690, - 0, - 0, - 0, - 15697, - 0, - 15699, - 15700, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15701, - 0, - 15702, - 15703, - 0, - 15704, - 0, - 15705, - 0, - 15707, - 0, - 15709, - 0, - 15712, - 15716, - 0, - 15717, - 0, - 15718, - 15720, - 0, - 0, - 0, - 0, - 0, - 15724, - 0, - 0, - 0, - 15725, - 0, - 15726, - 0, - 0, - 0, - 15740, - 0, - 15745, - 15746, - 0, - 0, - 15747, - 0, - 15748, - 0, - 0, - 0, - 0, - 0, - 15749, - 0, - 0, - 0, - 15752, - 0, - 15753, - 0, - 0, - 0, - 0, - 0, - 0, - 15759, - 0, - 0, - 0, - 15765, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15767, - 0, - 0, - 0, - 15771, - 0, - 0, - 15784, - 0, - 0, - 0, - 0, - 15785, - 15790, - 15791, - 0, - 0, - 15792, - 0, - 0, - 0, - 15807, - 0, - 15811, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15818, - 0, - 0, - 0, - 15819, - 0, - 0, - 0, - 0, - 15821, - 0, - 0, - 0, - 0, - 0, - 15822, - 15824, - 0, - 0, - 15827, - 0, - 0, - 15829, - 15831, - 0, - 15832, - 0, - 0, - 15833, - 0, - 15835, - 15838, - 15839, - 15843, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15844, - 0, - 0, - 0, - 0, - 15845, - 15851, - 15856, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15858, - 15860, - 0, - 15861, - 0, - 0, - 0, - 15864, - 0, - 0, - 0, - 0, - 15865, - 0, - 0, - 0, - 0, - 0, - 0, - 15866, - 0, - 15872, - 0, - 0, - 15876, - 0, - 0, - 0, - 0, - 15877, - 15878, - 15883, - 15885, - 0, - 0, - 15888, - 0, - 0, - 0, - 0, - 0, - 15889, - 15890, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15892, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15893, - 0, - 0, - 15894, - 0, - 0, - 0, - 15895, - 0, - 15896, - 15897, - 0, - 15898, - 15901, - 15902, - 0, - 15911, - 15915, - 0, - 15916, - 0, - 15924, - 15935, - 0, - 15937, - 0, - 0, - 0, - 0, - 0, - 15950, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15958, - 0, - 0, - 0, - 15961, - 0, - 0, - 15966, - 0, - 15967, - 0, - 0, - 15977, - 0, - 0, - 15978, - 0, - 0, - 15981, - 15982, - 15983, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 15986, - 0, - 0, - 0, - 15990, - 0, - 15991, - 15995, - 15998, - 0, - 15999, - 0, - 16000, - 0, - 0, - 0, - 0, - 16008, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16009, - 16011, - 0, - 16013, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16014, - 0, - 0, - 16015, - 16023, - 16024, - 16025, - 0, - 0, - 16026, - 0, - 16030, - 0, - 16032, - 0, - 16033, - 0, - 0, - 0, - 0, - 0, - 0, - 16035, - 16036, - 16037, - 0, - 0, - 0, - 0, - 0, - 16039, - 0, - 0, - 0, - 0, - 16041, - 0, - 0, - 0, - 0, - 0, - 16043, - 16044, - 0, - 0, - 16047, - 0, - 0, - 0, - 16048, - 0, - 0, - 16049, - 16050, - 16052, - 0, - 0, - 0, - 0, - 0, - 16055, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16056, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16058, - 16060, - 16061, - 0, - 0, - 16063, - 0, - 0, - 16064, - 0, - 0, - 0, - 16067, - 16068, - 0, - 0, - 16069, - 16078, - 0, - 0, - 0, - 16079, - 0, - 0, - 0, - 16080, - 0, - 16081, - 0, - 0, - 0, - 16088, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16089, - 16093, - 0, - 16097, - 0, - 16103, - 0, - 16104, - 16105, - 0, - 0, - 16256, - 0, - 0, - 16259, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16260, - 16261, - 0, - 0, - 16262, - 0, - 0, - 16263, - 0, - 16268, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16269, - 0, - 0, - 16270, - 16273, - 0, - 16274, - 0, - 0, - 0, - 0, - 16275, - 16276, - 16277, - 16280, - 0, - 0, - 0, - 16281, - 16284, - 0, - 0, - 0, - 16286, - 0, - 16289, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16290, - 0, - 0, - 0, - 0, - 16291, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16292, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16293, - 16295, - 16297, - 0, - 16302, - 0, - 16304, - 0, - 16305, - 0, - 16306, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16307, - 16308, - 16312, - 0, - 0, - 0, - 0, - 0, - 0, - 16313, - 16315, - 0, - 16318, - 0, - 0, - 0, - 16321, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16326, - 16333, - 16336, - 0, - 0, - 0, - 0, - 16337, - 16340, - 0, - 0, - 0, - 0, - 0, - 16345, - 0, - 0, - 16346, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16347, - 0, - 0, - 16348, - 0, - 0, - 0, - 0, - 16349, - 0, - 0, - 0, - 16350, - 0, - 16357, - 0, - 0, - 0, - 0, - 16359, - 16360, - 0, - 0, - 0, - 0, - 16362, - 16363, - 16364, - 16365, - 0, - 0, - 16366, - 0, - 0, - 0, - 0, - 16367, - 16368, - 0, - 16369, - 16374, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16376, - 0, - 0, - 0, - 0, - 16378, - 16379, - 0, - 16380, - 0, - 0, - 0, - 16381, - 16383, - 0, - 0, - 0, - 0, - 0, - 16390, - 0, - 0, - 0, - 16399, - 0, - 16402, - 16404, - 16406, - 16407, - 0, - 0, - 0, - 16409, - 16411, - 0, - 0, - 0, - 0, - 16412, - 0, - 16413, - 16415, - 16423, - 0, - 0, - 0, - 0, - 0, - 16424, - 0, - 0, - 0, - 16428, - 16434, - 16435, - 16449, - 0, - 16450, - 16451, - 0, - 0, - 0, - 16453, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16454, - 0, - 0, - 16456, - 16458, - 0, - 0, - 16459, - 0, - 0, - 16460, - 0, - 0, - 0, - 0, - 16462, - 0, - 16463, - 0, - 0, - 16466, - 0, - 0, - 0, - 0, - 0, - 16479, - 0, - 0, - 16480, - 0, - 16481, - 16484, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16485, - 0, - 0, - 0, - 0, - 0, - 0, - 16489, - 0, - 0, - 0, - 0, - 0, - 16491, - 0, - 0, - 16498, - 0, - 0, - 16503, - 0, - 16505, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16506, - 0, - 0, - 0, - 16508, - 16509, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16511, - 16513, - 0, - 0, - 0, - 16516, - 0, - 16517, - 0, - 16519, - 0, - 16529, - 0, - 0, - 16531, - 0, - 0, - 0, - 0, - 0, - 0, - 16534, - 0, - 0, - 16541, - 16542, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16543, - 16547, - 16548, - 0, - 0, - 0, - 16551, - 0, - 16552, - 0, - 0, - 0, - 16553, - 0, - 0, - 16558, - 0, - 0, - 16562, - 16565, - 0, - 0, - 0, - 16570, - 0, - 0, - 0, - 16573, - 16585, - 0, - 0, - 0, - 16586, - 16587, - 16595, - 0, - 16596, - 0, - 16598, - 0, - 0, - 0, - 16600, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16601, - 0, - 0, - 0, - 0, - 16603, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16604, - 16612, - 0, - 0, - 0, - 0, - 16613, - 0, - 16618, - 0, - 0, - 0, - 16640, - 0, - 0, - 16641, - 0, - 0, - 0, - 0, - 0, - 0, - 16645, - 0, - 0, - 0, - 0, - 16646, - 0, - 0, - 0, - 0, - 0, - 0, - 16651, - 0, - 0, - 0, - 0, - 16653, - 16654, - 0, - 0, - 0, - 16655, - 0, - 0, - 16656, - 16667, - 0, - 0, - 0, - 0, - 16671, - 0, - 16672, - 0, - 0, - 0, - 16673, - 0, - 0, - 0, - 0, - 0, - 16676, - 0, - 16686, - 0, - 0, - 0, - 0, - 16689, - 0, - 16690, - 0, - 16692, - 0, - 16693, - 0, - 16694, - 0, - 16696, - 0, - 0, - 0, - 16705, - 0, - 0, - 0, - 0, - 0, - 0, - 16707, - 0, - 0, - 0, - 16709, - 0, - 0, - 0, - 0, - 16711, - 0, - 16712, - 16713, - 0, - 0, - 0, - 16715, - 0, - 0, - 0, - 0, - 16716, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16718, - 16724, - 0, - 0, - 16726, - 16727, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16728, - 0, - 16729, - 0, - 0, - 16730, - 0, - 0, - 0, - 0, - 0, - 16731, - 0, - 0, - 0, - 16732, - 0, - 0, - 0, - 0, - 16734, - 16738, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16743, - 0, - 0, - 16745, - 0, - 0, - 0, - 0, - 0, - 16749, - 0, - 16752, - 0, - 0, - 0, - 0, - 16756, - 0, - 0, - 16758, - 0, - 16759, - 0, - 0, - 0, - 0, - 0, - 16760, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16762, - 0, - 16769, - 0, - 16770, - 0, - 16772, - 0, - 0, - 0, - 16777, - 16780, - 0, - 0, - 0, - 0, - 0, - 0, - 16781, - 0, - 0, - 16782, - 0, - 16784, - 0, - 0, - 16785, - 16787, - 16792, - 0, - 0, - 16794, - 0, - 0, - 0, - 16798, - 0, - 0, - 16809, - 0, - 0, - 16814, - 16816, - 16817, - 0, - 16819, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16820, - 0, - 0, - 16836, - 16839, - 0, - 0, - 16841, - 16851, - 16857, - 0, - 0, - 16858, - 16859, - 0, - 0, - 16860, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16862, - 0, - 16863, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16864, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16876, - 0, - 16881, - 16882, - 0, - 16885, - 16886, - 0, - 16887, - 0, - 0, - 0, - 16889, - 16891, - 0, - 0, - 0, - 0, - 0, - 16894, - 16895, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 16897, - 0, - 16898, - 0, - 0, - 0, - 0, - 0, - 16913, - 0, - 0, - 16924, - 16925, - 16926, - 0, - 0, - 16927, - 0, - 0, - 0, - 16937, - 16938, - 0, - 0, - 0, - 16940, - 16941, - 0, - 0, - 0, - 16942, - 16945, - 0, - 16946, - 16949, - 16950, - 0, - 0, - 0, - 16952, - 16955, - 0, - 0, - 0, - 16965, - 0, - 16969, - 0, - 0, - 16975, - 0, - 0, - 16976, - 0, - 0, - 0, - 0, - 16978, - 0, - 0, - 16981, - 0, - 16983, - 16989, - 0, - 0, - 0, - 0, - 16990, - 0, - 0, - 16991, - 0, - 0, - 0, - 16993, - 0, - 16994, - 16996, - 17000, - 0, - 0, - 0, - 0, - 0, - 17002, - 17004, - 0, - 17006, - 0, - 0, - 17007, - 0, - 0, - 0, - 0, - 17008, - 17013, - 17014, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17021, - 0, - 17031, - 0, - 0, - 0, - 0, - 0, - 17033, - 17036, - 0, - 17038, - 0, - 0, - 17039, - 0, - 17045, - 0, - 0, - 17046, - 17047, - 0, - 0, - 0, - 0, - 17048, - 0, - 17049, - 17050, - 0, - 17051, - 17053, - 0, - 17054, - 0, - 17055, - 0, - 0, - 0, - 0, - 0, - 17063, - 0, - 0, - 17064, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17065, - 0, - 0, - 17068, - 0, - 0, - 0, - 0, - 0, - 17072, - 0, - 0, - 0, - 0, - 0, - 0, - 17073, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17074, - 0, - 17080, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17081, - 17083, - 17084, - 0, - 0, - 0, - 17085, - 0, - 0, - 0, - 0, - 17092, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17093, - 0, - 17095, - 17102, - 0, - 0, - 0, - 0, - 0, - 0, - 17103, - 0, - 0, - 17105, - 0, - 17107, - 0, - 0, - 0, - 0, - 17114, - 0, - 0, - 0, - 0, - 0, - 17115, - 17125, - 17127, - 0, - 0, - 17128, - 0, - 0, - 0, - 17129, - 17130, - 0, - 17131, - 0, - 0, - 0, - 0, - 0, - 17132, - 17135, - 17145, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17146, - 0, - 17147, - 0, - 17148, - 0, - 0, - 0, - 0, - 0, - 0, - 17149, - 17150, - 0, - 17151, - 17153, - 0, - 17155, - 0, - 0, - 0, - 0, - 17163, - 17171, - 0, - 17174, - 0, - 0, - 0, - 0, - 17179, - 0, - 0, - 17182, - 17185, - 0, - 0, - 0, - 0, - 0, - 17186, - 0, - 0, - 17188, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17189, - 17191, - 0, - 17194, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17195, - 17196, - 17203, - 17204, - 0, - 0, - 17205, - 17217, - 0, - 0, - 0, - 0, - 0, - 17218, - 0, - 0, - 0, - 0, - 17219, - 0, - 17220, - 0, - 17221, - 0, - 0, - 17230, - 0, - 0, - 0, - 0, - 0, - 17236, - 0, - 17238, - 17239, - 0, - 0, - 0, - 17241, - 17244, - 0, - 0, - 17245, - 0, - 17248, - 0, - 0, - 17251, - 0, - 17252, - 0, - 0, - 17264, - 0, - 17266, - 0, - 0, - 0, - 17268, - 0, - 0, - 0, - 0, - 17271, - 17272, - 0, - 17273, - 0, - 17295, - 0, - 17302, - 0, - 17305, - 0, - 0, - 0, - 17306, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17308, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17309, - 0, - 17310, - 17313, - 0, - 0, - 0, - 0, - 17314, - 17315, - 0, - 17317, - 0, - 0, - 0, - 0, - 17318, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17320, - 0, - 0, - 0, - 0, - 0, - 0, - 17334, - 0, - 17344, - 17348, - 0, - 0, - 0, - 17350, - 17351, - 0, - 0, - 17353, - 0, - 0, - 17354, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17355, - 0, - 0, - 0, - 0, - 0, - 0, - 17356, - 17357, - 0, - 0, - 17359, - 0, - 0, - 0, - 17371, - 0, - 17372, - 0, - 0, - 0, - 17393, - 0, - 0, - 0, - 0, - 17394, - 0, - 0, - 0, - 0, - 0, - 17395, - 0, - 0, - 17399, - 0, - 0, - 0, - 17401, - 17417, - 0, - 17418, - 0, - 17419, - 0, - 0, - 0, - 0, - 0, - 17422, - 17423, - 0, - 0, - 0, - 0, - 0, - 17424, - 0, - 0, - 0, - 0, - 0, - 17428, - 17429, - 17433, - 0, - 0, - 0, - 17437, - 0, - 0, - 17441, - 0, - 0, - 17442, - 0, - 0, - 17453, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17454, - 17456, - 17462, - 0, - 0, - 17466, - 0, - 0, - 17468, - 0, - 0, - 17469, - 0, - 0, - 0, - 0, - 17470, - 0, - 17475, - 0, - 0, - 0, - 0, - 0, - 17479, - 0, - 0, - 0, - 17483, - 17484, - 0, - 17485, - 0, - 17486, - 0, - 17491, - 17492, - 0, - 0, - 17493, - 0, - 17494, - 17495, - 0, - 0, - 0, - 17496, - 0, - 0, - 0, - 17497, - 0, - 0, - 0, - 17502, - 0, - 0, - 0, - 0, - 0, - 17503, - 0, - 17505, - 0, - 17507, - 0, - 0, - 0, - 17512, - 17513, - 17514, - 0, - 0, - 17515, - 0, - 0, - 0, - 17519, - 0, - 0, - 0, - 17522, - 0, - 0, - 17523, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17527, - 0, - 0, - 0, - 17528, - 0, - 0, - 0, - 17534, - 0, - 0, - 0, - 0, - 17536, - 0, - 0, - 0, - 17539, - 0, - 17540, - 17543, - 17549, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17556, - 0, - 0, - 17558, - 0, - 17559, - 0, - 0, - 17560, - 0, - 0, - 0, - 17563, - 0, - 0, - 0, - 0, - 0, - 0, - 17564, - 0, - 0, - 17565, - 17566, - 0, - 17567, - 0, - 0, - 0, - 0, - 0, - 0, - 17569, - 17570, - 0, - 17575, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17581, - 0, - 0, - 0, - 17582, - 17583, - 0, - 17586, - 0, - 0, - 17587, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17588, - 0, - 0, - 0, - 0, - 17596, - 17597, - 0, - 0, - 17598, - 17600, - 0, - 0, - 0, - 0, - 0, - 0, - 17601, - 0, - 0, - 0, - 17604, - 0, - 0, - 17605, - 0, - 0, - 17607, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17612, - 0, - 0, - 17618, - 0, - 17621, - 17622, - 0, - 0, - 0, - 0, - 17623, - 0, - 0, - 17624, - 0, - 0, - 17630, - 0, - 0, - 17631, - 17633, - 17634, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17635, - 0, - 0, - 17636, - 0, - 0, - 17637, - 0, - 17638, - 0, - 17640, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17641, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17643, - 0, - 0, - 0, - 0, - 17645, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17646, - 17662, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17663, - 17664, - 0, - 17665, - 17666, - 0, - 0, - 0, - 17669, - 17671, - 17673, - 0, - 17679, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17684, - 0, - 0, - 0, - 17686, - 0, - 17714, - 0, - 0, - 17720, - 17722, - 17726, - 0, - 0, - 17728, - 0, - 0, - 17729, - 0, - 0, - 0, - 17732, - 0, - 17733, - 0, - 17734, - 0, - 0, - 0, - 17735, - 0, - 0, - 0, - 0, - 17737, - 0, - 0, - 0, - 0, - 17739, - 0, - 0, - 0, - 17741, - 17742, - 0, - 0, - 0, - 0, - 17743, - 17744, - 17745, - 0, - 0, - 0, - 17749, - 0, - 17750, - 17751, - 17752, - 17754, - 17761, - 17762, - 0, - 17763, - 0, - 17766, - 0, - 17772, - 0, - 0, - 0, - 0, - 0, - 17775, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17776, - 0, - 0, - 17777, - 0, - 0, - 17778, - 17779, - 0, - 17782, - 17783, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17784, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17821, - 0, - 0, - 0, - 17822, - 0, - 0, - 0, - 17823, - 17825, - 0, - 0, - 0, - 0, - 0, - 17826, - 17831, - 17832, - 17833, - 0, - 0, - 17845, - 0, - 0, - 0, - 17846, - 0, - 0, - 0, - 17848, - 17850, - 17854, - 0, - 17855, - 0, - 0, - 17859, - 0, - 0, - 0, - 0, - 0, - 0, - 17860, - 17861, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 17870, - 17871, - 0, - 0, - 0, - 0, - 0, - 0, - 17872, - 0, - 0, - 0, - 17879, - 0, - 0, - 0, - 17881, - 17883, - 0, - 17884, - 0, - 17885, - 0, - 0, - 17886, - 0, - 0, - 17887, - 17891, - 17953, - 0, - 0, - 0, - 0, - 17954, - 0, - 0, - 17955, - 0, - 17968, - 0, - 0, - 17972, - 0, - 0, - 0, - 0, - 0, - 17974, - 0, - 0, - 0, - 0, - 17976, - 17978, - 0, - 0, - 17983, - 0, - 0, - 0, - 0, - 18003, - 0, - 0, - 0, - 0, - 0, - 18007, - 0, - 0, - 0, - 0, - 0, - 18009, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18010, - 0, - 0, - 0, - 0, - 0, - 0, - 18012, - 0, - 0, - 18014, - 0, - 0, - 0, - 18015, - 0, - 0, - 0, - 18016, - 0, - 18017, - 0, - 0, - 0, - 18030, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18031, - 0, - 0, - 18036, - 18037, - 18038, - 0, - 0, - 18049, - 18056, - 0, - 18057, - 18058, - 0, - 18059, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18062, - 0, - 0, - 0, - 0, - 18064, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18067, - 0, - 0, - 0, - 18068, - 0, - 0, - 18075, - 0, - 0, - 18078, - 18093, - 18094, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18097, - 0, - 0, - 0, - 0, - 0, - 18098, - 18100, - 0, - 0, - 0, - 18108, - 0, - 18111, - 0, - 0, - 18112, - 0, - 18113, - 0, - 0, - 18115, - 18116, - 0, - 18118, - 0, - 0, - 0, - 0, - 18121, - 0, - 0, - 0, - 0, - 18123, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18124, - 0, - 0, - 0, - 0, - 18125, - 18126, - 0, - 18127, - 0, - 0, - 18128, - 18135, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18150, - 0, - 0, - 0, - 0, - 0, - 18151, - 18152, - 0, - 0, - 18156, - 18164, - 0, - 18166, - 18171, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18172, - 18183, - 0, - 18184, - 0, - 0, - 0, - 0, - 18185, - 0, - 18187, - 0, - 0, - 0, - 0, - 0, - 18188, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18189, - 0, - 0, - 18190, - 0, - 0, - 18191, - 18192, - 0, - 0, - 18194, - 18195, - 18196, - 0, - 0, - 0, - 18197, - 0, - 18203, - 0, - 18204, - 0, - 0, - 0, - 0, - 18205, - 0, - 0, - 0, - 18207, - 18208, - 0, - 0, - 18214, - 0, - 0, - 0, - 18215, - 18216, - 0, - 0, - 0, - 18220, - 0, - 0, - 18222, - 0, - 0, - 0, - 0, - 0, - 18223, - 0, - 18225, - 18231, - 0, - 18234, - 0, - 18235, - 0, - 0, - 0, - 0, - 18240, - 0, - 0, - 18241, - 18242, - 0, - 0, - 0, - 0, - 0, - 18243, - 18251, - 0, - 18253, - 0, - 18254, - 0, - 0, - 0, - 18266, - 0, - 0, - 0, - 0, - 0, - 0, - 18269, - 18270, - 18271, - 18273, - 18281, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18282, - 0, - 18283, - 0, - 18284, - 0, - 0, - 0, - 0, - 0, - 0, - 18285, - 0, - 18287, - 18289, - 0, - 0, - 18290, - 0, - 0, - 0, - 0, - 18308, - 0, - 0, - 0, - 18310, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18311, - 0, - 18312, - 18313, - 0, - 18315, - 0, - 0, - 18316, - 18320, - 0, - 18331, - 0, - 18332, - 0, - 18336, - 0, - 0, - 0, - 0, - 18337, - 0, - 18340, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18341, - 0, - 18344, - 18345, - 0, - 18346, - 0, - 0, - 0, - 0, - 0, - 18348, - 0, - 18351, - 0, - 0, - 18356, - 0, - 0, - 0, - 0, - 0, - 0, - 18357, - 0, - 0, - 0, - 0, - 0, - 18367, - 0, - 0, - 0, - 18368, - 0, - 18369, - 0, - 18370, - 18371, - 0, - 0, - 0, - 18437, - 18444, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18445, - 18450, - 0, - 0, - 0, - 0, - 18451, - 0, - 18452, - 0, - 0, - 0, - 18453, - 0, - 0, - 0, - 0, - 0, - 18455, - 0, - 0, - 0, - 18456, - 0, - 18457, - 0, - 18460, - 0, - 0, - 18461, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18466, - 0, - 0, - 18467, - 0, - 0, - 0, - 0, - 18473, - 0, - 0, - 0, - 18476, - 0, - 18477, - 0, - 0, - 0, - 18478, - 18479, - 18480, - 0, - 0, - 0, - 18485, - 0, - 0, - 0, - 18486, - 0, - 0, - 0, - 0, - 0, - 0, - 18488, - 18490, - 0, - 0, - 0, - 0, - 0, - 0, - 18491, - 0, - 0, - 0, - 0, - 0, - 18495, - 0, - 0, - 18496, - 0, - 0, - 0, - 0, - 0, - 0, - 18505, - 0, - 18521, - 0, - 18522, - 18523, - 0, - 0, - 0, - 18525, - 18526, - 0, - 0, - 0, - 0, - 0, - 18527, - 0, - 0, - 0, - 0, - 18532, - 18533, - 0, - 18534, - 0, - 0, - 0, - 0, - 0, - 0, - 18535, - 18537, - 0, - 18538, - 0, - 0, - 0, - 0, - 0, - 0, - 18540, - 18541, - 18542, - 18543, - 0, - 18546, - 0, - 0, - 0, - 0, - 18553, - 18556, - 0, - 0, - 18558, - 0, - 0, - 18569, - 18571, - 0, - 0, - 0, - 18572, - 0, - 18574, - 0, - 0, - 0, - 0, - 18586, - 0, - 0, - 0, - 0, - 0, - 18588, - 0, - 0, - 18589, - 0, - 0, - 0, - 0, - 0, - 0, - 18590, - 0, - 18592, - 0, - 0, - 0, - 0, - 18594, - 0, - 0, - 0, - 18596, - 0, - 0, - 18597, - 18598, - 0, - 0, - 18601, - 0, - 0, - 0, - 0, - 18602, - 0, - 0, - 0, - 18603, - 18604, - 0, - 18605, - 0, - 0, - 0, - 0, - 18608, - 0, - 0, - 18611, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18612, - 0, - 18616, - 0, - 0, - 18617, - 18619, - 0, - 0, - 0, - 18628, - 0, - 0, - 0, - 18629, - 0, - 0, - 18630, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18631, - 0, - 18632, - 0, - 0, - 18635, - 18637, - 0, - 0, - 0, - 0, - 0, - 0, - 18641, - 18643, - 18648, - 0, - 18652, - 0, - 0, - 18653, - 0, - 18655, - 18656, - 0, - 0, - 0, - 18657, - 0, - 0, - 18666, - 18674, - 0, - 0, - 0, - 0, - 18677, - 18684, - 18685, - 0, - 0, - 18686, - 0, - 0, - 18690, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18695, - 18696, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18697, - 0, - 0, - 18700, - 0, - 0, - 0, - 0, - 0, - 0, - 18702, - 0, - 18708, - 0, - 0, - 18709, - 0, - 18710, - 0, - 0, - 18711, - 0, - 18714, - 0, - 0, - 18718, - 0, - 0, - 0, - 0, - 0, - 0, - 18719, - 0, - 0, - 18722, - 0, - 18726, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18731, - 0, - 0, - 0, - 0, - 0, - 18739, - 18741, - 0, - 0, - 18742, - 0, - 18743, - 18744, - 18746, - 18748, - 0, - 18752, - 18753, - 0, - 0, - 18754, - 18763, - 0, - 18765, - 0, - 0, - 0, - 18766, - 0, - 0, - 0, - 18769, - 0, - 0, - 0, - 0, - 0, - 18773, - 18778, - 18779, - 18781, - 0, - 0, - 18784, - 18787, - 0, - 18788, - 0, - 18793, - 0, - 0, - 0, - 0, - 0, - 0, - 18795, - 0, - 0, - 18800, - 0, - 0, - 0, - 0, - 0, - 18801, - 18804, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18806, - 0, - 0, - 0, - 18811, - 18815, - 18816, - 0, - 0, - 0, - 0, - 18825, - 0, - 0, - 18827, - 18829, - 0, - 0, - 18830, - 0, - 0, - 0, - 0, - 18831, - 0, - 0, - 18832, - 0, - 0, - 0, - 0, - 18833, - 0, - 18840, - 0, - 18841, - 0, - 18842, - 0, - 0, - 0, - 0, - 18843, - 0, - 18844, - 0, - 0, - 0, - 0, - 0, - 0, - 18845, - 18846, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18848, - 0, - 0, - 0, - 18853, - 18860, - 0, - 0, - 18862, - 18866, - 0, - 0, - 18867, - 18869, - 0, - 0, - 18874, - 18881, - 18891, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18892, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18895, - 0, - 18896, - 0, - 0, - 0, - 18900, - 0, - 0, - 0, - 18901, - 0, - 18902, - 18915, - 18916, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18919, - 0, - 0, - 0, - 0, - 0, - 18920, - 0, - 0, - 0, - 18921, - 18929, - 0, - 0, - 0, - 0, - 18930, - 0, - 0, - 0, - 0, - 0, - 0, - 18932, - 0, - 0, - 0, - 0, - 18934, - 18942, - 0, - 0, - 0, - 18951, - 18957, - 0, - 0, - 0, - 0, - 18958, - 0, - 0, - 0, - 0, - 18959, - 18960, - 0, - 0, - 18961, - 0, - 0, - 18962, - 0, - 0, - 0, - 0, - 18963, - 18964, - 0, - 0, - 0, - 18965, - 0, - 18967, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18968, - 0, - 18969, - 0, - 18970, - 18973, - 18976, - 0, - 0, - 0, - 0, - 0, - 0, - 18977, - 0, - 0, - 0, - 18981, - 0, - 0, - 0, - 18990, - 0, - 18998, - 0, - 0, - 0, - 0, - 0, - 18999, - 19003, - 0, - 0, - 19005, - 0, - 0, - 0, - 19006, - 0, - 0, - 0, - 0, - 0, - 0, - 19008, - 19011, - 0, - 0, - 19018, - 0, - 0, - 19019, - 0, - 19024, - 0, - 19031, - 19032, - 0, - 19039, - 0, - 19041, - 19050, - 0, - 0, - 0, - 19051, - 19055, - 19056, - 0, - 19059, - 19063, - 19064, - 0, - 0, - 19088, - 0, - 0, - 0, - 19093, - 19094, - 0, - 0, - 0, - 0, - 19095, - 0, - 19096, - 0, - 0, - 0, - 19097, - 0, - 0, - 19098, - 0, - 19099, - 19100, - 0, - 0, - 19103, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19111, - 0, - 0, - 0, - 0, - 0, - 0, - 19112, - 0, - 0, - 0, - 19116, - 19117, - 0, - 19121, - 19122, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19123, - 19124, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19125, - 19126, - 0, - 19128, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19129, - 19130, - 19131, - 19132, - 0, - 0, - 19146, - 0, - 0, - 19147, - 19156, - 19158, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19182, - 19185, - 0, - 0, - 19187, - 0, - 0, - 0, - 19193, - 0, - 0, - 0, - 0, - 0, - 19194, - 0, - 19197, - 0, - 0, - 0, - 0, - 19198, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19202, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19203, - 0, - 19205, - 19210, - 0, - 0, - 0, - 19213, - 0, - 19218, - 0, - 0, - 0, - 19223, - 19229, - 0, - 0, - 19230, - 0, - 0, - 19231, - 19232, - 19233, - 19239, - 0, - 0, - 0, - 0, - 0, - 19240, - 0, - 19248, - 19249, - 0, - 0, - 0, - 0, - 19254, - 0, - 19256, - 19258, - 19259, - 0, - 0, - 19261, - 0, - 19266, - 0, - 0, - 0, - 19272, - 0, - 19278, - 19281, - 19282, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19283, - 0, - 0, - 19284, - 0, - 0, - 19285, - 19287, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19288, - 19291, - 0, - 19292, - 0, - 0, - 0, - 0, - 19297, - 0, - 19298, - 0, - 0, - 0, - 0, - 19302, - 19303, - 0, - 0, - 0, - 0, - 19304, - 19305, - 0, - 0, - 0, - 0, - 19314, - 0, - 0, - 19315, - 0, - 0, - 19321, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19322, - 0, - 19333, - 0, - 19334, - 19335, - 0, - 19336, - 19337, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19346, - 0, - 0, - 19353, - 0, - 19354, - 19362, - 0, - 19366, - 19367, - 0, - 0, - 19369, - 0, - 19375, - 0, - 19377, - 19380, - 19388, - 0, - 0, - 0, - 0, - 0, - 19389, - 19390, - 0, - 0, - 0, - 0, - 19392, - 0, - 0, - 0, - 0, - 0, - 19402, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19412, - 0, - 0, - 19413, - 19422, - 0, - 19424, - 0, - 0, - 0, - 19425, - 0, - 0, - 0, - 19428, - 0, - 0, - 0, - 0, - 19431, - 0, - 0, - 0, - 0, - 0, - 19432, - 0, - 0, - 0, - 0, - 0, - 19448, - 19459, - 0, - 0, - 19461, - 0, - 19462, - 19463, - 0, - 19467, - 19474, - 19482, - 0, - 0, - 0, - 0, - 19494, - 0, - 0, - 0, - 0, - 19501, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19502, - 19504, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19505, - 0, - 0, - 0, - 0, - 19506, - 19507, - 0, - 0, - 0, - 19508, - 0, - 0, - 19511, - 0, - 0, - 19514, - 0, - 19515, - 0, - 19516, - 0, - 19518, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19530, - 0, - 19537, - 19538, - 0, - 19543, - 19546, - 0, - 19547, - 19551, - 0, - 0, - 0, - 0, - 0, - 0, - 19552, - 19553, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19555, - 0, - 0, - 19556, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19560, - 19561, - 0, - 0, - 19562, - 0, - 0, - 0, - 0, - 0, - 0, - 19565, - 19567, - 0, - 19568, - 0, - 0, - 0, - 19569, - 19570, - 0, - 19578, - 0, - 0, - 0, - 0, - 19580, - 0, - 0, - 0, - 0, - 19581, - 19584, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19585, - 19586, - 0, - 0, - 0, - 19587, - 19588, - 0, - 19589, - 0, - 0, - 0, - 0, - 0, - 0, - 19592, - 19593, - 19599, - 0, - 19600, - 0, - 0, - 19604, - 0, - 0, - 19605, - 0, - 19606, - 19608, - 19610, - 0, - 19613, - 19614, - 0, - 0, - 0, - 0, - 0, - 0, - 19616, - 19617, - 0, - 0, - 19618, - 0, - 0, - 19619, - 0, - 0, - 0, - 19620, - 19621, - 19631, - 0, - 0, - 19632, - 19634, - 19636, - 0, - 19643, - 0, - 0, - 19644, - 19658, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19659, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19675, - 19677, - 0, - 0, - 0, - 0, - 19679, - 0, - 19683, - 0, - 19684, - 0, - 0, - 0, - 0, - 0, - 0, - 19687, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19688, - 19689, - 19692, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19695, - 19697, - 0, - 0, - 0, - 0, - 0, - 19698, - 19699, - 0, - 0, - 19700, - 0, - 19702, - 0, - 0, - 19703, - 0, - 0, - 0, - 0, - 0, - 0, - 19704, - 19708, - 0, - 19710, - 0, - 19713, - 0, - 0, - 0, - 19715, - 0, - 0, - 0, - 0, - 19718, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19720, - 0, - 19722, - 0, - 0, - 19725, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19730, - 0, - 0, - 0, - 0, - 0, - 19731, - 0, - 19734, - 19735, - 19739, - 0, - 0, - 19740, - 0, - 19741, - 0, - 0, - 0, - 19746, - 0, - 0, - 19747, - 0, - 19771, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19772, - 19775, - 0, - 0, - 0, - 0, - 0, - 0, - 19778, - 0, - 0, - 0, - 0, - 0, - 19779, - 0, - 0, - 19780, - 19790, - 0, - 19791, - 0, - 0, - 19792, - 0, - 0, - 0, - 19793, - 0, - 0, - 19796, - 19797, - 0, - 0, - 0, - 19799, - 0, - 0, - 0, - 19801, - 0, - 0, - 0, - 0, - 19803, - 0, - 19804, - 0, - 19805, - 0, - 0, - 19807, - 0, - 0, - 0, - 19808, - 0, - 0, - 0, - 0, - 0, - 0, - 19809, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19816, - 0, - 19821, - 0, - 19822, - 19830, - 19831, - 0, - 0, - 0, - 19833, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19838, - 0, - 0, - 0, - 0, - 19839, - 0, - 0, - 19843, - 0, - 0, - 0, - 0, - 19845, - 0, - 0, - 0, - 0, - 19847, - 0, - 0, - 19848, - 0, - 19849, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19851, - 0, - 0, - 0, - 19854, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19864, - 0, - 19865, - 0, - 19866, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19868, - 0, - 0, - 19870, - 0, - 0, - 19871, - 0, - 0, - 19872, - 19873, - 19875, - 0, - 19880, - 19882, - 19884, - 0, - 0, - 19885, - 19886, - 19888, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19890, - 19892, - 19893, - 0, - 0, - 19894, - 0, - 0, - 0, - 19895, - 0, - 19896, - 19902, - 0, - 0, - 19903, - 0, - 0, - 19905, - 0, - 0, - 0, - 19906, - 0, - 19908, - 0, - 19909, - 19911, - 0, - 0, - 0, - 19913, - 19920, - 0, - 19938, - 19939, - 19940, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 19942, - 0, - 19943, - 0, - 19945, - 0, - 0, - 0, - 19951, - 19952, - 19954, - 19960, - 0, - 19965, - 0, - 19971, - 0, - 0, - 0, - 0, - 0, - 19975, - 0, - 19976, - 0, - 19990, - 0, - 0, - 19991, - 0, - 19993, - 0, - 19995, - 0, - 0, - 0, - 19998, - 19999, - 20001, - 0, - 20003, - 20005, - 0, - 20011, - 20012, - 0, - 0, - 0, - 0, - 0, - 0, - 20014, - 0, - 20020, - 0, - 0, - 0, - 0, - 20021, - 0, - 0, - 0, - 0, - 0, - 20023, - 20024, - 0, - 0, - 0, - 0, - 0, - 20025, - 0, - 0, - 20027, - 0, - 0, - 20029, - 0, - 0, - 20032, - 0, - 0, - 0, - 0, - 20044, - 20045, - 0, - 20048, - 20049, - 0, - 0, - 20050, - 0, - 20052, - 0, - 0, - 20054, - 20057, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20059, - 0, - 0, - 20061, - 0, - 20062, - 0, - 20064, - 0, - 0, - 20066, - 0, - 0, - 20067, - 0, - 0, - 0, - 0, - 20069, - 0, - 0, - 0, - 0, - 0, - 0, - 20070, - 20071, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20072, - 0, - 0, - 20073, - 20074, - 0, - 0, - 0, - 0, - 0, - 20075, - 0, - 20078, - 0, - 0, - 0, - 0, - 20080, - 0, - 20081, - 0, - 0, - 0, - 0, - 0, - 0, - 20095, - 0, - 20098, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20107, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20112, - 0, - 0, - 0, - 20113, - 20114, - 0, - 0, - 0, - 20115, - 20123, - 20124, - 0, - 0, - 0, - 20131, - 20133, - 20134, - 0, - 0, - 0, - 0, - 20136, - 0, - 0, - 20137, - 20138, - 20150, - 0, - 20152, - 0, - 0, - 0, - 20153, - 0, - 0, - 20154, - 0, - 0, - 0, - 20158, - 0, - 20163, - 0, - 0, - 20164, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20166, - 0, - 20168, - 0, - 20170, - 0, - 20175, - 0, - 0, - 20178, - 0, - 0, - 0, - 0, - 20223, - 0, - 0, - 0, - 0, - 20224, - 0, - 20226, - 0, - 0, - 20230, - 0, - 20231, - 0, - 0, - 0, - 0, - 20232, - 0, - 0, - 20233, - 20234, - 0, - 20244, - 0, - 20247, - 0, - 0, - 0, - 0, - 0, - 0, - 20249, - 0, - 0, - 0, - 20250, - 0, - 0, - 0, - 0, - 20251, - 0, - 20253, - 0, - 20254, - 0, - 0, - 0, - 0, - 20256, - 0, - 0, - 20264, - 0, - 0, - 0, - 0, - 20266, - 0, - 0, - 0, - 20278, - 0, - 0, - 20279, - 20282, - 0, - 0, - 0, - 0, - 0, - 20283, - 0, - 20284, - 0, - 20285, - 0, - 20287, - 20290, - 0, - 0, - 0, - 0, - 20292, - 0, - 0, - 0, - 0, - 20293, - 20297, - 0, - 0, - 0, - 0, - 0, - 0, - 20299, - 0, - 20300, - 20303, - 0, - 0, - 0, - 0, - 0, - 0, - 20307, - 0, - 0, - 20308, - 0, - 20309, - 0, - 20310, - 0, - 0, - 0, - 0, - 0, - 0, - 20312, - 0, - 0, - 0, - 20314, - 0, - 0, - 0, - 0, - 20315, - 20316, - 0, - 20322, - 0, - 0, - 0, - 0, - 0, - 0, - 20339, - 0, - 0, - 0, - 20342, - 0, - 0, - 0, - 0, - 20352, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20362, - 0, - 0, - 20365, - 0, - 20375, - 20377, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20378, - 20379, - 0, - 20380, - 0, - 0, - 20381, - 0, - 20382, - 0, - 20383, - 0, - 20388, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20390, - 20392, - 20393, - 0, - 0, - 20395, - 0, - 0, - 0, - 0, - 0, - 20396, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20398, - 20415, - 0, - 0, - 0, - 20417, - 0, - 0, - 20420, - 0, - 0, - 20426, - 20428, - 0, - 20431, - 0, - 0, - 20432, - 0, - 20433, - 20434, - 20435, - 0, - 0, - 0, - 0, - 20440, - 0, - 0, - 0, - 0, - 0, - 20442, - 0, - 20443, - 0, - 20446, - 0, - 0, - 0, - 0, - 20448, - 0, - 20451, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20452, - 20453, - 0, - 0, - 20454, - 0, - 0, - 0, - 0, - 0, - 0, - 20457, - 0, - 20458, - 0, - 0, - 0, - 20465, - 0, - 0, - 0, - 0, - 0, - 20469, - 0, - 0, - 0, - 20473, - 0, - 20476, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20477, - 0, - 0, - 20485, - 0, - 0, - 20486, - 0, - 0, - 20487, - 0, - 20496, - 0, - 20497, - 0, - 0, - 20498, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20499, - 20500, - 0, - 20501, - 0, - 0, - 0, - 0, - 0, - 20520, - 20527, - 0, - 20529, - 0, - 0, - 0, - 0, - 20539, - 0, - 0, - 20540, - 0, - 0, - 0, - 20543, - 0, - 0, - 0, - 20546, - 0, - 0, - 0, - 0, - 0, - 20548, - 0, - 0, - 20563, - 0, - 0, - 20564, - 0, - 20566, - 0, - 0, - 0, - 0, - 0, - 20589, - 0, - 0, - 0, - 0, - 20590, - 0, - 0, - 20593, - 20594, - 0, - 0, - 0, - 0, - 20595, - 0, - 20597, - 20598, - 0, - 0, - 0, - 20618, - 20620, - 0, - 0, - 0, - 0, - 20621, - 0, - 0, - 0, - 0, - 20627, - 0, - 0, - 0, - 0, - 0, - 20628, - 0, - 0, - 0, - 20629, - 0, - 20630, - 0, - 0, - 20639, - 0, - 0, - 0, - 0, - 0, - 20707, - 0, - 0, - 20709, - 0, - 0, - 0, - 20713, - 20714, - 0, - 0, - 0, - 0, - 0, - 20724, - 20725, - 0, - 0, - 0, - 0, - 20726, - 20728, - 20729, - 0, - 20733, - 0, - 20734, - 0, - 20735, - 20736, - 0, - 20737, - 0, - 0, - 20744, - 0, - 20745, - 0, - 20748, - 0, - 0, - 20749, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20750, - 0, - 0, - 0, - 0, - 20754, - 0, - 0, - 0, - 20761, - 0, - 0, - 20763, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20766, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20767, - 0, - 0, - 0, - 0, - 20768, - 0, - 20769, - 20777, - 0, - 0, - 0, - 0, - 0, - 0, - 20785, - 0, - 0, - 0, - 20786, - 20795, - 20801, - 0, - 20802, - 0, - 20807, - 0, - 0, - 20808, - 0, - 0, - 20810, - 0, - 0, - 20811, - 0, - 20812, - 0, - 0, - 0, - 0, - 0, - 20813, - 0, - 0, - 20818, - 20820, - 20821, - 0, - 0, - 0, - 20822, - 0, - 20823, - 0, - 0, - 0, - 20826, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20829, - 20830, - 20831, - 0, - 20832, - 20836, - 0, - 0, - 20839, - 0, - 0, - 20840, - 20842, - 0, - 20843, - 0, - 20844, - 0, - 20854, - 0, - 0, - 0, - 20855, - 0, - 0, - 0, - 0, - 20856, - 0, - 0, - 0, - 20869, - 0, - 0, - 20871, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20873, - 0, - 0, - 0, - 0, - 0, - 20876, - 0, - 0, - 0, - 0, - 0, - 20880, - 0, - 0, - 20882, - 0, - 0, - 0, - 0, - 20883, - 20884, - 0, - 0, - 20890, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 20891, - 0, - 0, - 0, - 0, - 0, - 20905, - 0, - 20906, - 20910, - 0, - 0, - 20912, - 20915, - 0, - 0, - 0, - 0, - 0, - 20916, - 0, - 20917, - 0, - 20919, - 20920, - 20922, - 0, - 20927, - 0, - 20928, - 20929, - 20930, - 0, - 0, - 20935, - 0, - 0, - 20939, - 0, - 0, - 20941, - 0, - 0, - 0, - 20943, - 0, - 0, - 0, - 20946, - 20947, - 0, - 0, - 0, - 0, - 0, - 20950, - 0, - 20954, - 0, - 0, - 20955, - 20964, - 0, - 0, - 20967, - 0, - 0, - 0, - 0, - 0, - 20973, - 20975, - 0, - 0, - 0, - 20984, - 0, - 20987, - 20988, - 0, - 0, - 0, - 0, - 0, - 20989, - 0, - 0, - 0, - 20995, - 0, - 20998, - 0, - 20999, - 0, - 0, - 0, - 0, - 21000, - 21001, - 0, - 0, - 0, - 0, - 21008, - 0, - 21010, - 0, - 21016, - 0, - 0, - 0, - 21017, - 21018, - 0, - 0, - 0, - 0, - 0, - 21021, - 21026, - 21027, - 21028, - 0, - 0, - 21029, - 0, - 0, - 0, - 0, - 0, - 21030, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21031, - 21032, - 0, - 0, - 0, - 0, - 0, - 21037, - 0, - 0, - 21038, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21039, - 0, - 21041, - 0, - 21046, - 21047, - 0, - 0, - 0, - 21049, - 21053, - 0, - 0, - 21057, - 21064, - 21065, - 0, - 0, - 21066, - 21067, - 0, - 0, - 0, - 21069, - 0, - 0, - 0, - 21071, - 21072, - 0, - 0, - 21073, - 0, - 21074, - 0, - 0, - 21078, - 0, - 0, - 0, - 0, - 21079, - 0, - 0, - 21080, - 21081, - 0, - 0, - 21086, - 21087, - 0, - 21089, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21091, - 0, - 21093, - 0, - 21094, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21095, - 0, - 0, - 0, - 0, - 0, - 21096, - 0, - 21098, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21099, - 0, - 0, - 21100, - 21101, - 21102, - 0, - 0, - 0, - 0, - 0, - 21103, - 0, - 21104, - 0, - 0, - 0, - 0, - 0, - 21105, - 21108, - 21109, - 0, - 0, - 21112, - 21113, - 0, - 0, - 0, - 0, - 0, - 0, - 21115, - 21122, - 21123, - 0, - 0, - 0, - 0, - 0, - 21125, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21129, - 21131, - 0, - 0, - 21134, - 0, - 0, - 0, - 21137, - 21142, - 0, - 21143, - 0, - 0, - 21144, - 0, - 21145, - 21146, - 0, - 21152, - 21154, - 21155, - 21156, - 0, - 0, - 0, - 21160, - 0, - 0, - 0, - 0, - 0, - 0, - 21161, - 0, - 21164, - 0, - 21166, - 0, - 0, - 0, - 0, - 21170, - 0, - 0, - 0, - 0, - 21171, - 0, - 0, - 21172, - 0, - 21174, - 0, - 21175, - 0, - 0, - 0, - 0, - 0, - 21176, - 21179, - 21188, - 0, - 0, - 0, - 21189, - 0, - 0, - 21190, - 0, - 0, - 0, - 21192, - 0, - 0, - 21193, - 0, - 0, - 0, - 21198, - 0, - 21212, - 0, - 0, - 21213, - 0, - 0, - 0, - 0, - 0, - 0, - 21215, - 21216, - 0, - 0, - 21223, - 21225, - 0, - 21226, - 0, - 0, - 0, - 0, - 21227, - 21228, - 0, - 0, - 21229, - 0, - 0, - 0, - 0, - 21230, - 21236, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21237, - 0, - 0, - 21238, - 21239, - 0, - 0, - 0, - 0, - 21256, - 0, - 0, - 0, - 0, - 0, - 21257, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21259, - 0, - 0, - 0, - 21263, - 0, - 21272, - 0, - 21274, - 0, - 21282, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21283, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21294, - 0, - 0, - 21297, - 0, - 0, - 0, - 0, - 21298, - 0, - 0, - 0, - 21299, - 0, - 21300, - 21302, - 0, - 21316, - 0, - 21318, - 21322, - 21323, - 0, - 21324, - 0, - 21326, - 0, - 0, - 0, - 21327, - 21328, - 0, - 0, - 0, - 21352, - 0, - 0, - 21354, - 21361, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21362, - 0, - 0, - 0, - 21363, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21366, - 0, - 0, - 21367, - 21372, - 21374, - 0, - 0, - 0, - 21375, - 21377, - 0, - 21378, - 0, - 0, - 0, - 21380, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21381, - 0, - 0, - 0, - 0, - 0, - 0, - 21382, - 0, - 21383, - 0, - 0, - 21384, - 0, - 0, - 21385, - 0, - 0, - 0, - 0, - 21389, - 21390, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21397, - 21398, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21399, - 0, - 21400, - 0, - 0, - 0, - 0, - 21402, - 0, - 0, - 0, - 21403, - 21404, - 0, - 21405, - 21406, - 0, - 0, - 0, - 21407, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21408, - 0, - 0, - 0, - 0, - 21409, - 0, - 21421, - 0, - 21422, - 0, - 0, - 0, - 21425, - 21428, - 0, - 0, - 0, - 0, - 21429, - 0, - 0, - 0, - 0, - 0, - 21433, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21434, - 0, - 21443, - 0, - 21444, - 21449, - 0, - 21452, - 0, - 21453, - 21454, - 0, - 0, - 0, - 21457, - 0, - 0, - 21458, - 0, - 0, - 0, - 21460, - 21461, - 0, - 0, - 21464, - 0, - 0, - 0, - 21473, - 21478, - 0, - 0, - 21479, - 0, - 0, - 21481, - 21483, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21484, - 0, - 0, - 21485, - 21486, - 0, - 0, - 21488, - 0, - 0, - 0, - 0, - 0, - 0, - 21523, - 0, - 0, - 21525, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21526, - 0, - 0, - 0, - 0, - 0, - 0, - 21529, - 21530, - 0, - 0, - 21531, - 0, - 0, - 21533, - 0, - 0, - 21539, - 21564, - 0, - 21567, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21575, - 0, - 0, - 0, - 0, - 21577, - 0, - 0, - 0, - 0, - 0, - 21591, - 0, - 0, - 21604, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21605, - 0, - 21606, - 0, - 0, - 21617, - 21618, - 21619, - 21620, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21623, - 0, - 0, - 0, - 0, - 21631, - 0, - 21635, - 0, - 0, - 0, - 0, - 21639, - 21646, - 21653, - 21662, - 0, - 0, - 21663, - 21664, - 0, - 21666, - 0, - 0, - 21667, - 0, - 21670, - 21672, - 21673, - 0, - 21674, - 21683, - 0, - 0, - 0, - 0, - 0, - 21684, - 0, - 21694, - 0, - 0, - 0, - 0, - 21695, - 21700, - 0, - 21703, - 0, - 21704, - 0, - 0, - 21709, - 0, - 0, - 0, - 21710, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21711, - 0, - 0, - 0, - 21712, - 0, - 21717, - 0, - 21730, - 0, - 0, - 0, - 21731, - 21733, - 0, - 0, - 0, - 0, - 21737, - 21741, - 21742, - 0, - 21747, - 0, - 0, - 0, - 21749, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21750, - 0, - 0, - 0, - 0, - 0, - 21752, - 0, - 0, - 0, - 0, - 21753, - 0, - 0, - 0, - 0, - 0, - 0, - 21755, - 21756, - 0, - 21757, - 0, - 0, - 0, - 0, - 0, - 0, - 21760, - 0, - 0, - 21763, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21764, - 0, - 0, - 21766, - 0, - 0, - 21767, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21773, - 0, - 21774, - 0, - 0, - 21775, - 0, - 0, - 0, - 0, - 21776, - 0, - 0, - 21777, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21780, - 21787, - 21788, - 21791, - 0, - 0, - 0, - 21797, - 0, - 0, - 0, - 0, - 0, - 21805, - 0, - 0, - 0, - 0, - 21806, - 0, - 21807, - 21809, - 0, - 21810, - 21811, - 0, - 21817, - 21819, - 21820, - 0, - 21823, - 0, - 21824, - 0, - 0, - 21825, - 0, - 0, - 21826, - 21832, - 0, - 0, - 0, - 0, - 0, - 21833, - 21848, - 21849, - 0, - 0, - 21867, - 21870, - 21871, - 21873, - 0, - 0, - 0, - 21874, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21875, - 0, - 21878, - 0, - 0, - 0, - 21879, - 0, - 21881, - 21886, - 0, - 0, - 0, - 0, - 21887, - 0, - 0, - 21888, - 21894, - 21895, - 21897, - 0, - 21901, - 0, - 21904, - 0, - 0, - 21906, - 0, - 0, - 0, - 21909, - 21910, - 21911, - 0, - 0, - 21912, - 0, - 0, - 21913, - 21914, - 21915, - 0, - 21919, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21921, - 0, - 0, - 21922, - 21933, - 21939, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21944, - 0, - 0, - 0, - 0, - 0, - 21945, - 0, - 21947, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21949, - 0, - 0, - 0, - 21950, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21951, - 0, - 21952, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21954, - 21957, - 0, - 0, - 0, - 0, - 21958, - 0, - 21959, - 0, - 0, - 0, - 0, - 0, - 0, - 21962, - 21963, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 21964, - 21965, - 0, - 0, - 21969, - 21970, - 0, - 0, - 0, - 21974, - 0, - 0, - 21980, - 21981, - 0, - 21982, - 0, - 0, - 0, - 0, - 0, - 21985, - 0, - 21988, - 0, - 21992, - 0, - 21999, - 0, - 0, - 0, - 0, - 0, - 0, - 22001, - 0, - 22002, - 0, - 0, - 0, - 0, - 0, - 0, - 22003, - 0, - 0, - 0, - 0, - 0, - 22004, - 0, - 0, - 0, - 22008, - 0, - 22009, - 22015, - 0, - 0, - 22016, - 0, - 0, - 0, - 22017, - 22019, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22020, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22021, - 22037, - 0, - 22039, - 0, - 0, - 0, - 22040, - 0, - 0, - 0, - 22048, - 22049, - 0, - 0, - 22053, - 22055, - 22056, - 22059, - 0, - 0, - 22060, - 22061, - 0, - 0, - 22064, - 0, - 0, - 0, - 0, - 22066, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22073, - 0, - 0, - 0, - 22074, - 22075, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22076, - 0, - 0, - 0, - 0, - 22077, - 22084, - 22099, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22104, - 0, - 0, - 22107, - 0, - 22108, - 0, - 22109, - 0, - 22110, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22111, - 22119, - 0, - 22120, - 22122, - 0, - 0, - 0, - 0, - 22125, - 0, - 0, - 0, - 22128, - 22129, - 0, - 0, - 0, - 0, - 0, - 0, - 22141, - 0, - 0, - 0, - 22142, - 0, - 0, - 22144, - 22146, - 0, - 22148, - 22149, - 22151, - 22154, - 0, - 0, - 0, - 22162, - 0, - 0, - 0, - 0, - 22164, - 22177, - 0, - 0, - 0, - 0, - 22179, - 0, - 22182, - 22183, - 0, - 0, - 22184, - 22188, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22190, - 0, - 22194, - 22201, - 0, - 0, - 22208, - 0, - 22209, - 0, - 22212, - 0, - 0, - 22215, - 0, - 22223, - 22231, - 0, - 0, - 22232, - 0, - 22234, - 0, - 0, - 22235, - 22236, - 0, - 22237, - 0, - 22240, - 0, - 0, - 0, - 0, - 0, - 22241, - 0, - 0, - 0, - 22242, - 22246, - 22247, - 0, - 0, - 0, - 22259, - 22268, - 0, - 22269, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22270, - 0, - 0, - 0, - 0, - 22271, - 0, - 22272, - 0, - 22277, - 0, - 0, - 0, - 0, - 0, - 22278, - 22280, - 22283, - 22286, - 0, - 0, - 22287, - 22289, - 0, - 0, - 22290, - 0, - 22293, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22295, - 0, - 22301, - 22302, - 0, - 0, - 0, - 22305, - 0, - 22308, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22315, - 0, - 0, - 0, - 22317, - 0, - 22334, - 0, - 0, - 0, - 22335, - 0, - 0, - 0, - 0, - 0, - 22336, - 0, - 22338, - 22344, - 0, - 22347, - 22349, - 0, - 22350, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22357, - 0, - 0, - 0, - 0, - 0, - 22358, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22359, - 22360, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22361, - 22366, - 0, - 0, - 22369, - 0, - 22370, - 22373, - 0, - 0, - 0, - 0, - 0, - 22375, - 0, - 22377, - 0, - 0, - 0, - 0, - 0, - 22378, - 0, - 0, - 0, - 0, - 22381, - 0, - 0, - 0, - 0, - 22382, - 0, - 22383, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22391, - 0, - 0, - 22392, - 22395, - 22396, - 22402, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22405, - 0, - 0, - 22406, - 0, - 0, - 22408, - 0, - 0, - 22409, - 22410, - 0, - 0, - 0, - 0, - 0, - 0, - 22424, - 0, - 0, - 0, - 0, - 22426, - 0, - 0, - 0, - 22427, - 0, - 22428, - 0, - 22432, - 0, - 22435, - 22442, - 22443, - 0, - 0, - 0, - 0, - 22444, - 0, - 0, - 0, - 0, - 0, - 22446, - 0, - 22454, - 0, - 22455, - 0, - 0, - 0, - 22465, - 0, - 22470, - 0, - 22471, - 0, - 0, - 0, - 0, - 22472, - 22473, - 0, - 22487, - 0, - 0, - 0, - 22488, - 0, - 0, - 0, - 0, - 22489, - 0, - 0, - 22499, - 0, - 0, - 0, - 0, - 0, - 0, - 22514, - 0, - 0, - 22515, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22516, - 0, - 0, - 0, - 22517, - 22520, - 0, - 0, - 0, - 22534, - 0, - 0, - 22535, - 0, - 0, - 22536, - 0, - 22540, - 22553, - 0, - 22555, - 0, - 0, - 0, - 0, - 22561, - 0, - 0, - 22562, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22566, - 0, - 0, - 0, - 0, - 22567, - 22568, - 0, - 0, - 22575, - 0, - 22579, - 0, - 22582, - 22583, - 22585, - 0, - 0, - 0, - 0, - 0, - 22586, - 0, - 0, - 22587, - 0, - 0, - 22590, - 0, - 0, - 0, - 0, - 0, - 22591, - 0, - 22592, - 0, - 0, - 0, - 0, - 0, - 22593, - 0, - 22602, - 0, - 0, - 22604, - 0, - 0, - 22609, - 0, - 0, - 22618, - 0, - 0, - 0, - 0, - 0, - 0, - 22619, - 0, - 22624, - 22625, - 0, - 0, - 22638, - 0, - 0, - 0, - 0, - 0, - 22639, - 0, - 0, - 22640, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22644, - 0, - 22645, - 22647, - 0, - 0, - 0, - 0, - 22652, - 22653, - 0, - 0, - 0, - 22654, - 0, - 22655, - 0, - 0, - 0, - 22656, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22673, - 22675, - 22676, - 0, - 0, - 22678, - 22679, - 0, - 22691, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22693, - 0, - 0, - 22696, - 0, - 22699, - 22707, - 22708, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22718, - 0, - 22719, - 0, - 0, - 0, - 0, - 22723, - 0, - 0, - 0, - 22724, - 22725, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22726, - 22728, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22729, - 0, - 0, - 22731, - 0, - 0, - 0, - 0, - 22732, - 22735, - 22736, - 0, - 0, - 0, - 0, - 22739, - 0, - 22749, - 0, - 0, - 22751, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22758, - 0, - 0, - 0, - 0, - 0, - 22760, - 0, - 0, - 0, - 0, - 0, - 22764, - 22765, - 22766, - 0, - 22768, - 0, - 0, - 0, - 0, - 0, - 22769, - 22770, - 0, - 0, - 0, - 0, - 0, - 0, - 22771, - 0, - 0, - 22772, - 22775, - 0, - 22776, - 22777, - 22780, - 0, - 0, - 22782, - 22784, - 0, - 22787, - 0, - 22789, - 22796, - 0, - 0, - 0, - 0, - 0, - 22798, - 0, - 0, - 0, - 0, - 0, - 0, - 22802, - 0, - 22803, - 22804, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22805, - 0, - 0, - 22810, - 22811, - 22814, - 22816, - 0, - 22825, - 22826, - 0, - 22831, - 22833, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22834, - 0, - 22836, - 22838, - 0, - 22839, - 0, - 0, - 0, - 0, - 0, - 22840, - 0, - 22847, - 0, - 0, - 0, - 0, - 0, - 22856, - 22857, - 0, - 22858, - 22859, - 0, - 0, - 22862, - 0, - 0, - 22864, - 0, - 0, - 0, - 0, - 22865, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22866, - 0, - 22867, - 22868, - 0, - 0, - 0, - 0, - 22869, - 0, - 22871, - 0, - 22872, - 0, - 22873, - 22881, - 22882, - 22884, - 22885, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22886, - 22887, - 0, - 22894, - 0, - 22895, - 0, - 0, - 0, - 22900, - 0, - 22901, - 0, - 0, - 0, - 0, - 22904, - 0, - 0, - 0, - 0, - 22905, - 22907, - 0, - 0, - 0, - 22915, - 22917, - 0, - 0, - 22918, - 0, - 0, - 0, - 22920, - 0, - 0, - 0, - 22929, - 22930, - 0, - 0, - 0, - 22941, - 22942, - 0, - 0, - 0, - 22943, - 0, - 0, - 0, - 22944, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22946, - 0, - 22947, - 0, - 0, - 22954, - 0, - 22956, - 0, - 0, - 22962, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22963, - 0, - 0, - 22964, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 22965, - 0, - 22968, - 0, - 0, - 0, - 22969, - 0, - 0, - 0, - 0, - 0, - 22970, - 0, - 22971, - 0, - 0, - 0, - 0, - 0, - 22978, - 0, - 0, - 22979, - 0, - 22987, - 0, - 0, - 22989, - 0, - 0, - 0, - 0, - 0, - 0, - 22990, - 0, - 23005, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23006, - 23007, - 23008, - 0, - 0, - 23023, - 23024, - 23029, - 0, - 0, - 0, - 0, - 23030, - 0, - 0, - 0, - 0, - 0, - 23032, - 0, - 0, - 0, - 0, - 0, - 23035, - 0, - 0, - 0, - 0, - 23038, - 0, - 0, - 0, - 23048, - 0, - 23049, - 23052, - 23053, - 23060, - 23061, - 0, - 23063, - 0, - 0, - 0, - 0, - 23067, - 23068, - 0, - 0, - 0, - 23069, - 23073, - 0, - 0, - 0, - 23127, - 0, - 23128, - 0, - 0, - 0, - 0, - 0, - 23129, - 0, - 23138, - 23141, - 0, - 23149, - 0, - 0, - 23150, - 0, - 0, - 0, - 23152, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23154, - 0, - 0, - 0, - 0, - 23157, - 23159, - 23160, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23180, - 0, - 0, - 0, - 0, - 23181, - 0, - 0, - 23188, - 0, - 23189, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23195, - 0, - 0, - 23196, - 23199, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23202, - 0, - 23204, - 0, - 23207, - 0, - 23209, - 23210, - 0, - 0, - 0, - 0, - 0, - 0, - 23227, - 23229, - 0, - 0, - 23230, - 23234, - 23238, - 0, - 0, - 0, - 23245, - 23246, - 23248, - 0, - 0, - 0, - 0, - 23249, - 23254, - 0, - 0, - 0, - 23265, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23268, - 0, - 23276, - 0, - 0, - 0, - 0, - 23277, - 0, - 23297, - 0, - 23298, - 0, - 0, - 0, - 0, - 23299, - 0, - 23302, - 0, - 0, - 23303, - 23312, - 0, - 0, - 23314, - 0, - 23320, - 0, - 0, - 0, - 0, - 23324, - 0, - 23325, - 0, - 23328, - 0, - 23334, - 0, - 0, - 0, - 23337, - 0, - 0, - 0, - 0, - 23343, - 23344, - 23346, - 0, - 23348, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23353, - 0, - 0, - 0, - 0, - 23355, - 0, - 23356, - 23358, - 0, - 0, - 0, - 23359, - 23360, - 0, - 23361, - 0, - 23367, - 0, - 23369, - 0, - 0, - 23373, - 0, - 23378, - 23379, - 0, - 23382, - 23383, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23387, - 0, - 0, - 0, - 0, - 0, - 0, - 23388, - 23390, - 0, - 0, - 23393, - 23398, - 0, - 0, - 0, - 23399, - 0, - 0, - 0, - 23400, - 0, - 0, - 0, - 0, - 23401, - 0, - 0, - 0, - 23415, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23416, - 0, - 23422, - 0, - 23443, - 23444, - 0, - 0, - 0, - 0, - 23448, - 0, - 23454, - 0, - 0, - 0, - 0, - 0, - 0, - 23456, - 0, - 0, - 23458, - 23464, - 0, - 0, - 0, - 0, - 0, - 0, - 23465, - 0, - 0, - 0, - 23470, - 23471, - 0, - 0, - 23472, - 0, - 0, - 0, - 23473, - 23496, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23497, - 0, - 23499, - 0, - 0, - 23502, - 0, - 0, - 23503, - 0, - 0, - 23513, - 0, - 0, - 23515, - 0, - 0, - 0, - 23517, - 0, - 0, - 0, - 0, - 23518, - 23519, - 23521, - 23524, - 0, - 23525, - 23528, - 23539, - 0, - 0, - 0, - 0, - 0, - 23541, - 0, - 0, - 23544, - 0, - 0, - 23556, - 0, - 0, - 23557, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23559, - 0, - 23560, - 0, - 0, - 23561, - 0, - 0, - 23566, - 0, - 0, - 0, - 0, - 0, - 23568, - 23569, - 23570, - 0, - 0, - 0, - 0, - 23571, - 0, - 23574, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23575, - 0, - 23579, - 0, - 0, - 23581, - 0, - 0, - 0, - 0, - 0, - 0, - 23587, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23596, - 23598, - 0, - 0, - 0, - 0, - 23602, - 23606, - 0, - 0, - 23607, - 0, - 23608, - 0, - 0, - 0, - 23614, - 23616, - 0, - 0, - 0, - 0, - 0, - 23618, - 0, - 0, - 23619, - 0, - 0, - 0, - 0, - 23621, - 23626, - 0, - 23627, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23629, - 0, - 23630, - 0, - 0, - 0, - 0, - 23634, - 0, - 23636, - 0, - 0, - 0, - 0, - 0, - 0, - 23638, - 0, - 0, - 0, - 0, - 23640, - 23667, - 0, - 23669, - 0, - 0, - 0, - 23681, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23682, - 0, - 23683, - 0, - 0, - 0, - 0, - 0, - 23684, - 0, - 0, - 0, - 23685, - 23689, - 0, - 23693, - 23694, - 23700, - 0, - 23702, - 0, - 23709, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23712, - 0, - 0, - 0, - 0, - 0, - 23714, - 0, - 0, - 23715, - 0, - 0, - 0, - 0, - 23718, - 0, - 0, - 23720, - 0, - 0, - 0, - 0, - 23722, - 0, - 0, - 0, - 23726, - 23729, - 0, - 23741, - 23746, - 0, - 23748, - 0, - 0, - 0, - 0, - 23749, - 0, - 0, - 0, - 0, - 0, - 23750, - 0, - 0, - 0, - 0, - 23751, - 0, - 23753, - 0, - 0, - 0, - 0, - 23757, - 23765, - 0, - 0, - 0, - 23770, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23771, - 0, - 23772, - 23781, - 0, - 0, - 23796, - 0, - 0, - 0, - 0, - 23798, - 0, - 23799, - 0, - 0, - 0, - 23802, - 0, - 0, - 23806, - 0, - 23807, - 0, - 0, - 23808, - 0, - 23809, - 0, - 23819, - 0, - 0, - 0, - 23821, - 0, - 23827, - 0, - 0, - 0, - 23829, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23830, - 0, - 0, - 0, - 0, - 0, - 0, - 23832, - 23833, - 23834, - 23835, - 0, - 0, - 0, - 0, - 23837, - 23838, - 0, - 0, - 0, - 0, - 0, - 23846, - 0, - 0, - 0, - 0, - 0, - 0, - 23847, - 0, - 0, - 0, - 0, - 0, - 23879, - 23881, - 0, - 0, - 23882, - 23883, - 23895, - 0, - 23899, - 0, - 0, - 0, - 0, - 23901, - 0, - 0, - 0, - 0, - 0, - 0, - 23902, - 0, - 0, - 0, - 0, - 0, - 23903, - 23905, - 0, - 23906, - 0, - 23907, - 23918, - 23919, - 23920, - 0, - 23922, - 0, - 23924, - 0, - 23927, - 0, - 23934, - 0, - 23937, - 23941, - 0, - 23942, - 23946, - 0, - 0, - 0, - 0, - 0, - 23955, - 23956, - 23958, - 0, - 0, - 0, - 0, - 0, - 0, - 23959, - 0, - 23962, - 23965, - 0, - 23966, - 0, - 0, - 0, - 0, - 23967, - 23968, - 0, - 0, - 23973, - 0, - 0, - 23974, - 0, - 0, - 0, - 0, - 23975, - 0, - 23976, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23977, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23980, - 0, - 0, - 23984, - 0, - 23985, - 0, - 0, - 23987, - 0, - 0, - 23988, - 23990, - 23991, - 0, - 0, - 0, - 0, - 0, - 0, - 23992, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23994, - 0, - 0, - 0, - 23998, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 23999, - 0, - 0, - 24003, - 0, - 24004, - 0, - 24006, - 0, - 0, - 0, - 24007, - 0, - 0, - 24008, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24009, - 0, - 0, - 24010, - 0, - 0, - 24011, - 0, - 0, - 24013, - 24014, - 0, - 0, - 24015, - 24016, - 24027, - 0, - 24028, - 24029, - 0, - 24030, - 0, - 0, - 0, - 0, - 0, - 24033, - 24034, - 0, - 24035, - 0, - 0, - 24036, - 0, - 0, - 24044, - 0, - 24048, - 24049, - 24063, - 24067, - 0, - 24068, - 24070, - 0, - 0, - 24071, - 24078, - 24087, - 0, - 24090, - 0, - 0, - 0, - 24095, - 0, - 24098, - 24101, - 24104, - 24106, - 0, - 24107, - 0, - 0, - 0, - 24108, - 0, - 0, - 0, - 0, - 24110, - 24111, - 0, - 24113, - 0, - 0, - 24115, - 24120, - 0, - 0, - 0, - 0, - 0, - 0, - 24124, - 0, - 24125, - 0, - 24126, - 0, - 24127, - 0, - 0, - 0, - 0, - 0, - 24135, - 0, - 0, - 24136, - 0, - 24137, - 24142, - 0, - 0, - 0, - 24146, - 0, - 0, - 24147, - 24149, - 24154, - 0, - 24163, - 0, - 0, - 0, - 24165, - 24166, - 24167, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24169, - 24170, - 24175, - 0, - 0, - 0, - 24178, - 0, - 0, - 24179, - 0, - 0, - 24181, - 0, - 24184, - 24197, - 0, - 24201, - 24204, - 0, - 0, - 0, - 0, - 0, - 0, - 24206, - 24212, - 24220, - 0, - 0, - 0, - 24224, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24226, - 0, - 24234, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24235, - 0, - 24236, - 0, - 0, - 0, - 0, - 0, - 24239, - 24240, - 24241, - 0, - 0, - 24248, - 0, - 0, - 24249, - 0, - 24251, - 0, - 0, - 0, - 0, - 0, - 0, - 24253, - 0, - 24268, - 0, - 0, - 0, - 24269, - 0, - 24271, - 24272, - 0, - 0, - 0, - 0, - 24273, - 0, - 0, - 24274, - 0, - 0, - 24279, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24280, - 0, - 24293, - 24294, - 0, - 0, - 0, - 0, - 0, - 0, - 24296, - 0, - 0, - 24323, - 0, - 0, - 0, - 24329, - 24330, - 24331, - 24339, - 0, - 24351, - 0, - 0, - 24369, - 24370, - 0, - 0, - 0, - 24371, - 0, - 0, - 0, - 0, - 24372, - 24373, - 24374, - 0, - 0, - 0, - 0, - 0, - 24378, - 0, - 0, - 0, - 0, - 24379, - 0, - 24381, - 0, - 24383, - 24389, - 0, - 24390, - 0, - 0, - 24394, - 24395, - 24400, - 0, - 0, - 0, - 24401, - 24402, - 0, - 24406, - 0, - 0, - 0, - 24411, - 0, - 0, - 0, - 24415, - 0, - 24416, - 0, - 0, - 0, - 0, - 0, - 24417, - 0, - 24419, - 0, - 24422, - 0, - 24423, - 24428, - 0, - 24435, - 0, - 0, - 0, - 24439, - 0, - 0, - 0, - 24440, - 24442, - 24446, - 0, - 0, - 0, - 24447, - 24448, - 24449, - 24452, - 0, - 0, - 0, - 0, - 24453, - 24457, - 0, - 0, - 24458, - 24459, - 24460, - 0, - 24465, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24470, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24471, - 0, - 24473, - 24474, - 24475, - 24476, - 0, - 24478, - 0, - 0, - 0, - 0, - 24480, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24481, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24482, - 24485, - 0, - 0, - 0, - 0, - 24486, - 0, - 0, - 0, - 24488, - 0, - 0, - 0, - 24494, - 0, - 0, - 0, - 0, - 24497, - 0, - 0, - 24498, - 0, - 0, - 0, - 24499, - 24506, - 0, - 0, - 0, - 24507, - 0, - 0, - 24511, - 0, - 0, - 24513, - 24514, - 0, - 0, - 0, - 0, - 0, - 24517, - 0, - 24518, - 0, - 24520, - 0, - 24521, - 24524, - 24525, - 0, - 0, - 0, - 0, - 0, - 24527, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24528, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24537, - 24539, - 0, - 24540, - 0, - 0, - 0, - 24548, - 0, - 0, - 0, - 0, - 0, - 24549, - 24550, - 0, - 0, - 0, - 24553, - 24554, - 0, - 24555, - 0, - 24556, - 0, - 24558, - 0, - 0, - 0, - 0, - 0, - 24560, - 0, - 0, - 0, - 24561, - 0, - 0, - 0, - 0, - 0, - 24562, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24567, - 0, - 0, - 0, - 0, - 0, - 24569, - 0, - 0, - 0, - 24574, - 0, - 24575, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24577, - 24581, - 0, - 24584, - 0, - 0, - 0, - 0, - 0, - 24585, - 0, - 0, - 0, - 0, - 0, - 24586, - 0, - 0, - 24587, - 0, - 24588, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24590, - 24591, - 0, - 0, - 0, - 0, - 24592, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24594, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24596, - 24597, - 0, - 0, - 0, - 0, - 24602, - 24603, - 0, - 0, - 0, - 0, - 24604, - 0, - 0, - 24605, - 0, - 24610, - 0, - 0, - 24611, - 0, - 0, - 0, - 0, - 24612, - 24615, - 24616, - 24624, - 0, - 0, - 0, - 24627, - 0, - 24638, - 24639, - 0, - 0, - 0, - 0, - 24640, - 0, - 0, - 0, - 24655, - 24656, - 24657, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24662, - 0, - 24663, - 24664, - 0, - 0, - 0, - 0, - 0, - 24665, - 0, - 0, - 0, - 0, - 24667, - 0, - 0, - 0, - 0, - 0, - 0, - 24668, - 24669, - 0, - 24670, - 24674, - 0, - 0, - 0, - 24675, - 0, - 24678, - 0, - 0, - 24679, - 0, - 0, - 0, - 24681, - 0, - 24683, - 0, - 0, - 0, - 0, - 24684, - 0, - 24685, - 0, - 0, - 24686, - 0, - 0, - 24688, - 24689, - 0, - 0, - 0, - 0, - 24690, - 24691, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24697, - 0, - 24698, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24709, - 0, - 0, - 0, - 0, - 0, - 24710, - 0, - 24712, - 0, - 0, - 0, - 0, - 0, - 0, - 24713, - 24714, - 0, - 24715, - 0, - 24716, - 24718, - 0, - 24719, - 0, - 0, - 0, - 0, - 24720, - 0, - 0, - 24725, - 0, - 0, - 24738, - 0, - 24749, - 24750, - 0, - 0, - 0, - 24752, - 0, - 0, - 0, - 24753, - 0, - 0, - 0, - 24758, - 0, - 0, - 0, - 0, - 0, - 24762, - 0, - 24763, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24764, - 0, - 0, - 0, - 0, - 0, - 24765, - 24767, - 24768, - 0, - 24772, - 0, - 0, - 0, - 0, - 24773, - 0, - 0, - 0, - 0, - 24777, - 0, - 0, - 0, - 0, - 0, - 24785, - 0, - 24786, - 24788, - 0, - 0, - 0, - 24789, - 0, - 0, - 0, - 0, - 24794, - 24798, - 0, - 24799, - 24800, - 0, - 0, - 0, - 24803, - 0, - 24804, - 24806, - 0, - 24807, - 0, - 0, - 0, - 24810, - 0, - 0, - 0, - 0, - 0, - 0, - 24827, - 24828, - 0, - 24835, - 0, - 0, - 0, - 0, - 0, - 0, - 24836, - 0, - 0, - 0, - 0, - 0, - 24839, - 0, - 24843, - 24844, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24847, - 0, - 0, - 24848, - 0, - 0, - 0, - 0, - 0, - 0, - 24849, - 0, - 24850, - 24851, - 0, - 0, - 0, - 24852, - 0, - 24853, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24854, - 0, - 24855, - 0, - 0, - 24868, - 0, - 0, - 0, - 24883, - 0, - 0, - 0, - 24884, - 0, - 24895, - 24897, - 0, - 0, - 0, - 0, - 0, - 24899, - 0, - 0, - 0, - 0, - 0, - 24900, - 0, - 24913, - 0, - 0, - 0, - 0, - 0, - 0, - 24914, - 0, - 0, - 24917, - 24930, - 24931, - 0, - 0, - 0, - 24932, - 0, - 0, - 24939, - 0, - 0, - 24942, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 24945, - 24950, - 0, - 24951, - 0, - 0, - 24953, - 0, - 0, - 0, - 24954, - 0, - 24959, - 0, - 0, - 0, - 24961, - 0, - 0, - 24962, - 0, - 24964, - 24968, - 24970, - 24972, - 0, - 0, - 0, - 0, - 0, - 24976, - 0, - 0, - 0, - 24977, - 0, - 24982, - 0, - 0, - 24983, - 0, - 0, - 24984, - 0, - 0, - 0, - 24993, - 0, - 0, - 0, - 24994, - 0, - 0, - 25001, - 0, - 0, - 0, - 25003, - 0, - 0, - 25018, - 0, - 0, - 25023, - 0, - 0, - 0, - 25034, - 0, - 0, - 25035, - 25036, - 0, - 25037, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25039, - 0, - 0, - 0, - 0, - 0, - 25040, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25042, - 0, - 0, - 25043, - 25045, - 0, - 0, - 0, - 0, - 0, - 0, - 25049, - 0, - 0, - 25051, - 0, - 25052, - 25053, - 0, - 0, - 25054, - 0, - 0, - 0, - 25055, - 0, - 0, - 0, - 0, - 25057, - 25059, - 0, - 0, - 25060, - 25064, - 0, - 25065, - 25069, - 25070, - 0, - 0, - 0, - 0, - 25072, - 0, - 25073, - 0, - 25090, - 0, - 0, - 25092, - 25093, - 25101, - 0, - 0, - 0, - 0, - 0, - 0, - 25105, - 25108, - 0, - 0, - 25113, - 0, - 0, - 25115, - 25116, - 0, - 0, - 0, - 0, - 0, - 0, - 25117, - 0, - 0, - 0, - 25120, - 25121, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25125, - 0, - 0, - 0, - 25126, - 0, - 25130, - 25134, - 0, - 25139, - 0, - 25143, - 0, - 0, - 0, - 25151, - 0, - 25161, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25163, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25174, - 0, - 25175, - 0, - 25207, - 0, - 0, - 0, - 25209, - 0, - 0, - 0, - 0, - 25213, - 0, - 25219, - 0, - 25223, - 0, - 25225, - 0, - 0, - 0, - 25227, - 0, - 0, - 0, - 25228, - 0, - 0, - 0, - 25229, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25231, - 25233, - 0, - 0, - 0, - 0, - 25237, - 25239, - 0, - 0, - 0, - 25243, - 0, - 0, - 0, - 25252, - 0, - 25257, - 25258, - 0, - 0, - 0, - 0, - 25260, - 25265, - 0, - 25268, - 0, - 0, - 25273, - 25324, - 0, - 25325, - 0, - 25326, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25327, - 0, - 0, - 0, - 0, - 0, - 25328, - 0, - 0, - 0, - 0, - 0, - 0, - 25332, - 0, - 0, - 0, - 25333, - 0, - 0, - 0, - 25336, - 25337, - 25338, - 0, - 0, - 25343, - 0, - 25350, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25352, - 0, - 25354, - 0, - 25375, - 0, - 25379, - 0, - 0, - 0, - 0, - 25384, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25386, - 0, - 25388, - 0, - 25390, - 0, - 0, - 25399, - 0, - 0, - 25401, - 0, - 0, - 0, - 25402, - 0, - 0, - 0, - 25407, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25413, - 25415, - 0, - 0, - 25417, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25419, - 0, - 0, - 0, - 25421, - 0, - 0, - 0, - 25424, - 0, - 0, - 0, - 0, - 25433, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25435, - 0, - 0, - 0, - 0, - 0, - 0, - 25436, - 0, - 0, - 0, - 25437, - 0, - 0, - 25440, - 0, - 0, - 0, - 0, - 0, - 0, - 25442, - 0, - 0, - 25443, - 0, - 25446, - 0, - 0, - 25449, - 0, - 0, - 0, - 25450, - 0, - 0, - 0, - 0, - 25452, - 0, - 25453, - 25454, - 25455, - 0, - 0, - 0, - 25456, - 0, - 25457, - 0, - 0, - 0, - 25459, - 0, - 25461, - 0, - 25468, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25469, - 0, - 0, - 0, - 0, - 0, - 25471, - 0, - 0, - 0, - 0, - 0, - 25474, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25475, - 0, - 0, - 0, - 0, - 25477, - 0, - 0, - 0, - 0, - 25483, - 0, - 0, - 0, - 0, - 0, - 25484, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25485, - 0, - 25497, - 0, - 0, - 25498, - 0, - 25504, - 0, - 25510, - 0, - 25512, - 0, - 0, - 25513, - 25514, - 0, - 0, - 0, - 0, - 0, - 0, - 25517, - 25518, - 25519, - 0, - 25520, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25521, - 0, - 25522, - 25527, - 25534, - 0, - 25536, - 0, - 25537, - 0, - 0, - 25548, - 25550, - 0, - 0, - 25551, - 0, - 25552, - 0, - 0, - 0, - 0, - 0, - 25554, - 0, - 25555, - 0, - 25556, - 25557, - 25568, - 0, - 0, - 0, - 25570, - 25571, - 0, - 0, - 0, - 0, - 0, - 0, - 25574, - 0, - 0, - 0, - 0, - 25579, - 0, - 0, - 0, - 25581, - 0, - 0, - 0, - 25582, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25588, - 0, - 0, - 0, - 0, - 25589, - 0, - 0, - 0, - 0, - 25590, - 0, - 25591, - 25592, - 25593, - 0, - 25594, - 0, - 0, - 0, - 25596, - 0, - 25597, - 25615, - 0, - 0, - 0, - 0, - 0, - 25618, - 0, - 0, - 0, - 0, - 25619, - 25623, - 0, - 0, - 25629, - 0, - 0, - 25631, - 0, - 0, - 0, - 25635, - 25636, - 0, - 0, - 25649, - 0, - 0, - 0, - 0, - 25654, - 0, - 0, - 0, - 25661, - 25663, - 0, - 0, - 25671, - 0, - 0, - 25678, - 25698, - 0, - 25699, - 25702, - 25703, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25704, - 0, - 0, - 0, - 0, - 0, - 25706, - 0, - 0, - 25710, - 0, - 25711, - 0, - 25712, - 0, - 25715, - 25716, - 25717, - 0, - 0, - 25718, - 25728, - 25732, - 0, - 0, - 0, - 25734, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25737, - 0, - 0, - 25739, - 0, - 0, - 0, - 25740, - 0, - 25741, - 25745, - 0, - 25746, - 0, - 25748, - 25772, - 25778, - 0, - 0, - 0, - 0, - 0, - 25780, - 0, - 0, - 0, - 0, - 25781, - 0, - 25782, - 25784, - 25785, - 0, - 0, - 0, - 25789, - 0, - 0, - 0, - 0, - 0, - 0, - 25797, - 25801, - 0, - 0, - 0, - 25808, - 25809, - 0, - 0, - 25811, - 25814, - 25815, - 0, - 0, - 25817, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25820, - 0, - 0, - 0, - 0, - 25832, - 25833, - 0, - 0, - 0, - 25846, - 0, - 0, - 0, - 25847, - 25848, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25849, - 25850, - 0, - 0, - 25851, - 0, - 0, - 25852, - 0, - 25862, - 0, - 0, - 0, - 25863, - 25865, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25867, - 25868, - 0, - 25869, - 25874, - 0, - 25875, - 0, - 25876, - 25877, - 0, - 0, - 0, - 0, - 25878, - 25902, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25903, - 25904, - 25905, - 0, - 0, - 0, - 25908, - 25909, - 0, - 0, - 0, - 0, - 25910, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25912, - 0, - 25913, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25914, - 0, - 0, - 25916, - 0, - 0, - 0, - 0, - 0, - 25917, - 25927, - 0, - 0, - 0, - 0, - 25928, - 0, - 0, - 25930, - 0, - 0, - 0, - 25933, - 0, - 0, - 25938, - 25942, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25945, - 0, - 25950, - 0, - 25956, - 0, - 0, - 25961, - 25962, - 0, - 0, - 25963, - 0, - 25964, - 25965, - 25966, - 0, - 0, - 0, - 0, - 0, - 25967, - 0, - 0, - 0, - 0, - 25968, - 0, - 0, - 0, - 25969, - 25971, - 0, - 0, - 0, - 0, - 0, - 25973, - 25975, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25978, - 0, - 25981, - 0, - 0, - 0, - 25982, - 0, - 0, - 0, - 25984, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 25993, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26002, - 0, - 0, - 0, - 26005, - 0, - 0, - 0, - 26006, - 26007, - 0, - 0, - 26014, - 26015, - 26016, - 0, - 0, - 0, - 0, - 0, - 0, - 26017, - 26018, - 26020, - 0, - 26022, - 26023, - 0, - 0, - 0, - 26024, - 26028, - 0, - 26029, - 26033, - 26034, - 26044, - 0, - 0, - 0, - 0, - 0, - 26046, - 0, - 0, - 26047, - 0, - 0, - 26049, - 0, - 26050, - 0, - 26051, - 0, - 0, - 0, - 0, - 0, - 26053, - 0, - 0, - 0, - 0, - 26054, - 26059, - 0, - 0, - 0, - 0, - 0, - 0, - 26060, - 0, - 26066, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26067, - 0, - 26069, - 0, - 0, - 26071, - 0, - 0, - 0, - 26073, - 0, - 26074, - 26077, - 0, - 0, - 0, - 0, - 26078, - 0, - 0, - 0, - 26079, - 0, - 26090, - 0, - 0, - 26094, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26095, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26096, - 26101, - 0, - 26107, - 26122, - 0, - 26124, - 0, - 0, - 26125, - 0, - 0, - 0, - 0, - 0, - 0, - 26136, - 26141, - 26155, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26164, - 26166, - 0, - 0, - 0, - 26167, - 0, - 26170, - 26171, - 0, - 0, - 26172, - 0, - 0, - 26174, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26175, - 0, - 0, - 0, - 26176, - 26177, - 0, - 26321, - 26322, - 0, - 26323, - 0, - 0, - 26324, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26325, - 0, - 26331, - 0, - 0, - 0, - 0, - 0, - 0, - 26335, - 0, - 0, - 0, - 26350, - 0, - 0, - 0, - 26379, - 0, - 0, - 26382, - 26383, - 26385, - 0, - 0, - 26392, - 26406, - 0, - 0, - 0, - 0, - 26411, - 0, - 0, - 0, - 0, - 0, - 26412, - 0, - 0, - 26420, - 0, - 0, - 26423, - 0, - 26424, - 26426, - 26432, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26435, - 0, - 26436, - 0, - 0, - 0, - 0, - 0, - 26441, - 0, - 26444, - 0, - 0, - 0, - 26446, - 0, - 0, - 0, - 0, - 26447, - 0, - 0, - 0, - 0, - 26449, - 0, - 26450, - 26452, - 0, - 26453, - 26454, - 0, - 0, - 0, - 26455, - 0, - 0, - 0, - 26456, - 0, - 0, - 26458, - 0, - 0, - 26460, - 0, - 26463, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26464, - 26470, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26473, - 0, - 0, - 26474, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26475, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26477, - 0, - 26485, - 0, - 0, - 26486, - 0, - 26487, - 0, - 0, - 26488, - 26493, - 26494, - 0, - 0, - 26495, - 0, - 26497, - 26504, - 26506, - 0, - 0, - 0, - 0, - 0, - 26507, - 0, - 0, - 0, - 0, - 0, - 26509, - 0, - 0, - 26510, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26512, - 0, - 26513, - 26515, - 0, - 0, - 0, - 26518, - 0, - 0, - 0, - 26519, - 0, - 26524, - 26526, - 0, - 0, - 0, - 26527, - 0, - 26532, - 0, - 26533, - 26537, - 26558, - 0, - 0, - 0, - 26559, - 0, - 0, - 0, - 26571, - 0, - 0, - 26573, - 0, - 26588, - 0, - 26593, - 0, - 0, - 0, - 0, - 0, - 0, - 26603, - 0, - 26604, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26606, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26607, - 26609, - 26611, - 26614, - 0, - 0, - 0, - 26616, - 26620, - 0, - 26621, - 0, - 0, - 0, - 0, - 0, - 26627, - 0, - 26629, - 0, - 0, - 26630, - 0, - 0, - 26632, - 26643, - 0, - 0, - 0, - 26644, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26646, - 26647, - 0, - 0, - 0, - 26650, - 0, - 0, - 26656, - 0, - 0, - 0, - 0, - 26663, - 26670, - 26671, - 0, - 0, - 0, - 26685, - 26686, - 26687, - 0, - 26689, - 0, - 0, - 0, - 0, - 26744, - 0, - 26745, - 0, - 26747, - 26748, - 0, - 26749, - 26750, - 26751, - 0, - 0, - 0, - 0, - 26752, - 26755, - 0, - 0, - 0, - 26756, - 26769, - 0, - 0, - 0, - 26774, - 0, - 0, - 0, - 0, - 0, - 26775, - 0, - 26777, - 26778, - 0, - 26786, - 0, - 0, - 0, - 26787, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26788, - 0, - 0, - 26789, - 0, - 0, - 0, - 0, - 0, - 26791, - 0, - 26792, - 26793, - 0, - 0, - 0, - 26794, - 0, - 26797, - 26798, - 0, - 0, - 0, - 26800, - 0, - 0, - 26803, - 0, - 26804, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26805, - 0, - 0, - 26808, - 0, - 0, - 26809, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26812, - 0, - 26825, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26826, - 0, - 0, - 26827, - 26829, - 26834, - 0, - 0, - 0, - 0, - 26835, - 0, - 0, - 26849, - 0, - 26851, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26852, - 0, - 26853, - 26857, - 0, - 26858, - 0, - 26859, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26876, - 0, - 26878, - 26882, - 26883, - 0, - 0, - 0, - 0, - 26890, - 26894, - 0, - 0, - 0, - 0, - 26895, - 26896, - 0, - 0, - 0, - 0, - 0, - 26900, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26911, - 26913, - 26914, - 26915, - 26916, - 26919, - 0, - 0, - 0, - 26921, - 26922, - 0, - 0, - 26925, - 0, - 0, - 0, - 26928, - 0, - 0, - 26929, - 26930, - 0, - 0, - 0, - 26931, - 0, - 26932, - 0, - 0, - 0, - 0, - 0, - 26933, - 0, - 0, - 0, - 0, - 0, - 0, - 26937, - 0, - 0, - 26943, - 0, - 0, - 26944, - 0, - 0, - 0, - 26946, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26956, - 0, - 26958, - 0, - 0, - 26963, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 26965, - 0, - 26969, - 26970, - 26972, - 0, - 0, - 0, - 0, - 0, - 26973, - 0, - 26974, - 0, - 26978, - 0, - 26980, - 0, - 0, - 0, - 0, - 0, - 0, - 26982, - 0, - 26986, - 26987, - 0, - 26990, - 0, - 0, - 0, - 0, - 27003, - 27006, - 0, - 0, - 27007, - 27010, - 27012, - 27013, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27014, - 27015, - 27018, - 0, - 27019, - 0, - 0, - 0, - 0, - 0, - 27025, - 0, - 0, - 0, - 27026, - 0, - 0, - 0, - 0, - 27029, - 27030, - 27031, - 27034, - 0, - 0, - 27036, - 27037, - 0, - 0, - 0, - 27038, - 27042, - 0, - 0, - 0, - 27044, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27045, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27046, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27047, - 27049, - 0, - 27050, - 0, - 0, - 0, - 27051, - 27052, - 0, - 27055, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27056, - 27058, - 27059, - 0, - 27061, - 0, - 27064, - 0, - 0, - 0, - 0, - 0, - 27069, - 0, - 0, - 27070, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27072, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27076, - 0, - 0, - 0, - 0, - 0, - 27078, - 0, - 27079, - 0, - 0, - 0, - 27081, - 0, - 0, - 0, - 0, - 0, - 0, - 27082, - 0, - 27083, - 27086, - 0, - 0, - 0, - 0, - 27087, - 0, - 0, - 0, - 0, - 0, - 27088, - 27090, - 0, - 27094, - 0, - 0, - 27095, - 0, - 27099, - 27102, - 0, - 0, - 0, - 27103, - 0, - 0, - 0, - 0, - 27105, - 0, - 0, - 0, - 27106, - 0, - 0, - 0, - 0, - 0, - 0, - 27107, - 0, - 0, - 0, - 0, - 27108, - 27117, - 0, - 0, - 0, - 0, - 27118, - 0, - 0, - 27124, - 0, - 27126, - 0, - 0, - 27130, - 27131, - 0, - 0, - 0, - 0, - 0, - 0, - 27147, - 0, - 0, - 0, - 0, - 27148, - 27149, - 0, - 0, - 0, - 0, - 27150, - 27151, - 0, - 27152, - 0, - 27159, - 0, - 0, - 0, - 27164, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27175, - 0, - 27189, - 0, - 0, - 27191, - 0, - 27193, - 0, - 27195, - 0, - 27198, - 0, - 0, - 0, - 0, - 0, - 27200, - 0, - 0, - 0, - 0, - 27202, - 0, - 0, - 0, - 0, - 27203, - 0, - 0, - 27204, - 0, - 0, - 27206, - 0, - 27207, - 0, - 0, - 0, - 0, - 27209, - 0, - 0, - 0, - 27213, - 0, - 0, - 27216, - 27219, - 27220, - 27222, - 27223, - 0, - 27224, - 0, - 27225, - 27226, - 0, - 0, - 27233, - 0, - 0, - 0, - 0, - 27235, - 0, - 27237, - 0, - 27238, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27239, - 0, - 27242, - 27243, - 0, - 27250, - 0, - 0, - 0, - 27251, - 0, - 27253, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27254, - 27255, - 27258, - 0, - 0, - 0, - 27259, - 0, - 0, - 0, - 0, - 0, - 0, - 27267, - 0, - 27276, - 27278, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27296, - 27297, - 27301, - 0, - 0, - 0, - 0, - 0, - 0, - 27302, - 0, - 0, - 0, - 0, - 0, - 0, - 27312, - 27313, - 0, - 0, - 0, - 0, - 0, - 27318, - 0, - 27320, - 0, - 27329, - 0, - 27330, - 27331, - 0, - 27332, - 0, - 0, - 0, - 0, - 27340, - 0, - 0, - 0, - 27348, - 0, - 0, - 0, - 0, - 0, - 0, - 27350, - 0, - 27351, - 0, - 0, - 0, - 0, - 27355, - 0, - 0, - 27358, - 27359, - 27361, - 0, - 0, - 0, - 27365, - 0, - 27367, - 0, - 27376, - 27378, - 0, - 0, - 27379, - 0, - 0, - 0, - 0, - 0, - 0, - 27396, - 0, - 27397, - 27404, - 0, - 0, - 0, - 0, - 0, - 27408, - 0, - 0, - 0, - 0, - 27453, - 0, - 0, - 0, - 27456, - 0, - 0, - 0, - 27458, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27459, - 0, - 0, - 0, - 27460, - 0, - 0, - 27461, - 0, - 27465, - 27467, - 0, - 0, - 27469, - 0, - 27470, - 0, - 27471, - 0, - 27477, - 27482, - 0, - 0, - 0, - 0, - 0, - 0, - 27484, - 0, - 0, - 0, - 0, - 0, - 0, - 27485, - 0, - 0, - 0, - 0, - 0, - 27493, - 0, - 27494, - 27502, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27511, - 27532, - 0, - 0, - 0, - 27533, - 27545, - 0, - 0, - 0, - 27546, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27547, - 0, - 0, - 27549, - 27550, - 0, - 27551, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27555, - 0, - 0, - 27571, - 0, - 27573, - 27574, - 27575, - 27577, - 0, - 27578, - 0, - 0, - 27579, - 27585, - 0, - 0, - 0, - 0, - 0, - 27586, - 0, - 0, - 27588, - 27589, - 0, - 0, - 0, - 0, - 27596, - 0, - 0, - 27600, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27608, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27610, - 0, - 0, - 0, - 27618, - 0, - 0, - 27620, - 0, - 0, - 0, - 27631, - 0, - 0, - 27632, - 27634, - 0, - 27636, - 27638, - 0, - 0, - 0, - 27643, - 0, - 27644, - 27649, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27651, - 27660, - 0, - 27661, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27662, - 0, - 0, - 27664, - 0, - 27665, - 0, - 0, - 0, - 27669, - 0, - 27671, - 0, - 0, - 0, - 27673, - 27674, - 0, - 0, - 0, - 27682, - 0, - 0, - 0, - 27711, - 0, - 27712, - 27713, - 27719, - 27720, - 0, - 0, - 27728, - 0, - 27729, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27731, - 0, - 0, - 27732, - 0, - 27733, - 0, - 27738, - 0, - 0, - 0, - 27742, - 0, - 0, - 0, - 27743, - 27744, - 0, - 0, - 0, - 0, - 0, - 0, - 27745, - 27746, - 0, - 0, - 0, - 27747, - 27748, - 27751, - 27752, - 0, - 0, - 0, - 27768, - 27770, - 0, - 0, - 0, - 27774, - 27775, - 0, - 27776, - 27777, - 0, - 0, - 27781, - 0, - 27784, - 0, - 27786, - 0, - 0, - 27791, - 0, - 27792, - 27793, - 27804, - 0, - 27812, - 27813, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27814, - 0, - 27825, - 0, - 27827, - 0, - 0, - 0, - 0, - 27828, - 27861, - 27862, - 0, - 0, - 0, - 27864, - 0, - 0, - 0, - 27865, - 27884, - 0, - 27889, - 0, - 0, - 0, - 0, - 0, - 27890, - 0, - 27891, - 0, - 0, - 0, - 27892, - 0, - 0, - 0, - 0, - 0, - 27897, - 27898, - 0, - 0, - 27899, - 0, - 0, - 0, - 27901, - 27905, - 0, - 0, - 27920, - 0, - 0, - 27921, - 0, - 27922, - 0, - 0, - 0, - 27931, - 27934, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27941, - 0, - 27942, - 0, - 27945, - 0, - 27947, - 27954, - 0, - 0, - 0, - 0, - 27960, - 27963, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 27964, - 27965, - 0, - 0, - 0, - 27967, - 0, - 27969, - 27975, - 0, - 27976, - 27977, - 0, - 27981, - 0, - 27983, - 28051, - 28052, - 0, - 0, - 0, - 0, - 0, - 28056, - 0, - 0, - 0, - 0, - 0, - 0, - 28058, - 28059, - 0, - 0, - 28061, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28063, - 0, - 0, - 0, - 0, - 0, - 0, - 28066, - 0, - 0, - 0, - 0, - 0, - 0, - 28069, - 28070, - 28072, - 0, - 28073, - 0, - 0, - 28074, - 0, - 0, - 0, - 0, - 28075, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28078, - 0, - 0, - 0, - 0, - 28085, - 0, - 0, - 0, - 0, - 28086, - 0, - 0, - 0, - 0, - 0, - 0, - 28088, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28090, - 0, - 28097, - 28114, - 28115, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28116, - 0, - 0, - 0, - 0, - 0, - 28118, - 0, - 28129, - 0, - 28131, - 0, - 0, - 28135, - 0, - 0, - 0, - 28140, - 28141, - 0, - 0, - 0, - 28146, - 0, - 0, - 0, - 0, - 28152, - 0, - 0, - 0, - 0, - 28155, - 28157, - 28161, - 0, - 0, - 0, - 0, - 28166, - 0, - 28167, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28172, - 0, - 0, - 0, - 0, - 0, - 0, - 28173, - 0, - 0, - 28175, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28178, - 28188, - 0, - 28190, - 0, - 0, - 0, - 0, - 0, - 28191, - 0, - 28193, - 28206, - 0, - 0, - 28207, - 28209, - 0, - 28211, - 0, - 28213, - 0, - 0, - 0, - 28215, - 28216, - 28217, - 0, - 28222, - 0, - 28223, - 28225, - 0, - 0, - 0, - 28226, - 0, - 28227, - 28229, - 28232, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28235, - 0, - 28241, - 0, - 0, - 28242, - 0, - 0, - 0, - 0, - 28243, - 0, - 0, - 0, - 28245, - 0, - 0, - 0, - 28248, - 28250, - 0, - 28251, - 28252, - 0, - 0, - 0, - 0, - 0, - 0, - 28253, - 0, - 0, - 28254, - 28255, - 0, - 0, - 28256, - 0, - 0, - 28258, - 0, - 0, - 0, - 0, - 0, - 28259, - 0, - 0, - 28260, - 0, - 0, - 28261, - 0, - 0, - 0, - 0, - 28262, - 28263, - 0, - 0, - 28264, - 0, - 0, - 0, - 28266, - 0, - 28268, - 28269, - 0, - 28270, - 28272, - 28274, - 0, - 28277, - 28278, - 0, - 0, - 0, - 28279, - 0, - 28280, - 28281, - 28283, - 0, - 28292, - 0, - 28294, - 0, - 28297, - 0, - 0, - 0, - 0, - 28299, - 0, - 0, - 0, - 0, - 0, - 28300, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28301, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28302, - 28303, - 0, - 0, - 0, - 0, - 28304, - 0, - 0, - 28305, - 0, - 28312, - 0, - 28313, - 28314, - 0, - 0, - 0, - 0, - 0, - 0, - 28315, - 0, - 0, - 0, - 28320, - 28321, - 0, - 0, - 28328, - 0, - 0, - 0, - 28329, - 28338, - 0, - 28339, - 0, - 0, - 28344, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28347, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28348, - 0, - 0, - 0, - 0, - 0, - 28411, - 0, - 28412, - 28413, - 0, - 28416, - 0, - 0, - 0, - 28420, - 0, - 0, - 0, - 0, - 0, - 28421, - 0, - 0, - 0, - 0, - 28423, - 0, - 0, - 0, - 28424, - 0, - 0, - 28428, - 0, - 0, - 0, - 0, - 0, - 28429, - 0, - 0, - 0, - 28431, - 28434, - 0, - 28458, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28464, - 0, - 0, - 0, - 0, - 28465, - 0, - 28467, - 0, - 0, - 0, - 0, - 0, - 0, - 28471, - 0, - 0, - 0, - 0, - 28474, - 0, - 28480, - 0, - 28481, - 0, - 0, - 28485, - 0, - 0, - 0, - 0, - 28486, - 28488, - 0, - 0, - 28489, - 0, - 0, - 0, - 0, - 28492, - 0, - 0, - 0, - 28495, - 0, - 28497, - 0, - 28499, - 0, - 0, - 0, - 0, - 28500, - 0, - 0, - 28502, - 28503, - 0, - 0, - 0, - 28508, - 0, - 0, - 0, - 28510, - 0, - 0, - 28512, - 28513, - 28514, - 28521, - 0, - 28526, - 0, - 28527, - 28528, - 0, - 0, - 0, - 0, - 28529, - 0, - 0, - 28532, - 0, - 0, - 28537, - 28538, - 0, - 0, - 0, - 28539, - 0, - 28548, - 0, - 28553, - 28554, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28560, - 28563, - 0, - 0, - 28564, - 0, - 0, - 0, - 0, - 28565, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28566, - 28568, - 0, - 0, - 0, - 0, - 0, - 0, - 28569, - 0, - 0, - 0, - 28570, - 0, - 28572, - 28573, - 0, - 0, - 0, - 0, - 28575, - 0, - 0, - 0, - 0, - 28576, - 28581, - 28588, - 0, - 0, - 28589, - 0, - 0, - 0, - 28590, - 28595, - 0, - 28598, - 0, - 0, - 28601, - 0, - 0, - 28605, - 0, - 0, - 0, - 0, - 28614, - 28615, - 28619, - 0, - 0, - 0, - 0, - 0, - 0, - 28620, - 0, - 28626, - 0, - 0, - 28628, - 0, - 28631, - 0, - 28632, - 0, - 0, - 0, - 0, - 0, - 0, - 28635, - 0, - 0, - 0, - 28637, - 28638, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28639, - 0, - 28643, - 0, - 0, - 28652, - 0, - 0, - 0, - 28662, - 0, - 28670, - 28671, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28672, - 28673, - 28675, - 28676, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28691, - 0, - 0, - 0, - 28695, - 0, - 0, - 0, - 28696, - 0, - 28697, - 28698, - 0, - 28705, - 0, - 28707, - 28708, - 28710, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28711, - 28728, - 0, - 0, - 0, - 28736, - 0, - 0, - 0, - 28737, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28738, - 0, - 28739, - 0, - 28741, - 0, - 0, - 28742, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28745, - 0, - 0, - 0, - 0, - 0, - 0, - 28749, - 28750, - 28752, - 28754, - 28756, - 0, - 28757, - 0, - 0, - 0, - 0, - 28759, - 28760, - 0, - 0, - 0, - 0, - 0, - 0, - 28762, - 0, - 0, - 0, - 28764, - 0, - 0, - 0, - 0, - 0, - 0, - 28766, - 0, - 28767, - 28768, - 0, - 0, - 0, - 0, - 28769, - 28770, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28771, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28772, - 0, - 28773, - 0, - 28782, - 0, - 0, - 0, - 0, - 0, - 0, - 28784, - 0, - 28785, - 0, - 28786, - 0, - 0, - 0, - 28787, - 0, - 0, - 0, - 28797, - 0, - 0, - 0, - 0, - 0, - 0, - 28799, - 0, - 0, - 28801, - 0, - 0, - 0, - 0, - 28802, - 0, - 28805, - 0, - 0, - 28806, - 0, - 0, - 28807, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28808, - 0, - 0, - 0, - 0, - 0, - 28810, - 28812, - 0, - 0, - 28816, - 28819, - 0, - 0, - 28821, - 0, - 28826, - 0, - 0, - 0, - 28842, - 28852, - 0, - 0, - 28853, - 0, - 28854, - 28855, - 0, - 0, - 0, - 28857, - 0, - 0, - 0, - 28858, - 0, - 28867, - 28868, - 28869, - 0, - 0, - 0, - 28874, - 28880, - 28882, - 28890, - 28892, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28895, - 0, - 0, - 0, - 28898, - 28899, - 0, - 0, - 0, - 28900, - 0, - 0, - 28904, - 0, - 28906, - 0, - 0, - 0, - 0, - 28907, - 0, - 0, - 0, - 0, - 0, - 0, - 28908, - 0, - 0, - 0, - 28910, - 0, - 28914, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28915, - 28916, - 28919, - 0, - 0, - 28920, - 0, - 28921, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28924, - 0, - 0, - 0, - 0, - 28926, - 28929, - 0, - 0, - 0, - 28930, - 0, - 28936, - 0, - 28939, - 0, - 0, - 0, - 0, - 28942, - 0, - 0, - 0, - 0, - 0, - 0, - 28956, - 0, - 0, - 0, - 28966, - 0, - 0, - 0, - 0, - 28967, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 28968, - 0, - 28971, - 0, - 28975, - 28976, - 0, - 28982, - 28983, - 0, - 0, - 28984, - 28989, - 28996, - 28997, - 28998, - 0, - 0, - 0, - 0, - 0, - 0, - 28999, - 0, - 0, - 0, - 0, - 0, - 29000, - 0, - 29001, - 0, - 0, - 0, - 29009, - 0, - 0, - 29011, - 0, - 0, - 29021, - 0, - 0, - 0, - 0, - 29024, - 0, - 29025, - 0, - 0, - 0, - 0, - 0, - 29026, - 0, - 0, - 0, - 29036, - 0, - 0, - 0, - 29037, - 0, - 0, - 0, - 0, - 29038, - 0, - 29045, - 0, - 29047, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29051, - 0, - 0, - 0, - 29054, - 29056, - 29062, - 0, - 29070, - 29082, - 0, - 0, - 0, - 29083, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29084, - 0, - 0, - 0, - 0, - 29085, - 29088, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29090, - 29097, - 0, - 0, - 0, - 29103, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29105, - 0, - 0, - 0, - 0, - 0, - 29107, - 0, - 29109, - 0, - 0, - 0, - 29115, - 0, - 0, - 29120, - 0, - 0, - 29138, - 29140, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29152, - 0, - 29160, - 29174, - 0, - 29176, - 0, - 0, - 29180, - 0, - 29181, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29228, - 0, - 0, - 29229, - 0, - 0, - 29230, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29234, - 0, - 0, - 0, - 29241, - 0, - 29245, - 0, - 29248, - 0, - 29250, - 29256, - 29280, - 0, - 29282, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29285, - 0, - 0, - 29286, - 29291, - 29292, - 0, - 0, - 0, - 0, - 29294, - 0, - 29295, - 0, - 0, - 0, - 0, - 0, - 29296, - 29297, - 29298, - 29300, - 0, - 29302, - 0, - 0, - 29304, - 29307, - 0, - 29312, - 0, - 0, - 0, - 29322, - 0, - 0, - 29323, - 0, - 0, - 29324, - 29326, - 29328, - 0, - 29335, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29338, - 29339, - 0, - 0, - 0, - 0, - 0, - 29341, - 29343, - 0, - 0, - 0, - 0, - 29344, - 0, - 0, - 0, - 0, - 0, - 29345, - 0, - 0, - 0, - 0, - 29346, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29347, - 29348, - 29349, - 0, - 0, - 29354, - 0, - 0, - 29355, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29357, - 0, - 0, - 0, - 0, - 29364, - 0, - 29365, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29366, - 0, - 0, - 29368, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29378, - 0, - 29381, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29386, - 0, - 0, - 0, - 0, - 0, - 0, - 29389, - 0, - 0, - 0, - 29390, - 0, - 0, - 29391, - 29397, - 0, - 29398, - 29412, - 29414, - 29418, - 29419, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29420, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29423, - 0, - 0, - 0, - 29435, - 0, - 0, - 0, - 29437, - 0, - 0, - 29439, - 0, - 29441, - 0, - 0, - 0, - 0, - 29443, - 0, - 29446, - 29450, - 29452, - 0, - 0, - 0, - 0, - 0, - 29456, - 0, - 0, - 0, - 0, - 0, - 29461, - 0, - 0, - 0, - 29464, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29468, - 0, - 29473, - 0, - 0, - 0, - 29486, - 0, - 0, - 0, - 29490, - 0, - 0, - 0, - 29491, - 29492, - 0, - 0, - 29497, - 0, - 0, - 0, - 29498, - 0, - 29499, - 0, - 29502, - 29505, - 0, - 29509, - 0, - 0, - 0, - 29510, - 0, - 0, - 0, - 29512, - 0, - 0, - 0, - 29516, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29518, - 0, - 29519, - 0, - 0, - 0, - 0, - 0, - 29520, - 29521, - 29529, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29530, - 0, - 0, - 29531, - 29538, - 0, - 29540, - 0, - 0, - 0, - 29542, - 0, - 29543, - 29544, - 29547, - 0, - 0, - 29548, - 0, - 0, - 0, - 29549, - 0, - 0, - 0, - 29550, - 0, - 0, - 29552, - 0, - 0, - 0, - 0, - 29558, - 29561, - 0, - 29562, - 29564, - 0, - 0, - 29565, - 0, - 0, - 29566, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29578, - 29584, - 29586, - 29591, - 0, - 0, - 0, - 0, - 29593, - 29594, - 0, - 0, - 29597, - 0, - 0, - 29613, - 0, - 29614, - 0, - 29615, - 0, - 0, - 0, - 0, - 29616, - 29617, - 0, - 0, - 29625, - 0, - 0, - 0, - 29632, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29633, - 0, - 0, - 0, - 0, - 0, - 29634, - 29635, - 29637, - 0, - 29638, - 0, - 29641, - 29643, - 0, - 0, - 0, - 0, - 0, - 0, - 29644, - 0, - 29645, - 0, - 29649, - 0, - 0, - 0, - 29650, - 0, - 29653, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29656, - 29659, - 0, - 0, - 29660, - 0, - 0, - 0, - 29661, - 0, - 0, - 0, - 0, - 0, - 29664, - 0, - 0, - 0, - 29671, - 29673, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29675, - 0, - 29677, - 29679, - 0, - 0, - 29684, - 0, - 0, - 0, - 0, - 0, - 29685, - 0, - 0, - 0, - 29687, - 0, - 0, - 0, - 29688, - 0, - 29689, - 29690, - 29700, - 0, - 29701, - 0, - 0, - 0, - 29702, - 0, - 29706, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29720, - 0, - 29721, - 0, - 29727, - 0, - 29733, - 29734, - 0, - 29750, - 29761, - 0, - 29763, - 0, - 0, - 0, - 0, - 0, - 29764, - 0, - 0, - 29765, - 0, - 0, - 0, - 29771, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29772, - 0, - 0, - 0, - 29773, - 29774, - 29775, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29822, - 0, - 0, - 0, - 29824, - 0, - 29825, - 0, - 0, - 0, - 0, - 0, - 29827, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29829, - 0, - 29832, - 29834, - 0, - 0, - 29835, - 0, - 0, - 29837, - 29838, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29843, - 0, - 0, - 0, - 0, - 29844, - 29845, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29849, - 0, - 0, - 29869, - 29872, - 29890, - 29905, - 0, - 0, - 0, - 0, - 0, - 29907, - 29921, - 0, - 29922, - 0, - 0, - 29923, - 29926, - 29944, - 29946, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 29947, - 29948, - 0, - 0, - 0, - 29951, - 0, - 0, - 0, - 0, - 0, - 29953, - 0, - 0, - 29956, - 0, - 29957, - 0, - 0, - 29962, - 0, - 0, - 0, - 0, - 29971, - 0, - 0, - 0, - 29972, - 0, - 0, - 0, - 0, - 0, - 29978, - 0, - 29979, - 29992, - 30007, - 30008, - 30010, - 0, - 0, - 0, - 30013, - 0, - 0, - 0, - 0, - 30014, - 30016, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30017, - 0, - 0, - 0, - 0, - 0, - 30023, - 30031, - 0, - 0, - 30033, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30034, - 0, - 30038, - 0, - 30039, - 0, - 30040, - 0, - 0, - 0, - 0, - 0, - 0, - 30067, - 30068, - 0, - 0, - 0, - 30069, - 0, - 30072, - 0, - 0, - 0, - 30073, - 0, - 0, - 0, - 0, - 30075, - 0, - 0, - 0, - 0, - 0, - 0, - 30079, - 0, - 0, - 30080, - 0, - 0, - 0, - 0, - 0, - 30082, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30084, - 30090, - 0, - 0, - 30091, - 0, - 0, - 0, - 0, - 30098, - 30118, - 0, - 30119, - 0, - 30121, - 30130, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30131, - 30132, - 30133, - 0, - 0, - 0, - 0, - 0, - 0, - 30135, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30136, - 0, - 0, - 30137, - 30138, - 0, - 0, - 0, - 30139, - 30146, - 0, - 0, - 0, - 0, - 0, - 30147, - 0, - 0, - 30148, - 30151, - 0, - 0, - 0, - 30168, - 0, - 30172, - 30173, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30180, - 30181, - 0, - 30192, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30194, - 30196, - 0, - 0, - 30199, - 0, - 0, - 30202, - 0, - 0, - 0, - 0, - 30203, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30213, - 0, - 0, - 0, - 30216, - 0, - 0, - 30217, - 0, - 0, - 0, - 30218, - 0, - 0, - 0, - 0, - 30219, - 0, - 30220, - 0, - 30222, - 30227, - 0, - 0, - 0, - 0, - 0, - 30231, - 0, - 0, - 30233, - 30235, - 0, - 0, - 0, - 0, - 30238, - 0, - 30240, - 30243, - 30245, - 0, - 30250, - 30252, - 0, - 0, - 0, - 30269, - 0, - 0, - 30271, - 30272, - 0, - 0, - 0, - 30278, - 30280, - 0, - 0, - 30282, - 0, - 30284, - 0, - 30294, - 0, - 0, - 0, - 0, - 30295, - 30296, - 0, - 0, - 0, - 0, - 0, - 30298, - 30299, - 30302, - 30304, - 30306, - 0, - 0, - 0, - 0, - 0, - 0, - 30316, - 30317, - 0, - 0, - 0, - 30318, - 0, - 0, - 0, - 30319, - 0, - 30320, - 30322, - 30326, - 0, - 0, - 0, - 0, - 0, - 30327, - 0, - 30332, - 30348, - 30349, - 0, - 0, - 30356, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30357, - 0, - 30358, - 0, - 30359, - 30360, - 0, - 0, - 30365, - 30366, - 30378, - 0, - 0, - 0, - 0, - 30379, - 0, - 0, - 30381, - 0, - 30385, - 0, - 30388, - 30397, - 0, - 0, - 0, - 30401, - 0, - 0, - 0, - 0, - 30403, - 0, - 0, - 0, - 0, - 0, - 30404, - 0, - 0, - 30405, - 0, - 30406, - 30408, - 0, - 30409, - 0, - 30410, - 0, - 0, - 0, - 30417, - 0, - 0, - 30418, - 30419, - 0, - 30420, - 0, - 30424, - 0, - 0, - 0, - 30427, - 30430, - 30432, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30433, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30436, - 0, - 30437, - 30438, - 0, - 30441, - 30442, - 0, - 0, - 0, - 30445, - 0, - 0, - 0, - 0, - 30452, - 30456, - 30457, - 0, - 0, - 0, - 30458, - 0, - 30464, - 0, - 0, - 0, - 0, - 0, - 0, - 30467, - 0, - 30469, - 0, - 0, - 0, - 0, - 0, - 30477, - 0, - 0, - 30484, - 0, - 0, - 0, - 0, - 0, - 30485, - 0, - 0, - 0, - 0, - 0, - 30486, - 30487, - 30497, - 30498, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30505, - 0, - 30508, - 0, - 0, - 0, - 30509, - 30510, - 0, - 30514, - 30516, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30523, - 0, - 30524, - 0, - 30525, - 0, - 0, - 0, - 0, - 30537, - 0, - 0, - 30538, - 0, - 0, - 0, - 0, - 0, - 30553, - 0, - 0, - 30555, - 30556, - 30558, - 30559, - 30560, - 0, - 0, - 30561, - 0, - 30562, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30563, - 30570, - 30571, - 0, - 30586, - 30587, - 0, - 0, - 30590, - 0, - 0, - 30594, - 0, - 0, - 0, - 0, - 30611, - 30612, - 30623, - 30634, - 0, - 0, - 30636, - 30640, - 30655, - 30656, - 0, - 30657, - 0, - 0, - 30658, - 30669, - 0, - 30670, - 0, - 30676, - 30678, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30679, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30695, - 0, - 0, - 30698, - 0, - 0, - 0, - 0, - 30700, - 0, - 0, - 0, - 0, - 30701, - 0, - 30702, - 30703, - 0, - 0, - 0, - 0, - 30707, - 0, - 0, - 0, - 30709, - 0, - 0, - 30710, - 30719, - 30729, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30731, - 0, - 0, - 30733, - 0, - 0, - 0, - 30734, - 0, - 0, - 0, - 0, - 0, - 30736, - 30737, - 0, - 0, - 0, - 30740, - 0, - 0, - 0, - 30743, - 0, - 30746, - 0, - 30747, - 30748, - 0, - 0, - 30751, - 30752, - 30753, - 0, - 0, - 0, - 30754, - 0, - 0, - 30760, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30763, - 0, - 30764, - 0, - 0, - 30766, - 0, - 30769, - 30770, - 30771, - 30774, - 30777, - 0, - 0, - 30779, - 30780, - 30781, - 0, - 0, - 0, - 0, - 30790, - 0, - 0, - 0, - 30792, - 0, - 0, - 0, - 0, - 30810, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30812, - 30819, - 0, - 0, - 30823, - 30824, - 0, - 30825, - 0, - 30827, - 0, - 0, - 0, - 0, - 0, - 0, - 30828, - 0, - 0, - 30830, - 0, - 0, - 0, - 30834, - 0, - 30835, - 0, - 30837, - 30838, - 0, - 30845, - 0, - 0, - 0, - 0, - 0, - 30846, - 30847, - 0, - 0, - 30849, - 0, - 30851, - 0, - 0, - 0, - 0, - 0, - 30852, - 30858, - 0, - 0, - 30859, - 0, - 30865, - 0, - 0, - 30866, - 0, - 0, - 30868, - 0, - 0, - 30869, - 0, - 0, - 0, - 30881, - 30883, - 0, - 0, - 0, - 0, - 0, - 30889, - 0, - 30891, - 0, - 0, - 0, - 0, - 30894, - 0, - 30895, - 0, - 30897, - 0, - 30898, - 0, - 0, - 0, - 30904, - 30906, - 0, - 30909, - 0, - 0, - 0, - 0, - 0, - 0, - 30910, - 0, - 0, - 0, - 30915, - 30933, - 30942, - 0, - 0, - 0, - 0, - 30943, - 0, - 0, - 30945, - 0, - 0, - 0, - 0, - 0, - 0, - 30946, - 0, - 0, - 30947, - 0, - 0, - 30955, - 30956, - 0, - 0, - 30960, - 0, - 0, - 30961, - 30962, - 30966, - 0, - 0, - 30969, - 30974, - 0, - 0, - 0, - 30976, - 0, - 0, - 30977, - 0, - 30978, - 30982, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 30994, - 30995, - 30998, - 0, - 31000, - 0, - 0, - 31001, - 0, - 0, - 31003, - 31005, - 0, - 0, - 31006, - 31011, - 0, - 0, - 31014, - 0, - 31016, - 0, - 0, - 0, - 0, - 31018, - 0, - 0, - 31020, - 31023, - 31024, - 31025, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31027, - 31028, - 31029, - 0, - 0, - 0, - 0, - 0, - 0, - 31032, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31036, - 31037, - 31038, - 0, - 0, - 0, - 31041, - 31043, - 31045, - 0, - 31047, - 0, - 0, - 0, - 31048, - 0, - 31049, - 0, - 0, - 0, - 31053, - 31054, - 31055, - 0, - 0, - 31063, - 0, - 0, - 0, - 0, - 0, - 31066, - 0, - 31068, - 31071, - 0, - 0, - 0, - 31072, - 31073, - 0, - 0, - 0, - 0, - 31075, - 0, - 0, - 31076, - 0, - 0, - 0, - 31077, - 31079, - 0, - 31080, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31087, - 0, - 31142, - 0, - 31144, - 0, - 0, - 31145, - 31146, - 31147, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31149, - 0, - 31151, - 31152, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31162, - 31171, - 31174, - 31175, - 0, - 0, - 0, - 31176, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31179, - 0, - 0, - 0, - 31186, - 0, - 0, - 0, - 31192, - 31195, - 0, - 0, - 31196, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31198, - 0, - 0, - 0, - 0, - 0, - 31199, - 0, - 0, - 0, - 31205, - 0, - 0, - 0, - 0, - 31211, - 31215, - 0, - 0, - 0, - 0, - 31231, - 0, - 31232, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31233, - 31236, - 31253, - 0, - 31254, - 0, - 0, - 0, - 0, - 0, - 0, - 31255, - 0, - 0, - 31257, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31258, - 31259, - 0, - 0, - 31260, - 0, - 31261, - 0, - 0, - 0, - 0, - 0, - 31262, - 31263, - 0, - 0, - 31264, - 0, - 31266, - 0, - 31267, - 0, - 0, - 0, - 0, - 0, - 31281, - 0, - 31282, - 0, - 31284, - 0, - 0, - 31285, - 31287, - 31288, - 0, - 0, - 31290, - 0, - 0, - 0, - 31292, - 31295, - 0, - 31299, - 0, - 31300, - 0, - 0, - 0, - 0, - 0, - 31302, - 0, - 0, - 0, - 0, - 31303, - 0, - 0, - 0, - 0, - 0, - 0, - 31304, - 0, - 0, - 0, - 0, - 0, - 31305, - 31308, - 31309, - 31315, - 0, - 31317, - 0, - 0, - 0, - 0, - 0, - 31323, - 0, - 31324, - 0, - 0, - 0, - 0, - 0, - 31325, - 31327, - 0, - 0, - 31331, - 0, - 0, - 0, - 0, - 0, - 31333, - 0, - 0, - 0, - 0, - 0, - 31336, - 0, - 0, - 31337, - 0, - 0, - 0, - 0, - 0, - 0, - 31338, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31339, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31342, - 0, - 0, - 0, - 0, - 31345, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31347, - 0, - 0, - 0, - 0, - 0, - 0, - 31348, - 0, - 0, - 31350, - 31351, - 0, - 31352, - 0, - 0, - 31354, - 0, - 0, - 0, - 0, - 31355, - 0, - 0, - 31356, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31363, - 0, - 31372, - 0, - 0, - 31373, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31376, - 0, - 31388, - 0, - 31389, - 0, - 31392, - 0, - 31401, - 0, - 31405, - 31407, - 31408, - 0, - 31409, - 0, - 0, - 0, - 0, - 0, - 0, - 31413, - 31415, - 0, - 0, - 0, - 31416, - 31418, - 0, - 0, - 0, - 0, - 0, - 0, - 31422, - 31423, - 0, - 0, - 31424, - 0, - 31425, - 31432, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31433, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31434, - 0, - 0, - 0, - 0, - 0, - 0, - 31435, - 0, - 0, - 0, - 0, - 31438, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31442, - 0, - 31444, - 0, - 31448, - 0, - 0, - 31451, - 0, - 0, - 0, - 0, - 31452, - 0, - 31461, - 31465, - 0, - 0, - 31466, - 0, - 0, - 31467, - 0, - 0, - 31468, - 0, - 0, - 0, - 31469, - 31473, - 0, - 31476, - 0, - 0, - 0, - 0, - 31489, - 31490, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31492, - 31493, - 31494, - 0, - 0, - 0, - 0, - 31501, - 31504, - 31505, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31509, - 0, - 0, - 0, - 0, - 31510, - 0, - 0, - 31511, - 0, - 0, - 31513, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31514, - 0, - 31522, - 31536, - 31539, - 31540, - 0, - 31541, - 0, - 0, - 0, - 0, - 0, - 0, - 31546, - 31553, - 31559, - 0, - 0, - 0, - 31560, - 31561, - 31562, - 0, - 0, - 31564, - 31567, - 0, - 31569, - 0, - 0, - 0, - 31570, - 0, - 0, - 0, - 0, - 31571, - 0, - 0, - 0, - 0, - 0, - 0, - 31572, - 31574, - 31580, - 31581, - 0, - 0, - 31582, - 31584, - 31585, - 31586, - 31595, - 0, - 31596, - 0, - 0, - 0, - 0, - 31597, - 0, - 31599, - 0, - 31600, - 31601, - 0, - 0, - 31603, - 31604, - 0, - 0, - 31608, - 31610, - 0, - 0, - 0, - 31611, - 0, - 31615, - 0, - 0, - 0, - 0, - 31616, - 0, - 0, - 0, - 0, - 0, - 0, - 31617, - 0, - 0, - 0, - 0, - 0, - 31618, - 0, - 0, - 0, - 0, - 0, - 0, - 31621, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31622, - 31625, - 0, - 0, - 0, - 0, - 31627, - 0, - 31641, - 0, - 0, - 31642, - 0, - 0, - 31643, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31644, - 0, - 31646, - 0, - 0, - 0, - 0, - 31648, - 0, - 0, - 0, - 31652, - 0, - 0, - 0, - 31657, - 0, - 0, - 31676, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 31689, - 31691, - 31692, - 0, - 31694, - 0, - 0, - 0, - 31696, - 0, - 31702, - 0, - 31703, - 0, -} - -var kStaticDictionaryWords = [31705]dictWord{ - dictWord{0, 0, 0}, - dictWord{8, 0, 1002}, - dictWord{136, 0, 1015}, - dictWord{4, 0, 683}, - dictWord{4, 10, 325}, - dictWord{138, 10, 125}, - dictWord{7, 11, 572}, - dictWord{ - 9, - 11, - 592, - }, - dictWord{11, 11, 680}, - dictWord{11, 11, 842}, - dictWord{11, 11, 924}, - dictWord{12, 11, 356}, - dictWord{12, 11, 550}, - dictWord{13, 11, 317}, - dictWord{13, 11, 370}, - dictWord{13, 11, 469}, - dictWord{13, 11, 471}, - dictWord{14, 11, 397}, - dictWord{18, 11, 69}, - dictWord{146, 11, 145}, - dictWord{ - 134, - 0, - 1265, - }, - dictWord{136, 11, 534}, - dictWord{134, 0, 1431}, - dictWord{11, 0, 138}, - dictWord{140, 0, 40}, - dictWord{4, 0, 155}, - dictWord{7, 0, 1689}, - dictWord{ - 4, - 10, - 718, - }, - dictWord{135, 10, 1216}, - dictWord{4, 0, 245}, - dictWord{5, 0, 151}, - dictWord{5, 0, 741}, - dictWord{6, 0, 1147}, - dictWord{7, 0, 498}, - dictWord{7, 0, 870}, - dictWord{7, 0, 1542}, - dictWord{12, 0, 213}, - dictWord{14, 0, 36}, - dictWord{14, 0, 391}, - dictWord{17, 0, 111}, - dictWord{18, 0, 6}, - dictWord{18, 0, 46}, - dictWord{ - 18, - 0, - 151, - }, - dictWord{19, 0, 36}, - dictWord{20, 0, 32}, - dictWord{20, 0, 56}, - dictWord{20, 0, 69}, - dictWord{20, 0, 102}, - dictWord{21, 0, 4}, - dictWord{22, 0, 8}, - dictWord{ - 22, - 0, - 10, - }, - dictWord{22, 0, 14}, - dictWord{150, 0, 31}, - dictWord{4, 0, 624}, - dictWord{135, 0, 1752}, - dictWord{5, 10, 124}, - dictWord{5, 10, 144}, - dictWord{6, 10, 548}, - dictWord{7, 10, 15}, - dictWord{7, 10, 153}, - dictWord{137, 10, 629}, - dictWord{6, 0, 503}, - dictWord{9, 0, 586}, - dictWord{13, 0, 468}, - dictWord{14, 0, 66}, - dictWord{ - 16, - 0, - 58, - }, - dictWord{7, 10, 1531}, - dictWord{8, 10, 416}, - dictWord{9, 10, 275}, - dictWord{10, 10, 100}, - dictWord{11, 10, 658}, - dictWord{11, 10, 979}, - dictWord{ - 12, - 10, - 86, - }, - dictWord{14, 10, 207}, - dictWord{15, 10, 20}, - dictWord{143, 10, 25}, - dictWord{5, 0, 603}, - dictWord{7, 0, 1212}, - dictWord{9, 0, 565}, - dictWord{ - 14, - 0, - 301, - }, - dictWord{5, 10, 915}, - dictWord{6, 10, 1783}, - dictWord{7, 10, 211}, - dictWord{7, 10, 1353}, - dictWord{9, 10, 83}, - dictWord{10, 10, 376}, - dictWord{ - 10, - 10, - 431, - }, - dictWord{11, 10, 543}, - dictWord{12, 10, 664}, - dictWord{13, 10, 280}, - dictWord{13, 10, 428}, - dictWord{14, 10, 128}, - dictWord{17, 10, 52}, - dictWord{ - 145, - 10, - 81, - }, - dictWord{4, 0, 492}, - dictWord{133, 0, 451}, - dictWord{135, 0, 835}, - dictWord{141, 0, 70}, - dictWord{132, 0, 539}, - dictWord{7, 11, 748}, - dictWord{ - 139, - 11, - 700, - }, - dictWord{7, 11, 1517}, - dictWord{11, 11, 597}, - dictWord{14, 11, 76}, - dictWord{14, 11, 335}, - dictWord{148, 11, 33}, - dictWord{6, 0, 113}, - dictWord{135, 0, 436}, - dictWord{4, 10, 338}, - dictWord{133, 10, 400}, - dictWord{136, 0, 718}, - dictWord{133, 11, 127}, - dictWord{133, 11, 418}, - dictWord{ - 6, - 0, - 1505, - }, - dictWord{7, 0, 520}, - dictWord{6, 11, 198}, - dictWord{11, 10, 892}, - dictWord{140, 11, 83}, - dictWord{4, 10, 221}, - dictWord{5, 10, 659}, - dictWord{ - 5, - 10, - 989, - }, - dictWord{7, 10, 697}, - dictWord{7, 10, 1211}, - dictWord{138, 10, 284}, - dictWord{135, 0, 1070}, - dictWord{5, 11, 276}, - dictWord{6, 11, 55}, - dictWord{ - 135, - 11, - 1369, - }, - dictWord{134, 0, 1515}, - dictWord{6, 11, 1752}, - dictWord{136, 11, 726}, - dictWord{138, 10, 507}, - dictWord{15, 0, 78}, - dictWord{4, 10, 188}, - dictWord{135, 10, 805}, - dictWord{5, 10, 884}, - dictWord{139, 10, 991}, - dictWord{133, 11, 764}, - dictWord{134, 10, 1653}, - dictWord{6, 11, 309}, - dictWord{ - 7, - 11, - 331, - }, - dictWord{138, 11, 550}, - dictWord{135, 11, 1861}, - dictWord{132, 11, 348}, - dictWord{135, 11, 986}, - dictWord{135, 11, 1573}, - dictWord{ - 12, - 0, - 610, - }, - dictWord{13, 0, 431}, - dictWord{144, 0, 59}, - dictWord{9, 11, 799}, - dictWord{140, 10, 166}, - dictWord{134, 0, 1530}, - dictWord{132, 0, 750}, - dictWord{132, 0, 307}, - dictWord{133, 0, 964}, - dictWord{6, 11, 194}, - dictWord{7, 11, 133}, - dictWord{10, 11, 493}, - dictWord{10, 11, 570}, - dictWord{139, 11, 664}, - dictWord{5, 11, 24}, - dictWord{5, 11, 569}, - dictWord{6, 11, 3}, - dictWord{6, 11, 119}, - dictWord{6, 11, 143}, - dictWord{6, 11, 440}, - dictWord{7, 11, 295}, - dictWord{ - 7, - 11, - 599, - }, - dictWord{7, 11, 1686}, - dictWord{7, 11, 1854}, - dictWord{8, 11, 424}, - dictWord{9, 11, 43}, - dictWord{9, 11, 584}, - dictWord{9, 11, 760}, - dictWord{ - 10, - 11, - 148, - }, - dictWord{10, 11, 328}, - dictWord{11, 11, 159}, - dictWord{11, 11, 253}, - dictWord{11, 11, 506}, - dictWord{12, 11, 487}, - dictWord{12, 11, 531}, - dictWord{144, 11, 33}, - dictWord{136, 10, 760}, - dictWord{5, 11, 14}, - dictWord{5, 11, 892}, - dictWord{6, 11, 283}, - dictWord{7, 11, 234}, - dictWord{136, 11, 537}, - dictWord{135, 11, 1251}, - dictWord{4, 11, 126}, - dictWord{8, 11, 635}, - dictWord{147, 11, 34}, - dictWord{4, 11, 316}, - dictWord{135, 11, 1561}, - dictWord{ - 6, - 0, - 999, - }, - dictWord{6, 0, 1310}, - dictWord{137, 11, 861}, - dictWord{4, 11, 64}, - dictWord{5, 11, 352}, - dictWord{5, 11, 720}, - dictWord{6, 11, 368}, - dictWord{ - 139, - 11, - 359, - }, - dictWord{4, 0, 75}, - dictWord{5, 0, 180}, - dictWord{6, 0, 500}, - dictWord{7, 0, 58}, - dictWord{7, 0, 710}, - dictWord{10, 0, 645}, - dictWord{136, 10, 770}, - dictWord{133, 0, 649}, - dictWord{6, 0, 276}, - dictWord{7, 0, 282}, - dictWord{7, 0, 879}, - dictWord{7, 0, 924}, - dictWord{8, 0, 459}, - dictWord{9, 0, 599}, - dictWord{9, 0, 754}, - dictWord{11, 0, 574}, - dictWord{12, 0, 128}, - dictWord{12, 0, 494}, - dictWord{13, 0, 52}, - dictWord{13, 0, 301}, - dictWord{15, 0, 30}, - dictWord{143, 0, 132}, - dictWord{132, 0, 200}, - dictWord{4, 10, 89}, - dictWord{5, 10, 489}, - dictWord{6, 10, 315}, - dictWord{7, 10, 553}, - dictWord{7, 10, 1745}, - dictWord{138, 10, 243}, - dictWord{135, 11, 1050}, - dictWord{7, 0, 1621}, - dictWord{6, 10, 1658}, - dictWord{9, 10, 3}, - dictWord{10, 10, 154}, - dictWord{11, 10, 641}, - dictWord{13, 10, 85}, - dictWord{13, 10, 201}, - dictWord{141, 10, 346}, - dictWord{6, 11, 175}, - dictWord{137, 11, 289}, - dictWord{5, 11, 432}, - dictWord{133, 11, 913}, - dictWord{ - 6, - 0, - 225, - }, - dictWord{137, 0, 211}, - dictWord{7, 0, 718}, - dictWord{8, 0, 687}, - dictWord{139, 0, 374}, - dictWord{4, 10, 166}, - dictWord{133, 10, 505}, - dictWord{ - 9, - 0, - 110, - }, - dictWord{134, 10, 1670}, - dictWord{8, 0, 58}, - dictWord{9, 0, 724}, - dictWord{11, 0, 809}, - dictWord{13, 0, 113}, - dictWord{145, 0, 72}, - dictWord{6, 0, 345}, - dictWord{7, 0, 1247}, - dictWord{144, 11, 82}, - dictWord{5, 11, 931}, - dictWord{134, 11, 1698}, - dictWord{8, 0, 767}, - dictWord{8, 0, 803}, - dictWord{9, 0, 301}, - dictWord{137, 0, 903}, - dictWord{139, 0, 203}, - dictWord{134, 0, 1154}, - dictWord{7, 0, 1949}, - dictWord{136, 0, 674}, - dictWord{134, 0, 259}, - dictWord{ - 135, - 0, - 1275, - }, - dictWord{5, 11, 774}, - dictWord{6, 11, 1637}, - dictWord{6, 11, 1686}, - dictWord{134, 11, 1751}, - dictWord{134, 0, 1231}, - dictWord{7, 10, 445}, - dictWord{8, 10, 307}, - dictWord{8, 10, 704}, - dictWord{10, 10, 41}, - dictWord{10, 10, 439}, - dictWord{11, 10, 237}, - dictWord{11, 10, 622}, - dictWord{140, 10, 201}, - dictWord{136, 0, 254}, - dictWord{6, 11, 260}, - dictWord{135, 11, 1484}, - dictWord{139, 0, 277}, - dictWord{135, 10, 1977}, - dictWord{4, 10, 189}, - dictWord{ - 5, - 10, - 713, - }, - dictWord{6, 11, 573}, - dictWord{136, 10, 57}, - dictWord{138, 10, 371}, - dictWord{132, 10, 552}, - dictWord{134, 11, 344}, - dictWord{133, 0, 248}, - dictWord{9, 0, 800}, - dictWord{10, 0, 693}, - dictWord{11, 0, 482}, - dictWord{11, 0, 734}, - dictWord{11, 0, 789}, - dictWord{134, 11, 240}, - dictWord{4, 0, 116}, - dictWord{ - 5, - 0, - 95, - }, - dictWord{5, 0, 445}, - dictWord{7, 0, 1688}, - dictWord{8, 0, 29}, - dictWord{9, 0, 272}, - dictWord{11, 0, 509}, - dictWord{11, 0, 915}, - dictWord{4, 11, 292}, - dictWord{4, 11, 736}, - dictWord{5, 11, 871}, - dictWord{6, 11, 171}, - dictWord{6, 11, 1689}, - dictWord{7, 11, 1324}, - dictWord{7, 11, 1944}, - dictWord{9, 11, 415}, - dictWord{9, 11, 580}, - dictWord{14, 11, 230}, - dictWord{146, 11, 68}, - dictWord{7, 0, 490}, - dictWord{13, 0, 100}, - dictWord{143, 0, 75}, - dictWord{135, 0, 1641}, - dictWord{133, 0, 543}, - dictWord{7, 11, 209}, - dictWord{8, 11, 661}, - dictWord{10, 11, 42}, - dictWord{11, 11, 58}, - dictWord{12, 11, 58}, - dictWord{12, 11, 118}, - dictWord{141, 11, 32}, - dictWord{5, 0, 181}, - dictWord{8, 0, 41}, - dictWord{6, 11, 63}, - dictWord{135, 11, 920}, - dictWord{133, 0, 657}, - dictWord{133, 11, 793}, - dictWord{138, 0, 709}, - dictWord{7, 0, 25}, - dictWord{8, 0, 202}, - dictWord{138, 0, 536}, - dictWord{5, 11, 665}, - dictWord{135, 10, 1788}, - dictWord{145, 10, 49}, - dictWord{9, 0, 423}, - dictWord{140, 0, 89}, - dictWord{5, 11, 67}, - dictWord{6, 11, 62}, - dictWord{6, 11, 374}, - dictWord{135, 11, 1391}, - dictWord{8, 0, 113}, - dictWord{ - 9, - 0, - 877, - }, - dictWord{10, 0, 554}, - dictWord{11, 0, 83}, - dictWord{12, 0, 136}, - dictWord{19, 0, 109}, - dictWord{9, 11, 790}, - dictWord{140, 11, 47}, - dictWord{ - 138, - 10, - 661, - }, - dictWord{4, 0, 963}, - dictWord{10, 0, 927}, - dictWord{14, 0, 442}, - dictWord{135, 10, 1945}, - dictWord{133, 0, 976}, - dictWord{132, 0, 206}, - dictWord{ - 4, - 11, - 391, - }, - dictWord{135, 11, 1169}, - dictWord{134, 0, 2002}, - dictWord{6, 0, 696}, - dictWord{134, 0, 1008}, - dictWord{134, 0, 1170}, - dictWord{132, 11, 271}, - dictWord{7, 0, 13}, - dictWord{8, 0, 226}, - dictWord{10, 0, 537}, - dictWord{11, 0, 570}, - dictWord{11, 0, 605}, - dictWord{11, 0, 799}, - dictWord{11, 0, 804}, - dictWord{ - 12, - 0, - 85, - }, - dictWord{12, 0, 516}, - dictWord{12, 0, 623}, - dictWord{13, 0, 112}, - dictWord{13, 0, 361}, - dictWord{14, 0, 77}, - dictWord{14, 0, 78}, - dictWord{17, 0, 28}, - dictWord{19, 0, 110}, - dictWord{140, 11, 314}, - dictWord{132, 0, 769}, - dictWord{134, 0, 1544}, - dictWord{4, 0, 551}, - dictWord{137, 0, 678}, - dictWord{5, 10, 84}, - dictWord{134, 10, 163}, - dictWord{9, 0, 57}, - dictWord{9, 0, 459}, - dictWord{10, 0, 425}, - dictWord{11, 0, 119}, - dictWord{12, 0, 184}, - dictWord{12, 0, 371}, - dictWord{ - 13, - 0, - 358, - }, - dictWord{145, 0, 51}, - dictWord{5, 0, 188}, - dictWord{5, 0, 814}, - dictWord{8, 0, 10}, - dictWord{9, 0, 421}, - dictWord{9, 0, 729}, - dictWord{10, 0, 609}, - dictWord{11, 0, 689}, - dictWord{4, 11, 253}, - dictWord{5, 10, 410}, - dictWord{5, 11, 544}, - dictWord{7, 11, 300}, - dictWord{137, 11, 340}, - dictWord{134, 0, 624}, - dictWord{138, 11, 321}, - dictWord{135, 0, 1941}, - dictWord{18, 0, 130}, - dictWord{5, 10, 322}, - dictWord{8, 10, 186}, - dictWord{9, 10, 262}, - dictWord{10, 10, 187}, - dictWord{142, 10, 208}, - dictWord{5, 11, 53}, - dictWord{5, 11, 541}, - dictWord{6, 11, 94}, - dictWord{6, 11, 499}, - dictWord{7, 11, 230}, - dictWord{139, 11, 321}, - dictWord{133, 10, 227}, - dictWord{4, 0, 378}, - dictWord{4, 11, 920}, - dictWord{5, 11, 25}, - dictWord{5, 11, 790}, - dictWord{6, 11, 457}, - dictWord{135, 11, 853}, - dictWord{137, 0, 269}, - dictWord{132, 0, 528}, - dictWord{134, 0, 1146}, - dictWord{7, 10, 1395}, - dictWord{8, 10, 486}, - dictWord{9, 10, 236}, - dictWord{9, 10, 878}, - dictWord{10, 10, 218}, - dictWord{11, 10, 95}, - dictWord{19, 10, 17}, - dictWord{147, 10, 31}, - dictWord{7, 10, 2043}, - dictWord{8, 10, 672}, - dictWord{ - 141, - 10, - 448, - }, - dictWord{134, 0, 1105}, - dictWord{134, 0, 1616}, - dictWord{134, 11, 1765}, - dictWord{140, 11, 163}, - dictWord{5, 10, 412}, - dictWord{133, 11, 822}, - dictWord{132, 11, 634}, - dictWord{6, 0, 656}, - dictWord{134, 11, 1730}, - dictWord{134, 0, 1940}, - dictWord{5, 0, 104}, - dictWord{6, 0, 173}, - dictWord{ - 135, - 0, - 1631, - }, - dictWord{136, 10, 562}, - dictWord{6, 11, 36}, - dictWord{7, 11, 658}, - dictWord{8, 11, 454}, - dictWord{147, 11, 86}, - dictWord{5, 0, 457}, - dictWord{ - 134, - 10, - 1771, - }, - dictWord{7, 0, 810}, - dictWord{8, 0, 138}, - dictWord{8, 0, 342}, - dictWord{9, 0, 84}, - dictWord{10, 0, 193}, - dictWord{11, 0, 883}, - dictWord{140, 0, 359}, - dictWord{9, 0, 620}, - dictWord{135, 10, 1190}, - dictWord{137, 10, 132}, - dictWord{7, 11, 975}, - dictWord{137, 11, 789}, - dictWord{6, 0, 95}, - dictWord{6, 0, 1934}, - dictWord{136, 0, 967}, - dictWord{141, 11, 335}, - dictWord{6, 0, 406}, - dictWord{10, 0, 409}, - dictWord{10, 0, 447}, - dictWord{11, 0, 44}, - dictWord{140, 0, 100}, - dictWord{4, 10, 317}, - dictWord{135, 10, 1279}, - dictWord{132, 0, 477}, - dictWord{134, 0, 1268}, - dictWord{6, 0, 1941}, - dictWord{8, 0, 944}, - dictWord{5, 10, 63}, - dictWord{133, 10, 509}, - dictWord{132, 0, 629}, - dictWord{132, 11, 104}, - dictWord{4, 0, 246}, - dictWord{133, 0, 375}, - dictWord{6, 0, 1636}, - dictWord{ - 132, - 10, - 288, - }, - dictWord{135, 11, 1614}, - dictWord{9, 0, 49}, - dictWord{10, 0, 774}, - dictWord{8, 10, 89}, - dictWord{8, 10, 620}, - dictWord{11, 10, 628}, - dictWord{ - 12, - 10, - 322, - }, - dictWord{143, 10, 124}, - dictWord{4, 0, 282}, - dictWord{7, 0, 1034}, - dictWord{11, 0, 398}, - dictWord{11, 0, 634}, - dictWord{12, 0, 1}, - dictWord{12, 0, 79}, - dictWord{12, 0, 544}, - dictWord{14, 0, 237}, - dictWord{17, 0, 10}, - dictWord{146, 0, 20}, - dictWord{132, 0, 824}, - dictWord{7, 11, 45}, - dictWord{9, 11, 542}, - dictWord{ - 9, - 11, - 566, - }, - dictWord{138, 11, 728}, - dictWord{5, 0, 118}, - dictWord{5, 0, 499}, - dictWord{6, 0, 476}, - dictWord{6, 0, 665}, - dictWord{6, 0, 1176}, - dictWord{ - 6, - 0, - 1196, - }, - dictWord{7, 0, 600}, - dictWord{7, 0, 888}, - dictWord{135, 0, 1096}, - dictWord{7, 0, 296}, - dictWord{7, 0, 596}, - dictWord{8, 0, 560}, - dictWord{8, 0, 586}, - dictWord{9, 0, 612}, - dictWord{11, 0, 304}, - dictWord{12, 0, 46}, - dictWord{13, 0, 89}, - dictWord{14, 0, 112}, - dictWord{145, 0, 122}, - dictWord{5, 0, 894}, - dictWord{ - 6, - 0, - 1772, - }, - dictWord{9, 0, 1009}, - dictWord{138, 10, 120}, - dictWord{5, 11, 533}, - dictWord{7, 11, 755}, - dictWord{138, 11, 780}, - dictWord{151, 10, 1}, - dictWord{ - 6, - 0, - 1474, - }, - dictWord{7, 11, 87}, - dictWord{142, 11, 288}, - dictWord{139, 0, 366}, - dictWord{137, 10, 461}, - dictWord{7, 11, 988}, - dictWord{7, 11, 1939}, - dictWord{ - 9, - 11, - 64, - }, - dictWord{9, 11, 502}, - dictWord{12, 11, 7}, - dictWord{12, 11, 34}, - dictWord{13, 11, 12}, - dictWord{13, 11, 234}, - dictWord{147, 11, 77}, - dictWord{ - 7, - 0, - 1599, - }, - dictWord{7, 0, 1723}, - dictWord{8, 0, 79}, - dictWord{8, 0, 106}, - dictWord{8, 0, 190}, - dictWord{8, 0, 302}, - dictWord{8, 0, 383}, - dictWord{8, 0, 713}, - dictWord{ - 9, - 0, - 119, - }, - dictWord{9, 0, 233}, - dictWord{9, 0, 419}, - dictWord{9, 0, 471}, - dictWord{10, 0, 181}, - dictWord{10, 0, 406}, - dictWord{11, 0, 57}, - dictWord{11, 0, 85}, - dictWord{11, 0, 120}, - dictWord{11, 0, 177}, - dictWord{11, 0, 296}, - dictWord{11, 0, 382}, - dictWord{11, 0, 454}, - dictWord{11, 0, 758}, - dictWord{11, 0, 999}, - dictWord{ - 12, - 0, - 27, - }, - dictWord{12, 0, 98}, - dictWord{12, 0, 131}, - dictWord{12, 0, 245}, - dictWord{12, 0, 312}, - dictWord{12, 0, 446}, - dictWord{12, 0, 454}, - dictWord{13, 0, 25}, - dictWord{13, 0, 98}, - dictWord{13, 0, 426}, - dictWord{13, 0, 508}, - dictWord{14, 0, 70}, - dictWord{14, 0, 163}, - dictWord{14, 0, 272}, - dictWord{14, 0, 277}, - dictWord{ - 14, - 0, - 370, - }, - dictWord{15, 0, 95}, - dictWord{15, 0, 138}, - dictWord{15, 0, 167}, - dictWord{17, 0, 38}, - dictWord{148, 0, 96}, - dictWord{135, 10, 1346}, - dictWord{ - 10, - 0, - 200, - }, - dictWord{19, 0, 2}, - dictWord{151, 0, 22}, - dictWord{135, 11, 141}, - dictWord{134, 10, 85}, - dictWord{134, 0, 1759}, - dictWord{138, 0, 372}, - dictWord{ - 145, - 0, - 16, - }, - dictWord{8, 0, 943}, - dictWord{132, 11, 619}, - dictWord{139, 11, 88}, - dictWord{5, 11, 246}, - dictWord{8, 11, 189}, - dictWord{9, 11, 355}, - dictWord{ - 9, - 11, - 512, - }, - dictWord{10, 11, 124}, - dictWord{10, 11, 453}, - dictWord{11, 11, 143}, - dictWord{11, 11, 416}, - dictWord{11, 11, 859}, - dictWord{141, 11, 341}, - dictWord{ - 5, - 0, - 258, - }, - dictWord{134, 0, 719}, - dictWord{6, 0, 1798}, - dictWord{6, 0, 1839}, - dictWord{8, 0, 900}, - dictWord{10, 0, 874}, - dictWord{10, 0, 886}, - dictWord{ - 12, - 0, - 698, - }, - dictWord{12, 0, 732}, - dictWord{12, 0, 770}, - dictWord{16, 0, 106}, - dictWord{18, 0, 163}, - dictWord{18, 0, 170}, - dictWord{18, 0, 171}, - dictWord{152, 0, 20}, - dictWord{9, 0, 707}, - dictWord{11, 0, 326}, - dictWord{11, 0, 339}, - dictWord{12, 0, 423}, - dictWord{12, 0, 502}, - dictWord{20, 0, 62}, - dictWord{9, 11, 707}, - dictWord{ - 11, - 11, - 326, - }, - dictWord{11, 11, 339}, - dictWord{12, 11, 423}, - dictWord{12, 11, 502}, - dictWord{148, 11, 62}, - dictWord{5, 0, 30}, - dictWord{7, 0, 495}, - dictWord{ - 8, - 0, - 134, - }, - dictWord{9, 0, 788}, - dictWord{140, 0, 438}, - dictWord{133, 11, 678}, - dictWord{5, 10, 279}, - dictWord{6, 10, 235}, - dictWord{7, 10, 468}, - dictWord{ - 8, - 10, - 446, - }, - dictWord{9, 10, 637}, - dictWord{10, 10, 717}, - dictWord{11, 10, 738}, - dictWord{140, 10, 514}, - dictWord{5, 11, 35}, - dictWord{6, 11, 287}, - dictWord{ - 7, - 11, - 862, - }, - dictWord{7, 11, 1886}, - dictWord{138, 11, 179}, - dictWord{7, 0, 1948}, - dictWord{7, 0, 2004}, - dictWord{132, 11, 517}, - dictWord{5, 10, 17}, - dictWord{ - 6, - 10, - 371, - }, - dictWord{137, 10, 528}, - dictWord{4, 0, 115}, - dictWord{5, 0, 669}, - dictWord{6, 0, 407}, - dictWord{8, 0, 311}, - dictWord{11, 0, 10}, - dictWord{141, 0, 5}, - dictWord{137, 0, 381}, - dictWord{5, 0, 50}, - dictWord{6, 0, 439}, - dictWord{7, 0, 780}, - dictWord{135, 0, 1040}, - dictWord{136, 11, 667}, - dictWord{11, 11, 403}, - dictWord{146, 11, 83}, - dictWord{5, 0, 1}, - dictWord{6, 0, 81}, - dictWord{138, 0, 520}, - dictWord{134, 0, 738}, - dictWord{5, 0, 482}, - dictWord{8, 0, 98}, - dictWord{9, 0, 172}, - dictWord{10, 0, 360}, - dictWord{10, 0, 700}, - dictWord{10, 0, 822}, - dictWord{11, 0, 302}, - dictWord{11, 0, 778}, - dictWord{12, 0, 50}, - dictWord{12, 0, 127}, - dictWord{ - 12, - 0, - 396, - }, - dictWord{13, 0, 62}, - dictWord{13, 0, 328}, - dictWord{14, 0, 122}, - dictWord{147, 0, 72}, - dictWord{9, 11, 157}, - dictWord{10, 11, 131}, - dictWord{ - 140, - 11, - 72, - }, - dictWord{135, 11, 714}, - dictWord{135, 11, 539}, - dictWord{5, 0, 2}, - dictWord{6, 0, 512}, - dictWord{7, 0, 797}, - dictWord{7, 0, 1494}, - dictWord{8, 0, 253}, - dictWord{8, 0, 589}, - dictWord{9, 0, 77}, - dictWord{10, 0, 1}, - dictWord{10, 0, 129}, - dictWord{10, 0, 225}, - dictWord{11, 0, 118}, - dictWord{11, 0, 226}, - dictWord{ - 11, - 0, - 251, - }, - dictWord{11, 0, 430}, - dictWord{11, 0, 701}, - dictWord{11, 0, 974}, - dictWord{11, 0, 982}, - dictWord{12, 0, 64}, - dictWord{12, 0, 260}, - dictWord{12, 0, 488}, - dictWord{140, 0, 690}, - dictWord{5, 11, 394}, - dictWord{7, 11, 367}, - dictWord{7, 11, 487}, - dictWord{7, 11, 857}, - dictWord{7, 11, 1713}, - dictWord{8, 11, 246}, - dictWord{9, 11, 537}, - dictWord{10, 11, 165}, - dictWord{12, 11, 219}, - dictWord{140, 11, 561}, - dictWord{136, 0, 557}, - dictWord{5, 10, 779}, - dictWord{5, 10, 807}, - dictWord{6, 10, 1655}, - dictWord{134, 10, 1676}, - dictWord{4, 10, 196}, - dictWord{5, 10, 558}, - dictWord{133, 10, 949}, - dictWord{11, 11, 827}, - dictWord{ - 12, - 11, - 56, - }, - dictWord{14, 11, 34}, - dictWord{143, 11, 148}, - dictWord{137, 0, 347}, - dictWord{133, 0, 572}, - dictWord{134, 0, 832}, - dictWord{4, 0, 12}, - dictWord{ - 7, - 0, - 504, - }, - dictWord{7, 0, 522}, - dictWord{7, 0, 809}, - dictWord{8, 0, 797}, - dictWord{141, 0, 88}, - dictWord{4, 10, 752}, - dictWord{133, 11, 449}, - dictWord{7, 11, 86}, - dictWord{8, 11, 103}, - dictWord{145, 11, 69}, - dictWord{7, 11, 2028}, - dictWord{138, 11, 641}, - dictWord{5, 0, 528}, - dictWord{6, 11, 1}, - dictWord{142, 11, 2}, - dictWord{134, 0, 861}, - dictWord{10, 0, 294}, - dictWord{4, 10, 227}, - dictWord{5, 10, 159}, - dictWord{5, 10, 409}, - dictWord{7, 10, 80}, - dictWord{10, 10, 479}, - dictWord{ - 12, - 10, - 418, - }, - dictWord{14, 10, 50}, - dictWord{14, 10, 249}, - dictWord{142, 10, 295}, - dictWord{7, 10, 1470}, - dictWord{8, 10, 66}, - dictWord{8, 10, 137}, - dictWord{ - 8, - 10, - 761, - }, - dictWord{9, 10, 638}, - dictWord{11, 10, 80}, - dictWord{11, 10, 212}, - dictWord{11, 10, 368}, - dictWord{11, 10, 418}, - dictWord{12, 10, 8}, - dictWord{ - 13, - 10, - 15, - }, - dictWord{16, 10, 61}, - dictWord{17, 10, 59}, - dictWord{19, 10, 28}, - dictWord{148, 10, 84}, - dictWord{20, 0, 109}, - dictWord{135, 11, 1148}, - dictWord{ - 6, - 11, - 277, - }, - dictWord{7, 11, 1274}, - dictWord{7, 11, 1386}, - dictWord{7, 11, 1392}, - dictWord{12, 11, 129}, - dictWord{146, 11, 87}, - dictWord{6, 11, 187}, - dictWord{7, 11, 39}, - dictWord{7, 11, 1203}, - dictWord{8, 11, 380}, - dictWord{8, 11, 542}, - dictWord{14, 11, 117}, - dictWord{149, 11, 28}, - dictWord{134, 0, 1187}, - dictWord{5, 0, 266}, - dictWord{9, 0, 290}, - dictWord{9, 0, 364}, - dictWord{10, 0, 293}, - dictWord{11, 0, 606}, - dictWord{142, 0, 45}, - dictWord{6, 11, 297}, - dictWord{ - 7, - 11, - 793, - }, - dictWord{139, 11, 938}, - dictWord{4, 0, 50}, - dictWord{6, 0, 594}, - dictWord{9, 0, 121}, - dictWord{10, 0, 49}, - dictWord{10, 0, 412}, - dictWord{139, 0, 834}, - dictWord{136, 0, 748}, - dictWord{7, 11, 464}, - dictWord{8, 11, 438}, - dictWord{11, 11, 105}, - dictWord{11, 11, 363}, - dictWord{12, 11, 231}, - dictWord{ - 14, - 11, - 386, - }, - dictWord{15, 11, 102}, - dictWord{148, 11, 75}, - dictWord{132, 0, 466}, - dictWord{13, 0, 399}, - dictWord{14, 0, 337}, - dictWord{6, 10, 38}, - dictWord{ - 7, - 10, - 1220, - }, - dictWord{8, 10, 185}, - dictWord{8, 10, 256}, - dictWord{9, 10, 22}, - dictWord{9, 10, 331}, - dictWord{10, 10, 738}, - dictWord{11, 10, 205}, - dictWord{ - 11, - 10, - 540, - }, - dictWord{11, 10, 746}, - dictWord{13, 10, 465}, - dictWord{142, 10, 194}, - dictWord{9, 0, 378}, - dictWord{141, 0, 162}, - dictWord{137, 0, 519}, - dictWord{ - 4, - 10, - 159, - }, - dictWord{6, 10, 115}, - dictWord{7, 10, 252}, - dictWord{7, 10, 257}, - dictWord{7, 10, 1928}, - dictWord{8, 10, 69}, - dictWord{9, 10, 384}, - dictWord{ - 10, - 10, - 91, - }, - dictWord{10, 10, 615}, - dictWord{12, 10, 375}, - dictWord{14, 10, 235}, - dictWord{18, 10, 117}, - dictWord{147, 10, 123}, - dictWord{5, 11, 604}, - dictWord{ - 5, - 10, - 911, - }, - dictWord{136, 10, 278}, - dictWord{132, 0, 667}, - dictWord{8, 0, 351}, - dictWord{9, 0, 322}, - dictWord{4, 10, 151}, - dictWord{135, 10, 1567}, - dictWord{134, 0, 902}, - dictWord{133, 10, 990}, - dictWord{12, 0, 180}, - dictWord{5, 10, 194}, - dictWord{7, 10, 1662}, - dictWord{137, 10, 90}, - dictWord{4, 0, 869}, - dictWord{134, 0, 1996}, - dictWord{134, 0, 813}, - dictWord{133, 10, 425}, - dictWord{137, 11, 761}, - dictWord{132, 0, 260}, - dictWord{133, 10, 971}, - dictWord{ - 5, - 11, - 20, - }, - dictWord{6, 11, 298}, - dictWord{7, 11, 659}, - dictWord{7, 11, 1366}, - dictWord{137, 11, 219}, - dictWord{4, 0, 39}, - dictWord{5, 0, 36}, - dictWord{ - 7, - 0, - 1843, - }, - dictWord{8, 0, 407}, - dictWord{11, 0, 144}, - dictWord{140, 0, 523}, - dictWord{4, 0, 510}, - dictWord{10, 0, 587}, - dictWord{139, 10, 752}, - dictWord{7, 0, 29}, - dictWord{7, 0, 66}, - dictWord{7, 0, 1980}, - dictWord{10, 0, 487}, - dictWord{138, 0, 809}, - dictWord{13, 0, 260}, - dictWord{14, 0, 82}, - dictWord{18, 0, 63}, - dictWord{ - 137, - 10, - 662, - }, - dictWord{5, 10, 72}, - dictWord{6, 10, 264}, - dictWord{7, 10, 21}, - dictWord{7, 10, 46}, - dictWord{7, 10, 2013}, - dictWord{8, 10, 215}, - dictWord{ - 8, - 10, - 513, - }, - dictWord{10, 10, 266}, - dictWord{139, 10, 22}, - dictWord{134, 0, 570}, - dictWord{6, 0, 565}, - dictWord{7, 0, 1667}, - dictWord{4, 11, 439}, - dictWord{ - 10, - 10, - 95, - }, - dictWord{11, 10, 603}, - dictWord{12, 11, 242}, - dictWord{13, 10, 443}, - dictWord{14, 10, 160}, - dictWord{143, 10, 4}, - dictWord{134, 0, 1464}, - dictWord{ - 134, - 10, - 431, - }, - dictWord{9, 0, 372}, - dictWord{15, 0, 2}, - dictWord{19, 0, 10}, - dictWord{19, 0, 18}, - dictWord{5, 10, 874}, - dictWord{6, 10, 1677}, - dictWord{143, 10, 0}, - dictWord{132, 0, 787}, - dictWord{6, 0, 380}, - dictWord{12, 0, 399}, - dictWord{21, 0, 19}, - dictWord{7, 10, 939}, - dictWord{7, 10, 1172}, - dictWord{7, 10, 1671}, - dictWord{9, 10, 540}, - dictWord{10, 10, 696}, - dictWord{11, 10, 265}, - dictWord{11, 10, 732}, - dictWord{11, 10, 928}, - dictWord{11, 10, 937}, - dictWord{ - 141, - 10, - 438, - }, - dictWord{137, 0, 200}, - dictWord{132, 11, 233}, - dictWord{132, 0, 516}, - dictWord{134, 11, 577}, - dictWord{132, 0, 844}, - dictWord{11, 0, 887}, - dictWord{14, 0, 365}, - dictWord{142, 0, 375}, - dictWord{132, 11, 482}, - dictWord{8, 0, 821}, - dictWord{140, 0, 44}, - dictWord{7, 0, 1655}, - dictWord{136, 0, 305}, - dictWord{5, 10, 682}, - dictWord{135, 10, 1887}, - dictWord{135, 11, 346}, - dictWord{132, 10, 696}, - dictWord{4, 0, 10}, - dictWord{7, 0, 917}, - dictWord{139, 0, 786}, - dictWord{5, 11, 795}, - dictWord{6, 11, 1741}, - dictWord{8, 11, 417}, - dictWord{137, 11, 782}, - dictWord{4, 0, 1016}, - dictWord{134, 0, 2031}, - dictWord{5, 0, 684}, - dictWord{4, 10, 726}, - dictWord{133, 10, 630}, - dictWord{6, 0, 1021}, - dictWord{134, 0, 1480}, - dictWord{8, 10, 802}, - dictWord{136, 10, 838}, - dictWord{ - 134, - 0, - 27, - }, - dictWord{134, 0, 395}, - dictWord{135, 11, 622}, - dictWord{7, 11, 625}, - dictWord{135, 11, 1750}, - dictWord{4, 11, 203}, - dictWord{135, 11, 1936}, - dictWord{6, 10, 118}, - dictWord{7, 10, 215}, - dictWord{7, 10, 1521}, - dictWord{140, 10, 11}, - dictWord{132, 0, 813}, - dictWord{136, 0, 511}, - dictWord{7, 10, 615}, - dictWord{138, 10, 251}, - dictWord{135, 10, 1044}, - dictWord{145, 0, 56}, - dictWord{133, 10, 225}, - dictWord{6, 0, 342}, - dictWord{6, 0, 496}, - dictWord{8, 0, 275}, - dictWord{137, 0, 206}, - dictWord{4, 0, 909}, - dictWord{133, 0, 940}, - dictWord{132, 0, 891}, - dictWord{7, 11, 311}, - dictWord{9, 11, 308}, - dictWord{ - 140, - 11, - 255, - }, - dictWord{4, 10, 370}, - dictWord{5, 10, 756}, - dictWord{135, 10, 1326}, - dictWord{4, 0, 687}, - dictWord{134, 0, 1596}, - dictWord{134, 0, 1342}, - dictWord{ - 6, - 10, - 1662, - }, - dictWord{7, 10, 48}, - dictWord{8, 10, 771}, - dictWord{10, 10, 116}, - dictWord{13, 10, 104}, - dictWord{14, 10, 105}, - dictWord{14, 10, 184}, - dictWord{15, 10, 168}, - dictWord{19, 10, 92}, - dictWord{148, 10, 68}, - dictWord{138, 10, 209}, - dictWord{4, 11, 400}, - dictWord{5, 11, 267}, - dictWord{135, 11, 232}, - dictWord{151, 11, 12}, - dictWord{6, 0, 41}, - dictWord{141, 0, 160}, - dictWord{141, 11, 314}, - dictWord{134, 0, 1718}, - dictWord{136, 0, 778}, - dictWord{ - 142, - 11, - 261, - }, - dictWord{134, 0, 1610}, - dictWord{133, 0, 115}, - dictWord{132, 0, 294}, - dictWord{14, 0, 314}, - dictWord{132, 10, 120}, - dictWord{132, 0, 983}, - dictWord{5, 0, 193}, - dictWord{140, 0, 178}, - dictWord{138, 10, 429}, - dictWord{5, 10, 820}, - dictWord{135, 10, 931}, - dictWord{6, 0, 994}, - dictWord{6, 0, 1051}, - dictWord{6, 0, 1439}, - dictWord{7, 0, 174}, - dictWord{133, 11, 732}, - dictWord{4, 11, 100}, - dictWord{7, 11, 679}, - dictWord{8, 11, 313}, - dictWord{138, 10, 199}, - dictWord{6, 10, 151}, - dictWord{6, 10, 1675}, - dictWord{7, 10, 383}, - dictWord{151, 10, 10}, - dictWord{6, 0, 1796}, - dictWord{8, 0, 848}, - dictWord{8, 0, 867}, - dictWord{ - 8, - 0, - 907, - }, - dictWord{10, 0, 855}, - dictWord{140, 0, 703}, - dictWord{140, 0, 221}, - dictWord{4, 0, 122}, - dictWord{5, 0, 796}, - dictWord{5, 0, 952}, - dictWord{6, 0, 1660}, - dictWord{6, 0, 1671}, - dictWord{8, 0, 567}, - dictWord{9, 0, 687}, - dictWord{9, 0, 742}, - dictWord{10, 0, 686}, - dictWord{11, 0, 682}, - dictWord{11, 0, 909}, - dictWord{ - 140, - 0, - 281, - }, - dictWord{5, 11, 362}, - dictWord{5, 11, 443}, - dictWord{6, 11, 318}, - dictWord{7, 11, 1019}, - dictWord{139, 11, 623}, - dictWord{5, 11, 463}, - dictWord{136, 11, 296}, - dictWord{11, 0, 583}, - dictWord{13, 0, 262}, - dictWord{6, 10, 1624}, - dictWord{12, 10, 422}, - dictWord{142, 10, 360}, - dictWord{5, 0, 179}, - dictWord{7, 0, 1095}, - dictWord{135, 0, 1213}, - dictWord{4, 10, 43}, - dictWord{4, 11, 454}, - dictWord{5, 10, 344}, - dictWord{133, 10, 357}, - dictWord{4, 0, 66}, - dictWord{7, 0, 722}, - dictWord{135, 0, 904}, - dictWord{134, 0, 773}, - dictWord{7, 0, 352}, - dictWord{133, 10, 888}, - dictWord{5, 11, 48}, - dictWord{5, 11, 404}, - dictWord{ - 6, - 11, - 557, - }, - dictWord{7, 11, 458}, - dictWord{8, 11, 597}, - dictWord{10, 11, 455}, - dictWord{10, 11, 606}, - dictWord{11, 11, 49}, - dictWord{11, 11, 548}, - dictWord{ - 12, - 11, - 476, - }, - dictWord{13, 11, 18}, - dictWord{141, 11, 450}, - dictWord{134, 11, 418}, - dictWord{132, 10, 711}, - dictWord{5, 11, 442}, - dictWord{ - 135, - 11, - 1984, - }, - dictWord{141, 0, 35}, - dictWord{137, 0, 152}, - dictWord{134, 0, 1197}, - dictWord{135, 11, 1093}, - dictWord{137, 11, 203}, - dictWord{137, 10, 440}, - dictWord{10, 0, 592}, - dictWord{10, 0, 753}, - dictWord{12, 0, 317}, - dictWord{12, 0, 355}, - dictWord{12, 0, 465}, - dictWord{12, 0, 469}, - dictWord{12, 0, 560}, - dictWord{12, 0, 578}, - dictWord{141, 0, 243}, - dictWord{133, 0, 564}, - dictWord{134, 0, 797}, - dictWord{5, 10, 958}, - dictWord{133, 10, 987}, - dictWord{5, 11, 55}, - dictWord{7, 11, 376}, - dictWord{140, 11, 161}, - dictWord{133, 11, 450}, - dictWord{134, 0, 556}, - dictWord{134, 0, 819}, - dictWord{11, 10, 276}, - dictWord{ - 142, - 10, - 293, - }, - dictWord{7, 0, 544}, - dictWord{138, 0, 61}, - dictWord{8, 0, 719}, - dictWord{4, 10, 65}, - dictWord{5, 10, 479}, - dictWord{5, 10, 1004}, - dictWord{7, 10, 1913}, - dictWord{8, 10, 317}, - dictWord{9, 10, 302}, - dictWord{10, 10, 612}, - dictWord{141, 10, 22}, - dictWord{4, 0, 5}, - dictWord{5, 0, 498}, - dictWord{8, 0, 637}, - dictWord{ - 9, - 0, - 521, - }, - dictWord{4, 11, 213}, - dictWord{4, 10, 261}, - dictWord{7, 11, 223}, - dictWord{7, 10, 510}, - dictWord{136, 11, 80}, - dictWord{5, 0, 927}, - dictWord{7, 0, 101}, - dictWord{4, 10, 291}, - dictWord{7, 11, 381}, - dictWord{7, 11, 806}, - dictWord{7, 11, 820}, - dictWord{8, 11, 354}, - dictWord{8, 11, 437}, - dictWord{8, 11, 787}, - dictWord{9, 10, 515}, - dictWord{9, 11, 657}, - dictWord{10, 11, 58}, - dictWord{10, 11, 339}, - dictWord{10, 11, 749}, - dictWord{11, 11, 914}, - dictWord{12, 10, 152}, - dictWord{12, 11, 162}, - dictWord{12, 10, 443}, - dictWord{13, 11, 75}, - dictWord{13, 10, 392}, - dictWord{14, 11, 106}, - dictWord{14, 11, 198}, - dictWord{ - 14, - 11, - 320, - }, - dictWord{14, 10, 357}, - dictWord{14, 11, 413}, - dictWord{146, 11, 43}, - dictWord{6, 0, 1153}, - dictWord{7, 0, 1441}, - dictWord{136, 11, 747}, - dictWord{ - 4, - 0, - 893, - }, - dictWord{5, 0, 780}, - dictWord{133, 0, 893}, - dictWord{138, 11, 654}, - dictWord{133, 11, 692}, - dictWord{133, 0, 238}, - dictWord{134, 11, 191}, - dictWord{4, 10, 130}, - dictWord{135, 10, 843}, - dictWord{6, 0, 1296}, - dictWord{5, 10, 42}, - dictWord{5, 10, 879}, - dictWord{7, 10, 245}, - dictWord{7, 10, 324}, - dictWord{ - 7, - 10, - 1532, - }, - dictWord{11, 10, 463}, - dictWord{11, 10, 472}, - dictWord{13, 10, 363}, - dictWord{144, 10, 52}, - dictWord{134, 0, 1729}, - dictWord{6, 0, 1999}, - dictWord{136, 0, 969}, - dictWord{4, 10, 134}, - dictWord{133, 10, 372}, - dictWord{4, 0, 60}, - dictWord{7, 0, 941}, - dictWord{7, 0, 1800}, - dictWord{8, 0, 314}, - dictWord{ - 9, - 0, - 700, - }, - dictWord{139, 0, 487}, - dictWord{134, 0, 1144}, - dictWord{6, 11, 162}, - dictWord{7, 11, 1960}, - dictWord{136, 11, 831}, - dictWord{132, 11, 706}, - dictWord{135, 0, 1147}, - dictWord{138, 11, 426}, - dictWord{138, 11, 89}, - dictWord{7, 0, 1853}, - dictWord{138, 0, 437}, - dictWord{136, 0, 419}, - dictWord{ - 135, - 10, - 1634, - }, - dictWord{133, 0, 828}, - dictWord{5, 0, 806}, - dictWord{7, 0, 176}, - dictWord{7, 0, 178}, - dictWord{7, 0, 1240}, - dictWord{7, 0, 1976}, - dictWord{ - 132, - 10, - 644, - }, - dictWord{135, 11, 1877}, - dictWord{5, 11, 420}, - dictWord{135, 11, 1449}, - dictWord{4, 0, 51}, - dictWord{5, 0, 39}, - dictWord{6, 0, 4}, - dictWord{7, 0, 591}, - dictWord{7, 0, 849}, - dictWord{7, 0, 951}, - dictWord{7, 0, 1613}, - dictWord{7, 0, 1760}, - dictWord{7, 0, 1988}, - dictWord{9, 0, 434}, - dictWord{10, 0, 754}, - dictWord{ - 11, - 0, - 25, - }, - dictWord{139, 0, 37}, - dictWord{10, 11, 57}, - dictWord{138, 11, 277}, - dictWord{135, 10, 540}, - dictWord{132, 11, 204}, - dictWord{135, 0, 159}, - dictWord{139, 11, 231}, - dictWord{133, 0, 902}, - dictWord{7, 0, 928}, - dictWord{7, 11, 366}, - dictWord{9, 11, 287}, - dictWord{12, 11, 199}, - dictWord{12, 11, 556}, - dictWord{140, 11, 577}, - dictWord{6, 10, 623}, - dictWord{136, 10, 789}, - dictWord{4, 10, 908}, - dictWord{5, 10, 359}, - dictWord{5, 10, 508}, - dictWord{6, 10, 1723}, - dictWord{7, 10, 343}, - dictWord{7, 10, 1996}, - dictWord{135, 10, 2026}, - dictWord{134, 0, 270}, - dictWord{4, 10, 341}, - dictWord{135, 10, 480}, - dictWord{ - 5, - 11, - 356, - }, - dictWord{135, 11, 224}, - dictWord{11, 11, 588}, - dictWord{11, 11, 864}, - dictWord{11, 11, 968}, - dictWord{143, 11, 160}, - dictWord{132, 0, 556}, - dictWord{137, 0, 801}, - dictWord{132, 0, 416}, - dictWord{142, 0, 372}, - dictWord{5, 0, 152}, - dictWord{5, 0, 197}, - dictWord{7, 0, 340}, - dictWord{7, 0, 867}, - dictWord{ - 10, - 0, - 548, - }, - dictWord{10, 0, 581}, - dictWord{11, 0, 6}, - dictWord{12, 0, 3}, - dictWord{12, 0, 19}, - dictWord{14, 0, 110}, - dictWord{142, 0, 289}, - dictWord{139, 0, 369}, - dictWord{7, 11, 630}, - dictWord{9, 11, 567}, - dictWord{11, 11, 150}, - dictWord{11, 11, 444}, - dictWord{141, 11, 119}, - dictWord{134, 11, 539}, - dictWord{ - 7, - 10, - 1995, - }, - dictWord{8, 10, 299}, - dictWord{11, 10, 890}, - dictWord{140, 10, 674}, - dictWord{7, 0, 34}, - dictWord{7, 0, 190}, - dictWord{8, 0, 28}, - dictWord{8, 0, 141}, - dictWord{8, 0, 444}, - dictWord{8, 0, 811}, - dictWord{9, 0, 468}, - dictWord{11, 0, 334}, - dictWord{12, 0, 24}, - dictWord{12, 0, 386}, - dictWord{140, 0, 576}, - dictWord{ - 133, - 0, - 757, - }, - dictWord{7, 0, 1553}, - dictWord{136, 0, 898}, - dictWord{133, 0, 721}, - dictWord{136, 0, 1012}, - dictWord{4, 0, 789}, - dictWord{5, 0, 647}, - dictWord{ - 135, - 0, - 1102, - }, - dictWord{132, 0, 898}, - dictWord{10, 0, 183}, - dictWord{4, 10, 238}, - dictWord{5, 10, 503}, - dictWord{6, 10, 179}, - dictWord{7, 10, 2003}, - dictWord{ - 8, - 10, - 381, - }, - dictWord{8, 10, 473}, - dictWord{9, 10, 149}, - dictWord{10, 10, 788}, - dictWord{15, 10, 45}, - dictWord{15, 10, 86}, - dictWord{20, 10, 110}, - dictWord{ - 150, - 10, - 57, - }, - dictWord{9, 0, 136}, - dictWord{19, 0, 107}, - dictWord{4, 10, 121}, - dictWord{5, 10, 156}, - dictWord{5, 10, 349}, - dictWord{10, 10, 605}, - dictWord{ - 142, - 10, - 342, - }, - dictWord{4, 11, 235}, - dictWord{135, 11, 255}, - dictWord{4, 11, 194}, - dictWord{5, 11, 584}, - dictWord{6, 11, 384}, - dictWord{7, 11, 583}, - dictWord{ - 10, - 11, - 761, - }, - dictWord{11, 11, 760}, - dictWord{139, 11, 851}, - dictWord{6, 10, 80}, - dictWord{6, 10, 1694}, - dictWord{7, 10, 173}, - dictWord{7, 10, 1974}, - dictWord{ - 9, - 10, - 547, - }, - dictWord{10, 10, 730}, - dictWord{14, 10, 18}, - dictWord{150, 10, 39}, - dictWord{4, 10, 923}, - dictWord{134, 10, 1711}, - dictWord{5, 0, 277}, - dictWord{141, 0, 247}, - dictWord{132, 0, 435}, - dictWord{133, 11, 562}, - dictWord{134, 0, 1311}, - dictWord{5, 11, 191}, - dictWord{137, 11, 271}, - dictWord{ - 132, - 10, - 595, - }, - dictWord{7, 11, 1537}, - dictWord{14, 11, 96}, - dictWord{143, 11, 73}, - dictWord{5, 0, 437}, - dictWord{7, 0, 502}, - dictWord{7, 0, 519}, - dictWord{7, 0, 1122}, - dictWord{7, 0, 1751}, - dictWord{14, 0, 211}, - dictWord{6, 10, 459}, - dictWord{7, 10, 1753}, - dictWord{7, 10, 1805}, - dictWord{8, 10, 658}, - dictWord{9, 10, 1}, - dictWord{11, 10, 959}, - dictWord{141, 10, 446}, - dictWord{6, 0, 814}, - dictWord{4, 11, 470}, - dictWord{5, 11, 473}, - dictWord{6, 11, 153}, - dictWord{7, 11, 1503}, - dictWord{7, 11, 1923}, - dictWord{10, 11, 701}, - dictWord{11, 11, 132}, - dictWord{11, 11, 168}, - dictWord{11, 11, 227}, - dictWord{11, 11, 320}, - dictWord{ - 11, - 11, - 436, - }, - dictWord{11, 11, 525}, - dictWord{11, 11, 855}, - dictWord{12, 11, 41}, - dictWord{12, 11, 286}, - dictWord{13, 11, 103}, - dictWord{13, 11, 284}, - dictWord{ - 14, - 11, - 255, - }, - dictWord{14, 11, 262}, - dictWord{15, 11, 117}, - dictWord{143, 11, 127}, - dictWord{5, 0, 265}, - dictWord{6, 0, 212}, - dictWord{135, 0, 28}, - dictWord{ - 138, - 0, - 750, - }, - dictWord{133, 11, 327}, - dictWord{6, 11, 552}, - dictWord{7, 11, 1754}, - dictWord{137, 11, 604}, - dictWord{134, 0, 2012}, - dictWord{132, 0, 702}, - dictWord{5, 11, 80}, - dictWord{6, 11, 405}, - dictWord{7, 11, 403}, - dictWord{7, 11, 1502}, - dictWord{7, 11, 1626}, - dictWord{8, 11, 456}, - dictWord{9, 11, 487}, - dictWord{9, 11, 853}, - dictWord{9, 11, 889}, - dictWord{10, 11, 309}, - dictWord{11, 11, 721}, - dictWord{11, 11, 994}, - dictWord{12, 11, 430}, - dictWord{ - 141, - 11, - 165, - }, - dictWord{5, 0, 808}, - dictWord{135, 0, 2045}, - dictWord{5, 0, 166}, - dictWord{8, 0, 739}, - dictWord{140, 0, 511}, - dictWord{134, 10, 490}, - dictWord{ - 4, - 11, - 453, - }, - dictWord{5, 11, 887}, - dictWord{6, 11, 535}, - dictWord{8, 11, 6}, - dictWord{136, 11, 543}, - dictWord{4, 0, 119}, - dictWord{5, 0, 170}, - dictWord{5, 0, 447}, - dictWord{7, 0, 1708}, - dictWord{7, 0, 1889}, - dictWord{9, 0, 357}, - dictWord{9, 0, 719}, - dictWord{12, 0, 486}, - dictWord{140, 0, 596}, - dictWord{137, 0, 500}, - dictWord{ - 7, - 10, - 250, - }, - dictWord{136, 10, 507}, - dictWord{132, 10, 158}, - dictWord{6, 0, 809}, - dictWord{134, 0, 1500}, - dictWord{9, 0, 327}, - dictWord{11, 0, 350}, - dictWord{11, 0, 831}, - dictWord{13, 0, 352}, - dictWord{4, 10, 140}, - dictWord{7, 10, 362}, - dictWord{8, 10, 209}, - dictWord{9, 10, 10}, - dictWord{9, 10, 503}, - dictWord{ - 9, - 10, - 614, - }, - dictWord{10, 10, 689}, - dictWord{11, 10, 327}, - dictWord{11, 10, 725}, - dictWord{12, 10, 252}, - dictWord{12, 10, 583}, - dictWord{13, 10, 192}, - dictWord{14, 10, 269}, - dictWord{14, 10, 356}, - dictWord{148, 10, 50}, - dictWord{135, 11, 741}, - dictWord{4, 0, 450}, - dictWord{7, 0, 1158}, - dictWord{19, 10, 1}, - dictWord{19, 10, 26}, - dictWord{150, 10, 9}, - dictWord{6, 0, 597}, - dictWord{135, 0, 1318}, - dictWord{134, 0, 1602}, - dictWord{6, 10, 228}, - dictWord{7, 10, 1341}, - dictWord{9, 10, 408}, - dictWord{138, 10, 343}, - dictWord{7, 0, 1375}, - dictWord{7, 0, 1466}, - dictWord{138, 0, 331}, - dictWord{132, 0, 754}, - dictWord{ - 132, - 10, - 557, - }, - dictWord{5, 11, 101}, - dictWord{6, 11, 88}, - dictWord{6, 11, 543}, - dictWord{7, 11, 1677}, - dictWord{9, 11, 100}, - dictWord{10, 11, 677}, - dictWord{ - 14, - 11, - 169, - }, - dictWord{14, 11, 302}, - dictWord{14, 11, 313}, - dictWord{15, 11, 48}, - dictWord{143, 11, 84}, - dictWord{134, 0, 1368}, - dictWord{4, 11, 310}, - dictWord{ - 9, - 11, - 795, - }, - dictWord{10, 11, 733}, - dictWord{11, 11, 451}, - dictWord{12, 11, 249}, - dictWord{14, 11, 115}, - dictWord{14, 11, 286}, - dictWord{143, 11, 100}, - dictWord{132, 10, 548}, - dictWord{10, 0, 557}, - dictWord{7, 10, 197}, - dictWord{8, 10, 142}, - dictWord{8, 10, 325}, - dictWord{9, 10, 150}, - dictWord{9, 10, 596}, - dictWord{10, 10, 353}, - dictWord{11, 10, 74}, - dictWord{11, 10, 315}, - dictWord{12, 10, 662}, - dictWord{12, 10, 681}, - dictWord{14, 10, 423}, - dictWord{ - 143, - 10, - 141, - }, - dictWord{133, 11, 587}, - dictWord{5, 0, 850}, - dictWord{136, 0, 799}, - dictWord{10, 0, 908}, - dictWord{12, 0, 701}, - dictWord{12, 0, 757}, - dictWord{ - 142, - 0, - 466, - }, - dictWord{4, 0, 62}, - dictWord{5, 0, 275}, - dictWord{18, 0, 19}, - dictWord{6, 10, 399}, - dictWord{6, 10, 579}, - dictWord{7, 10, 692}, - dictWord{7, 10, 846}, - dictWord{ - 7, - 10, - 1015, - }, - dictWord{7, 10, 1799}, - dictWord{8, 10, 403}, - dictWord{9, 10, 394}, - dictWord{10, 10, 133}, - dictWord{12, 10, 4}, - dictWord{12, 10, 297}, - dictWord{12, 10, 452}, - dictWord{16, 10, 81}, - dictWord{18, 10, 25}, - dictWord{21, 10, 14}, - dictWord{22, 10, 12}, - dictWord{151, 10, 18}, - dictWord{12, 0, 459}, - dictWord{ - 7, - 10, - 1546, - }, - dictWord{11, 10, 299}, - dictWord{142, 10, 407}, - dictWord{132, 10, 177}, - dictWord{132, 11, 498}, - dictWord{7, 11, 217}, - dictWord{ - 8, - 11, - 140, - }, - dictWord{138, 11, 610}, - dictWord{5, 10, 411}, - dictWord{135, 10, 653}, - dictWord{134, 0, 1802}, - dictWord{7, 10, 439}, - dictWord{10, 10, 727}, - dictWord{11, 10, 260}, - dictWord{139, 10, 684}, - dictWord{133, 11, 905}, - dictWord{11, 11, 580}, - dictWord{142, 11, 201}, - dictWord{134, 0, 1397}, - dictWord{ - 5, - 10, - 208, - }, - dictWord{7, 10, 753}, - dictWord{135, 10, 1528}, - dictWord{7, 0, 238}, - dictWord{7, 0, 2033}, - dictWord{8, 0, 120}, - dictWord{8, 0, 188}, - dictWord{8, 0, 659}, - dictWord{9, 0, 598}, - dictWord{10, 0, 466}, - dictWord{12, 0, 342}, - dictWord{12, 0, 588}, - dictWord{13, 0, 503}, - dictWord{14, 0, 246}, - dictWord{143, 0, 92}, - dictWord{135, 11, 1041}, - dictWord{4, 11, 456}, - dictWord{7, 11, 105}, - dictWord{7, 11, 358}, - dictWord{7, 11, 1637}, - dictWord{8, 11, 643}, - dictWord{139, 11, 483}, - dictWord{6, 0, 1318}, - dictWord{134, 0, 1324}, - dictWord{4, 0, 201}, - dictWord{7, 0, 1744}, - dictWord{8, 0, 602}, - dictWord{11, 0, 247}, - dictWord{11, 0, 826}, - dictWord{17, 0, 65}, - dictWord{133, 10, 242}, - dictWord{8, 0, 164}, - dictWord{146, 0, 62}, - dictWord{133, 10, 953}, - dictWord{139, 10, 802}, - dictWord{133, 0, 615}, - dictWord{7, 11, 1566}, - dictWord{8, 11, 269}, - dictWord{9, 11, 212}, - dictWord{9, 11, 718}, - dictWord{14, 11, 15}, - dictWord{14, 11, 132}, - dictWord{142, 11, 227}, - dictWord{133, 10, 290}, - dictWord{132, 10, 380}, - dictWord{5, 10, 52}, - dictWord{7, 10, 277}, - dictWord{9, 10, 368}, - dictWord{139, 10, 791}, - dictWord{ - 135, - 0, - 1243, - }, - dictWord{133, 11, 539}, - dictWord{11, 11, 919}, - dictWord{141, 11, 409}, - dictWord{136, 0, 968}, - dictWord{133, 11, 470}, - dictWord{134, 0, 882}, - dictWord{132, 0, 907}, - dictWord{5, 0, 100}, - dictWord{10, 0, 329}, - dictWord{12, 0, 416}, - dictWord{149, 0, 29}, - dictWord{10, 10, 138}, - dictWord{139, 10, 476}, - dictWord{5, 10, 725}, - dictWord{5, 10, 727}, - dictWord{6, 11, 91}, - dictWord{7, 11, 435}, - dictWord{135, 10, 1811}, - dictWord{4, 11, 16}, - dictWord{5, 11, 316}, - dictWord{5, 11, 842}, - dictWord{6, 11, 370}, - dictWord{6, 11, 1778}, - dictWord{8, 11, 166}, - dictWord{11, 11, 812}, - dictWord{12, 11, 206}, - dictWord{12, 11, 351}, - dictWord{14, 11, 418}, - dictWord{16, 11, 15}, - dictWord{16, 11, 34}, - dictWord{18, 11, 3}, - dictWord{19, 11, 3}, - dictWord{19, 11, 7}, - dictWord{20, 11, 4}, - dictWord{ - 149, - 11, - 21, - }, - dictWord{132, 0, 176}, - dictWord{5, 0, 636}, - dictWord{5, 0, 998}, - dictWord{7, 0, 9}, - dictWord{7, 0, 1508}, - dictWord{8, 0, 26}, - dictWord{9, 0, 317}, - dictWord{ - 9, - 0, - 358, - }, - dictWord{10, 0, 210}, - dictWord{10, 0, 292}, - dictWord{10, 0, 533}, - dictWord{11, 0, 555}, - dictWord{12, 0, 526}, - dictWord{12, 0, 607}, - dictWord{ - 13, - 0, - 263, - }, - dictWord{13, 0, 459}, - dictWord{142, 0, 271}, - dictWord{6, 0, 256}, - dictWord{8, 0, 265}, - dictWord{4, 10, 38}, - dictWord{7, 10, 307}, - dictWord{7, 10, 999}, - dictWord{7, 10, 1481}, - dictWord{7, 10, 1732}, - dictWord{7, 10, 1738}, - dictWord{9, 10, 414}, - dictWord{11, 10, 316}, - dictWord{12, 10, 52}, - dictWord{13, 10, 420}, - dictWord{147, 10, 100}, - dictWord{135, 10, 1296}, - dictWord{4, 11, 611}, - dictWord{133, 11, 606}, - dictWord{4, 0, 643}, - dictWord{142, 11, 21}, - dictWord{ - 133, - 11, - 715, - }, - dictWord{133, 10, 723}, - dictWord{6, 0, 610}, - dictWord{135, 11, 597}, - dictWord{10, 0, 127}, - dictWord{141, 0, 27}, - dictWord{6, 0, 1995}, - dictWord{ - 6, - 0, - 2001, - }, - dictWord{8, 0, 119}, - dictWord{136, 0, 973}, - dictWord{4, 11, 149}, - dictWord{138, 11, 368}, - dictWord{12, 0, 522}, - dictWord{4, 11, 154}, - dictWord{ - 5, - 10, - 109, - }, - dictWord{6, 10, 1784}, - dictWord{7, 11, 1134}, - dictWord{7, 10, 1895}, - dictWord{8, 11, 105}, - dictWord{12, 10, 296}, - dictWord{140, 10, 302}, - dictWord{4, 11, 31}, - dictWord{6, 11, 429}, - dictWord{7, 11, 962}, - dictWord{9, 11, 458}, - dictWord{139, 11, 691}, - dictWord{10, 0, 553}, - dictWord{11, 0, 876}, - dictWord{13, 0, 193}, - dictWord{13, 0, 423}, - dictWord{14, 0, 166}, - dictWord{19, 0, 84}, - dictWord{4, 11, 312}, - dictWord{5, 10, 216}, - dictWord{7, 10, 1879}, - dictWord{ - 9, - 10, - 141, - }, - dictWord{9, 10, 270}, - dictWord{9, 10, 679}, - dictWord{10, 10, 159}, - dictWord{11, 10, 197}, - dictWord{12, 10, 538}, - dictWord{12, 10, 559}, - dictWord{14, 10, 144}, - dictWord{14, 10, 167}, - dictWord{143, 10, 67}, - dictWord{134, 0, 1582}, - dictWord{7, 0, 1578}, - dictWord{135, 11, 1578}, - dictWord{ - 137, - 10, - 81, - }, - dictWord{132, 11, 236}, - dictWord{134, 10, 391}, - dictWord{134, 0, 795}, - dictWord{7, 10, 322}, - dictWord{136, 10, 249}, - dictWord{5, 11, 836}, - dictWord{ - 5, - 11, - 857, - }, - dictWord{6, 11, 1680}, - dictWord{7, 11, 59}, - dictWord{147, 11, 53}, - dictWord{135, 0, 432}, - dictWord{10, 11, 68}, - dictWord{139, 11, 494}, - dictWord{4, 11, 81}, - dictWord{139, 11, 867}, - dictWord{7, 0, 126}, - dictWord{136, 0, 84}, - dictWord{142, 11, 280}, - dictWord{5, 11, 282}, - dictWord{8, 11, 650}, - dictWord{ - 9, - 11, - 295, - }, - dictWord{9, 11, 907}, - dictWord{138, 11, 443}, - dictWord{136, 0, 790}, - dictWord{5, 10, 632}, - dictWord{138, 10, 526}, - dictWord{6, 0, 64}, - dictWord{12, 0, 377}, - dictWord{13, 0, 309}, - dictWord{14, 0, 141}, - dictWord{14, 0, 429}, - dictWord{14, 11, 141}, - dictWord{142, 11, 429}, - dictWord{134, 0, 1529}, - dictWord{6, 0, 321}, - dictWord{7, 0, 1857}, - dictWord{9, 0, 530}, - dictWord{19, 0, 99}, - dictWord{7, 10, 948}, - dictWord{7, 10, 1042}, - dictWord{8, 10, 235}, - dictWord{ - 8, - 10, - 461, - }, - dictWord{9, 10, 453}, - dictWord{10, 10, 354}, - dictWord{145, 10, 77}, - dictWord{7, 0, 1104}, - dictWord{11, 0, 269}, - dictWord{11, 0, 539}, - dictWord{ - 11, - 0, - 627, - }, - dictWord{11, 0, 706}, - dictWord{11, 0, 975}, - dictWord{12, 0, 248}, - dictWord{12, 0, 434}, - dictWord{12, 0, 600}, - dictWord{12, 0, 622}, - dictWord{ - 13, - 0, - 297, - }, - dictWord{13, 0, 485}, - dictWord{14, 0, 69}, - dictWord{14, 0, 409}, - dictWord{143, 0, 108}, - dictWord{4, 10, 362}, - dictWord{7, 10, 52}, - dictWord{7, 10, 303}, - dictWord{10, 11, 70}, - dictWord{12, 11, 26}, - dictWord{14, 11, 17}, - dictWord{14, 11, 178}, - dictWord{15, 11, 34}, - dictWord{149, 11, 12}, - dictWord{11, 0, 977}, - dictWord{141, 0, 507}, - dictWord{9, 0, 34}, - dictWord{139, 0, 484}, - dictWord{5, 10, 196}, - dictWord{6, 10, 486}, - dictWord{7, 10, 212}, - dictWord{8, 10, 309}, - dictWord{136, 10, 346}, - dictWord{6, 0, 1700}, - dictWord{7, 0, 26}, - dictWord{7, 0, 293}, - dictWord{7, 0, 382}, - dictWord{7, 0, 1026}, - dictWord{7, 0, 1087}, - dictWord{ - 7, - 0, - 2027, - }, - dictWord{8, 0, 24}, - dictWord{8, 0, 114}, - dictWord{8, 0, 252}, - dictWord{8, 0, 727}, - dictWord{8, 0, 729}, - dictWord{9, 0, 30}, - dictWord{9, 0, 199}, - dictWord{ - 9, - 0, - 231, - }, - dictWord{9, 0, 251}, - dictWord{9, 0, 334}, - dictWord{9, 0, 361}, - dictWord{9, 0, 712}, - dictWord{10, 0, 55}, - dictWord{10, 0, 60}, - dictWord{10, 0, 232}, - dictWord{ - 10, - 0, - 332, - }, - dictWord{10, 0, 384}, - dictWord{10, 0, 396}, - dictWord{10, 0, 504}, - dictWord{10, 0, 542}, - dictWord{10, 0, 652}, - dictWord{11, 0, 20}, - dictWord{11, 0, 48}, - dictWord{11, 0, 207}, - dictWord{11, 0, 291}, - dictWord{11, 0, 298}, - dictWord{11, 0, 342}, - dictWord{11, 0, 365}, - dictWord{11, 0, 394}, - dictWord{11, 0, 620}, - dictWord{11, 0, 705}, - dictWord{11, 0, 1017}, - dictWord{12, 0, 123}, - dictWord{12, 0, 340}, - dictWord{12, 0, 406}, - dictWord{12, 0, 643}, - dictWord{13, 0, 61}, - dictWord{ - 13, - 0, - 269, - }, - dictWord{13, 0, 311}, - dictWord{13, 0, 319}, - dictWord{13, 0, 486}, - dictWord{14, 0, 234}, - dictWord{15, 0, 62}, - dictWord{15, 0, 85}, - dictWord{16, 0, 71}, - dictWord{18, 0, 119}, - dictWord{20, 0, 105}, - dictWord{135, 10, 1912}, - dictWord{4, 11, 71}, - dictWord{5, 11, 376}, - dictWord{7, 11, 119}, - dictWord{138, 11, 665}, - dictWord{10, 0, 918}, - dictWord{10, 0, 926}, - dictWord{4, 10, 686}, - dictWord{136, 11, 55}, - dictWord{138, 10, 625}, - dictWord{136, 10, 706}, - dictWord{ - 132, - 11, - 479, - }, - dictWord{4, 10, 30}, - dictWord{133, 10, 43}, - dictWord{6, 0, 379}, - dictWord{7, 0, 270}, - dictWord{8, 0, 176}, - dictWord{8, 0, 183}, - dictWord{9, 0, 432}, - dictWord{ - 9, - 0, - 661, - }, - dictWord{12, 0, 247}, - dictWord{12, 0, 617}, - dictWord{18, 0, 125}, - dictWord{7, 11, 607}, - dictWord{8, 11, 99}, - dictWord{152, 11, 4}, - dictWord{ - 5, - 0, - 792, - }, - dictWord{133, 0, 900}, - dictWord{4, 11, 612}, - dictWord{133, 11, 561}, - dictWord{4, 11, 41}, - dictWord{4, 10, 220}, - dictWord{5, 11, 74}, - dictWord{ - 7, - 10, - 1535, - }, - dictWord{7, 11, 1627}, - dictWord{11, 11, 871}, - dictWord{140, 11, 619}, - dictWord{135, 0, 1920}, - dictWord{7, 11, 94}, - dictWord{11, 11, 329}, - dictWord{11, 11, 965}, - dictWord{12, 11, 241}, - dictWord{14, 11, 354}, - dictWord{15, 11, 22}, - dictWord{148, 11, 63}, - dictWord{9, 11, 209}, - dictWord{137, 11, 300}, - dictWord{134, 0, 771}, - dictWord{135, 0, 1979}, - dictWord{4, 0, 901}, - dictWord{133, 0, 776}, - dictWord{142, 0, 254}, - dictWord{133, 11, 98}, - dictWord{ - 9, - 11, - 16, - }, - dictWord{141, 11, 386}, - dictWord{133, 11, 984}, - dictWord{4, 11, 182}, - dictWord{6, 11, 205}, - dictWord{135, 11, 220}, - dictWord{7, 10, 1725}, - dictWord{ - 7, - 10, - 1774, - }, - dictWord{138, 10, 393}, - dictWord{5, 10, 263}, - dictWord{134, 10, 414}, - dictWord{4, 11, 42}, - dictWord{9, 11, 205}, - dictWord{9, 11, 786}, - dictWord{138, 11, 659}, - dictWord{14, 0, 140}, - dictWord{148, 0, 41}, - dictWord{8, 0, 440}, - dictWord{10, 0, 359}, - dictWord{6, 10, 178}, - dictWord{6, 11, 289}, - dictWord{ - 6, - 10, - 1750, - }, - dictWord{7, 11, 1670}, - dictWord{9, 10, 690}, - dictWord{10, 10, 155}, - dictWord{10, 10, 373}, - dictWord{11, 10, 698}, - dictWord{12, 11, 57}, - dictWord{13, 10, 155}, - dictWord{20, 10, 93}, - dictWord{151, 11, 4}, - dictWord{4, 0, 37}, - dictWord{5, 0, 334}, - dictWord{7, 0, 1253}, - dictWord{151, 11, 25}, - dictWord{ - 4, - 0, - 508, - }, - dictWord{4, 11, 635}, - dictWord{5, 10, 97}, - dictWord{137, 10, 393}, - dictWord{139, 11, 533}, - dictWord{4, 0, 640}, - dictWord{133, 0, 513}, - dictWord{ - 134, - 10, - 1639, - }, - dictWord{132, 11, 371}, - dictWord{4, 11, 272}, - dictWord{7, 11, 836}, - dictWord{7, 11, 1651}, - dictWord{145, 11, 89}, - dictWord{5, 11, 825}, - dictWord{6, 11, 444}, - dictWord{6, 11, 1640}, - dictWord{136, 11, 308}, - dictWord{4, 10, 191}, - dictWord{7, 10, 934}, - dictWord{8, 10, 647}, - dictWord{145, 10, 97}, - dictWord{12, 0, 246}, - dictWord{15, 0, 162}, - dictWord{19, 0, 64}, - dictWord{20, 0, 8}, - dictWord{20, 0, 95}, - dictWord{22, 0, 24}, - dictWord{152, 0, 17}, - dictWord{4, 0, 533}, - dictWord{5, 10, 165}, - dictWord{9, 10, 346}, - dictWord{138, 10, 655}, - dictWord{5, 11, 737}, - dictWord{139, 10, 885}, - dictWord{133, 10, 877}, - dictWord{ - 8, - 10, - 128, - }, - dictWord{139, 10, 179}, - dictWord{137, 11, 307}, - dictWord{140, 0, 752}, - dictWord{133, 0, 920}, - dictWord{135, 0, 1048}, - dictWord{5, 0, 153}, - dictWord{ - 6, - 0, - 580, - }, - dictWord{6, 10, 1663}, - dictWord{7, 10, 132}, - dictWord{7, 10, 1154}, - dictWord{7, 10, 1415}, - dictWord{7, 10, 1507}, - dictWord{12, 10, 493}, - dictWord{15, 10, 105}, - dictWord{151, 10, 15}, - dictWord{5, 10, 459}, - dictWord{7, 10, 1073}, - dictWord{8, 10, 241}, - dictWord{136, 10, 334}, - dictWord{138, 0, 391}, - dictWord{135, 0, 1952}, - dictWord{133, 11, 525}, - dictWord{8, 11, 641}, - dictWord{11, 11, 388}, - dictWord{140, 11, 580}, - dictWord{142, 0, 126}, - dictWord{ - 134, - 0, - 640, - }, - dictWord{132, 0, 483}, - dictWord{7, 0, 1616}, - dictWord{9, 0, 69}, - dictWord{6, 10, 324}, - dictWord{6, 10, 520}, - dictWord{7, 10, 338}, - dictWord{ - 7, - 10, - 1729, - }, - dictWord{8, 10, 228}, - dictWord{139, 10, 750}, - dictWord{5, 11, 493}, - dictWord{134, 11, 528}, - dictWord{135, 0, 734}, - dictWord{4, 11, 174}, - dictWord{135, 11, 911}, - dictWord{138, 0, 480}, - dictWord{9, 0, 495}, - dictWord{146, 0, 104}, - dictWord{135, 10, 705}, - dictWord{9, 0, 472}, - dictWord{4, 10, 73}, - dictWord{6, 10, 612}, - dictWord{7, 10, 927}, - dictWord{7, 10, 1330}, - dictWord{7, 10, 1822}, - dictWord{8, 10, 217}, - dictWord{9, 10, 765}, - dictWord{9, 10, 766}, - dictWord{10, 10, 408}, - dictWord{11, 10, 51}, - dictWord{11, 10, 793}, - dictWord{12, 10, 266}, - dictWord{15, 10, 158}, - dictWord{20, 10, 89}, - dictWord{150, 10, 32}, - dictWord{7, 11, 548}, - dictWord{137, 11, 58}, - dictWord{4, 11, 32}, - dictWord{5, 11, 215}, - dictWord{6, 11, 269}, - dictWord{7, 11, 1782}, - dictWord{7, 11, 1892}, - dictWord{10, 11, 16}, - dictWord{11, 11, 822}, - dictWord{11, 11, 954}, - dictWord{141, 11, 481}, - dictWord{132, 0, 874}, - dictWord{9, 0, 229}, - dictWord{5, 10, 389}, - dictWord{136, 10, 636}, - dictWord{7, 11, 1749}, - dictWord{136, 11, 477}, - dictWord{134, 0, 948}, - dictWord{5, 11, 308}, - dictWord{135, 11, 1088}, - dictWord{ - 4, - 0, - 748, - }, - dictWord{139, 0, 1009}, - dictWord{136, 10, 21}, - dictWord{6, 0, 555}, - dictWord{135, 0, 485}, - dictWord{5, 11, 126}, - dictWord{8, 11, 297}, - dictWord{ - 9, - 11, - 366, - }, - dictWord{9, 11, 445}, - dictWord{12, 11, 53}, - dictWord{12, 11, 374}, - dictWord{141, 11, 492}, - dictWord{7, 11, 1551}, - dictWord{139, 11, 361}, - dictWord{136, 0, 193}, - dictWord{136, 0, 472}, - dictWord{8, 0, 653}, - dictWord{13, 0, 93}, - dictWord{147, 0, 14}, - dictWord{132, 0, 984}, - dictWord{132, 11, 175}, - dictWord{5, 0, 172}, - dictWord{6, 0, 1971}, - dictWord{132, 11, 685}, - dictWord{149, 11, 8}, - dictWord{133, 11, 797}, - dictWord{13, 0, 83}, - dictWord{5, 10, 189}, - dictWord{ - 7, - 10, - 442, - }, - dictWord{7, 10, 443}, - dictWord{8, 10, 281}, - dictWord{12, 10, 174}, - dictWord{141, 10, 261}, - dictWord{134, 0, 1568}, - dictWord{133, 11, 565}, - dictWord{139, 0, 384}, - dictWord{133, 0, 260}, - dictWord{7, 0, 758}, - dictWord{7, 0, 880}, - dictWord{7, 0, 1359}, - dictWord{9, 0, 164}, - dictWord{9, 0, 167}, - dictWord{ - 10, - 0, - 156, - }, - dictWord{10, 0, 588}, - dictWord{12, 0, 101}, - dictWord{14, 0, 48}, - dictWord{15, 0, 70}, - dictWord{6, 10, 2}, - dictWord{7, 10, 1262}, - dictWord{ - 7, - 10, - 1737, - }, - dictWord{8, 10, 22}, - dictWord{8, 10, 270}, - dictWord{8, 10, 612}, - dictWord{9, 10, 312}, - dictWord{9, 10, 436}, - dictWord{10, 10, 311}, - dictWord{ - 10, - 10, - 623, - }, - dictWord{11, 10, 72}, - dictWord{11, 10, 330}, - dictWord{11, 10, 455}, - dictWord{12, 10, 321}, - dictWord{12, 10, 504}, - dictWord{12, 10, 530}, - dictWord{ - 12, - 10, - 543, - }, - dictWord{13, 10, 17}, - dictWord{13, 10, 156}, - dictWord{13, 10, 334}, - dictWord{17, 10, 60}, - dictWord{148, 10, 64}, - dictWord{4, 11, 252}, - dictWord{ - 7, - 11, - 1068, - }, - dictWord{10, 11, 434}, - dictWord{11, 11, 228}, - dictWord{11, 11, 426}, - dictWord{13, 11, 231}, - dictWord{18, 11, 106}, - dictWord{148, 11, 87}, - dictWord{7, 10, 354}, - dictWord{10, 10, 410}, - dictWord{139, 10, 815}, - dictWord{6, 0, 367}, - dictWord{7, 10, 670}, - dictWord{7, 10, 1327}, - dictWord{8, 10, 411}, - dictWord{8, 10, 435}, - dictWord{9, 10, 653}, - dictWord{9, 10, 740}, - dictWord{10, 10, 385}, - dictWord{11, 10, 222}, - dictWord{11, 10, 324}, - dictWord{11, 10, 829}, - dictWord{140, 10, 611}, - dictWord{7, 0, 1174}, - dictWord{6, 10, 166}, - dictWord{135, 10, 374}, - dictWord{146, 0, 121}, - dictWord{132, 0, 828}, - dictWord{ - 5, - 11, - 231, - }, - dictWord{138, 11, 509}, - dictWord{7, 11, 601}, - dictWord{9, 11, 277}, - dictWord{9, 11, 674}, - dictWord{10, 11, 178}, - dictWord{10, 11, 257}, - dictWord{ - 10, - 11, - 418, - }, - dictWord{11, 11, 531}, - dictWord{11, 11, 544}, - dictWord{11, 11, 585}, - dictWord{12, 11, 113}, - dictWord{12, 11, 475}, - dictWord{13, 11, 99}, - dictWord{142, 11, 428}, - dictWord{134, 0, 1541}, - dictWord{135, 11, 1779}, - dictWord{5, 0, 343}, - dictWord{134, 10, 398}, - dictWord{135, 10, 50}, - dictWord{ - 135, - 11, - 1683, - }, - dictWord{4, 0, 440}, - dictWord{7, 0, 57}, - dictWord{8, 0, 167}, - dictWord{8, 0, 375}, - dictWord{9, 0, 82}, - dictWord{9, 0, 561}, - dictWord{9, 0, 744}, - dictWord{ - 10, - 0, - 620, - }, - dictWord{137, 11, 744}, - dictWord{134, 0, 926}, - dictWord{6, 10, 517}, - dictWord{7, 10, 1159}, - dictWord{10, 10, 621}, - dictWord{139, 10, 192}, - dictWord{137, 0, 827}, - dictWord{8, 0, 194}, - dictWord{136, 0, 756}, - dictWord{10, 10, 223}, - dictWord{139, 10, 645}, - dictWord{7, 10, 64}, - dictWord{ - 136, - 10, - 245, - }, - dictWord{4, 11, 399}, - dictWord{5, 11, 119}, - dictWord{5, 11, 494}, - dictWord{7, 11, 751}, - dictWord{137, 11, 556}, - dictWord{132, 0, 808}, - dictWord{ - 135, - 0, - 22, - }, - dictWord{7, 10, 1763}, - dictWord{140, 10, 310}, - dictWord{5, 0, 639}, - dictWord{7, 0, 1249}, - dictWord{11, 0, 896}, - dictWord{134, 11, 584}, - dictWord{ - 134, - 0, - 1614, - }, - dictWord{135, 0, 860}, - dictWord{135, 11, 1121}, - dictWord{5, 10, 129}, - dictWord{6, 10, 61}, - dictWord{135, 10, 947}, - dictWord{4, 0, 102}, - dictWord{ - 7, - 0, - 815, - }, - dictWord{7, 0, 1699}, - dictWord{139, 0, 964}, - dictWord{13, 10, 505}, - dictWord{141, 10, 506}, - dictWord{139, 10, 1000}, - dictWord{ - 132, - 11, - 679, - }, - dictWord{132, 0, 899}, - dictWord{132, 0, 569}, - dictWord{5, 11, 694}, - dictWord{137, 11, 714}, - dictWord{136, 0, 795}, - dictWord{6, 0, 2045}, - dictWord{ - 139, - 11, - 7, - }, - dictWord{6, 0, 52}, - dictWord{9, 0, 104}, - dictWord{9, 0, 559}, - dictWord{12, 0, 308}, - dictWord{147, 0, 87}, - dictWord{4, 0, 301}, - dictWord{132, 0, 604}, - dictWord{133, 10, 637}, - dictWord{136, 0, 779}, - dictWord{5, 11, 143}, - dictWord{5, 11, 769}, - dictWord{6, 11, 1760}, - dictWord{7, 11, 682}, - dictWord{7, 11, 1992}, - dictWord{136, 11, 736}, - dictWord{137, 10, 590}, - dictWord{147, 0, 32}, - dictWord{137, 11, 527}, - dictWord{5, 10, 280}, - dictWord{135, 10, 1226}, - dictWord{134, 0, 494}, - dictWord{6, 0, 677}, - dictWord{6, 0, 682}, - dictWord{134, 0, 1044}, - dictWord{133, 10, 281}, - dictWord{135, 10, 1064}, - dictWord{7, 0, 508}, - dictWord{133, 11, 860}, - dictWord{6, 11, 422}, - dictWord{7, 11, 0}, - dictWord{7, 11, 1544}, - dictWord{9, 11, 577}, - dictWord{11, 11, 990}, - dictWord{12, 11, 141}, - dictWord{12, 11, 453}, - dictWord{13, 11, 47}, - dictWord{141, 11, 266}, - dictWord{134, 0, 1014}, - dictWord{5, 11, 515}, - dictWord{137, 11, 131}, - dictWord{ - 134, - 0, - 957, - }, - dictWord{132, 11, 646}, - dictWord{6, 0, 310}, - dictWord{7, 0, 1849}, - dictWord{8, 0, 72}, - dictWord{8, 0, 272}, - dictWord{8, 0, 431}, - dictWord{9, 0, 12}, - dictWord{ - 9, - 0, - 376, - }, - dictWord{10, 0, 563}, - dictWord{10, 0, 630}, - dictWord{10, 0, 796}, - dictWord{10, 0, 810}, - dictWord{11, 0, 367}, - dictWord{11, 0, 599}, - dictWord{ - 11, - 0, - 686, - }, - dictWord{140, 0, 672}, - dictWord{7, 0, 570}, - dictWord{4, 11, 396}, - dictWord{7, 10, 120}, - dictWord{7, 11, 728}, - dictWord{8, 10, 489}, - dictWord{9, 11, 117}, - dictWord{9, 10, 319}, - dictWord{10, 10, 820}, - dictWord{11, 10, 1004}, - dictWord{12, 10, 379}, - dictWord{12, 10, 679}, - dictWord{13, 10, 117}, - dictWord{ - 13, - 11, - 202, - }, - dictWord{13, 10, 412}, - dictWord{14, 10, 25}, - dictWord{15, 10, 52}, - dictWord{15, 10, 161}, - dictWord{16, 10, 47}, - dictWord{20, 11, 51}, - dictWord{ - 149, - 10, - 2, - }, - dictWord{6, 11, 121}, - dictWord{6, 11, 124}, - dictWord{6, 11, 357}, - dictWord{7, 11, 1138}, - dictWord{7, 11, 1295}, - dictWord{8, 11, 162}, - dictWord{ - 139, - 11, - 655, - }, - dictWord{8, 0, 449}, - dictWord{4, 10, 937}, - dictWord{5, 10, 801}, - dictWord{136, 11, 449}, - dictWord{139, 11, 958}, - dictWord{6, 0, 181}, - dictWord{ - 7, - 0, - 537, - }, - dictWord{8, 0, 64}, - dictWord{9, 0, 127}, - dictWord{10, 0, 496}, - dictWord{12, 0, 510}, - dictWord{141, 0, 384}, - dictWord{138, 11, 253}, - dictWord{4, 0, 244}, - dictWord{135, 0, 233}, - dictWord{133, 11, 237}, - dictWord{132, 10, 365}, - dictWord{6, 0, 1650}, - dictWord{10, 0, 702}, - dictWord{139, 0, 245}, - dictWord{ - 5, - 10, - 7, - }, - dictWord{139, 10, 774}, - dictWord{13, 0, 463}, - dictWord{20, 0, 49}, - dictWord{13, 11, 463}, - dictWord{148, 11, 49}, - dictWord{4, 10, 734}, - dictWord{ - 5, - 10, - 662, - }, - dictWord{134, 10, 430}, - dictWord{4, 10, 746}, - dictWord{135, 10, 1090}, - dictWord{5, 10, 360}, - dictWord{136, 10, 237}, - dictWord{137, 0, 338}, - dictWord{143, 11, 10}, - dictWord{7, 11, 571}, - dictWord{138, 11, 366}, - dictWord{134, 0, 1279}, - dictWord{9, 11, 513}, - dictWord{10, 11, 22}, - dictWord{10, 11, 39}, - dictWord{12, 11, 122}, - dictWord{140, 11, 187}, - dictWord{133, 0, 896}, - dictWord{146, 0, 178}, - dictWord{134, 0, 695}, - dictWord{137, 0, 808}, - dictWord{ - 134, - 11, - 587, - }, - dictWord{7, 11, 107}, - dictWord{7, 11, 838}, - dictWord{8, 11, 550}, - dictWord{138, 11, 401}, - dictWord{7, 0, 1117}, - dictWord{136, 0, 539}, - dictWord{ - 4, - 10, - 277, - }, - dictWord{5, 10, 608}, - dictWord{6, 10, 493}, - dictWord{7, 10, 457}, - dictWord{140, 10, 384}, - dictWord{133, 11, 768}, - dictWord{12, 0, 257}, - dictWord{ - 7, - 10, - 27, - }, - dictWord{135, 10, 316}, - dictWord{140, 0, 1003}, - dictWord{4, 0, 207}, - dictWord{5, 0, 586}, - dictWord{5, 0, 676}, - dictWord{6, 0, 448}, - dictWord{ - 8, - 0, - 244, - }, - dictWord{11, 0, 1}, - dictWord{13, 0, 3}, - dictWord{16, 0, 54}, - dictWord{17, 0, 4}, - dictWord{18, 0, 13}, - dictWord{133, 10, 552}, - dictWord{4, 10, 401}, - dictWord{ - 137, - 10, - 264, - }, - dictWord{5, 0, 516}, - dictWord{7, 0, 1883}, - dictWord{135, 11, 1883}, - dictWord{12, 0, 960}, - dictWord{132, 11, 894}, - dictWord{5, 0, 4}, - dictWord{ - 5, - 0, - 810, - }, - dictWord{6, 0, 13}, - dictWord{6, 0, 538}, - dictWord{6, 0, 1690}, - dictWord{6, 0, 1726}, - dictWord{7, 0, 499}, - dictWord{7, 0, 1819}, - dictWord{8, 0, 148}, - dictWord{ - 8, - 0, - 696, - }, - dictWord{8, 0, 791}, - dictWord{12, 0, 125}, - dictWord{143, 0, 9}, - dictWord{135, 0, 1268}, - dictWord{11, 0, 30}, - dictWord{14, 0, 315}, - dictWord{ - 9, - 10, - 543, - }, - dictWord{10, 10, 524}, - dictWord{12, 10, 524}, - dictWord{16, 10, 18}, - dictWord{20, 10, 26}, - dictWord{148, 10, 65}, - dictWord{6, 0, 748}, - dictWord{ - 4, - 10, - 205, - }, - dictWord{5, 10, 623}, - dictWord{7, 10, 104}, - dictWord{136, 10, 519}, - dictWord{11, 0, 542}, - dictWord{139, 0, 852}, - dictWord{140, 0, 6}, - dictWord{ - 132, - 0, - 848, - }, - dictWord{7, 0, 1385}, - dictWord{11, 0, 582}, - dictWord{11, 0, 650}, - dictWord{11, 0, 901}, - dictWord{11, 0, 949}, - dictWord{12, 0, 232}, - dictWord{12, 0, 236}, - dictWord{13, 0, 413}, - dictWord{13, 0, 501}, - dictWord{18, 0, 116}, - dictWord{7, 10, 579}, - dictWord{9, 10, 41}, - dictWord{9, 10, 244}, - dictWord{9, 10, 669}, - dictWord{10, 10, 5}, - dictWord{11, 10, 861}, - dictWord{11, 10, 951}, - dictWord{139, 10, 980}, - dictWord{4, 0, 945}, - dictWord{6, 0, 1811}, - dictWord{6, 0, 1845}, - dictWord{ - 6, - 0, - 1853, - }, - dictWord{6, 0, 1858}, - dictWord{8, 0, 862}, - dictWord{12, 0, 782}, - dictWord{12, 0, 788}, - dictWord{18, 0, 160}, - dictWord{148, 0, 117}, - dictWord{ - 132, - 10, - 717, - }, - dictWord{4, 0, 925}, - dictWord{5, 0, 803}, - dictWord{8, 0, 698}, - dictWord{138, 0, 828}, - dictWord{134, 0, 1416}, - dictWord{132, 0, 610}, - dictWord{ - 139, - 0, - 992, - }, - dictWord{6, 0, 878}, - dictWord{134, 0, 1477}, - dictWord{135, 0, 1847}, - dictWord{138, 11, 531}, - dictWord{137, 11, 539}, - dictWord{134, 11, 272}, - dictWord{133, 0, 383}, - dictWord{134, 0, 1404}, - dictWord{132, 10, 489}, - dictWord{4, 11, 9}, - dictWord{5, 11, 128}, - dictWord{7, 11, 368}, - dictWord{ - 11, - 11, - 480, - }, - dictWord{148, 11, 3}, - dictWord{136, 0, 986}, - dictWord{9, 0, 660}, - dictWord{138, 0, 347}, - dictWord{135, 10, 892}, - dictWord{136, 11, 682}, - dictWord{ - 7, - 0, - 572, - }, - dictWord{9, 0, 592}, - dictWord{11, 0, 680}, - dictWord{12, 0, 356}, - dictWord{140, 0, 550}, - dictWord{7, 0, 1411}, - dictWord{138, 11, 527}, - dictWord{ - 4, - 11, - 2, - }, - dictWord{7, 11, 545}, - dictWord{135, 11, 894}, - dictWord{137, 10, 473}, - dictWord{11, 0, 64}, - dictWord{7, 11, 481}, - dictWord{7, 10, 819}, - dictWord{9, 10, 26}, - dictWord{9, 10, 392}, - dictWord{9, 11, 792}, - dictWord{10, 10, 152}, - dictWord{10, 10, 226}, - dictWord{12, 10, 276}, - dictWord{12, 10, 426}, - dictWord{ - 12, - 10, - 589, - }, - dictWord{13, 10, 460}, - dictWord{15, 10, 97}, - dictWord{19, 10, 48}, - dictWord{148, 10, 104}, - dictWord{135, 10, 51}, - dictWord{136, 11, 445}, - dictWord{136, 11, 646}, - dictWord{135, 0, 606}, - dictWord{132, 10, 674}, - dictWord{6, 0, 1829}, - dictWord{134, 0, 1830}, - dictWord{132, 10, 770}, - dictWord{ - 5, - 10, - 79, - }, - dictWord{7, 10, 1027}, - dictWord{7, 10, 1477}, - dictWord{139, 10, 52}, - dictWord{5, 11, 530}, - dictWord{142, 11, 113}, - dictWord{134, 10, 1666}, - dictWord{ - 7, - 0, - 748, - }, - dictWord{139, 0, 700}, - dictWord{134, 10, 195}, - dictWord{133, 10, 789}, - dictWord{9, 0, 87}, - dictWord{10, 0, 365}, - dictWord{4, 10, 251}, - dictWord{ - 4, - 10, - 688, - }, - dictWord{7, 10, 513}, - dictWord{135, 10, 1284}, - dictWord{136, 11, 111}, - dictWord{133, 0, 127}, - dictWord{6, 0, 198}, - dictWord{140, 0, 83}, - dictWord{133, 11, 556}, - dictWord{133, 10, 889}, - dictWord{4, 10, 160}, - dictWord{5, 10, 330}, - dictWord{7, 10, 1434}, - dictWord{136, 10, 174}, - dictWord{5, 0, 276}, - dictWord{6, 0, 55}, - dictWord{7, 0, 1369}, - dictWord{138, 0, 864}, - dictWord{8, 11, 16}, - dictWord{140, 11, 568}, - dictWord{6, 0, 1752}, - dictWord{136, 0, 726}, - dictWord{135, 0, 1066}, - dictWord{133, 0, 764}, - dictWord{6, 11, 186}, - dictWord{137, 11, 426}, - dictWord{11, 0, 683}, - dictWord{139, 11, 683}, - dictWord{ - 6, - 0, - 309, - }, - dictWord{7, 0, 331}, - dictWord{138, 0, 550}, - dictWord{133, 10, 374}, - dictWord{6, 0, 1212}, - dictWord{6, 0, 1852}, - dictWord{7, 0, 1062}, - dictWord{ - 8, - 0, - 874, - }, - dictWord{8, 0, 882}, - dictWord{138, 0, 936}, - dictWord{132, 11, 585}, - dictWord{134, 0, 1364}, - dictWord{7, 0, 986}, - dictWord{133, 10, 731}, - dictWord{ - 6, - 0, - 723, - }, - dictWord{6, 0, 1408}, - dictWord{138, 0, 381}, - dictWord{135, 0, 1573}, - dictWord{134, 0, 1025}, - dictWord{4, 10, 626}, - dictWord{5, 10, 642}, - dictWord{ - 6, - 10, - 425, - }, - dictWord{10, 10, 202}, - dictWord{139, 10, 141}, - dictWord{4, 11, 93}, - dictWord{5, 11, 252}, - dictWord{6, 11, 229}, - dictWord{7, 11, 291}, - dictWord{ - 9, - 11, - 550, - }, - dictWord{139, 11, 644}, - dictWord{137, 11, 749}, - dictWord{137, 11, 162}, - dictWord{132, 11, 381}, - dictWord{135, 0, 1559}, - dictWord{ - 6, - 0, - 194, - }, - dictWord{7, 0, 133}, - dictWord{10, 0, 493}, - dictWord{10, 0, 570}, - dictWord{139, 0, 664}, - dictWord{5, 0, 24}, - dictWord{5, 0, 569}, - dictWord{6, 0, 3}, - dictWord{ - 6, - 0, - 119, - }, - dictWord{6, 0, 143}, - dictWord{6, 0, 440}, - dictWord{7, 0, 295}, - dictWord{7, 0, 599}, - dictWord{7, 0, 1686}, - dictWord{7, 0, 1854}, - dictWord{8, 0, 424}, - dictWord{ - 9, - 0, - 43, - }, - dictWord{9, 0, 584}, - dictWord{9, 0, 760}, - dictWord{10, 0, 148}, - dictWord{10, 0, 328}, - dictWord{11, 0, 159}, - dictWord{11, 0, 253}, - dictWord{11, 0, 506}, - dictWord{12, 0, 487}, - dictWord{140, 0, 531}, - dictWord{6, 0, 661}, - dictWord{134, 0, 1517}, - dictWord{136, 10, 835}, - dictWord{151, 10, 17}, - dictWord{5, 0, 14}, - dictWord{5, 0, 892}, - dictWord{6, 0, 283}, - dictWord{7, 0, 234}, - dictWord{136, 0, 537}, - dictWord{139, 0, 541}, - dictWord{4, 0, 126}, - dictWord{8, 0, 635}, - dictWord{ - 147, - 0, - 34, - }, - dictWord{4, 0, 316}, - dictWord{4, 0, 495}, - dictWord{135, 0, 1561}, - dictWord{4, 11, 187}, - dictWord{5, 11, 184}, - dictWord{5, 11, 690}, - dictWord{ - 7, - 11, - 1869, - }, - dictWord{138, 11, 756}, - dictWord{139, 11, 783}, - dictWord{4, 0, 998}, - dictWord{137, 0, 861}, - dictWord{136, 0, 1009}, - dictWord{139, 11, 292}, - dictWord{5, 11, 21}, - dictWord{6, 11, 77}, - dictWord{6, 11, 157}, - dictWord{7, 11, 974}, - dictWord{7, 11, 1301}, - dictWord{7, 11, 1339}, - dictWord{7, 11, 1490}, - dictWord{ - 7, - 11, - 1873, - }, - dictWord{137, 11, 628}, - dictWord{7, 11, 1283}, - dictWord{9, 11, 227}, - dictWord{9, 11, 499}, - dictWord{10, 11, 341}, - dictWord{11, 11, 325}, - dictWord{11, 11, 408}, - dictWord{14, 11, 180}, - dictWord{15, 11, 144}, - dictWord{18, 11, 47}, - dictWord{147, 11, 49}, - dictWord{4, 0, 64}, - dictWord{5, 0, 352}, - dictWord{5, 0, 720}, - dictWord{6, 0, 368}, - dictWord{139, 0, 359}, - dictWord{5, 10, 384}, - dictWord{8, 10, 455}, - dictWord{140, 10, 48}, - dictWord{5, 10, 264}, - dictWord{ - 134, - 10, - 184, - }, - dictWord{7, 0, 1577}, - dictWord{10, 0, 304}, - dictWord{10, 0, 549}, - dictWord{12, 0, 365}, - dictWord{13, 0, 220}, - dictWord{13, 0, 240}, - dictWord{ - 142, - 0, - 33, - }, - dictWord{134, 0, 1107}, - dictWord{134, 0, 929}, - dictWord{135, 0, 1142}, - dictWord{6, 0, 175}, - dictWord{137, 0, 289}, - dictWord{5, 0, 432}, - dictWord{ - 133, - 0, - 913, - }, - dictWord{6, 0, 279}, - dictWord{7, 0, 219}, - dictWord{5, 10, 633}, - dictWord{135, 10, 1323}, - dictWord{7, 0, 785}, - dictWord{7, 10, 359}, - dictWord{ - 8, - 10, - 243, - }, - dictWord{140, 10, 175}, - dictWord{139, 0, 595}, - dictWord{132, 10, 105}, - dictWord{8, 11, 398}, - dictWord{9, 11, 681}, - dictWord{139, 11, 632}, - dictWord{140, 0, 80}, - dictWord{5, 0, 931}, - dictWord{134, 0, 1698}, - dictWord{142, 11, 241}, - dictWord{134, 11, 20}, - dictWord{134, 0, 1323}, - dictWord{11, 0, 526}, - dictWord{11, 0, 939}, - dictWord{141, 0, 290}, - dictWord{5, 0, 774}, - dictWord{6, 0, 780}, - dictWord{6, 0, 1637}, - dictWord{6, 0, 1686}, - dictWord{6, 0, 1751}, - dictWord{ - 8, - 0, - 559, - }, - dictWord{141, 0, 109}, - dictWord{141, 0, 127}, - dictWord{7, 0, 1167}, - dictWord{11, 0, 934}, - dictWord{13, 0, 391}, - dictWord{17, 0, 76}, - dictWord{ - 135, - 11, - 709, - }, - dictWord{135, 0, 963}, - dictWord{6, 0, 260}, - dictWord{135, 0, 1484}, - dictWord{134, 0, 573}, - dictWord{4, 10, 758}, - dictWord{139, 11, 941}, - dictWord{135, 10, 1649}, - dictWord{145, 11, 36}, - dictWord{4, 0, 292}, - dictWord{137, 0, 580}, - dictWord{4, 0, 736}, - dictWord{5, 0, 871}, - dictWord{6, 0, 1689}, - dictWord{135, 0, 1944}, - dictWord{7, 11, 945}, - dictWord{11, 11, 713}, - dictWord{139, 11, 744}, - dictWord{134, 0, 1164}, - dictWord{135, 11, 937}, - dictWord{ - 6, - 0, - 1922, - }, - dictWord{9, 0, 982}, - dictWord{15, 0, 173}, - dictWord{15, 0, 178}, - dictWord{15, 0, 200}, - dictWord{18, 0, 189}, - dictWord{18, 0, 207}, - dictWord{21, 0, 47}, - dictWord{135, 11, 1652}, - dictWord{7, 0, 1695}, - dictWord{139, 10, 128}, - dictWord{6, 0, 63}, - dictWord{135, 0, 920}, - dictWord{133, 0, 793}, - dictWord{ - 143, - 11, - 134, - }, - dictWord{133, 10, 918}, - dictWord{5, 0, 67}, - dictWord{6, 0, 62}, - dictWord{6, 0, 374}, - dictWord{135, 0, 1391}, - dictWord{9, 0, 790}, - dictWord{12, 0, 47}, - dictWord{4, 11, 579}, - dictWord{5, 11, 226}, - dictWord{5, 11, 323}, - dictWord{135, 11, 960}, - dictWord{10, 11, 784}, - dictWord{141, 11, 191}, - dictWord{4, 0, 391}, - dictWord{135, 0, 1169}, - dictWord{137, 0, 443}, - dictWord{13, 11, 232}, - dictWord{146, 11, 35}, - dictWord{132, 10, 340}, - dictWord{132, 0, 271}, - dictWord{ - 137, - 11, - 313, - }, - dictWord{5, 11, 973}, - dictWord{137, 11, 659}, - dictWord{134, 0, 1140}, - dictWord{6, 11, 135}, - dictWord{135, 11, 1176}, - dictWord{4, 0, 253}, - dictWord{5, 0, 544}, - dictWord{7, 0, 300}, - dictWord{137, 0, 340}, - dictWord{7, 0, 897}, - dictWord{5, 10, 985}, - dictWord{7, 10, 509}, - dictWord{145, 10, 96}, - dictWord{ - 138, - 11, - 735, - }, - dictWord{135, 10, 1919}, - dictWord{138, 0, 890}, - dictWord{5, 0, 818}, - dictWord{134, 0, 1122}, - dictWord{5, 0, 53}, - dictWord{5, 0, 541}, - dictWord{ - 6, - 0, - 94, - }, - dictWord{6, 0, 499}, - dictWord{7, 0, 230}, - dictWord{139, 0, 321}, - dictWord{4, 0, 920}, - dictWord{5, 0, 25}, - dictWord{5, 0, 790}, - dictWord{6, 0, 457}, - dictWord{ - 7, - 0, - 853, - }, - dictWord{8, 0, 788}, - dictWord{142, 11, 31}, - dictWord{132, 10, 247}, - dictWord{135, 11, 314}, - dictWord{132, 0, 468}, - dictWord{7, 0, 243}, - dictWord{ - 6, - 10, - 337, - }, - dictWord{7, 10, 494}, - dictWord{8, 10, 27}, - dictWord{8, 10, 599}, - dictWord{138, 10, 153}, - dictWord{4, 10, 184}, - dictWord{5, 10, 390}, - dictWord{ - 7, - 10, - 618, - }, - dictWord{7, 10, 1456}, - dictWord{139, 10, 710}, - dictWord{134, 0, 870}, - dictWord{134, 0, 1238}, - dictWord{134, 0, 1765}, - dictWord{10, 0, 853}, - dictWord{10, 0, 943}, - dictWord{14, 0, 437}, - dictWord{14, 0, 439}, - dictWord{14, 0, 443}, - dictWord{14, 0, 446}, - dictWord{14, 0, 452}, - dictWord{14, 0, 469}, - dictWord{ - 14, - 0, - 471, - }, - dictWord{14, 0, 473}, - dictWord{16, 0, 93}, - dictWord{16, 0, 102}, - dictWord{16, 0, 110}, - dictWord{148, 0, 121}, - dictWord{4, 0, 605}, - dictWord{ - 7, - 0, - 518, - }, - dictWord{7, 0, 1282}, - dictWord{7, 0, 1918}, - dictWord{10, 0, 180}, - dictWord{139, 0, 218}, - dictWord{133, 0, 822}, - dictWord{4, 0, 634}, - dictWord{ - 11, - 0, - 916, - }, - dictWord{142, 0, 419}, - dictWord{6, 11, 281}, - dictWord{7, 11, 6}, - dictWord{8, 11, 282}, - dictWord{8, 11, 480}, - dictWord{8, 11, 499}, - dictWord{9, 11, 198}, - dictWord{10, 11, 143}, - dictWord{10, 11, 169}, - dictWord{10, 11, 211}, - dictWord{10, 11, 417}, - dictWord{10, 11, 574}, - dictWord{11, 11, 147}, - dictWord{ - 11, - 11, - 395, - }, - dictWord{12, 11, 75}, - dictWord{12, 11, 407}, - dictWord{12, 11, 608}, - dictWord{13, 11, 500}, - dictWord{142, 11, 251}, - dictWord{134, 0, 898}, - dictWord{ - 6, - 0, - 36, - }, - dictWord{7, 0, 658}, - dictWord{8, 0, 454}, - dictWord{150, 11, 48}, - dictWord{133, 11, 674}, - dictWord{135, 11, 1776}, - dictWord{4, 11, 419}, - dictWord{ - 10, - 10, - 227, - }, - dictWord{11, 10, 497}, - dictWord{11, 10, 709}, - dictWord{140, 10, 415}, - dictWord{6, 10, 360}, - dictWord{7, 10, 1664}, - dictWord{136, 10, 478}, - dictWord{137, 0, 806}, - dictWord{12, 11, 508}, - dictWord{14, 11, 102}, - dictWord{14, 11, 226}, - dictWord{144, 11, 57}, - dictWord{135, 11, 1123}, - dictWord{ - 4, - 11, - 138, - }, - dictWord{7, 11, 1012}, - dictWord{7, 11, 1280}, - dictWord{137, 11, 76}, - dictWord{5, 11, 29}, - dictWord{140, 11, 638}, - dictWord{136, 10, 699}, - dictWord{134, 0, 1326}, - dictWord{132, 0, 104}, - dictWord{135, 11, 735}, - dictWord{132, 10, 739}, - dictWord{134, 0, 1331}, - dictWord{7, 0, 260}, - dictWord{ - 135, - 11, - 260, - }, - dictWord{135, 11, 1063}, - dictWord{7, 0, 45}, - dictWord{9, 0, 542}, - dictWord{9, 0, 566}, - dictWord{10, 0, 728}, - dictWord{137, 10, 869}, - dictWord{ - 4, - 10, - 67, - }, - dictWord{5, 10, 422}, - dictWord{7, 10, 1037}, - dictWord{7, 10, 1289}, - dictWord{7, 10, 1555}, - dictWord{9, 10, 741}, - dictWord{145, 10, 108}, - dictWord{ - 139, - 0, - 263, - }, - dictWord{134, 0, 1516}, - dictWord{14, 0, 146}, - dictWord{15, 0, 42}, - dictWord{16, 0, 23}, - dictWord{17, 0, 86}, - dictWord{146, 0, 17}, - dictWord{ - 138, - 0, - 468, - }, - dictWord{136, 0, 1005}, - dictWord{4, 11, 17}, - dictWord{5, 11, 23}, - dictWord{7, 11, 995}, - dictWord{11, 11, 383}, - dictWord{11, 11, 437}, - dictWord{ - 12, - 11, - 460, - }, - dictWord{140, 11, 532}, - dictWord{7, 0, 87}, - dictWord{142, 0, 288}, - dictWord{138, 10, 96}, - dictWord{135, 11, 626}, - dictWord{144, 10, 26}, - dictWord{ - 7, - 0, - 988, - }, - dictWord{7, 0, 1939}, - dictWord{9, 0, 64}, - dictWord{9, 0, 502}, - dictWord{12, 0, 22}, - dictWord{12, 0, 34}, - dictWord{13, 0, 12}, - dictWord{13, 0, 234}, - dictWord{147, 0, 77}, - dictWord{13, 0, 133}, - dictWord{8, 10, 203}, - dictWord{11, 10, 823}, - dictWord{11, 10, 846}, - dictWord{12, 10, 482}, - dictWord{13, 10, 277}, - dictWord{13, 10, 302}, - dictWord{13, 10, 464}, - dictWord{14, 10, 205}, - dictWord{142, 10, 221}, - dictWord{4, 10, 449}, - dictWord{133, 10, 718}, - dictWord{ - 135, - 0, - 141, - }, - dictWord{6, 0, 1842}, - dictWord{136, 0, 872}, - dictWord{8, 11, 70}, - dictWord{12, 11, 171}, - dictWord{141, 11, 272}, - dictWord{4, 10, 355}, - dictWord{ - 6, - 10, - 311, - }, - dictWord{9, 10, 256}, - dictWord{138, 10, 404}, - dictWord{132, 0, 619}, - dictWord{137, 0, 261}, - dictWord{10, 11, 233}, - dictWord{10, 10, 758}, - dictWord{139, 11, 76}, - dictWord{5, 0, 246}, - dictWord{8, 0, 189}, - dictWord{9, 0, 355}, - dictWord{9, 0, 512}, - dictWord{10, 0, 124}, - dictWord{10, 0, 453}, - dictWord{ - 11, - 0, - 143, - }, - dictWord{11, 0, 416}, - dictWord{11, 0, 859}, - dictWord{141, 0, 341}, - dictWord{134, 11, 442}, - dictWord{133, 10, 827}, - dictWord{5, 10, 64}, - dictWord{ - 140, - 10, - 581, - }, - dictWord{4, 10, 442}, - dictWord{7, 10, 1047}, - dictWord{7, 10, 1352}, - dictWord{135, 10, 1643}, - dictWord{134, 11, 1709}, - dictWord{5, 0, 678}, - dictWord{6, 0, 305}, - dictWord{7, 0, 775}, - dictWord{7, 0, 1065}, - dictWord{133, 10, 977}, - dictWord{11, 11, 69}, - dictWord{12, 11, 105}, - dictWord{12, 11, 117}, - dictWord{13, 11, 213}, - dictWord{14, 11, 13}, - dictWord{14, 11, 62}, - dictWord{14, 11, 177}, - dictWord{14, 11, 421}, - dictWord{15, 11, 19}, - dictWord{146, 11, 141}, - dictWord{137, 11, 309}, - dictWord{5, 0, 35}, - dictWord{7, 0, 862}, - dictWord{7, 0, 1886}, - dictWord{138, 0, 179}, - dictWord{136, 0, 285}, - dictWord{132, 0, 517}, - dictWord{7, 11, 976}, - dictWord{9, 11, 146}, - dictWord{10, 11, 206}, - dictWord{10, 11, 596}, - dictWord{13, 11, 218}, - dictWord{142, 11, 153}, - dictWord{ - 132, - 10, - 254, - }, - dictWord{6, 0, 214}, - dictWord{12, 0, 540}, - dictWord{4, 10, 275}, - dictWord{7, 10, 1219}, - dictWord{140, 10, 376}, - dictWord{8, 0, 667}, - dictWord{ - 11, - 0, - 403, - }, - dictWord{146, 0, 83}, - dictWord{12, 0, 74}, - dictWord{10, 11, 648}, - dictWord{11, 11, 671}, - dictWord{143, 11, 46}, - dictWord{135, 0, 125}, - dictWord{ - 134, - 10, - 1753, - }, - dictWord{133, 0, 761}, - dictWord{6, 0, 912}, - dictWord{4, 11, 518}, - dictWord{6, 10, 369}, - dictWord{6, 10, 502}, - dictWord{7, 10, 1036}, - dictWord{ - 7, - 11, - 1136, - }, - dictWord{8, 10, 348}, - dictWord{9, 10, 452}, - dictWord{10, 10, 26}, - dictWord{11, 10, 224}, - dictWord{11, 10, 387}, - dictWord{11, 10, 772}, - dictWord{12, 10, 95}, - dictWord{12, 10, 629}, - dictWord{13, 10, 195}, - dictWord{13, 10, 207}, - dictWord{13, 10, 241}, - dictWord{14, 10, 260}, - dictWord{14, 10, 270}, - dictWord{143, 10, 140}, - dictWord{10, 0, 131}, - dictWord{140, 0, 72}, - dictWord{132, 10, 269}, - dictWord{5, 10, 480}, - dictWord{7, 10, 532}, - dictWord{ - 7, - 10, - 1197, - }, - dictWord{7, 10, 1358}, - dictWord{8, 10, 291}, - dictWord{11, 10, 349}, - dictWord{142, 10, 396}, - dictWord{8, 11, 689}, - dictWord{137, 11, 863}, - dictWord{ - 8, - 0, - 333, - }, - dictWord{138, 0, 182}, - dictWord{4, 11, 18}, - dictWord{7, 11, 145}, - dictWord{7, 11, 444}, - dictWord{7, 11, 1278}, - dictWord{8, 11, 49}, - dictWord{ - 8, - 11, - 400, - }, - dictWord{9, 11, 71}, - dictWord{9, 11, 250}, - dictWord{10, 11, 459}, - dictWord{12, 11, 160}, - dictWord{144, 11, 24}, - dictWord{14, 11, 35}, - dictWord{ - 142, - 11, - 191, - }, - dictWord{135, 11, 1864}, - dictWord{135, 0, 1338}, - dictWord{148, 10, 15}, - dictWord{14, 0, 94}, - dictWord{15, 0, 65}, - dictWord{16, 0, 4}, - dictWord{ - 16, - 0, - 77, - }, - dictWord{16, 0, 80}, - dictWord{145, 0, 5}, - dictWord{12, 11, 82}, - dictWord{143, 11, 36}, - dictWord{133, 11, 1010}, - dictWord{133, 0, 449}, - dictWord{ - 133, - 0, - 646, - }, - dictWord{7, 0, 86}, - dictWord{8, 0, 103}, - dictWord{135, 10, 657}, - dictWord{7, 0, 2028}, - dictWord{138, 0, 641}, - dictWord{136, 10, 533}, - dictWord{ - 134, - 0, - 1, - }, - dictWord{139, 11, 970}, - dictWord{5, 11, 87}, - dictWord{7, 11, 313}, - dictWord{7, 11, 1103}, - dictWord{10, 11, 112}, - dictWord{10, 11, 582}, - dictWord{ - 11, - 11, - 389, - }, - dictWord{11, 11, 813}, - dictWord{12, 11, 385}, - dictWord{13, 11, 286}, - dictWord{14, 11, 124}, - dictWord{146, 11, 108}, - dictWord{6, 0, 869}, - dictWord{ - 132, - 11, - 267, - }, - dictWord{6, 0, 277}, - dictWord{7, 0, 1274}, - dictWord{7, 0, 1386}, - dictWord{146, 0, 87}, - dictWord{6, 0, 187}, - dictWord{7, 0, 39}, - dictWord{7, 0, 1203}, - dictWord{8, 0, 380}, - dictWord{14, 0, 117}, - dictWord{149, 0, 28}, - dictWord{4, 10, 211}, - dictWord{4, 10, 332}, - dictWord{5, 10, 335}, - dictWord{6, 10, 238}, - dictWord{ - 7, - 10, - 269, - }, - dictWord{7, 10, 811}, - dictWord{7, 10, 1797}, - dictWord{8, 10, 836}, - dictWord{9, 10, 507}, - dictWord{141, 10, 242}, - dictWord{4, 0, 785}, - dictWord{ - 5, - 0, - 368, - }, - dictWord{6, 0, 297}, - dictWord{7, 0, 793}, - dictWord{139, 0, 938}, - dictWord{7, 0, 464}, - dictWord{8, 0, 558}, - dictWord{11, 0, 105}, - dictWord{12, 0, 231}, - dictWord{14, 0, 386}, - dictWord{15, 0, 102}, - dictWord{148, 0, 75}, - dictWord{133, 10, 1009}, - dictWord{8, 0, 877}, - dictWord{140, 0, 731}, - dictWord{ - 139, - 11, - 289, - }, - dictWord{10, 11, 249}, - dictWord{139, 11, 209}, - dictWord{132, 11, 561}, - dictWord{134, 0, 1608}, - dictWord{132, 11, 760}, - dictWord{134, 0, 1429}, - dictWord{9, 11, 154}, - dictWord{140, 11, 485}, - dictWord{5, 10, 228}, - dictWord{6, 10, 203}, - dictWord{7, 10, 156}, - dictWord{8, 10, 347}, - dictWord{ - 137, - 10, - 265, - }, - dictWord{7, 0, 1010}, - dictWord{11, 0, 733}, - dictWord{11, 0, 759}, - dictWord{13, 0, 34}, - dictWord{14, 0, 427}, - dictWord{146, 0, 45}, - dictWord{7, 10, 1131}, - dictWord{135, 10, 1468}, - dictWord{136, 11, 255}, - dictWord{7, 0, 1656}, - dictWord{9, 0, 369}, - dictWord{10, 0, 338}, - dictWord{10, 0, 490}, - dictWord{ - 11, - 0, - 154, - }, - dictWord{11, 0, 545}, - dictWord{11, 0, 775}, - dictWord{13, 0, 77}, - dictWord{141, 0, 274}, - dictWord{133, 11, 621}, - dictWord{134, 0, 1038}, - dictWord{ - 4, - 11, - 368, - }, - dictWord{135, 11, 641}, - dictWord{6, 0, 2010}, - dictWord{8, 0, 979}, - dictWord{8, 0, 985}, - dictWord{10, 0, 951}, - dictWord{138, 0, 1011}, - dictWord{ - 134, - 0, - 1005, - }, - dictWord{19, 0, 121}, - dictWord{5, 10, 291}, - dictWord{5, 10, 318}, - dictWord{7, 10, 765}, - dictWord{9, 10, 389}, - dictWord{140, 10, 548}, - dictWord{ - 5, - 0, - 20, - }, - dictWord{6, 0, 298}, - dictWord{7, 0, 659}, - dictWord{137, 0, 219}, - dictWord{7, 0, 1440}, - dictWord{11, 0, 854}, - dictWord{11, 0, 872}, - dictWord{11, 0, 921}, - dictWord{12, 0, 551}, - dictWord{13, 0, 472}, - dictWord{142, 0, 367}, - dictWord{5, 0, 490}, - dictWord{6, 0, 615}, - dictWord{6, 0, 620}, - dictWord{135, 0, 683}, - dictWord{ - 6, - 0, - 1070, - }, - dictWord{134, 0, 1597}, - dictWord{139, 0, 522}, - dictWord{132, 0, 439}, - dictWord{136, 0, 669}, - dictWord{6, 0, 766}, - dictWord{6, 0, 1143}, - dictWord{ - 6, - 0, - 1245, - }, - dictWord{10, 10, 525}, - dictWord{139, 10, 82}, - dictWord{9, 11, 92}, - dictWord{147, 11, 91}, - dictWord{6, 0, 668}, - dictWord{134, 0, 1218}, - dictWord{ - 6, - 11, - 525, - }, - dictWord{9, 11, 876}, - dictWord{140, 11, 284}, - dictWord{132, 0, 233}, - dictWord{136, 0, 547}, - dictWord{132, 10, 422}, - dictWord{5, 10, 355}, - dictWord{145, 10, 0}, - dictWord{6, 11, 300}, - dictWord{135, 11, 1515}, - dictWord{4, 0, 482}, - dictWord{137, 10, 905}, - dictWord{4, 0, 886}, - dictWord{7, 0, 346}, - dictWord{133, 11, 594}, - dictWord{133, 10, 865}, - dictWord{5, 10, 914}, - dictWord{134, 10, 1625}, - dictWord{135, 0, 334}, - dictWord{5, 0, 795}, - dictWord{ - 6, - 0, - 1741, - }, - dictWord{133, 10, 234}, - dictWord{135, 10, 1383}, - dictWord{6, 11, 1641}, - dictWord{136, 11, 820}, - dictWord{135, 0, 371}, - dictWord{7, 11, 1313}, - dictWord{138, 11, 660}, - dictWord{135, 10, 1312}, - dictWord{135, 0, 622}, - dictWord{7, 0, 625}, - dictWord{135, 0, 1750}, - dictWord{135, 0, 339}, - dictWord{ - 4, - 0, - 203, - }, - dictWord{135, 0, 1936}, - dictWord{15, 0, 29}, - dictWord{16, 0, 38}, - dictWord{15, 11, 29}, - dictWord{144, 11, 38}, - dictWord{5, 0, 338}, - dictWord{ - 135, - 0, - 1256, - }, - dictWord{135, 10, 1493}, - dictWord{10, 0, 130}, - dictWord{6, 10, 421}, - dictWord{7, 10, 61}, - dictWord{7, 10, 1540}, - dictWord{138, 10, 501}, - dictWord{ - 6, - 11, - 389, - }, - dictWord{7, 11, 149}, - dictWord{9, 11, 142}, - dictWord{138, 11, 94}, - dictWord{137, 10, 341}, - dictWord{11, 0, 678}, - dictWord{12, 0, 307}, - dictWord{142, 10, 98}, - dictWord{6, 11, 8}, - dictWord{7, 11, 1881}, - dictWord{136, 11, 91}, - dictWord{135, 0, 2044}, - dictWord{6, 0, 770}, - dictWord{6, 0, 802}, - dictWord{ - 6, - 0, - 812, - }, - dictWord{7, 0, 311}, - dictWord{9, 0, 308}, - dictWord{12, 0, 255}, - dictWord{6, 10, 102}, - dictWord{7, 10, 72}, - dictWord{15, 10, 142}, - dictWord{ - 147, - 10, - 67, - }, - dictWord{151, 10, 30}, - dictWord{135, 10, 823}, - dictWord{135, 0, 1266}, - dictWord{135, 11, 1746}, - dictWord{135, 10, 1870}, - dictWord{4, 0, 400}, - dictWord{5, 0, 267}, - dictWord{135, 0, 232}, - dictWord{7, 11, 24}, - dictWord{11, 11, 542}, - dictWord{139, 11, 852}, - dictWord{135, 11, 1739}, - dictWord{4, 11, 503}, - dictWord{135, 11, 1661}, - dictWord{5, 11, 130}, - dictWord{7, 11, 1314}, - dictWord{9, 11, 610}, - dictWord{10, 11, 718}, - dictWord{11, 11, 601}, - dictWord{ - 11, - 11, - 819, - }, - dictWord{11, 11, 946}, - dictWord{140, 11, 536}, - dictWord{10, 11, 149}, - dictWord{11, 11, 280}, - dictWord{142, 11, 336}, - dictWord{7, 0, 739}, - dictWord{11, 0, 690}, - dictWord{7, 11, 1946}, - dictWord{8, 10, 48}, - dictWord{8, 10, 88}, - dictWord{8, 10, 582}, - dictWord{8, 10, 681}, - dictWord{9, 10, 373}, - dictWord{ - 9, - 10, - 864, - }, - dictWord{11, 10, 157}, - dictWord{11, 10, 843}, - dictWord{148, 10, 27}, - dictWord{134, 0, 990}, - dictWord{4, 10, 88}, - dictWord{5, 10, 137}, - dictWord{ - 5, - 10, - 174, - }, - dictWord{5, 10, 777}, - dictWord{6, 10, 1664}, - dictWord{6, 10, 1725}, - dictWord{7, 10, 77}, - dictWord{7, 10, 426}, - dictWord{7, 10, 1317}, - dictWord{ - 7, - 10, - 1355, - }, - dictWord{8, 10, 126}, - dictWord{8, 10, 563}, - dictWord{9, 10, 523}, - dictWord{9, 10, 750}, - dictWord{10, 10, 310}, - dictWord{10, 10, 836}, - dictWord{ - 11, - 10, - 42, - }, - dictWord{11, 10, 318}, - dictWord{11, 10, 731}, - dictWord{12, 10, 68}, - dictWord{12, 10, 92}, - dictWord{12, 10, 507}, - dictWord{12, 10, 692}, - dictWord{ - 13, - 10, - 81, - }, - dictWord{13, 10, 238}, - dictWord{13, 10, 374}, - dictWord{14, 10, 436}, - dictWord{18, 10, 138}, - dictWord{19, 10, 78}, - dictWord{19, 10, 111}, - dictWord{20, 10, 55}, - dictWord{20, 10, 77}, - dictWord{148, 10, 92}, - dictWord{141, 10, 418}, - dictWord{7, 0, 1831}, - dictWord{132, 10, 938}, - dictWord{6, 0, 776}, - dictWord{134, 0, 915}, - dictWord{138, 10, 351}, - dictWord{5, 11, 348}, - dictWord{6, 11, 522}, - dictWord{6, 10, 1668}, - dictWord{7, 10, 1499}, - dictWord{8, 10, 117}, - dictWord{9, 10, 314}, - dictWord{138, 10, 174}, - dictWord{135, 10, 707}, - dictWord{132, 0, 613}, - dictWord{133, 10, 403}, - dictWord{132, 11, 392}, - dictWord{ - 5, - 11, - 433, - }, - dictWord{9, 11, 633}, - dictWord{139, 11, 629}, - dictWord{133, 0, 763}, - dictWord{132, 0, 878}, - dictWord{132, 0, 977}, - dictWord{132, 0, 100}, - dictWord{6, 0, 463}, - dictWord{4, 10, 44}, - dictWord{5, 10, 311}, - dictWord{7, 10, 639}, - dictWord{7, 10, 762}, - dictWord{7, 10, 1827}, - dictWord{9, 10, 8}, - dictWord{ - 9, - 10, - 462, - }, - dictWord{148, 10, 83}, - dictWord{134, 11, 234}, - dictWord{4, 10, 346}, - dictWord{7, 10, 115}, - dictWord{9, 10, 180}, - dictWord{9, 10, 456}, - dictWord{ - 138, - 10, - 363, - }, - dictWord{5, 0, 362}, - dictWord{5, 0, 443}, - dictWord{6, 0, 318}, - dictWord{7, 0, 1019}, - dictWord{139, 0, 623}, - dictWord{5, 0, 463}, - dictWord{8, 0, 296}, - dictWord{7, 11, 140}, - dictWord{7, 11, 1950}, - dictWord{8, 11, 680}, - dictWord{11, 11, 817}, - dictWord{147, 11, 88}, - dictWord{7, 11, 1222}, - dictWord{ - 138, - 11, - 386, - }, - dictWord{142, 0, 137}, - dictWord{132, 0, 454}, - dictWord{7, 0, 1914}, - dictWord{6, 11, 5}, - dictWord{7, 10, 1051}, - dictWord{9, 10, 545}, - dictWord{ - 11, - 11, - 249, - }, - dictWord{12, 11, 313}, - dictWord{16, 11, 66}, - dictWord{145, 11, 26}, - dictWord{135, 0, 1527}, - dictWord{145, 0, 58}, - dictWord{148, 11, 59}, - dictWord{ - 5, - 0, - 48, - }, - dictWord{5, 0, 404}, - dictWord{6, 0, 557}, - dictWord{7, 0, 458}, - dictWord{8, 0, 597}, - dictWord{10, 0, 455}, - dictWord{10, 0, 606}, - dictWord{11, 0, 49}, - dictWord{ - 11, - 0, - 548, - }, - dictWord{12, 0, 476}, - dictWord{13, 0, 18}, - dictWord{141, 0, 450}, - dictWord{5, 11, 963}, - dictWord{134, 11, 1773}, - dictWord{133, 0, 729}, - dictWord{138, 11, 586}, - dictWord{5, 0, 442}, - dictWord{135, 0, 1984}, - dictWord{134, 0, 449}, - dictWord{144, 0, 40}, - dictWord{4, 0, 853}, - dictWord{7, 11, 180}, - dictWord{8, 11, 509}, - dictWord{136, 11, 792}, - dictWord{6, 10, 185}, - dictWord{7, 10, 1899}, - dictWord{9, 10, 875}, - dictWord{139, 10, 673}, - dictWord{ - 134, - 11, - 524, - }, - dictWord{12, 0, 227}, - dictWord{4, 10, 327}, - dictWord{5, 10, 478}, - dictWord{7, 10, 1332}, - dictWord{136, 10, 753}, - dictWord{6, 0, 1491}, - dictWord{ - 5, - 10, - 1020, - }, - dictWord{133, 10, 1022}, - dictWord{4, 10, 103}, - dictWord{133, 10, 401}, - dictWord{132, 11, 931}, - dictWord{4, 10, 499}, - dictWord{135, 10, 1421}, - dictWord{5, 0, 55}, - dictWord{7, 0, 376}, - dictWord{140, 0, 161}, - dictWord{133, 0, 450}, - dictWord{6, 0, 1174}, - dictWord{134, 0, 1562}, - dictWord{10, 0, 62}, - dictWord{13, 0, 400}, - dictWord{135, 11, 1837}, - dictWord{140, 0, 207}, - dictWord{135, 0, 869}, - dictWord{4, 11, 773}, - dictWord{5, 11, 618}, - dictWord{ - 137, - 11, - 756, - }, - dictWord{132, 10, 96}, - dictWord{4, 0, 213}, - dictWord{7, 0, 223}, - dictWord{8, 0, 80}, - dictWord{135, 10, 968}, - dictWord{4, 11, 90}, - dictWord{5, 11, 337}, - dictWord{5, 11, 545}, - dictWord{7, 11, 754}, - dictWord{9, 11, 186}, - dictWord{10, 11, 72}, - dictWord{10, 11, 782}, - dictWord{11, 11, 513}, - dictWord{11, 11, 577}, - dictWord{11, 11, 610}, - dictWord{11, 11, 889}, - dictWord{11, 11, 961}, - dictWord{12, 11, 354}, - dictWord{12, 11, 362}, - dictWord{12, 11, 461}, - dictWord{ - 12, - 11, - 595, - }, - dictWord{13, 11, 79}, - dictWord{143, 11, 121}, - dictWord{7, 0, 381}, - dictWord{7, 0, 806}, - dictWord{7, 0, 820}, - dictWord{8, 0, 354}, - dictWord{8, 0, 437}, - dictWord{8, 0, 787}, - dictWord{9, 0, 657}, - dictWord{10, 0, 58}, - dictWord{10, 0, 339}, - dictWord{10, 0, 749}, - dictWord{11, 0, 914}, - dictWord{12, 0, 162}, - dictWord{ - 13, - 0, - 75, - }, - dictWord{14, 0, 106}, - dictWord{14, 0, 198}, - dictWord{14, 0, 320}, - dictWord{14, 0, 413}, - dictWord{146, 0, 43}, - dictWord{136, 0, 747}, - dictWord{ - 136, - 0, - 954, - }, - dictWord{134, 0, 1073}, - dictWord{135, 0, 556}, - dictWord{7, 11, 151}, - dictWord{9, 11, 329}, - dictWord{139, 11, 254}, - dictWord{5, 0, 692}, - dictWord{ - 134, - 0, - 1395, - }, - dictWord{6, 10, 563}, - dictWord{137, 10, 224}, - dictWord{134, 0, 191}, - dictWord{132, 0, 804}, - dictWord{9, 11, 187}, - dictWord{10, 11, 36}, - dictWord{17, 11, 44}, - dictWord{146, 11, 64}, - dictWord{7, 11, 165}, - dictWord{7, 11, 919}, - dictWord{136, 11, 517}, - dictWord{4, 11, 506}, - dictWord{5, 11, 295}, - dictWord{7, 11, 1680}, - dictWord{15, 11, 14}, - dictWord{144, 11, 5}, - dictWord{4, 0, 706}, - dictWord{6, 0, 162}, - dictWord{7, 0, 1960}, - dictWord{136, 0, 831}, - dictWord{ - 135, - 11, - 1376, - }, - dictWord{7, 11, 987}, - dictWord{9, 11, 688}, - dictWord{10, 11, 522}, - dictWord{11, 11, 788}, - dictWord{140, 11, 566}, - dictWord{150, 0, 35}, - dictWord{138, 0, 426}, - dictWord{135, 0, 1235}, - dictWord{135, 11, 1741}, - dictWord{7, 11, 389}, - dictWord{7, 11, 700}, - dictWord{7, 11, 940}, - dictWord{ - 8, - 11, - 514, - }, - dictWord{9, 11, 116}, - dictWord{9, 11, 535}, - dictWord{10, 11, 118}, - dictWord{11, 11, 107}, - dictWord{11, 11, 148}, - dictWord{11, 11, 922}, - dictWord{ - 12, - 11, - 254, - }, - dictWord{12, 11, 421}, - dictWord{142, 11, 238}, - dictWord{134, 0, 1234}, - dictWord{132, 11, 743}, - dictWord{4, 10, 910}, - dictWord{5, 10, 832}, - dictWord{135, 11, 1335}, - dictWord{141, 0, 96}, - dictWord{135, 11, 185}, - dictWord{146, 0, 149}, - dictWord{4, 0, 204}, - dictWord{137, 0, 902}, - dictWord{ - 4, - 11, - 784, - }, - dictWord{133, 11, 745}, - dictWord{136, 0, 833}, - dictWord{136, 0, 949}, - dictWord{7, 0, 366}, - dictWord{9, 0, 287}, - dictWord{12, 0, 199}, - dictWord{ - 12, - 0, - 556, - }, - dictWord{12, 0, 577}, - dictWord{5, 11, 81}, - dictWord{7, 11, 146}, - dictWord{7, 11, 1342}, - dictWord{7, 11, 1446}, - dictWord{8, 11, 53}, - dictWord{8, 11, 561}, - dictWord{8, 11, 694}, - dictWord{8, 11, 754}, - dictWord{9, 11, 97}, - dictWord{9, 11, 115}, - dictWord{9, 11, 894}, - dictWord{10, 11, 462}, - dictWord{10, 11, 813}, - dictWord{11, 11, 230}, - dictWord{11, 11, 657}, - dictWord{11, 11, 699}, - dictWord{11, 11, 748}, - dictWord{12, 11, 119}, - dictWord{12, 11, 200}, - dictWord{ - 12, - 11, - 283, - }, - dictWord{14, 11, 273}, - dictWord{145, 11, 15}, - dictWord{5, 11, 408}, - dictWord{137, 11, 747}, - dictWord{9, 11, 498}, - dictWord{140, 11, 181}, - dictWord{ - 6, - 0, - 2020, - }, - dictWord{136, 0, 992}, - dictWord{5, 0, 356}, - dictWord{135, 0, 224}, - dictWord{134, 0, 784}, - dictWord{7, 0, 630}, - dictWord{9, 0, 567}, - dictWord{ - 11, - 0, - 150, - }, - dictWord{11, 0, 444}, - dictWord{13, 0, 119}, - dictWord{8, 10, 528}, - dictWord{137, 10, 348}, - dictWord{134, 0, 539}, - dictWord{4, 10, 20}, - dictWord{ - 133, - 10, - 616, - }, - dictWord{142, 0, 27}, - dictWord{7, 11, 30}, - dictWord{8, 11, 86}, - dictWord{8, 11, 315}, - dictWord{8, 11, 700}, - dictWord{9, 11, 576}, - dictWord{9, 11, 858}, - dictWord{11, 11, 310}, - dictWord{11, 11, 888}, - dictWord{11, 11, 904}, - dictWord{12, 11, 361}, - dictWord{141, 11, 248}, - dictWord{138, 11, 839}, - dictWord{ - 134, - 0, - 755, - }, - dictWord{134, 0, 1063}, - dictWord{7, 10, 1091}, - dictWord{135, 10, 1765}, - dictWord{134, 11, 428}, - dictWord{7, 11, 524}, - dictWord{8, 11, 169}, - dictWord{8, 11, 234}, - dictWord{9, 11, 480}, - dictWord{138, 11, 646}, - dictWord{139, 0, 814}, - dictWord{7, 11, 1462}, - dictWord{139, 11, 659}, - dictWord{ - 4, - 10, - 26, - }, - dictWord{5, 10, 429}, - dictWord{6, 10, 245}, - dictWord{7, 10, 704}, - dictWord{7, 10, 1379}, - dictWord{135, 10, 1474}, - dictWord{7, 11, 1205}, - dictWord{ - 138, - 11, - 637, - }, - dictWord{139, 11, 803}, - dictWord{132, 10, 621}, - dictWord{136, 0, 987}, - dictWord{4, 11, 266}, - dictWord{8, 11, 4}, - dictWord{9, 11, 39}, - dictWord{ - 10, - 11, - 166, - }, - dictWord{11, 11, 918}, - dictWord{12, 11, 635}, - dictWord{20, 11, 10}, - dictWord{22, 11, 27}, - dictWord{150, 11, 43}, - dictWord{4, 0, 235}, - dictWord{ - 135, - 0, - 255, - }, - dictWord{4, 0, 194}, - dictWord{5, 0, 584}, - dictWord{6, 0, 384}, - dictWord{7, 0, 583}, - dictWord{10, 0, 761}, - dictWord{11, 0, 760}, - dictWord{139, 0, 851}, - dictWord{133, 10, 542}, - dictWord{134, 0, 1086}, - dictWord{133, 10, 868}, - dictWord{8, 0, 1016}, - dictWord{136, 0, 1018}, - dictWord{7, 0, 1396}, - dictWord{ - 7, - 11, - 1396, - }, - dictWord{136, 10, 433}, - dictWord{135, 10, 1495}, - dictWord{138, 10, 215}, - dictWord{141, 10, 124}, - dictWord{7, 11, 157}, - dictWord{ - 8, - 11, - 279, - }, - dictWord{9, 11, 759}, - dictWord{16, 11, 31}, - dictWord{16, 11, 39}, - dictWord{16, 11, 75}, - dictWord{18, 11, 24}, - dictWord{20, 11, 42}, - dictWord{152, 11, 1}, - dictWord{5, 0, 562}, - dictWord{134, 11, 604}, - dictWord{134, 0, 913}, - dictWord{5, 0, 191}, - dictWord{137, 0, 271}, - dictWord{4, 0, 470}, - dictWord{6, 0, 153}, - dictWord{7, 0, 1503}, - dictWord{7, 0, 1923}, - dictWord{10, 0, 701}, - dictWord{11, 0, 132}, - dictWord{11, 0, 227}, - dictWord{11, 0, 320}, - dictWord{11, 0, 436}, - dictWord{ - 11, - 0, - 525, - }, - dictWord{11, 0, 855}, - dictWord{11, 0, 873}, - dictWord{12, 0, 41}, - dictWord{12, 0, 286}, - dictWord{13, 0, 103}, - dictWord{13, 0, 284}, - dictWord{ - 14, - 0, - 255, - }, - dictWord{14, 0, 262}, - dictWord{15, 0, 117}, - dictWord{143, 0, 127}, - dictWord{7, 0, 475}, - dictWord{12, 0, 45}, - dictWord{147, 10, 112}, - dictWord{ - 132, - 11, - 567, - }, - dictWord{137, 11, 859}, - dictWord{6, 0, 713}, - dictWord{6, 0, 969}, - dictWord{6, 0, 1290}, - dictWord{134, 0, 1551}, - dictWord{133, 0, 327}, - dictWord{ - 6, - 0, - 552, - }, - dictWord{6, 0, 1292}, - dictWord{7, 0, 1754}, - dictWord{137, 0, 604}, - dictWord{4, 0, 223}, - dictWord{6, 0, 359}, - dictWord{11, 0, 3}, - dictWord{13, 0, 108}, - dictWord{14, 0, 89}, - dictWord{16, 0, 22}, - dictWord{5, 11, 762}, - dictWord{7, 11, 1880}, - dictWord{9, 11, 680}, - dictWord{139, 11, 798}, - dictWord{5, 0, 80}, - dictWord{ - 6, - 0, - 405, - }, - dictWord{7, 0, 403}, - dictWord{7, 0, 1502}, - dictWord{8, 0, 456}, - dictWord{9, 0, 487}, - dictWord{9, 0, 853}, - dictWord{9, 0, 889}, - dictWord{10, 0, 309}, - dictWord{ - 11, - 0, - 721, - }, - dictWord{11, 0, 994}, - dictWord{12, 0, 430}, - dictWord{141, 0, 165}, - dictWord{133, 11, 298}, - dictWord{132, 10, 647}, - dictWord{134, 0, 2016}, - dictWord{18, 10, 10}, - dictWord{146, 11, 10}, - dictWord{4, 0, 453}, - dictWord{5, 0, 887}, - dictWord{6, 0, 535}, - dictWord{8, 0, 6}, - dictWord{8, 0, 543}, - dictWord{ - 136, - 0, - 826, - }, - dictWord{136, 0, 975}, - dictWord{10, 0, 961}, - dictWord{138, 0, 962}, - dictWord{138, 10, 220}, - dictWord{6, 0, 1891}, - dictWord{6, 0, 1893}, - dictWord{ - 9, - 0, - 916, - }, - dictWord{9, 0, 965}, - dictWord{9, 0, 972}, - dictWord{12, 0, 801}, - dictWord{12, 0, 859}, - dictWord{12, 0, 883}, - dictWord{15, 0, 226}, - dictWord{149, 0, 51}, - dictWord{132, 10, 109}, - dictWord{135, 11, 267}, - dictWord{7, 11, 92}, - dictWord{7, 11, 182}, - dictWord{8, 11, 453}, - dictWord{9, 11, 204}, - dictWord{11, 11, 950}, - dictWord{12, 11, 94}, - dictWord{12, 11, 644}, - dictWord{16, 11, 20}, - dictWord{16, 11, 70}, - dictWord{16, 11, 90}, - dictWord{147, 11, 55}, - dictWord{ - 134, - 10, - 1746, - }, - dictWord{6, 11, 71}, - dictWord{7, 11, 845}, - dictWord{7, 11, 1308}, - dictWord{8, 11, 160}, - dictWord{137, 11, 318}, - dictWord{5, 0, 101}, - dictWord{6, 0, 88}, - dictWord{7, 0, 263}, - dictWord{7, 0, 628}, - dictWord{7, 0, 1677}, - dictWord{8, 0, 349}, - dictWord{9, 0, 100}, - dictWord{10, 0, 677}, - dictWord{14, 0, 169}, - dictWord{ - 14, - 0, - 302, - }, - dictWord{14, 0, 313}, - dictWord{15, 0, 48}, - dictWord{15, 0, 84}, - dictWord{7, 11, 237}, - dictWord{8, 11, 664}, - dictWord{9, 11, 42}, - dictWord{9, 11, 266}, - dictWord{9, 11, 380}, - dictWord{9, 11, 645}, - dictWord{10, 11, 177}, - dictWord{138, 11, 276}, - dictWord{138, 11, 69}, - dictWord{4, 0, 310}, - dictWord{7, 0, 708}, - dictWord{7, 0, 996}, - dictWord{9, 0, 795}, - dictWord{10, 0, 390}, - dictWord{10, 0, 733}, - dictWord{11, 0, 451}, - dictWord{12, 0, 249}, - dictWord{14, 0, 115}, - dictWord{ - 14, - 0, - 286, - }, - dictWord{143, 0, 100}, - dictWord{5, 0, 587}, - dictWord{4, 10, 40}, - dictWord{10, 10, 67}, - dictWord{11, 10, 117}, - dictWord{11, 10, 768}, - dictWord{ - 139, - 10, - 935, - }, - dictWord{6, 0, 1942}, - dictWord{7, 0, 512}, - dictWord{136, 0, 983}, - dictWord{7, 10, 992}, - dictWord{8, 10, 301}, - dictWord{9, 10, 722}, - dictWord{12, 10, 63}, - dictWord{13, 10, 29}, - dictWord{14, 10, 161}, - dictWord{143, 10, 18}, - dictWord{136, 11, 76}, - dictWord{139, 10, 923}, - dictWord{134, 0, 645}, - dictWord{ - 134, - 0, - 851, - }, - dictWord{4, 0, 498}, - dictWord{132, 11, 293}, - dictWord{7, 0, 217}, - dictWord{8, 0, 140}, - dictWord{10, 0, 610}, - dictWord{14, 11, 352}, - dictWord{ - 17, - 11, - 53, - }, - dictWord{18, 11, 146}, - dictWord{18, 11, 152}, - dictWord{19, 11, 11}, - dictWord{150, 11, 54}, - dictWord{134, 0, 1448}, - dictWord{138, 11, 841}, - dictWord{133, 0, 905}, - dictWord{4, 11, 605}, - dictWord{7, 11, 518}, - dictWord{7, 11, 1282}, - dictWord{7, 11, 1918}, - dictWord{10, 11, 180}, - dictWord{139, 11, 218}, - dictWord{139, 11, 917}, - dictWord{135, 10, 825}, - dictWord{140, 10, 328}, - dictWord{4, 0, 456}, - dictWord{7, 0, 105}, - dictWord{7, 0, 358}, - dictWord{7, 0, 1637}, - dictWord{8, 0, 643}, - dictWord{139, 0, 483}, - dictWord{134, 0, 792}, - dictWord{6, 11, 96}, - dictWord{135, 11, 1426}, - dictWord{137, 11, 691}, - dictWord{ - 4, - 11, - 651, - }, - dictWord{133, 11, 289}, - dictWord{7, 11, 688}, - dictWord{8, 11, 35}, - dictWord{9, 11, 511}, - dictWord{10, 11, 767}, - dictWord{147, 11, 118}, - dictWord{ - 150, - 0, - 56, - }, - dictWord{5, 0, 243}, - dictWord{5, 0, 535}, - dictWord{6, 10, 204}, - dictWord{10, 10, 320}, - dictWord{10, 10, 583}, - dictWord{13, 10, 502}, - dictWord{ - 14, - 10, - 72, - }, - dictWord{14, 10, 274}, - dictWord{14, 10, 312}, - dictWord{14, 10, 344}, - dictWord{15, 10, 159}, - dictWord{16, 10, 62}, - dictWord{16, 10, 69}, - dictWord{ - 17, - 10, - 30, - }, - dictWord{18, 10, 42}, - dictWord{18, 10, 53}, - dictWord{18, 10, 84}, - dictWord{18, 10, 140}, - dictWord{19, 10, 68}, - dictWord{19, 10, 85}, - dictWord{20, 10, 5}, - dictWord{20, 10, 45}, - dictWord{20, 10, 101}, - dictWord{22, 10, 7}, - dictWord{150, 10, 20}, - dictWord{4, 10, 558}, - dictWord{6, 10, 390}, - dictWord{7, 10, 162}, - dictWord{7, 10, 689}, - dictWord{9, 10, 360}, - dictWord{138, 10, 653}, - dictWord{146, 11, 23}, - dictWord{135, 0, 1748}, - dictWord{5, 10, 856}, - dictWord{ - 6, - 10, - 1672, - }, - dictWord{6, 10, 1757}, - dictWord{134, 10, 1781}, - dictWord{5, 0, 539}, - dictWord{5, 0, 754}, - dictWord{6, 0, 876}, - dictWord{132, 11, 704}, - dictWord{ - 135, - 11, - 1078, - }, - dictWord{5, 10, 92}, - dictWord{10, 10, 736}, - dictWord{140, 10, 102}, - dictWord{17, 0, 91}, - dictWord{5, 10, 590}, - dictWord{137, 10, 213}, - dictWord{134, 0, 1565}, - dictWord{6, 0, 91}, - dictWord{135, 0, 435}, - dictWord{4, 0, 939}, - dictWord{140, 0, 792}, - dictWord{134, 0, 1399}, - dictWord{4, 0, 16}, - dictWord{ - 5, - 0, - 316, - }, - dictWord{5, 0, 842}, - dictWord{6, 0, 370}, - dictWord{6, 0, 1778}, - dictWord{8, 0, 166}, - dictWord{11, 0, 812}, - dictWord{12, 0, 206}, - dictWord{12, 0, 351}, - dictWord{14, 0, 418}, - dictWord{16, 0, 15}, - dictWord{16, 0, 34}, - dictWord{18, 0, 3}, - dictWord{19, 0, 3}, - dictWord{19, 0, 7}, - dictWord{20, 0, 4}, - dictWord{21, 0, 21}, - dictWord{ - 4, - 11, - 720, - }, - dictWord{133, 11, 306}, - dictWord{144, 0, 95}, - dictWord{133, 11, 431}, - dictWord{132, 11, 234}, - dictWord{135, 0, 551}, - dictWord{4, 0, 999}, - dictWord{6, 0, 1966}, - dictWord{134, 0, 2042}, - dictWord{7, 0, 619}, - dictWord{10, 0, 547}, - dictWord{11, 0, 122}, - dictWord{12, 0, 601}, - dictWord{15, 0, 7}, - dictWord{148, 0, 20}, - dictWord{5, 11, 464}, - dictWord{6, 11, 236}, - dictWord{7, 11, 276}, - dictWord{7, 11, 696}, - dictWord{7, 11, 914}, - dictWord{7, 11, 1108}, - dictWord{ - 7, - 11, - 1448, - }, - dictWord{9, 11, 15}, - dictWord{9, 11, 564}, - dictWord{10, 11, 14}, - dictWord{12, 11, 565}, - dictWord{13, 11, 449}, - dictWord{14, 11, 53}, - dictWord{ - 15, - 11, - 13, - }, - dictWord{16, 11, 64}, - dictWord{145, 11, 41}, - dictWord{6, 0, 884}, - dictWord{6, 0, 1019}, - dictWord{134, 0, 1150}, - dictWord{6, 11, 1767}, - dictWord{ - 12, - 11, - 194, - }, - dictWord{145, 11, 107}, - dictWord{136, 10, 503}, - dictWord{133, 11, 840}, - dictWord{7, 0, 671}, - dictWord{134, 10, 466}, - dictWord{132, 0, 888}, - dictWord{4, 0, 149}, - dictWord{138, 0, 368}, - dictWord{4, 0, 154}, - dictWord{7, 0, 1134}, - dictWord{136, 0, 105}, - dictWord{135, 0, 983}, - dictWord{9, 11, 642}, - dictWord{11, 11, 236}, - dictWord{142, 11, 193}, - dictWord{4, 0, 31}, - dictWord{6, 0, 429}, - dictWord{7, 0, 962}, - dictWord{9, 0, 458}, - dictWord{139, 0, 691}, - dictWord{ - 6, - 0, - 643, - }, - dictWord{134, 0, 1102}, - dictWord{132, 0, 312}, - dictWord{4, 11, 68}, - dictWord{5, 11, 634}, - dictWord{6, 11, 386}, - dictWord{7, 11, 794}, - dictWord{ - 8, - 11, - 273, - }, - dictWord{9, 11, 563}, - dictWord{10, 11, 105}, - dictWord{10, 11, 171}, - dictWord{11, 11, 94}, - dictWord{139, 11, 354}, - dictWord{133, 0, 740}, - dictWord{ - 135, - 0, - 1642, - }, - dictWord{4, 11, 95}, - dictWord{7, 11, 416}, - dictWord{8, 11, 211}, - dictWord{139, 11, 830}, - dictWord{132, 0, 236}, - dictWord{138, 10, 241}, - dictWord{7, 11, 731}, - dictWord{13, 11, 20}, - dictWord{143, 11, 11}, - dictWord{5, 0, 836}, - dictWord{5, 0, 857}, - dictWord{6, 0, 1680}, - dictWord{135, 0, 59}, - dictWord{ - 10, - 0, - 68, - }, - dictWord{11, 0, 494}, - dictWord{152, 11, 6}, - dictWord{4, 0, 81}, - dictWord{139, 0, 867}, - dictWord{135, 0, 795}, - dictWord{133, 11, 689}, - dictWord{ - 4, - 0, - 1001, - }, - dictWord{5, 0, 282}, - dictWord{6, 0, 1932}, - dictWord{6, 0, 1977}, - dictWord{6, 0, 1987}, - dictWord{6, 0, 1992}, - dictWord{8, 0, 650}, - dictWord{8, 0, 919}, - dictWord{8, 0, 920}, - dictWord{8, 0, 923}, - dictWord{8, 0, 926}, - dictWord{8, 0, 927}, - dictWord{8, 0, 931}, - dictWord{8, 0, 939}, - dictWord{8, 0, 947}, - dictWord{8, 0, 956}, - dictWord{8, 0, 997}, - dictWord{9, 0, 907}, - dictWord{10, 0, 950}, - dictWord{10, 0, 953}, - dictWord{10, 0, 954}, - dictWord{10, 0, 956}, - dictWord{10, 0, 958}, - dictWord{ - 10, - 0, - 959, - }, - dictWord{10, 0, 964}, - dictWord{10, 0, 970}, - dictWord{10, 0, 972}, - dictWord{10, 0, 973}, - dictWord{10, 0, 975}, - dictWord{10, 0, 976}, - dictWord{ - 10, - 0, - 980, - }, - dictWord{10, 0, 981}, - dictWord{10, 0, 984}, - dictWord{10, 0, 988}, - dictWord{10, 0, 990}, - dictWord{10, 0, 995}, - dictWord{10, 0, 999}, - dictWord{ - 10, - 0, - 1002, - }, - dictWord{10, 0, 1003}, - dictWord{10, 0, 1005}, - dictWord{10, 0, 1006}, - dictWord{10, 0, 1008}, - dictWord{10, 0, 1009}, - dictWord{10, 0, 1012}, - dictWord{10, 0, 1014}, - dictWord{10, 0, 1015}, - dictWord{10, 0, 1019}, - dictWord{10, 0, 1020}, - dictWord{10, 0, 1022}, - dictWord{12, 0, 959}, - dictWord{12, 0, 961}, - dictWord{12, 0, 962}, - dictWord{12, 0, 963}, - dictWord{12, 0, 964}, - dictWord{12, 0, 965}, - dictWord{12, 0, 967}, - dictWord{12, 0, 968}, - dictWord{12, 0, 969}, - dictWord{12, 0, 970}, - dictWord{12, 0, 971}, - dictWord{12, 0, 972}, - dictWord{12, 0, 973}, - dictWord{12, 0, 974}, - dictWord{12, 0, 975}, - dictWord{12, 0, 976}, - dictWord{ - 12, - 0, - 977, - }, - dictWord{12, 0, 979}, - dictWord{12, 0, 981}, - dictWord{12, 0, 982}, - dictWord{12, 0, 983}, - dictWord{12, 0, 984}, - dictWord{12, 0, 985}, - dictWord{ - 12, - 0, - 986, - }, - dictWord{12, 0, 987}, - dictWord{12, 0, 989}, - dictWord{12, 0, 990}, - dictWord{12, 0, 992}, - dictWord{12, 0, 993}, - dictWord{12, 0, 995}, - dictWord{12, 0, 998}, - dictWord{12, 0, 999}, - dictWord{12, 0, 1000}, - dictWord{12, 0, 1001}, - dictWord{12, 0, 1002}, - dictWord{12, 0, 1004}, - dictWord{12, 0, 1005}, - dictWord{ - 12, - 0, - 1006, - }, - dictWord{12, 0, 1007}, - dictWord{12, 0, 1008}, - dictWord{12, 0, 1009}, - dictWord{12, 0, 1010}, - dictWord{12, 0, 1011}, - dictWord{12, 0, 1012}, - dictWord{12, 0, 1014}, - dictWord{12, 0, 1015}, - dictWord{12, 0, 1016}, - dictWord{12, 0, 1017}, - dictWord{12, 0, 1018}, - dictWord{12, 0, 1019}, - dictWord{ - 12, - 0, - 1022, - }, - dictWord{12, 0, 1023}, - dictWord{14, 0, 475}, - dictWord{14, 0, 477}, - dictWord{14, 0, 478}, - dictWord{14, 0, 479}, - dictWord{14, 0, 480}, - dictWord{ - 14, - 0, - 482, - }, - dictWord{14, 0, 483}, - dictWord{14, 0, 484}, - dictWord{14, 0, 485}, - dictWord{14, 0, 486}, - dictWord{14, 0, 487}, - dictWord{14, 0, 488}, - dictWord{14, 0, 489}, - dictWord{14, 0, 490}, - dictWord{14, 0, 491}, - dictWord{14, 0, 492}, - dictWord{14, 0, 493}, - dictWord{14, 0, 494}, - dictWord{14, 0, 495}, - dictWord{14, 0, 496}, - dictWord{14, 0, 497}, - dictWord{14, 0, 498}, - dictWord{14, 0, 499}, - dictWord{14, 0, 500}, - dictWord{14, 0, 501}, - dictWord{14, 0, 502}, - dictWord{14, 0, 503}, - dictWord{ - 14, - 0, - 504, - }, - dictWord{14, 0, 506}, - dictWord{14, 0, 507}, - dictWord{14, 0, 508}, - dictWord{14, 0, 509}, - dictWord{14, 0, 510}, - dictWord{14, 0, 511}, - dictWord{ - 16, - 0, - 113, - }, - dictWord{16, 0, 114}, - dictWord{16, 0, 115}, - dictWord{16, 0, 117}, - dictWord{16, 0, 118}, - dictWord{16, 0, 119}, - dictWord{16, 0, 121}, - dictWord{16, 0, 122}, - dictWord{16, 0, 123}, - dictWord{16, 0, 124}, - dictWord{16, 0, 125}, - dictWord{16, 0, 126}, - dictWord{16, 0, 127}, - dictWord{18, 0, 242}, - dictWord{18, 0, 243}, - dictWord{18, 0, 244}, - dictWord{18, 0, 245}, - dictWord{18, 0, 248}, - dictWord{18, 0, 249}, - dictWord{18, 0, 250}, - dictWord{18, 0, 251}, - dictWord{18, 0, 252}, - dictWord{ - 18, - 0, - 253, - }, - dictWord{18, 0, 254}, - dictWord{18, 0, 255}, - dictWord{20, 0, 125}, - dictWord{20, 0, 126}, - dictWord{148, 0, 127}, - dictWord{7, 11, 1717}, - dictWord{ - 7, - 11, - 1769, - }, - dictWord{138, 11, 546}, - dictWord{7, 11, 1127}, - dictWord{7, 11, 1572}, - dictWord{10, 11, 297}, - dictWord{10, 11, 422}, - dictWord{11, 11, 764}, - dictWord{11, 11, 810}, - dictWord{12, 11, 264}, - dictWord{13, 11, 102}, - dictWord{13, 11, 300}, - dictWord{13, 11, 484}, - dictWord{14, 11, 147}, - dictWord{ - 14, - 11, - 229, - }, - dictWord{17, 11, 71}, - dictWord{18, 11, 118}, - dictWord{147, 11, 120}, - dictWord{6, 0, 1148}, - dictWord{134, 0, 1586}, - dictWord{132, 0, 775}, - dictWord{135, 10, 954}, - dictWord{133, 11, 864}, - dictWord{133, 11, 928}, - dictWord{138, 11, 189}, - dictWord{135, 10, 1958}, - dictWord{6, 10, 549}, - dictWord{ - 8, - 10, - 34, - }, - dictWord{8, 10, 283}, - dictWord{9, 10, 165}, - dictWord{138, 10, 475}, - dictWord{5, 10, 652}, - dictWord{5, 10, 701}, - dictWord{135, 10, 449}, - dictWord{135, 11, 695}, - dictWord{4, 10, 655}, - dictWord{7, 10, 850}, - dictWord{17, 10, 75}, - dictWord{146, 10, 137}, - dictWord{140, 11, 682}, - dictWord{ - 133, - 11, - 523, - }, - dictWord{8, 0, 970}, - dictWord{136, 10, 670}, - dictWord{136, 11, 555}, - dictWord{7, 11, 76}, - dictWord{8, 11, 44}, - dictWord{9, 11, 884}, - dictWord{ - 10, - 11, - 580, - }, - dictWord{11, 11, 399}, - dictWord{11, 11, 894}, - dictWord{15, 11, 122}, - dictWord{18, 11, 144}, - dictWord{147, 11, 61}, - dictWord{6, 10, 159}, - dictWord{ - 6, - 10, - 364, - }, - dictWord{7, 10, 516}, - dictWord{7, 10, 1439}, - dictWord{137, 10, 518}, - dictWord{4, 0, 71}, - dictWord{5, 0, 376}, - dictWord{7, 0, 119}, - dictWord{ - 138, - 0, - 665, - }, - dictWord{141, 10, 151}, - dictWord{11, 0, 827}, - dictWord{14, 0, 34}, - dictWord{143, 0, 148}, - dictWord{133, 11, 518}, - dictWord{4, 0, 479}, - dictWord{ - 135, - 11, - 1787, - }, - dictWord{135, 11, 1852}, - dictWord{135, 10, 993}, - dictWord{7, 0, 607}, - dictWord{136, 0, 99}, - dictWord{134, 0, 1960}, - dictWord{132, 0, 793}, - dictWord{4, 0, 41}, - dictWord{5, 0, 74}, - dictWord{7, 0, 1627}, - dictWord{11, 0, 871}, - dictWord{140, 0, 619}, - dictWord{7, 0, 94}, - dictWord{11, 0, 329}, - dictWord{ - 11, - 0, - 965, - }, - dictWord{12, 0, 241}, - dictWord{14, 0, 354}, - dictWord{15, 0, 22}, - dictWord{148, 0, 63}, - dictWord{7, 10, 501}, - dictWord{9, 10, 111}, - dictWord{10, 10, 141}, - dictWord{11, 10, 332}, - dictWord{13, 10, 43}, - dictWord{13, 10, 429}, - dictWord{14, 10, 130}, - dictWord{14, 10, 415}, - dictWord{145, 10, 102}, - dictWord{ - 9, - 0, - 209, - }, - dictWord{137, 0, 300}, - dictWord{134, 0, 1497}, - dictWord{138, 11, 255}, - dictWord{4, 11, 934}, - dictWord{5, 11, 138}, - dictWord{136, 11, 610}, - dictWord{133, 0, 98}, - dictWord{6, 0, 1316}, - dictWord{10, 11, 804}, - dictWord{138, 11, 832}, - dictWord{8, 11, 96}, - dictWord{9, 11, 36}, - dictWord{10, 11, 607}, - dictWord{11, 11, 423}, - dictWord{11, 11, 442}, - dictWord{12, 11, 309}, - dictWord{14, 11, 199}, - dictWord{15, 11, 90}, - dictWord{145, 11, 110}, - dictWord{ - 132, - 0, - 463, - }, - dictWord{5, 10, 149}, - dictWord{136, 10, 233}, - dictWord{133, 10, 935}, - dictWord{4, 11, 652}, - dictWord{8, 11, 320}, - dictWord{9, 11, 13}, - dictWord{ - 9, - 11, - 398, - }, - dictWord{9, 11, 727}, - dictWord{10, 11, 75}, - dictWord{10, 11, 184}, - dictWord{10, 11, 230}, - dictWord{10, 11, 564}, - dictWord{10, 11, 569}, - dictWord{ - 11, - 11, - 973, - }, - dictWord{12, 11, 70}, - dictWord{12, 11, 189}, - dictWord{13, 11, 57}, - dictWord{13, 11, 257}, - dictWord{22, 11, 6}, - dictWord{150, 11, 16}, - dictWord{ - 142, - 0, - 291, - }, - dictWord{12, 10, 582}, - dictWord{146, 10, 131}, - dictWord{136, 10, 801}, - dictWord{133, 0, 984}, - dictWord{145, 11, 116}, - dictWord{4, 11, 692}, - dictWord{133, 11, 321}, - dictWord{4, 0, 182}, - dictWord{6, 0, 205}, - dictWord{135, 0, 220}, - dictWord{4, 0, 42}, - dictWord{9, 0, 205}, - dictWord{9, 0, 786}, - dictWord{ - 138, - 0, - 659, - }, - dictWord{6, 0, 801}, - dictWord{11, 11, 130}, - dictWord{140, 11, 609}, - dictWord{132, 0, 635}, - dictWord{5, 11, 345}, - dictWord{135, 11, 1016}, - dictWord{139, 0, 533}, - dictWord{132, 0, 371}, - dictWord{4, 0, 272}, - dictWord{135, 0, 836}, - dictWord{6, 0, 1282}, - dictWord{135, 11, 1100}, - dictWord{5, 0, 825}, - dictWord{134, 0, 1640}, - dictWord{135, 11, 1325}, - dictWord{133, 11, 673}, - dictWord{4, 11, 287}, - dictWord{133, 11, 1018}, - dictWord{135, 0, 357}, - dictWord{ - 6, - 0, - 467, - }, - dictWord{137, 0, 879}, - dictWord{7, 0, 317}, - dictWord{135, 0, 569}, - dictWord{6, 0, 924}, - dictWord{134, 0, 1588}, - dictWord{5, 11, 34}, - dictWord{ - 5, - 10, - 406, - }, - dictWord{10, 11, 724}, - dictWord{12, 11, 444}, - dictWord{13, 11, 354}, - dictWord{18, 11, 32}, - dictWord{23, 11, 24}, - dictWord{23, 11, 31}, - dictWord{ - 152, - 11, - 5, - }, - dictWord{6, 0, 1795}, - dictWord{6, 0, 1835}, - dictWord{6, 0, 1836}, - dictWord{6, 0, 1856}, - dictWord{8, 0, 844}, - dictWord{8, 0, 849}, - dictWord{8, 0, 854}, - dictWord{8, 0, 870}, - dictWord{8, 0, 887}, - dictWord{10, 0, 852}, - dictWord{138, 0, 942}, - dictWord{6, 10, 69}, - dictWord{135, 10, 117}, - dictWord{137, 0, 307}, - dictWord{ - 4, - 0, - 944, - }, - dictWord{6, 0, 1799}, - dictWord{6, 0, 1825}, - dictWord{10, 0, 848}, - dictWord{10, 0, 875}, - dictWord{10, 0, 895}, - dictWord{10, 0, 899}, - dictWord{ - 10, - 0, - 902, - }, - dictWord{140, 0, 773}, - dictWord{11, 0, 43}, - dictWord{13, 0, 72}, - dictWord{141, 0, 142}, - dictWord{135, 10, 1830}, - dictWord{134, 11, 382}, - dictWord{ - 4, - 10, - 432, - }, - dictWord{135, 10, 824}, - dictWord{132, 11, 329}, - dictWord{7, 0, 1820}, - dictWord{139, 11, 124}, - dictWord{133, 10, 826}, - dictWord{ - 133, - 0, - 525, - }, - dictWord{132, 11, 906}, - dictWord{7, 11, 1940}, - dictWord{136, 11, 366}, - dictWord{138, 11, 10}, - dictWord{4, 11, 123}, - dictWord{4, 11, 649}, - dictWord{ - 5, - 11, - 605, - }, - dictWord{7, 11, 1509}, - dictWord{136, 11, 36}, - dictWord{6, 0, 110}, - dictWord{135, 0, 1681}, - dictWord{133, 0, 493}, - dictWord{133, 11, 767}, - dictWord{4, 0, 174}, - dictWord{135, 0, 911}, - dictWord{138, 11, 786}, - dictWord{8, 0, 417}, - dictWord{137, 0, 782}, - dictWord{133, 10, 1000}, - dictWord{7, 0, 733}, - dictWord{137, 0, 583}, - dictWord{4, 10, 297}, - dictWord{6, 10, 529}, - dictWord{7, 10, 152}, - dictWord{7, 10, 713}, - dictWord{7, 10, 1845}, - dictWord{8, 10, 710}, - dictWord{8, 10, 717}, - dictWord{12, 10, 639}, - dictWord{140, 10, 685}, - dictWord{4, 0, 32}, - dictWord{5, 0, 215}, - dictWord{6, 0, 269}, - dictWord{7, 0, 1782}, - dictWord{ - 7, - 0, - 1892, - }, - dictWord{10, 0, 16}, - dictWord{11, 0, 822}, - dictWord{11, 0, 954}, - dictWord{141, 0, 481}, - dictWord{4, 11, 273}, - dictWord{5, 11, 658}, - dictWord{ - 133, - 11, - 995, - }, - dictWord{136, 0, 477}, - dictWord{134, 11, 72}, - dictWord{135, 11, 1345}, - dictWord{5, 0, 308}, - dictWord{7, 0, 1088}, - dictWord{4, 10, 520}, - dictWord{ - 135, - 10, - 575, - }, - dictWord{133, 11, 589}, - dictWord{5, 0, 126}, - dictWord{8, 0, 297}, - dictWord{9, 0, 366}, - dictWord{140, 0, 374}, - dictWord{7, 0, 1551}, - dictWord{ - 139, - 0, - 361, - }, - dictWord{5, 11, 117}, - dictWord{6, 11, 514}, - dictWord{6, 11, 541}, - dictWord{7, 11, 1164}, - dictWord{7, 11, 1436}, - dictWord{8, 11, 220}, - dictWord{ - 8, - 11, - 648, - }, - dictWord{10, 11, 688}, - dictWord{139, 11, 560}, - dictWord{133, 11, 686}, - dictWord{4, 0, 946}, - dictWord{6, 0, 1807}, - dictWord{8, 0, 871}, - dictWord{ - 10, - 0, - 854, - }, - dictWord{10, 0, 870}, - dictWord{10, 0, 888}, - dictWord{10, 0, 897}, - dictWord{10, 0, 920}, - dictWord{12, 0, 722}, - dictWord{12, 0, 761}, - dictWord{ - 12, - 0, - 763, - }, - dictWord{12, 0, 764}, - dictWord{14, 0, 454}, - dictWord{14, 0, 465}, - dictWord{16, 0, 107}, - dictWord{18, 0, 167}, - dictWord{18, 0, 168}, - dictWord{ - 146, - 0, - 172, - }, - dictWord{132, 0, 175}, - dictWord{135, 0, 1307}, - dictWord{132, 0, 685}, - dictWord{135, 11, 1834}, - dictWord{133, 0, 797}, - dictWord{6, 0, 745}, - dictWord{ - 6, - 0, - 858, - }, - dictWord{134, 0, 963}, - dictWord{133, 0, 565}, - dictWord{5, 10, 397}, - dictWord{6, 10, 154}, - dictWord{7, 11, 196}, - dictWord{7, 10, 676}, - dictWord{ - 8, - 10, - 443, - }, - dictWord{8, 10, 609}, - dictWord{9, 10, 24}, - dictWord{9, 10, 325}, - dictWord{10, 10, 35}, - dictWord{10, 11, 765}, - dictWord{11, 11, 347}, - dictWord{ - 11, - 10, - 535, - }, - dictWord{11, 11, 552}, - dictWord{11, 11, 576}, - dictWord{11, 10, 672}, - dictWord{11, 11, 790}, - dictWord{11, 10, 1018}, - dictWord{12, 11, 263}, - dictWord{12, 10, 637}, - dictWord{13, 11, 246}, - dictWord{13, 11, 270}, - dictWord{13, 11, 395}, - dictWord{14, 11, 74}, - dictWord{14, 11, 176}, - dictWord{ - 14, - 11, - 190, - }, - dictWord{14, 11, 398}, - dictWord{14, 11, 412}, - dictWord{15, 11, 32}, - dictWord{15, 11, 63}, - dictWord{16, 10, 30}, - dictWord{16, 11, 88}, - dictWord{ - 147, - 11, - 105, - }, - dictWord{13, 11, 84}, - dictWord{141, 11, 122}, - dictWord{4, 0, 252}, - dictWord{7, 0, 1068}, - dictWord{10, 0, 434}, - dictWord{11, 0, 228}, - dictWord{ - 11, - 0, - 426, - }, - dictWord{13, 0, 231}, - dictWord{18, 0, 106}, - dictWord{148, 0, 87}, - dictWord{137, 0, 826}, - dictWord{4, 11, 589}, - dictWord{139, 11, 282}, - dictWord{ - 5, - 11, - 381, - }, - dictWord{135, 11, 1792}, - dictWord{132, 0, 791}, - dictWord{5, 0, 231}, - dictWord{10, 0, 509}, - dictWord{133, 10, 981}, - dictWord{7, 0, 601}, - dictWord{ - 9, - 0, - 277, - }, - dictWord{9, 0, 674}, - dictWord{10, 0, 178}, - dictWord{10, 0, 418}, - dictWord{10, 0, 571}, - dictWord{11, 0, 531}, - dictWord{12, 0, 113}, - dictWord{12, 0, 475}, - dictWord{13, 0, 99}, - dictWord{142, 0, 428}, - dictWord{4, 10, 56}, - dictWord{7, 11, 616}, - dictWord{7, 10, 1791}, - dictWord{8, 10, 607}, - dictWord{8, 10, 651}, - dictWord{10, 11, 413}, - dictWord{11, 10, 465}, - dictWord{11, 10, 835}, - dictWord{12, 10, 337}, - dictWord{141, 10, 480}, - dictWord{7, 0, 1591}, - dictWord{144, 0, 43}, - dictWord{9, 10, 158}, - dictWord{138, 10, 411}, - dictWord{135, 0, 1683}, - dictWord{8, 0, 289}, - dictWord{11, 0, 45}, - dictWord{12, 0, 278}, - dictWord{140, 0, 537}, - dictWord{6, 11, 120}, - dictWord{7, 11, 1188}, - dictWord{7, 11, 1710}, - dictWord{8, 11, 286}, - dictWord{9, 11, 667}, - dictWord{11, 11, 592}, - dictWord{ - 139, - 11, - 730, - }, - dictWord{136, 10, 617}, - dictWord{135, 0, 1120}, - dictWord{135, 11, 1146}, - dictWord{139, 10, 563}, - dictWord{4, 11, 352}, - dictWord{4, 10, 369}, - dictWord{135, 11, 687}, - dictWord{143, 11, 38}, - dictWord{4, 0, 399}, - dictWord{5, 0, 119}, - dictWord{5, 0, 494}, - dictWord{7, 0, 751}, - dictWord{9, 0, 556}, - dictWord{ - 14, - 11, - 179, - }, - dictWord{15, 11, 151}, - dictWord{150, 11, 11}, - dictWord{4, 11, 192}, - dictWord{5, 11, 49}, - dictWord{6, 11, 200}, - dictWord{6, 11, 293}, - dictWord{ - 6, - 11, - 1696, - }, - dictWord{135, 11, 488}, - dictWord{4, 0, 398}, - dictWord{133, 0, 660}, - dictWord{7, 0, 1030}, - dictWord{134, 10, 622}, - dictWord{135, 11, 595}, - dictWord{141, 0, 168}, - dictWord{132, 11, 147}, - dictWord{7, 0, 973}, - dictWord{10, 10, 624}, - dictWord{142, 10, 279}, - dictWord{132, 10, 363}, - dictWord{ - 132, - 0, - 642, - }, - dictWord{133, 11, 934}, - dictWord{134, 0, 1615}, - dictWord{7, 11, 505}, - dictWord{135, 11, 523}, - dictWord{7, 0, 594}, - dictWord{7, 0, 851}, - dictWord{ - 7, - 0, - 1858, - }, - dictWord{9, 0, 411}, - dictWord{9, 0, 574}, - dictWord{9, 0, 666}, - dictWord{9, 0, 737}, - dictWord{10, 0, 346}, - dictWord{10, 0, 712}, - dictWord{11, 0, 246}, - dictWord{11, 0, 432}, - dictWord{11, 0, 517}, - dictWord{11, 0, 647}, - dictWord{11, 0, 679}, - dictWord{11, 0, 727}, - dictWord{12, 0, 304}, - dictWord{12, 0, 305}, - dictWord{ - 12, - 0, - 323, - }, - dictWord{12, 0, 483}, - dictWord{12, 0, 572}, - dictWord{12, 0, 593}, - dictWord{12, 0, 602}, - dictWord{13, 0, 95}, - dictWord{13, 0, 101}, - dictWord{ - 13, - 0, - 171, - }, - dictWord{13, 0, 315}, - dictWord{13, 0, 378}, - dictWord{13, 0, 425}, - dictWord{13, 0, 475}, - dictWord{14, 0, 63}, - dictWord{14, 0, 380}, - dictWord{14, 0, 384}, - dictWord{15, 0, 133}, - dictWord{18, 0, 112}, - dictWord{148, 0, 72}, - dictWord{135, 0, 1093}, - dictWord{132, 0, 679}, - dictWord{8, 0, 913}, - dictWord{10, 0, 903}, - dictWord{10, 0, 915}, - dictWord{12, 0, 648}, - dictWord{12, 0, 649}, - dictWord{14, 0, 455}, - dictWord{16, 0, 112}, - dictWord{138, 11, 438}, - dictWord{137, 0, 203}, - dictWord{134, 10, 292}, - dictWord{134, 0, 1492}, - dictWord{7, 0, 1374}, - dictWord{8, 0, 540}, - dictWord{5, 10, 177}, - dictWord{6, 10, 616}, - dictWord{7, 10, 827}, - dictWord{9, 10, 525}, - dictWord{138, 10, 656}, - dictWord{135, 0, 1486}, - dictWord{9, 0, 714}, - dictWord{138, 10, 31}, - dictWord{136, 0, 825}, - dictWord{ - 134, - 0, - 1511, - }, - dictWord{132, 11, 637}, - dictWord{134, 0, 952}, - dictWord{4, 10, 161}, - dictWord{133, 10, 631}, - dictWord{5, 0, 143}, - dictWord{5, 0, 769}, - dictWord{ - 6, - 0, - 1760, - }, - dictWord{7, 0, 682}, - dictWord{7, 0, 1992}, - dictWord{136, 0, 736}, - dictWord{132, 0, 700}, - dictWord{134, 0, 1540}, - dictWord{132, 11, 777}, - dictWord{ - 9, - 11, - 867, - }, - dictWord{138, 11, 837}, - dictWord{7, 0, 1557}, - dictWord{135, 10, 1684}, - dictWord{133, 0, 860}, - dictWord{6, 0, 422}, - dictWord{7, 0, 0}, - dictWord{ - 7, - 0, - 1544, - }, - dictWord{9, 0, 605}, - dictWord{11, 0, 990}, - dictWord{12, 0, 235}, - dictWord{12, 0, 453}, - dictWord{13, 0, 47}, - dictWord{13, 0, 266}, - dictWord{9, 10, 469}, - dictWord{9, 10, 709}, - dictWord{12, 10, 512}, - dictWord{14, 10, 65}, - dictWord{145, 10, 12}, - dictWord{11, 0, 807}, - dictWord{10, 10, 229}, - dictWord{11, 10, 73}, - dictWord{139, 10, 376}, - dictWord{6, 11, 170}, - dictWord{7, 11, 1080}, - dictWord{8, 11, 395}, - dictWord{8, 11, 487}, - dictWord{11, 11, 125}, - dictWord{ - 141, - 11, - 147, - }, - dictWord{5, 0, 515}, - dictWord{137, 0, 131}, - dictWord{7, 0, 1605}, - dictWord{11, 0, 962}, - dictWord{146, 0, 139}, - dictWord{132, 0, 646}, - dictWord{ - 4, - 0, - 396, - }, - dictWord{7, 0, 728}, - dictWord{9, 0, 117}, - dictWord{13, 0, 202}, - dictWord{148, 0, 51}, - dictWord{6, 0, 121}, - dictWord{6, 0, 124}, - dictWord{6, 0, 357}, - dictWord{ - 7, - 0, - 1138, - }, - dictWord{7, 0, 1295}, - dictWord{8, 0, 162}, - dictWord{8, 0, 508}, - dictWord{11, 0, 655}, - dictWord{4, 11, 535}, - dictWord{6, 10, 558}, - dictWord{ - 7, - 10, - 651, - }, - dictWord{8, 11, 618}, - dictWord{9, 10, 0}, - dictWord{10, 10, 34}, - dictWord{139, 10, 1008}, - dictWord{135, 11, 1245}, - dictWord{138, 0, 357}, - dictWord{ - 150, - 11, - 23, - }, - dictWord{133, 0, 237}, - dictWord{135, 0, 1784}, - dictWord{7, 10, 1832}, - dictWord{138, 10, 374}, - dictWord{132, 0, 713}, - dictWord{132, 11, 46}, - dictWord{6, 0, 1536}, - dictWord{10, 0, 348}, - dictWord{5, 11, 811}, - dictWord{6, 11, 1679}, - dictWord{6, 11, 1714}, - dictWord{135, 11, 2032}, - dictWord{ - 11, - 11, - 182, - }, - dictWord{142, 11, 195}, - dictWord{6, 0, 523}, - dictWord{7, 0, 738}, - dictWord{7, 10, 771}, - dictWord{7, 10, 1731}, - dictWord{9, 10, 405}, - dictWord{ - 138, - 10, - 421, - }, - dictWord{7, 11, 1458}, - dictWord{9, 11, 407}, - dictWord{139, 11, 15}, - dictWord{6, 11, 34}, - dictWord{7, 11, 69}, - dictWord{7, 11, 640}, - dictWord{ - 7, - 11, - 1089, - }, - dictWord{8, 11, 708}, - dictWord{8, 11, 721}, - dictWord{9, 11, 363}, - dictWord{9, 11, 643}, - dictWord{10, 11, 628}, - dictWord{148, 11, 98}, - dictWord{ - 133, - 0, - 434, - }, - dictWord{135, 0, 1877}, - dictWord{7, 0, 571}, - dictWord{138, 0, 366}, - dictWord{5, 10, 881}, - dictWord{133, 10, 885}, - dictWord{9, 0, 513}, - dictWord{ - 10, - 0, - 25, - }, - dictWord{10, 0, 39}, - dictWord{12, 0, 122}, - dictWord{140, 0, 187}, - dictWord{132, 0, 580}, - dictWord{5, 10, 142}, - dictWord{134, 10, 546}, - dictWord{ - 132, - 11, - 462, - }, - dictWord{137, 0, 873}, - dictWord{5, 10, 466}, - dictWord{11, 10, 571}, - dictWord{12, 10, 198}, - dictWord{13, 10, 283}, - dictWord{14, 10, 186}, - dictWord{15, 10, 21}, - dictWord{143, 10, 103}, - dictWord{7, 0, 171}, - dictWord{4, 10, 185}, - dictWord{5, 10, 257}, - dictWord{5, 10, 839}, - dictWord{5, 10, 936}, - dictWord{ - 9, - 10, - 399, - }, - dictWord{10, 10, 258}, - dictWord{10, 10, 395}, - dictWord{10, 10, 734}, - dictWord{11, 10, 1014}, - dictWord{12, 10, 23}, - dictWord{13, 10, 350}, - dictWord{14, 10, 150}, - dictWord{147, 10, 6}, - dictWord{134, 0, 625}, - dictWord{7, 0, 107}, - dictWord{7, 0, 838}, - dictWord{8, 0, 550}, - dictWord{138, 0, 401}, - dictWord{ - 5, - 11, - 73, - }, - dictWord{6, 11, 23}, - dictWord{134, 11, 338}, - dictWord{4, 0, 943}, - dictWord{6, 0, 1850}, - dictWord{12, 0, 713}, - dictWord{142, 0, 434}, - dictWord{ - 11, - 0, - 588, - }, - dictWord{11, 0, 864}, - dictWord{11, 0, 936}, - dictWord{11, 0, 968}, - dictWord{12, 0, 73}, - dictWord{12, 0, 343}, - dictWord{12, 0, 394}, - dictWord{13, 0, 275}, - dictWord{14, 0, 257}, - dictWord{15, 0, 160}, - dictWord{7, 10, 404}, - dictWord{7, 10, 1377}, - dictWord{7, 10, 1430}, - dictWord{7, 10, 2017}, - dictWord{8, 10, 149}, - dictWord{8, 10, 239}, - dictWord{8, 10, 512}, - dictWord{8, 10, 793}, - dictWord{8, 10, 818}, - dictWord{9, 10, 474}, - dictWord{9, 10, 595}, - dictWord{10, 10, 122}, - dictWord{10, 10, 565}, - dictWord{10, 10, 649}, - dictWord{10, 10, 783}, - dictWord{11, 10, 239}, - dictWord{11, 10, 295}, - dictWord{11, 10, 447}, - dictWord{ - 11, - 10, - 528, - }, - dictWord{11, 10, 639}, - dictWord{11, 10, 800}, - dictWord{12, 10, 25}, - dictWord{12, 10, 157}, - dictWord{12, 10, 316}, - dictWord{12, 10, 390}, - dictWord{ - 12, - 10, - 391, - }, - dictWord{12, 10, 395}, - dictWord{12, 10, 478}, - dictWord{12, 10, 503}, - dictWord{12, 10, 592}, - dictWord{12, 10, 680}, - dictWord{13, 10, 50}, - dictWord{13, 10, 53}, - dictWord{13, 10, 132}, - dictWord{13, 10, 198}, - dictWord{13, 10, 322}, - dictWord{13, 10, 415}, - dictWord{13, 10, 511}, - dictWord{14, 10, 71}, - dictWord{14, 10, 395}, - dictWord{15, 10, 71}, - dictWord{15, 10, 136}, - dictWord{17, 10, 123}, - dictWord{18, 10, 93}, - dictWord{147, 10, 58}, - dictWord{ - 133, - 0, - 768, - }, - dictWord{11, 0, 103}, - dictWord{142, 0, 0}, - dictWord{136, 10, 712}, - dictWord{132, 0, 799}, - dictWord{132, 0, 894}, - dictWord{7, 11, 725}, - dictWord{ - 8, - 11, - 498, - }, - dictWord{139, 11, 268}, - dictWord{135, 11, 1798}, - dictWord{135, 11, 773}, - dictWord{141, 11, 360}, - dictWord{4, 10, 377}, - dictWord{152, 10, 13}, - dictWord{135, 0, 1673}, - dictWord{132, 11, 583}, - dictWord{134, 0, 1052}, - dictWord{133, 11, 220}, - dictWord{140, 11, 69}, - dictWord{132, 11, 544}, - dictWord{ - 4, - 10, - 180, - }, - dictWord{135, 10, 1906}, - dictWord{134, 0, 272}, - dictWord{4, 0, 441}, - dictWord{134, 0, 1421}, - dictWord{4, 0, 9}, - dictWord{5, 0, 128}, - dictWord{ - 7, - 0, - 368, - }, - dictWord{11, 0, 480}, - dictWord{148, 0, 3}, - dictWord{5, 11, 176}, - dictWord{6, 11, 437}, - dictWord{6, 11, 564}, - dictWord{11, 11, 181}, - dictWord{ - 141, - 11, - 183, - }, - dictWord{132, 10, 491}, - dictWord{7, 0, 1182}, - dictWord{141, 11, 67}, - dictWord{6, 0, 1346}, - dictWord{4, 10, 171}, - dictWord{138, 10, 234}, - dictWord{ - 4, - 10, - 586, - }, - dictWord{7, 10, 1186}, - dictWord{138, 10, 631}, - dictWord{136, 0, 682}, - dictWord{134, 0, 1004}, - dictWord{15, 0, 24}, - dictWord{143, 11, 24}, - dictWord{134, 0, 968}, - dictWord{4, 0, 2}, - dictWord{6, 0, 742}, - dictWord{6, 0, 793}, - dictWord{7, 0, 545}, - dictWord{7, 0, 894}, - dictWord{9, 10, 931}, - dictWord{ - 10, - 10, - 334, - }, - dictWord{148, 10, 71}, - dictWord{136, 11, 600}, - dictWord{133, 10, 765}, - dictWord{9, 0, 769}, - dictWord{140, 0, 185}, - dictWord{4, 11, 790}, - dictWord{ - 5, - 11, - 273, - }, - dictWord{134, 11, 394}, - dictWord{7, 0, 474}, - dictWord{137, 0, 578}, - dictWord{4, 11, 135}, - dictWord{6, 11, 127}, - dictWord{7, 11, 1185}, - dictWord{ - 7, - 11, - 1511, - }, - dictWord{8, 11, 613}, - dictWord{11, 11, 5}, - dictWord{12, 11, 133}, - dictWord{12, 11, 495}, - dictWord{12, 11, 586}, - dictWord{14, 11, 385}, - dictWord{15, 11, 118}, - dictWord{17, 11, 20}, - dictWord{146, 11, 98}, - dictWord{133, 10, 424}, - dictWord{5, 0, 530}, - dictWord{142, 0, 113}, - dictWord{6, 11, 230}, - dictWord{7, 11, 961}, - dictWord{7, 11, 1085}, - dictWord{136, 11, 462}, - dictWord{7, 11, 1954}, - dictWord{137, 11, 636}, - dictWord{136, 10, 714}, - dictWord{ - 149, - 11, - 6, - }, - dictWord{135, 10, 685}, - dictWord{9, 10, 420}, - dictWord{10, 10, 269}, - dictWord{10, 10, 285}, - dictWord{10, 10, 576}, - dictWord{11, 10, 397}, - dictWord{13, 10, 175}, - dictWord{145, 10, 90}, - dictWord{132, 10, 429}, - dictWord{5, 0, 556}, - dictWord{5, 11, 162}, - dictWord{136, 11, 68}, - dictWord{132, 11, 654}, - dictWord{4, 11, 156}, - dictWord{7, 11, 998}, - dictWord{7, 11, 1045}, - dictWord{7, 11, 1860}, - dictWord{9, 11, 48}, - dictWord{9, 11, 692}, - dictWord{11, 11, 419}, - dictWord{139, 11, 602}, - dictWord{6, 0, 1317}, - dictWord{8, 0, 16}, - dictWord{9, 0, 825}, - dictWord{12, 0, 568}, - dictWord{7, 11, 1276}, - dictWord{8, 11, 474}, - dictWord{137, 11, 652}, - dictWord{18, 0, 97}, - dictWord{7, 10, 18}, - dictWord{7, 10, 699}, - dictWord{7, 10, 1966}, - dictWord{8, 10, 752}, - dictWord{9, 10, 273}, - dictWord{ - 9, - 10, - 412, - }, - dictWord{9, 10, 703}, - dictWord{10, 10, 71}, - dictWord{10, 10, 427}, - dictWord{138, 10, 508}, - dictWord{10, 0, 703}, - dictWord{7, 11, 1454}, - dictWord{138, 11, 703}, - dictWord{4, 10, 53}, - dictWord{5, 10, 186}, - dictWord{135, 10, 752}, - dictWord{134, 0, 892}, - dictWord{134, 0, 1571}, - dictWord{8, 10, 575}, - dictWord{10, 10, 289}, - dictWord{139, 10, 319}, - dictWord{6, 0, 186}, - dictWord{137, 0, 426}, - dictWord{134, 0, 1101}, - dictWord{132, 10, 675}, - dictWord{ - 132, - 0, - 585, - }, - dictWord{6, 0, 1870}, - dictWord{137, 0, 937}, - dictWord{152, 11, 10}, - dictWord{9, 11, 197}, - dictWord{10, 11, 300}, - dictWord{12, 11, 473}, - dictWord{ - 13, - 11, - 90, - }, - dictWord{141, 11, 405}, - dictWord{4, 0, 93}, - dictWord{5, 0, 252}, - dictWord{6, 0, 229}, - dictWord{7, 0, 291}, - dictWord{9, 0, 550}, - dictWord{139, 0, 644}, - dictWord{137, 0, 749}, - dictWord{9, 0, 162}, - dictWord{6, 10, 209}, - dictWord{8, 10, 468}, - dictWord{9, 10, 210}, - dictWord{11, 10, 36}, - dictWord{12, 10, 28}, - dictWord{12, 10, 630}, - dictWord{13, 10, 21}, - dictWord{13, 10, 349}, - dictWord{14, 10, 7}, - dictWord{145, 10, 13}, - dictWord{132, 0, 381}, - dictWord{132, 11, 606}, - dictWord{4, 10, 342}, - dictWord{135, 10, 1179}, - dictWord{7, 11, 1587}, - dictWord{7, 11, 1707}, - dictWord{10, 11, 528}, - dictWord{139, 11, 504}, - dictWord{ - 12, - 11, - 39, - }, - dictWord{13, 11, 265}, - dictWord{141, 11, 439}, - dictWord{4, 10, 928}, - dictWord{133, 10, 910}, - dictWord{7, 10, 1838}, - dictWord{7, 11, 1978}, - dictWord{136, 11, 676}, - dictWord{6, 0, 762}, - dictWord{6, 0, 796}, - dictWord{134, 0, 956}, - dictWord{4, 10, 318}, - dictWord{4, 10, 496}, - dictWord{7, 10, 856}, - dictWord{139, 10, 654}, - dictWord{137, 11, 242}, - dictWord{4, 11, 361}, - dictWord{133, 11, 315}, - dictWord{132, 11, 461}, - dictWord{132, 11, 472}, - dictWord{ - 132, - 0, - 857, - }, - dictWord{5, 0, 21}, - dictWord{6, 0, 77}, - dictWord{6, 0, 157}, - dictWord{7, 0, 974}, - dictWord{7, 0, 1301}, - dictWord{7, 0, 1339}, - dictWord{7, 0, 1490}, - dictWord{ - 7, - 0, - 1873, - }, - dictWord{9, 0, 628}, - dictWord{7, 10, 915}, - dictWord{8, 10, 247}, - dictWord{147, 10, 0}, - dictWord{4, 10, 202}, - dictWord{5, 10, 382}, - dictWord{ - 6, - 10, - 454, - }, - dictWord{7, 10, 936}, - dictWord{7, 10, 1803}, - dictWord{8, 10, 758}, - dictWord{9, 10, 375}, - dictWord{9, 10, 895}, - dictWord{10, 10, 743}, - dictWord{ - 10, - 10, - 792, - }, - dictWord{11, 10, 978}, - dictWord{11, 10, 1012}, - dictWord{142, 10, 109}, - dictWord{7, 11, 617}, - dictWord{10, 11, 498}, - dictWord{11, 11, 501}, - dictWord{12, 11, 16}, - dictWord{140, 11, 150}, - dictWord{7, 10, 1150}, - dictWord{7, 10, 1425}, - dictWord{7, 10, 1453}, - dictWord{10, 11, 747}, - dictWord{ - 140, - 10, - 513, - }, - dictWord{133, 11, 155}, - dictWord{11, 0, 919}, - dictWord{141, 0, 409}, - dictWord{138, 10, 791}, - dictWord{10, 0, 633}, - dictWord{139, 11, 729}, - dictWord{ - 7, - 11, - 163, - }, - dictWord{8, 11, 319}, - dictWord{9, 11, 402}, - dictWord{10, 11, 24}, - dictWord{10, 11, 681}, - dictWord{11, 11, 200}, - dictWord{11, 11, 567}, - dictWord{12, 11, 253}, - dictWord{12, 11, 410}, - dictWord{142, 11, 219}, - dictWord{5, 11, 475}, - dictWord{7, 11, 1780}, - dictWord{9, 11, 230}, - dictWord{11, 11, 297}, - dictWord{11, 11, 558}, - dictWord{14, 11, 322}, - dictWord{147, 11, 76}, - dictWord{7, 0, 332}, - dictWord{6, 10, 445}, - dictWord{137, 10, 909}, - dictWord{ - 135, - 11, - 1956, - }, - dictWord{136, 11, 274}, - dictWord{134, 10, 578}, - dictWord{135, 0, 1489}, - dictWord{135, 11, 1848}, - dictWord{5, 11, 944}, - dictWord{ - 134, - 11, - 1769, - }, - dictWord{132, 11, 144}, - dictWord{136, 10, 766}, - dictWord{4, 0, 832}, - dictWord{135, 10, 541}, - dictWord{8, 0, 398}, - dictWord{9, 0, 681}, - dictWord{ - 139, - 0, - 632, - }, - dictWord{136, 0, 645}, - dictWord{9, 0, 791}, - dictWord{10, 0, 93}, - dictWord{16, 0, 13}, - dictWord{17, 0, 23}, - dictWord{18, 0, 135}, - dictWord{19, 0, 12}, - dictWord{20, 0, 1}, - dictWord{20, 0, 12}, - dictWord{148, 0, 14}, - dictWord{6, 11, 247}, - dictWord{137, 11, 555}, - dictWord{134, 0, 20}, - dictWord{132, 0, 800}, - dictWord{135, 0, 1841}, - dictWord{139, 10, 983}, - dictWord{137, 10, 768}, - dictWord{132, 10, 584}, - dictWord{141, 11, 51}, - dictWord{6, 0, 1993}, - dictWord{ - 4, - 11, - 620, - }, - dictWord{138, 11, 280}, - dictWord{136, 0, 769}, - dictWord{11, 0, 290}, - dictWord{11, 0, 665}, - dictWord{7, 11, 1810}, - dictWord{11, 11, 866}, - dictWord{ - 12, - 11, - 103, - }, - dictWord{13, 11, 495}, - dictWord{17, 11, 67}, - dictWord{147, 11, 74}, - dictWord{134, 0, 1426}, - dictWord{139, 0, 60}, - dictWord{4, 10, 326}, - dictWord{135, 10, 1770}, - dictWord{7, 0, 1874}, - dictWord{9, 0, 641}, - dictWord{132, 10, 226}, - dictWord{6, 0, 644}, - dictWord{5, 10, 426}, - dictWord{8, 10, 30}, - dictWord{ - 9, - 10, - 2, - }, - dictWord{11, 10, 549}, - dictWord{147, 10, 122}, - dictWord{5, 11, 428}, - dictWord{138, 11, 442}, - dictWord{135, 11, 1871}, - dictWord{ - 135, - 0, - 1757, - }, - dictWord{147, 10, 117}, - dictWord{135, 0, 937}, - dictWord{135, 0, 1652}, - dictWord{6, 0, 654}, - dictWord{134, 0, 1476}, - dictWord{133, 11, 99}, - dictWord{135, 0, 527}, - dictWord{132, 10, 345}, - dictWord{4, 10, 385}, - dictWord{4, 11, 397}, - dictWord{7, 10, 265}, - dictWord{135, 10, 587}, - dictWord{4, 0, 579}, - dictWord{5, 0, 226}, - dictWord{5, 0, 323}, - dictWord{135, 0, 960}, - dictWord{134, 0, 1486}, - dictWord{8, 11, 502}, - dictWord{144, 11, 9}, - dictWord{4, 10, 347}, - dictWord{ - 5, - 10, - 423, - }, - dictWord{5, 10, 996}, - dictWord{135, 10, 1329}, - dictWord{7, 11, 727}, - dictWord{146, 11, 73}, - dictWord{4, 11, 485}, - dictWord{7, 11, 353}, - dictWord{7, 10, 1259}, - dictWord{7, 11, 1523}, - dictWord{9, 10, 125}, - dictWord{139, 10, 65}, - dictWord{6, 0, 325}, - dictWord{5, 10, 136}, - dictWord{6, 11, 366}, - dictWord{ - 7, - 11, - 1384, - }, - dictWord{7, 11, 1601}, - dictWord{136, 10, 644}, - dictWord{138, 11, 160}, - dictWord{6, 0, 1345}, - dictWord{137, 11, 282}, - dictWord{18, 0, 91}, - dictWord{147, 0, 70}, - dictWord{136, 0, 404}, - dictWord{4, 11, 157}, - dictWord{133, 11, 471}, - dictWord{133, 0, 973}, - dictWord{6, 0, 135}, - dictWord{ - 135, - 0, - 1176, - }, - dictWord{8, 11, 116}, - dictWord{11, 11, 551}, - dictWord{142, 11, 159}, - dictWord{4, 0, 549}, - dictWord{4, 10, 433}, - dictWord{133, 10, 719}, - dictWord{ - 136, - 0, - 976, - }, - dictWord{5, 11, 160}, - dictWord{7, 11, 363}, - dictWord{7, 11, 589}, - dictWord{10, 11, 170}, - dictWord{141, 11, 55}, - dictWord{144, 0, 21}, - dictWord{ - 144, - 0, - 51, - }, - dictWord{135, 0, 314}, - dictWord{135, 10, 1363}, - dictWord{4, 11, 108}, - dictWord{7, 11, 405}, - dictWord{10, 11, 491}, - dictWord{139, 11, 498}, - dictWord{146, 0, 4}, - dictWord{4, 10, 555}, - dictWord{8, 10, 536}, - dictWord{10, 10, 288}, - dictWord{139, 10, 1005}, - dictWord{135, 11, 1005}, - dictWord{6, 0, 281}, - dictWord{7, 0, 6}, - dictWord{8, 0, 282}, - dictWord{8, 0, 480}, - dictWord{8, 0, 499}, - dictWord{9, 0, 198}, - dictWord{10, 0, 143}, - dictWord{10, 0, 169}, - dictWord{ - 10, - 0, - 211, - }, - dictWord{10, 0, 417}, - dictWord{10, 0, 574}, - dictWord{11, 0, 147}, - dictWord{11, 0, 395}, - dictWord{12, 0, 75}, - dictWord{12, 0, 407}, - dictWord{12, 0, 608}, - dictWord{13, 0, 500}, - dictWord{142, 0, 251}, - dictWord{6, 0, 1093}, - dictWord{6, 0, 1405}, - dictWord{9, 10, 370}, - dictWord{138, 10, 90}, - dictWord{4, 11, 926}, - dictWord{133, 11, 983}, - dictWord{135, 0, 1776}, - dictWord{134, 0, 1528}, - dictWord{132, 0, 419}, - dictWord{132, 11, 538}, - dictWord{6, 11, 294}, - dictWord{ - 7, - 11, - 1267, - }, - dictWord{136, 11, 624}, - dictWord{135, 11, 1772}, - dictWord{138, 11, 301}, - dictWord{4, 10, 257}, - dictWord{135, 10, 2031}, - dictWord{4, 0, 138}, - dictWord{7, 0, 1012}, - dictWord{7, 0, 1280}, - dictWord{9, 0, 76}, - dictWord{135, 10, 1768}, - dictWord{132, 11, 757}, - dictWord{5, 0, 29}, - dictWord{140, 0, 638}, - dictWord{7, 11, 655}, - dictWord{135, 11, 1844}, - dictWord{7, 0, 1418}, - dictWord{6, 11, 257}, - dictWord{135, 11, 1522}, - dictWord{8, 11, 469}, - dictWord{ - 138, - 11, - 47, - }, - dictWord{142, 11, 278}, - dictWord{6, 10, 83}, - dictWord{6, 10, 1733}, - dictWord{135, 10, 1389}, - dictWord{11, 11, 204}, - dictWord{11, 11, 243}, - dictWord{140, 11, 293}, - dictWord{135, 11, 1875}, - dictWord{6, 0, 1710}, - dictWord{135, 0, 2038}, - dictWord{137, 11, 299}, - dictWord{4, 0, 17}, - dictWord{5, 0, 23}, - dictWord{7, 0, 995}, - dictWord{11, 0, 383}, - dictWord{11, 0, 437}, - dictWord{12, 0, 460}, - dictWord{140, 0, 532}, - dictWord{133, 0, 862}, - dictWord{137, 10, 696}, - dictWord{6, 0, 592}, - dictWord{138, 0, 946}, - dictWord{138, 11, 599}, - dictWord{7, 10, 1718}, - dictWord{9, 10, 95}, - dictWord{9, 10, 274}, - dictWord{10, 10, 279}, - dictWord{10, 10, 317}, - dictWord{10, 10, 420}, - dictWord{11, 10, 303}, - dictWord{11, 10, 808}, - dictWord{12, 10, 134}, - dictWord{12, 10, 367}, - dictWord{ - 13, - 10, - 149, - }, - dictWord{13, 10, 347}, - dictWord{14, 10, 349}, - dictWord{14, 10, 406}, - dictWord{18, 10, 22}, - dictWord{18, 10, 89}, - dictWord{18, 10, 122}, - dictWord{ - 147, - 10, - 47, - }, - dictWord{8, 0, 70}, - dictWord{12, 0, 171}, - dictWord{141, 0, 272}, - dictWord{133, 10, 26}, - dictWord{132, 10, 550}, - dictWord{137, 0, 812}, - dictWord{ - 10, - 0, - 233, - }, - dictWord{139, 0, 76}, - dictWord{134, 0, 988}, - dictWord{134, 0, 442}, - dictWord{136, 10, 822}, - dictWord{7, 0, 896}, - dictWord{4, 10, 902}, - dictWord{ - 5, - 10, - 809, - }, - dictWord{134, 10, 122}, - dictWord{5, 11, 150}, - dictWord{7, 11, 106}, - dictWord{8, 11, 603}, - dictWord{9, 11, 593}, - dictWord{9, 11, 634}, - dictWord{ - 10, - 11, - 44, - }, - dictWord{10, 11, 173}, - dictWord{11, 11, 462}, - dictWord{11, 11, 515}, - dictWord{13, 11, 216}, - dictWord{13, 11, 288}, - dictWord{142, 11, 400}, - dictWord{136, 0, 483}, - dictWord{135, 10, 262}, - dictWord{6, 0, 1709}, - dictWord{133, 10, 620}, - dictWord{4, 10, 34}, - dictWord{5, 10, 574}, - dictWord{7, 10, 279}, - dictWord{7, 10, 1624}, - dictWord{136, 10, 601}, - dictWord{137, 10, 170}, - dictWord{147, 0, 119}, - dictWord{12, 11, 108}, - dictWord{141, 11, 291}, - dictWord{ - 11, - 0, - 69, - }, - dictWord{12, 0, 105}, - dictWord{12, 0, 117}, - dictWord{13, 0, 213}, - dictWord{14, 0, 13}, - dictWord{14, 0, 62}, - dictWord{14, 0, 177}, - dictWord{14, 0, 421}, - dictWord{15, 0, 19}, - dictWord{146, 0, 141}, - dictWord{137, 0, 309}, - dictWord{11, 11, 278}, - dictWord{142, 11, 73}, - dictWord{7, 0, 608}, - dictWord{7, 0, 976}, - dictWord{9, 0, 146}, - dictWord{10, 0, 206}, - dictWord{10, 0, 596}, - dictWord{13, 0, 218}, - dictWord{142, 0, 153}, - dictWord{133, 10, 332}, - dictWord{6, 10, 261}, - dictWord{ - 8, - 10, - 182, - }, - dictWord{139, 10, 943}, - dictWord{4, 11, 493}, - dictWord{144, 11, 55}, - dictWord{134, 10, 1721}, - dictWord{132, 0, 768}, - dictWord{4, 10, 933}, - dictWord{133, 10, 880}, - dictWord{7, 11, 555}, - dictWord{7, 11, 1316}, - dictWord{7, 11, 1412}, - dictWord{7, 11, 1839}, - dictWord{9, 11, 192}, - dictWord{ - 9, - 11, - 589, - }, - dictWord{11, 11, 241}, - dictWord{11, 11, 676}, - dictWord{11, 11, 811}, - dictWord{11, 11, 891}, - dictWord{12, 11, 140}, - dictWord{12, 11, 346}, - dictWord{ - 12, - 11, - 479, - }, - dictWord{13, 11, 30}, - dictWord{13, 11, 49}, - dictWord{13, 11, 381}, - dictWord{14, 11, 188}, - dictWord{15, 11, 150}, - dictWord{16, 11, 76}, - dictWord{18, 11, 30}, - dictWord{148, 11, 52}, - dictWord{4, 0, 518}, - dictWord{135, 0, 1136}, - dictWord{6, 11, 568}, - dictWord{7, 11, 112}, - dictWord{7, 11, 1804}, - dictWord{8, 11, 362}, - dictWord{8, 11, 410}, - dictWord{8, 11, 830}, - dictWord{9, 11, 514}, - dictWord{11, 11, 649}, - dictWord{142, 11, 157}, - dictWord{135, 11, 673}, - dictWord{8, 0, 689}, - dictWord{137, 0, 863}, - dictWord{4, 0, 18}, - dictWord{7, 0, 145}, - dictWord{7, 0, 444}, - dictWord{7, 0, 1278}, - dictWord{8, 0, 49}, - dictWord{8, 0, 400}, - dictWord{9, 0, 71}, - dictWord{9, 0, 250}, - dictWord{10, 0, 459}, - dictWord{12, 0, 160}, - dictWord{16, 0, 24}, - dictWord{132, 11, 625}, - dictWord{140, 0, 1020}, - dictWord{4, 0, 997}, - dictWord{6, 0, 1946}, - dictWord{6, 0, 1984}, - dictWord{134, 0, 1998}, - dictWord{6, 11, 16}, - dictWord{6, 11, 158}, - dictWord{7, 11, 43}, - dictWord{ - 7, - 11, - 129, - }, - dictWord{7, 11, 181}, - dictWord{8, 11, 276}, - dictWord{8, 11, 377}, - dictWord{10, 11, 523}, - dictWord{11, 11, 816}, - dictWord{12, 11, 455}, - dictWord{ - 13, - 11, - 303, - }, - dictWord{142, 11, 135}, - dictWord{133, 10, 812}, - dictWord{134, 0, 658}, - dictWord{4, 11, 1}, - dictWord{7, 11, 1143}, - dictWord{7, 11, 1463}, - dictWord{8, 11, 61}, - dictWord{9, 11, 207}, - dictWord{9, 11, 390}, - dictWord{9, 11, 467}, - dictWord{139, 11, 836}, - dictWord{150, 11, 26}, - dictWord{140, 0, 106}, - dictWord{6, 0, 1827}, - dictWord{10, 0, 931}, - dictWord{18, 0, 166}, - dictWord{20, 0, 114}, - dictWord{4, 10, 137}, - dictWord{7, 10, 1178}, - dictWord{7, 11, 1319}, - dictWord{135, 10, 1520}, - dictWord{133, 0, 1010}, - dictWord{4, 11, 723}, - dictWord{5, 11, 895}, - dictWord{7, 11, 1031}, - dictWord{8, 11, 199}, - dictWord{8, 11, 340}, - dictWord{9, 11, 153}, - dictWord{9, 11, 215}, - dictWord{10, 11, 21}, - dictWord{10, 11, 59}, - dictWord{10, 11, 80}, - dictWord{10, 11, 224}, - dictWord{11, 11, 229}, - dictWord{11, 11, 652}, - dictWord{12, 11, 192}, - dictWord{13, 11, 146}, - dictWord{142, 11, 91}, - dictWord{132, 11, 295}, - dictWord{6, 11, 619}, - dictWord{ - 7, - 11, - 898, - }, - dictWord{7, 11, 1092}, - dictWord{8, 11, 485}, - dictWord{18, 11, 28}, - dictWord{147, 11, 116}, - dictWord{137, 11, 51}, - dictWord{6, 10, 1661}, - dictWord{ - 7, - 10, - 1975, - }, - dictWord{7, 10, 2009}, - dictWord{135, 10, 2011}, - dictWord{5, 11, 309}, - dictWord{140, 11, 211}, - dictWord{5, 0, 87}, - dictWord{7, 0, 313}, - dictWord{ - 7, - 0, - 1103, - }, - dictWord{10, 0, 208}, - dictWord{10, 0, 582}, - dictWord{11, 0, 389}, - dictWord{11, 0, 813}, - dictWord{12, 0, 385}, - dictWord{13, 0, 286}, - dictWord{ - 14, - 0, - 124, - }, - dictWord{146, 0, 108}, - dictWord{5, 11, 125}, - dictWord{8, 11, 77}, - dictWord{138, 11, 15}, - dictWord{132, 0, 267}, - dictWord{133, 0, 703}, - dictWord{ - 137, - 11, - 155, - }, - dictWord{133, 11, 439}, - dictWord{11, 11, 164}, - dictWord{140, 11, 76}, - dictWord{9, 0, 496}, - dictWord{5, 10, 89}, - dictWord{7, 10, 1915}, - dictWord{ - 9, - 10, - 185, - }, - dictWord{9, 10, 235}, - dictWord{10, 10, 64}, - dictWord{10, 10, 270}, - dictWord{10, 10, 403}, - dictWord{10, 10, 469}, - dictWord{10, 10, 529}, - dictWord{10, 10, 590}, - dictWord{11, 10, 140}, - dictWord{11, 10, 860}, - dictWord{13, 10, 1}, - dictWord{13, 10, 422}, - dictWord{14, 10, 341}, - dictWord{14, 10, 364}, - dictWord{17, 10, 93}, - dictWord{18, 10, 113}, - dictWord{19, 10, 97}, - dictWord{147, 10, 113}, - dictWord{133, 10, 695}, - dictWord{135, 0, 1121}, - dictWord{ - 5, - 10, - 6, - }, - dictWord{6, 10, 183}, - dictWord{7, 10, 680}, - dictWord{7, 10, 978}, - dictWord{7, 10, 1013}, - dictWord{7, 10, 1055}, - dictWord{12, 10, 230}, - dictWord{ - 13, - 10, - 172, - }, - dictWord{146, 10, 29}, - dictWord{4, 11, 8}, - dictWord{7, 11, 1152}, - dictWord{7, 11, 1153}, - dictWord{7, 11, 1715}, - dictWord{9, 11, 374}, - dictWord{ - 10, - 11, - 478, - }, - dictWord{139, 11, 648}, - dictWord{135, 11, 1099}, - dictWord{6, 10, 29}, - dictWord{139, 10, 63}, - dictWord{4, 0, 561}, - dictWord{10, 0, 249}, - dictWord{ - 139, - 0, - 209, - }, - dictWord{132, 0, 760}, - dictWord{7, 11, 799}, - dictWord{138, 11, 511}, - dictWord{136, 11, 87}, - dictWord{9, 0, 154}, - dictWord{140, 0, 485}, - dictWord{136, 0, 255}, - dictWord{132, 0, 323}, - dictWord{140, 0, 419}, - dictWord{132, 10, 311}, - dictWord{134, 10, 1740}, - dictWord{4, 0, 368}, - dictWord{ - 135, - 0, - 641, - }, - dictWord{7, 10, 170}, - dictWord{8, 10, 90}, - dictWord{8, 10, 177}, - dictWord{8, 10, 415}, - dictWord{11, 10, 714}, - dictWord{142, 10, 281}, - dictWord{ - 4, - 11, - 69, - }, - dictWord{5, 11, 122}, - dictWord{9, 11, 656}, - dictWord{138, 11, 464}, - dictWord{5, 11, 849}, - dictWord{134, 11, 1633}, - dictWord{8, 0, 522}, - dictWord{ - 142, - 0, - 328, - }, - dictWord{11, 10, 91}, - dictWord{13, 10, 129}, - dictWord{15, 10, 101}, - dictWord{145, 10, 125}, - dictWord{7, 0, 562}, - dictWord{8, 0, 551}, - dictWord{ - 4, - 10, - 494, - }, - dictWord{6, 10, 74}, - dictWord{7, 10, 44}, - dictWord{11, 11, 499}, - dictWord{12, 10, 17}, - dictWord{15, 10, 5}, - dictWord{148, 10, 11}, - dictWord{4, 10, 276}, - dictWord{133, 10, 296}, - dictWord{9, 0, 92}, - dictWord{147, 0, 91}, - dictWord{4, 10, 7}, - dictWord{5, 10, 90}, - dictWord{5, 10, 158}, - dictWord{6, 10, 542}, - dictWord{ - 7, - 10, - 221, - }, - dictWord{7, 10, 1574}, - dictWord{9, 10, 490}, - dictWord{10, 10, 540}, - dictWord{11, 10, 443}, - dictWord{139, 10, 757}, - dictWord{6, 0, 525}, - dictWord{ - 6, - 0, - 1976, - }, - dictWord{8, 0, 806}, - dictWord{9, 0, 876}, - dictWord{140, 0, 284}, - dictWord{5, 11, 859}, - dictWord{7, 10, 588}, - dictWord{7, 11, 1160}, - dictWord{ - 8, - 11, - 107, - }, - dictWord{9, 10, 175}, - dictWord{9, 11, 291}, - dictWord{9, 11, 439}, - dictWord{10, 10, 530}, - dictWord{10, 11, 663}, - dictWord{11, 11, 609}, - dictWord{ - 140, - 11, - 197, - }, - dictWord{7, 11, 168}, - dictWord{13, 11, 196}, - dictWord{141, 11, 237}, - dictWord{139, 0, 958}, - dictWord{133, 0, 594}, - dictWord{135, 10, 580}, - dictWord{7, 10, 88}, - dictWord{136, 10, 627}, - dictWord{6, 0, 479}, - dictWord{6, 0, 562}, - dictWord{7, 0, 1060}, - dictWord{13, 0, 6}, - dictWord{5, 10, 872}, - dictWord{ - 6, - 10, - 57, - }, - dictWord{7, 10, 471}, - dictWord{9, 10, 447}, - dictWord{137, 10, 454}, - dictWord{136, 11, 413}, - dictWord{145, 11, 19}, - dictWord{4, 11, 117}, - dictWord{ - 6, - 11, - 372, - }, - dictWord{7, 11, 1905}, - dictWord{142, 11, 323}, - dictWord{4, 11, 722}, - dictWord{139, 11, 471}, - dictWord{17, 0, 61}, - dictWord{5, 10, 31}, - dictWord{134, 10, 614}, - dictWord{8, 10, 330}, - dictWord{140, 10, 477}, - dictWord{7, 10, 1200}, - dictWord{138, 10, 460}, - dictWord{6, 10, 424}, - dictWord{ - 135, - 10, - 1866, - }, - dictWord{6, 0, 1641}, - dictWord{136, 0, 820}, - dictWord{6, 0, 1556}, - dictWord{134, 0, 1618}, - dictWord{9, 11, 5}, - dictWord{12, 11, 216}, - dictWord{ - 12, - 11, - 294, - }, - dictWord{12, 11, 298}, - dictWord{12, 11, 400}, - dictWord{12, 11, 518}, - dictWord{13, 11, 229}, - dictWord{143, 11, 139}, - dictWord{15, 11, 155}, - dictWord{144, 11, 79}, - dictWord{4, 0, 302}, - dictWord{135, 0, 1766}, - dictWord{5, 10, 13}, - dictWord{134, 10, 142}, - dictWord{6, 0, 148}, - dictWord{7, 0, 1313}, - dictWord{ - 7, - 10, - 116, - }, - dictWord{8, 10, 322}, - dictWord{8, 10, 755}, - dictWord{9, 10, 548}, - dictWord{10, 10, 714}, - dictWord{11, 10, 884}, - dictWord{141, 10, 324}, - dictWord{137, 0, 676}, - dictWord{9, 11, 88}, - dictWord{139, 11, 270}, - dictWord{5, 11, 12}, - dictWord{7, 11, 375}, - dictWord{137, 11, 438}, - dictWord{134, 0, 1674}, - dictWord{7, 10, 1472}, - dictWord{135, 10, 1554}, - dictWord{11, 0, 178}, - dictWord{7, 10, 1071}, - dictWord{7, 10, 1541}, - dictWord{7, 10, 1767}, - dictWord{ - 7, - 10, - 1806, - }, - dictWord{11, 10, 162}, - dictWord{11, 10, 242}, - dictWord{12, 10, 605}, - dictWord{15, 10, 26}, - dictWord{144, 10, 44}, - dictWord{6, 0, 389}, - dictWord{ - 7, - 0, - 149, - }, - dictWord{9, 0, 142}, - dictWord{138, 0, 94}, - dictWord{140, 11, 71}, - dictWord{145, 10, 115}, - dictWord{6, 0, 8}, - dictWord{7, 0, 1881}, - dictWord{8, 0, 91}, - dictWord{11, 11, 966}, - dictWord{12, 11, 287}, - dictWord{13, 11, 342}, - dictWord{13, 11, 402}, - dictWord{15, 11, 110}, - dictWord{143, 11, 163}, - dictWord{ - 4, - 11, - 258, - }, - dictWord{136, 11, 639}, - dictWord{6, 11, 22}, - dictWord{7, 11, 903}, - dictWord{138, 11, 577}, - dictWord{133, 11, 681}, - dictWord{135, 10, 1111}, - dictWord{135, 11, 1286}, - dictWord{9, 0, 112}, - dictWord{8, 10, 1}, - dictWord{138, 10, 326}, - dictWord{5, 10, 488}, - dictWord{6, 10, 527}, - dictWord{7, 10, 489}, - dictWord{ - 7, - 10, - 1636, - }, - dictWord{8, 10, 121}, - dictWord{8, 10, 144}, - dictWord{8, 10, 359}, - dictWord{9, 10, 193}, - dictWord{9, 10, 241}, - dictWord{9, 10, 336}, - dictWord{ - 9, - 10, - 882, - }, - dictWord{11, 10, 266}, - dictWord{11, 10, 372}, - dictWord{11, 10, 944}, - dictWord{12, 10, 401}, - dictWord{140, 10, 641}, - dictWord{4, 11, 664}, - dictWord{133, 11, 804}, - dictWord{6, 0, 747}, - dictWord{134, 0, 1015}, - dictWord{135, 0, 1746}, - dictWord{9, 10, 31}, - dictWord{10, 10, 244}, - dictWord{ - 10, - 10, - 699, - }, - dictWord{12, 10, 149}, - dictWord{141, 10, 497}, - dictWord{133, 10, 377}, - dictWord{135, 0, 24}, - dictWord{6, 0, 1352}, - dictWord{5, 11, 32}, - dictWord{ - 145, - 10, - 101, - }, - dictWord{7, 0, 1530}, - dictWord{10, 0, 158}, - dictWord{13, 0, 13}, - dictWord{13, 0, 137}, - dictWord{13, 0, 258}, - dictWord{14, 0, 111}, - dictWord{ - 14, - 0, - 225, - }, - dictWord{14, 0, 253}, - dictWord{14, 0, 304}, - dictWord{14, 0, 339}, - dictWord{14, 0, 417}, - dictWord{146, 0, 33}, - dictWord{4, 0, 503}, - dictWord{ - 135, - 0, - 1661, - }, - dictWord{5, 0, 130}, - dictWord{6, 0, 845}, - dictWord{7, 0, 1314}, - dictWord{9, 0, 610}, - dictWord{10, 0, 718}, - dictWord{11, 0, 601}, - dictWord{11, 0, 819}, - dictWord{11, 0, 946}, - dictWord{140, 0, 536}, - dictWord{10, 0, 149}, - dictWord{11, 0, 280}, - dictWord{142, 0, 336}, - dictWord{134, 0, 1401}, - dictWord{ - 135, - 0, - 1946, - }, - dictWord{8, 0, 663}, - dictWord{144, 0, 8}, - dictWord{134, 0, 1607}, - dictWord{135, 10, 2023}, - dictWord{4, 11, 289}, - dictWord{7, 11, 629}, - dictWord{ - 7, - 11, - 1698, - }, - dictWord{7, 11, 1711}, - dictWord{140, 11, 215}, - dictWord{6, 11, 450}, - dictWord{136, 11, 109}, - dictWord{10, 0, 882}, - dictWord{10, 0, 883}, - dictWord{10, 0, 914}, - dictWord{138, 0, 928}, - dictWord{133, 10, 843}, - dictWord{136, 11, 705}, - dictWord{132, 10, 554}, - dictWord{133, 10, 536}, - dictWord{ - 5, - 0, - 417, - }, - dictWord{9, 10, 79}, - dictWord{11, 10, 625}, - dictWord{145, 10, 7}, - dictWord{7, 11, 1238}, - dictWord{142, 11, 37}, - dictWord{4, 0, 392}, - dictWord{ - 135, - 0, - 1597, - }, - dictWord{5, 0, 433}, - dictWord{9, 0, 633}, - dictWord{11, 0, 629}, - dictWord{132, 10, 424}, - dictWord{7, 10, 336}, - dictWord{136, 10, 785}, - dictWord{ - 134, - 11, - 355, - }, - dictWord{6, 0, 234}, - dictWord{7, 0, 769}, - dictWord{9, 0, 18}, - dictWord{138, 0, 358}, - dictWord{4, 10, 896}, - dictWord{134, 10, 1777}, - dictWord{ - 138, - 11, - 323, - }, - dictWord{7, 0, 140}, - dictWord{7, 0, 1950}, - dictWord{8, 0, 680}, - dictWord{11, 0, 817}, - dictWord{147, 0, 88}, - dictWord{7, 0, 1222}, - dictWord{ - 138, - 0, - 386, - }, - dictWord{139, 11, 908}, - dictWord{11, 0, 249}, - dictWord{12, 0, 313}, - dictWord{16, 0, 66}, - dictWord{145, 0, 26}, - dictWord{134, 0, 5}, - dictWord{7, 10, 750}, - dictWord{9, 10, 223}, - dictWord{11, 10, 27}, - dictWord{11, 10, 466}, - dictWord{12, 10, 624}, - dictWord{14, 10, 265}, - dictWord{146, 10, 61}, - dictWord{ - 134, - 11, - 26, - }, - dictWord{134, 0, 1216}, - dictWord{5, 0, 963}, - dictWord{134, 0, 1773}, - dictWord{4, 11, 414}, - dictWord{5, 11, 467}, - dictWord{9, 11, 654}, - dictWord{ - 10, - 11, - 451, - }, - dictWord{12, 11, 59}, - dictWord{141, 11, 375}, - dictWord{135, 11, 17}, - dictWord{4, 10, 603}, - dictWord{133, 10, 661}, - dictWord{4, 10, 11}, - dictWord{ - 6, - 10, - 128, - }, - dictWord{7, 10, 231}, - dictWord{7, 10, 1533}, - dictWord{138, 10, 725}, - dictWord{135, 11, 955}, - dictWord{7, 0, 180}, - dictWord{8, 0, 509}, - dictWord{ - 136, - 0, - 792, - }, - dictWord{132, 10, 476}, - dictWord{132, 0, 1002}, - dictWord{133, 11, 538}, - dictWord{135, 10, 1807}, - dictWord{132, 0, 931}, - dictWord{7, 0, 943}, - dictWord{11, 0, 614}, - dictWord{140, 0, 747}, - dictWord{135, 0, 1837}, - dictWord{9, 10, 20}, - dictWord{10, 10, 324}, - dictWord{10, 10, 807}, - dictWord{ - 139, - 10, - 488, - }, - dictWord{134, 0, 641}, - dictWord{6, 11, 280}, - dictWord{10, 11, 502}, - dictWord{11, 11, 344}, - dictWord{140, 11, 38}, - dictWord{5, 11, 45}, - dictWord{ - 7, - 11, - 1161, - }, - dictWord{11, 11, 448}, - dictWord{11, 11, 880}, - dictWord{13, 11, 139}, - dictWord{13, 11, 407}, - dictWord{15, 11, 16}, - dictWord{17, 11, 95}, - dictWord{ - 18, - 11, - 66, - }, - dictWord{18, 11, 88}, - dictWord{18, 11, 123}, - dictWord{149, 11, 7}, - dictWord{9, 0, 280}, - dictWord{138, 0, 134}, - dictWord{22, 0, 22}, - dictWord{23, 0, 5}, - dictWord{151, 0, 29}, - dictWord{136, 11, 777}, - dictWord{4, 0, 90}, - dictWord{5, 0, 545}, - dictWord{7, 0, 754}, - dictWord{9, 0, 186}, - dictWord{10, 0, 72}, - dictWord{ - 10, - 0, - 782, - }, - dictWord{11, 0, 577}, - dictWord{11, 0, 610}, - dictWord{11, 0, 960}, - dictWord{12, 0, 354}, - dictWord{12, 0, 362}, - dictWord{12, 0, 595}, - dictWord{ - 4, - 11, - 410, - }, - dictWord{135, 11, 521}, - dictWord{135, 11, 1778}, - dictWord{5, 10, 112}, - dictWord{6, 10, 103}, - dictWord{134, 10, 150}, - dictWord{138, 10, 356}, - dictWord{132, 0, 742}, - dictWord{7, 0, 151}, - dictWord{9, 0, 329}, - dictWord{139, 0, 254}, - dictWord{8, 0, 853}, - dictWord{8, 0, 881}, - dictWord{8, 0, 911}, - dictWord{ - 8, - 0, - 912, - }, - dictWord{10, 0, 872}, - dictWord{12, 0, 741}, - dictWord{12, 0, 742}, - dictWord{152, 0, 18}, - dictWord{4, 11, 573}, - dictWord{136, 11, 655}, - dictWord{ - 6, - 0, - 921, - }, - dictWord{134, 0, 934}, - dictWord{9, 0, 187}, - dictWord{10, 0, 36}, - dictWord{11, 0, 1016}, - dictWord{17, 0, 44}, - dictWord{146, 0, 64}, - dictWord{7, 0, 833}, - dictWord{136, 0, 517}, - dictWord{4, 0, 506}, - dictWord{5, 0, 295}, - dictWord{135, 0, 1680}, - dictWord{4, 10, 708}, - dictWord{8, 10, 15}, - dictWord{9, 10, 50}, - dictWord{ - 9, - 10, - 386, - }, - dictWord{11, 10, 18}, - dictWord{11, 10, 529}, - dictWord{140, 10, 228}, - dictWord{7, 0, 251}, - dictWord{7, 0, 1701}, - dictWord{8, 0, 436}, - dictWord{ - 4, - 10, - 563, - }, - dictWord{7, 10, 592}, - dictWord{7, 10, 637}, - dictWord{7, 10, 770}, - dictWord{8, 10, 463}, - dictWord{9, 10, 60}, - dictWord{9, 10, 335}, - dictWord{9, 10, 904}, - dictWord{10, 10, 73}, - dictWord{11, 10, 434}, - dictWord{12, 10, 585}, - dictWord{13, 10, 331}, - dictWord{18, 10, 110}, - dictWord{148, 10, 60}, - dictWord{ - 132, - 10, - 502, - }, - dictWord{136, 0, 584}, - dictWord{6, 10, 347}, - dictWord{138, 10, 161}, - dictWord{7, 0, 987}, - dictWord{9, 0, 688}, - dictWord{10, 0, 522}, - dictWord{ - 11, - 0, - 788, - }, - dictWord{12, 0, 137}, - dictWord{12, 0, 566}, - dictWord{14, 0, 9}, - dictWord{14, 0, 24}, - dictWord{14, 0, 64}, - dictWord{7, 11, 899}, - dictWord{142, 11, 325}, - dictWord{4, 0, 214}, - dictWord{5, 0, 500}, - dictWord{5, 10, 102}, - dictWord{6, 10, 284}, - dictWord{7, 10, 1079}, - dictWord{7, 10, 1423}, - dictWord{7, 10, 1702}, - dictWord{ - 8, - 10, - 470, - }, - dictWord{9, 10, 554}, - dictWord{9, 10, 723}, - dictWord{139, 10, 333}, - dictWord{7, 10, 246}, - dictWord{135, 10, 840}, - dictWord{6, 10, 10}, - dictWord{ - 8, - 10, - 571, - }, - dictWord{9, 10, 739}, - dictWord{143, 10, 91}, - dictWord{133, 10, 626}, - dictWord{146, 0, 195}, - dictWord{134, 0, 1775}, - dictWord{7, 0, 389}, - dictWord{7, 0, 700}, - dictWord{7, 0, 940}, - dictWord{8, 0, 514}, - dictWord{9, 0, 116}, - dictWord{9, 0, 535}, - dictWord{10, 0, 118}, - dictWord{11, 0, 107}, - dictWord{ - 11, - 0, - 148, - }, - dictWord{11, 0, 922}, - dictWord{12, 0, 254}, - dictWord{12, 0, 421}, - dictWord{142, 0, 238}, - dictWord{5, 10, 18}, - dictWord{6, 10, 526}, - dictWord{13, 10, 24}, - dictWord{13, 10, 110}, - dictWord{19, 10, 5}, - dictWord{147, 10, 44}, - dictWord{132, 0, 743}, - dictWord{11, 0, 292}, - dictWord{4, 10, 309}, - dictWord{5, 10, 462}, - dictWord{7, 10, 970}, - dictWord{135, 10, 1097}, - dictWord{22, 10, 30}, - dictWord{150, 10, 33}, - dictWord{139, 11, 338}, - dictWord{135, 11, 1598}, - dictWord{ - 7, - 0, - 1283, - }, - dictWord{9, 0, 227}, - dictWord{11, 0, 325}, - dictWord{11, 0, 408}, - dictWord{14, 0, 180}, - dictWord{146, 0, 47}, - dictWord{4, 0, 953}, - dictWord{6, 0, 1805}, - dictWord{6, 0, 1814}, - dictWord{6, 0, 1862}, - dictWord{140, 0, 774}, - dictWord{6, 11, 611}, - dictWord{135, 11, 1733}, - dictWord{135, 11, 1464}, - dictWord{ - 5, - 0, - 81, - }, - dictWord{7, 0, 146}, - dictWord{7, 0, 1342}, - dictWord{8, 0, 53}, - dictWord{8, 0, 561}, - dictWord{8, 0, 694}, - dictWord{8, 0, 754}, - dictWord{9, 0, 115}, - dictWord{ - 9, - 0, - 179, - }, - dictWord{9, 0, 894}, - dictWord{10, 0, 462}, - dictWord{10, 0, 813}, - dictWord{11, 0, 230}, - dictWord{11, 0, 657}, - dictWord{11, 0, 699}, - dictWord{11, 0, 748}, - dictWord{12, 0, 119}, - dictWord{12, 0, 200}, - dictWord{12, 0, 283}, - dictWord{142, 0, 273}, - dictWord{5, 0, 408}, - dictWord{6, 0, 789}, - dictWord{6, 0, 877}, - dictWord{ - 6, - 0, - 1253, - }, - dictWord{6, 0, 1413}, - dictWord{137, 0, 747}, - dictWord{134, 10, 1704}, - dictWord{135, 11, 663}, - dictWord{6, 0, 1910}, - dictWord{6, 0, 1915}, - dictWord{6, 0, 1923}, - dictWord{9, 0, 913}, - dictWord{9, 0, 928}, - dictWord{9, 0, 950}, - dictWord{9, 0, 954}, - dictWord{9, 0, 978}, - dictWord{9, 0, 993}, - dictWord{12, 0, 812}, - dictWord{12, 0, 819}, - dictWord{12, 0, 831}, - dictWord{12, 0, 833}, - dictWord{12, 0, 838}, - dictWord{12, 0, 909}, - dictWord{12, 0, 928}, - dictWord{12, 0, 931}, - dictWord{12, 0, 950}, - dictWord{15, 0, 186}, - dictWord{15, 0, 187}, - dictWord{15, 0, 195}, - dictWord{15, 0, 196}, - dictWord{15, 0, 209}, - dictWord{15, 0, 215}, - dictWord{ - 15, - 0, - 236, - }, - dictWord{15, 0, 241}, - dictWord{15, 0, 249}, - dictWord{15, 0, 253}, - dictWord{18, 0, 180}, - dictWord{18, 0, 221}, - dictWord{18, 0, 224}, - dictWord{ - 18, - 0, - 227, - }, - dictWord{18, 0, 229}, - dictWord{149, 0, 60}, - dictWord{7, 0, 1826}, - dictWord{135, 0, 1938}, - dictWord{11, 0, 490}, - dictWord{18, 0, 143}, - dictWord{ - 5, - 10, - 86, - }, - dictWord{7, 10, 743}, - dictWord{9, 10, 85}, - dictWord{10, 10, 281}, - dictWord{10, 10, 432}, - dictWord{12, 10, 251}, - dictWord{13, 10, 118}, - dictWord{ - 142, - 10, - 378, - }, - dictWord{5, 10, 524}, - dictWord{133, 10, 744}, - dictWord{141, 11, 442}, - dictWord{10, 10, 107}, - dictWord{140, 10, 436}, - dictWord{135, 11, 503}, - dictWord{134, 0, 1162}, - dictWord{132, 10, 927}, - dictWord{7, 0, 30}, - dictWord{8, 0, 86}, - dictWord{8, 0, 315}, - dictWord{8, 0, 700}, - dictWord{9, 0, 576}, - dictWord{ - 9, - 0, - 858, - }, - dictWord{10, 0, 414}, - dictWord{11, 0, 310}, - dictWord{11, 0, 888}, - dictWord{11, 0, 904}, - dictWord{12, 0, 361}, - dictWord{13, 0, 248}, - dictWord{13, 0, 371}, - dictWord{14, 0, 142}, - dictWord{12, 10, 670}, - dictWord{146, 10, 94}, - dictWord{134, 0, 721}, - dictWord{4, 11, 113}, - dictWord{5, 11, 163}, - dictWord{5, 11, 735}, - dictWord{7, 11, 1009}, - dictWord{7, 10, 1149}, - dictWord{9, 11, 9}, - dictWord{9, 10, 156}, - dictWord{9, 11, 771}, - dictWord{12, 11, 90}, - dictWord{13, 11, 138}, - dictWord{13, 11, 410}, - dictWord{143, 11, 128}, - dictWord{138, 0, 839}, - dictWord{133, 10, 778}, - dictWord{137, 0, 617}, - dictWord{133, 10, 502}, - dictWord{ - 8, - 10, - 196, - }, - dictWord{10, 10, 283}, - dictWord{139, 10, 406}, - dictWord{6, 0, 428}, - dictWord{7, 0, 524}, - dictWord{8, 0, 169}, - dictWord{8, 0, 234}, - dictWord{9, 0, 480}, - dictWord{138, 0, 646}, - dictWord{133, 10, 855}, - dictWord{134, 0, 1648}, - dictWord{7, 0, 1205}, - dictWord{138, 0, 637}, - dictWord{7, 0, 1596}, - dictWord{ - 4, - 11, - 935, - }, - dictWord{133, 11, 823}, - dictWord{5, 11, 269}, - dictWord{7, 11, 434}, - dictWord{7, 11, 891}, - dictWord{8, 11, 339}, - dictWord{9, 11, 702}, - dictWord{ - 11, - 11, - 594, - }, - dictWord{11, 11, 718}, - dictWord{145, 11, 100}, - dictWord{7, 11, 878}, - dictWord{9, 11, 485}, - dictWord{141, 11, 264}, - dictWord{4, 0, 266}, - dictWord{ - 8, - 0, - 4, - }, - dictWord{9, 0, 39}, - dictWord{10, 0, 166}, - dictWord{11, 0, 918}, - dictWord{12, 0, 635}, - dictWord{20, 0, 10}, - dictWord{22, 0, 27}, - dictWord{22, 0, 43}, - dictWord{ - 22, - 0, - 52, - }, - dictWord{134, 11, 1713}, - dictWord{7, 10, 1400}, - dictWord{9, 10, 446}, - dictWord{138, 10, 45}, - dictWord{135, 11, 900}, - dictWord{132, 0, 862}, - dictWord{134, 0, 1554}, - dictWord{135, 11, 1033}, - dictWord{19, 0, 16}, - dictWord{147, 11, 16}, - dictWord{135, 11, 1208}, - dictWord{7, 0, 157}, - dictWord{ - 136, - 0, - 279, - }, - dictWord{6, 0, 604}, - dictWord{136, 0, 391}, - dictWord{13, 10, 455}, - dictWord{15, 10, 99}, - dictWord{15, 10, 129}, - dictWord{144, 10, 68}, - dictWord{ - 135, - 10, - 172, - }, - dictWord{7, 0, 945}, - dictWord{11, 0, 713}, - dictWord{139, 0, 744}, - dictWord{4, 0, 973}, - dictWord{10, 0, 877}, - dictWord{10, 0, 937}, - dictWord{ - 10, - 0, - 938, - }, - dictWord{140, 0, 711}, - dictWord{139, 0, 1022}, - dictWord{132, 10, 568}, - dictWord{142, 11, 143}, - dictWord{4, 0, 567}, - dictWord{9, 0, 859}, - dictWord{ - 132, - 10, - 732, - }, - dictWord{7, 0, 1846}, - dictWord{136, 0, 628}, - dictWord{136, 10, 733}, - dictWord{133, 0, 762}, - dictWord{4, 10, 428}, - dictWord{135, 10, 1789}, - dictWord{10, 0, 784}, - dictWord{13, 0, 191}, - dictWord{7, 10, 2015}, - dictWord{140, 10, 665}, - dictWord{133, 0, 298}, - dictWord{7, 0, 633}, - dictWord{7, 0, 905}, - dictWord{7, 0, 909}, - dictWord{7, 0, 1538}, - dictWord{9, 0, 767}, - dictWord{140, 0, 636}, - dictWord{138, 10, 806}, - dictWord{132, 0, 795}, - dictWord{139, 0, 301}, - dictWord{135, 0, 1970}, - dictWord{5, 11, 625}, - dictWord{135, 11, 1617}, - dictWord{135, 11, 275}, - dictWord{7, 11, 37}, - dictWord{8, 11, 425}, - dictWord{ - 8, - 11, - 693, - }, - dictWord{9, 11, 720}, - dictWord{10, 11, 380}, - dictWord{10, 11, 638}, - dictWord{11, 11, 273}, - dictWord{11, 11, 307}, - dictWord{11, 11, 473}, - dictWord{ - 12, - 11, - 61, - }, - dictWord{143, 11, 43}, - dictWord{135, 11, 198}, - dictWord{134, 0, 1236}, - dictWord{7, 0, 369}, - dictWord{12, 0, 644}, - dictWord{12, 0, 645}, - dictWord{144, 0, 90}, - dictWord{19, 0, 15}, - dictWord{149, 0, 27}, - dictWord{6, 0, 71}, - dictWord{7, 0, 845}, - dictWord{8, 0, 160}, - dictWord{9, 0, 318}, - dictWord{6, 10, 1623}, - dictWord{134, 10, 1681}, - dictWord{134, 0, 1447}, - dictWord{134, 0, 1255}, - dictWord{138, 0, 735}, - dictWord{8, 0, 76}, - dictWord{132, 11, 168}, - dictWord{ - 6, - 10, - 1748, - }, - dictWord{8, 10, 715}, - dictWord{9, 10, 802}, - dictWord{10, 10, 46}, - dictWord{10, 10, 819}, - dictWord{13, 10, 308}, - dictWord{14, 10, 351}, - dictWord{14, 10, 363}, - dictWord{146, 10, 67}, - dictWord{135, 11, 91}, - dictWord{6, 0, 474}, - dictWord{4, 10, 63}, - dictWord{133, 10, 347}, - dictWord{133, 10, 749}, - dictWord{138, 0, 841}, - dictWord{133, 10, 366}, - dictWord{6, 0, 836}, - dictWord{132, 11, 225}, - dictWord{135, 0, 1622}, - dictWord{135, 10, 89}, - dictWord{ - 140, - 0, - 735, - }, - dictWord{134, 0, 1601}, - dictWord{138, 11, 145}, - dictWord{6, 0, 1390}, - dictWord{137, 0, 804}, - dictWord{142, 0, 394}, - dictWord{6, 11, 15}, - dictWord{ - 7, - 11, - 70, - }, - dictWord{10, 11, 240}, - dictWord{147, 11, 93}, - dictWord{6, 0, 96}, - dictWord{135, 0, 1426}, - dictWord{4, 0, 651}, - dictWord{133, 0, 289}, - dictWord{ - 7, - 11, - 956, - }, - dictWord{7, 10, 977}, - dictWord{7, 11, 1157}, - dictWord{7, 11, 1506}, - dictWord{7, 11, 1606}, - dictWord{7, 11, 1615}, - dictWord{7, 11, 1619}, - dictWord{ - 7, - 11, - 1736, - }, - dictWord{7, 11, 1775}, - dictWord{8, 11, 590}, - dictWord{9, 11, 324}, - dictWord{9, 11, 736}, - dictWord{9, 11, 774}, - dictWord{9, 11, 776}, - dictWord{ - 9, - 11, - 784, - }, - dictWord{10, 11, 567}, - dictWord{10, 11, 708}, - dictWord{11, 11, 518}, - dictWord{11, 11, 613}, - dictWord{11, 11, 695}, - dictWord{11, 11, 716}, - dictWord{11, 11, 739}, - dictWord{11, 11, 770}, - dictWord{11, 11, 771}, - dictWord{11, 11, 848}, - dictWord{11, 11, 857}, - dictWord{11, 11, 931}, - dictWord{ - 11, - 11, - 947, - }, - dictWord{12, 11, 326}, - dictWord{12, 11, 387}, - dictWord{12, 11, 484}, - dictWord{12, 11, 528}, - dictWord{12, 11, 552}, - dictWord{12, 11, 613}, - dictWord{ - 13, - 11, - 189, - }, - dictWord{13, 11, 256}, - dictWord{13, 11, 340}, - dictWord{13, 11, 432}, - dictWord{13, 11, 436}, - dictWord{13, 11, 440}, - dictWord{13, 11, 454}, - dictWord{14, 11, 174}, - dictWord{14, 11, 220}, - dictWord{14, 11, 284}, - dictWord{14, 11, 390}, - dictWord{145, 11, 121}, - dictWord{7, 0, 688}, - dictWord{8, 0, 35}, - dictWord{9, 0, 511}, - dictWord{10, 0, 767}, - dictWord{147, 0, 118}, - dictWord{134, 0, 667}, - dictWord{4, 0, 513}, - dictWord{5, 10, 824}, - dictWord{133, 10, 941}, - dictWord{7, 10, 440}, - dictWord{8, 10, 230}, - dictWord{139, 10, 106}, - dictWord{134, 0, 2034}, - dictWord{135, 11, 1399}, - dictWord{143, 11, 66}, - dictWord{ - 135, - 11, - 1529, - }, - dictWord{4, 11, 145}, - dictWord{6, 11, 176}, - dictWord{7, 11, 395}, - dictWord{9, 11, 562}, - dictWord{144, 11, 28}, - dictWord{132, 11, 501}, - dictWord{132, 0, 704}, - dictWord{134, 0, 1524}, - dictWord{7, 0, 1078}, - dictWord{134, 11, 464}, - dictWord{6, 11, 509}, - dictWord{10, 11, 82}, - dictWord{20, 11, 91}, - dictWord{151, 11, 13}, - dictWord{4, 0, 720}, - dictWord{133, 0, 306}, - dictWord{133, 0, 431}, - dictWord{7, 0, 1196}, - dictWord{4, 10, 914}, - dictWord{5, 10, 800}, - dictWord{133, 10, 852}, - dictWord{135, 11, 1189}, - dictWord{10, 0, 54}, - dictWord{141, 10, 115}, - dictWord{7, 10, 564}, - dictWord{142, 10, 168}, - dictWord{ - 5, - 0, - 464, - }, - dictWord{6, 0, 236}, - dictWord{7, 0, 696}, - dictWord{7, 0, 914}, - dictWord{7, 0, 1108}, - dictWord{7, 0, 1448}, - dictWord{9, 0, 15}, - dictWord{9, 0, 564}, - dictWord{ - 10, - 0, - 14, - }, - dictWord{12, 0, 565}, - dictWord{13, 0, 449}, - dictWord{14, 0, 53}, - dictWord{15, 0, 13}, - dictWord{16, 0, 64}, - dictWord{17, 0, 41}, - dictWord{4, 10, 918}, - dictWord{133, 10, 876}, - dictWord{6, 0, 1418}, - dictWord{134, 10, 1764}, - dictWord{4, 10, 92}, - dictWord{133, 10, 274}, - dictWord{134, 0, 907}, - dictWord{ - 4, - 11, - 114, - }, - dictWord{8, 10, 501}, - dictWord{9, 11, 492}, - dictWord{13, 11, 462}, - dictWord{142, 11, 215}, - dictWord{4, 11, 77}, - dictWord{5, 11, 361}, - dictWord{ - 6, - 11, - 139, - }, - dictWord{6, 11, 401}, - dictWord{6, 11, 404}, - dictWord{7, 11, 413}, - dictWord{7, 11, 715}, - dictWord{7, 11, 1716}, - dictWord{11, 11, 279}, - dictWord{ - 12, - 11, - 179, - }, - dictWord{12, 11, 258}, - dictWord{13, 11, 244}, - dictWord{142, 11, 358}, - dictWord{6, 0, 1767}, - dictWord{12, 0, 194}, - dictWord{145, 0, 107}, - dictWord{ - 134, - 11, - 1717, - }, - dictWord{5, 10, 743}, - dictWord{142, 11, 329}, - dictWord{4, 10, 49}, - dictWord{7, 10, 280}, - dictWord{135, 10, 1633}, - dictWord{5, 0, 840}, - dictWord{7, 11, 1061}, - dictWord{8, 11, 82}, - dictWord{11, 11, 250}, - dictWord{12, 11, 420}, - dictWord{141, 11, 184}, - dictWord{135, 11, 724}, - dictWord{ - 134, - 0, - 900, - }, - dictWord{136, 10, 47}, - dictWord{134, 0, 1436}, - dictWord{144, 11, 0}, - dictWord{6, 0, 675}, - dictWord{7, 0, 1008}, - dictWord{7, 0, 1560}, - dictWord{ - 9, - 0, - 642, - }, - dictWord{11, 0, 236}, - dictWord{14, 0, 193}, - dictWord{5, 10, 272}, - dictWord{5, 10, 908}, - dictWord{5, 10, 942}, - dictWord{8, 10, 197}, - dictWord{9, 10, 47}, - dictWord{11, 10, 538}, - dictWord{139, 10, 742}, - dictWord{4, 0, 68}, - dictWord{5, 0, 628}, - dictWord{5, 0, 634}, - dictWord{6, 0, 386}, - dictWord{7, 0, 794}, - dictWord{ - 8, - 0, - 273, - }, - dictWord{9, 0, 563}, - dictWord{10, 0, 105}, - dictWord{10, 0, 171}, - dictWord{11, 0, 94}, - dictWord{139, 0, 354}, - dictWord{135, 10, 1911}, - dictWord{ - 137, - 10, - 891, - }, - dictWord{4, 0, 95}, - dictWord{6, 0, 1297}, - dictWord{6, 0, 1604}, - dictWord{7, 0, 416}, - dictWord{139, 0, 830}, - dictWord{6, 11, 513}, - dictWord{ - 135, - 11, - 1052, - }, - dictWord{7, 0, 731}, - dictWord{13, 0, 20}, - dictWord{143, 0, 11}, - dictWord{137, 11, 899}, - dictWord{10, 0, 850}, - dictWord{140, 0, 697}, - dictWord{ - 4, - 0, - 662, - }, - dictWord{7, 11, 1417}, - dictWord{12, 11, 382}, - dictWord{17, 11, 48}, - dictWord{152, 11, 12}, - dictWord{133, 0, 736}, - dictWord{132, 0, 861}, - dictWord{ - 4, - 10, - 407, - }, - dictWord{132, 10, 560}, - dictWord{141, 10, 490}, - dictWord{6, 11, 545}, - dictWord{7, 11, 565}, - dictWord{7, 11, 1669}, - dictWord{10, 11, 114}, - dictWord{11, 11, 642}, - dictWord{140, 11, 618}, - dictWord{6, 0, 871}, - dictWord{134, 0, 1000}, - dictWord{5, 0, 864}, - dictWord{10, 0, 648}, - dictWord{11, 0, 671}, - dictWord{15, 0, 46}, - dictWord{133, 11, 5}, - dictWord{133, 0, 928}, - dictWord{11, 0, 90}, - dictWord{13, 0, 7}, - dictWord{4, 10, 475}, - dictWord{11, 10, 35}, - dictWord{ - 13, - 10, - 71, - }, - dictWord{13, 10, 177}, - dictWord{142, 10, 422}, - dictWord{136, 0, 332}, - dictWord{135, 11, 192}, - dictWord{134, 0, 1055}, - dictWord{136, 11, 763}, - dictWord{11, 0, 986}, - dictWord{140, 0, 682}, - dictWord{7, 0, 76}, - dictWord{8, 0, 44}, - dictWord{9, 0, 884}, - dictWord{10, 0, 580}, - dictWord{11, 0, 399}, - dictWord{ - 11, - 0, - 894, - }, - dictWord{143, 0, 122}, - dictWord{135, 11, 1237}, - dictWord{135, 10, 636}, - dictWord{11, 0, 300}, - dictWord{6, 10, 222}, - dictWord{7, 10, 1620}, - dictWord{ - 8, - 10, - 409, - }, - dictWord{137, 10, 693}, - dictWord{4, 11, 87}, - dictWord{5, 11, 250}, - dictWord{10, 11, 601}, - dictWord{13, 11, 298}, - dictWord{13, 11, 353}, - dictWord{141, 11, 376}, - dictWord{5, 0, 518}, - dictWord{10, 0, 340}, - dictWord{11, 0, 175}, - dictWord{149, 0, 16}, - dictWord{140, 0, 771}, - dictWord{6, 0, 1108}, - dictWord{137, 0, 831}, - dictWord{132, 0, 836}, - dictWord{135, 0, 1852}, - dictWord{4, 0, 957}, - dictWord{6, 0, 1804}, - dictWord{8, 0, 842}, - dictWord{8, 0, 843}, - dictWord{ - 8, - 0, - 851, - }, - dictWord{8, 0, 855}, - dictWord{140, 0, 767}, - dictWord{135, 11, 814}, - dictWord{4, 11, 57}, - dictWord{7, 11, 1195}, - dictWord{7, 11, 1438}, - dictWord{ - 7, - 11, - 1548, - }, - dictWord{7, 11, 1835}, - dictWord{7, 11, 1904}, - dictWord{9, 11, 757}, - dictWord{10, 11, 604}, - dictWord{139, 11, 519}, - dictWord{133, 10, 882}, - dictWord{138, 0, 246}, - dictWord{4, 0, 934}, - dictWord{5, 0, 202}, - dictWord{8, 0, 610}, - dictWord{7, 11, 1897}, - dictWord{12, 11, 290}, - dictWord{13, 11, 80}, - dictWord{13, 11, 437}, - dictWord{145, 11, 74}, - dictWord{8, 0, 96}, - dictWord{9, 0, 36}, - dictWord{10, 0, 607}, - dictWord{10, 0, 804}, - dictWord{10, 0, 832}, - dictWord{ - 11, - 0, - 423, - }, - dictWord{11, 0, 442}, - dictWord{12, 0, 309}, - dictWord{14, 0, 199}, - dictWord{15, 0, 90}, - dictWord{145, 0, 110}, - dictWord{132, 10, 426}, - dictWord{ - 7, - 0, - 654, - }, - dictWord{8, 0, 240}, - dictWord{6, 10, 58}, - dictWord{7, 10, 745}, - dictWord{7, 10, 1969}, - dictWord{8, 10, 675}, - dictWord{9, 10, 479}, - dictWord{9, 10, 731}, - dictWord{10, 10, 330}, - dictWord{10, 10, 593}, - dictWord{10, 10, 817}, - dictWord{11, 10, 32}, - dictWord{11, 10, 133}, - dictWord{11, 10, 221}, - dictWord{ - 145, - 10, - 68, - }, - dictWord{9, 0, 13}, - dictWord{9, 0, 398}, - dictWord{9, 0, 727}, - dictWord{10, 0, 75}, - dictWord{10, 0, 184}, - dictWord{10, 0, 230}, - dictWord{10, 0, 564}, - dictWord{ - 10, - 0, - 569, - }, - dictWord{11, 0, 973}, - dictWord{12, 0, 70}, - dictWord{12, 0, 189}, - dictWord{13, 0, 57}, - dictWord{141, 0, 257}, - dictWord{4, 11, 209}, - dictWord{ - 135, - 11, - 902, - }, - dictWord{7, 0, 391}, - dictWord{137, 10, 538}, - dictWord{134, 0, 403}, - dictWord{6, 11, 303}, - dictWord{7, 11, 335}, - dictWord{7, 11, 1437}, - dictWord{ - 7, - 11, - 1668, - }, - dictWord{8, 11, 553}, - dictWord{8, 11, 652}, - dictWord{8, 11, 656}, - dictWord{9, 11, 558}, - dictWord{11, 11, 743}, - dictWord{149, 11, 18}, - dictWord{ - 132, - 11, - 559, - }, - dictWord{11, 0, 75}, - dictWord{142, 0, 267}, - dictWord{6, 0, 815}, - dictWord{141, 11, 2}, - dictWord{141, 0, 366}, - dictWord{137, 0, 631}, - dictWord{ - 133, - 11, - 1017, - }, - dictWord{5, 0, 345}, - dictWord{135, 0, 1016}, - dictWord{133, 11, 709}, - dictWord{134, 11, 1745}, - dictWord{133, 10, 566}, - dictWord{7, 0, 952}, - dictWord{6, 10, 48}, - dictWord{9, 10, 139}, - dictWord{10, 10, 399}, - dictWord{11, 10, 469}, - dictWord{12, 10, 634}, - dictWord{141, 10, 223}, - dictWord{ - 133, - 0, - 673, - }, - dictWord{9, 0, 850}, - dictWord{7, 11, 8}, - dictWord{136, 11, 206}, - dictWord{6, 0, 662}, - dictWord{149, 0, 35}, - dictWord{4, 0, 287}, - dictWord{133, 0, 1018}, - dictWord{6, 10, 114}, - dictWord{7, 10, 1224}, - dictWord{7, 10, 1556}, - dictWord{136, 10, 3}, - dictWord{8, 10, 576}, - dictWord{137, 10, 267}, - dictWord{4, 0, 884}, - dictWord{5, 0, 34}, - dictWord{10, 0, 724}, - dictWord{12, 0, 444}, - dictWord{13, 0, 354}, - dictWord{18, 0, 32}, - dictWord{23, 0, 24}, - dictWord{23, 0, 31}, - dictWord{ - 152, - 0, - 5, - }, - dictWord{133, 10, 933}, - dictWord{132, 11, 776}, - dictWord{138, 0, 151}, - dictWord{136, 0, 427}, - dictWord{134, 0, 382}, - dictWord{132, 0, 329}, - dictWord{ - 9, - 0, - 846, - }, - dictWord{10, 0, 827}, - dictWord{138, 11, 33}, - dictWord{9, 0, 279}, - dictWord{10, 0, 407}, - dictWord{14, 0, 84}, - dictWord{22, 0, 18}, - dictWord{ - 135, - 11, - 1297, - }, - dictWord{136, 11, 406}, - dictWord{132, 0, 906}, - dictWord{136, 0, 366}, - dictWord{134, 0, 843}, - dictWord{134, 0, 1443}, - dictWord{135, 0, 1372}, - dictWord{138, 0, 992}, - dictWord{4, 0, 123}, - dictWord{5, 0, 605}, - dictWord{7, 0, 1509}, - dictWord{136, 0, 36}, - dictWord{132, 0, 649}, - dictWord{8, 11, 175}, - dictWord{10, 11, 168}, - dictWord{138, 11, 573}, - dictWord{133, 0, 767}, - dictWord{134, 0, 1018}, - dictWord{135, 11, 1305}, - dictWord{12, 10, 30}, - dictWord{ - 13, - 10, - 148, - }, - dictWord{14, 10, 87}, - dictWord{14, 10, 182}, - dictWord{16, 10, 42}, - dictWord{148, 10, 70}, - dictWord{134, 11, 607}, - dictWord{4, 0, 273}, - dictWord{ - 5, - 0, - 658, - }, - dictWord{133, 0, 995}, - dictWord{6, 0, 72}, - dictWord{139, 11, 174}, - dictWord{10, 0, 483}, - dictWord{12, 0, 368}, - dictWord{7, 10, 56}, - dictWord{ - 7, - 10, - 1989, - }, - dictWord{8, 10, 337}, - dictWord{8, 10, 738}, - dictWord{9, 10, 600}, - dictWord{13, 10, 447}, - dictWord{142, 10, 92}, - dictWord{5, 11, 784}, - dictWord{ - 138, - 10, - 666, - }, - dictWord{135, 0, 1345}, - dictWord{139, 11, 882}, - dictWord{134, 0, 1293}, - dictWord{133, 0, 589}, - dictWord{134, 0, 1988}, - dictWord{5, 0, 117}, - dictWord{6, 0, 514}, - dictWord{6, 0, 541}, - dictWord{7, 0, 1164}, - dictWord{7, 0, 1436}, - dictWord{8, 0, 220}, - dictWord{8, 0, 648}, - dictWord{10, 0, 688}, - dictWord{ - 139, - 0, - 560, - }, - dictWord{136, 0, 379}, - dictWord{5, 0, 686}, - dictWord{7, 10, 866}, - dictWord{135, 10, 1163}, - dictWord{132, 10, 328}, - dictWord{9, 11, 14}, - dictWord{ - 9, - 11, - 441, - }, - dictWord{10, 11, 306}, - dictWord{139, 11, 9}, - dictWord{4, 10, 101}, - dictWord{135, 10, 1171}, - dictWord{5, 10, 833}, - dictWord{136, 10, 744}, - dictWord{5, 11, 161}, - dictWord{7, 11, 839}, - dictWord{135, 11, 887}, - dictWord{7, 0, 196}, - dictWord{10, 0, 765}, - dictWord{11, 0, 347}, - dictWord{11, 0, 552}, - dictWord{11, 0, 790}, - dictWord{12, 0, 263}, - dictWord{13, 0, 246}, - dictWord{13, 0, 270}, - dictWord{13, 0, 395}, - dictWord{14, 0, 176}, - dictWord{14, 0, 190}, - dictWord{ - 14, - 0, - 398, - }, - dictWord{14, 0, 412}, - dictWord{15, 0, 32}, - dictWord{15, 0, 63}, - dictWord{16, 0, 88}, - dictWord{147, 0, 105}, - dictWord{6, 10, 9}, - dictWord{6, 10, 397}, - dictWord{7, 10, 53}, - dictWord{7, 10, 1742}, - dictWord{10, 10, 632}, - dictWord{11, 10, 828}, - dictWord{140, 10, 146}, - dictWord{5, 0, 381}, - dictWord{135, 0, 1792}, - dictWord{134, 0, 1452}, - dictWord{135, 11, 429}, - dictWord{8, 0, 367}, - dictWord{10, 0, 760}, - dictWord{14, 0, 79}, - dictWord{20, 0, 17}, - dictWord{152, 0, 0}, - dictWord{7, 0, 616}, - dictWord{138, 0, 413}, - dictWord{11, 10, 417}, - dictWord{12, 10, 223}, - dictWord{140, 10, 265}, - dictWord{7, 11, 1611}, - dictWord{13, 11, 14}, - dictWord{15, 11, 44}, - dictWord{19, 11, 13}, - dictWord{148, 11, 76}, - dictWord{135, 0, 1229}, - dictWord{6, 0, 120}, - dictWord{7, 0, 1188}, - dictWord{7, 0, 1710}, - dictWord{8, 0, 286}, - dictWord{9, 0, 667}, - dictWord{11, 0, 592}, - dictWord{139, 0, 730}, - dictWord{135, 11, 1814}, - dictWord{135, 0, 1146}, - dictWord{4, 10, 186}, - dictWord{5, 10, 157}, - dictWord{8, 10, 168}, - dictWord{138, 10, 6}, - dictWord{4, 0, 352}, - dictWord{135, 0, 687}, - dictWord{4, 0, 192}, - dictWord{5, 0, 49}, - dictWord{ - 6, - 0, - 200, - }, - dictWord{6, 0, 293}, - dictWord{6, 0, 1696}, - dictWord{135, 0, 1151}, - dictWord{133, 10, 875}, - dictWord{5, 10, 773}, - dictWord{5, 10, 991}, - dictWord{ - 6, - 10, - 1635, - }, - dictWord{134, 10, 1788}, - dictWord{7, 10, 111}, - dictWord{136, 10, 581}, - dictWord{6, 0, 935}, - dictWord{134, 0, 1151}, - dictWord{134, 0, 1050}, - dictWord{132, 0, 650}, - dictWord{132, 0, 147}, - dictWord{11, 0, 194}, - dictWord{12, 0, 62}, - dictWord{12, 0, 88}, - dictWord{11, 11, 194}, - dictWord{12, 11, 62}, - dictWord{140, 11, 88}, - dictWord{6, 0, 339}, - dictWord{135, 0, 923}, - dictWord{134, 10, 1747}, - dictWord{7, 11, 643}, - dictWord{136, 11, 236}, - dictWord{ - 133, - 0, - 934, - }, - dictWord{7, 10, 1364}, - dictWord{7, 10, 1907}, - dictWord{141, 10, 158}, - dictWord{132, 10, 659}, - dictWord{4, 10, 404}, - dictWord{135, 10, 675}, - dictWord{7, 11, 581}, - dictWord{9, 11, 644}, - dictWord{137, 11, 699}, - dictWord{13, 0, 211}, - dictWord{14, 0, 133}, - dictWord{14, 0, 204}, - dictWord{15, 0, 64}, - dictWord{ - 15, - 0, - 69, - }, - dictWord{15, 0, 114}, - dictWord{16, 0, 10}, - dictWord{19, 0, 23}, - dictWord{19, 0, 35}, - dictWord{19, 0, 39}, - dictWord{19, 0, 51}, - dictWord{19, 0, 71}, - dictWord{19, 0, 75}, - dictWord{152, 0, 15}, - dictWord{133, 10, 391}, - dictWord{5, 11, 54}, - dictWord{135, 11, 1513}, - dictWord{7, 0, 222}, - dictWord{8, 0, 341}, - dictWord{ - 5, - 10, - 540, - }, - dictWord{134, 10, 1697}, - dictWord{134, 10, 78}, - dictWord{132, 11, 744}, - dictWord{136, 0, 293}, - dictWord{137, 11, 701}, - dictWord{ - 7, - 11, - 930, - }, - dictWord{10, 11, 402}, - dictWord{10, 11, 476}, - dictWord{13, 11, 452}, - dictWord{18, 11, 55}, - dictWord{147, 11, 104}, - dictWord{132, 0, 637}, - dictWord{133, 10, 460}, - dictWord{8, 11, 50}, - dictWord{137, 11, 624}, - dictWord{132, 11, 572}, - dictWord{134, 0, 1159}, - dictWord{4, 10, 199}, - dictWord{ - 139, - 10, - 34, - }, - dictWord{134, 0, 847}, - dictWord{134, 10, 388}, - dictWord{6, 11, 43}, - dictWord{7, 11, 38}, - dictWord{8, 11, 248}, - dictWord{9, 11, 504}, - dictWord{ - 138, - 11, - 513, - }, - dictWord{9, 0, 683}, - dictWord{4, 10, 511}, - dictWord{6, 10, 608}, - dictWord{9, 10, 333}, - dictWord{10, 10, 602}, - dictWord{11, 10, 441}, - dictWord{ - 11, - 10, - 723, - }, - dictWord{11, 10, 976}, - dictWord{140, 10, 357}, - dictWord{9, 0, 867}, - dictWord{138, 0, 837}, - dictWord{6, 0, 944}, - dictWord{135, 11, 326}, - dictWord{ - 135, - 0, - 1809, - }, - dictWord{5, 10, 938}, - dictWord{7, 11, 783}, - dictWord{136, 10, 707}, - dictWord{133, 11, 766}, - dictWord{133, 11, 363}, - dictWord{6, 0, 170}, - dictWord{7, 0, 1080}, - dictWord{8, 0, 395}, - dictWord{8, 0, 487}, - dictWord{141, 0, 147}, - dictWord{6, 11, 258}, - dictWord{140, 11, 409}, - dictWord{4, 0, 535}, - dictWord{ - 8, - 0, - 618, - }, - dictWord{5, 11, 249}, - dictWord{148, 11, 82}, - dictWord{6, 0, 1379}, - dictWord{149, 11, 15}, - dictWord{135, 0, 1625}, - dictWord{150, 0, 23}, - dictWord{ - 5, - 11, - 393, - }, - dictWord{6, 11, 378}, - dictWord{7, 11, 1981}, - dictWord{9, 11, 32}, - dictWord{9, 11, 591}, - dictWord{10, 11, 685}, - dictWord{10, 11, 741}, - dictWord{ - 142, - 11, - 382, - }, - dictWord{133, 11, 788}, - dictWord{7, 11, 1968}, - dictWord{10, 11, 19}, - dictWord{139, 11, 911}, - dictWord{7, 11, 1401}, - dictWord{ - 135, - 11, - 1476, - }, - dictWord{4, 11, 61}, - dictWord{5, 11, 58}, - dictWord{5, 11, 171}, - dictWord{5, 11, 635}, - dictWord{5, 11, 683}, - dictWord{5, 11, 700}, - dictWord{6, 11, 291}, - dictWord{6, 11, 566}, - dictWord{7, 11, 1650}, - dictWord{11, 11, 523}, - dictWord{12, 11, 273}, - dictWord{12, 11, 303}, - dictWord{15, 11, 39}, - dictWord{ - 143, - 11, - 111, - }, - dictWord{6, 10, 469}, - dictWord{7, 10, 1709}, - dictWord{138, 10, 515}, - dictWord{4, 0, 778}, - dictWord{134, 11, 589}, - dictWord{132, 0, 46}, - dictWord{ - 5, - 0, - 811, - }, - dictWord{6, 0, 1679}, - dictWord{6, 0, 1714}, - dictWord{135, 0, 2032}, - dictWord{7, 0, 1458}, - dictWord{9, 0, 407}, - dictWord{11, 0, 15}, - dictWord{12, 0, 651}, - dictWord{149, 0, 37}, - dictWord{7, 0, 938}, - dictWord{132, 10, 500}, - dictWord{6, 0, 34}, - dictWord{7, 0, 69}, - dictWord{7, 0, 1089}, - dictWord{7, 0, 1281}, - dictWord{ - 8, - 0, - 708, - }, - dictWord{8, 0, 721}, - dictWord{9, 0, 363}, - dictWord{148, 0, 98}, - dictWord{10, 11, 231}, - dictWord{147, 11, 124}, - dictWord{7, 11, 726}, - dictWord{ - 152, - 11, - 9, - }, - dictWord{5, 10, 68}, - dictWord{134, 10, 383}, - dictWord{136, 11, 583}, - dictWord{4, 11, 917}, - dictWord{133, 11, 1005}, - dictWord{11, 10, 216}, - dictWord{139, 10, 340}, - dictWord{135, 11, 1675}, - dictWord{8, 0, 441}, - dictWord{10, 0, 314}, - dictWord{143, 0, 3}, - dictWord{132, 11, 919}, - dictWord{4, 10, 337}, - dictWord{6, 10, 353}, - dictWord{7, 10, 1934}, - dictWord{8, 10, 488}, - dictWord{137, 10, 429}, - dictWord{7, 0, 889}, - dictWord{7, 10, 1795}, - dictWord{8, 10, 259}, - dictWord{9, 10, 135}, - dictWord{9, 10, 177}, - dictWord{9, 10, 860}, - dictWord{10, 10, 825}, - dictWord{11, 10, 115}, - dictWord{11, 10, 370}, - dictWord{11, 10, 405}, - dictWord{11, 10, 604}, - dictWord{12, 10, 10}, - dictWord{12, 10, 667}, - dictWord{12, 10, 669}, - dictWord{13, 10, 76}, - dictWord{14, 10, 310}, - dictWord{ - 15, - 10, - 76, - }, - dictWord{15, 10, 147}, - dictWord{148, 10, 23}, - dictWord{4, 10, 15}, - dictWord{4, 11, 255}, - dictWord{5, 10, 22}, - dictWord{5, 11, 302}, - dictWord{6, 11, 132}, - dictWord{6, 10, 244}, - dictWord{7, 10, 40}, - dictWord{7, 11, 128}, - dictWord{7, 10, 200}, - dictWord{7, 11, 283}, - dictWord{7, 10, 906}, - dictWord{7, 10, 1199}, - dictWord{ - 7, - 11, - 1299, - }, - dictWord{9, 10, 616}, - dictWord{10, 11, 52}, - dictWord{10, 11, 514}, - dictWord{10, 10, 716}, - dictWord{11, 10, 635}, - dictWord{11, 10, 801}, - dictWord{11, 11, 925}, - dictWord{12, 10, 458}, - dictWord{13, 11, 92}, - dictWord{142, 11, 309}, - dictWord{132, 0, 462}, - dictWord{137, 11, 173}, - dictWord{ - 135, - 10, - 1735, - }, - dictWord{8, 0, 525}, - dictWord{5, 10, 598}, - dictWord{7, 10, 791}, - dictWord{8, 10, 108}, - dictWord{137, 10, 123}, - dictWord{5, 0, 73}, - dictWord{6, 0, 23}, - dictWord{134, 0, 338}, - dictWord{132, 0, 676}, - dictWord{132, 10, 683}, - dictWord{7, 0, 725}, - dictWord{8, 0, 498}, - dictWord{139, 0, 268}, - dictWord{12, 0, 21}, - dictWord{151, 0, 7}, - dictWord{135, 0, 773}, - dictWord{4, 10, 155}, - dictWord{135, 10, 1689}, - dictWord{4, 0, 164}, - dictWord{5, 0, 730}, - dictWord{5, 10, 151}, - dictWord{ - 5, - 10, - 741, - }, - dictWord{6, 11, 210}, - dictWord{7, 10, 498}, - dictWord{7, 10, 870}, - dictWord{7, 10, 1542}, - dictWord{12, 10, 213}, - dictWord{14, 10, 36}, - dictWord{ - 14, - 10, - 391, - }, - dictWord{17, 10, 111}, - dictWord{18, 10, 6}, - dictWord{18, 10, 46}, - dictWord{18, 10, 151}, - dictWord{19, 10, 36}, - dictWord{20, 10, 32}, - dictWord{ - 20, - 10, - 56, - }, - dictWord{20, 10, 69}, - dictWord{20, 10, 102}, - dictWord{21, 10, 4}, - dictWord{22, 10, 8}, - dictWord{22, 10, 10}, - dictWord{22, 10, 14}, - dictWord{ - 150, - 10, - 31, - }, - dictWord{4, 10, 624}, - dictWord{135, 10, 1752}, - dictWord{4, 0, 583}, - dictWord{9, 0, 936}, - dictWord{15, 0, 214}, - dictWord{18, 0, 199}, - dictWord{24, 0, 26}, - dictWord{134, 11, 588}, - dictWord{7, 0, 1462}, - dictWord{11, 0, 659}, - dictWord{4, 11, 284}, - dictWord{134, 11, 223}, - dictWord{133, 0, 220}, - dictWord{ - 139, - 0, - 803, - }, - dictWord{132, 0, 544}, - dictWord{4, 10, 492}, - dictWord{133, 10, 451}, - dictWord{16, 0, 98}, - dictWord{148, 0, 119}, - dictWord{4, 11, 218}, - dictWord{ - 7, - 11, - 526, - }, - dictWord{143, 11, 137}, - dictWord{135, 10, 835}, - dictWord{4, 11, 270}, - dictWord{5, 11, 192}, - dictWord{6, 11, 332}, - dictWord{7, 11, 1322}, - dictWord{ - 13, - 11, - 9, - }, - dictWord{13, 10, 70}, - dictWord{14, 11, 104}, - dictWord{142, 11, 311}, - dictWord{132, 10, 539}, - dictWord{140, 11, 661}, - dictWord{5, 0, 176}, - dictWord{ - 6, - 0, - 437, - }, - dictWord{6, 0, 564}, - dictWord{11, 0, 181}, - dictWord{141, 0, 183}, - dictWord{135, 0, 1192}, - dictWord{6, 10, 113}, - dictWord{135, 10, 436}, - dictWord{136, 10, 718}, - dictWord{135, 10, 520}, - dictWord{135, 0, 1878}, - dictWord{140, 11, 196}, - dictWord{7, 11, 379}, - dictWord{8, 11, 481}, - dictWord{ - 137, - 11, - 377, - }, - dictWord{5, 11, 1003}, - dictWord{6, 11, 149}, - dictWord{137, 11, 746}, - dictWord{8, 11, 262}, - dictWord{9, 11, 627}, - dictWord{10, 11, 18}, - dictWord{ - 11, - 11, - 214, - }, - dictWord{11, 11, 404}, - dictWord{11, 11, 457}, - dictWord{11, 11, 780}, - dictWord{11, 11, 849}, - dictWord{11, 11, 913}, - dictWord{13, 11, 330}, - dictWord{13, 11, 401}, - dictWord{142, 11, 200}, - dictWord{149, 0, 26}, - dictWord{136, 11, 304}, - dictWord{132, 11, 142}, - dictWord{135, 0, 944}, - dictWord{ - 4, - 0, - 790, - }, - dictWord{5, 0, 273}, - dictWord{134, 0, 394}, - dictWord{134, 0, 855}, - dictWord{4, 0, 135}, - dictWord{6, 0, 127}, - dictWord{7, 0, 1185}, - dictWord{7, 0, 1511}, - dictWord{8, 0, 613}, - dictWord{11, 0, 5}, - dictWord{12, 0, 336}, - dictWord{12, 0, 495}, - dictWord{12, 0, 586}, - dictWord{12, 0, 660}, - dictWord{12, 0, 668}, - dictWord{ - 14, - 0, - 385, - }, - dictWord{15, 0, 118}, - dictWord{17, 0, 20}, - dictWord{146, 0, 98}, - dictWord{6, 0, 230}, - dictWord{9, 0, 752}, - dictWord{18, 0, 109}, - dictWord{12, 10, 610}, - dictWord{13, 10, 431}, - dictWord{144, 10, 59}, - dictWord{7, 0, 1954}, - dictWord{135, 11, 925}, - dictWord{4, 11, 471}, - dictWord{5, 11, 51}, - dictWord{6, 11, 602}, - dictWord{8, 11, 484}, - dictWord{10, 11, 195}, - dictWord{140, 11, 159}, - dictWord{132, 10, 307}, - dictWord{136, 11, 688}, - dictWord{132, 11, 697}, - dictWord{ - 7, - 11, - 812, - }, - dictWord{7, 11, 1261}, - dictWord{7, 11, 1360}, - dictWord{9, 11, 632}, - dictWord{140, 11, 352}, - dictWord{5, 0, 162}, - dictWord{8, 0, 68}, - dictWord{ - 133, - 10, - 964, - }, - dictWord{4, 0, 654}, - dictWord{136, 11, 212}, - dictWord{4, 0, 156}, - dictWord{7, 0, 998}, - dictWord{7, 0, 1045}, - dictWord{7, 0, 1860}, - dictWord{9, 0, 48}, - dictWord{9, 0, 692}, - dictWord{11, 0, 419}, - dictWord{139, 0, 602}, - dictWord{133, 11, 221}, - dictWord{4, 11, 373}, - dictWord{5, 11, 283}, - dictWord{6, 11, 480}, - dictWord{135, 11, 609}, - dictWord{142, 11, 216}, - dictWord{132, 0, 240}, - dictWord{6, 11, 192}, - dictWord{9, 11, 793}, - dictWord{145, 11, 55}, - dictWord{ - 4, - 10, - 75, - }, - dictWord{5, 10, 180}, - dictWord{6, 10, 500}, - dictWord{7, 10, 58}, - dictWord{7, 10, 710}, - dictWord{138, 10, 645}, - dictWord{4, 11, 132}, - dictWord{5, 11, 69}, - dictWord{5, 10, 649}, - dictWord{135, 11, 1242}, - dictWord{6, 10, 276}, - dictWord{7, 10, 282}, - dictWord{7, 10, 879}, - dictWord{7, 10, 924}, - dictWord{8, 10, 459}, - dictWord{9, 10, 599}, - dictWord{9, 10, 754}, - dictWord{11, 10, 574}, - dictWord{12, 10, 128}, - dictWord{12, 10, 494}, - dictWord{13, 10, 52}, - dictWord{13, 10, 301}, - dictWord{15, 10, 30}, - dictWord{143, 10, 132}, - dictWord{132, 10, 200}, - dictWord{4, 11, 111}, - dictWord{135, 11, 302}, - dictWord{9, 0, 197}, - dictWord{ - 10, - 0, - 300, - }, - dictWord{12, 0, 473}, - dictWord{13, 0, 90}, - dictWord{141, 0, 405}, - dictWord{132, 11, 767}, - dictWord{6, 11, 42}, - dictWord{7, 11, 1416}, - dictWord{ - 7, - 11, - 1590, - }, - dictWord{7, 11, 2005}, - dictWord{8, 11, 131}, - dictWord{8, 11, 466}, - dictWord{9, 11, 672}, - dictWord{13, 11, 252}, - dictWord{148, 11, 103}, - dictWord{ - 8, - 0, - 958, - }, - dictWord{8, 0, 999}, - dictWord{10, 0, 963}, - dictWord{138, 0, 1001}, - dictWord{135, 10, 1621}, - dictWord{135, 0, 858}, - dictWord{4, 0, 606}, - dictWord{ - 137, - 11, - 444, - }, - dictWord{6, 11, 44}, - dictWord{136, 11, 368}, - dictWord{139, 11, 172}, - dictWord{4, 11, 570}, - dictWord{133, 11, 120}, - dictWord{139, 11, 624}, - dictWord{7, 0, 1978}, - dictWord{8, 0, 676}, - dictWord{6, 10, 225}, - dictWord{137, 10, 211}, - dictWord{7, 0, 972}, - dictWord{11, 0, 102}, - dictWord{136, 10, 687}, - dictWord{6, 11, 227}, - dictWord{135, 11, 1589}, - dictWord{8, 10, 58}, - dictWord{9, 10, 724}, - dictWord{11, 10, 809}, - dictWord{13, 10, 113}, - dictWord{ - 145, - 10, - 72, - }, - dictWord{4, 0, 361}, - dictWord{133, 0, 315}, - dictWord{132, 0, 461}, - dictWord{6, 10, 345}, - dictWord{135, 10, 1247}, - dictWord{132, 0, 472}, - dictWord{ - 8, - 10, - 767, - }, - dictWord{8, 10, 803}, - dictWord{9, 10, 301}, - dictWord{137, 10, 903}, - dictWord{135, 11, 1333}, - dictWord{135, 11, 477}, - dictWord{7, 10, 1949}, - dictWord{136, 10, 674}, - dictWord{6, 0, 905}, - dictWord{138, 0, 747}, - dictWord{133, 0, 155}, - dictWord{134, 10, 259}, - dictWord{7, 0, 163}, - dictWord{8, 0, 319}, - dictWord{9, 0, 402}, - dictWord{10, 0, 24}, - dictWord{10, 0, 681}, - dictWord{11, 0, 200}, - dictWord{12, 0, 253}, - dictWord{12, 0, 410}, - dictWord{142, 0, 219}, - dictWord{ - 5, - 0, - 475, - }, - dictWord{7, 0, 1780}, - dictWord{9, 0, 230}, - dictWord{11, 0, 297}, - dictWord{11, 0, 558}, - dictWord{14, 0, 322}, - dictWord{19, 0, 76}, - dictWord{6, 11, 1667}, - dictWord{7, 11, 2036}, - dictWord{138, 11, 600}, - dictWord{136, 10, 254}, - dictWord{6, 0, 848}, - dictWord{135, 0, 1956}, - dictWord{6, 11, 511}, - dictWord{ - 140, - 11, - 132, - }, - dictWord{5, 11, 568}, - dictWord{6, 11, 138}, - dictWord{135, 11, 1293}, - dictWord{6, 0, 631}, - dictWord{137, 0, 838}, - dictWord{149, 0, 36}, - dictWord{ - 4, - 11, - 565, - }, - dictWord{8, 11, 23}, - dictWord{136, 11, 827}, - dictWord{5, 0, 944}, - dictWord{134, 0, 1769}, - dictWord{4, 0, 144}, - dictWord{6, 0, 842}, - dictWord{ - 6, - 0, - 1400, - }, - dictWord{4, 11, 922}, - dictWord{133, 11, 1023}, - dictWord{133, 10, 248}, - dictWord{9, 10, 800}, - dictWord{10, 10, 693}, - dictWord{11, 10, 482}, - dictWord{11, 10, 734}, - dictWord{139, 10, 789}, - dictWord{7, 11, 1002}, - dictWord{139, 11, 145}, - dictWord{4, 10, 116}, - dictWord{5, 10, 95}, - dictWord{5, 10, 445}, - dictWord{7, 10, 1688}, - dictWord{8, 10, 29}, - dictWord{9, 10, 272}, - dictWord{11, 10, 509}, - dictWord{139, 10, 915}, - dictWord{14, 0, 369}, - dictWord{146, 0, 72}, - dictWord{135, 10, 1641}, - dictWord{132, 11, 740}, - dictWord{133, 10, 543}, - dictWord{140, 11, 116}, - dictWord{6, 0, 247}, - dictWord{9, 0, 555}, - dictWord{ - 5, - 10, - 181, - }, - dictWord{136, 10, 41}, - dictWord{133, 10, 657}, - dictWord{136, 0, 996}, - dictWord{138, 10, 709}, - dictWord{7, 0, 189}, - dictWord{8, 10, 202}, - dictWord{ - 138, - 10, - 536, - }, - dictWord{136, 11, 402}, - dictWord{4, 11, 716}, - dictWord{141, 11, 31}, - dictWord{10, 0, 280}, - dictWord{138, 0, 797}, - dictWord{9, 10, 423}, - dictWord{140, 10, 89}, - dictWord{8, 10, 113}, - dictWord{9, 10, 877}, - dictWord{10, 10, 554}, - dictWord{11, 10, 83}, - dictWord{12, 10, 136}, - dictWord{147, 10, 109}, - dictWord{133, 10, 976}, - dictWord{7, 0, 746}, - dictWord{132, 10, 206}, - dictWord{136, 0, 526}, - dictWord{139, 0, 345}, - dictWord{136, 0, 1017}, - dictWord{ - 8, - 11, - 152, - }, - dictWord{9, 11, 53}, - dictWord{9, 11, 268}, - dictWord{9, 11, 901}, - dictWord{10, 11, 518}, - dictWord{10, 11, 829}, - dictWord{11, 11, 188}, - dictWord{ - 13, - 11, - 74, - }, - dictWord{14, 11, 46}, - dictWord{15, 11, 17}, - dictWord{15, 11, 33}, - dictWord{17, 11, 40}, - dictWord{18, 11, 36}, - dictWord{19, 11, 20}, - dictWord{22, 11, 1}, - dictWord{152, 11, 2}, - dictWord{133, 11, 736}, - dictWord{136, 11, 532}, - dictWord{5, 0, 428}, - dictWord{138, 0, 651}, - dictWord{135, 11, 681}, - dictWord{ - 135, - 0, - 1162, - }, - dictWord{7, 0, 327}, - dictWord{13, 0, 230}, - dictWord{17, 0, 113}, - dictWord{8, 10, 226}, - dictWord{10, 10, 537}, - dictWord{11, 10, 570}, - dictWord{ - 11, - 10, - 605, - }, - dictWord{11, 10, 799}, - dictWord{11, 10, 804}, - dictWord{12, 10, 85}, - dictWord{12, 10, 516}, - dictWord{12, 10, 623}, - dictWord{12, 11, 677}, - dictWord{ - 13, - 10, - 361, - }, - dictWord{14, 10, 77}, - dictWord{14, 10, 78}, - dictWord{147, 10, 110}, - dictWord{4, 0, 792}, - dictWord{7, 0, 1717}, - dictWord{10, 0, 546}, - dictWord{ - 132, - 10, - 769, - }, - dictWord{4, 11, 684}, - dictWord{136, 11, 384}, - dictWord{132, 10, 551}, - dictWord{134, 0, 1203}, - dictWord{9, 10, 57}, - dictWord{9, 10, 459}, - dictWord{10, 10, 425}, - dictWord{11, 10, 119}, - dictWord{12, 10, 184}, - dictWord{12, 10, 371}, - dictWord{13, 10, 358}, - dictWord{145, 10, 51}, - dictWord{5, 0, 672}, - dictWord{5, 10, 814}, - dictWord{8, 10, 10}, - dictWord{9, 10, 421}, - dictWord{9, 10, 729}, - dictWord{10, 10, 609}, - dictWord{139, 10, 689}, - dictWord{138, 0, 189}, - dictWord{134, 10, 624}, - dictWord{7, 11, 110}, - dictWord{7, 11, 188}, - dictWord{8, 11, 290}, - dictWord{8, 11, 591}, - dictWord{9, 11, 382}, - dictWord{9, 11, 649}, - dictWord{11, 11, 71}, - dictWord{11, 11, 155}, - dictWord{11, 11, 313}, - dictWord{12, 11, 5}, - dictWord{13, 11, 325}, - dictWord{142, 11, 287}, - dictWord{133, 0, 99}, - dictWord{6, 0, 1053}, - dictWord{135, 0, 298}, - dictWord{7, 11, 360}, - dictWord{7, 11, 425}, - dictWord{9, 11, 66}, - dictWord{9, 11, 278}, - dictWord{138, 11, 644}, - dictWord{4, 0, 397}, - dictWord{136, 0, 555}, - dictWord{137, 10, 269}, - dictWord{132, 10, 528}, - dictWord{4, 11, 900}, - dictWord{133, 11, 861}, - dictWord{ - 6, - 0, - 1157, - }, - dictWord{5, 11, 254}, - dictWord{7, 11, 985}, - dictWord{136, 11, 73}, - dictWord{7, 11, 1959}, - dictWord{136, 11, 683}, - dictWord{12, 0, 398}, - dictWord{ - 20, - 0, - 39, - }, - dictWord{21, 0, 11}, - dictWord{150, 0, 41}, - dictWord{4, 0, 485}, - dictWord{7, 0, 353}, - dictWord{135, 0, 1523}, - dictWord{6, 0, 366}, - dictWord{7, 0, 1384}, - dictWord{135, 0, 1601}, - dictWord{138, 0, 787}, - dictWord{137, 0, 282}, - dictWord{5, 10, 104}, - dictWord{6, 10, 173}, - dictWord{135, 10, 1631}, - dictWord{ - 139, - 11, - 146, - }, - dictWord{4, 0, 157}, - dictWord{133, 0, 471}, - dictWord{134, 0, 941}, - dictWord{132, 11, 725}, - dictWord{7, 0, 1336}, - dictWord{8, 10, 138}, - dictWord{ - 8, - 10, - 342, - }, - dictWord{9, 10, 84}, - dictWord{10, 10, 193}, - dictWord{11, 10, 883}, - dictWord{140, 10, 359}, - dictWord{134, 11, 196}, - dictWord{136, 0, 116}, - dictWord{133, 11, 831}, - dictWord{134, 0, 787}, - dictWord{134, 10, 95}, - dictWord{6, 10, 406}, - dictWord{10, 10, 409}, - dictWord{10, 10, 447}, - dictWord{ - 11, - 10, - 44, - }, - dictWord{140, 10, 100}, - dictWord{5, 0, 160}, - dictWord{7, 0, 363}, - dictWord{7, 0, 589}, - dictWord{10, 0, 170}, - dictWord{141, 0, 55}, - dictWord{134, 0, 1815}, - dictWord{132, 0, 866}, - dictWord{6, 0, 889}, - dictWord{6, 0, 1067}, - dictWord{6, 0, 1183}, - dictWord{4, 11, 321}, - dictWord{134, 11, 569}, - dictWord{5, 11, 848}, - dictWord{134, 11, 66}, - dictWord{4, 11, 36}, - dictWord{6, 10, 1636}, - dictWord{7, 11, 1387}, - dictWord{10, 11, 205}, - dictWord{11, 11, 755}, - dictWord{ - 141, - 11, - 271, - }, - dictWord{132, 0, 689}, - dictWord{9, 0, 820}, - dictWord{4, 10, 282}, - dictWord{7, 10, 1034}, - dictWord{11, 10, 398}, - dictWord{11, 10, 634}, - dictWord{ - 12, - 10, - 1, - }, - dictWord{12, 10, 79}, - dictWord{12, 10, 544}, - dictWord{14, 10, 237}, - dictWord{17, 10, 10}, - dictWord{146, 10, 20}, - dictWord{4, 0, 108}, - dictWord{7, 0, 804}, - dictWord{139, 0, 498}, - dictWord{132, 11, 887}, - dictWord{6, 0, 1119}, - dictWord{135, 11, 620}, - dictWord{6, 11, 165}, - dictWord{138, 11, 388}, - dictWord{ - 5, - 0, - 244, - }, - dictWord{5, 10, 499}, - dictWord{6, 10, 476}, - dictWord{7, 10, 600}, - dictWord{7, 10, 888}, - dictWord{135, 10, 1096}, - dictWord{140, 0, 609}, - dictWord{ - 135, - 0, - 1005, - }, - dictWord{4, 0, 412}, - dictWord{133, 0, 581}, - dictWord{4, 11, 719}, - dictWord{135, 11, 155}, - dictWord{7, 10, 296}, - dictWord{7, 10, 596}, - dictWord{ - 8, - 10, - 560, - }, - dictWord{8, 10, 586}, - dictWord{9, 10, 612}, - dictWord{11, 10, 304}, - dictWord{12, 10, 46}, - dictWord{13, 10, 89}, - dictWord{14, 10, 112}, - dictWord{ - 145, - 10, - 122, - }, - dictWord{4, 0, 895}, - dictWord{133, 0, 772}, - dictWord{142, 11, 307}, - dictWord{135, 0, 1898}, - dictWord{4, 0, 926}, - dictWord{133, 0, 983}, - dictWord{4, 11, 353}, - dictWord{6, 11, 146}, - dictWord{6, 11, 1789}, - dictWord{7, 11, 288}, - dictWord{7, 11, 990}, - dictWord{7, 11, 1348}, - dictWord{9, 11, 665}, - dictWord{ - 9, - 11, - 898, - }, - dictWord{11, 11, 893}, - dictWord{142, 11, 212}, - dictWord{132, 0, 538}, - dictWord{133, 11, 532}, - dictWord{6, 0, 294}, - dictWord{7, 0, 1267}, - dictWord{8, 0, 624}, - dictWord{141, 0, 496}, - dictWord{7, 0, 1325}, - dictWord{4, 11, 45}, - dictWord{135, 11, 1257}, - dictWord{138, 0, 301}, - dictWord{9, 0, 298}, - dictWord{12, 0, 291}, - dictWord{13, 0, 276}, - dictWord{14, 0, 6}, - dictWord{17, 0, 18}, - dictWord{21, 0, 32}, - dictWord{7, 10, 1599}, - dictWord{7, 10, 1723}, - dictWord{ - 8, - 10, - 79, - }, - dictWord{8, 10, 106}, - dictWord{8, 10, 190}, - dictWord{8, 10, 302}, - dictWord{8, 10, 383}, - dictWord{8, 10, 713}, - dictWord{9, 10, 119}, - dictWord{9, 10, 233}, - dictWord{9, 10, 419}, - dictWord{9, 10, 471}, - dictWord{10, 10, 181}, - dictWord{10, 10, 406}, - dictWord{11, 10, 57}, - dictWord{11, 10, 85}, - dictWord{11, 10, 120}, - dictWord{11, 10, 177}, - dictWord{11, 10, 296}, - dictWord{11, 10, 382}, - dictWord{11, 10, 454}, - dictWord{11, 10, 758}, - dictWord{11, 10, 999}, - dictWord{ - 12, - 10, - 27, - }, - dictWord{12, 10, 131}, - dictWord{12, 10, 245}, - dictWord{12, 10, 312}, - dictWord{12, 10, 446}, - dictWord{12, 10, 454}, - dictWord{13, 10, 98}, - dictWord{ - 13, - 10, - 426, - }, - dictWord{13, 10, 508}, - dictWord{14, 10, 163}, - dictWord{14, 10, 272}, - dictWord{14, 10, 277}, - dictWord{14, 10, 370}, - dictWord{15, 10, 95}, - dictWord{15, 10, 138}, - dictWord{15, 10, 167}, - dictWord{17, 10, 38}, - dictWord{148, 10, 96}, - dictWord{132, 0, 757}, - dictWord{134, 0, 1263}, - dictWord{4, 0, 820}, - dictWord{134, 10, 1759}, - dictWord{133, 0, 722}, - dictWord{136, 11, 816}, - dictWord{138, 10, 372}, - dictWord{145, 10, 16}, - dictWord{134, 0, 1039}, - dictWord{ - 4, - 0, - 991, - }, - dictWord{134, 0, 2028}, - dictWord{133, 10, 258}, - dictWord{7, 0, 1875}, - dictWord{139, 0, 124}, - dictWord{6, 11, 559}, - dictWord{6, 11, 1691}, - dictWord{135, 11, 586}, - dictWord{5, 0, 324}, - dictWord{7, 0, 881}, - dictWord{8, 10, 134}, - dictWord{9, 10, 788}, - dictWord{140, 10, 438}, - dictWord{7, 11, 1823}, - dictWord{139, 11, 693}, - dictWord{6, 0, 1348}, - dictWord{134, 0, 1545}, - dictWord{134, 0, 911}, - dictWord{132, 0, 954}, - dictWord{8, 0, 329}, - dictWord{8, 0, 414}, - dictWord{7, 10, 1948}, - dictWord{135, 10, 2004}, - dictWord{5, 0, 517}, - dictWord{6, 10, 439}, - dictWord{7, 10, 780}, - dictWord{135, 10, 1040}, - dictWord{ - 132, - 0, - 816, - }, - dictWord{5, 10, 1}, - dictWord{6, 10, 81}, - dictWord{138, 10, 520}, - dictWord{9, 0, 713}, - dictWord{10, 0, 222}, - dictWord{5, 10, 482}, - dictWord{8, 10, 98}, - dictWord{10, 10, 700}, - dictWord{10, 10, 822}, - dictWord{11, 10, 302}, - dictWord{11, 10, 778}, - dictWord{12, 10, 50}, - dictWord{12, 10, 127}, - dictWord{12, 10, 396}, - dictWord{13, 10, 62}, - dictWord{13, 10, 328}, - dictWord{14, 10, 122}, - dictWord{147, 10, 72}, - dictWord{137, 0, 33}, - dictWord{5, 10, 2}, - dictWord{7, 10, 1494}, - dictWord{136, 10, 589}, - dictWord{6, 10, 512}, - dictWord{7, 10, 797}, - dictWord{8, 10, 253}, - dictWord{9, 10, 77}, - dictWord{10, 10, 1}, - dictWord{10, 11, 108}, - dictWord{10, 10, 129}, - dictWord{10, 10, 225}, - dictWord{11, 11, 116}, - dictWord{11, 10, 118}, - dictWord{11, 10, 226}, - dictWord{11, 10, 251}, - dictWord{ - 11, - 10, - 430, - }, - dictWord{11, 10, 701}, - dictWord{11, 10, 974}, - dictWord{11, 10, 982}, - dictWord{12, 10, 64}, - dictWord{12, 10, 260}, - dictWord{12, 10, 488}, - dictWord{ - 140, - 10, - 690, - }, - dictWord{134, 11, 456}, - dictWord{133, 11, 925}, - dictWord{5, 0, 150}, - dictWord{7, 0, 106}, - dictWord{7, 0, 774}, - dictWord{8, 0, 603}, - dictWord{ - 9, - 0, - 593, - }, - dictWord{9, 0, 634}, - dictWord{10, 0, 44}, - dictWord{10, 0, 173}, - dictWord{11, 0, 462}, - dictWord{11, 0, 515}, - dictWord{13, 0, 216}, - dictWord{13, 0, 288}, - dictWord{142, 0, 400}, - dictWord{137, 10, 347}, - dictWord{5, 0, 748}, - dictWord{134, 0, 553}, - dictWord{12, 0, 108}, - dictWord{141, 0, 291}, - dictWord{7, 0, 420}, - dictWord{4, 10, 12}, - dictWord{7, 10, 522}, - dictWord{7, 10, 809}, - dictWord{8, 10, 797}, - dictWord{141, 10, 88}, - dictWord{6, 11, 193}, - dictWord{7, 11, 240}, - dictWord{ - 7, - 11, - 1682, - }, - dictWord{10, 11, 51}, - dictWord{10, 11, 640}, - dictWord{11, 11, 410}, - dictWord{13, 11, 82}, - dictWord{14, 11, 247}, - dictWord{14, 11, 331}, - dictWord{142, 11, 377}, - dictWord{133, 10, 528}, - dictWord{135, 0, 1777}, - dictWord{4, 0, 493}, - dictWord{144, 0, 55}, - dictWord{136, 11, 633}, - dictWord{ - 139, - 0, - 81, - }, - dictWord{6, 0, 980}, - dictWord{136, 0, 321}, - dictWord{148, 10, 109}, - dictWord{5, 10, 266}, - dictWord{9, 10, 290}, - dictWord{9, 10, 364}, - dictWord{ - 10, - 10, - 293, - }, - dictWord{11, 10, 606}, - dictWord{142, 10, 45}, - dictWord{6, 0, 568}, - dictWord{7, 0, 112}, - dictWord{7, 0, 1804}, - dictWord{8, 0, 362}, - dictWord{8, 0, 410}, - dictWord{8, 0, 830}, - dictWord{9, 0, 514}, - dictWord{11, 0, 649}, - dictWord{142, 0, 157}, - dictWord{4, 0, 74}, - dictWord{6, 0, 510}, - dictWord{6, 10, 594}, - dictWord{ - 9, - 10, - 121, - }, - dictWord{10, 10, 49}, - dictWord{10, 10, 412}, - dictWord{139, 10, 834}, - dictWord{134, 0, 838}, - dictWord{136, 10, 748}, - dictWord{132, 10, 466}, - dictWord{132, 0, 625}, - dictWord{135, 11, 1443}, - dictWord{4, 11, 237}, - dictWord{135, 11, 514}, - dictWord{9, 10, 378}, - dictWord{141, 10, 162}, - dictWord{6, 0, 16}, - dictWord{6, 0, 158}, - dictWord{7, 0, 43}, - dictWord{7, 0, 129}, - dictWord{7, 0, 181}, - dictWord{8, 0, 276}, - dictWord{8, 0, 377}, - dictWord{10, 0, 523}, - dictWord{ - 11, - 0, - 816, - }, - dictWord{12, 0, 455}, - dictWord{13, 0, 303}, - dictWord{142, 0, 135}, - dictWord{135, 0, 281}, - dictWord{4, 0, 1}, - dictWord{7, 0, 1143}, - dictWord{7, 0, 1463}, - dictWord{8, 0, 61}, - dictWord{9, 0, 207}, - dictWord{9, 0, 390}, - dictWord{9, 0, 467}, - dictWord{139, 0, 836}, - dictWord{6, 11, 392}, - dictWord{7, 11, 65}, - dictWord{ - 135, - 11, - 2019, - }, - dictWord{132, 10, 667}, - dictWord{4, 0, 723}, - dictWord{5, 0, 895}, - dictWord{7, 0, 1031}, - dictWord{8, 0, 199}, - dictWord{8, 0, 340}, - dictWord{9, 0, 153}, - dictWord{9, 0, 215}, - dictWord{10, 0, 21}, - dictWord{10, 0, 59}, - dictWord{10, 0, 80}, - dictWord{10, 0, 224}, - dictWord{10, 0, 838}, - dictWord{11, 0, 229}, - dictWord{ - 11, - 0, - 652, - }, - dictWord{12, 0, 192}, - dictWord{13, 0, 146}, - dictWord{142, 0, 91}, - dictWord{132, 0, 295}, - dictWord{137, 0, 51}, - dictWord{9, 11, 222}, - dictWord{ - 10, - 11, - 43, - }, - dictWord{139, 11, 900}, - dictWord{5, 0, 309}, - dictWord{140, 0, 211}, - dictWord{5, 0, 125}, - dictWord{8, 0, 77}, - dictWord{138, 0, 15}, - dictWord{136, 11, 604}, - dictWord{138, 0, 789}, - dictWord{5, 0, 173}, - dictWord{4, 10, 39}, - dictWord{7, 10, 1843}, - dictWord{8, 10, 407}, - dictWord{11, 10, 144}, - dictWord{140, 10, 523}, - dictWord{138, 11, 265}, - dictWord{133, 0, 439}, - dictWord{132, 10, 510}, - dictWord{7, 0, 648}, - dictWord{7, 0, 874}, - dictWord{11, 0, 164}, - dictWord{12, 0, 76}, - dictWord{18, 0, 9}, - dictWord{7, 10, 1980}, - dictWord{10, 10, 487}, - dictWord{138, 10, 809}, - dictWord{12, 0, 111}, - dictWord{14, 0, 294}, - dictWord{19, 0, 45}, - dictWord{13, 10, 260}, - dictWord{146, 10, 63}, - dictWord{133, 11, 549}, - dictWord{134, 10, 570}, - dictWord{4, 0, 8}, - dictWord{7, 0, 1152}, - dictWord{7, 0, 1153}, - dictWord{7, 0, 1715}, - dictWord{9, 0, 374}, - dictWord{10, 0, 478}, - dictWord{139, 0, 648}, - dictWord{135, 0, 1099}, - dictWord{5, 0, 575}, - dictWord{6, 0, 354}, - dictWord{ - 135, - 0, - 701, - }, - dictWord{7, 11, 36}, - dictWord{8, 11, 201}, - dictWord{136, 11, 605}, - dictWord{4, 10, 787}, - dictWord{136, 11, 156}, - dictWord{6, 0, 518}, - dictWord{ - 149, - 11, - 13, - }, - dictWord{140, 11, 224}, - dictWord{134, 0, 702}, - dictWord{132, 10, 516}, - dictWord{5, 11, 724}, - dictWord{10, 11, 305}, - dictWord{11, 11, 151}, - dictWord{12, 11, 33}, - dictWord{12, 11, 121}, - dictWord{12, 11, 381}, - dictWord{17, 11, 3}, - dictWord{17, 11, 27}, - dictWord{17, 11, 78}, - dictWord{18, 11, 18}, - dictWord{19, 11, 54}, - dictWord{149, 11, 5}, - dictWord{8, 0, 87}, - dictWord{4, 11, 523}, - dictWord{5, 11, 638}, - dictWord{11, 10, 887}, - dictWord{14, 10, 365}, - dictWord{ - 142, - 10, - 375, - }, - dictWord{138, 0, 438}, - dictWord{136, 10, 821}, - dictWord{135, 11, 1908}, - dictWord{6, 11, 242}, - dictWord{7, 11, 227}, - dictWord{7, 11, 1581}, - dictWord{8, 11, 104}, - dictWord{9, 11, 113}, - dictWord{9, 11, 220}, - dictWord{9, 11, 427}, - dictWord{10, 11, 74}, - dictWord{10, 11, 239}, - dictWord{11, 11, 579}, - dictWord{11, 11, 1023}, - dictWord{13, 11, 4}, - dictWord{13, 11, 204}, - dictWord{13, 11, 316}, - dictWord{18, 11, 95}, - dictWord{148, 11, 86}, - dictWord{4, 0, 69}, - dictWord{5, 0, 122}, - dictWord{5, 0, 849}, - dictWord{6, 0, 1633}, - dictWord{9, 0, 656}, - dictWord{138, 0, 464}, - dictWord{7, 0, 1802}, - dictWord{4, 10, 10}, - dictWord{ - 139, - 10, - 786, - }, - dictWord{135, 11, 861}, - dictWord{139, 0, 499}, - dictWord{7, 0, 476}, - dictWord{7, 0, 1592}, - dictWord{138, 0, 87}, - dictWord{133, 10, 684}, - dictWord{ - 4, - 0, - 840, - }, - dictWord{134, 10, 27}, - dictWord{142, 0, 283}, - dictWord{6, 0, 1620}, - dictWord{7, 11, 1328}, - dictWord{136, 11, 494}, - dictWord{5, 0, 859}, - dictWord{ - 7, - 0, - 1160, - }, - dictWord{8, 0, 107}, - dictWord{9, 0, 291}, - dictWord{9, 0, 439}, - dictWord{10, 0, 663}, - dictWord{11, 0, 609}, - dictWord{140, 0, 197}, - dictWord{ - 7, - 11, - 1306, - }, - dictWord{8, 11, 505}, - dictWord{9, 11, 482}, - dictWord{10, 11, 126}, - dictWord{11, 11, 225}, - dictWord{12, 11, 347}, - dictWord{12, 11, 449}, - dictWord{ - 13, - 11, - 19, - }, - dictWord{142, 11, 218}, - dictWord{5, 11, 268}, - dictWord{10, 11, 764}, - dictWord{12, 11, 120}, - dictWord{13, 11, 39}, - dictWord{145, 11, 127}, - dictWord{145, 10, 56}, - dictWord{7, 11, 1672}, - dictWord{10, 11, 472}, - dictWord{11, 11, 189}, - dictWord{143, 11, 51}, - dictWord{6, 10, 342}, - dictWord{6, 10, 496}, - dictWord{8, 10, 275}, - dictWord{137, 10, 206}, - dictWord{133, 0, 600}, - dictWord{4, 0, 117}, - dictWord{6, 0, 372}, - dictWord{7, 0, 1905}, - dictWord{142, 0, 323}, - dictWord{4, 10, 909}, - dictWord{5, 10, 940}, - dictWord{135, 11, 1471}, - dictWord{132, 10, 891}, - dictWord{4, 0, 722}, - dictWord{139, 0, 471}, - dictWord{4, 11, 384}, - dictWord{135, 11, 1022}, - dictWord{132, 10, 687}, - dictWord{9, 0, 5}, - dictWord{12, 0, 216}, - dictWord{12, 0, 294}, - dictWord{12, 0, 298}, - dictWord{12, 0, 400}, - dictWord{12, 0, 518}, - dictWord{13, 0, 229}, - dictWord{143, 0, 139}, - dictWord{135, 11, 1703}, - dictWord{7, 11, 1602}, - dictWord{10, 11, 698}, - dictWord{ - 12, - 11, - 212, - }, - dictWord{141, 11, 307}, - dictWord{6, 10, 41}, - dictWord{141, 10, 160}, - dictWord{135, 11, 1077}, - dictWord{9, 11, 159}, - dictWord{11, 11, 28}, - dictWord{140, 11, 603}, - dictWord{4, 0, 514}, - dictWord{7, 0, 1304}, - dictWord{138, 0, 477}, - dictWord{134, 0, 1774}, - dictWord{9, 0, 88}, - dictWord{139, 0, 270}, - dictWord{5, 0, 12}, - dictWord{7, 0, 375}, - dictWord{9, 0, 438}, - dictWord{134, 10, 1718}, - dictWord{132, 11, 515}, - dictWord{136, 10, 778}, - dictWord{8, 11, 632}, - dictWord{8, 11, 697}, - dictWord{137, 11, 854}, - dictWord{6, 0, 362}, - dictWord{6, 0, 997}, - dictWord{146, 0, 51}, - dictWord{7, 0, 816}, - dictWord{7, 0, 1241}, - dictWord{ - 9, - 0, - 283, - }, - dictWord{9, 0, 520}, - dictWord{10, 0, 213}, - dictWord{10, 0, 307}, - dictWord{10, 0, 463}, - dictWord{10, 0, 671}, - dictWord{10, 0, 746}, - dictWord{11, 0, 401}, - dictWord{11, 0, 794}, - dictWord{12, 0, 517}, - dictWord{18, 0, 107}, - dictWord{147, 0, 115}, - dictWord{133, 10, 115}, - dictWord{150, 11, 28}, - dictWord{4, 11, 136}, - dictWord{133, 11, 551}, - dictWord{142, 10, 314}, - dictWord{132, 0, 258}, - dictWord{6, 0, 22}, - dictWord{7, 0, 903}, - dictWord{7, 0, 1963}, - dictWord{8, 0, 639}, - dictWord{138, 0, 577}, - dictWord{5, 0, 681}, - dictWord{8, 0, 782}, - dictWord{13, 0, 130}, - dictWord{17, 0, 84}, - dictWord{5, 10, 193}, - dictWord{140, 10, 178}, - dictWord{ - 9, - 11, - 17, - }, - dictWord{138, 11, 291}, - dictWord{7, 11, 1287}, - dictWord{9, 11, 44}, - dictWord{10, 11, 552}, - dictWord{10, 11, 642}, - dictWord{11, 11, 839}, - dictWord{12, 11, 274}, - dictWord{12, 11, 275}, - dictWord{12, 11, 372}, - dictWord{13, 11, 91}, - dictWord{142, 11, 125}, - dictWord{135, 10, 174}, - dictWord{4, 0, 664}, - dictWord{5, 0, 804}, - dictWord{139, 0, 1013}, - dictWord{134, 0, 942}, - dictWord{6, 0, 1349}, - dictWord{6, 0, 1353}, - dictWord{6, 0, 1450}, - dictWord{7, 11, 1518}, - dictWord{139, 11, 694}, - dictWord{11, 0, 356}, - dictWord{4, 10, 122}, - dictWord{5, 10, 796}, - dictWord{5, 10, 952}, - dictWord{6, 10, 1660}, - dictWord{ - 6, - 10, - 1671, - }, - dictWord{8, 10, 567}, - dictWord{9, 10, 687}, - dictWord{9, 10, 742}, - dictWord{10, 10, 686}, - dictWord{11, 10, 682}, - dictWord{140, 10, 281}, - dictWord{ - 5, - 0, - 32, - }, - dictWord{6, 11, 147}, - dictWord{7, 11, 886}, - dictWord{9, 11, 753}, - dictWord{138, 11, 268}, - dictWord{5, 10, 179}, - dictWord{7, 10, 1095}, - dictWord{ - 135, - 10, - 1213, - }, - dictWord{4, 10, 66}, - dictWord{7, 10, 722}, - dictWord{135, 10, 904}, - dictWord{135, 10, 352}, - dictWord{9, 11, 245}, - dictWord{138, 11, 137}, - dictWord{4, 0, 289}, - dictWord{7, 0, 629}, - dictWord{7, 0, 1698}, - dictWord{7, 0, 1711}, - dictWord{12, 0, 215}, - dictWord{133, 11, 414}, - dictWord{6, 0, 1975}, - dictWord{135, 11, 1762}, - dictWord{6, 0, 450}, - dictWord{136, 0, 109}, - dictWord{141, 10, 35}, - dictWord{134, 11, 599}, - dictWord{136, 0, 705}, - dictWord{ - 133, - 0, - 664, - }, - dictWord{134, 11, 1749}, - dictWord{11, 11, 402}, - dictWord{12, 11, 109}, - dictWord{12, 11, 431}, - dictWord{13, 11, 179}, - dictWord{13, 11, 206}, - dictWord{14, 11, 175}, - dictWord{14, 11, 217}, - dictWord{16, 11, 3}, - dictWord{148, 11, 53}, - dictWord{135, 0, 1238}, - dictWord{134, 11, 1627}, - dictWord{ - 132, - 11, - 488, - }, - dictWord{13, 0, 318}, - dictWord{10, 10, 592}, - dictWord{10, 10, 753}, - dictWord{12, 10, 317}, - dictWord{12, 10, 355}, - dictWord{12, 10, 465}, - dictWord{ - 12, - 10, - 469, - }, - dictWord{12, 10, 560}, - dictWord{140, 10, 578}, - dictWord{133, 10, 564}, - dictWord{132, 11, 83}, - dictWord{140, 11, 676}, - dictWord{6, 0, 1872}, - dictWord{6, 0, 1906}, - dictWord{6, 0, 1907}, - dictWord{9, 0, 934}, - dictWord{9, 0, 956}, - dictWord{9, 0, 960}, - dictWord{9, 0, 996}, - dictWord{12, 0, 794}, - dictWord{ - 12, - 0, - 876, - }, - dictWord{12, 0, 880}, - dictWord{12, 0, 918}, - dictWord{15, 0, 230}, - dictWord{18, 0, 234}, - dictWord{18, 0, 238}, - dictWord{21, 0, 38}, - dictWord{149, 0, 62}, - dictWord{134, 10, 556}, - dictWord{134, 11, 278}, - dictWord{137, 0, 103}, - dictWord{7, 10, 544}, - dictWord{8, 10, 719}, - dictWord{138, 10, 61}, - dictWord{ - 4, - 10, - 5, - }, - dictWord{5, 10, 498}, - dictWord{8, 10, 637}, - dictWord{137, 10, 521}, - dictWord{7, 0, 777}, - dictWord{12, 0, 229}, - dictWord{12, 0, 239}, - dictWord{15, 0, 12}, - dictWord{12, 11, 229}, - dictWord{12, 11, 239}, - dictWord{143, 11, 12}, - dictWord{6, 0, 26}, - dictWord{7, 11, 388}, - dictWord{7, 11, 644}, - dictWord{139, 11, 781}, - dictWord{7, 11, 229}, - dictWord{8, 11, 59}, - dictWord{9, 11, 190}, - dictWord{9, 11, 257}, - dictWord{10, 11, 378}, - dictWord{140, 11, 191}, - dictWord{133, 10, 927}, - dictWord{135, 10, 1441}, - dictWord{4, 10, 893}, - dictWord{5, 10, 780}, - dictWord{133, 10, 893}, - dictWord{4, 0, 414}, - dictWord{5, 0, 467}, - dictWord{9, 0, 654}, - dictWord{10, 0, 451}, - dictWord{12, 0, 59}, - dictWord{141, 0, 375}, - dictWord{142, 0, 173}, - dictWord{135, 0, 17}, - dictWord{7, 0, 1350}, - dictWord{133, 10, 238}, - dictWord{135, 0, 955}, - dictWord{4, 0, 960}, - dictWord{10, 0, 887}, - dictWord{12, 0, 753}, - dictWord{18, 0, 161}, - dictWord{18, 0, 162}, - dictWord{152, 0, 19}, - dictWord{136, 11, 344}, - dictWord{6, 10, 1729}, - dictWord{137, 11, 288}, - dictWord{132, 11, 660}, - dictWord{4, 0, 217}, - dictWord{5, 0, 710}, - dictWord{7, 0, 760}, - dictWord{7, 0, 1926}, - dictWord{9, 0, 428}, - dictWord{9, 0, 708}, - dictWord{10, 0, 254}, - dictWord{10, 0, 296}, - dictWord{10, 0, 720}, - dictWord{11, 0, 109}, - dictWord{ - 11, - 0, - 255, - }, - dictWord{12, 0, 165}, - dictWord{12, 0, 315}, - dictWord{13, 0, 107}, - dictWord{13, 0, 203}, - dictWord{14, 0, 54}, - dictWord{14, 0, 99}, - dictWord{14, 0, 114}, - dictWord{14, 0, 388}, - dictWord{16, 0, 85}, - dictWord{17, 0, 9}, - dictWord{17, 0, 33}, - dictWord{20, 0, 25}, - dictWord{20, 0, 28}, - dictWord{20, 0, 29}, - dictWord{21, 0, 9}, - dictWord{21, 0, 10}, - dictWord{21, 0, 34}, - dictWord{22, 0, 17}, - dictWord{4, 10, 60}, - dictWord{7, 10, 1800}, - dictWord{8, 10, 314}, - dictWord{9, 10, 700}, - dictWord{ - 139, - 10, - 487, - }, - dictWord{7, 11, 1035}, - dictWord{138, 11, 737}, - dictWord{7, 11, 690}, - dictWord{9, 11, 217}, - dictWord{9, 11, 587}, - dictWord{140, 11, 521}, - dictWord{6, 0, 919}, - dictWord{7, 11, 706}, - dictWord{7, 11, 1058}, - dictWord{138, 11, 538}, - dictWord{7, 10, 1853}, - dictWord{138, 10, 437}, - dictWord{ - 136, - 10, - 419, - }, - dictWord{6, 0, 280}, - dictWord{10, 0, 502}, - dictWord{11, 0, 344}, - dictWord{140, 0, 38}, - dictWord{5, 0, 45}, - dictWord{7, 0, 1161}, - dictWord{11, 0, 448}, - dictWord{11, 0, 880}, - dictWord{13, 0, 139}, - dictWord{13, 0, 407}, - dictWord{15, 0, 16}, - dictWord{17, 0, 95}, - dictWord{18, 0, 66}, - dictWord{18, 0, 88}, - dictWord{ - 18, - 0, - 123, - }, - dictWord{149, 0, 7}, - dictWord{11, 11, 92}, - dictWord{11, 11, 196}, - dictWord{11, 11, 409}, - dictWord{11, 11, 450}, - dictWord{11, 11, 666}, - dictWord{ - 11, - 11, - 777, - }, - dictWord{12, 11, 262}, - dictWord{13, 11, 385}, - dictWord{13, 11, 393}, - dictWord{15, 11, 115}, - dictWord{16, 11, 45}, - dictWord{145, 11, 82}, - dictWord{136, 0, 777}, - dictWord{134, 11, 1744}, - dictWord{4, 0, 410}, - dictWord{7, 0, 521}, - dictWord{133, 10, 828}, - dictWord{134, 0, 673}, - dictWord{7, 0, 1110}, - dictWord{7, 0, 1778}, - dictWord{7, 10, 176}, - dictWord{135, 10, 178}, - dictWord{5, 10, 806}, - dictWord{7, 11, 268}, - dictWord{7, 10, 1976}, - dictWord{ - 136, - 11, - 569, - }, - dictWord{4, 11, 733}, - dictWord{9, 11, 194}, - dictWord{10, 11, 92}, - dictWord{11, 11, 198}, - dictWord{12, 11, 84}, - dictWord{12, 11, 87}, - dictWord{ - 13, - 11, - 128, - }, - dictWord{144, 11, 74}, - dictWord{5, 0, 341}, - dictWord{7, 0, 1129}, - dictWord{11, 0, 414}, - dictWord{4, 10, 51}, - dictWord{6, 10, 4}, - dictWord{7, 10, 591}, - dictWord{7, 10, 849}, - dictWord{7, 10, 951}, - dictWord{7, 10, 1613}, - dictWord{7, 10, 1760}, - dictWord{7, 10, 1988}, - dictWord{9, 10, 434}, - dictWord{10, 10, 754}, - dictWord{11, 10, 25}, - dictWord{139, 10, 37}, - dictWord{133, 10, 902}, - dictWord{135, 10, 928}, - dictWord{135, 0, 787}, - dictWord{132, 0, 436}, - dictWord{ - 134, - 10, - 270, - }, - dictWord{7, 0, 1587}, - dictWord{135, 0, 1707}, - dictWord{6, 0, 377}, - dictWord{7, 0, 1025}, - dictWord{9, 0, 613}, - dictWord{145, 0, 104}, - dictWord{ - 7, - 11, - 982, - }, - dictWord{7, 11, 1361}, - dictWord{10, 11, 32}, - dictWord{143, 11, 56}, - dictWord{139, 0, 96}, - dictWord{132, 0, 451}, - dictWord{132, 10, 416}, - dictWord{ - 142, - 10, - 372, - }, - dictWord{5, 10, 152}, - dictWord{5, 10, 197}, - dictWord{7, 11, 306}, - dictWord{7, 10, 340}, - dictWord{7, 10, 867}, - dictWord{10, 10, 548}, - dictWord{ - 10, - 10, - 581, - }, - dictWord{11, 10, 6}, - dictWord{12, 10, 3}, - dictWord{12, 10, 19}, - dictWord{14, 10, 110}, - dictWord{142, 10, 289}, - dictWord{134, 0, 680}, - dictWord{ - 134, - 11, - 609, - }, - dictWord{7, 0, 483}, - dictWord{7, 10, 190}, - dictWord{8, 10, 28}, - dictWord{8, 10, 141}, - dictWord{8, 10, 444}, - dictWord{8, 10, 811}, - dictWord{ - 9, - 10, - 468, - }, - dictWord{11, 10, 334}, - dictWord{12, 10, 24}, - dictWord{12, 10, 386}, - dictWord{140, 10, 576}, - dictWord{10, 0, 916}, - dictWord{133, 10, 757}, - dictWord{ - 5, - 10, - 721, - }, - dictWord{135, 10, 1553}, - dictWord{133, 11, 178}, - dictWord{134, 0, 937}, - dictWord{132, 10, 898}, - dictWord{133, 0, 739}, - dictWord{ - 147, - 0, - 82, - }, - dictWord{135, 0, 663}, - dictWord{146, 0, 128}, - dictWord{5, 10, 277}, - dictWord{141, 10, 247}, - dictWord{134, 0, 1087}, - dictWord{132, 10, 435}, - dictWord{ - 6, - 11, - 381, - }, - dictWord{7, 11, 645}, - dictWord{7, 11, 694}, - dictWord{136, 11, 546}, - dictWord{7, 0, 503}, - dictWord{135, 0, 1885}, - dictWord{6, 0, 1965}, - dictWord{ - 8, - 0, - 925, - }, - dictWord{138, 0, 955}, - dictWord{4, 0, 113}, - dictWord{5, 0, 163}, - dictWord{5, 0, 735}, - dictWord{7, 0, 1009}, - dictWord{9, 0, 9}, - dictWord{9, 0, 771}, - dictWord{12, 0, 90}, - dictWord{13, 0, 138}, - dictWord{13, 0, 410}, - dictWord{143, 0, 128}, - dictWord{4, 0, 324}, - dictWord{138, 0, 104}, - dictWord{7, 0, 460}, - dictWord{ - 5, - 10, - 265, - }, - dictWord{134, 10, 212}, - dictWord{133, 11, 105}, - dictWord{7, 11, 261}, - dictWord{7, 11, 1107}, - dictWord{7, 11, 1115}, - dictWord{7, 11, 1354}, - dictWord{7, 11, 1588}, - dictWord{7, 11, 1705}, - dictWord{7, 11, 1902}, - dictWord{9, 11, 465}, - dictWord{10, 11, 248}, - dictWord{10, 11, 349}, - dictWord{10, 11, 647}, - dictWord{11, 11, 527}, - dictWord{11, 11, 660}, - dictWord{11, 11, 669}, - dictWord{12, 11, 529}, - dictWord{141, 11, 305}, - dictWord{5, 11, 438}, - dictWord{ - 9, - 11, - 694, - }, - dictWord{12, 11, 627}, - dictWord{141, 11, 210}, - dictWord{152, 11, 11}, - dictWord{4, 0, 935}, - dictWord{133, 0, 823}, - dictWord{132, 10, 702}, - dictWord{ - 5, - 0, - 269, - }, - dictWord{7, 0, 434}, - dictWord{7, 0, 891}, - dictWord{8, 0, 339}, - dictWord{9, 0, 702}, - dictWord{11, 0, 594}, - dictWord{11, 0, 718}, - dictWord{17, 0, 100}, - dictWord{5, 10, 808}, - dictWord{135, 10, 2045}, - dictWord{7, 0, 1014}, - dictWord{9, 0, 485}, - dictWord{141, 0, 264}, - dictWord{134, 0, 1713}, - dictWord{7, 0, 1810}, - dictWord{11, 0, 866}, - dictWord{12, 0, 103}, - dictWord{13, 0, 495}, - dictWord{140, 11, 233}, - dictWord{4, 0, 423}, - dictWord{10, 0, 949}, - dictWord{138, 0, 1013}, - dictWord{135, 0, 900}, - dictWord{8, 11, 25}, - dictWord{138, 11, 826}, - dictWord{5, 10, 166}, - dictWord{8, 10, 739}, - dictWord{140, 10, 511}, - dictWord{ - 134, - 0, - 2018, - }, - dictWord{7, 11, 1270}, - dictWord{139, 11, 612}, - dictWord{4, 10, 119}, - dictWord{5, 10, 170}, - dictWord{5, 10, 447}, - dictWord{7, 10, 1708}, - dictWord{ - 7, - 10, - 1889, - }, - dictWord{9, 10, 357}, - dictWord{9, 10, 719}, - dictWord{12, 10, 486}, - dictWord{140, 10, 596}, - dictWord{12, 0, 574}, - dictWord{140, 11, 574}, - dictWord{132, 11, 308}, - dictWord{6, 0, 964}, - dictWord{6, 0, 1206}, - dictWord{134, 0, 1302}, - dictWord{4, 10, 450}, - dictWord{135, 10, 1158}, - dictWord{ - 135, - 11, - 150, - }, - dictWord{136, 11, 649}, - dictWord{14, 0, 213}, - dictWord{148, 0, 38}, - dictWord{9, 11, 45}, - dictWord{9, 11, 311}, - dictWord{141, 11, 42}, - dictWord{ - 134, - 11, - 521, - }, - dictWord{7, 10, 1375}, - dictWord{7, 10, 1466}, - dictWord{138, 10, 331}, - dictWord{132, 10, 754}, - dictWord{5, 11, 339}, - dictWord{7, 11, 1442}, - dictWord{14, 11, 3}, - dictWord{15, 11, 41}, - dictWord{147, 11, 66}, - dictWord{136, 11, 378}, - dictWord{134, 0, 1022}, - dictWord{5, 10, 850}, - dictWord{136, 10, 799}, - dictWord{142, 0, 143}, - dictWord{135, 0, 2029}, - dictWord{134, 11, 1628}, - dictWord{8, 0, 523}, - dictWord{150, 0, 34}, - dictWord{5, 0, 625}, - dictWord{ - 135, - 0, - 1617, - }, - dictWord{7, 0, 275}, - dictWord{7, 10, 238}, - dictWord{7, 10, 2033}, - dictWord{8, 10, 120}, - dictWord{8, 10, 188}, - dictWord{8, 10, 659}, - dictWord{ - 9, - 10, - 598, - }, - dictWord{10, 10, 466}, - dictWord{12, 10, 342}, - dictWord{12, 10, 588}, - dictWord{13, 10, 503}, - dictWord{14, 10, 246}, - dictWord{143, 10, 92}, - dictWord{ - 7, - 0, - 37, - }, - dictWord{8, 0, 425}, - dictWord{8, 0, 693}, - dictWord{9, 0, 720}, - dictWord{10, 0, 380}, - dictWord{10, 0, 638}, - dictWord{11, 0, 273}, - dictWord{11, 0, 473}, - dictWord{12, 0, 61}, - dictWord{143, 0, 43}, - dictWord{135, 11, 829}, - dictWord{135, 0, 1943}, - dictWord{132, 0, 765}, - dictWord{5, 11, 486}, - dictWord{ - 135, - 11, - 1349, - }, - dictWord{7, 11, 1635}, - dictWord{8, 11, 17}, - dictWord{10, 11, 217}, - dictWord{138, 11, 295}, - dictWord{4, 10, 201}, - dictWord{7, 10, 1744}, - dictWord{ - 8, - 10, - 602, - }, - dictWord{11, 10, 247}, - dictWord{11, 10, 826}, - dictWord{145, 10, 65}, - dictWord{138, 11, 558}, - dictWord{11, 0, 551}, - dictWord{142, 0, 159}, - dictWord{8, 10, 164}, - dictWord{146, 10, 62}, - dictWord{139, 11, 176}, - dictWord{132, 0, 168}, - dictWord{136, 0, 1010}, - dictWord{134, 0, 1994}, - dictWord{ - 135, - 0, - 91, - }, - dictWord{138, 0, 532}, - dictWord{135, 10, 1243}, - dictWord{135, 0, 1884}, - dictWord{132, 10, 907}, - dictWord{5, 10, 100}, - dictWord{10, 10, 329}, - dictWord{12, 10, 416}, - dictWord{149, 10, 29}, - dictWord{134, 11, 447}, - dictWord{132, 10, 176}, - dictWord{5, 10, 636}, - dictWord{5, 10, 998}, - dictWord{7, 10, 9}, - dictWord{7, 10, 1508}, - dictWord{8, 10, 26}, - dictWord{9, 10, 317}, - dictWord{9, 10, 358}, - dictWord{10, 10, 210}, - dictWord{10, 10, 292}, - dictWord{10, 10, 533}, - dictWord{11, 10, 555}, - dictWord{12, 10, 526}, - dictWord{12, 10, 607}, - dictWord{13, 10, 263}, - dictWord{13, 10, 459}, - dictWord{142, 10, 271}, - dictWord{ - 4, - 11, - 609, - }, - dictWord{135, 11, 756}, - dictWord{6, 0, 15}, - dictWord{7, 0, 70}, - dictWord{10, 0, 240}, - dictWord{147, 0, 93}, - dictWord{4, 11, 930}, - dictWord{133, 11, 947}, - dictWord{134, 0, 1227}, - dictWord{134, 0, 1534}, - dictWord{133, 11, 939}, - dictWord{133, 11, 962}, - dictWord{5, 11, 651}, - dictWord{8, 11, 170}, - dictWord{ - 9, - 11, - 61, - }, - dictWord{9, 11, 63}, - dictWord{10, 11, 23}, - dictWord{10, 11, 37}, - dictWord{10, 11, 834}, - dictWord{11, 11, 4}, - dictWord{11, 11, 187}, - dictWord{ - 11, - 11, - 281, - }, - dictWord{11, 11, 503}, - dictWord{11, 11, 677}, - dictWord{12, 11, 96}, - dictWord{12, 11, 130}, - dictWord{12, 11, 244}, - dictWord{14, 11, 5}, - dictWord{ - 14, - 11, - 40, - }, - dictWord{14, 11, 162}, - dictWord{14, 11, 202}, - dictWord{146, 11, 133}, - dictWord{4, 11, 406}, - dictWord{5, 11, 579}, - dictWord{12, 11, 492}, - dictWord{ - 150, - 11, - 15, - }, - dictWord{139, 0, 392}, - dictWord{6, 10, 610}, - dictWord{10, 10, 127}, - dictWord{141, 10, 27}, - dictWord{7, 0, 655}, - dictWord{7, 0, 1844}, - dictWord{ - 136, - 10, - 119, - }, - dictWord{4, 0, 145}, - dictWord{6, 0, 176}, - dictWord{7, 0, 395}, - dictWord{137, 0, 562}, - dictWord{132, 0, 501}, - dictWord{140, 11, 145}, - dictWord{ - 136, - 0, - 1019, - }, - dictWord{134, 0, 509}, - dictWord{139, 0, 267}, - dictWord{6, 11, 17}, - dictWord{7, 11, 16}, - dictWord{7, 11, 1001}, - dictWord{7, 11, 1982}, - dictWord{ - 9, - 11, - 886, - }, - dictWord{10, 11, 489}, - dictWord{10, 11, 800}, - dictWord{11, 11, 782}, - dictWord{12, 11, 320}, - dictWord{13, 11, 467}, - dictWord{14, 11, 145}, - dictWord{14, 11, 387}, - dictWord{143, 11, 119}, - dictWord{145, 11, 17}, - dictWord{6, 0, 1099}, - dictWord{133, 11, 458}, - dictWord{7, 11, 1983}, - dictWord{8, 11, 0}, - dictWord{8, 11, 171}, - dictWord{9, 11, 120}, - dictWord{9, 11, 732}, - dictWord{10, 11, 473}, - dictWord{11, 11, 656}, - dictWord{11, 11, 998}, - dictWord{18, 11, 0}, - dictWord{18, 11, 2}, - dictWord{147, 11, 21}, - dictWord{12, 11, 427}, - dictWord{146, 11, 38}, - dictWord{10, 0, 948}, - dictWord{138, 0, 968}, - dictWord{7, 10, 126}, - dictWord{136, 10, 84}, - dictWord{136, 10, 790}, - dictWord{4, 0, 114}, - dictWord{9, 0, 492}, - dictWord{13, 0, 462}, - dictWord{142, 0, 215}, - dictWord{6, 10, 64}, - dictWord{12, 10, 377}, - dictWord{141, 10, 309}, - dictWord{4, 0, 77}, - dictWord{5, 0, 361}, - dictWord{6, 0, 139}, - dictWord{6, 0, 401}, - dictWord{6, 0, 404}, - dictWord{ - 7, - 0, - 413, - }, - dictWord{7, 0, 715}, - dictWord{7, 0, 1716}, - dictWord{11, 0, 279}, - dictWord{12, 0, 179}, - dictWord{12, 0, 258}, - dictWord{13, 0, 244}, - dictWord{142, 0, 358}, - dictWord{134, 0, 1717}, - dictWord{7, 0, 772}, - dictWord{7, 0, 1061}, - dictWord{7, 0, 1647}, - dictWord{8, 0, 82}, - dictWord{11, 0, 250}, - dictWord{11, 0, 607}, - dictWord{12, 0, 311}, - dictWord{12, 0, 420}, - dictWord{13, 0, 184}, - dictWord{13, 0, 367}, - dictWord{7, 10, 1104}, - dictWord{11, 10, 269}, - dictWord{11, 10, 539}, - dictWord{11, 10, 627}, - dictWord{11, 10, 706}, - dictWord{11, 10, 975}, - dictWord{12, 10, 248}, - dictWord{12, 10, 434}, - dictWord{12, 10, 600}, - dictWord{ - 12, - 10, - 622, - }, - dictWord{13, 10, 297}, - dictWord{13, 10, 485}, - dictWord{14, 10, 69}, - dictWord{14, 10, 409}, - dictWord{143, 10, 108}, - dictWord{135, 0, 724}, - dictWord{ - 4, - 11, - 512, - }, - dictWord{4, 11, 519}, - dictWord{133, 11, 342}, - dictWord{134, 0, 1133}, - dictWord{145, 11, 29}, - dictWord{11, 10, 977}, - dictWord{141, 10, 507}, - dictWord{6, 0, 841}, - dictWord{6, 0, 1042}, - dictWord{6, 0, 1194}, - dictWord{10, 0, 993}, - dictWord{140, 0, 1021}, - dictWord{6, 11, 31}, - dictWord{7, 11, 491}, - dictWord{7, 11, 530}, - dictWord{8, 11, 592}, - dictWord{9, 10, 34}, - dictWord{11, 11, 53}, - dictWord{11, 10, 484}, - dictWord{11, 11, 779}, - dictWord{12, 11, 167}, - dictWord{12, 11, 411}, - dictWord{14, 11, 14}, - dictWord{14, 11, 136}, - dictWord{15, 11, 72}, - dictWord{16, 11, 17}, - dictWord{144, 11, 72}, - dictWord{4, 0, 1021}, - dictWord{6, 0, 2037}, - dictWord{133, 11, 907}, - dictWord{7, 0, 373}, - dictWord{8, 0, 335}, - dictWord{8, 0, 596}, - dictWord{9, 0, 488}, - dictWord{6, 10, 1700}, - dictWord{ - 7, - 10, - 293, - }, - dictWord{7, 10, 382}, - dictWord{7, 10, 1026}, - dictWord{7, 10, 1087}, - dictWord{7, 10, 2027}, - dictWord{8, 10, 252}, - dictWord{8, 10, 727}, - dictWord{ - 8, - 10, - 729, - }, - dictWord{9, 10, 30}, - dictWord{9, 10, 199}, - dictWord{9, 10, 231}, - dictWord{9, 10, 251}, - dictWord{9, 10, 334}, - dictWord{9, 10, 361}, - dictWord{9, 10, 712}, - dictWord{10, 10, 55}, - dictWord{10, 10, 60}, - dictWord{10, 10, 232}, - dictWord{10, 10, 332}, - dictWord{10, 10, 384}, - dictWord{10, 10, 396}, - dictWord{ - 10, - 10, - 504, - }, - dictWord{10, 10, 542}, - dictWord{10, 10, 652}, - dictWord{11, 10, 20}, - dictWord{11, 10, 48}, - dictWord{11, 10, 207}, - dictWord{11, 10, 291}, - dictWord{ - 11, - 10, - 298, - }, - dictWord{11, 10, 342}, - dictWord{11, 10, 365}, - dictWord{11, 10, 394}, - dictWord{11, 10, 620}, - dictWord{11, 10, 705}, - dictWord{11, 10, 1017}, - dictWord{12, 10, 123}, - dictWord{12, 10, 340}, - dictWord{12, 10, 406}, - dictWord{12, 10, 643}, - dictWord{13, 10, 61}, - dictWord{13, 10, 269}, - dictWord{ - 13, - 10, - 311, - }, - dictWord{13, 10, 319}, - dictWord{13, 10, 486}, - dictWord{14, 10, 234}, - dictWord{15, 10, 62}, - dictWord{15, 10, 85}, - dictWord{16, 10, 71}, - dictWord{ - 18, - 10, - 119, - }, - dictWord{148, 10, 105}, - dictWord{150, 0, 37}, - dictWord{4, 11, 208}, - dictWord{5, 11, 106}, - dictWord{6, 11, 531}, - dictWord{8, 11, 408}, - dictWord{ - 9, - 11, - 188, - }, - dictWord{138, 11, 572}, - dictWord{132, 0, 564}, - dictWord{6, 0, 513}, - dictWord{135, 0, 1052}, - dictWord{132, 0, 825}, - dictWord{9, 0, 899}, - dictWord{ - 140, - 11, - 441, - }, - dictWord{134, 0, 778}, - dictWord{133, 11, 379}, - dictWord{7, 0, 1417}, - dictWord{12, 0, 382}, - dictWord{17, 0, 48}, - dictWord{152, 0, 12}, - dictWord{ - 132, - 11, - 241, - }, - dictWord{7, 0, 1116}, - dictWord{6, 10, 379}, - dictWord{7, 10, 270}, - dictWord{8, 10, 176}, - dictWord{8, 10, 183}, - dictWord{9, 10, 432}, - dictWord{ - 9, - 10, - 661, - }, - dictWord{12, 10, 247}, - dictWord{12, 10, 617}, - dictWord{146, 10, 125}, - dictWord{5, 10, 792}, - dictWord{133, 10, 900}, - dictWord{6, 0, 545}, - dictWord{ - 7, - 0, - 565, - }, - dictWord{7, 0, 1669}, - dictWord{10, 0, 114}, - dictWord{11, 0, 642}, - dictWord{140, 0, 618}, - dictWord{133, 0, 5}, - dictWord{138, 11, 7}, - dictWord{ - 132, - 11, - 259, - }, - dictWord{135, 0, 192}, - dictWord{134, 0, 701}, - dictWord{136, 0, 763}, - dictWord{135, 10, 1979}, - dictWord{4, 10, 901}, - dictWord{133, 10, 776}, - dictWord{10, 0, 755}, - dictWord{147, 0, 29}, - dictWord{133, 0, 759}, - dictWord{4, 11, 173}, - dictWord{5, 11, 312}, - dictWord{5, 11, 512}, - dictWord{135, 11, 1285}, - dictWord{7, 11, 1603}, - dictWord{7, 11, 1691}, - dictWord{9, 11, 464}, - dictWord{11, 11, 195}, - dictWord{12, 11, 279}, - dictWord{12, 11, 448}, - dictWord{ - 14, - 11, - 11, - }, - dictWord{147, 11, 102}, - dictWord{7, 0, 370}, - dictWord{7, 0, 1007}, - dictWord{7, 0, 1177}, - dictWord{135, 0, 1565}, - dictWord{135, 0, 1237}, - dictWord{ - 4, - 0, - 87, - }, - dictWord{5, 0, 250}, - dictWord{141, 0, 298}, - dictWord{4, 11, 452}, - dictWord{5, 11, 583}, - dictWord{5, 11, 817}, - dictWord{6, 11, 433}, - dictWord{7, 11, 593}, - dictWord{7, 11, 720}, - dictWord{7, 11, 1378}, - dictWord{8, 11, 161}, - dictWord{9, 11, 284}, - dictWord{10, 11, 313}, - dictWord{139, 11, 886}, - dictWord{4, 11, 547}, - dictWord{135, 11, 1409}, - dictWord{136, 11, 722}, - dictWord{4, 10, 37}, - dictWord{5, 10, 334}, - dictWord{135, 10, 1253}, - dictWord{132, 10, 508}, - dictWord{ - 12, - 0, - 107, - }, - dictWord{146, 0, 31}, - dictWord{8, 11, 420}, - dictWord{139, 11, 193}, - dictWord{135, 0, 814}, - dictWord{135, 11, 409}, - dictWord{140, 0, 991}, - dictWord{4, 0, 57}, - dictWord{7, 0, 1195}, - dictWord{7, 0, 1438}, - dictWord{7, 0, 1548}, - dictWord{7, 0, 1835}, - dictWord{7, 0, 1904}, - dictWord{9, 0, 757}, - dictWord{ - 10, - 0, - 604, - }, - dictWord{139, 0, 519}, - dictWord{132, 0, 540}, - dictWord{138, 11, 308}, - dictWord{132, 10, 533}, - dictWord{136, 0, 608}, - dictWord{144, 11, 65}, - dictWord{4, 0, 1014}, - dictWord{134, 0, 2029}, - dictWord{4, 0, 209}, - dictWord{7, 0, 902}, - dictWord{5, 11, 1002}, - dictWord{136, 11, 745}, - dictWord{134, 0, 2030}, - dictWord{6, 0, 303}, - dictWord{7, 0, 335}, - dictWord{7, 0, 1437}, - dictWord{7, 0, 1668}, - dictWord{8, 0, 553}, - dictWord{8, 0, 652}, - dictWord{8, 0, 656}, - dictWord{ - 9, - 0, - 558, - }, - dictWord{11, 0, 743}, - dictWord{149, 0, 18}, - dictWord{5, 11, 575}, - dictWord{6, 11, 354}, - dictWord{135, 11, 701}, - dictWord{4, 11, 239}, - dictWord{ - 6, - 11, - 477, - }, - dictWord{7, 11, 1607}, - dictWord{11, 11, 68}, - dictWord{139, 11, 617}, - dictWord{132, 0, 559}, - dictWord{8, 0, 527}, - dictWord{18, 0, 60}, - dictWord{ - 147, - 0, - 24, - }, - dictWord{133, 10, 920}, - dictWord{138, 0, 511}, - dictWord{133, 0, 1017}, - dictWord{133, 0, 675}, - dictWord{138, 10, 391}, - dictWord{11, 0, 156}, - dictWord{135, 10, 1952}, - dictWord{138, 11, 369}, - dictWord{132, 11, 367}, - dictWord{133, 0, 709}, - dictWord{6, 0, 698}, - dictWord{134, 0, 887}, - dictWord{ - 142, - 10, - 126, - }, - dictWord{134, 0, 1745}, - dictWord{132, 10, 483}, - dictWord{13, 11, 299}, - dictWord{142, 11, 75}, - dictWord{133, 0, 714}, - dictWord{7, 0, 8}, - dictWord{ - 136, - 0, - 206, - }, - dictWord{138, 10, 480}, - dictWord{4, 11, 694}, - dictWord{9, 10, 495}, - dictWord{146, 10, 104}, - dictWord{7, 11, 1248}, - dictWord{11, 11, 621}, - dictWord{139, 11, 702}, - dictWord{140, 11, 687}, - dictWord{132, 0, 776}, - dictWord{139, 10, 1009}, - dictWord{135, 0, 1272}, - dictWord{134, 0, 1059}, - dictWord{ - 8, - 10, - 653, - }, - dictWord{13, 10, 93}, - dictWord{147, 10, 14}, - dictWord{135, 11, 213}, - dictWord{136, 0, 406}, - dictWord{133, 10, 172}, - dictWord{132, 0, 947}, - dictWord{8, 0, 175}, - dictWord{10, 0, 168}, - dictWord{138, 0, 573}, - dictWord{132, 0, 870}, - dictWord{6, 0, 1567}, - dictWord{151, 11, 28}, - dictWord{ - 134, - 11, - 472, - }, - dictWord{5, 10, 260}, - dictWord{136, 11, 132}, - dictWord{4, 11, 751}, - dictWord{11, 11, 390}, - dictWord{140, 11, 32}, - dictWord{4, 11, 409}, - dictWord{ - 133, - 11, - 78, - }, - dictWord{12, 0, 554}, - dictWord{6, 11, 473}, - dictWord{145, 11, 105}, - dictWord{133, 0, 784}, - dictWord{8, 0, 908}, - dictWord{136, 11, 306}, - dictWord{139, 0, 882}, - dictWord{6, 0, 358}, - dictWord{7, 0, 1393}, - dictWord{8, 0, 396}, - dictWord{10, 0, 263}, - dictWord{14, 0, 154}, - dictWord{16, 0, 48}, - dictWord{ - 17, - 0, - 8, - }, - dictWord{7, 11, 1759}, - dictWord{8, 11, 396}, - dictWord{10, 11, 263}, - dictWord{14, 11, 154}, - dictWord{16, 11, 48}, - dictWord{145, 11, 8}, - dictWord{ - 13, - 11, - 163, - }, - dictWord{13, 11, 180}, - dictWord{18, 11, 78}, - dictWord{148, 11, 35}, - dictWord{14, 0, 32}, - dictWord{18, 0, 85}, - dictWord{20, 0, 2}, - dictWord{152, 0, 16}, - dictWord{7, 0, 228}, - dictWord{10, 0, 770}, - dictWord{8, 10, 167}, - dictWord{8, 10, 375}, - dictWord{9, 10, 82}, - dictWord{9, 10, 561}, - dictWord{138, 10, 620}, - dictWord{132, 0, 845}, - dictWord{9, 0, 14}, - dictWord{9, 0, 441}, - dictWord{10, 0, 306}, - dictWord{139, 0, 9}, - dictWord{11, 0, 966}, - dictWord{12, 0, 287}, - dictWord{ - 13, - 0, - 342, - }, - dictWord{13, 0, 402}, - dictWord{15, 0, 110}, - dictWord{15, 0, 163}, - dictWord{8, 10, 194}, - dictWord{136, 10, 756}, - dictWord{134, 0, 1578}, - dictWord{ - 4, - 0, - 967, - }, - dictWord{6, 0, 1820}, - dictWord{6, 0, 1847}, - dictWord{140, 0, 716}, - dictWord{136, 0, 594}, - dictWord{7, 0, 1428}, - dictWord{7, 0, 1640}, - dictWord{ - 7, - 0, - 1867, - }, - dictWord{9, 0, 169}, - dictWord{9, 0, 182}, - dictWord{9, 0, 367}, - dictWord{9, 0, 478}, - dictWord{9, 0, 506}, - dictWord{9, 0, 551}, - dictWord{9, 0, 557}, - dictWord{ - 9, - 0, - 648, - }, - dictWord{9, 0, 697}, - dictWord{9, 0, 705}, - dictWord{9, 0, 725}, - dictWord{9, 0, 787}, - dictWord{9, 0, 794}, - dictWord{10, 0, 198}, - dictWord{10, 0, 214}, - dictWord{10, 0, 267}, - dictWord{10, 0, 275}, - dictWord{10, 0, 456}, - dictWord{10, 0, 551}, - dictWord{10, 0, 561}, - dictWord{10, 0, 613}, - dictWord{10, 0, 627}, - dictWord{ - 10, - 0, - 668, - }, - dictWord{10, 0, 675}, - dictWord{10, 0, 691}, - dictWord{10, 0, 695}, - dictWord{10, 0, 707}, - dictWord{10, 0, 715}, - dictWord{11, 0, 183}, - dictWord{ - 11, - 0, - 201, - }, - dictWord{11, 0, 244}, - dictWord{11, 0, 262}, - dictWord{11, 0, 352}, - dictWord{11, 0, 439}, - dictWord{11, 0, 493}, - dictWord{11, 0, 572}, - dictWord{11, 0, 591}, - dictWord{11, 0, 608}, - dictWord{11, 0, 611}, - dictWord{11, 0, 646}, - dictWord{11, 0, 674}, - dictWord{11, 0, 711}, - dictWord{11, 0, 751}, - dictWord{11, 0, 761}, - dictWord{11, 0, 776}, - dictWord{11, 0, 785}, - dictWord{11, 0, 850}, - dictWord{11, 0, 853}, - dictWord{11, 0, 862}, - dictWord{11, 0, 865}, - dictWord{11, 0, 868}, - dictWord{ - 11, - 0, - 875, - }, - dictWord{11, 0, 898}, - dictWord{11, 0, 902}, - dictWord{11, 0, 903}, - dictWord{11, 0, 910}, - dictWord{11, 0, 932}, - dictWord{11, 0, 942}, - dictWord{ - 11, - 0, - 957, - }, - dictWord{11, 0, 967}, - dictWord{11, 0, 972}, - dictWord{12, 0, 148}, - dictWord{12, 0, 195}, - dictWord{12, 0, 220}, - dictWord{12, 0, 237}, - dictWord{12, 0, 318}, - dictWord{12, 0, 339}, - dictWord{12, 0, 393}, - dictWord{12, 0, 445}, - dictWord{12, 0, 450}, - dictWord{12, 0, 474}, - dictWord{12, 0, 505}, - dictWord{12, 0, 509}, - dictWord{12, 0, 533}, - dictWord{12, 0, 591}, - dictWord{12, 0, 594}, - dictWord{12, 0, 597}, - dictWord{12, 0, 621}, - dictWord{12, 0, 633}, - dictWord{12, 0, 642}, - dictWord{ - 13, - 0, - 59, - }, - dictWord{13, 0, 60}, - dictWord{13, 0, 145}, - dictWord{13, 0, 239}, - dictWord{13, 0, 250}, - dictWord{13, 0, 329}, - dictWord{13, 0, 344}, - dictWord{13, 0, 365}, - dictWord{13, 0, 372}, - dictWord{13, 0, 387}, - dictWord{13, 0, 403}, - dictWord{13, 0, 414}, - dictWord{13, 0, 456}, - dictWord{13, 0, 470}, - dictWord{13, 0, 478}, - dictWord{13, 0, 483}, - dictWord{13, 0, 489}, - dictWord{14, 0, 55}, - dictWord{14, 0, 57}, - dictWord{14, 0, 81}, - dictWord{14, 0, 90}, - dictWord{14, 0, 148}, - dictWord{ - 14, - 0, - 239, - }, - dictWord{14, 0, 266}, - dictWord{14, 0, 321}, - dictWord{14, 0, 326}, - dictWord{14, 0, 327}, - dictWord{14, 0, 330}, - dictWord{14, 0, 347}, - dictWord{14, 0, 355}, - dictWord{14, 0, 401}, - dictWord{14, 0, 404}, - dictWord{14, 0, 411}, - dictWord{14, 0, 414}, - dictWord{14, 0, 416}, - dictWord{14, 0, 420}, - dictWord{15, 0, 61}, - dictWord{15, 0, 74}, - dictWord{15, 0, 87}, - dictWord{15, 0, 88}, - dictWord{15, 0, 94}, - dictWord{15, 0, 96}, - dictWord{15, 0, 116}, - dictWord{15, 0, 149}, - dictWord{15, 0, 154}, - dictWord{16, 0, 50}, - dictWord{16, 0, 63}, - dictWord{16, 0, 73}, - dictWord{17, 0, 2}, - dictWord{17, 0, 66}, - dictWord{17, 0, 92}, - dictWord{17, 0, 103}, - dictWord{ - 17, - 0, - 112, - }, - dictWord{17, 0, 120}, - dictWord{18, 0, 50}, - dictWord{18, 0, 54}, - dictWord{18, 0, 82}, - dictWord{18, 0, 86}, - dictWord{18, 0, 90}, - dictWord{18, 0, 111}, - dictWord{ - 18, - 0, - 115, - }, - dictWord{18, 0, 156}, - dictWord{19, 0, 40}, - dictWord{19, 0, 79}, - dictWord{20, 0, 78}, - dictWord{21, 0, 22}, - dictWord{135, 11, 883}, - dictWord{5, 0, 161}, - dictWord{135, 0, 839}, - dictWord{4, 0, 782}, - dictWord{13, 11, 293}, - dictWord{142, 11, 56}, - dictWord{133, 11, 617}, - dictWord{139, 11, 50}, - dictWord{ - 135, - 10, - 22, - }, - dictWord{145, 0, 64}, - dictWord{5, 10, 639}, - dictWord{7, 10, 1249}, - dictWord{139, 10, 896}, - dictWord{138, 0, 998}, - dictWord{135, 11, 2042}, - dictWord{ - 4, - 11, - 546, - }, - dictWord{142, 11, 233}, - dictWord{6, 0, 1043}, - dictWord{134, 0, 1574}, - dictWord{134, 0, 1496}, - dictWord{4, 10, 102}, - dictWord{7, 10, 815}, - dictWord{7, 10, 1699}, - dictWord{139, 10, 964}, - dictWord{12, 0, 781}, - dictWord{142, 0, 461}, - dictWord{4, 11, 313}, - dictWord{133, 11, 577}, - dictWord{ - 6, - 0, - 639, - }, - dictWord{6, 0, 1114}, - dictWord{137, 0, 817}, - dictWord{8, 11, 184}, - dictWord{141, 11, 433}, - dictWord{7, 0, 1814}, - dictWord{135, 11, 935}, - dictWord{ - 10, - 0, - 997, - }, - dictWord{140, 0, 958}, - dictWord{4, 0, 812}, - dictWord{137, 11, 625}, - dictWord{132, 10, 899}, - dictWord{136, 10, 795}, - dictWord{5, 11, 886}, - dictWord{6, 11, 46}, - dictWord{6, 11, 1790}, - dictWord{7, 11, 14}, - dictWord{7, 11, 732}, - dictWord{7, 11, 1654}, - dictWord{8, 11, 95}, - dictWord{8, 11, 327}, - dictWord{ - 8, - 11, - 616, - }, - dictWord{10, 11, 598}, - dictWord{10, 11, 769}, - dictWord{11, 11, 134}, - dictWord{11, 11, 747}, - dictWord{12, 11, 378}, - dictWord{142, 11, 97}, - dictWord{136, 0, 139}, - dictWord{6, 10, 52}, - dictWord{9, 10, 104}, - dictWord{9, 10, 559}, - dictWord{12, 10, 308}, - dictWord{147, 10, 87}, - dictWord{133, 11, 1021}, - dictWord{132, 10, 604}, - dictWord{132, 10, 301}, - dictWord{136, 10, 779}, - dictWord{7, 0, 643}, - dictWord{136, 0, 236}, - dictWord{132, 11, 153}, - dictWord{ - 134, - 0, - 1172, - }, - dictWord{147, 10, 32}, - dictWord{133, 11, 798}, - dictWord{6, 0, 1338}, - dictWord{132, 11, 587}, - dictWord{6, 11, 598}, - dictWord{7, 11, 42}, - dictWord{ - 8, - 11, - 695, - }, - dictWord{10, 11, 212}, - dictWord{11, 11, 158}, - dictWord{14, 11, 196}, - dictWord{145, 11, 85}, - dictWord{135, 10, 508}, - dictWord{5, 11, 957}, - dictWord{5, 11, 1008}, - dictWord{135, 11, 249}, - dictWord{4, 11, 129}, - dictWord{135, 11, 465}, - dictWord{5, 0, 54}, - dictWord{7, 11, 470}, - dictWord{7, 11, 1057}, - dictWord{7, 11, 1201}, - dictWord{9, 11, 755}, - dictWord{11, 11, 906}, - dictWord{140, 11, 527}, - dictWord{7, 11, 908}, - dictWord{146, 11, 7}, - dictWord{ - 5, - 11, - 148, - }, - dictWord{136, 11, 450}, - dictWord{144, 11, 1}, - dictWord{4, 0, 256}, - dictWord{135, 0, 1488}, - dictWord{9, 0, 351}, - dictWord{6, 10, 310}, - dictWord{ - 7, - 10, - 1849, - }, - dictWord{8, 10, 72}, - dictWord{8, 10, 272}, - dictWord{8, 10, 431}, - dictWord{9, 10, 12}, - dictWord{10, 10, 563}, - dictWord{10, 10, 630}, - dictWord{ - 10, - 10, - 796, - }, - dictWord{10, 10, 810}, - dictWord{11, 10, 367}, - dictWord{11, 10, 599}, - dictWord{11, 10, 686}, - dictWord{140, 10, 672}, - dictWord{6, 0, 1885}, - dictWord{ - 6, - 0, - 1898, - }, - dictWord{6, 0, 1899}, - dictWord{140, 0, 955}, - dictWord{4, 0, 714}, - dictWord{133, 0, 469}, - dictWord{6, 0, 1270}, - dictWord{134, 0, 1456}, - dictWord{132, 0, 744}, - dictWord{6, 0, 313}, - dictWord{7, 10, 537}, - dictWord{8, 10, 64}, - dictWord{9, 10, 127}, - dictWord{10, 10, 496}, - dictWord{12, 10, 510}, - dictWord{141, 10, 384}, - dictWord{4, 11, 217}, - dictWord{4, 10, 244}, - dictWord{5, 11, 710}, - dictWord{7, 10, 233}, - dictWord{7, 11, 1926}, - dictWord{9, 11, 428}, - dictWord{9, 11, 708}, - dictWord{10, 11, 254}, - dictWord{10, 11, 296}, - dictWord{10, 11, 720}, - dictWord{11, 11, 109}, - dictWord{11, 11, 255}, - dictWord{12, 11, 165}, - dictWord{12, 11, 315}, - dictWord{13, 11, 107}, - dictWord{13, 11, 203}, - dictWord{14, 11, 54}, - dictWord{14, 11, 99}, - dictWord{14, 11, 114}, - dictWord{ - 14, - 11, - 388, - }, - dictWord{16, 11, 85}, - dictWord{17, 11, 9}, - dictWord{17, 11, 33}, - dictWord{20, 11, 25}, - dictWord{20, 11, 28}, - dictWord{20, 11, 29}, - dictWord{21, 11, 9}, - dictWord{21, 11, 10}, - dictWord{21, 11, 34}, - dictWord{150, 11, 17}, - dictWord{138, 0, 402}, - dictWord{7, 0, 969}, - dictWord{146, 0, 55}, - dictWord{8, 0, 50}, - dictWord{ - 137, - 0, - 624, - }, - dictWord{134, 0, 1355}, - dictWord{132, 0, 572}, - dictWord{134, 10, 1650}, - dictWord{10, 10, 702}, - dictWord{139, 10, 245}, - dictWord{ - 10, - 0, - 847, - }, - dictWord{142, 0, 445}, - dictWord{6, 0, 43}, - dictWord{7, 0, 38}, - dictWord{8, 0, 248}, - dictWord{138, 0, 513}, - dictWord{133, 0, 369}, - dictWord{137, 10, 338}, - dictWord{133, 0, 766}, - dictWord{133, 0, 363}, - dictWord{133, 10, 896}, - dictWord{8, 11, 392}, - dictWord{11, 11, 54}, - dictWord{13, 11, 173}, - dictWord{ - 13, - 11, - 294, - }, - dictWord{148, 11, 7}, - dictWord{134, 0, 678}, - dictWord{7, 11, 1230}, - dictWord{136, 11, 531}, - dictWord{6, 0, 258}, - dictWord{140, 0, 409}, - dictWord{ - 5, - 0, - 249, - }, - dictWord{148, 0, 82}, - dictWord{7, 10, 1117}, - dictWord{136, 10, 539}, - dictWord{5, 0, 393}, - dictWord{6, 0, 378}, - dictWord{7, 0, 1981}, - dictWord{9, 0, 32}, - dictWord{9, 0, 591}, - dictWord{10, 0, 685}, - dictWord{10, 0, 741}, - dictWord{142, 0, 382}, - dictWord{133, 0, 788}, - dictWord{134, 0, 1281}, - dictWord{ - 134, - 0, - 1295, - }, - dictWord{7, 0, 1968}, - dictWord{141, 0, 509}, - dictWord{4, 0, 61}, - dictWord{5, 0, 58}, - dictWord{5, 0, 171}, - dictWord{5, 0, 683}, - dictWord{6, 0, 291}, - dictWord{ - 6, - 0, - 566, - }, - dictWord{7, 0, 1650}, - dictWord{11, 0, 523}, - dictWord{12, 0, 273}, - dictWord{12, 0, 303}, - dictWord{15, 0, 39}, - dictWord{143, 0, 111}, - dictWord{ - 6, - 0, - 706, - }, - dictWord{134, 0, 1283}, - dictWord{134, 0, 589}, - dictWord{135, 11, 1433}, - dictWord{133, 11, 435}, - dictWord{7, 0, 1059}, - dictWord{13, 0, 54}, - dictWord{ - 5, - 10, - 4, - }, - dictWord{5, 10, 810}, - dictWord{6, 10, 13}, - dictWord{6, 10, 538}, - dictWord{6, 10, 1690}, - dictWord{6, 10, 1726}, - dictWord{7, 10, 1819}, - dictWord{ - 8, - 10, - 148, - }, - dictWord{8, 10, 696}, - dictWord{8, 10, 791}, - dictWord{12, 10, 125}, - dictWord{143, 10, 9}, - dictWord{135, 10, 1268}, - dictWord{5, 11, 85}, - dictWord{ - 6, - 11, - 419, - }, - dictWord{7, 11, 134}, - dictWord{7, 11, 305}, - dictWord{7, 11, 361}, - dictWord{7, 11, 1337}, - dictWord{8, 11, 71}, - dictWord{140, 11, 519}, - dictWord{ - 137, - 0, - 824, - }, - dictWord{140, 11, 688}, - dictWord{5, 11, 691}, - dictWord{7, 11, 345}, - dictWord{7, 10, 1385}, - dictWord{9, 11, 94}, - dictWord{11, 10, 582}, - dictWord{ - 11, - 10, - 650, - }, - dictWord{11, 10, 901}, - dictWord{11, 10, 949}, - dictWord{12, 11, 169}, - dictWord{12, 10, 232}, - dictWord{12, 10, 236}, - dictWord{13, 10, 413}, - dictWord{13, 10, 501}, - dictWord{146, 10, 116}, - dictWord{4, 0, 917}, - dictWord{133, 0, 1005}, - dictWord{7, 0, 1598}, - dictWord{5, 11, 183}, - dictWord{6, 11, 582}, - dictWord{9, 11, 344}, - dictWord{10, 11, 679}, - dictWord{140, 11, 435}, - dictWord{4, 10, 925}, - dictWord{5, 10, 803}, - dictWord{8, 10, 698}, - dictWord{ - 138, - 10, - 828, - }, - dictWord{132, 0, 919}, - dictWord{135, 11, 511}, - dictWord{139, 10, 992}, - dictWord{4, 0, 255}, - dictWord{5, 0, 302}, - dictWord{6, 0, 132}, - dictWord{ - 7, - 0, - 128, - }, - dictWord{7, 0, 283}, - dictWord{7, 0, 1299}, - dictWord{10, 0, 52}, - dictWord{10, 0, 514}, - dictWord{11, 0, 925}, - dictWord{13, 0, 92}, - dictWord{142, 0, 309}, - dictWord{134, 0, 1369}, - dictWord{135, 10, 1847}, - dictWord{134, 0, 328}, - dictWord{7, 11, 1993}, - dictWord{136, 11, 684}, - dictWord{133, 10, 383}, - dictWord{137, 0, 173}, - dictWord{134, 11, 583}, - dictWord{134, 0, 1411}, - dictWord{19, 0, 65}, - dictWord{5, 11, 704}, - dictWord{8, 11, 357}, - dictWord{10, 11, 745}, - dictWord{14, 11, 426}, - dictWord{17, 11, 94}, - dictWord{147, 11, 57}, - dictWord{9, 10, 660}, - dictWord{138, 10, 347}, - dictWord{4, 11, 179}, - dictWord{5, 11, 198}, - dictWord{133, 11, 697}, - dictWord{7, 11, 347}, - dictWord{7, 11, 971}, - dictWord{8, 11, 181}, - dictWord{138, 11, 711}, - dictWord{141, 0, 442}, - dictWord{ - 11, - 0, - 842, - }, - dictWord{11, 0, 924}, - dictWord{13, 0, 317}, - dictWord{13, 0, 370}, - dictWord{13, 0, 469}, - dictWord{13, 0, 471}, - dictWord{14, 0, 397}, - dictWord{18, 0, 69}, - dictWord{18, 0, 145}, - dictWord{7, 10, 572}, - dictWord{9, 10, 592}, - dictWord{11, 10, 680}, - dictWord{12, 10, 356}, - dictWord{140, 10, 550}, - dictWord{14, 11, 19}, - dictWord{14, 11, 28}, - dictWord{144, 11, 29}, - dictWord{136, 0, 534}, - dictWord{4, 11, 243}, - dictWord{5, 11, 203}, - dictWord{7, 11, 19}, - dictWord{7, 11, 71}, - dictWord{7, 11, 113}, - dictWord{10, 11, 405}, - dictWord{11, 11, 357}, - dictWord{142, 11, 240}, - dictWord{6, 0, 210}, - dictWord{10, 0, 845}, - dictWord{138, 0, 862}, - dictWord{7, 11, 1351}, - dictWord{9, 11, 581}, - dictWord{10, 11, 639}, - dictWord{11, 11, 453}, - dictWord{140, 11, 584}, - dictWord{7, 11, 1450}, - dictWord{ - 139, - 11, - 99, - }, - dictWord{10, 0, 892}, - dictWord{12, 0, 719}, - dictWord{144, 0, 105}, - dictWord{4, 0, 284}, - dictWord{6, 0, 223}, - dictWord{134, 11, 492}, - dictWord{5, 11, 134}, - dictWord{6, 11, 408}, - dictWord{6, 11, 495}, - dictWord{135, 11, 1593}, - dictWord{136, 0, 529}, - dictWord{137, 0, 807}, - dictWord{4, 0, 218}, - dictWord{7, 0, 526}, - dictWord{143, 0, 137}, - dictWord{6, 0, 1444}, - dictWord{142, 11, 4}, - dictWord{132, 11, 665}, - dictWord{4, 0, 270}, - dictWord{5, 0, 192}, - dictWord{6, 0, 332}, - dictWord{7, 0, 1322}, - dictWord{4, 11, 248}, - dictWord{7, 11, 137}, - dictWord{137, 11, 349}, - dictWord{140, 0, 661}, - dictWord{7, 0, 1517}, - dictWord{11, 0, 597}, - dictWord{14, 0, 76}, - dictWord{14, 0, 335}, - dictWord{20, 0, 33}, - dictWord{7, 10, 748}, - dictWord{139, 10, 700}, - dictWord{5, 11, 371}, - dictWord{135, 11, 563}, - dictWord{146, 11, 57}, - dictWord{133, 10, 127}, - dictWord{133, 0, 418}, - dictWord{4, 11, 374}, - dictWord{7, 11, 547}, - dictWord{7, 11, 1700}, - dictWord{7, 11, 1833}, - dictWord{139, 11, 858}, - dictWord{6, 10, 198}, - dictWord{140, 10, 83}, - dictWord{7, 11, 1812}, - dictWord{13, 11, 259}, - dictWord{13, 11, 356}, - dictWord{ - 14, - 11, - 242, - }, - dictWord{147, 11, 114}, - dictWord{7, 0, 379}, - dictWord{8, 0, 481}, - dictWord{9, 0, 377}, - dictWord{5, 10, 276}, - dictWord{6, 10, 55}, - dictWord{ - 135, - 10, - 1369, - }, - dictWord{138, 11, 286}, - dictWord{5, 0, 1003}, - dictWord{6, 0, 149}, - dictWord{6, 10, 1752}, - dictWord{136, 10, 726}, - dictWord{8, 0, 262}, - dictWord{ - 9, - 0, - 627, - }, - dictWord{10, 0, 18}, - dictWord{11, 0, 214}, - dictWord{11, 0, 404}, - dictWord{11, 0, 457}, - dictWord{11, 0, 780}, - dictWord{11, 0, 913}, - dictWord{13, 0, 401}, - dictWord{14, 0, 200}, - dictWord{6, 11, 1647}, - dictWord{7, 11, 1552}, - dictWord{7, 11, 2010}, - dictWord{9, 11, 494}, - dictWord{137, 11, 509}, - dictWord{ - 135, - 0, - 742, - }, - dictWord{136, 0, 304}, - dictWord{132, 0, 142}, - dictWord{133, 10, 764}, - dictWord{6, 10, 309}, - dictWord{7, 10, 331}, - dictWord{138, 10, 550}, - dictWord{135, 10, 1062}, - dictWord{6, 11, 123}, - dictWord{7, 11, 214}, - dictWord{7, 10, 986}, - dictWord{9, 11, 728}, - dictWord{10, 11, 157}, - dictWord{11, 11, 346}, - dictWord{11, 11, 662}, - dictWord{143, 11, 106}, - dictWord{135, 10, 1573}, - dictWord{7, 0, 925}, - dictWord{137, 0, 799}, - dictWord{4, 0, 471}, - dictWord{5, 0, 51}, - dictWord{6, 0, 602}, - dictWord{8, 0, 484}, - dictWord{138, 0, 195}, - dictWord{136, 0, 688}, - dictWord{132, 0, 697}, - dictWord{6, 0, 1169}, - dictWord{6, 0, 1241}, - dictWord{6, 10, 194}, - dictWord{7, 10, 133}, - dictWord{10, 10, 493}, - dictWord{10, 10, 570}, - dictWord{139, 10, 664}, - dictWord{140, 0, 751}, - dictWord{7, 0, 929}, - dictWord{10, 0, 452}, - dictWord{11, 0, 878}, - dictWord{16, 0, 33}, - dictWord{5, 10, 24}, - dictWord{5, 10, 569}, - dictWord{6, 10, 3}, - dictWord{6, 10, 119}, - dictWord{ - 6, - 10, - 143, - }, - dictWord{6, 10, 440}, - dictWord{7, 10, 599}, - dictWord{7, 10, 1686}, - dictWord{7, 10, 1854}, - dictWord{8, 10, 424}, - dictWord{9, 10, 43}, - dictWord{ - 9, - 10, - 584, - }, - dictWord{9, 10, 760}, - dictWord{10, 10, 328}, - dictWord{11, 10, 159}, - dictWord{11, 10, 253}, - dictWord{12, 10, 487}, - dictWord{140, 10, 531}, - dictWord{ - 4, - 11, - 707, - }, - dictWord{13, 11, 106}, - dictWord{18, 11, 49}, - dictWord{147, 11, 41}, - dictWord{5, 0, 221}, - dictWord{5, 11, 588}, - dictWord{134, 11, 393}, - dictWord{134, 0, 1437}, - dictWord{6, 11, 211}, - dictWord{7, 11, 1690}, - dictWord{11, 11, 486}, - dictWord{140, 11, 369}, - dictWord{5, 10, 14}, - dictWord{5, 10, 892}, - dictWord{6, 10, 283}, - dictWord{7, 10, 234}, - dictWord{136, 10, 537}, - dictWord{4, 0, 988}, - dictWord{136, 0, 955}, - dictWord{135, 0, 1251}, - dictWord{4, 10, 126}, - dictWord{8, 10, 635}, - dictWord{147, 10, 34}, - dictWord{4, 10, 316}, - dictWord{135, 10, 1561}, - dictWord{137, 10, 861}, - dictWord{4, 10, 64}, - dictWord{ - 5, - 10, - 352, - }, - dictWord{5, 10, 720}, - dictWord{6, 10, 368}, - dictWord{139, 10, 359}, - dictWord{134, 0, 192}, - dictWord{4, 0, 132}, - dictWord{5, 0, 69}, - dictWord{ - 135, - 0, - 1242, - }, - dictWord{7, 10, 1577}, - dictWord{10, 10, 304}, - dictWord{10, 10, 549}, - dictWord{12, 10, 365}, - dictWord{13, 10, 220}, - dictWord{13, 10, 240}, - dictWord{142, 10, 33}, - dictWord{4, 0, 111}, - dictWord{7, 0, 865}, - dictWord{134, 11, 219}, - dictWord{5, 11, 582}, - dictWord{6, 11, 1646}, - dictWord{7, 11, 99}, - dictWord{ - 7, - 11, - 1962, - }, - dictWord{7, 11, 1986}, - dictWord{8, 11, 515}, - dictWord{8, 11, 773}, - dictWord{9, 11, 23}, - dictWord{9, 11, 491}, - dictWord{12, 11, 620}, - dictWord{ - 14, - 11, - 52, - }, - dictWord{145, 11, 50}, - dictWord{132, 0, 767}, - dictWord{7, 11, 568}, - dictWord{148, 11, 21}, - dictWord{6, 0, 42}, - dictWord{7, 0, 1416}, - dictWord{ - 7, - 0, - 2005, - }, - dictWord{8, 0, 131}, - dictWord{8, 0, 466}, - dictWord{9, 0, 672}, - dictWord{13, 0, 252}, - dictWord{20, 0, 103}, - dictWord{133, 11, 851}, - dictWord{ - 135, - 0, - 1050, - }, - dictWord{6, 10, 175}, - dictWord{137, 10, 289}, - dictWord{5, 10, 432}, - dictWord{133, 10, 913}, - dictWord{6, 0, 44}, - dictWord{136, 0, 368}, - dictWord{ - 135, - 11, - 784, - }, - dictWord{132, 0, 570}, - dictWord{133, 0, 120}, - dictWord{139, 10, 595}, - dictWord{140, 0, 29}, - dictWord{6, 0, 227}, - dictWord{135, 0, 1589}, - dictWord{4, 11, 98}, - dictWord{7, 11, 1365}, - dictWord{9, 11, 422}, - dictWord{9, 11, 670}, - dictWord{10, 11, 775}, - dictWord{11, 11, 210}, - dictWord{13, 11, 26}, - dictWord{13, 11, 457}, - dictWord{141, 11, 476}, - dictWord{140, 10, 80}, - dictWord{5, 10, 931}, - dictWord{134, 10, 1698}, - dictWord{133, 0, 522}, - dictWord{ - 134, - 0, - 1120, - }, - dictWord{135, 0, 1529}, - dictWord{12, 0, 739}, - dictWord{14, 0, 448}, - dictWord{142, 0, 467}, - dictWord{11, 10, 526}, - dictWord{11, 10, 939}, - dictWord{141, 10, 290}, - dictWord{5, 10, 774}, - dictWord{6, 10, 1637}, - dictWord{6, 10, 1686}, - dictWord{134, 10, 1751}, - dictWord{6, 0, 1667}, - dictWord{ - 135, - 0, - 2036, - }, - dictWord{7, 10, 1167}, - dictWord{11, 10, 934}, - dictWord{13, 10, 391}, - dictWord{145, 10, 76}, - dictWord{137, 11, 147}, - dictWord{6, 10, 260}, - dictWord{ - 7, - 10, - 1484, - }, - dictWord{11, 11, 821}, - dictWord{12, 11, 110}, - dictWord{12, 11, 153}, - dictWord{18, 11, 41}, - dictWord{150, 11, 19}, - dictWord{6, 0, 511}, - dictWord{12, 0, 132}, - dictWord{134, 10, 573}, - dictWord{5, 0, 568}, - dictWord{6, 0, 138}, - dictWord{135, 0, 1293}, - dictWord{132, 0, 1020}, - dictWord{8, 0, 258}, - dictWord{9, 0, 208}, - dictWord{137, 0, 359}, - dictWord{4, 0, 565}, - dictWord{8, 0, 23}, - dictWord{136, 0, 827}, - dictWord{134, 0, 344}, - dictWord{4, 0, 922}, - dictWord{ - 5, - 0, - 1023, - }, - dictWord{13, 11, 477}, - dictWord{14, 11, 120}, - dictWord{148, 11, 61}, - dictWord{134, 0, 240}, - dictWord{5, 11, 209}, - dictWord{6, 11, 30}, - dictWord{ - 11, - 11, - 56, - }, - dictWord{139, 11, 305}, - dictWord{6, 0, 171}, - dictWord{7, 0, 1002}, - dictWord{7, 0, 1324}, - dictWord{9, 0, 415}, - dictWord{14, 0, 230}, - dictWord{ - 18, - 0, - 68, - }, - dictWord{4, 10, 292}, - dictWord{4, 10, 736}, - dictWord{5, 10, 871}, - dictWord{6, 10, 1689}, - dictWord{7, 10, 1944}, - dictWord{137, 10, 580}, - dictWord{ - 9, - 11, - 635, - }, - dictWord{139, 11, 559}, - dictWord{4, 11, 150}, - dictWord{5, 11, 303}, - dictWord{134, 11, 327}, - dictWord{6, 10, 63}, - dictWord{135, 10, 920}, - dictWord{ - 133, - 10, - 793, - }, - dictWord{8, 11, 192}, - dictWord{10, 11, 78}, - dictWord{10, 11, 555}, - dictWord{11, 11, 308}, - dictWord{13, 11, 359}, - dictWord{147, 11, 95}, - dictWord{135, 11, 786}, - dictWord{135, 11, 1712}, - dictWord{136, 0, 402}, - dictWord{6, 0, 754}, - dictWord{6, 11, 1638}, - dictWord{7, 11, 79}, - dictWord{7, 11, 496}, - dictWord{9, 11, 138}, - dictWord{10, 11, 336}, - dictWord{11, 11, 12}, - dictWord{12, 11, 412}, - dictWord{12, 11, 440}, - dictWord{142, 11, 305}, - dictWord{4, 0, 716}, - dictWord{141, 0, 31}, - dictWord{133, 0, 982}, - dictWord{8, 0, 691}, - dictWord{8, 0, 731}, - dictWord{5, 10, 67}, - dictWord{6, 10, 62}, - dictWord{6, 10, 374}, - dictWord{ - 135, - 10, - 1391, - }, - dictWord{9, 10, 790}, - dictWord{140, 10, 47}, - dictWord{139, 11, 556}, - dictWord{151, 11, 1}, - dictWord{7, 11, 204}, - dictWord{7, 11, 415}, - dictWord{8, 11, 42}, - dictWord{10, 11, 85}, - dictWord{11, 11, 33}, - dictWord{11, 11, 564}, - dictWord{12, 11, 571}, - dictWord{149, 11, 1}, - dictWord{8, 0, 888}, - dictWord{ - 7, - 11, - 610, - }, - dictWord{135, 11, 1501}, - dictWord{4, 10, 391}, - dictWord{135, 10, 1169}, - dictWord{5, 0, 847}, - dictWord{9, 0, 840}, - dictWord{138, 0, 803}, - dictWord{137, 0, 823}, - dictWord{134, 0, 785}, - dictWord{8, 0, 152}, - dictWord{9, 0, 53}, - dictWord{9, 0, 268}, - dictWord{9, 0, 901}, - dictWord{10, 0, 518}, - dictWord{ - 10, - 0, - 829, - }, - dictWord{11, 0, 188}, - dictWord{13, 0, 74}, - dictWord{14, 0, 46}, - dictWord{15, 0, 17}, - dictWord{15, 0, 33}, - dictWord{17, 0, 40}, - dictWord{18, 0, 36}, - dictWord{ - 19, - 0, - 20, - }, - dictWord{22, 0, 1}, - dictWord{152, 0, 2}, - dictWord{4, 11, 3}, - dictWord{5, 11, 247}, - dictWord{5, 11, 644}, - dictWord{7, 11, 744}, - dictWord{7, 11, 1207}, - dictWord{7, 11, 1225}, - dictWord{7, 11, 1909}, - dictWord{146, 11, 147}, - dictWord{136, 0, 532}, - dictWord{135, 0, 681}, - dictWord{132, 10, 271}, - dictWord{ - 140, - 0, - 314, - }, - dictWord{140, 0, 677}, - dictWord{4, 0, 684}, - dictWord{136, 0, 384}, - dictWord{5, 11, 285}, - dictWord{9, 11, 67}, - dictWord{13, 11, 473}, - dictWord{ - 143, - 11, - 82, - }, - dictWord{4, 10, 253}, - dictWord{5, 10, 544}, - dictWord{7, 10, 300}, - dictWord{137, 10, 340}, - dictWord{7, 0, 110}, - dictWord{7, 0, 447}, - dictWord{8, 0, 290}, - dictWord{8, 0, 591}, - dictWord{9, 0, 382}, - dictWord{9, 0, 649}, - dictWord{11, 0, 71}, - dictWord{11, 0, 155}, - dictWord{11, 0, 313}, - dictWord{12, 0, 5}, - dictWord{13, 0, 325}, - dictWord{142, 0, 287}, - dictWord{134, 0, 1818}, - dictWord{136, 0, 1007}, - dictWord{138, 0, 321}, - dictWord{7, 0, 360}, - dictWord{7, 0, 425}, - dictWord{9, 0, 66}, - dictWord{9, 0, 278}, - dictWord{138, 0, 644}, - dictWord{133, 10, 818}, - dictWord{5, 0, 385}, - dictWord{5, 10, 541}, - dictWord{6, 10, 94}, - dictWord{6, 10, 499}, - dictWord{ - 7, - 10, - 230, - }, - dictWord{139, 10, 321}, - dictWord{4, 10, 920}, - dictWord{5, 10, 25}, - dictWord{5, 10, 790}, - dictWord{6, 10, 457}, - dictWord{7, 10, 853}, - dictWord{ - 136, - 10, - 788, - }, - dictWord{4, 0, 900}, - dictWord{133, 0, 861}, - dictWord{5, 0, 254}, - dictWord{7, 0, 985}, - dictWord{136, 0, 73}, - dictWord{7, 0, 1959}, - dictWord{ - 136, - 0, - 683, - }, - dictWord{134, 10, 1765}, - dictWord{133, 10, 822}, - dictWord{132, 10, 634}, - dictWord{4, 11, 29}, - dictWord{6, 11, 532}, - dictWord{7, 11, 1628}, - dictWord{ - 7, - 11, - 1648, - }, - dictWord{9, 11, 303}, - dictWord{9, 11, 350}, - dictWord{10, 11, 433}, - dictWord{11, 11, 97}, - dictWord{11, 11, 557}, - dictWord{11, 11, 745}, - dictWord{12, 11, 289}, - dictWord{12, 11, 335}, - dictWord{12, 11, 348}, - dictWord{12, 11, 606}, - dictWord{13, 11, 116}, - dictWord{13, 11, 233}, - dictWord{ - 13, - 11, - 466, - }, - dictWord{14, 11, 181}, - dictWord{14, 11, 209}, - dictWord{14, 11, 232}, - dictWord{14, 11, 236}, - dictWord{14, 11, 300}, - dictWord{16, 11, 41}, - dictWord{ - 148, - 11, - 97, - }, - dictWord{19, 0, 86}, - dictWord{6, 10, 36}, - dictWord{7, 10, 658}, - dictWord{136, 10, 454}, - dictWord{135, 11, 1692}, - dictWord{132, 0, 725}, - dictWord{ - 5, - 11, - 501, - }, - dictWord{7, 11, 1704}, - dictWord{9, 11, 553}, - dictWord{11, 11, 520}, - dictWord{12, 11, 557}, - dictWord{141, 11, 249}, - dictWord{134, 0, 196}, - dictWord{133, 0, 831}, - dictWord{136, 0, 723}, - dictWord{7, 0, 1897}, - dictWord{13, 0, 80}, - dictWord{13, 0, 437}, - dictWord{145, 0, 74}, - dictWord{4, 0, 992}, - dictWord{ - 6, - 0, - 627, - }, - dictWord{136, 0, 994}, - dictWord{135, 11, 1294}, - dictWord{132, 10, 104}, - dictWord{5, 0, 848}, - dictWord{6, 0, 66}, - dictWord{136, 0, 764}, - dictWord{ - 4, - 0, - 36, - }, - dictWord{7, 0, 1387}, - dictWord{10, 0, 205}, - dictWord{139, 0, 755}, - dictWord{6, 0, 1046}, - dictWord{134, 0, 1485}, - dictWord{134, 0, 950}, - dictWord{132, 0, 887}, - dictWord{14, 0, 450}, - dictWord{148, 0, 111}, - dictWord{7, 0, 620}, - dictWord{7, 0, 831}, - dictWord{9, 10, 542}, - dictWord{9, 10, 566}, - dictWord{ - 138, - 10, - 728, - }, - dictWord{6, 0, 165}, - dictWord{138, 0, 388}, - dictWord{139, 10, 263}, - dictWord{4, 0, 719}, - dictWord{135, 0, 155}, - dictWord{138, 10, 468}, - dictWord{6, 11, 453}, - dictWord{144, 11, 36}, - dictWord{134, 11, 129}, - dictWord{5, 0, 533}, - dictWord{7, 0, 755}, - dictWord{138, 0, 780}, - dictWord{134, 0, 1465}, - dictWord{4, 0, 353}, - dictWord{6, 0, 146}, - dictWord{6, 0, 1789}, - dictWord{7, 0, 427}, - dictWord{7, 0, 990}, - dictWord{7, 0, 1348}, - dictWord{9, 0, 665}, - dictWord{9, 0, 898}, - dictWord{11, 0, 893}, - dictWord{142, 0, 212}, - dictWord{7, 10, 87}, - dictWord{142, 10, 288}, - dictWord{4, 0, 45}, - dictWord{135, 0, 1257}, - dictWord{12, 0, 7}, - dictWord{7, 10, 988}, - dictWord{7, 10, 1939}, - dictWord{9, 10, 64}, - dictWord{9, 10, 502}, - dictWord{12, 10, 34}, - dictWord{13, 10, 12}, - dictWord{13, 10, 234}, - dictWord{147, 10, 77}, - dictWord{4, 0, 607}, - dictWord{5, 11, 60}, - dictWord{6, 11, 504}, - dictWord{7, 11, 614}, - dictWord{7, 11, 1155}, - dictWord{140, 11, 0}, - dictWord{ - 135, - 10, - 141, - }, - dictWord{8, 11, 198}, - dictWord{11, 11, 29}, - dictWord{140, 11, 534}, - dictWord{140, 0, 65}, - dictWord{136, 0, 816}, - dictWord{132, 10, 619}, - dictWord{139, 0, 88}, - dictWord{5, 10, 246}, - dictWord{8, 10, 189}, - dictWord{9, 10, 355}, - dictWord{9, 10, 512}, - dictWord{10, 10, 124}, - dictWord{10, 10, 453}, - dictWord{11, 10, 143}, - dictWord{11, 10, 416}, - dictWord{11, 10, 859}, - dictWord{141, 10, 341}, - dictWord{4, 11, 379}, - dictWord{135, 11, 1397}, - dictWord{ - 4, - 0, - 600, - }, - dictWord{137, 0, 621}, - dictWord{133, 0, 367}, - dictWord{134, 0, 561}, - dictWord{6, 0, 559}, - dictWord{134, 0, 1691}, - dictWord{6, 0, 585}, - dictWord{ - 134, - 11, - 585, - }, - dictWord{135, 11, 1228}, - dictWord{4, 11, 118}, - dictWord{5, 10, 678}, - dictWord{6, 11, 274}, - dictWord{6, 11, 361}, - dictWord{7, 11, 75}, - dictWord{ - 141, - 11, - 441, - }, - dictWord{135, 11, 1818}, - dictWord{137, 11, 841}, - dictWord{5, 0, 573}, - dictWord{6, 0, 287}, - dictWord{7, 10, 862}, - dictWord{7, 10, 1886}, - dictWord{138, 10, 179}, - dictWord{132, 10, 517}, - dictWord{140, 11, 693}, - dictWord{5, 11, 314}, - dictWord{6, 11, 221}, - dictWord{7, 11, 419}, - dictWord{ - 10, - 11, - 650, - }, - dictWord{11, 11, 396}, - dictWord{12, 11, 156}, - dictWord{13, 11, 369}, - dictWord{14, 11, 333}, - dictWord{145, 11, 47}, - dictWord{140, 10, 540}, - dictWord{136, 10, 667}, - dictWord{11, 10, 403}, - dictWord{146, 10, 83}, - dictWord{6, 0, 672}, - dictWord{133, 10, 761}, - dictWord{9, 0, 157}, - dictWord{10, 10, 131}, - dictWord{140, 10, 72}, - dictWord{7, 0, 714}, - dictWord{134, 11, 460}, - dictWord{134, 0, 456}, - dictWord{133, 0, 925}, - dictWord{5, 11, 682}, - dictWord{ - 135, - 11, - 1887, - }, - dictWord{136, 11, 510}, - dictWord{136, 11, 475}, - dictWord{133, 11, 1016}, - dictWord{9, 0, 19}, - dictWord{7, 11, 602}, - dictWord{8, 11, 179}, - dictWord{ - 10, - 11, - 781, - }, - dictWord{140, 11, 126}, - dictWord{6, 11, 329}, - dictWord{138, 11, 111}, - dictWord{6, 0, 822}, - dictWord{134, 0, 1473}, - dictWord{144, 11, 86}, - dictWord{11, 0, 113}, - dictWord{139, 11, 113}, - dictWord{5, 11, 821}, - dictWord{134, 11, 1687}, - dictWord{133, 10, 449}, - dictWord{7, 0, 463}, - dictWord{ - 17, - 0, - 69, - }, - dictWord{136, 10, 103}, - dictWord{7, 10, 2028}, - dictWord{138, 10, 641}, - dictWord{6, 0, 193}, - dictWord{7, 0, 240}, - dictWord{7, 0, 1682}, - dictWord{ - 10, - 0, - 51, - }, - dictWord{10, 0, 640}, - dictWord{11, 0, 410}, - dictWord{13, 0, 82}, - dictWord{14, 0, 247}, - dictWord{14, 0, 331}, - dictWord{142, 0, 377}, - dictWord{6, 0, 471}, - dictWord{11, 0, 411}, - dictWord{142, 0, 2}, - dictWord{5, 11, 71}, - dictWord{7, 11, 1407}, - dictWord{9, 11, 388}, - dictWord{9, 11, 704}, - dictWord{10, 11, 261}, - dictWord{ - 10, - 11, - 619, - }, - dictWord{11, 11, 547}, - dictWord{11, 11, 619}, - dictWord{143, 11, 157}, - dictWord{136, 0, 633}, - dictWord{135, 0, 1148}, - dictWord{6, 0, 554}, - dictWord{7, 0, 1392}, - dictWord{12, 0, 129}, - dictWord{7, 10, 1274}, - dictWord{7, 10, 1386}, - dictWord{7, 11, 2008}, - dictWord{9, 11, 337}, - dictWord{10, 11, 517}, - dictWord{146, 10, 87}, - dictWord{7, 0, 803}, - dictWord{8, 0, 542}, - dictWord{6, 10, 187}, - dictWord{7, 10, 1203}, - dictWord{8, 10, 380}, - dictWord{14, 10, 117}, - dictWord{149, 10, 28}, - dictWord{6, 10, 297}, - dictWord{7, 10, 793}, - dictWord{139, 10, 938}, - dictWord{8, 0, 438}, - dictWord{11, 0, 363}, - dictWord{7, 10, 464}, - dictWord{11, 10, 105}, - dictWord{12, 10, 231}, - dictWord{14, 10, 386}, - dictWord{15, 10, 102}, - dictWord{148, 10, 75}, - dictWord{5, 11, 16}, - dictWord{6, 11, 86}, - dictWord{6, 11, 603}, - dictWord{7, 11, 292}, - dictWord{7, 11, 561}, - dictWord{8, 11, 257}, - dictWord{8, 11, 382}, - dictWord{9, 11, 721}, - dictWord{9, 11, 778}, - dictWord{ - 11, - 11, - 581, - }, - dictWord{140, 11, 466}, - dictWord{6, 0, 717}, - dictWord{4, 11, 486}, - dictWord{133, 11, 491}, - dictWord{132, 0, 875}, - dictWord{132, 11, 72}, - dictWord{6, 11, 265}, - dictWord{135, 11, 847}, - dictWord{4, 0, 237}, - dictWord{135, 0, 514}, - dictWord{6, 0, 392}, - dictWord{7, 0, 65}, - dictWord{135, 0, 2019}, - dictWord{140, 11, 261}, - dictWord{135, 11, 922}, - dictWord{137, 11, 404}, - dictWord{12, 0, 563}, - dictWord{14, 0, 101}, - dictWord{18, 0, 129}, - dictWord{ - 7, - 10, - 1010, - }, - dictWord{11, 10, 733}, - dictWord{11, 10, 759}, - dictWord{13, 10, 34}, - dictWord{146, 10, 45}, - dictWord{7, 10, 1656}, - dictWord{9, 10, 369}, - dictWord{ - 10, - 10, - 338, - }, - dictWord{10, 10, 490}, - dictWord{11, 10, 154}, - dictWord{11, 10, 545}, - dictWord{11, 10, 775}, - dictWord{13, 10, 77}, - dictWord{141, 10, 274}, - dictWord{4, 0, 444}, - dictWord{10, 0, 146}, - dictWord{140, 0, 9}, - dictWord{139, 11, 163}, - dictWord{7, 0, 1260}, - dictWord{135, 0, 1790}, - dictWord{9, 0, 222}, - dictWord{10, 0, 43}, - dictWord{139, 0, 900}, - dictWord{137, 11, 234}, - dictWord{138, 0, 971}, - dictWord{137, 0, 761}, - dictWord{134, 0, 699}, - dictWord{ - 136, - 11, - 434, - }, - dictWord{6, 0, 1116}, - dictWord{7, 0, 1366}, - dictWord{5, 10, 20}, - dictWord{6, 11, 197}, - dictWord{6, 10, 298}, - dictWord{7, 10, 659}, - dictWord{8, 11, 205}, - dictWord{137, 10, 219}, - dictWord{132, 11, 490}, - dictWord{11, 11, 820}, - dictWord{150, 11, 51}, - dictWord{7, 10, 1440}, - dictWord{11, 10, 854}, - dictWord{ - 11, - 10, - 872, - }, - dictWord{11, 10, 921}, - dictWord{12, 10, 551}, - dictWord{13, 10, 472}, - dictWord{142, 10, 367}, - dictWord{140, 11, 13}, - dictWord{132, 0, 829}, - dictWord{12, 0, 242}, - dictWord{132, 10, 439}, - dictWord{136, 10, 669}, - dictWord{6, 0, 593}, - dictWord{6, 11, 452}, - dictWord{7, 11, 312}, - dictWord{ - 138, - 11, - 219, - }, - dictWord{4, 11, 333}, - dictWord{9, 11, 176}, - dictWord{12, 11, 353}, - dictWord{141, 11, 187}, - dictWord{7, 0, 36}, - dictWord{8, 0, 201}, - dictWord{ - 136, - 0, - 605, - }, - dictWord{140, 0, 224}, - dictWord{132, 10, 233}, - dictWord{134, 0, 1430}, - dictWord{134, 0, 1806}, - dictWord{4, 0, 523}, - dictWord{133, 0, 638}, - dictWord{ - 6, - 0, - 1889, - }, - dictWord{9, 0, 958}, - dictWord{9, 0, 971}, - dictWord{9, 0, 976}, - dictWord{12, 0, 796}, - dictWord{12, 0, 799}, - dictWord{12, 0, 808}, - dictWord{ - 12, - 0, - 835, - }, - dictWord{12, 0, 836}, - dictWord{12, 0, 914}, - dictWord{12, 0, 946}, - dictWord{15, 0, 216}, - dictWord{15, 0, 232}, - dictWord{18, 0, 183}, - dictWord{18, 0, 187}, - dictWord{18, 0, 194}, - dictWord{18, 0, 212}, - dictWord{18, 0, 232}, - dictWord{149, 0, 49}, - dictWord{132, 10, 482}, - dictWord{6, 0, 827}, - dictWord{134, 0, 1434}, - dictWord{135, 10, 346}, - dictWord{134, 0, 2043}, - dictWord{6, 0, 242}, - dictWord{7, 0, 227}, - dictWord{7, 0, 1581}, - dictWord{8, 0, 104}, - dictWord{9, 0, 113}, - dictWord{9, 0, 220}, - dictWord{9, 0, 427}, - dictWord{10, 0, 136}, - dictWord{10, 0, 239}, - dictWord{11, 0, 579}, - dictWord{11, 0, 1023}, - dictWord{13, 0, 4}, - dictWord{ - 13, - 0, - 204, - }, - dictWord{13, 0, 316}, - dictWord{148, 0, 86}, - dictWord{134, 11, 1685}, - dictWord{7, 0, 148}, - dictWord{8, 0, 284}, - dictWord{141, 0, 63}, - dictWord{ - 142, - 0, - 10, - }, - dictWord{135, 11, 584}, - dictWord{134, 0, 1249}, - dictWord{7, 0, 861}, - dictWord{135, 10, 334}, - dictWord{5, 10, 795}, - dictWord{6, 10, 1741}, - dictWord{ - 137, - 11, - 70, - }, - dictWord{132, 0, 807}, - dictWord{7, 11, 135}, - dictWord{8, 11, 7}, - dictWord{8, 11, 62}, - dictWord{9, 11, 243}, - dictWord{10, 11, 658}, - dictWord{ - 10, - 11, - 697, - }, - dictWord{11, 11, 456}, - dictWord{139, 11, 756}, - dictWord{9, 11, 395}, - dictWord{138, 11, 79}, - dictWord{137, 11, 108}, - dictWord{147, 0, 94}, - dictWord{136, 0, 494}, - dictWord{135, 11, 631}, - dictWord{135, 10, 622}, - dictWord{7, 0, 1510}, - dictWord{135, 10, 1750}, - dictWord{4, 10, 203}, - dictWord{ - 135, - 10, - 1936, - }, - dictWord{7, 11, 406}, - dictWord{7, 11, 459}, - dictWord{8, 11, 606}, - dictWord{139, 11, 726}, - dictWord{7, 0, 1306}, - dictWord{8, 0, 505}, - dictWord{ - 9, - 0, - 482, - }, - dictWord{10, 0, 126}, - dictWord{11, 0, 225}, - dictWord{12, 0, 347}, - dictWord{12, 0, 449}, - dictWord{13, 0, 19}, - dictWord{14, 0, 218}, - dictWord{142, 0, 435}, - dictWord{5, 0, 268}, - dictWord{10, 0, 764}, - dictWord{12, 0, 120}, - dictWord{13, 0, 39}, - dictWord{145, 0, 127}, - dictWord{142, 11, 68}, - dictWord{11, 10, 678}, - dictWord{140, 10, 307}, - dictWord{12, 11, 268}, - dictWord{12, 11, 640}, - dictWord{142, 11, 119}, - dictWord{135, 10, 2044}, - dictWord{133, 11, 612}, - dictWord{ - 4, - 11, - 372, - }, - dictWord{7, 11, 482}, - dictWord{8, 11, 158}, - dictWord{9, 11, 602}, - dictWord{9, 11, 615}, - dictWord{10, 11, 245}, - dictWord{10, 11, 678}, - dictWord{ - 10, - 11, - 744, - }, - dictWord{11, 11, 248}, - dictWord{139, 11, 806}, - dictWord{7, 10, 311}, - dictWord{9, 10, 308}, - dictWord{140, 10, 255}, - dictWord{4, 0, 384}, - dictWord{135, 0, 1022}, - dictWord{5, 11, 854}, - dictWord{135, 11, 1991}, - dictWord{135, 10, 1266}, - dictWord{4, 10, 400}, - dictWord{5, 10, 267}, - dictWord{ - 135, - 10, - 232, - }, - dictWord{135, 0, 1703}, - dictWord{9, 0, 159}, - dictWord{11, 0, 661}, - dictWord{140, 0, 603}, - dictWord{4, 0, 964}, - dictWord{14, 0, 438}, - dictWord{ - 14, - 0, - 444, - }, - dictWord{14, 0, 456}, - dictWord{22, 0, 60}, - dictWord{22, 0, 63}, - dictWord{9, 11, 106}, - dictWord{9, 11, 163}, - dictWord{9, 11, 296}, - dictWord{10, 11, 167}, - dictWord{10, 11, 172}, - dictWord{10, 11, 777}, - dictWord{139, 11, 16}, - dictWord{136, 0, 583}, - dictWord{132, 0, 515}, - dictWord{8, 0, 632}, - dictWord{8, 0, 697}, - dictWord{137, 0, 854}, - dictWord{5, 11, 195}, - dictWord{135, 11, 1685}, - dictWord{6, 0, 1123}, - dictWord{134, 0, 1365}, - dictWord{134, 11, 328}, - dictWord{ - 7, - 11, - 1997, - }, - dictWord{8, 11, 730}, - dictWord{139, 11, 1006}, - dictWord{4, 0, 136}, - dictWord{133, 0, 551}, - dictWord{134, 0, 1782}, - dictWord{7, 0, 1287}, - dictWord{ - 9, - 0, - 44, - }, - dictWord{10, 0, 552}, - dictWord{10, 0, 642}, - dictWord{11, 0, 839}, - dictWord{12, 0, 274}, - dictWord{12, 0, 275}, - dictWord{12, 0, 372}, - dictWord{ - 13, - 0, - 91, - }, - dictWord{142, 0, 125}, - dictWord{5, 11, 751}, - dictWord{11, 11, 797}, - dictWord{140, 11, 203}, - dictWord{133, 0, 732}, - dictWord{7, 0, 679}, - dictWord{ - 8, - 0, - 313, - }, - dictWord{4, 10, 100}, - dictWord{135, 11, 821}, - dictWord{10, 0, 361}, - dictWord{142, 0, 316}, - dictWord{134, 0, 595}, - dictWord{6, 0, 147}, - dictWord{ - 7, - 0, - 886, - }, - dictWord{9, 0, 753}, - dictWord{138, 0, 268}, - dictWord{5, 10, 362}, - dictWord{5, 10, 443}, - dictWord{6, 10, 318}, - dictWord{7, 10, 1019}, - dictWord{ - 139, - 10, - 623, - }, - dictWord{5, 10, 463}, - dictWord{136, 10, 296}, - dictWord{4, 10, 454}, - dictWord{5, 11, 950}, - dictWord{5, 11, 994}, - dictWord{134, 11, 351}, - dictWord{ - 138, - 0, - 137, - }, - dictWord{5, 10, 48}, - dictWord{5, 10, 404}, - dictWord{6, 10, 557}, - dictWord{7, 10, 458}, - dictWord{8, 10, 597}, - dictWord{10, 10, 455}, - dictWord{ - 10, - 10, - 606, - }, - dictWord{11, 10, 49}, - dictWord{11, 10, 548}, - dictWord{12, 10, 476}, - dictWord{13, 10, 18}, - dictWord{141, 10, 450}, - dictWord{133, 0, 414}, - dictWord{ - 135, - 0, - 1762, - }, - dictWord{5, 11, 421}, - dictWord{135, 11, 47}, - dictWord{5, 10, 442}, - dictWord{135, 10, 1984}, - dictWord{134, 0, 599}, - dictWord{134, 0, 1749}, - dictWord{134, 0, 1627}, - dictWord{4, 0, 488}, - dictWord{132, 11, 350}, - dictWord{137, 11, 751}, - dictWord{132, 0, 83}, - dictWord{140, 0, 676}, - dictWord{ - 133, - 11, - 967, - }, - dictWord{7, 0, 1639}, - dictWord{5, 10, 55}, - dictWord{140, 10, 161}, - dictWord{4, 11, 473}, - dictWord{7, 11, 623}, - dictWord{8, 11, 808}, - dictWord{ - 9, - 11, - 871, - }, - dictWord{9, 11, 893}, - dictWord{11, 11, 38}, - dictWord{11, 11, 431}, - dictWord{12, 11, 112}, - dictWord{12, 11, 217}, - dictWord{12, 11, 243}, - dictWord{ - 12, - 11, - 562, - }, - dictWord{12, 11, 683}, - dictWord{13, 11, 141}, - dictWord{13, 11, 197}, - dictWord{13, 11, 227}, - dictWord{13, 11, 406}, - dictWord{13, 11, 487}, - dictWord{14, 11, 156}, - dictWord{14, 11, 203}, - dictWord{14, 11, 224}, - dictWord{14, 11, 256}, - dictWord{18, 11, 58}, - dictWord{150, 11, 0}, - dictWord{ - 133, - 10, - 450, - }, - dictWord{7, 11, 736}, - dictWord{139, 11, 264}, - dictWord{134, 0, 278}, - dictWord{4, 11, 222}, - dictWord{7, 11, 286}, - dictWord{136, 11, 629}, - dictWord{ - 135, - 10, - 869, - }, - dictWord{140, 0, 97}, - dictWord{144, 0, 14}, - dictWord{134, 0, 1085}, - dictWord{4, 10, 213}, - dictWord{7, 10, 223}, - dictWord{136, 10, 80}, - dictWord{ - 7, - 0, - 388, - }, - dictWord{7, 0, 644}, - dictWord{139, 0, 781}, - dictWord{132, 0, 849}, - dictWord{7, 0, 229}, - dictWord{8, 0, 59}, - dictWord{9, 0, 190}, - dictWord{10, 0, 378}, - dictWord{140, 0, 191}, - dictWord{7, 10, 381}, - dictWord{7, 10, 806}, - dictWord{7, 10, 820}, - dictWord{8, 10, 354}, - dictWord{8, 10, 437}, - dictWord{8, 10, 787}, - dictWord{9, 10, 657}, - dictWord{10, 10, 58}, - dictWord{10, 10, 339}, - dictWord{10, 10, 749}, - dictWord{11, 10, 914}, - dictWord{12, 10, 162}, - dictWord{13, 10, 75}, - dictWord{14, 10, 106}, - dictWord{14, 10, 198}, - dictWord{14, 10, 320}, - dictWord{14, 10, 413}, - dictWord{146, 10, 43}, - dictWord{141, 11, 306}, - dictWord{ - 136, - 10, - 747, - }, - dictWord{134, 0, 1115}, - dictWord{16, 0, 94}, - dictWord{16, 0, 108}, - dictWord{136, 11, 146}, - dictWord{6, 0, 700}, - dictWord{6, 0, 817}, - dictWord{ - 134, - 0, - 1002, - }, - dictWord{133, 10, 692}, - dictWord{4, 11, 465}, - dictWord{135, 11, 1663}, - dictWord{134, 10, 191}, - dictWord{6, 0, 1414}, - dictWord{ - 135, - 11, - 913, - }, - dictWord{132, 0, 660}, - dictWord{7, 0, 1035}, - dictWord{138, 0, 737}, - dictWord{6, 10, 162}, - dictWord{7, 10, 1960}, - dictWord{136, 10, 831}, - dictWord{ - 132, - 10, - 706, - }, - dictWord{7, 0, 690}, - dictWord{9, 0, 217}, - dictWord{9, 0, 587}, - dictWord{140, 0, 521}, - dictWord{138, 10, 426}, - dictWord{135, 10, 1235}, - dictWord{ - 6, - 11, - 82, - }, - dictWord{7, 11, 138}, - dictWord{7, 11, 517}, - dictWord{9, 11, 673}, - dictWord{139, 11, 238}, - dictWord{138, 0, 272}, - dictWord{5, 11, 495}, - dictWord{ - 7, - 11, - 834, - }, - dictWord{9, 11, 733}, - dictWord{139, 11, 378}, - dictWord{134, 0, 1744}, - dictWord{132, 0, 1011}, - dictWord{7, 11, 828}, - dictWord{142, 11, 116}, - dictWord{4, 0, 733}, - dictWord{9, 0, 194}, - dictWord{10, 0, 92}, - dictWord{11, 0, 198}, - dictWord{12, 0, 84}, - dictWord{13, 0, 128}, - dictWord{133, 11, 559}, - dictWord{ - 10, - 0, - 57, - }, - dictWord{10, 0, 277}, - dictWord{6, 11, 21}, - dictWord{6, 11, 1737}, - dictWord{7, 11, 1444}, - dictWord{136, 11, 224}, - dictWord{4, 10, 204}, - dictWord{ - 137, - 10, - 902, - }, - dictWord{136, 10, 833}, - dictWord{11, 0, 348}, - dictWord{12, 0, 99}, - dictWord{18, 0, 1}, - dictWord{18, 0, 11}, - dictWord{19, 0, 4}, - dictWord{7, 10, 366}, - dictWord{9, 10, 287}, - dictWord{12, 10, 199}, - dictWord{12, 10, 556}, - dictWord{140, 10, 577}, - dictWord{6, 0, 1981}, - dictWord{136, 0, 936}, - dictWord{ - 21, - 0, - 33, - }, - dictWord{150, 0, 40}, - dictWord{5, 11, 519}, - dictWord{138, 11, 204}, - dictWord{5, 10, 356}, - dictWord{135, 10, 224}, - dictWord{134, 0, 775}, - dictWord{ - 135, - 0, - 306, - }, - dictWord{7, 10, 630}, - dictWord{9, 10, 567}, - dictWord{11, 10, 150}, - dictWord{11, 10, 444}, - dictWord{141, 10, 119}, - dictWord{5, 0, 979}, - dictWord{ - 134, - 10, - 539, - }, - dictWord{133, 0, 611}, - dictWord{4, 11, 402}, - dictWord{135, 11, 1679}, - dictWord{5, 0, 178}, - dictWord{7, 11, 2}, - dictWord{8, 11, 323}, - dictWord{ - 136, - 11, - 479, - }, - dictWord{5, 11, 59}, - dictWord{135, 11, 672}, - dictWord{4, 0, 1010}, - dictWord{6, 0, 1969}, - dictWord{138, 11, 237}, - dictWord{133, 11, 412}, - dictWord{146, 11, 34}, - dictWord{7, 11, 1740}, - dictWord{146, 11, 48}, - dictWord{134, 0, 664}, - dictWord{139, 10, 814}, - dictWord{4, 11, 85}, - dictWord{ - 135, - 11, - 549, - }, - dictWord{133, 11, 94}, - dictWord{133, 11, 457}, - dictWord{132, 0, 390}, - dictWord{134, 0, 1510}, - dictWord{4, 10, 235}, - dictWord{135, 10, 255}, - dictWord{4, 10, 194}, - dictWord{5, 10, 584}, - dictWord{6, 11, 11}, - dictWord{6, 10, 384}, - dictWord{7, 11, 187}, - dictWord{7, 10, 583}, - dictWord{10, 10, 761}, - dictWord{ - 11, - 10, - 760, - }, - dictWord{139, 10, 851}, - dictWord{4, 11, 522}, - dictWord{139, 11, 802}, - dictWord{135, 0, 493}, - dictWord{10, 11, 776}, - dictWord{13, 11, 345}, - dictWord{142, 11, 425}, - dictWord{146, 0, 37}, - dictWord{4, 11, 52}, - dictWord{135, 11, 661}, - dictWord{134, 0, 724}, - dictWord{134, 0, 829}, - dictWord{ - 133, - 11, - 520, - }, - dictWord{133, 10, 562}, - dictWord{4, 11, 281}, - dictWord{5, 11, 38}, - dictWord{7, 11, 194}, - dictWord{7, 11, 668}, - dictWord{7, 11, 1893}, - dictWord{ - 137, - 11, - 397, - }, - dictWord{5, 10, 191}, - dictWord{137, 10, 271}, - dictWord{7, 0, 1537}, - dictWord{14, 0, 96}, - dictWord{143, 0, 73}, - dictWord{5, 0, 473}, - dictWord{ - 11, - 0, - 168, - }, - dictWord{4, 10, 470}, - dictWord{6, 10, 153}, - dictWord{7, 10, 1503}, - dictWord{7, 10, 1923}, - dictWord{10, 10, 701}, - dictWord{11, 10, 132}, - dictWord{ - 11, - 10, - 227, - }, - dictWord{11, 10, 320}, - dictWord{11, 10, 436}, - dictWord{11, 10, 525}, - dictWord{11, 10, 855}, - dictWord{12, 10, 41}, - dictWord{12, 10, 286}, - dictWord{13, 10, 103}, - dictWord{13, 10, 284}, - dictWord{14, 10, 255}, - dictWord{14, 10, 262}, - dictWord{15, 10, 117}, - dictWord{143, 10, 127}, - dictWord{ - 133, - 0, - 105, - }, - dictWord{5, 0, 438}, - dictWord{9, 0, 694}, - dictWord{12, 0, 627}, - dictWord{141, 0, 210}, - dictWord{133, 10, 327}, - dictWord{6, 10, 552}, - dictWord{ - 7, - 10, - 1754, - }, - dictWord{137, 10, 604}, - dictWord{134, 0, 1256}, - dictWord{152, 0, 11}, - dictWord{5, 11, 448}, - dictWord{11, 11, 98}, - dictWord{139, 11, 524}, - dictWord{ - 7, - 0, - 1626, - }, - dictWord{5, 10, 80}, - dictWord{6, 10, 405}, - dictWord{7, 10, 403}, - dictWord{7, 10, 1502}, - dictWord{8, 10, 456}, - dictWord{9, 10, 487}, - dictWord{ - 9, - 10, - 853, - }, - dictWord{9, 10, 889}, - dictWord{10, 10, 309}, - dictWord{11, 10, 721}, - dictWord{11, 10, 994}, - dictWord{12, 10, 430}, - dictWord{13, 10, 165}, - dictWord{ - 14, - 11, - 16, - }, - dictWord{146, 11, 44}, - dictWord{132, 0, 779}, - dictWord{8, 0, 25}, - dictWord{138, 0, 826}, - dictWord{4, 10, 453}, - dictWord{5, 10, 887}, - dictWord{ - 6, - 10, - 535, - }, - dictWord{8, 10, 6}, - dictWord{8, 10, 543}, - dictWord{136, 10, 826}, - dictWord{137, 11, 461}, - dictWord{140, 11, 632}, - dictWord{132, 0, 308}, - dictWord{135, 0, 741}, - dictWord{132, 0, 671}, - dictWord{7, 0, 150}, - dictWord{8, 0, 649}, - dictWord{136, 0, 1020}, - dictWord{9, 0, 99}, - dictWord{6, 11, 336}, - dictWord{ - 8, - 11, - 552, - }, - dictWord{9, 11, 285}, - dictWord{10, 11, 99}, - dictWord{139, 11, 568}, - dictWord{134, 0, 521}, - dictWord{5, 0, 339}, - dictWord{14, 0, 3}, - dictWord{ - 15, - 0, - 41, - }, - dictWord{15, 0, 166}, - dictWord{147, 0, 66}, - dictWord{6, 11, 423}, - dictWord{7, 11, 665}, - dictWord{7, 11, 1210}, - dictWord{9, 11, 218}, - dictWord{ - 141, - 11, - 222, - }, - dictWord{6, 0, 543}, - dictWord{5, 10, 101}, - dictWord{5, 11, 256}, - dictWord{6, 10, 88}, - dictWord{7, 10, 1677}, - dictWord{9, 10, 100}, - dictWord{10, 10, 677}, - dictWord{14, 10, 169}, - dictWord{14, 10, 302}, - dictWord{14, 10, 313}, - dictWord{15, 10, 48}, - dictWord{143, 10, 84}, - dictWord{4, 10, 310}, - dictWord{ - 7, - 10, - 708, - }, - dictWord{7, 10, 996}, - dictWord{9, 10, 795}, - dictWord{10, 10, 390}, - dictWord{10, 10, 733}, - dictWord{11, 10, 451}, - dictWord{12, 10, 249}, - dictWord{ - 14, - 10, - 115, - }, - dictWord{14, 10, 286}, - dictWord{143, 10, 100}, - dictWord{133, 10, 587}, - dictWord{13, 11, 417}, - dictWord{14, 11, 129}, - dictWord{143, 11, 15}, - dictWord{134, 0, 1358}, - dictWord{136, 11, 554}, - dictWord{132, 10, 498}, - dictWord{7, 10, 217}, - dictWord{8, 10, 140}, - dictWord{138, 10, 610}, - dictWord{ - 135, - 11, - 989, - }, - dictWord{135, 11, 634}, - dictWord{6, 0, 155}, - dictWord{140, 0, 234}, - dictWord{135, 11, 462}, - dictWord{132, 11, 618}, - dictWord{ - 134, - 0, - 1628, - }, - dictWord{132, 0, 766}, - dictWord{4, 11, 339}, - dictWord{5, 10, 905}, - dictWord{135, 11, 259}, - dictWord{135, 0, 829}, - dictWord{4, 11, 759}, - dictWord{ - 141, - 11, - 169, - }, - dictWord{7, 0, 1445}, - dictWord{4, 10, 456}, - dictWord{7, 10, 358}, - dictWord{7, 10, 1637}, - dictWord{8, 10, 643}, - dictWord{139, 10, 483}, - dictWord{ - 5, - 0, - 486, - }, - dictWord{135, 0, 1349}, - dictWord{5, 11, 688}, - dictWord{135, 11, 712}, - dictWord{7, 0, 1635}, - dictWord{8, 0, 17}, - dictWord{10, 0, 217}, - dictWord{ - 10, - 0, - 295, - }, - dictWord{12, 0, 2}, - dictWord{140, 11, 2}, - dictWord{138, 0, 558}, - dictWord{150, 10, 56}, - dictWord{4, 11, 278}, - dictWord{5, 11, 465}, - dictWord{ - 135, - 11, - 1367, - }, - dictWord{136, 11, 482}, - dictWord{133, 10, 535}, - dictWord{6, 0, 1362}, - dictWord{6, 0, 1461}, - dictWord{10, 11, 274}, - dictWord{10, 11, 625}, - dictWord{139, 11, 530}, - dictWord{5, 0, 599}, - dictWord{5, 11, 336}, - dictWord{6, 11, 341}, - dictWord{6, 11, 478}, - dictWord{6, 11, 1763}, - dictWord{136, 11, 386}, - dictWord{7, 10, 1748}, - dictWord{137, 11, 151}, - dictWord{134, 0, 1376}, - dictWord{133, 10, 539}, - dictWord{135, 11, 73}, - dictWord{135, 11, 1971}, - dictWord{139, 11, 283}, - dictWord{9, 0, 93}, - dictWord{139, 0, 474}, - dictWord{6, 10, 91}, - dictWord{135, 10, 435}, - dictWord{6, 0, 447}, - dictWord{5, 11, 396}, - dictWord{134, 11, 501}, - dictWord{4, 10, 16}, - dictWord{5, 10, 316}, - dictWord{5, 10, 842}, - dictWord{6, 10, 370}, - dictWord{6, 10, 1778}, - dictWord{8, 10, 166}, - dictWord{11, 10, 812}, - dictWord{12, 10, 206}, - dictWord{12, 10, 351}, - dictWord{14, 10, 418}, - dictWord{16, 10, 15}, - dictWord{16, 10, 34}, - dictWord{18, 10, 3}, - dictWord{19, 10, 3}, - dictWord{19, 10, 7}, - dictWord{20, 10, 4}, - dictWord{149, 10, 21}, - dictWord{7, 0, 577}, - dictWord{7, 0, 1432}, - dictWord{9, 0, 475}, - dictWord{9, 0, 505}, - dictWord{9, 0, 526}, - dictWord{9, 0, 609}, - dictWord{9, 0, 689}, - dictWord{9, 0, 726}, - dictWord{9, 0, 735}, - dictWord{9, 0, 738}, - dictWord{10, 0, 556}, - dictWord{ - 10, - 0, - 674, - }, - dictWord{10, 0, 684}, - dictWord{11, 0, 89}, - dictWord{11, 0, 202}, - dictWord{11, 0, 272}, - dictWord{11, 0, 380}, - dictWord{11, 0, 415}, - dictWord{11, 0, 505}, - dictWord{11, 0, 537}, - dictWord{11, 0, 550}, - dictWord{11, 0, 562}, - dictWord{11, 0, 640}, - dictWord{11, 0, 667}, - dictWord{11, 0, 688}, - dictWord{11, 0, 847}, - dictWord{11, 0, 927}, - dictWord{11, 0, 930}, - dictWord{11, 0, 940}, - dictWord{12, 0, 144}, - dictWord{12, 0, 325}, - dictWord{12, 0, 329}, - dictWord{12, 0, 389}, - dictWord{ - 12, - 0, - 403, - }, - dictWord{12, 0, 451}, - dictWord{12, 0, 515}, - dictWord{12, 0, 604}, - dictWord{12, 0, 616}, - dictWord{12, 0, 626}, - dictWord{13, 0, 66}, - dictWord{ - 13, - 0, - 131, - }, - dictWord{13, 0, 167}, - dictWord{13, 0, 236}, - dictWord{13, 0, 368}, - dictWord{13, 0, 411}, - dictWord{13, 0, 434}, - dictWord{13, 0, 453}, - dictWord{13, 0, 461}, - dictWord{13, 0, 474}, - dictWord{14, 0, 59}, - dictWord{14, 0, 60}, - dictWord{14, 0, 139}, - dictWord{14, 0, 152}, - dictWord{14, 0, 276}, - dictWord{14, 0, 353}, - dictWord{ - 14, - 0, - 402, - }, - dictWord{15, 0, 28}, - dictWord{15, 0, 81}, - dictWord{15, 0, 123}, - dictWord{15, 0, 152}, - dictWord{18, 0, 136}, - dictWord{148, 0, 88}, - dictWord{ - 4, - 11, - 929, - }, - dictWord{133, 11, 799}, - dictWord{136, 11, 46}, - dictWord{142, 0, 307}, - dictWord{4, 0, 609}, - dictWord{7, 0, 756}, - dictWord{9, 0, 544}, - dictWord{ - 11, - 0, - 413, - }, - dictWord{144, 0, 25}, - dictWord{10, 0, 687}, - dictWord{7, 10, 619}, - dictWord{10, 10, 547}, - dictWord{11, 10, 122}, - dictWord{140, 10, 601}, - dictWord{ - 4, - 0, - 930, - }, - dictWord{133, 0, 947}, - dictWord{133, 0, 939}, - dictWord{142, 0, 21}, - dictWord{4, 11, 892}, - dictWord{133, 11, 770}, - dictWord{133, 0, 962}, - dictWord{ - 5, - 0, - 651, - }, - dictWord{8, 0, 170}, - dictWord{9, 0, 61}, - dictWord{9, 0, 63}, - dictWord{10, 0, 23}, - dictWord{10, 0, 37}, - dictWord{10, 0, 834}, - dictWord{11, 0, 4}, - dictWord{ - 11, - 0, - 187, - }, - dictWord{11, 0, 281}, - dictWord{11, 0, 503}, - dictWord{11, 0, 677}, - dictWord{12, 0, 96}, - dictWord{12, 0, 130}, - dictWord{12, 0, 244}, - dictWord{14, 0, 5}, - dictWord{14, 0, 40}, - dictWord{14, 0, 162}, - dictWord{14, 0, 202}, - dictWord{146, 0, 133}, - dictWord{4, 0, 406}, - dictWord{5, 0, 579}, - dictWord{12, 0, 492}, - dictWord{ - 150, - 0, - 15, - }, - dictWord{135, 11, 158}, - dictWord{135, 0, 597}, - dictWord{132, 0, 981}, - dictWord{132, 10, 888}, - dictWord{4, 10, 149}, - dictWord{138, 10, 368}, - dictWord{132, 0, 545}, - dictWord{4, 10, 154}, - dictWord{7, 10, 1134}, - dictWord{136, 10, 105}, - dictWord{135, 11, 2001}, - dictWord{134, 0, 1558}, - dictWord{ - 4, - 10, - 31, - }, - dictWord{6, 10, 429}, - dictWord{7, 10, 962}, - dictWord{9, 10, 458}, - dictWord{139, 10, 691}, - dictWord{132, 10, 312}, - dictWord{135, 10, 1642}, - dictWord{ - 6, - 0, - 17, - }, - dictWord{6, 0, 1304}, - dictWord{7, 0, 16}, - dictWord{7, 0, 1001}, - dictWord{9, 0, 886}, - dictWord{10, 0, 489}, - dictWord{10, 0, 800}, - dictWord{11, 0, 782}, - dictWord{12, 0, 320}, - dictWord{13, 0, 467}, - dictWord{14, 0, 145}, - dictWord{14, 0, 387}, - dictWord{143, 0, 119}, - dictWord{135, 0, 1982}, - dictWord{17, 0, 17}, - dictWord{7, 11, 1461}, - dictWord{140, 11, 91}, - dictWord{4, 10, 236}, - dictWord{132, 11, 602}, - dictWord{138, 0, 907}, - dictWord{136, 0, 110}, - dictWord{7, 0, 272}, - dictWord{19, 0, 53}, - dictWord{5, 10, 836}, - dictWord{5, 10, 857}, - dictWord{134, 10, 1680}, - dictWord{5, 0, 458}, - dictWord{7, 11, 1218}, - dictWord{136, 11, 303}, - dictWord{7, 0, 1983}, - dictWord{8, 0, 0}, - dictWord{8, 0, 171}, - dictWord{9, 0, 120}, - dictWord{9, 0, 732}, - dictWord{10, 0, 473}, - dictWord{11, 0, 656}, - dictWord{ - 11, - 0, - 998, - }, - dictWord{18, 0, 0}, - dictWord{18, 0, 2}, - dictWord{19, 0, 21}, - dictWord{10, 10, 68}, - dictWord{139, 10, 494}, - dictWord{137, 11, 662}, - dictWord{4, 11, 13}, - dictWord{5, 11, 567}, - dictWord{7, 11, 1498}, - dictWord{9, 11, 124}, - dictWord{11, 11, 521}, - dictWord{140, 11, 405}, - dictWord{4, 10, 81}, - dictWord{139, 10, 867}, - dictWord{135, 11, 1006}, - dictWord{7, 11, 800}, - dictWord{7, 11, 1783}, - dictWord{138, 11, 12}, - dictWord{9, 0, 295}, - dictWord{10, 0, 443}, - dictWord{ - 5, - 10, - 282, - }, - dictWord{8, 10, 650}, - dictWord{137, 10, 907}, - dictWord{132, 11, 735}, - dictWord{4, 11, 170}, - dictWord{4, 10, 775}, - dictWord{135, 11, 323}, - dictWord{ - 6, - 0, - 1844, - }, - dictWord{10, 0, 924}, - dictWord{11, 11, 844}, - dictWord{12, 11, 104}, - dictWord{140, 11, 625}, - dictWord{5, 11, 304}, - dictWord{7, 11, 1403}, - dictWord{140, 11, 498}, - dictWord{134, 0, 1232}, - dictWord{4, 0, 519}, - dictWord{10, 0, 70}, - dictWord{12, 0, 26}, - dictWord{14, 0, 17}, - dictWord{14, 0, 178}, - dictWord{ - 15, - 0, - 34, - }, - dictWord{149, 0, 12}, - dictWord{132, 0, 993}, - dictWord{4, 11, 148}, - dictWord{133, 11, 742}, - dictWord{6, 0, 31}, - dictWord{7, 0, 491}, - dictWord{7, 0, 530}, - dictWord{8, 0, 592}, - dictWord{11, 0, 53}, - dictWord{11, 0, 779}, - dictWord{12, 0, 167}, - dictWord{12, 0, 411}, - dictWord{14, 0, 14}, - dictWord{14, 0, 136}, - dictWord{ - 15, - 0, - 72, - }, - dictWord{16, 0, 17}, - dictWord{144, 0, 72}, - dictWord{133, 0, 907}, - dictWord{134, 0, 733}, - dictWord{133, 11, 111}, - dictWord{4, 10, 71}, - dictWord{ - 5, - 10, - 376, - }, - dictWord{7, 10, 119}, - dictWord{138, 10, 665}, - dictWord{136, 0, 55}, - dictWord{8, 0, 430}, - dictWord{136, 11, 430}, - dictWord{4, 0, 208}, - dictWord{ - 5, - 0, - 106, - }, - dictWord{6, 0, 531}, - dictWord{8, 0, 408}, - dictWord{9, 0, 188}, - dictWord{138, 0, 572}, - dictWord{12, 0, 56}, - dictWord{11, 10, 827}, - dictWord{14, 10, 34}, - dictWord{143, 10, 148}, - dictWord{134, 0, 1693}, - dictWord{133, 11, 444}, - dictWord{132, 10, 479}, - dictWord{140, 0, 441}, - dictWord{9, 0, 449}, - dictWord{ - 10, - 0, - 192, - }, - dictWord{138, 0, 740}, - dictWord{134, 0, 928}, - dictWord{4, 0, 241}, - dictWord{7, 10, 607}, - dictWord{136, 10, 99}, - dictWord{8, 11, 123}, - dictWord{ - 15, - 11, - 6, - }, - dictWord{144, 11, 7}, - dictWord{6, 11, 285}, - dictWord{8, 11, 654}, - dictWord{11, 11, 749}, - dictWord{12, 11, 190}, - dictWord{12, 11, 327}, - dictWord{ - 13, - 11, - 120, - }, - dictWord{13, 11, 121}, - dictWord{13, 11, 327}, - dictWord{15, 11, 47}, - dictWord{146, 11, 40}, - dictWord{4, 10, 41}, - dictWord{5, 10, 74}, - dictWord{ - 7, - 10, - 1627, - }, - dictWord{11, 10, 871}, - dictWord{140, 10, 619}, - dictWord{7, 0, 1525}, - dictWord{11, 10, 329}, - dictWord{11, 10, 965}, - dictWord{12, 10, 241}, - dictWord{14, 10, 354}, - dictWord{15, 10, 22}, - dictWord{148, 10, 63}, - dictWord{132, 0, 259}, - dictWord{135, 11, 183}, - dictWord{9, 10, 209}, - dictWord{ - 137, - 10, - 300, - }, - dictWord{5, 11, 937}, - dictWord{135, 11, 100}, - dictWord{133, 10, 98}, - dictWord{4, 0, 173}, - dictWord{5, 0, 312}, - dictWord{5, 0, 512}, - dictWord{ - 135, - 0, - 1285, - }, - dictWord{141, 0, 185}, - dictWord{7, 0, 1603}, - dictWord{7, 0, 1691}, - dictWord{9, 0, 464}, - dictWord{11, 0, 195}, - dictWord{12, 0, 279}, - dictWord{ - 12, - 0, - 448, - }, - dictWord{14, 0, 11}, - dictWord{147, 0, 102}, - dictWord{135, 0, 1113}, - dictWord{133, 10, 984}, - dictWord{4, 0, 452}, - dictWord{5, 0, 583}, - dictWord{ - 135, - 0, - 720, - }, - dictWord{4, 0, 547}, - dictWord{5, 0, 817}, - dictWord{6, 0, 433}, - dictWord{7, 0, 593}, - dictWord{7, 0, 1378}, - dictWord{8, 0, 161}, - dictWord{9, 0, 284}, - dictWord{ - 10, - 0, - 313, - }, - dictWord{139, 0, 886}, - dictWord{8, 0, 722}, - dictWord{4, 10, 182}, - dictWord{6, 10, 205}, - dictWord{135, 10, 220}, - dictWord{150, 0, 13}, - dictWord{ - 4, - 10, - 42, - }, - dictWord{9, 10, 205}, - dictWord{9, 10, 786}, - dictWord{138, 10, 659}, - dictWord{6, 0, 289}, - dictWord{7, 0, 1670}, - dictWord{12, 0, 57}, - dictWord{151, 0, 4}, - dictWord{132, 10, 635}, - dictWord{14, 0, 43}, - dictWord{146, 0, 21}, - dictWord{139, 10, 533}, - dictWord{135, 0, 1694}, - dictWord{8, 0, 420}, - dictWord{ - 139, - 0, - 193, - }, - dictWord{135, 0, 409}, - dictWord{132, 10, 371}, - dictWord{4, 10, 272}, - dictWord{135, 10, 836}, - dictWord{5, 10, 825}, - dictWord{134, 10, 1640}, - dictWord{5, 11, 251}, - dictWord{5, 11, 956}, - dictWord{8, 11, 268}, - dictWord{9, 11, 214}, - dictWord{146, 11, 142}, - dictWord{138, 0, 308}, - dictWord{6, 0, 1863}, - dictWord{141, 11, 37}, - dictWord{137, 10, 879}, - dictWord{7, 10, 317}, - dictWord{135, 10, 569}, - dictWord{132, 11, 294}, - dictWord{134, 0, 790}, - dictWord{ - 5, - 0, - 1002, - }, - dictWord{136, 0, 745}, - dictWord{5, 11, 346}, - dictWord{5, 11, 711}, - dictWord{136, 11, 390}, - dictWord{135, 0, 289}, - dictWord{5, 0, 504}, - dictWord{ - 11, - 0, - 68, - }, - dictWord{137, 10, 307}, - dictWord{4, 0, 239}, - dictWord{6, 0, 477}, - dictWord{7, 0, 1607}, - dictWord{139, 0, 617}, - dictWord{149, 0, 13}, - dictWord{ - 133, - 0, - 609, - }, - dictWord{133, 11, 624}, - dictWord{5, 11, 783}, - dictWord{7, 11, 1998}, - dictWord{135, 11, 2047}, - dictWord{133, 10, 525}, - dictWord{132, 0, 367}, - dictWord{132, 11, 594}, - dictWord{6, 0, 528}, - dictWord{133, 10, 493}, - dictWord{4, 10, 174}, - dictWord{135, 10, 911}, - dictWord{8, 10, 417}, - dictWord{ - 137, - 10, - 782, - }, - dictWord{132, 0, 694}, - dictWord{7, 0, 548}, - dictWord{137, 0, 58}, - dictWord{4, 10, 32}, - dictWord{5, 10, 215}, - dictWord{6, 10, 269}, - dictWord{7, 10, 1782}, - dictWord{7, 10, 1892}, - dictWord{10, 10, 16}, - dictWord{11, 10, 822}, - dictWord{11, 10, 954}, - dictWord{141, 10, 481}, - dictWord{140, 0, 687}, - dictWord{ - 7, - 0, - 1749, - }, - dictWord{136, 10, 477}, - dictWord{132, 11, 569}, - dictWord{133, 10, 308}, - dictWord{135, 10, 1088}, - dictWord{4, 0, 661}, - dictWord{138, 0, 1004}, - dictWord{5, 11, 37}, - dictWord{6, 11, 39}, - dictWord{6, 11, 451}, - dictWord{7, 11, 218}, - dictWord{7, 11, 667}, - dictWord{7, 11, 1166}, - dictWord{7, 11, 1687}, - dictWord{8, 11, 662}, - dictWord{144, 11, 2}, - dictWord{9, 0, 445}, - dictWord{12, 0, 53}, - dictWord{13, 0, 492}, - dictWord{5, 10, 126}, - dictWord{8, 10, 297}, - dictWord{ - 9, - 10, - 366, - }, - dictWord{140, 10, 374}, - dictWord{7, 10, 1551}, - dictWord{139, 10, 361}, - dictWord{148, 0, 74}, - dictWord{134, 11, 508}, - dictWord{135, 0, 213}, - dictWord{132, 10, 175}, - dictWord{132, 10, 685}, - dictWord{6, 0, 760}, - dictWord{6, 0, 834}, - dictWord{134, 0, 1248}, - dictWord{7, 11, 453}, - dictWord{7, 11, 635}, - dictWord{7, 11, 796}, - dictWord{8, 11, 331}, - dictWord{9, 11, 328}, - dictWord{9, 11, 330}, - dictWord{9, 11, 865}, - dictWord{10, 11, 119}, - dictWord{10, 11, 235}, - dictWord{11, 11, 111}, - dictWord{11, 11, 129}, - dictWord{11, 11, 240}, - dictWord{12, 11, 31}, - dictWord{12, 11, 66}, - dictWord{12, 11, 222}, - dictWord{12, 11, 269}, - dictWord{12, 11, 599}, - dictWord{12, 11, 689}, - dictWord{13, 11, 186}, - dictWord{13, 11, 364}, - dictWord{142, 11, 345}, - dictWord{7, 0, 1672}, - dictWord{ - 139, - 0, - 189, - }, - dictWord{133, 10, 797}, - dictWord{133, 10, 565}, - dictWord{6, 0, 1548}, - dictWord{6, 11, 98}, - dictWord{7, 11, 585}, - dictWord{135, 11, 702}, - dictWord{ - 9, - 0, - 968, - }, - dictWord{15, 0, 192}, - dictWord{149, 0, 56}, - dictWord{4, 10, 252}, - dictWord{6, 11, 37}, - dictWord{7, 11, 299}, - dictWord{7, 10, 1068}, - dictWord{ - 7, - 11, - 1666, - }, - dictWord{8, 11, 195}, - dictWord{8, 11, 316}, - dictWord{9, 11, 178}, - dictWord{9, 11, 276}, - dictWord{9, 11, 339}, - dictWord{9, 11, 536}, - dictWord{ - 10, - 11, - 102, - }, - dictWord{10, 11, 362}, - dictWord{10, 10, 434}, - dictWord{10, 11, 785}, - dictWord{11, 11, 55}, - dictWord{11, 11, 149}, - dictWord{11, 10, 228}, - dictWord{ - 11, - 10, - 426, - }, - dictWord{11, 11, 773}, - dictWord{13, 10, 231}, - dictWord{13, 11, 416}, - dictWord{13, 11, 419}, - dictWord{14, 11, 38}, - dictWord{14, 11, 41}, - dictWord{14, 11, 210}, - dictWord{18, 10, 106}, - dictWord{148, 10, 87}, - dictWord{4, 0, 751}, - dictWord{11, 0, 390}, - dictWord{140, 0, 32}, - dictWord{4, 0, 409}, - dictWord{133, 0, 78}, - dictWord{11, 11, 458}, - dictWord{12, 11, 15}, - dictWord{140, 11, 432}, - dictWord{7, 0, 1602}, - dictWord{10, 0, 257}, - dictWord{10, 0, 698}, - dictWord{11, 0, 544}, - dictWord{11, 0, 585}, - dictWord{12, 0, 212}, - dictWord{13, 0, 307}, - dictWord{5, 10, 231}, - dictWord{7, 10, 601}, - dictWord{9, 10, 277}, - dictWord{ - 9, - 10, - 674, - }, - dictWord{10, 10, 178}, - dictWord{10, 10, 418}, - dictWord{10, 10, 509}, - dictWord{11, 10, 531}, - dictWord{12, 10, 113}, - dictWord{12, 10, 475}, - dictWord{13, 10, 99}, - dictWord{142, 10, 428}, - dictWord{6, 0, 473}, - dictWord{145, 0, 105}, - dictWord{6, 0, 1949}, - dictWord{15, 0, 156}, - dictWord{133, 11, 645}, - dictWord{7, 10, 1591}, - dictWord{144, 10, 43}, - dictWord{135, 0, 1779}, - dictWord{135, 10, 1683}, - dictWord{4, 11, 290}, - dictWord{135, 11, 1356}, - dictWord{134, 0, 763}, - dictWord{6, 11, 70}, - dictWord{7, 11, 1292}, - dictWord{10, 11, 762}, - dictWord{139, 11, 288}, - dictWord{142, 0, 29}, - dictWord{140, 11, 428}, - dictWord{7, 0, 883}, - dictWord{7, 11, 131}, - dictWord{7, 11, 422}, - dictWord{8, 11, 210}, - dictWord{140, 11, 573}, - dictWord{134, 0, 488}, - dictWord{4, 10, 399}, - dictWord{5, 10, 119}, - dictWord{5, 10, 494}, - dictWord{7, 10, 751}, - dictWord{137, 10, 556}, - dictWord{133, 0, 617}, - dictWord{132, 11, 936}, - dictWord{ - 139, - 0, - 50, - }, - dictWord{7, 0, 1518}, - dictWord{139, 0, 694}, - dictWord{137, 0, 785}, - dictWord{4, 0, 546}, - dictWord{135, 0, 2042}, - dictWord{7, 11, 716}, - dictWord{ - 13, - 11, - 97, - }, - dictWord{141, 11, 251}, - dictWord{132, 11, 653}, - dictWord{145, 0, 22}, - dictWord{134, 0, 1016}, - dictWord{4, 0, 313}, - dictWord{133, 0, 577}, - dictWord{ - 136, - 11, - 657, - }, - dictWord{8, 0, 184}, - dictWord{141, 0, 433}, - dictWord{135, 0, 935}, - dictWord{6, 0, 720}, - dictWord{9, 0, 114}, - dictWord{146, 11, 80}, - dictWord{ - 12, - 0, - 186, - }, - dictWord{12, 0, 292}, - dictWord{14, 0, 100}, - dictWord{18, 0, 70}, - dictWord{7, 10, 594}, - dictWord{7, 10, 851}, - dictWord{7, 10, 1858}, - dictWord{ - 9, - 10, - 411, - }, - dictWord{9, 10, 574}, - dictWord{9, 10, 666}, - dictWord{9, 10, 737}, - dictWord{10, 10, 346}, - dictWord{10, 10, 712}, - dictWord{11, 10, 246}, - dictWord{ - 11, - 10, - 432, - }, - dictWord{11, 10, 517}, - dictWord{11, 10, 647}, - dictWord{11, 10, 679}, - dictWord{11, 10, 727}, - dictWord{12, 10, 304}, - dictWord{12, 10, 305}, - dictWord{12, 10, 323}, - dictWord{12, 10, 483}, - dictWord{12, 10, 572}, - dictWord{12, 10, 593}, - dictWord{12, 10, 602}, - dictWord{13, 10, 95}, - dictWord{13, 10, 101}, - dictWord{13, 10, 171}, - dictWord{13, 10, 315}, - dictWord{13, 10, 378}, - dictWord{13, 10, 425}, - dictWord{13, 10, 475}, - dictWord{14, 10, 63}, - dictWord{ - 14, - 10, - 380, - }, - dictWord{14, 10, 384}, - dictWord{15, 10, 133}, - dictWord{18, 10, 112}, - dictWord{148, 10, 72}, - dictWord{135, 10, 1093}, - dictWord{135, 11, 1836}, - dictWord{132, 10, 679}, - dictWord{137, 10, 203}, - dictWord{11, 0, 402}, - dictWord{12, 0, 109}, - dictWord{12, 0, 431}, - dictWord{13, 0, 179}, - dictWord{13, 0, 206}, - dictWord{14, 0, 217}, - dictWord{16, 0, 3}, - dictWord{148, 0, 53}, - dictWord{7, 11, 1368}, - dictWord{8, 11, 232}, - dictWord{8, 11, 361}, - dictWord{10, 11, 682}, - dictWord{138, 11, 742}, - dictWord{137, 10, 714}, - dictWord{5, 0, 886}, - dictWord{6, 0, 46}, - dictWord{6, 0, 1790}, - dictWord{7, 0, 14}, - dictWord{7, 0, 732}, - dictWord{ - 7, - 0, - 1654, - }, - dictWord{8, 0, 95}, - dictWord{8, 0, 327}, - dictWord{8, 0, 616}, - dictWord{9, 0, 892}, - dictWord{10, 0, 598}, - dictWord{10, 0, 769}, - dictWord{11, 0, 134}, - dictWord{11, 0, 747}, - dictWord{12, 0, 378}, - dictWord{14, 0, 97}, - dictWord{137, 11, 534}, - dictWord{4, 0, 969}, - dictWord{136, 10, 825}, - dictWord{137, 11, 27}, - dictWord{6, 0, 727}, - dictWord{142, 11, 12}, - dictWord{133, 0, 1021}, - dictWord{134, 0, 1190}, - dictWord{134, 11, 1657}, - dictWord{5, 10, 143}, - dictWord{ - 5, - 10, - 769, - }, - dictWord{6, 10, 1760}, - dictWord{7, 10, 682}, - dictWord{7, 10, 1992}, - dictWord{136, 10, 736}, - dictWord{132, 0, 153}, - dictWord{135, 11, 127}, - dictWord{133, 0, 798}, - dictWord{132, 0, 587}, - dictWord{6, 0, 598}, - dictWord{7, 0, 42}, - dictWord{8, 0, 695}, - dictWord{10, 0, 212}, - dictWord{11, 0, 158}, - dictWord{ - 14, - 0, - 196, - }, - dictWord{145, 0, 85}, - dictWord{133, 10, 860}, - dictWord{6, 0, 1929}, - dictWord{134, 0, 1933}, - dictWord{5, 0, 957}, - dictWord{5, 0, 1008}, - dictWord{ - 9, - 0, - 577, - }, - dictWord{12, 0, 141}, - dictWord{6, 10, 422}, - dictWord{7, 10, 0}, - dictWord{7, 10, 1544}, - dictWord{8, 11, 364}, - dictWord{11, 10, 990}, - dictWord{ - 12, - 10, - 453, - }, - dictWord{13, 10, 47}, - dictWord{141, 10, 266}, - dictWord{134, 0, 1319}, - dictWord{4, 0, 129}, - dictWord{135, 0, 465}, - dictWord{7, 0, 470}, - dictWord{ - 7, - 0, - 1057, - }, - dictWord{7, 0, 1201}, - dictWord{9, 0, 755}, - dictWord{11, 0, 906}, - dictWord{140, 0, 527}, - dictWord{7, 0, 908}, - dictWord{146, 0, 7}, - dictWord{5, 0, 148}, - dictWord{136, 0, 450}, - dictWord{5, 10, 515}, - dictWord{137, 10, 131}, - dictWord{7, 10, 1605}, - dictWord{11, 10, 962}, - dictWord{146, 10, 139}, - dictWord{ - 132, - 10, - 646, - }, - dictWord{134, 0, 1166}, - dictWord{4, 10, 396}, - dictWord{7, 10, 728}, - dictWord{9, 10, 117}, - dictWord{13, 10, 202}, - dictWord{148, 10, 51}, - dictWord{ - 6, - 10, - 121, - }, - dictWord{6, 10, 124}, - dictWord{6, 10, 357}, - dictWord{7, 10, 1138}, - dictWord{7, 10, 1295}, - dictWord{8, 10, 162}, - dictWord{139, 10, 655}, - dictWord{14, 0, 374}, - dictWord{142, 11, 374}, - dictWord{138, 0, 253}, - dictWord{139, 0, 1003}, - dictWord{5, 11, 909}, - dictWord{9, 11, 849}, - dictWord{ - 138, - 11, - 805, - }, - dictWord{133, 10, 237}, - dictWord{7, 11, 525}, - dictWord{7, 11, 1579}, - dictWord{8, 11, 497}, - dictWord{136, 11, 573}, - dictWord{137, 0, 46}, - dictWord{ - 132, - 0, - 879, - }, - dictWord{134, 0, 806}, - dictWord{135, 0, 1868}, - dictWord{6, 0, 1837}, - dictWord{134, 0, 1846}, - dictWord{6, 0, 730}, - dictWord{134, 0, 881}, - dictWord{7, 0, 965}, - dictWord{7, 0, 1460}, - dictWord{7, 0, 1604}, - dictWord{7, 11, 193}, - dictWord{7, 11, 397}, - dictWord{7, 11, 1105}, - dictWord{8, 11, 124}, - dictWord{ - 8, - 11, - 619, - }, - dictWord{9, 11, 305}, - dictWord{10, 11, 264}, - dictWord{11, 11, 40}, - dictWord{12, 11, 349}, - dictWord{13, 11, 134}, - dictWord{13, 11, 295}, - dictWord{14, 11, 155}, - dictWord{15, 11, 120}, - dictWord{146, 11, 105}, - dictWord{136, 0, 506}, - dictWord{143, 0, 10}, - dictWord{4, 11, 262}, - dictWord{7, 11, 342}, - dictWord{7, 10, 571}, - dictWord{7, 10, 1877}, - dictWord{10, 10, 366}, - dictWord{141, 11, 23}, - dictWord{133, 11, 641}, - dictWord{10, 0, 22}, - dictWord{9, 10, 513}, - dictWord{10, 10, 39}, - dictWord{12, 10, 122}, - dictWord{140, 10, 187}, - dictWord{135, 11, 1431}, - dictWord{150, 11, 49}, - dictWord{4, 11, 99}, - dictWord{ - 6, - 11, - 250, - }, - dictWord{6, 11, 346}, - dictWord{8, 11, 127}, - dictWord{138, 11, 81}, - dictWord{6, 0, 2014}, - dictWord{8, 0, 928}, - dictWord{10, 0, 960}, - dictWord{10, 0, 979}, - dictWord{140, 0, 996}, - dictWord{134, 0, 296}, - dictWord{132, 11, 915}, - dictWord{5, 11, 75}, - dictWord{9, 11, 517}, - dictWord{10, 11, 470}, - dictWord{ - 12, - 11, - 155, - }, - dictWord{141, 11, 224}, - dictWord{137, 10, 873}, - dictWord{4, 0, 854}, - dictWord{140, 11, 18}, - dictWord{134, 0, 587}, - dictWord{7, 10, 107}, - dictWord{ - 7, - 10, - 838, - }, - dictWord{8, 10, 550}, - dictWord{138, 10, 401}, - dictWord{11, 0, 636}, - dictWord{15, 0, 145}, - dictWord{17, 0, 34}, - dictWord{19, 0, 50}, - dictWord{ - 23, - 0, - 20, - }, - dictWord{11, 10, 588}, - dictWord{11, 10, 864}, - dictWord{11, 10, 968}, - dictWord{143, 10, 160}, - dictWord{135, 11, 216}, - dictWord{7, 0, 982}, - dictWord{ - 10, - 0, - 32, - }, - dictWord{143, 0, 56}, - dictWord{133, 10, 768}, - dictWord{133, 11, 954}, - dictWord{6, 11, 304}, - dictWord{7, 11, 1114}, - dictWord{8, 11, 418}, - dictWord{ - 10, - 11, - 345, - }, - dictWord{11, 11, 341}, - dictWord{11, 11, 675}, - dictWord{141, 11, 40}, - dictWord{9, 11, 410}, - dictWord{139, 11, 425}, - dictWord{136, 0, 941}, - dictWord{5, 0, 435}, - dictWord{132, 10, 894}, - dictWord{5, 0, 85}, - dictWord{6, 0, 419}, - dictWord{7, 0, 134}, - dictWord{7, 0, 305}, - dictWord{7, 0, 361}, - dictWord{ - 7, - 0, - 1337, - }, - dictWord{8, 0, 71}, - dictWord{140, 0, 519}, - dictWord{140, 0, 688}, - dictWord{135, 0, 740}, - dictWord{5, 0, 691}, - dictWord{7, 0, 345}, - dictWord{9, 0, 94}, - dictWord{140, 0, 169}, - dictWord{5, 0, 183}, - dictWord{6, 0, 582}, - dictWord{10, 0, 679}, - dictWord{140, 0, 435}, - dictWord{134, 11, 14}, - dictWord{6, 0, 945}, - dictWord{135, 0, 511}, - dictWord{134, 11, 1708}, - dictWord{5, 11, 113}, - dictWord{6, 11, 243}, - dictWord{7, 11, 1865}, - dictWord{11, 11, 161}, - dictWord{16, 11, 37}, - dictWord{145, 11, 99}, - dictWord{132, 11, 274}, - dictWord{137, 0, 539}, - dictWord{7, 0, 1993}, - dictWord{8, 0, 684}, - dictWord{134, 10, 272}, - dictWord{ - 6, - 0, - 659, - }, - dictWord{134, 0, 982}, - dictWord{4, 10, 9}, - dictWord{5, 10, 128}, - dictWord{7, 10, 368}, - dictWord{11, 10, 480}, - dictWord{148, 10, 3}, - dictWord{ - 134, - 0, - 583, - }, - dictWord{132, 0, 803}, - dictWord{133, 0, 704}, - dictWord{4, 0, 179}, - dictWord{5, 0, 198}, - dictWord{133, 0, 697}, - dictWord{7, 0, 347}, - dictWord{7, 0, 971}, - dictWord{8, 0, 181}, - dictWord{10, 0, 711}, - dictWord{135, 11, 166}, - dictWord{136, 10, 682}, - dictWord{4, 10, 2}, - dictWord{7, 10, 545}, - dictWord{7, 10, 894}, - dictWord{136, 11, 521}, - dictWord{135, 0, 481}, - dictWord{132, 0, 243}, - dictWord{5, 0, 203}, - dictWord{7, 0, 19}, - dictWord{7, 0, 71}, - dictWord{7, 0, 113}, - dictWord{ - 10, - 0, - 405, - }, - dictWord{11, 0, 357}, - dictWord{142, 0, 240}, - dictWord{5, 11, 725}, - dictWord{5, 11, 727}, - dictWord{135, 11, 1811}, - dictWord{6, 0, 826}, - dictWord{ - 137, - 11, - 304, - }, - dictWord{7, 0, 1450}, - dictWord{139, 0, 99}, - dictWord{133, 11, 654}, - dictWord{134, 0, 492}, - dictWord{5, 0, 134}, - dictWord{6, 0, 408}, - dictWord{ - 6, - 0, - 495, - }, - dictWord{7, 0, 1593}, - dictWord{6, 11, 273}, - dictWord{10, 11, 188}, - dictWord{13, 11, 377}, - dictWord{146, 11, 77}, - dictWord{9, 10, 769}, - dictWord{ - 140, - 10, - 185, - }, - dictWord{135, 11, 410}, - dictWord{142, 0, 4}, - dictWord{4, 0, 665}, - dictWord{134, 11, 1785}, - dictWord{4, 0, 248}, - dictWord{7, 0, 137}, - dictWord{ - 137, - 0, - 349, - }, - dictWord{5, 10, 530}, - dictWord{142, 10, 113}, - dictWord{7, 0, 1270}, - dictWord{139, 0, 612}, - dictWord{132, 11, 780}, - dictWord{5, 0, 371}, - dictWord{135, 0, 563}, - dictWord{135, 0, 826}, - dictWord{6, 0, 1535}, - dictWord{23, 0, 21}, - dictWord{151, 0, 23}, - dictWord{4, 0, 374}, - dictWord{7, 0, 547}, - dictWord{ - 7, - 0, - 1700, - }, - dictWord{7, 0, 1833}, - dictWord{139, 0, 858}, - dictWord{133, 10, 556}, - dictWord{7, 11, 612}, - dictWord{8, 11, 545}, - dictWord{8, 11, 568}, - dictWord{ - 8, - 11, - 642, - }, - dictWord{9, 11, 717}, - dictWord{10, 11, 541}, - dictWord{10, 11, 763}, - dictWord{11, 11, 449}, - dictWord{12, 11, 489}, - dictWord{13, 11, 153}, - dictWord{ - 13, - 11, - 296, - }, - dictWord{14, 11, 138}, - dictWord{14, 11, 392}, - dictWord{15, 11, 50}, - dictWord{16, 11, 6}, - dictWord{16, 11, 12}, - dictWord{148, 11, 9}, - dictWord{ - 9, - 0, - 311, - }, - dictWord{141, 0, 42}, - dictWord{8, 10, 16}, - dictWord{140, 10, 568}, - dictWord{6, 0, 1968}, - dictWord{6, 0, 2027}, - dictWord{138, 0, 991}, - dictWord{ - 6, - 0, - 1647, - }, - dictWord{7, 0, 1552}, - dictWord{7, 0, 2010}, - dictWord{9, 0, 494}, - dictWord{137, 0, 509}, - dictWord{133, 11, 948}, - dictWord{6, 10, 186}, - dictWord{ - 137, - 10, - 426, - }, - dictWord{134, 0, 769}, - dictWord{134, 0, 642}, - dictWord{132, 10, 585}, - dictWord{6, 0, 123}, - dictWord{7, 0, 214}, - dictWord{9, 0, 728}, - dictWord{ - 10, - 0, - 157, - }, - dictWord{11, 0, 346}, - dictWord{11, 0, 662}, - dictWord{143, 0, 106}, - dictWord{142, 11, 381}, - dictWord{135, 0, 1435}, - dictWord{4, 11, 532}, - dictWord{ - 5, - 11, - 706, - }, - dictWord{135, 11, 662}, - dictWord{5, 11, 837}, - dictWord{134, 11, 1651}, - dictWord{4, 10, 93}, - dictWord{5, 10, 252}, - dictWord{6, 10, 229}, - dictWord{ - 7, - 10, - 291, - }, - dictWord{9, 10, 550}, - dictWord{139, 10, 644}, - dictWord{148, 0, 79}, - dictWord{137, 10, 749}, - dictWord{134, 0, 1425}, - dictWord{ - 137, - 10, - 162, - }, - dictWord{4, 11, 362}, - dictWord{7, 11, 52}, - dictWord{7, 11, 303}, - dictWord{140, 11, 166}, - dictWord{132, 10, 381}, - dictWord{4, 11, 330}, - dictWord{ - 7, - 11, - 933, - }, - dictWord{7, 11, 2012}, - dictWord{136, 11, 292}, - dictWord{135, 11, 767}, - dictWord{4, 0, 707}, - dictWord{5, 0, 588}, - dictWord{6, 0, 393}, - dictWord{ - 13, - 0, - 106, - }, - dictWord{18, 0, 49}, - dictWord{147, 0, 41}, - dictWord{6, 0, 211}, - dictWord{7, 0, 1690}, - dictWord{11, 0, 486}, - dictWord{140, 0, 369}, - dictWord{ - 137, - 11, - 883, - }, - dictWord{4, 11, 703}, - dictWord{135, 11, 207}, - dictWord{4, 0, 187}, - dictWord{5, 0, 184}, - dictWord{5, 0, 690}, - dictWord{7, 0, 1869}, - dictWord{10, 0, 756}, - dictWord{139, 0, 783}, - dictWord{132, 11, 571}, - dictWord{134, 0, 1382}, - dictWord{5, 0, 175}, - dictWord{6, 10, 77}, - dictWord{6, 10, 157}, - dictWord{7, 10, 974}, - dictWord{7, 10, 1301}, - dictWord{7, 10, 1339}, - dictWord{7, 10, 1490}, - dictWord{7, 10, 1873}, - dictWord{137, 10, 628}, - dictWord{134, 0, 1493}, - dictWord{ - 5, - 11, - 873, - }, - dictWord{133, 11, 960}, - dictWord{134, 0, 1007}, - dictWord{12, 11, 93}, - dictWord{12, 11, 501}, - dictWord{13, 11, 362}, - dictWord{14, 11, 151}, - dictWord{15, 11, 40}, - dictWord{15, 11, 59}, - dictWord{16, 11, 46}, - dictWord{17, 11, 25}, - dictWord{18, 11, 14}, - dictWord{18, 11, 134}, - dictWord{19, 11, 25}, - dictWord{ - 19, - 11, - 69, - }, - dictWord{20, 11, 16}, - dictWord{20, 11, 19}, - dictWord{20, 11, 66}, - dictWord{21, 11, 23}, - dictWord{21, 11, 25}, - dictWord{150, 11, 42}, - dictWord{ - 11, - 10, - 919, - }, - dictWord{141, 10, 409}, - dictWord{134, 0, 219}, - dictWord{5, 0, 582}, - dictWord{6, 0, 1646}, - dictWord{7, 0, 99}, - dictWord{7, 0, 1962}, - dictWord{ - 7, - 0, - 1986, - }, - dictWord{8, 0, 515}, - dictWord{8, 0, 773}, - dictWord{9, 0, 23}, - dictWord{9, 0, 491}, - dictWord{12, 0, 620}, - dictWord{142, 0, 93}, - dictWord{133, 0, 851}, - dictWord{5, 11, 33}, - dictWord{134, 11, 470}, - dictWord{135, 11, 1291}, - dictWord{134, 0, 1278}, - dictWord{135, 11, 1882}, - dictWord{135, 10, 1489}, - dictWord{132, 0, 1000}, - dictWord{138, 0, 982}, - dictWord{8, 0, 762}, - dictWord{8, 0, 812}, - dictWord{137, 0, 910}, - dictWord{6, 11, 47}, - dictWord{7, 11, 90}, - dictWord{ - 7, - 11, - 664, - }, - dictWord{7, 11, 830}, - dictWord{7, 11, 1380}, - dictWord{7, 11, 2025}, - dictWord{8, 11, 448}, - dictWord{136, 11, 828}, - dictWord{4, 0, 98}, - dictWord{ - 4, - 0, - 940, - }, - dictWord{6, 0, 1819}, - dictWord{6, 0, 1834}, - dictWord{6, 0, 1841}, - dictWord{7, 0, 1365}, - dictWord{8, 0, 859}, - dictWord{8, 0, 897}, - dictWord{8, 0, 918}, - dictWord{9, 0, 422}, - dictWord{9, 0, 670}, - dictWord{10, 0, 775}, - dictWord{10, 0, 894}, - dictWord{10, 0, 909}, - dictWord{10, 0, 910}, - dictWord{10, 0, 935}, - dictWord{ - 11, - 0, - 210, - }, - dictWord{12, 0, 750}, - dictWord{12, 0, 755}, - dictWord{13, 0, 26}, - dictWord{13, 0, 457}, - dictWord{13, 0, 476}, - dictWord{16, 0, 100}, - dictWord{16, 0, 109}, - dictWord{18, 0, 173}, - dictWord{18, 0, 175}, - dictWord{8, 10, 398}, - dictWord{9, 10, 681}, - dictWord{139, 10, 632}, - dictWord{9, 11, 417}, - dictWord{ - 137, - 11, - 493, - }, - dictWord{136, 10, 645}, - dictWord{138, 0, 906}, - dictWord{134, 0, 1730}, - dictWord{134, 10, 20}, - dictWord{133, 11, 1019}, - dictWord{134, 0, 1185}, - dictWord{10, 0, 40}, - dictWord{136, 10, 769}, - dictWord{9, 0, 147}, - dictWord{134, 11, 208}, - dictWord{140, 0, 650}, - dictWord{5, 0, 209}, - dictWord{6, 0, 30}, - dictWord{11, 0, 56}, - dictWord{139, 0, 305}, - dictWord{132, 0, 553}, - dictWord{138, 11, 344}, - dictWord{6, 11, 68}, - dictWord{7, 11, 398}, - dictWord{7, 11, 448}, - dictWord{ - 7, - 11, - 1629, - }, - dictWord{7, 11, 1813}, - dictWord{8, 11, 387}, - dictWord{8, 11, 442}, - dictWord{9, 11, 710}, - dictWord{10, 11, 282}, - dictWord{138, 11, 722}, - dictWord{5, 0, 597}, - dictWord{14, 0, 20}, - dictWord{142, 11, 20}, - dictWord{135, 0, 1614}, - dictWord{135, 10, 1757}, - dictWord{4, 0, 150}, - dictWord{5, 0, 303}, - dictWord{6, 0, 327}, - dictWord{135, 10, 937}, - dictWord{16, 0, 49}, - dictWord{7, 10, 1652}, - dictWord{144, 11, 49}, - dictWord{8, 0, 192}, - dictWord{10, 0, 78}, - dictWord{ - 141, - 0, - 359, - }, - dictWord{135, 0, 786}, - dictWord{143, 0, 134}, - dictWord{6, 0, 1638}, - dictWord{7, 0, 79}, - dictWord{7, 0, 496}, - dictWord{9, 0, 138}, - dictWord{ - 10, - 0, - 336, - }, - dictWord{11, 0, 12}, - dictWord{12, 0, 412}, - dictWord{12, 0, 440}, - dictWord{142, 0, 305}, - dictWord{136, 11, 491}, - dictWord{4, 10, 579}, - dictWord{ - 5, - 10, - 226, - }, - dictWord{5, 10, 323}, - dictWord{135, 10, 960}, - dictWord{7, 0, 204}, - dictWord{7, 0, 415}, - dictWord{8, 0, 42}, - dictWord{10, 0, 85}, - dictWord{139, 0, 564}, - dictWord{132, 0, 614}, - dictWord{4, 11, 403}, - dictWord{5, 11, 441}, - dictWord{7, 11, 450}, - dictWord{11, 11, 101}, - dictWord{12, 11, 193}, - dictWord{141, 11, 430}, - dictWord{135, 11, 1927}, - dictWord{135, 11, 1330}, - dictWord{4, 0, 3}, - dictWord{5, 0, 247}, - dictWord{5, 0, 644}, - dictWord{7, 0, 744}, - dictWord{7, 0, 1207}, - dictWord{7, 0, 1225}, - dictWord{7, 0, 1909}, - dictWord{146, 0, 147}, - dictWord{136, 0, 942}, - dictWord{4, 0, 1019}, - dictWord{134, 0, 2023}, - dictWord{5, 11, 679}, - dictWord{133, 10, 973}, - dictWord{5, 0, 285}, - dictWord{9, 0, 67}, - dictWord{13, 0, 473}, - dictWord{143, 0, 82}, - dictWord{7, 11, 328}, - dictWord{137, 11, 326}, - dictWord{151, 0, 8}, - dictWord{6, 10, 135}, - dictWord{135, 10, 1176}, - dictWord{135, 11, 1128}, - dictWord{134, 0, 1309}, - dictWord{135, 11, 1796}, - dictWord{ - 135, - 10, - 314, - }, - dictWord{4, 11, 574}, - dictWord{7, 11, 350}, - dictWord{7, 11, 1024}, - dictWord{8, 11, 338}, - dictWord{9, 11, 677}, - dictWord{10, 11, 808}, - dictWord{ - 139, - 11, - 508, - }, - dictWord{7, 11, 818}, - dictWord{17, 11, 14}, - dictWord{17, 11, 45}, - dictWord{18, 11, 75}, - dictWord{148, 11, 18}, - dictWord{146, 10, 4}, - dictWord{ - 135, - 11, - 1081, - }, - dictWord{4, 0, 29}, - dictWord{6, 0, 532}, - dictWord{7, 0, 1628}, - dictWord{7, 0, 1648}, - dictWord{9, 0, 350}, - dictWord{10, 0, 433}, - dictWord{11, 0, 97}, - dictWord{11, 0, 557}, - dictWord{11, 0, 745}, - dictWord{12, 0, 289}, - dictWord{12, 0, 335}, - dictWord{12, 0, 348}, - dictWord{12, 0, 606}, - dictWord{13, 0, 116}, - dictWord{13, 0, 233}, - dictWord{13, 0, 466}, - dictWord{14, 0, 181}, - dictWord{14, 0, 209}, - dictWord{14, 0, 232}, - dictWord{14, 0, 236}, - dictWord{14, 0, 300}, - dictWord{ - 16, - 0, - 41, - }, - dictWord{148, 0, 97}, - dictWord{7, 0, 318}, - dictWord{6, 10, 281}, - dictWord{8, 10, 282}, - dictWord{8, 10, 480}, - dictWord{8, 10, 499}, - dictWord{9, 10, 198}, - dictWord{10, 10, 143}, - dictWord{10, 10, 169}, - dictWord{10, 10, 211}, - dictWord{10, 10, 417}, - dictWord{10, 10, 574}, - dictWord{11, 10, 147}, - dictWord{ - 11, - 10, - 395, - }, - dictWord{12, 10, 75}, - dictWord{12, 10, 407}, - dictWord{12, 10, 608}, - dictWord{13, 10, 500}, - dictWord{142, 10, 251}, - dictWord{135, 11, 1676}, - dictWord{135, 11, 2037}, - dictWord{135, 0, 1692}, - dictWord{5, 0, 501}, - dictWord{7, 0, 1704}, - dictWord{9, 0, 553}, - dictWord{11, 0, 520}, - dictWord{12, 0, 557}, - dictWord{141, 0, 249}, - dictWord{6, 0, 1527}, - dictWord{14, 0, 324}, - dictWord{15, 0, 55}, - dictWord{15, 0, 80}, - dictWord{14, 11, 324}, - dictWord{15, 11, 55}, - dictWord{143, 11, 80}, - dictWord{135, 10, 1776}, - dictWord{8, 0, 988}, - dictWord{137, 11, 297}, - dictWord{132, 10, 419}, - dictWord{142, 0, 223}, - dictWord{ - 139, - 11, - 234, - }, - dictWord{7, 0, 1123}, - dictWord{12, 0, 508}, - dictWord{14, 0, 102}, - dictWord{14, 0, 226}, - dictWord{144, 0, 57}, - dictWord{4, 10, 138}, - dictWord{ - 7, - 10, - 1012, - }, - dictWord{7, 10, 1280}, - dictWord{137, 10, 76}, - dictWord{7, 0, 1764}, - dictWord{5, 10, 29}, - dictWord{140, 10, 638}, - dictWord{134, 0, 2015}, - dictWord{134, 0, 1599}, - dictWord{138, 11, 56}, - dictWord{6, 11, 306}, - dictWord{7, 11, 1140}, - dictWord{7, 11, 1340}, - dictWord{8, 11, 133}, - dictWord{ - 138, - 11, - 449, - }, - dictWord{139, 11, 1011}, - dictWord{6, 10, 1710}, - dictWord{135, 10, 2038}, - dictWord{7, 11, 1763}, - dictWord{140, 11, 310}, - dictWord{6, 0, 129}, - dictWord{4, 10, 17}, - dictWord{5, 10, 23}, - dictWord{7, 10, 995}, - dictWord{11, 10, 383}, - dictWord{11, 10, 437}, - dictWord{12, 10, 460}, - dictWord{140, 10, 532}, - dictWord{5, 11, 329}, - dictWord{136, 11, 260}, - dictWord{133, 10, 862}, - dictWord{132, 0, 534}, - dictWord{6, 0, 811}, - dictWord{135, 0, 626}, - dictWord{ - 132, - 11, - 657, - }, - dictWord{4, 0, 25}, - dictWord{5, 0, 60}, - dictWord{6, 0, 504}, - dictWord{7, 0, 614}, - dictWord{7, 0, 1155}, - dictWord{12, 0, 0}, - dictWord{152, 11, 7}, - dictWord{ - 7, - 0, - 1248, - }, - dictWord{11, 0, 621}, - dictWord{139, 0, 702}, - dictWord{137, 0, 321}, - dictWord{8, 10, 70}, - dictWord{12, 10, 171}, - dictWord{141, 10, 272}, - dictWord{ - 10, - 10, - 233, - }, - dictWord{139, 10, 76}, - dictWord{4, 0, 379}, - dictWord{7, 0, 1397}, - dictWord{134, 10, 442}, - dictWord{5, 11, 66}, - dictWord{7, 11, 1896}, - dictWord{ - 136, - 11, - 288, - }, - dictWord{134, 11, 1643}, - dictWord{134, 10, 1709}, - dictWord{4, 11, 21}, - dictWord{5, 11, 91}, - dictWord{5, 11, 570}, - dictWord{5, 11, 648}, - dictWord{5, 11, 750}, - dictWord{5, 11, 781}, - dictWord{6, 11, 54}, - dictWord{6, 11, 112}, - dictWord{6, 11, 402}, - dictWord{6, 11, 1732}, - dictWord{7, 11, 315}, - dictWord{ - 7, - 11, - 749, - }, - dictWord{7, 11, 1347}, - dictWord{7, 11, 1900}, - dictWord{9, 11, 78}, - dictWord{9, 11, 508}, - dictWord{10, 11, 611}, - dictWord{11, 11, 510}, - dictWord{ - 11, - 11, - 728, - }, - dictWord{13, 11, 36}, - dictWord{14, 11, 39}, - dictWord{16, 11, 83}, - dictWord{17, 11, 124}, - dictWord{148, 11, 30}, - dictWord{4, 0, 118}, - dictWord{ - 6, - 0, - 274, - }, - dictWord{6, 0, 361}, - dictWord{7, 0, 75}, - dictWord{141, 0, 441}, - dictWord{10, 11, 322}, - dictWord{10, 11, 719}, - dictWord{139, 11, 407}, - dictWord{ - 147, - 10, - 119, - }, - dictWord{12, 11, 549}, - dictWord{14, 11, 67}, - dictWord{147, 11, 60}, - dictWord{11, 10, 69}, - dictWord{12, 10, 105}, - dictWord{12, 10, 117}, - dictWord{13, 10, 213}, - dictWord{14, 10, 13}, - dictWord{14, 10, 62}, - dictWord{14, 10, 177}, - dictWord{14, 10, 421}, - dictWord{15, 10, 19}, - dictWord{146, 10, 141}, - dictWord{9, 0, 841}, - dictWord{137, 10, 309}, - dictWord{7, 10, 608}, - dictWord{7, 10, 976}, - dictWord{8, 11, 125}, - dictWord{8, 11, 369}, - dictWord{8, 11, 524}, - dictWord{9, 10, 146}, - dictWord{10, 10, 206}, - dictWord{10, 11, 486}, - dictWord{10, 10, 596}, - dictWord{11, 11, 13}, - dictWord{11, 11, 381}, - dictWord{11, 11, 736}, - dictWord{11, 11, 766}, - dictWord{11, 11, 845}, - dictWord{13, 11, 114}, - dictWord{13, 10, 218}, - dictWord{13, 11, 292}, - dictWord{14, 11, 47}, - dictWord{ - 142, - 10, - 153, - }, - dictWord{12, 0, 693}, - dictWord{135, 11, 759}, - dictWord{5, 0, 314}, - dictWord{6, 0, 221}, - dictWord{7, 0, 419}, - dictWord{10, 0, 650}, - dictWord{11, 0, 396}, - dictWord{12, 0, 156}, - dictWord{13, 0, 369}, - dictWord{14, 0, 333}, - dictWord{145, 0, 47}, - dictWord{6, 11, 1684}, - dictWord{6, 11, 1731}, - dictWord{7, 11, 356}, - dictWord{7, 11, 1932}, - dictWord{8, 11, 54}, - dictWord{8, 11, 221}, - dictWord{9, 11, 225}, - dictWord{9, 11, 356}, - dictWord{10, 11, 77}, - dictWord{10, 11, 446}, - dictWord{10, 11, 731}, - dictWord{12, 11, 404}, - dictWord{141, 11, 491}, - dictWord{132, 11, 375}, - dictWord{4, 10, 518}, - dictWord{135, 10, 1136}, - dictWord{ - 4, - 0, - 913, - }, - dictWord{4, 11, 411}, - dictWord{11, 11, 643}, - dictWord{140, 11, 115}, - dictWord{4, 11, 80}, - dictWord{133, 11, 44}, - dictWord{8, 10, 689}, - dictWord{ - 137, - 10, - 863, - }, - dictWord{138, 0, 880}, - dictWord{4, 10, 18}, - dictWord{7, 10, 145}, - dictWord{7, 10, 444}, - dictWord{7, 10, 1278}, - dictWord{8, 10, 49}, - dictWord{ - 8, - 10, - 400, - }, - dictWord{9, 10, 71}, - dictWord{9, 10, 250}, - dictWord{10, 10, 459}, - dictWord{12, 10, 160}, - dictWord{144, 10, 24}, - dictWord{136, 0, 475}, - dictWord{ - 5, - 0, - 1016, - }, - dictWord{5, 11, 299}, - dictWord{135, 11, 1083}, - dictWord{7, 0, 602}, - dictWord{8, 0, 179}, - dictWord{10, 0, 781}, - dictWord{140, 0, 126}, - dictWord{ - 6, - 0, - 329, - }, - dictWord{138, 0, 111}, - dictWord{135, 0, 1864}, - dictWord{4, 11, 219}, - dictWord{7, 11, 1761}, - dictWord{137, 11, 86}, - dictWord{6, 0, 1888}, - dictWord{ - 6, - 0, - 1892, - }, - dictWord{6, 0, 1901}, - dictWord{6, 0, 1904}, - dictWord{9, 0, 953}, - dictWord{9, 0, 985}, - dictWord{9, 0, 991}, - dictWord{9, 0, 1001}, - dictWord{12, 0, 818}, - dictWord{12, 0, 846}, - dictWord{12, 0, 847}, - dictWord{12, 0, 861}, - dictWord{12, 0, 862}, - dictWord{12, 0, 873}, - dictWord{12, 0, 875}, - dictWord{12, 0, 877}, - dictWord{12, 0, 879}, - dictWord{12, 0, 881}, - dictWord{12, 0, 884}, - dictWord{12, 0, 903}, - dictWord{12, 0, 915}, - dictWord{12, 0, 926}, - dictWord{12, 0, 939}, - dictWord{ - 15, - 0, - 182, - }, - dictWord{15, 0, 219}, - dictWord{15, 0, 255}, - dictWord{18, 0, 191}, - dictWord{18, 0, 209}, - dictWord{18, 0, 211}, - dictWord{149, 0, 41}, - dictWord{ - 5, - 11, - 328, - }, - dictWord{135, 11, 918}, - dictWord{137, 0, 780}, - dictWord{12, 0, 82}, - dictWord{143, 0, 36}, - dictWord{133, 10, 1010}, - dictWord{5, 0, 821}, - dictWord{ - 134, - 0, - 1687, - }, - dictWord{133, 11, 514}, - dictWord{132, 0, 956}, - dictWord{134, 0, 1180}, - dictWord{10, 0, 112}, - dictWord{5, 10, 87}, - dictWord{7, 10, 313}, - dictWord{ - 7, - 10, - 1103, - }, - dictWord{10, 10, 582}, - dictWord{11, 10, 389}, - dictWord{11, 10, 813}, - dictWord{12, 10, 385}, - dictWord{13, 10, 286}, - dictWord{14, 10, 124}, - dictWord{146, 10, 108}, - dictWord{5, 0, 71}, - dictWord{7, 0, 1407}, - dictWord{9, 0, 704}, - dictWord{10, 0, 261}, - dictWord{10, 0, 619}, - dictWord{11, 0, 547}, - dictWord{11, 0, 619}, - dictWord{143, 0, 157}, - dictWord{4, 0, 531}, - dictWord{5, 0, 455}, - dictWord{5, 11, 301}, - dictWord{6, 11, 571}, - dictWord{14, 11, 49}, - dictWord{ - 146, - 11, - 102, - }, - dictWord{132, 10, 267}, - dictWord{6, 0, 385}, - dictWord{7, 0, 2008}, - dictWord{9, 0, 337}, - dictWord{138, 0, 517}, - dictWord{133, 11, 726}, - dictWord{133, 11, 364}, - dictWord{4, 11, 76}, - dictWord{7, 11, 1550}, - dictWord{9, 11, 306}, - dictWord{9, 11, 430}, - dictWord{9, 11, 663}, - dictWord{10, 11, 683}, - dictWord{11, 11, 427}, - dictWord{11, 11, 753}, - dictWord{12, 11, 334}, - dictWord{12, 11, 442}, - dictWord{14, 11, 258}, - dictWord{14, 11, 366}, - dictWord{ - 143, - 11, - 131, - }, - dictWord{6, 0, 1865}, - dictWord{6, 0, 1879}, - dictWord{6, 0, 1881}, - dictWord{6, 0, 1894}, - dictWord{6, 0, 1908}, - dictWord{9, 0, 915}, - dictWord{9, 0, 926}, - dictWord{9, 0, 940}, - dictWord{9, 0, 943}, - dictWord{9, 0, 966}, - dictWord{9, 0, 980}, - dictWord{9, 0, 989}, - dictWord{9, 0, 1005}, - dictWord{9, 0, 1010}, - dictWord{ - 12, - 0, - 813, - }, - dictWord{12, 0, 817}, - dictWord{12, 0, 840}, - dictWord{12, 0, 843}, - dictWord{12, 0, 855}, - dictWord{12, 0, 864}, - dictWord{12, 0, 871}, - dictWord{12, 0, 872}, - dictWord{12, 0, 899}, - dictWord{12, 0, 905}, - dictWord{12, 0, 924}, - dictWord{15, 0, 171}, - dictWord{15, 0, 181}, - dictWord{15, 0, 224}, - dictWord{15, 0, 235}, - dictWord{15, 0, 251}, - dictWord{146, 0, 184}, - dictWord{137, 11, 52}, - dictWord{5, 0, 16}, - dictWord{6, 0, 86}, - dictWord{6, 0, 603}, - dictWord{7, 0, 292}, - dictWord{7, 0, 561}, - dictWord{8, 0, 257}, - dictWord{8, 0, 382}, - dictWord{9, 0, 721}, - dictWord{9, 0, 778}, - dictWord{11, 0, 581}, - dictWord{140, 0, 466}, - dictWord{4, 0, 486}, - dictWord{ - 5, - 0, - 491, - }, - dictWord{135, 10, 1121}, - dictWord{4, 0, 72}, - dictWord{6, 0, 265}, - dictWord{135, 0, 1300}, - dictWord{135, 11, 1183}, - dictWord{10, 10, 249}, - dictWord{139, 10, 209}, - dictWord{132, 10, 561}, - dictWord{137, 11, 519}, - dictWord{4, 11, 656}, - dictWord{4, 10, 760}, - dictWord{135, 11, 779}, - dictWord{ - 9, - 10, - 154, - }, - dictWord{140, 10, 485}, - dictWord{135, 11, 1793}, - dictWord{135, 11, 144}, - dictWord{136, 10, 255}, - dictWord{133, 0, 621}, - dictWord{4, 10, 368}, - dictWord{135, 10, 641}, - dictWord{135, 11, 1373}, - dictWord{7, 11, 554}, - dictWord{7, 11, 605}, - dictWord{141, 11, 10}, - dictWord{137, 0, 234}, - dictWord{ - 5, - 0, - 815, - }, - dictWord{6, 0, 1688}, - dictWord{134, 0, 1755}, - dictWord{5, 11, 838}, - dictWord{5, 11, 841}, - dictWord{134, 11, 1649}, - dictWord{7, 0, 1987}, - dictWord{ - 7, - 0, - 2040, - }, - dictWord{136, 0, 743}, - dictWord{133, 11, 1012}, - dictWord{6, 0, 197}, - dictWord{136, 0, 205}, - dictWord{6, 0, 314}, - dictWord{134, 11, 314}, - dictWord{144, 11, 53}, - dictWord{6, 11, 251}, - dictWord{7, 11, 365}, - dictWord{7, 11, 1357}, - dictWord{7, 11, 1497}, - dictWord{8, 11, 154}, - dictWord{141, 11, 281}, - dictWord{133, 11, 340}, - dictWord{6, 0, 452}, - dictWord{7, 0, 312}, - dictWord{138, 0, 219}, - dictWord{138, 0, 589}, - dictWord{4, 0, 333}, - dictWord{9, 0, 176}, - dictWord{12, 0, 353}, - dictWord{141, 0, 187}, - dictWord{9, 10, 92}, - dictWord{147, 10, 91}, - dictWord{134, 0, 1110}, - dictWord{11, 0, 47}, - dictWord{139, 11, 495}, - dictWord{6, 10, 525}, - dictWord{8, 10, 806}, - dictWord{9, 10, 876}, - dictWord{140, 10, 284}, - dictWord{8, 11, 261}, - dictWord{9, 11, 144}, - dictWord{9, 11, 466}, - dictWord{10, 11, 370}, - dictWord{12, 11, 470}, - dictWord{13, 11, 144}, - dictWord{142, 11, 348}, - dictWord{137, 11, 897}, - dictWord{8, 0, 863}, - dictWord{8, 0, 864}, - dictWord{8, 0, 868}, - dictWord{8, 0, 884}, - dictWord{10, 0, 866}, - dictWord{10, 0, 868}, - dictWord{10, 0, 873}, - dictWord{10, 0, 911}, - dictWord{10, 0, 912}, - dictWord{ - 10, - 0, - 944, - }, - dictWord{12, 0, 727}, - dictWord{6, 11, 248}, - dictWord{9, 11, 546}, - dictWord{10, 11, 535}, - dictWord{11, 11, 681}, - dictWord{141, 11, 135}, - dictWord{ - 6, - 0, - 300, - }, - dictWord{135, 0, 1515}, - dictWord{134, 0, 1237}, - dictWord{139, 10, 958}, - dictWord{133, 10, 594}, - dictWord{140, 11, 250}, - dictWord{ - 134, - 0, - 1685, - }, - dictWord{134, 11, 567}, - dictWord{7, 0, 135}, - dictWord{8, 0, 7}, - dictWord{8, 0, 62}, - dictWord{9, 0, 243}, - dictWord{10, 0, 658}, - dictWord{10, 0, 697}, - dictWord{11, 0, 456}, - dictWord{139, 0, 756}, - dictWord{9, 0, 395}, - dictWord{138, 0, 79}, - dictWord{6, 10, 1641}, - dictWord{136, 10, 820}, - dictWord{4, 10, 302}, - dictWord{135, 10, 1766}, - dictWord{134, 11, 174}, - dictWord{135, 10, 1313}, - dictWord{135, 0, 631}, - dictWord{134, 10, 1674}, - dictWord{134, 11, 395}, - dictWord{138, 0, 835}, - dictWord{7, 0, 406}, - dictWord{7, 0, 459}, - dictWord{8, 0, 606}, - dictWord{139, 0, 726}, - dictWord{134, 11, 617}, - dictWord{134, 0, 979}, - dictWord{ - 6, - 10, - 389, - }, - dictWord{7, 10, 149}, - dictWord{9, 10, 142}, - dictWord{138, 10, 94}, - dictWord{5, 11, 878}, - dictWord{133, 11, 972}, - dictWord{6, 10, 8}, - dictWord{ - 7, - 10, - 1881, - }, - dictWord{8, 10, 91}, - dictWord{136, 11, 511}, - dictWord{133, 0, 612}, - dictWord{132, 11, 351}, - dictWord{4, 0, 372}, - dictWord{7, 0, 482}, - dictWord{ - 8, - 0, - 158, - }, - dictWord{9, 0, 602}, - dictWord{9, 0, 615}, - dictWord{10, 0, 245}, - dictWord{10, 0, 678}, - dictWord{10, 0, 744}, - dictWord{11, 0, 248}, - dictWord{ - 139, - 0, - 806, - }, - dictWord{5, 0, 854}, - dictWord{135, 0, 1991}, - dictWord{132, 11, 286}, - dictWord{135, 11, 344}, - dictWord{7, 11, 438}, - dictWord{7, 11, 627}, - dictWord{ - 7, - 11, - 1516, - }, - dictWord{8, 11, 40}, - dictWord{9, 11, 56}, - dictWord{9, 11, 294}, - dictWord{10, 11, 30}, - dictWord{10, 11, 259}, - dictWord{11, 11, 969}, - dictWord{ - 146, - 11, - 148, - }, - dictWord{135, 0, 1492}, - dictWord{5, 11, 259}, - dictWord{7, 11, 414}, - dictWord{7, 11, 854}, - dictWord{142, 11, 107}, - dictWord{135, 10, 1746}, - dictWord{6, 0, 833}, - dictWord{134, 0, 998}, - dictWord{135, 10, 24}, - dictWord{6, 0, 750}, - dictWord{135, 0, 1739}, - dictWord{4, 10, 503}, - dictWord{ - 135, - 10, - 1661, - }, - dictWord{5, 10, 130}, - dictWord{7, 10, 1314}, - dictWord{9, 10, 610}, - dictWord{10, 10, 718}, - dictWord{11, 10, 601}, - dictWord{11, 10, 819}, - dictWord{ - 11, - 10, - 946, - }, - dictWord{140, 10, 536}, - dictWord{10, 10, 149}, - dictWord{11, 10, 280}, - dictWord{142, 10, 336}, - dictWord{132, 11, 738}, - dictWord{ - 135, - 10, - 1946, - }, - dictWord{5, 0, 195}, - dictWord{135, 0, 1685}, - dictWord{7, 0, 1997}, - dictWord{8, 0, 730}, - dictWord{139, 0, 1006}, - dictWord{151, 11, 17}, - dictWord{ - 133, - 11, - 866, - }, - dictWord{14, 0, 463}, - dictWord{14, 0, 470}, - dictWord{150, 0, 61}, - dictWord{5, 0, 751}, - dictWord{8, 0, 266}, - dictWord{11, 0, 578}, - dictWord{ - 4, - 10, - 392, - }, - dictWord{135, 10, 1597}, - dictWord{5, 10, 433}, - dictWord{9, 10, 633}, - dictWord{139, 10, 629}, - dictWord{135, 0, 821}, - dictWord{6, 0, 715}, - dictWord{ - 134, - 0, - 1325, - }, - dictWord{133, 11, 116}, - dictWord{6, 0, 868}, - dictWord{132, 11, 457}, - dictWord{134, 0, 959}, - dictWord{6, 10, 234}, - dictWord{138, 11, 199}, - dictWord{7, 0, 1053}, - dictWord{7, 10, 1950}, - dictWord{8, 10, 680}, - dictWord{11, 10, 817}, - dictWord{147, 10, 88}, - dictWord{7, 10, 1222}, - dictWord{ - 138, - 10, - 386, - }, - dictWord{5, 0, 950}, - dictWord{5, 0, 994}, - dictWord{6, 0, 351}, - dictWord{134, 0, 1124}, - dictWord{134, 0, 1081}, - dictWord{7, 0, 1595}, - dictWord{6, 10, 5}, - dictWord{11, 10, 249}, - dictWord{12, 10, 313}, - dictWord{16, 10, 66}, - dictWord{145, 10, 26}, - dictWord{148, 0, 59}, - dictWord{5, 11, 527}, - dictWord{6, 11, 189}, - dictWord{135, 11, 859}, - dictWord{5, 10, 963}, - dictWord{6, 10, 1773}, - dictWord{11, 11, 104}, - dictWord{11, 11, 554}, - dictWord{15, 11, 60}, - dictWord{ - 143, - 11, - 125, - }, - dictWord{135, 0, 47}, - dictWord{137, 0, 684}, - dictWord{134, 11, 116}, - dictWord{134, 0, 1606}, - dictWord{134, 0, 777}, - dictWord{7, 0, 1020}, - dictWord{ - 8, - 10, - 509, - }, - dictWord{136, 10, 792}, - dictWord{135, 0, 1094}, - dictWord{132, 0, 350}, - dictWord{133, 11, 487}, - dictWord{4, 11, 86}, - dictWord{5, 11, 667}, - dictWord{5, 11, 753}, - dictWord{6, 11, 316}, - dictWord{6, 11, 455}, - dictWord{135, 11, 946}, - dictWord{7, 0, 1812}, - dictWord{13, 0, 259}, - dictWord{13, 0, 356}, - dictWord{14, 0, 242}, - dictWord{147, 0, 114}, - dictWord{132, 10, 931}, - dictWord{133, 0, 967}, - dictWord{4, 0, 473}, - dictWord{7, 0, 623}, - dictWord{8, 0, 808}, - dictWord{ - 9, - 0, - 871, - }, - dictWord{9, 0, 893}, - dictWord{11, 0, 38}, - dictWord{11, 0, 431}, - dictWord{12, 0, 112}, - dictWord{12, 0, 217}, - dictWord{12, 0, 243}, - dictWord{12, 0, 562}, - dictWord{12, 0, 663}, - dictWord{12, 0, 683}, - dictWord{13, 0, 141}, - dictWord{13, 0, 197}, - dictWord{13, 0, 227}, - dictWord{13, 0, 406}, - dictWord{13, 0, 487}, - dictWord{14, 0, 156}, - dictWord{14, 0, 203}, - dictWord{14, 0, 224}, - dictWord{14, 0, 256}, - dictWord{18, 0, 58}, - dictWord{150, 0, 0}, - dictWord{138, 0, 286}, - dictWord{ - 7, - 10, - 943, - }, - dictWord{139, 10, 614}, - dictWord{135, 10, 1837}, - dictWord{150, 11, 45}, - dictWord{132, 0, 798}, - dictWord{4, 0, 222}, - dictWord{7, 0, 286}, - dictWord{136, 0, 629}, - dictWord{4, 11, 79}, - dictWord{7, 11, 1773}, - dictWord{10, 11, 450}, - dictWord{11, 11, 589}, - dictWord{13, 11, 332}, - dictWord{13, 11, 493}, - dictWord{14, 11, 183}, - dictWord{14, 11, 334}, - dictWord{14, 11, 362}, - dictWord{14, 11, 368}, - dictWord{14, 11, 376}, - dictWord{14, 11, 379}, - dictWord{ - 19, - 11, - 90, - }, - dictWord{19, 11, 103}, - dictWord{19, 11, 127}, - dictWord{148, 11, 90}, - dictWord{5, 0, 337}, - dictWord{11, 0, 513}, - dictWord{11, 0, 889}, - dictWord{ - 11, - 0, - 961, - }, - dictWord{12, 0, 461}, - dictWord{13, 0, 79}, - dictWord{15, 0, 121}, - dictWord{4, 10, 90}, - dictWord{5, 10, 545}, - dictWord{7, 10, 754}, - dictWord{9, 10, 186}, - dictWord{10, 10, 72}, - dictWord{10, 10, 782}, - dictWord{11, 10, 577}, - dictWord{11, 10, 610}, - dictWord{12, 10, 354}, - dictWord{12, 10, 362}, - dictWord{ - 140, - 10, - 595, - }, - dictWord{141, 0, 306}, - dictWord{136, 0, 146}, - dictWord{7, 0, 1646}, - dictWord{9, 10, 329}, - dictWord{11, 10, 254}, - dictWord{141, 11, 124}, - dictWord{ - 4, - 0, - 465, - }, - dictWord{135, 0, 1663}, - dictWord{132, 0, 525}, - dictWord{133, 11, 663}, - dictWord{10, 0, 299}, - dictWord{18, 0, 74}, - dictWord{9, 10, 187}, - dictWord{ - 11, - 10, - 1016, - }, - dictWord{145, 10, 44}, - dictWord{7, 0, 165}, - dictWord{7, 0, 919}, - dictWord{4, 10, 506}, - dictWord{136, 10, 517}, - dictWord{5, 10, 295}, - dictWord{ - 135, - 10, - 1680, - }, - dictWord{133, 11, 846}, - dictWord{134, 0, 1064}, - dictWord{5, 11, 378}, - dictWord{7, 11, 1402}, - dictWord{7, 11, 1414}, - dictWord{8, 11, 465}, - dictWord{9, 11, 286}, - dictWord{10, 11, 185}, - dictWord{10, 11, 562}, - dictWord{10, 11, 635}, - dictWord{11, 11, 31}, - dictWord{11, 11, 393}, - dictWord{ - 12, - 11, - 456, - }, - dictWord{13, 11, 312}, - dictWord{18, 11, 65}, - dictWord{18, 11, 96}, - dictWord{147, 11, 89}, - dictWord{132, 0, 596}, - dictWord{7, 10, 987}, - dictWord{ - 9, - 10, - 688, - }, - dictWord{10, 10, 522}, - dictWord{11, 10, 788}, - dictWord{140, 10, 566}, - dictWord{6, 0, 82}, - dictWord{7, 0, 138}, - dictWord{7, 0, 517}, - dictWord{7, 0, 1741}, - dictWord{11, 0, 238}, - dictWord{4, 11, 648}, - dictWord{134, 10, 1775}, - dictWord{7, 0, 1233}, - dictWord{7, 10, 700}, - dictWord{7, 10, 940}, - dictWord{8, 10, 514}, - dictWord{9, 10, 116}, - dictWord{9, 10, 535}, - dictWord{10, 10, 118}, - dictWord{11, 10, 107}, - dictWord{11, 10, 148}, - dictWord{11, 10, 922}, - dictWord{ - 12, - 10, - 254, - }, - dictWord{12, 10, 421}, - dictWord{142, 10, 238}, - dictWord{4, 0, 962}, - dictWord{6, 0, 1824}, - dictWord{8, 0, 894}, - dictWord{12, 0, 708}, - dictWord{ - 12, - 0, - 725, - }, - dictWord{14, 0, 451}, - dictWord{20, 0, 94}, - dictWord{22, 0, 59}, - dictWord{150, 0, 62}, - dictWord{5, 11, 945}, - dictWord{6, 11, 1656}, - dictWord{6, 11, 1787}, - dictWord{7, 11, 167}, - dictWord{8, 11, 824}, - dictWord{9, 11, 391}, - dictWord{10, 11, 375}, - dictWord{139, 11, 185}, - dictWord{5, 0, 495}, - dictWord{7, 0, 834}, - dictWord{9, 0, 733}, - dictWord{139, 0, 378}, - dictWord{4, 10, 743}, - dictWord{135, 11, 1273}, - dictWord{6, 0, 1204}, - dictWord{7, 11, 1645}, - dictWord{8, 11, 352}, - dictWord{137, 11, 249}, - dictWord{139, 10, 292}, - dictWord{133, 0, 559}, - dictWord{132, 11, 152}, - dictWord{9, 0, 499}, - dictWord{10, 0, 341}, - dictWord{ - 15, - 0, - 144, - }, - dictWord{19, 0, 49}, - dictWord{7, 10, 1283}, - dictWord{9, 10, 227}, - dictWord{11, 10, 325}, - dictWord{11, 10, 408}, - dictWord{14, 10, 180}, - dictWord{ - 146, - 10, - 47, - }, - dictWord{6, 0, 21}, - dictWord{6, 0, 1737}, - dictWord{7, 0, 1444}, - dictWord{136, 0, 224}, - dictWord{133, 11, 1006}, - dictWord{7, 0, 1446}, - dictWord{ - 9, - 0, - 97, - }, - dictWord{17, 0, 15}, - dictWord{5, 10, 81}, - dictWord{7, 10, 146}, - dictWord{7, 10, 1342}, - dictWord{8, 10, 53}, - dictWord{8, 10, 561}, - dictWord{8, 10, 694}, - dictWord{8, 10, 754}, - dictWord{9, 10, 115}, - dictWord{9, 10, 894}, - dictWord{10, 10, 462}, - dictWord{10, 10, 813}, - dictWord{11, 10, 230}, - dictWord{11, 10, 657}, - dictWord{11, 10, 699}, - dictWord{11, 10, 748}, - dictWord{12, 10, 119}, - dictWord{12, 10, 200}, - dictWord{12, 10, 283}, - dictWord{142, 10, 273}, - dictWord{ - 5, - 10, - 408, - }, - dictWord{137, 10, 747}, - dictWord{135, 11, 431}, - dictWord{135, 11, 832}, - dictWord{6, 0, 729}, - dictWord{134, 0, 953}, - dictWord{4, 0, 727}, - dictWord{ - 8, - 0, - 565, - }, - dictWord{5, 11, 351}, - dictWord{7, 11, 264}, - dictWord{136, 11, 565}, - dictWord{134, 0, 1948}, - dictWord{5, 0, 519}, - dictWord{5, 11, 40}, - dictWord{ - 7, - 11, - 598, - }, - dictWord{7, 11, 1638}, - dictWord{8, 11, 78}, - dictWord{9, 11, 166}, - dictWord{9, 11, 640}, - dictWord{9, 11, 685}, - dictWord{9, 11, 773}, - dictWord{ - 11, - 11, - 215, - }, - dictWord{13, 11, 65}, - dictWord{14, 11, 172}, - dictWord{14, 11, 317}, - dictWord{145, 11, 6}, - dictWord{8, 11, 60}, - dictWord{9, 11, 343}, - dictWord{ - 139, - 11, - 769, - }, - dictWord{137, 11, 455}, - dictWord{134, 0, 1193}, - dictWord{140, 0, 790}, - dictWord{7, 11, 1951}, - dictWord{8, 11, 765}, - dictWord{8, 11, 772}, - dictWord{140, 11, 671}, - dictWord{7, 11, 108}, - dictWord{8, 11, 219}, - dictWord{8, 11, 388}, - dictWord{9, 11, 639}, - dictWord{9, 11, 775}, - dictWord{11, 11, 275}, - dictWord{140, 11, 464}, - dictWord{132, 11, 468}, - dictWord{7, 10, 30}, - dictWord{8, 10, 86}, - dictWord{8, 10, 315}, - dictWord{8, 10, 700}, - dictWord{9, 10, 576}, - dictWord{ - 9, - 10, - 858, - }, - dictWord{11, 10, 310}, - dictWord{11, 10, 888}, - dictWord{11, 10, 904}, - dictWord{12, 10, 361}, - dictWord{141, 10, 248}, - dictWord{5, 11, 15}, - dictWord{6, 11, 56}, - dictWord{7, 11, 1758}, - dictWord{8, 11, 500}, - dictWord{9, 11, 730}, - dictWord{11, 11, 331}, - dictWord{13, 11, 150}, - dictWord{142, 11, 282}, - dictWord{4, 0, 402}, - dictWord{7, 0, 2}, - dictWord{8, 0, 323}, - dictWord{136, 0, 479}, - dictWord{138, 10, 839}, - dictWord{11, 0, 580}, - dictWord{142, 0, 201}, - dictWord{ - 5, - 0, - 59, - }, - dictWord{135, 0, 672}, - dictWord{137, 10, 617}, - dictWord{146, 0, 34}, - dictWord{134, 11, 1886}, - dictWord{4, 0, 961}, - dictWord{136, 0, 896}, - dictWord{ - 6, - 0, - 1285, - }, - dictWord{5, 11, 205}, - dictWord{6, 11, 438}, - dictWord{137, 11, 711}, - dictWord{134, 10, 428}, - dictWord{7, 10, 524}, - dictWord{8, 10, 169}, - dictWord{8, 10, 234}, - dictWord{9, 10, 480}, - dictWord{138, 10, 646}, - dictWord{148, 0, 46}, - dictWord{141, 0, 479}, - dictWord{133, 11, 534}, - dictWord{6, 0, 2019}, - dictWord{134, 10, 1648}, - dictWord{4, 0, 85}, - dictWord{7, 0, 549}, - dictWord{7, 10, 1205}, - dictWord{138, 10, 637}, - dictWord{4, 0, 663}, - dictWord{5, 0, 94}, - dictWord{ - 7, - 11, - 235, - }, - dictWord{7, 11, 1475}, - dictWord{15, 11, 68}, - dictWord{146, 11, 120}, - dictWord{6, 11, 443}, - dictWord{9, 11, 237}, - dictWord{9, 11, 571}, - dictWord{ - 9, - 11, - 695, - }, - dictWord{10, 11, 139}, - dictWord{11, 11, 715}, - dictWord{12, 11, 417}, - dictWord{141, 11, 421}, - dictWord{132, 0, 783}, - dictWord{4, 0, 682}, - dictWord{8, 0, 65}, - dictWord{9, 10, 39}, - dictWord{10, 10, 166}, - dictWord{11, 10, 918}, - dictWord{12, 10, 635}, - dictWord{20, 10, 10}, - dictWord{22, 10, 27}, - dictWord{ - 22, - 10, - 43, - }, - dictWord{150, 10, 52}, - dictWord{6, 0, 11}, - dictWord{135, 0, 187}, - dictWord{132, 0, 522}, - dictWord{4, 0, 52}, - dictWord{135, 0, 661}, - dictWord{ - 4, - 0, - 383, - }, - dictWord{133, 0, 520}, - dictWord{135, 11, 546}, - dictWord{11, 0, 343}, - dictWord{142, 0, 127}, - dictWord{4, 11, 578}, - dictWord{7, 10, 157}, - dictWord{ - 7, - 11, - 624, - }, - dictWord{7, 11, 916}, - dictWord{8, 10, 279}, - dictWord{10, 11, 256}, - dictWord{11, 11, 87}, - dictWord{139, 11, 703}, - dictWord{134, 10, 604}, - dictWord{ - 4, - 0, - 281, - }, - dictWord{5, 0, 38}, - dictWord{7, 0, 194}, - dictWord{7, 0, 668}, - dictWord{7, 0, 1893}, - dictWord{137, 0, 397}, - dictWord{7, 10, 945}, - dictWord{11, 10, 713}, - dictWord{139, 10, 744}, - dictWord{139, 10, 1022}, - dictWord{9, 0, 635}, - dictWord{139, 0, 559}, - dictWord{5, 11, 923}, - dictWord{7, 11, 490}, - dictWord{ - 12, - 11, - 553, - }, - dictWord{13, 11, 100}, - dictWord{14, 11, 118}, - dictWord{143, 11, 75}, - dictWord{132, 0, 975}, - dictWord{132, 10, 567}, - dictWord{137, 10, 859}, - dictWord{7, 10, 1846}, - dictWord{7, 11, 1846}, - dictWord{8, 10, 628}, - dictWord{136, 11, 628}, - dictWord{148, 0, 116}, - dictWord{138, 11, 750}, - dictWord{14, 0, 51}, - dictWord{14, 11, 51}, - dictWord{15, 11, 7}, - dictWord{148, 11, 20}, - dictWord{132, 0, 858}, - dictWord{134, 0, 1075}, - dictWord{4, 11, 924}, - dictWord{ - 133, - 10, - 762, - }, - dictWord{136, 0, 535}, - dictWord{133, 0, 448}, - dictWord{10, 10, 784}, - dictWord{141, 10, 191}, - dictWord{133, 10, 298}, - dictWord{7, 0, 610}, - dictWord{135, 0, 1501}, - dictWord{7, 10, 633}, - dictWord{7, 10, 905}, - dictWord{7, 10, 909}, - dictWord{7, 10, 1538}, - dictWord{9, 10, 767}, - dictWord{140, 10, 636}, - dictWord{4, 11, 265}, - dictWord{7, 11, 807}, - dictWord{135, 11, 950}, - dictWord{5, 11, 93}, - dictWord{12, 11, 267}, - dictWord{144, 11, 26}, - dictWord{136, 0, 191}, - dictWord{139, 10, 301}, - dictWord{135, 10, 1970}, - dictWord{135, 0, 267}, - dictWord{4, 0, 319}, - dictWord{5, 0, 699}, - dictWord{138, 0, 673}, - dictWord{ - 6, - 0, - 336, - }, - dictWord{7, 0, 92}, - dictWord{7, 0, 182}, - dictWord{8, 0, 453}, - dictWord{8, 0, 552}, - dictWord{9, 0, 204}, - dictWord{9, 0, 285}, - dictWord{10, 0, 99}, - dictWord{ - 11, - 0, - 568, - }, - dictWord{11, 0, 950}, - dictWord{12, 0, 94}, - dictWord{16, 0, 20}, - dictWord{16, 0, 70}, - dictWord{19, 0, 55}, - dictWord{12, 10, 644}, - dictWord{144, 10, 90}, - dictWord{6, 0, 551}, - dictWord{7, 0, 1308}, - dictWord{7, 10, 845}, - dictWord{7, 11, 994}, - dictWord{8, 10, 160}, - dictWord{137, 10, 318}, - dictWord{19, 11, 1}, - dictWord{ - 19, - 11, - 26, - }, - dictWord{150, 11, 9}, - dictWord{7, 0, 1406}, - dictWord{9, 0, 218}, - dictWord{141, 0, 222}, - dictWord{5, 0, 256}, - dictWord{138, 0, 69}, - dictWord{ - 5, - 11, - 233, - }, - dictWord{5, 11, 320}, - dictWord{6, 11, 140}, - dictWord{7, 11, 330}, - dictWord{136, 11, 295}, - dictWord{6, 0, 1980}, - dictWord{136, 0, 952}, - dictWord{ - 4, - 0, - 833, - }, - dictWord{137, 11, 678}, - dictWord{133, 11, 978}, - dictWord{4, 11, 905}, - dictWord{6, 11, 1701}, - dictWord{137, 11, 843}, - dictWord{138, 10, 735}, - dictWord{136, 10, 76}, - dictWord{17, 0, 39}, - dictWord{148, 0, 36}, - dictWord{18, 0, 81}, - dictWord{146, 11, 81}, - dictWord{14, 0, 352}, - dictWord{17, 0, 53}, - dictWord{ - 18, - 0, - 146, - }, - dictWord{18, 0, 152}, - dictWord{19, 0, 11}, - dictWord{150, 0, 54}, - dictWord{135, 0, 634}, - dictWord{138, 10, 841}, - dictWord{132, 0, 618}, - dictWord{ - 4, - 0, - 339, - }, - dictWord{7, 0, 259}, - dictWord{17, 0, 73}, - dictWord{4, 11, 275}, - dictWord{140, 11, 376}, - dictWord{132, 11, 509}, - dictWord{7, 11, 273}, - dictWord{ - 139, - 11, - 377, - }, - dictWord{4, 0, 759}, - dictWord{13, 0, 169}, - dictWord{137, 10, 804}, - dictWord{6, 10, 96}, - dictWord{135, 10, 1426}, - dictWord{4, 10, 651}, - dictWord{133, 10, 289}, - dictWord{7, 0, 1075}, - dictWord{8, 10, 35}, - dictWord{9, 10, 511}, - dictWord{10, 10, 767}, - dictWord{147, 10, 118}, - dictWord{6, 0, 649}, - dictWord{6, 0, 670}, - dictWord{136, 0, 482}, - dictWord{5, 0, 336}, - dictWord{6, 0, 341}, - dictWord{6, 0, 478}, - dictWord{6, 0, 1763}, - dictWord{136, 0, 386}, - dictWord{ - 5, - 11, - 802, - }, - dictWord{7, 11, 2021}, - dictWord{8, 11, 805}, - dictWord{14, 11, 94}, - dictWord{15, 11, 65}, - dictWord{16, 11, 4}, - dictWord{16, 11, 77}, - dictWord{16, 11, 80}, - dictWord{145, 11, 5}, - dictWord{6, 0, 1035}, - dictWord{5, 11, 167}, - dictWord{5, 11, 899}, - dictWord{6, 11, 410}, - dictWord{137, 11, 777}, - dictWord{ - 134, - 11, - 1705, - }, - dictWord{5, 0, 924}, - dictWord{133, 0, 969}, - dictWord{132, 10, 704}, - dictWord{135, 0, 73}, - dictWord{135, 11, 10}, - dictWord{135, 10, 1078}, - dictWord{ - 5, - 11, - 11, - }, - dictWord{6, 11, 117}, - dictWord{6, 11, 485}, - dictWord{7, 11, 1133}, - dictWord{9, 11, 582}, - dictWord{9, 11, 594}, - dictWord{11, 11, 21}, - dictWord{ - 11, - 11, - 818, - }, - dictWord{12, 11, 535}, - dictWord{141, 11, 86}, - dictWord{135, 0, 1971}, - dictWord{4, 11, 264}, - dictWord{7, 11, 1067}, - dictWord{8, 11, 204}, - dictWord{8, 11, 385}, - dictWord{139, 11, 953}, - dictWord{6, 0, 1458}, - dictWord{135, 0, 1344}, - dictWord{5, 0, 396}, - dictWord{134, 0, 501}, - dictWord{4, 10, 720}, - dictWord{133, 10, 306}, - dictWord{4, 0, 929}, - dictWord{5, 0, 799}, - dictWord{8, 0, 46}, - dictWord{8, 0, 740}, - dictWord{133, 10, 431}, - dictWord{7, 11, 646}, - dictWord{ - 7, - 11, - 1730, - }, - dictWord{11, 11, 446}, - dictWord{141, 11, 178}, - dictWord{7, 0, 276}, - dictWord{5, 10, 464}, - dictWord{6, 10, 236}, - dictWord{7, 10, 696}, - dictWord{ - 7, - 10, - 914, - }, - dictWord{7, 10, 1108}, - dictWord{7, 10, 1448}, - dictWord{9, 10, 15}, - dictWord{9, 10, 564}, - dictWord{10, 10, 14}, - dictWord{12, 10, 565}, - dictWord{ - 13, - 10, - 449, - }, - dictWord{14, 10, 53}, - dictWord{15, 10, 13}, - dictWord{16, 10, 64}, - dictWord{145, 10, 41}, - dictWord{4, 0, 892}, - dictWord{133, 0, 770}, - dictWord{ - 6, - 10, - 1767, - }, - dictWord{12, 10, 194}, - dictWord{145, 10, 107}, - dictWord{135, 0, 158}, - dictWord{5, 10, 840}, - dictWord{138, 11, 608}, - dictWord{134, 0, 1432}, - dictWord{138, 11, 250}, - dictWord{8, 11, 794}, - dictWord{9, 11, 400}, - dictWord{10, 11, 298}, - dictWord{142, 11, 228}, - dictWord{151, 0, 25}, - dictWord{ - 7, - 11, - 1131, - }, - dictWord{135, 11, 1468}, - dictWord{135, 0, 2001}, - dictWord{9, 10, 642}, - dictWord{11, 10, 236}, - dictWord{142, 10, 193}, - dictWord{4, 10, 68}, - dictWord{5, 10, 634}, - dictWord{6, 10, 386}, - dictWord{7, 10, 794}, - dictWord{8, 10, 273}, - dictWord{9, 10, 563}, - dictWord{10, 10, 105}, - dictWord{10, 10, 171}, - dictWord{11, 10, 94}, - dictWord{139, 10, 354}, - dictWord{136, 11, 724}, - dictWord{132, 0, 478}, - dictWord{11, 11, 512}, - dictWord{13, 11, 205}, - dictWord{ - 19, - 11, - 30, - }, - dictWord{22, 11, 36}, - dictWord{151, 11, 19}, - dictWord{7, 0, 1461}, - dictWord{140, 0, 91}, - dictWord{6, 11, 190}, - dictWord{7, 11, 768}, - dictWord{ - 135, - 11, - 1170, - }, - dictWord{4, 0, 602}, - dictWord{8, 0, 211}, - dictWord{4, 10, 95}, - dictWord{7, 10, 416}, - dictWord{139, 10, 830}, - dictWord{7, 10, 731}, - dictWord{13, 10, 20}, - dictWord{143, 10, 11}, - dictWord{6, 0, 1068}, - dictWord{135, 0, 1872}, - dictWord{4, 0, 13}, - dictWord{5, 0, 567}, - dictWord{7, 0, 1498}, - dictWord{9, 0, 124}, - dictWord{11, 0, 521}, - dictWord{12, 0, 405}, - dictWord{135, 11, 1023}, - dictWord{135, 0, 1006}, - dictWord{132, 0, 735}, - dictWord{138, 0, 812}, - dictWord{4, 0, 170}, - dictWord{135, 0, 323}, - dictWord{6, 11, 137}, - dictWord{9, 11, 75}, - dictWord{9, 11, 253}, - dictWord{10, 11, 194}, - dictWord{138, 11, 444}, - dictWord{5, 0, 304}, - dictWord{7, 0, 1403}, - dictWord{5, 10, 864}, - dictWord{10, 10, 648}, - dictWord{11, 10, 671}, - dictWord{143, 10, 46}, - dictWord{135, 11, 1180}, - dictWord{ - 133, - 10, - 928, - }, - dictWord{4, 0, 148}, - dictWord{133, 0, 742}, - dictWord{11, 10, 986}, - dictWord{140, 10, 682}, - dictWord{133, 0, 523}, - dictWord{135, 11, 1743}, - dictWord{7, 0, 730}, - dictWord{18, 0, 144}, - dictWord{19, 0, 61}, - dictWord{8, 10, 44}, - dictWord{9, 10, 884}, - dictWord{10, 10, 580}, - dictWord{11, 10, 399}, - dictWord{ - 11, - 10, - 894, - }, - dictWord{143, 10, 122}, - dictWord{5, 11, 760}, - dictWord{7, 11, 542}, - dictWord{8, 11, 135}, - dictWord{136, 11, 496}, - dictWord{136, 0, 981}, - dictWord{133, 0, 111}, - dictWord{10, 0, 132}, - dictWord{11, 0, 191}, - dictWord{11, 0, 358}, - dictWord{139, 0, 460}, - dictWord{7, 11, 319}, - dictWord{7, 11, 355}, - dictWord{ - 7, - 11, - 763, - }, - dictWord{10, 11, 389}, - dictWord{145, 11, 43}, - dictWord{134, 0, 890}, - dictWord{134, 0, 1420}, - dictWord{136, 11, 557}, - dictWord{ - 133, - 10, - 518, - }, - dictWord{133, 0, 444}, - dictWord{135, 0, 1787}, - dictWord{135, 10, 1852}, - dictWord{8, 0, 123}, - dictWord{15, 0, 6}, - dictWord{144, 0, 7}, - dictWord{ - 6, - 0, - 2041, - }, - dictWord{10, 11, 38}, - dictWord{139, 11, 784}, - dictWord{136, 0, 932}, - dictWord{5, 0, 937}, - dictWord{135, 0, 100}, - dictWord{6, 0, 995}, - dictWord{ - 4, - 11, - 58, - }, - dictWord{5, 11, 286}, - dictWord{6, 11, 319}, - dictWord{7, 11, 402}, - dictWord{7, 11, 1254}, - dictWord{7, 11, 1903}, - dictWord{8, 11, 356}, - dictWord{ - 140, - 11, - 408, - }, - dictWord{4, 11, 389}, - dictWord{9, 11, 181}, - dictWord{9, 11, 255}, - dictWord{10, 11, 8}, - dictWord{10, 11, 29}, - dictWord{10, 11, 816}, - dictWord{ - 11, - 11, - 311, - }, - dictWord{11, 11, 561}, - dictWord{12, 11, 67}, - dictWord{141, 11, 181}, - dictWord{138, 0, 255}, - dictWord{5, 0, 138}, - dictWord{4, 10, 934}, - dictWord{ - 136, - 10, - 610, - }, - dictWord{4, 0, 965}, - dictWord{10, 0, 863}, - dictWord{138, 0, 898}, - dictWord{10, 10, 804}, - dictWord{138, 10, 832}, - dictWord{12, 0, 631}, - dictWord{ - 8, - 10, - 96, - }, - dictWord{9, 10, 36}, - dictWord{10, 10, 607}, - dictWord{11, 10, 423}, - dictWord{11, 10, 442}, - dictWord{12, 10, 309}, - dictWord{14, 10, 199}, - dictWord{ - 15, - 10, - 90, - }, - dictWord{145, 10, 110}, - dictWord{134, 0, 1394}, - dictWord{4, 0, 652}, - dictWord{8, 0, 320}, - dictWord{22, 0, 6}, - dictWord{22, 0, 16}, - dictWord{ - 9, - 10, - 13, - }, - dictWord{9, 10, 398}, - dictWord{9, 10, 727}, - dictWord{10, 10, 75}, - dictWord{10, 10, 184}, - dictWord{10, 10, 230}, - dictWord{10, 10, 564}, - dictWord{ - 10, - 10, - 569, - }, - dictWord{11, 10, 973}, - dictWord{12, 10, 70}, - dictWord{12, 10, 189}, - dictWord{13, 10, 57}, - dictWord{141, 10, 257}, - dictWord{6, 0, 897}, - dictWord{ - 134, - 0, - 1333, - }, - dictWord{4, 0, 692}, - dictWord{133, 0, 321}, - dictWord{133, 11, 373}, - dictWord{135, 0, 922}, - dictWord{5, 0, 619}, - dictWord{133, 0, 698}, - dictWord{ - 137, - 10, - 631, - }, - dictWord{5, 10, 345}, - dictWord{135, 10, 1016}, - dictWord{9, 0, 957}, - dictWord{9, 0, 1018}, - dictWord{12, 0, 828}, - dictWord{12, 0, 844}, - dictWord{ - 12, - 0, - 897, - }, - dictWord{12, 0, 901}, - dictWord{12, 0, 943}, - dictWord{15, 0, 180}, - dictWord{18, 0, 197}, - dictWord{18, 0, 200}, - dictWord{18, 0, 213}, - dictWord{ - 18, - 0, - 214, - }, - dictWord{146, 0, 226}, - dictWord{5, 0, 917}, - dictWord{134, 0, 1659}, - dictWord{135, 0, 1100}, - dictWord{134, 0, 1173}, - dictWord{134, 0, 1930}, - dictWord{5, 0, 251}, - dictWord{5, 0, 956}, - dictWord{8, 0, 268}, - dictWord{9, 0, 214}, - dictWord{146, 0, 142}, - dictWord{133, 10, 673}, - dictWord{137, 10, 850}, - dictWord{ - 4, - 10, - 287, - }, - dictWord{133, 10, 1018}, - dictWord{132, 11, 672}, - dictWord{5, 0, 346}, - dictWord{5, 0, 711}, - dictWord{8, 0, 390}, - dictWord{11, 11, 752}, - dictWord{139, 11, 885}, - dictWord{5, 10, 34}, - dictWord{10, 10, 724}, - dictWord{12, 10, 444}, - dictWord{13, 10, 354}, - dictWord{18, 10, 32}, - dictWord{23, 10, 24}, - dictWord{23, 10, 31}, - dictWord{152, 10, 5}, - dictWord{4, 11, 710}, - dictWord{134, 11, 606}, - dictWord{134, 0, 744}, - dictWord{134, 10, 382}, - dictWord{ - 133, - 11, - 145, - }, - dictWord{4, 10, 329}, - dictWord{7, 11, 884}, - dictWord{140, 11, 124}, - dictWord{4, 11, 467}, - dictWord{5, 11, 405}, - dictWord{134, 11, 544}, - dictWord{ - 9, - 10, - 846, - }, - dictWord{138, 10, 827}, - dictWord{133, 0, 624}, - dictWord{9, 11, 372}, - dictWord{15, 11, 2}, - dictWord{19, 11, 10}, - dictWord{147, 11, 18}, - dictWord{ - 4, - 11, - 387, - }, - dictWord{135, 11, 1288}, - dictWord{5, 0, 783}, - dictWord{7, 0, 1998}, - dictWord{135, 0, 2047}, - dictWord{132, 10, 906}, - dictWord{136, 10, 366}, - dictWord{135, 11, 550}, - dictWord{4, 10, 123}, - dictWord{4, 10, 649}, - dictWord{5, 10, 605}, - dictWord{7, 10, 1509}, - dictWord{136, 10, 36}, - dictWord{ - 134, - 0, - 1125, - }, - dictWord{132, 0, 594}, - dictWord{133, 10, 767}, - dictWord{135, 11, 1227}, - dictWord{136, 11, 467}, - dictWord{4, 11, 576}, - dictWord{ - 135, - 11, - 1263, - }, - dictWord{4, 0, 268}, - dictWord{7, 0, 1534}, - dictWord{135, 11, 1534}, - dictWord{4, 10, 273}, - dictWord{5, 10, 658}, - dictWord{5, 11, 919}, - dictWord{ - 5, - 10, - 995, - }, - dictWord{134, 11, 1673}, - dictWord{133, 0, 563}, - dictWord{134, 10, 72}, - dictWord{135, 10, 1345}, - dictWord{4, 11, 82}, - dictWord{5, 11, 333}, - dictWord{ - 5, - 11, - 904, - }, - dictWord{6, 11, 207}, - dictWord{7, 11, 325}, - dictWord{7, 11, 1726}, - dictWord{8, 11, 101}, - dictWord{10, 11, 778}, - dictWord{139, 11, 220}, - dictWord{5, 0, 37}, - dictWord{6, 0, 39}, - dictWord{6, 0, 451}, - dictWord{7, 0, 218}, - dictWord{7, 0, 667}, - dictWord{7, 0, 1166}, - dictWord{7, 0, 1687}, - dictWord{8, 0, 662}, - dictWord{16, 0, 2}, - dictWord{133, 10, 589}, - dictWord{134, 0, 1332}, - dictWord{133, 11, 903}, - dictWord{134, 0, 508}, - dictWord{5, 10, 117}, - dictWord{6, 10, 514}, - dictWord{6, 10, 541}, - dictWord{7, 10, 1164}, - dictWord{7, 10, 1436}, - dictWord{8, 10, 220}, - dictWord{8, 10, 648}, - dictWord{10, 10, 688}, - dictWord{11, 10, 560}, - dictWord{140, 11, 147}, - dictWord{6, 11, 555}, - dictWord{135, 11, 485}, - dictWord{133, 10, 686}, - dictWord{7, 0, 453}, - dictWord{7, 0, 635}, - dictWord{7, 0, 796}, - dictWord{8, 0, 331}, - dictWord{9, 0, 330}, - dictWord{9, 0, 865}, - dictWord{10, 0, 119}, - dictWord{10, 0, 235}, - dictWord{11, 0, 111}, - dictWord{11, 0, 129}, - dictWord{ - 11, - 0, - 240, - }, - dictWord{12, 0, 31}, - dictWord{12, 0, 66}, - dictWord{12, 0, 222}, - dictWord{12, 0, 269}, - dictWord{12, 0, 599}, - dictWord{12, 0, 684}, - dictWord{12, 0, 689}, - dictWord{12, 0, 691}, - dictWord{142, 0, 345}, - dictWord{135, 0, 1834}, - dictWord{4, 11, 705}, - dictWord{7, 11, 615}, - dictWord{138, 11, 251}, - dictWord{ - 136, - 11, - 345, - }, - dictWord{137, 0, 527}, - dictWord{6, 0, 98}, - dictWord{7, 0, 702}, - dictWord{135, 0, 991}, - dictWord{11, 0, 576}, - dictWord{14, 0, 74}, - dictWord{7, 10, 196}, - dictWord{10, 10, 765}, - dictWord{11, 10, 347}, - dictWord{11, 10, 552}, - dictWord{11, 10, 790}, - dictWord{12, 10, 263}, - dictWord{13, 10, 246}, - dictWord{ - 13, - 10, - 270, - }, - dictWord{13, 10, 395}, - dictWord{14, 10, 176}, - dictWord{14, 10, 190}, - dictWord{14, 10, 398}, - dictWord{14, 10, 412}, - dictWord{15, 10, 32}, - dictWord{ - 15, - 10, - 63, - }, - dictWord{16, 10, 88}, - dictWord{147, 10, 105}, - dictWord{134, 11, 90}, - dictWord{13, 0, 84}, - dictWord{141, 0, 122}, - dictWord{6, 0, 37}, - dictWord{ - 7, - 0, - 299, - }, - dictWord{7, 0, 1666}, - dictWord{8, 0, 195}, - dictWord{8, 0, 316}, - dictWord{9, 0, 178}, - dictWord{9, 0, 276}, - dictWord{9, 0, 339}, - dictWord{9, 0, 536}, - dictWord{ - 10, - 0, - 102, - }, - dictWord{10, 0, 362}, - dictWord{10, 0, 785}, - dictWord{11, 0, 55}, - dictWord{11, 0, 149}, - dictWord{11, 0, 773}, - dictWord{13, 0, 416}, - dictWord{ - 13, - 0, - 419, - }, - dictWord{14, 0, 38}, - dictWord{14, 0, 41}, - dictWord{142, 0, 210}, - dictWord{5, 10, 381}, - dictWord{135, 10, 1792}, - dictWord{7, 11, 813}, - dictWord{ - 12, - 11, - 497, - }, - dictWord{141, 11, 56}, - dictWord{7, 10, 616}, - dictWord{138, 10, 413}, - dictWord{133, 0, 645}, - dictWord{6, 11, 125}, - dictWord{135, 11, 1277}, - dictWord{132, 0, 290}, - dictWord{6, 0, 70}, - dictWord{7, 0, 1292}, - dictWord{10, 0, 762}, - dictWord{139, 0, 288}, - dictWord{6, 10, 120}, - dictWord{7, 10, 1188}, - dictWord{ - 7, - 10, - 1710, - }, - dictWord{8, 10, 286}, - dictWord{9, 10, 667}, - dictWord{11, 10, 592}, - dictWord{139, 10, 730}, - dictWord{135, 11, 1784}, - dictWord{7, 0, 1315}, - dictWord{135, 11, 1315}, - dictWord{134, 0, 1955}, - dictWord{135, 10, 1146}, - dictWord{7, 0, 131}, - dictWord{7, 0, 422}, - dictWord{8, 0, 210}, - dictWord{ - 140, - 0, - 573, - }, - dictWord{4, 10, 352}, - dictWord{135, 10, 687}, - dictWord{139, 0, 797}, - dictWord{143, 0, 38}, - dictWord{14, 0, 179}, - dictWord{15, 0, 151}, - dictWord{ - 150, - 0, - 11, - }, - dictWord{7, 0, 488}, - dictWord{4, 10, 192}, - dictWord{5, 10, 49}, - dictWord{6, 10, 200}, - dictWord{6, 10, 293}, - dictWord{134, 10, 1696}, - dictWord{ - 132, - 0, - 936, - }, - dictWord{135, 11, 703}, - dictWord{6, 11, 160}, - dictWord{7, 11, 1106}, - dictWord{9, 11, 770}, - dictWord{10, 11, 618}, - dictWord{11, 11, 112}, - dictWord{ - 140, - 11, - 413, - }, - dictWord{5, 0, 453}, - dictWord{134, 0, 441}, - dictWord{135, 0, 595}, - dictWord{132, 10, 650}, - dictWord{132, 10, 147}, - dictWord{6, 0, 991}, - dictWord{6, 0, 1182}, - dictWord{12, 11, 271}, - dictWord{145, 11, 109}, - dictWord{133, 10, 934}, - dictWord{140, 11, 221}, - dictWord{132, 0, 653}, - dictWord{ - 7, - 0, - 505, - }, - dictWord{135, 0, 523}, - dictWord{134, 0, 903}, - dictWord{135, 11, 479}, - dictWord{7, 11, 304}, - dictWord{9, 11, 646}, - dictWord{9, 11, 862}, - dictWord{ - 10, - 11, - 262, - }, - dictWord{11, 11, 696}, - dictWord{12, 11, 208}, - dictWord{15, 11, 79}, - dictWord{147, 11, 108}, - dictWord{146, 0, 80}, - dictWord{135, 11, 981}, - dictWord{142, 0, 432}, - dictWord{132, 0, 314}, - dictWord{137, 11, 152}, - dictWord{7, 0, 1368}, - dictWord{8, 0, 232}, - dictWord{8, 0, 361}, - dictWord{10, 0, 682}, - dictWord{138, 0, 742}, - dictWord{135, 11, 1586}, - dictWord{9, 0, 534}, - dictWord{4, 11, 434}, - dictWord{11, 11, 663}, - dictWord{12, 11, 210}, - dictWord{13, 11, 166}, - dictWord{13, 11, 310}, - dictWord{14, 11, 373}, - dictWord{147, 11, 43}, - dictWord{7, 11, 1091}, - dictWord{135, 11, 1765}, - dictWord{6, 11, 550}, - dictWord{ - 135, - 11, - 652, - }, - dictWord{137, 0, 27}, - dictWord{142, 0, 12}, - dictWord{4, 10, 637}, - dictWord{5, 11, 553}, - dictWord{7, 11, 766}, - dictWord{138, 11, 824}, - dictWord{ - 7, - 11, - 737, - }, - dictWord{8, 11, 298}, - dictWord{136, 11, 452}, - dictWord{7, 0, 736}, - dictWord{139, 0, 264}, - dictWord{134, 0, 1657}, - dictWord{133, 11, 292}, - dictWord{138, 11, 135}, - dictWord{6, 0, 844}, - dictWord{134, 0, 1117}, - dictWord{135, 0, 127}, - dictWord{9, 10, 867}, - dictWord{138, 10, 837}, - dictWord{ - 6, - 0, - 1184, - }, - dictWord{134, 0, 1208}, - dictWord{134, 0, 1294}, - dictWord{136, 0, 364}, - dictWord{6, 0, 1415}, - dictWord{7, 0, 1334}, - dictWord{11, 0, 125}, - dictWord{ - 6, - 10, - 170, - }, - dictWord{7, 11, 393}, - dictWord{8, 10, 395}, - dictWord{8, 10, 487}, - dictWord{10, 11, 603}, - dictWord{11, 11, 206}, - dictWord{141, 10, 147}, - dictWord{137, 11, 748}, - dictWord{4, 11, 912}, - dictWord{137, 11, 232}, - dictWord{4, 10, 535}, - dictWord{136, 10, 618}, - dictWord{137, 0, 792}, - dictWord{ - 7, - 11, - 1973, - }, - dictWord{136, 11, 716}, - dictWord{135, 11, 98}, - dictWord{5, 0, 909}, - dictWord{9, 0, 849}, - dictWord{138, 0, 805}, - dictWord{4, 0, 630}, - dictWord{ - 132, - 0, - 699, - }, - dictWord{5, 11, 733}, - dictWord{14, 11, 103}, - dictWord{150, 10, 23}, - dictWord{12, 11, 158}, - dictWord{18, 11, 8}, - dictWord{19, 11, 62}, - dictWord{ - 20, - 11, - 6, - }, - dictWord{22, 11, 4}, - dictWord{23, 11, 2}, - dictWord{151, 11, 9}, - dictWord{132, 0, 968}, - dictWord{132, 10, 778}, - dictWord{132, 10, 46}, - dictWord{5, 10, 811}, - dictWord{6, 10, 1679}, - dictWord{6, 10, 1714}, - dictWord{135, 10, 2032}, - dictWord{6, 0, 1446}, - dictWord{7, 10, 1458}, - dictWord{9, 10, 407}, - dictWord{ - 139, - 10, - 15, - }, - dictWord{7, 0, 206}, - dictWord{7, 0, 397}, - dictWord{7, 0, 621}, - dictWord{7, 0, 640}, - dictWord{8, 0, 124}, - dictWord{8, 0, 619}, - dictWord{9, 0, 305}, - dictWord{ - 9, - 0, - 643, - }, - dictWord{10, 0, 264}, - dictWord{10, 0, 628}, - dictWord{11, 0, 40}, - dictWord{12, 0, 349}, - dictWord{13, 0, 134}, - dictWord{13, 0, 295}, - dictWord{ - 14, - 0, - 155, - }, - dictWord{15, 0, 120}, - dictWord{18, 0, 105}, - dictWord{6, 10, 34}, - dictWord{7, 10, 1089}, - dictWord{8, 10, 708}, - dictWord{8, 10, 721}, - dictWord{9, 10, 363}, - dictWord{148, 10, 98}, - dictWord{4, 0, 262}, - dictWord{5, 0, 641}, - dictWord{135, 0, 342}, - dictWord{137, 11, 72}, - dictWord{4, 0, 99}, - dictWord{6, 0, 250}, - dictWord{ - 6, - 0, - 346, - }, - dictWord{8, 0, 127}, - dictWord{138, 0, 81}, - dictWord{132, 0, 915}, - dictWord{5, 0, 75}, - dictWord{9, 0, 517}, - dictWord{10, 0, 470}, - dictWord{12, 0, 155}, - dictWord{141, 0, 224}, - dictWord{132, 10, 462}, - dictWord{11, 11, 600}, - dictWord{11, 11, 670}, - dictWord{141, 11, 245}, - dictWord{142, 0, 83}, - dictWord{ - 5, - 10, - 73, - }, - dictWord{6, 10, 23}, - dictWord{134, 10, 338}, - dictWord{6, 0, 1031}, - dictWord{139, 11, 923}, - dictWord{7, 11, 164}, - dictWord{7, 11, 1571}, - dictWord{ - 9, - 11, - 107, - }, - dictWord{140, 11, 225}, - dictWord{134, 0, 1470}, - dictWord{133, 0, 954}, - dictWord{6, 0, 304}, - dictWord{8, 0, 418}, - dictWord{10, 0, 345}, - dictWord{ - 11, - 0, - 341, - }, - dictWord{139, 0, 675}, - dictWord{9, 0, 410}, - dictWord{139, 0, 425}, - dictWord{4, 11, 27}, - dictWord{5, 11, 484}, - dictWord{5, 11, 510}, - dictWord{6, 11, 434}, - dictWord{7, 11, 1000}, - dictWord{7, 11, 1098}, - dictWord{8, 11, 2}, - dictWord{136, 11, 200}, - dictWord{134, 0, 734}, - dictWord{140, 11, 257}, - dictWord{ - 7, - 10, - 725, - }, - dictWord{8, 10, 498}, - dictWord{139, 10, 268}, - dictWord{134, 0, 1822}, - dictWord{135, 0, 1798}, - dictWord{135, 10, 773}, - dictWord{132, 11, 460}, - dictWord{4, 11, 932}, - dictWord{133, 11, 891}, - dictWord{134, 0, 14}, - dictWord{132, 10, 583}, - dictWord{7, 10, 1462}, - dictWord{8, 11, 625}, - dictWord{ - 139, - 10, - 659, - }, - dictWord{5, 0, 113}, - dictWord{6, 0, 243}, - dictWord{6, 0, 1708}, - dictWord{7, 0, 1865}, - dictWord{11, 0, 161}, - dictWord{16, 0, 37}, - dictWord{17, 0, 99}, - dictWord{133, 10, 220}, - dictWord{134, 11, 76}, - dictWord{5, 11, 461}, - dictWord{135, 11, 1925}, - dictWord{140, 0, 69}, - dictWord{8, 11, 92}, - dictWord{ - 137, - 11, - 221, - }, - dictWord{139, 10, 803}, - dictWord{132, 10, 544}, - dictWord{4, 0, 274}, - dictWord{134, 0, 922}, - dictWord{132, 0, 541}, - dictWord{5, 0, 627}, - dictWord{ - 6, - 10, - 437, - }, - dictWord{6, 10, 564}, - dictWord{11, 10, 181}, - dictWord{141, 10, 183}, - dictWord{135, 10, 1192}, - dictWord{7, 0, 166}, - dictWord{132, 11, 763}, - dictWord{133, 11, 253}, - dictWord{134, 0, 849}, - dictWord{9, 11, 73}, - dictWord{10, 11, 110}, - dictWord{14, 11, 185}, - dictWord{145, 11, 119}, - dictWord{5, 11, 212}, - dictWord{12, 11, 35}, - dictWord{141, 11, 382}, - dictWord{133, 0, 717}, - dictWord{137, 0, 304}, - dictWord{136, 0, 600}, - dictWord{133, 0, 654}, - dictWord{ - 6, - 0, - 273, - }, - dictWord{10, 0, 188}, - dictWord{13, 0, 377}, - dictWord{146, 0, 77}, - dictWord{4, 10, 790}, - dictWord{5, 10, 273}, - dictWord{134, 10, 394}, - dictWord{ - 132, - 0, - 543, - }, - dictWord{135, 0, 410}, - dictWord{11, 0, 98}, - dictWord{11, 0, 524}, - dictWord{141, 0, 87}, - dictWord{132, 0, 941}, - dictWord{135, 11, 1175}, - dictWord{ - 4, - 0, - 250, - }, - dictWord{7, 0, 1612}, - dictWord{11, 0, 186}, - dictWord{12, 0, 133}, - dictWord{6, 10, 127}, - dictWord{7, 10, 1511}, - dictWord{8, 10, 613}, - dictWord{ - 12, - 10, - 495, - }, - dictWord{12, 10, 586}, - dictWord{12, 10, 660}, - dictWord{12, 10, 668}, - dictWord{14, 10, 385}, - dictWord{15, 10, 118}, - dictWord{17, 10, 20}, - dictWord{ - 146, - 10, - 98, - }, - dictWord{6, 0, 1785}, - dictWord{133, 11, 816}, - dictWord{134, 0, 1339}, - dictWord{7, 0, 961}, - dictWord{7, 0, 1085}, - dictWord{7, 0, 1727}, - dictWord{ - 8, - 0, - 462, - }, - dictWord{6, 10, 230}, - dictWord{135, 11, 1727}, - dictWord{9, 0, 636}, - dictWord{135, 10, 1954}, - dictWord{132, 0, 780}, - dictWord{5, 11, 869}, - dictWord{5, 11, 968}, - dictWord{6, 11, 1626}, - dictWord{8, 11, 734}, - dictWord{136, 11, 784}, - dictWord{4, 11, 542}, - dictWord{6, 11, 1716}, - dictWord{6, 11, 1727}, - dictWord{7, 11, 1082}, - dictWord{7, 11, 1545}, - dictWord{8, 11, 56}, - dictWord{8, 11, 118}, - dictWord{8, 11, 412}, - dictWord{8, 11, 564}, - dictWord{9, 11, 888}, - dictWord{9, 11, 908}, - dictWord{10, 11, 50}, - dictWord{10, 11, 423}, - dictWord{11, 11, 685}, - dictWord{11, 11, 697}, - dictWord{11, 11, 933}, - dictWord{12, 11, 299}, - dictWord{13, 11, 126}, - dictWord{13, 11, 136}, - dictWord{13, 11, 170}, - dictWord{141, 11, 190}, - dictWord{134, 11, 226}, - dictWord{4, 11, 232}, - dictWord{ - 9, - 11, - 202, - }, - dictWord{10, 11, 474}, - dictWord{140, 11, 433}, - dictWord{137, 11, 500}, - dictWord{5, 0, 529}, - dictWord{136, 10, 68}, - dictWord{132, 10, 654}, - dictWord{ - 4, - 10, - 156, - }, - dictWord{7, 10, 998}, - dictWord{7, 10, 1045}, - dictWord{7, 10, 1860}, - dictWord{9, 10, 48}, - dictWord{9, 10, 692}, - dictWord{11, 10, 419}, - dictWord{139, 10, 602}, - dictWord{7, 0, 1276}, - dictWord{8, 0, 474}, - dictWord{9, 0, 652}, - dictWord{6, 11, 108}, - dictWord{7, 11, 1003}, - dictWord{7, 11, 1181}, - dictWord{136, 11, 343}, - dictWord{7, 11, 1264}, - dictWord{7, 11, 1678}, - dictWord{11, 11, 945}, - dictWord{12, 11, 341}, - dictWord{12, 11, 471}, - dictWord{ - 140, - 11, - 569, - }, - dictWord{134, 11, 1712}, - dictWord{5, 0, 948}, - dictWord{12, 0, 468}, - dictWord{19, 0, 96}, - dictWord{148, 0, 24}, - dictWord{4, 11, 133}, - dictWord{ - 7, - 11, - 711, - }, - dictWord{7, 11, 1298}, - dictWord{7, 11, 1585}, - dictWord{135, 11, 1929}, - dictWord{6, 0, 753}, - dictWord{140, 0, 657}, - dictWord{139, 0, 941}, - dictWord{ - 6, - 11, - 99, - }, - dictWord{7, 11, 1808}, - dictWord{145, 11, 57}, - dictWord{6, 11, 574}, - dictWord{7, 11, 428}, - dictWord{7, 11, 1250}, - dictWord{10, 11, 669}, - dictWord{ - 11, - 11, - 485, - }, - dictWord{11, 11, 840}, - dictWord{12, 11, 300}, - dictWord{142, 11, 250}, - dictWord{4, 0, 532}, - dictWord{5, 0, 706}, - dictWord{135, 0, 662}, - dictWord{ - 5, - 0, - 837, - }, - dictWord{6, 0, 1651}, - dictWord{139, 0, 985}, - dictWord{7, 0, 1861}, - dictWord{9, 10, 197}, - dictWord{10, 10, 300}, - dictWord{12, 10, 473}, - dictWord{ - 13, - 10, - 90, - }, - dictWord{141, 10, 405}, - dictWord{137, 11, 252}, - dictWord{6, 11, 323}, - dictWord{135, 11, 1564}, - dictWord{4, 0, 330}, - dictWord{4, 0, 863}, - dictWord{7, 0, 933}, - dictWord{7, 0, 2012}, - dictWord{8, 0, 292}, - dictWord{7, 11, 461}, - dictWord{8, 11, 775}, - dictWord{138, 11, 435}, - dictWord{132, 10, 606}, - dictWord{ - 4, - 11, - 655, - }, - dictWord{7, 11, 850}, - dictWord{17, 11, 75}, - dictWord{146, 11, 137}, - dictWord{135, 0, 767}, - dictWord{7, 10, 1978}, - dictWord{136, 10, 676}, - dictWord{132, 0, 641}, - dictWord{135, 11, 1559}, - dictWord{134, 0, 1233}, - dictWord{137, 0, 242}, - dictWord{17, 0, 114}, - dictWord{4, 10, 361}, - dictWord{ - 133, - 10, - 315, - }, - dictWord{137, 0, 883}, - dictWord{132, 10, 461}, - dictWord{138, 0, 274}, - dictWord{134, 0, 2008}, - dictWord{134, 0, 1794}, - dictWord{4, 0, 703}, - dictWord{135, 0, 207}, - dictWord{12, 0, 285}, - dictWord{132, 10, 472}, - dictWord{132, 0, 571}, - dictWord{5, 0, 873}, - dictWord{5, 0, 960}, - dictWord{8, 0, 823}, - dictWord{9, 0, 881}, - dictWord{136, 11, 577}, - dictWord{7, 0, 617}, - dictWord{10, 0, 498}, - dictWord{11, 0, 501}, - dictWord{12, 0, 16}, - dictWord{140, 0, 150}, - dictWord{ - 138, - 10, - 747, - }, - dictWord{132, 0, 431}, - dictWord{133, 10, 155}, - dictWord{11, 0, 283}, - dictWord{11, 0, 567}, - dictWord{7, 10, 163}, - dictWord{8, 10, 319}, - dictWord{ - 9, - 10, - 402, - }, - dictWord{10, 10, 24}, - dictWord{10, 10, 681}, - dictWord{11, 10, 200}, - dictWord{12, 10, 253}, - dictWord{12, 10, 410}, - dictWord{142, 10, 219}, - dictWord{4, 11, 413}, - dictWord{5, 11, 677}, - dictWord{8, 11, 432}, - dictWord{140, 11, 280}, - dictWord{9, 0, 401}, - dictWord{5, 10, 475}, - dictWord{7, 10, 1780}, - dictWord{11, 10, 297}, - dictWord{11, 10, 558}, - dictWord{14, 10, 322}, - dictWord{147, 10, 76}, - dictWord{6, 0, 781}, - dictWord{9, 0, 134}, - dictWord{10, 0, 2}, - dictWord{ - 10, - 0, - 27, - }, - dictWord{10, 0, 333}, - dictWord{11, 0, 722}, - dictWord{143, 0, 1}, - dictWord{5, 0, 33}, - dictWord{6, 0, 470}, - dictWord{139, 0, 424}, - dictWord{ - 135, - 0, - 2006, - }, - dictWord{12, 0, 783}, - dictWord{135, 10, 1956}, - dictWord{136, 0, 274}, - dictWord{135, 0, 1882}, - dictWord{132, 0, 794}, - dictWord{135, 0, 1848}, - dictWord{5, 10, 944}, - dictWord{134, 10, 1769}, - dictWord{6, 0, 47}, - dictWord{7, 0, 90}, - dictWord{7, 0, 664}, - dictWord{7, 0, 830}, - dictWord{7, 0, 1380}, - dictWord{ - 7, - 0, - 2025, - }, - dictWord{8, 0, 448}, - dictWord{136, 0, 828}, - dictWord{132, 10, 144}, - dictWord{134, 0, 1199}, - dictWord{4, 11, 395}, - dictWord{139, 11, 762}, - dictWord{135, 11, 1504}, - dictWord{9, 0, 417}, - dictWord{137, 0, 493}, - dictWord{9, 11, 174}, - dictWord{10, 11, 164}, - dictWord{11, 11, 440}, - dictWord{11, 11, 841}, - dictWord{143, 11, 98}, - dictWord{134, 11, 426}, - dictWord{139, 11, 1002}, - dictWord{134, 0, 295}, - dictWord{134, 0, 816}, - dictWord{6, 10, 247}, - dictWord{ - 137, - 10, - 555, - }, - dictWord{133, 0, 1019}, - dictWord{4, 0, 620}, - dictWord{5, 11, 476}, - dictWord{10, 10, 280}, - dictWord{138, 10, 797}, - dictWord{139, 0, 464}, - dictWord{5, 11, 76}, - dictWord{6, 11, 458}, - dictWord{6, 11, 497}, - dictWord{7, 11, 764}, - dictWord{7, 11, 868}, - dictWord{9, 11, 658}, - dictWord{10, 11, 594}, - dictWord{ - 11, - 11, - 173, - }, - dictWord{11, 11, 566}, - dictWord{12, 11, 20}, - dictWord{12, 11, 338}, - dictWord{141, 11, 200}, - dictWord{134, 0, 208}, - dictWord{4, 11, 526}, - dictWord{7, 11, 1029}, - dictWord{135, 11, 1054}, - dictWord{132, 11, 636}, - dictWord{6, 11, 233}, - dictWord{7, 11, 660}, - dictWord{7, 11, 1124}, - dictWord{ - 17, - 11, - 31, - }, - dictWord{19, 11, 22}, - dictWord{151, 11, 14}, - dictWord{10, 0, 442}, - dictWord{133, 10, 428}, - dictWord{10, 0, 930}, - dictWord{140, 0, 778}, - dictWord{ - 6, - 0, - 68, - }, - dictWord{7, 0, 448}, - dictWord{7, 0, 1629}, - dictWord{7, 0, 1769}, - dictWord{7, 0, 1813}, - dictWord{8, 0, 442}, - dictWord{8, 0, 516}, - dictWord{9, 0, 710}, - dictWord{ - 10, - 0, - 282, - }, - dictWord{10, 0, 722}, - dictWord{7, 10, 1717}, - dictWord{138, 10, 546}, - dictWord{134, 0, 1128}, - dictWord{11, 0, 844}, - dictWord{12, 0, 104}, - dictWord{140, 0, 625}, - dictWord{4, 11, 432}, - dictWord{135, 11, 824}, - dictWord{138, 10, 189}, - dictWord{133, 0, 787}, - dictWord{133, 10, 99}, - dictWord{ - 4, - 11, - 279, - }, - dictWord{7, 11, 301}, - dictWord{137, 11, 362}, - dictWord{8, 0, 491}, - dictWord{4, 10, 397}, - dictWord{136, 10, 555}, - dictWord{4, 11, 178}, - dictWord{ - 133, - 11, - 399, - }, - dictWord{134, 0, 711}, - dictWord{144, 0, 9}, - dictWord{4, 0, 403}, - dictWord{5, 0, 441}, - dictWord{7, 0, 450}, - dictWord{10, 0, 840}, - dictWord{11, 0, 101}, - dictWord{12, 0, 193}, - dictWord{141, 0, 430}, - dictWord{135, 11, 1246}, - dictWord{12, 10, 398}, - dictWord{20, 10, 39}, - dictWord{21, 10, 11}, - dictWord{ - 150, - 10, - 41, - }, - dictWord{4, 10, 485}, - dictWord{7, 10, 353}, - dictWord{135, 10, 1523}, - dictWord{6, 10, 366}, - dictWord{7, 10, 1384}, - dictWord{7, 10, 1601}, - dictWord{ - 135, - 11, - 1912, - }, - dictWord{7, 0, 396}, - dictWord{10, 0, 160}, - dictWord{135, 11, 396}, - dictWord{137, 10, 282}, - dictWord{134, 11, 1692}, - dictWord{4, 10, 157}, - dictWord{5, 10, 471}, - dictWord{6, 11, 202}, - dictWord{10, 11, 448}, - dictWord{11, 11, 208}, - dictWord{12, 11, 360}, - dictWord{17, 11, 117}, - dictWord{ - 17, - 11, - 118, - }, - dictWord{18, 11, 27}, - dictWord{148, 11, 67}, - dictWord{133, 0, 679}, - dictWord{137, 0, 326}, - dictWord{136, 10, 116}, - dictWord{7, 11, 872}, - dictWord{ - 10, - 11, - 516, - }, - dictWord{139, 11, 167}, - dictWord{132, 11, 224}, - dictWord{5, 11, 546}, - dictWord{7, 11, 35}, - dictWord{8, 11, 11}, - dictWord{8, 11, 12}, - dictWord{ - 9, - 11, - 315, - }, - dictWord{9, 11, 533}, - dictWord{10, 11, 802}, - dictWord{11, 11, 166}, - dictWord{12, 11, 525}, - dictWord{142, 11, 243}, - dictWord{7, 0, 1128}, - dictWord{135, 11, 1920}, - dictWord{5, 11, 241}, - dictWord{8, 11, 242}, - dictWord{9, 11, 451}, - dictWord{10, 11, 667}, - dictWord{11, 11, 598}, - dictWord{ - 140, - 11, - 429, - }, - dictWord{6, 0, 737}, - dictWord{5, 10, 160}, - dictWord{7, 10, 363}, - dictWord{7, 10, 589}, - dictWord{10, 10, 170}, - dictWord{141, 10, 55}, - dictWord{ - 135, - 0, - 1796, - }, - dictWord{142, 11, 254}, - dictWord{4, 0, 574}, - dictWord{7, 0, 350}, - dictWord{7, 0, 1024}, - dictWord{8, 0, 338}, - dictWord{9, 0, 677}, - dictWord{138, 0, 808}, - dictWord{134, 0, 1096}, - dictWord{137, 11, 516}, - dictWord{7, 0, 405}, - dictWord{10, 0, 491}, - dictWord{4, 10, 108}, - dictWord{4, 11, 366}, - dictWord{ - 139, - 10, - 498, - }, - dictWord{11, 11, 337}, - dictWord{142, 11, 303}, - dictWord{134, 11, 1736}, - dictWord{7, 0, 1081}, - dictWord{140, 11, 364}, - dictWord{7, 10, 1005}, - dictWord{140, 10, 609}, - dictWord{7, 0, 1676}, - dictWord{4, 10, 895}, - dictWord{133, 10, 772}, - dictWord{135, 0, 2037}, - dictWord{6, 0, 1207}, - dictWord{ - 11, - 11, - 916, - }, - dictWord{142, 11, 419}, - dictWord{14, 11, 140}, - dictWord{148, 11, 41}, - dictWord{6, 11, 331}, - dictWord{136, 11, 623}, - dictWord{9, 0, 944}, - dictWord{ - 9, - 0, - 969, - }, - dictWord{9, 0, 1022}, - dictWord{12, 0, 913}, - dictWord{12, 0, 936}, - dictWord{15, 0, 177}, - dictWord{15, 0, 193}, - dictWord{4, 10, 926}, - dictWord{ - 133, - 10, - 983, - }, - dictWord{5, 0, 354}, - dictWord{135, 11, 506}, - dictWord{8, 0, 598}, - dictWord{9, 0, 664}, - dictWord{138, 0, 441}, - dictWord{4, 11, 640}, - dictWord{ - 133, - 11, - 513, - }, - dictWord{137, 0, 297}, - dictWord{132, 10, 538}, - dictWord{6, 10, 294}, - dictWord{7, 10, 1267}, - dictWord{136, 10, 624}, - dictWord{7, 0, 1772}, - dictWord{ - 7, - 11, - 1888, - }, - dictWord{8, 11, 289}, - dictWord{11, 11, 45}, - dictWord{12, 11, 278}, - dictWord{140, 11, 537}, - dictWord{135, 10, 1325}, - dictWord{138, 0, 751}, - dictWord{141, 0, 37}, - dictWord{134, 0, 1828}, - dictWord{132, 10, 757}, - dictWord{132, 11, 394}, - dictWord{6, 0, 257}, - dictWord{135, 0, 1522}, - dictWord{ - 4, - 0, - 582, - }, - dictWord{9, 0, 191}, - dictWord{135, 11, 1931}, - dictWord{7, 11, 574}, - dictWord{7, 11, 1719}, - dictWord{137, 11, 145}, - dictWord{132, 11, 658}, - dictWord{10, 0, 790}, - dictWord{132, 11, 369}, - dictWord{9, 11, 781}, - dictWord{10, 11, 144}, - dictWord{11, 11, 385}, - dictWord{13, 11, 161}, - dictWord{13, 11, 228}, - dictWord{13, 11, 268}, - dictWord{148, 11, 107}, - dictWord{8, 0, 469}, - dictWord{10, 0, 47}, - dictWord{136, 11, 374}, - dictWord{6, 0, 306}, - dictWord{7, 0, 1140}, - dictWord{7, 0, 1340}, - dictWord{8, 0, 133}, - dictWord{138, 0, 449}, - dictWord{139, 0, 1011}, - dictWord{7, 10, 1875}, - dictWord{139, 10, 124}, - dictWord{ - 4, - 11, - 344, - }, - dictWord{6, 11, 498}, - dictWord{139, 11, 323}, - dictWord{137, 0, 299}, - dictWord{132, 0, 837}, - dictWord{133, 11, 906}, - dictWord{5, 0, 329}, - dictWord{ - 8, - 0, - 260, - }, - dictWord{138, 0, 10}, - dictWord{134, 0, 1320}, - dictWord{4, 0, 657}, - dictWord{146, 0, 158}, - dictWord{135, 0, 1191}, - dictWord{152, 0, 7}, - dictWord{ - 6, - 0, - 1939, - }, - dictWord{8, 0, 974}, - dictWord{138, 0, 996}, - dictWord{135, 0, 1665}, - dictWord{11, 11, 126}, - dictWord{139, 11, 287}, - dictWord{143, 0, 8}, - dictWord{ - 14, - 11, - 149, - }, - dictWord{14, 11, 399}, - dictWord{143, 11, 57}, - dictWord{5, 0, 66}, - dictWord{7, 0, 1896}, - dictWord{136, 0, 288}, - dictWord{7, 0, 175}, - dictWord{ - 10, - 0, - 494, - }, - dictWord{5, 10, 150}, - dictWord{8, 10, 603}, - dictWord{9, 10, 593}, - dictWord{9, 10, 634}, - dictWord{10, 10, 173}, - dictWord{11, 10, 462}, - dictWord{ - 11, - 10, - 515, - }, - dictWord{13, 10, 216}, - dictWord{13, 10, 288}, - dictWord{142, 10, 400}, - dictWord{134, 0, 1643}, - dictWord{136, 11, 21}, - dictWord{4, 0, 21}, - dictWord{ - 5, - 0, - 91, - }, - dictWord{5, 0, 648}, - dictWord{5, 0, 750}, - dictWord{5, 0, 781}, - dictWord{6, 0, 54}, - dictWord{6, 0, 112}, - dictWord{6, 0, 402}, - dictWord{6, 0, 1732}, - dictWord{ - 7, - 0, - 315, - }, - dictWord{7, 0, 749}, - dictWord{7, 0, 1427}, - dictWord{7, 0, 1900}, - dictWord{9, 0, 78}, - dictWord{9, 0, 508}, - dictWord{10, 0, 611}, - dictWord{10, 0, 811}, - dictWord{11, 0, 510}, - dictWord{11, 0, 728}, - dictWord{13, 0, 36}, - dictWord{14, 0, 39}, - dictWord{16, 0, 83}, - dictWord{17, 0, 124}, - dictWord{148, 0, 30}, - dictWord{ - 4, - 0, - 668, - }, - dictWord{136, 0, 570}, - dictWord{10, 0, 322}, - dictWord{10, 0, 719}, - dictWord{139, 0, 407}, - dictWord{135, 11, 1381}, - dictWord{136, 11, 193}, - dictWord{12, 10, 108}, - dictWord{141, 10, 291}, - dictWord{132, 11, 616}, - dictWord{136, 11, 692}, - dictWord{8, 0, 125}, - dictWord{8, 0, 369}, - dictWord{8, 0, 524}, - dictWord{10, 0, 486}, - dictWord{11, 0, 13}, - dictWord{11, 0, 381}, - dictWord{11, 0, 736}, - dictWord{11, 0, 766}, - dictWord{11, 0, 845}, - dictWord{13, 0, 114}, - dictWord{ - 13, - 0, - 292, - }, - dictWord{142, 0, 47}, - dictWord{134, 0, 1247}, - dictWord{6, 0, 1684}, - dictWord{6, 0, 1731}, - dictWord{7, 0, 356}, - dictWord{8, 0, 54}, - dictWord{8, 0, 221}, - dictWord{9, 0, 225}, - dictWord{9, 0, 356}, - dictWord{10, 0, 77}, - dictWord{10, 0, 446}, - dictWord{10, 0, 731}, - dictWord{12, 0, 404}, - dictWord{141, 0, 491}, - dictWord{135, 10, 1777}, - dictWord{4, 11, 305}, - dictWord{4, 10, 493}, - dictWord{144, 10, 55}, - dictWord{4, 0, 951}, - dictWord{6, 0, 1809}, - dictWord{6, 0, 1849}, - dictWord{8, 0, 846}, - dictWord{8, 0, 866}, - dictWord{8, 0, 899}, - dictWord{10, 0, 896}, - dictWord{12, 0, 694}, - dictWord{142, 0, 468}, - dictWord{5, 11, 214}, - dictWord{ - 7, - 11, - 603, - }, - dictWord{8, 11, 611}, - dictWord{9, 11, 686}, - dictWord{10, 11, 88}, - dictWord{11, 11, 459}, - dictWord{11, 11, 496}, - dictWord{12, 11, 463}, - dictWord{ - 12, - 11, - 590, - }, - dictWord{13, 11, 0}, - dictWord{142, 11, 214}, - dictWord{132, 0, 411}, - dictWord{4, 0, 80}, - dictWord{133, 0, 44}, - dictWord{140, 11, 74}, - dictWord{ - 143, - 0, - 31, - }, - dictWord{7, 0, 669}, - dictWord{6, 10, 568}, - dictWord{7, 10, 1804}, - dictWord{8, 10, 362}, - dictWord{8, 10, 410}, - dictWord{8, 10, 830}, - dictWord{9, 10, 514}, - dictWord{11, 10, 649}, - dictWord{142, 10, 157}, - dictWord{7, 0, 673}, - dictWord{134, 11, 1703}, - dictWord{132, 10, 625}, - dictWord{134, 0, 1303}, - dictWord{ - 5, - 0, - 299, - }, - dictWord{135, 0, 1083}, - dictWord{138, 0, 704}, - dictWord{6, 0, 275}, - dictWord{7, 0, 408}, - dictWord{6, 10, 158}, - dictWord{7, 10, 129}, - dictWord{ - 7, - 10, - 181, - }, - dictWord{8, 10, 276}, - dictWord{8, 10, 377}, - dictWord{10, 10, 523}, - dictWord{11, 10, 816}, - dictWord{12, 10, 455}, - dictWord{13, 10, 303}, - dictWord{ - 142, - 10, - 135, - }, - dictWord{4, 0, 219}, - dictWord{7, 0, 367}, - dictWord{7, 0, 1713}, - dictWord{7, 0, 1761}, - dictWord{9, 0, 86}, - dictWord{9, 0, 537}, - dictWord{10, 0, 165}, - dictWord{12, 0, 219}, - dictWord{140, 0, 561}, - dictWord{8, 0, 216}, - dictWord{4, 10, 1}, - dictWord{4, 11, 737}, - dictWord{6, 11, 317}, - dictWord{7, 10, 1143}, - dictWord{ - 7, - 10, - 1463, - }, - dictWord{9, 10, 207}, - dictWord{9, 10, 390}, - dictWord{9, 10, 467}, - dictWord{10, 11, 98}, - dictWord{11, 11, 294}, - dictWord{11, 10, 836}, - dictWord{ - 12, - 11, - 60, - }, - dictWord{12, 11, 437}, - dictWord{13, 11, 64}, - dictWord{13, 11, 380}, - dictWord{142, 11, 430}, - dictWord{6, 11, 1758}, - dictWord{8, 11, 520}, - dictWord{9, 11, 345}, - dictWord{9, 11, 403}, - dictWord{142, 11, 350}, - dictWord{5, 11, 47}, - dictWord{10, 11, 242}, - dictWord{138, 11, 579}, - dictWord{5, 11, 139}, - dictWord{7, 11, 1168}, - dictWord{138, 11, 539}, - dictWord{135, 0, 1319}, - dictWord{4, 10, 295}, - dictWord{4, 10, 723}, - dictWord{5, 10, 895}, - dictWord{ - 7, - 10, - 1031, - }, - dictWord{8, 10, 199}, - dictWord{8, 10, 340}, - dictWord{9, 10, 153}, - dictWord{9, 10, 215}, - dictWord{10, 10, 21}, - dictWord{10, 10, 59}, - dictWord{ - 10, - 10, - 80, - }, - dictWord{10, 10, 224}, - dictWord{10, 10, 838}, - dictWord{11, 10, 229}, - dictWord{11, 10, 652}, - dictWord{12, 10, 192}, - dictWord{13, 10, 146}, - dictWord{ - 142, - 10, - 91, - }, - dictWord{140, 0, 428}, - dictWord{137, 10, 51}, - dictWord{133, 0, 514}, - dictWord{5, 10, 309}, - dictWord{140, 10, 211}, - dictWord{6, 0, 1010}, - dictWord{5, 10, 125}, - dictWord{8, 10, 77}, - dictWord{138, 10, 15}, - dictWord{4, 0, 55}, - dictWord{5, 0, 301}, - dictWord{6, 0, 571}, - dictWord{142, 0, 49}, - dictWord{ - 146, - 0, - 102, - }, - dictWord{136, 11, 370}, - dictWord{4, 11, 107}, - dictWord{7, 11, 613}, - dictWord{8, 11, 358}, - dictWord{8, 11, 439}, - dictWord{8, 11, 504}, - dictWord{ - 9, - 11, - 501, - }, - dictWord{10, 11, 383}, - dictWord{139, 11, 477}, - dictWord{132, 11, 229}, - dictWord{133, 0, 364}, - dictWord{133, 10, 439}, - dictWord{4, 11, 903}, - dictWord{135, 11, 1816}, - dictWord{11, 0, 379}, - dictWord{140, 10, 76}, - dictWord{4, 0, 76}, - dictWord{4, 0, 971}, - dictWord{7, 0, 1550}, - dictWord{9, 0, 306}, - dictWord{ - 9, - 0, - 430, - }, - dictWord{9, 0, 663}, - dictWord{10, 0, 683}, - dictWord{10, 0, 921}, - dictWord{11, 0, 427}, - dictWord{11, 0, 753}, - dictWord{12, 0, 334}, - dictWord{12, 0, 442}, - dictWord{14, 0, 258}, - dictWord{14, 0, 366}, - dictWord{143, 0, 131}, - dictWord{137, 0, 52}, - dictWord{4, 11, 47}, - dictWord{6, 11, 373}, - dictWord{7, 11, 452}, - dictWord{7, 11, 543}, - dictWord{7, 11, 1714}, - dictWord{7, 11, 1856}, - dictWord{9, 11, 6}, - dictWord{11, 11, 257}, - dictWord{139, 11, 391}, - dictWord{4, 10, 8}, - dictWord{ - 7, - 10, - 1152, - }, - dictWord{7, 10, 1153}, - dictWord{7, 10, 1715}, - dictWord{9, 10, 374}, - dictWord{10, 10, 478}, - dictWord{139, 10, 648}, - dictWord{4, 11, 785}, - dictWord{133, 11, 368}, - dictWord{135, 10, 1099}, - dictWord{135, 11, 860}, - dictWord{5, 11, 980}, - dictWord{134, 11, 1754}, - dictWord{134, 0, 1258}, - dictWord{ - 6, - 0, - 1058, - }, - dictWord{6, 0, 1359}, - dictWord{7, 11, 536}, - dictWord{7, 11, 1331}, - dictWord{136, 11, 143}, - dictWord{4, 0, 656}, - dictWord{135, 0, 779}, - dictWord{136, 10, 87}, - dictWord{5, 11, 19}, - dictWord{6, 11, 533}, - dictWord{146, 11, 126}, - dictWord{7, 0, 144}, - dictWord{138, 10, 438}, - dictWord{5, 11, 395}, - dictWord{5, 11, 951}, - dictWord{134, 11, 1776}, - dictWord{135, 0, 1373}, - dictWord{7, 0, 554}, - dictWord{7, 0, 605}, - dictWord{141, 0, 10}, - dictWord{4, 10, 69}, - dictWord{ - 5, - 10, - 122, - }, - dictWord{9, 10, 656}, - dictWord{138, 10, 464}, - dictWord{5, 10, 849}, - dictWord{134, 10, 1633}, - dictWord{5, 0, 838}, - dictWord{5, 0, 841}, - dictWord{134, 0, 1649}, - dictWord{133, 0, 1012}, - dictWord{139, 10, 499}, - dictWord{7, 10, 476}, - dictWord{7, 10, 1592}, - dictWord{138, 10, 87}, - dictWord{ - 6, - 0, - 251, - }, - dictWord{7, 0, 365}, - dictWord{7, 0, 1357}, - dictWord{7, 0, 1497}, - dictWord{8, 0, 154}, - dictWord{141, 0, 281}, - dictWord{132, 11, 441}, - dictWord{ - 132, - 11, - 695, - }, - dictWord{7, 11, 497}, - dictWord{9, 11, 387}, - dictWord{147, 11, 81}, - dictWord{133, 0, 340}, - dictWord{14, 10, 283}, - dictWord{142, 11, 283}, - dictWord{ - 134, - 0, - 810, - }, - dictWord{135, 11, 1894}, - dictWord{139, 0, 495}, - dictWord{5, 11, 284}, - dictWord{6, 11, 49}, - dictWord{6, 11, 350}, - dictWord{7, 11, 1}, - dictWord{ - 7, - 11, - 377, - }, - dictWord{7, 11, 1693}, - dictWord{8, 11, 18}, - dictWord{8, 11, 678}, - dictWord{9, 11, 161}, - dictWord{9, 11, 585}, - dictWord{9, 11, 671}, - dictWord{ - 9, - 11, - 839, - }, - dictWord{11, 11, 912}, - dictWord{141, 11, 427}, - dictWord{5, 10, 859}, - dictWord{7, 10, 1160}, - dictWord{8, 10, 107}, - dictWord{9, 10, 291}, - dictWord{ - 9, - 10, - 439, - }, - dictWord{10, 10, 663}, - dictWord{11, 10, 609}, - dictWord{140, 10, 197}, - dictWord{8, 0, 261}, - dictWord{9, 0, 144}, - dictWord{9, 0, 466}, - dictWord{ - 10, - 0, - 370, - }, - dictWord{12, 0, 470}, - dictWord{13, 0, 144}, - dictWord{142, 0, 348}, - dictWord{137, 0, 897}, - dictWord{6, 0, 248}, - dictWord{9, 0, 546}, - dictWord{10, 0, 535}, - dictWord{11, 0, 681}, - dictWord{141, 0, 135}, - dictWord{4, 0, 358}, - dictWord{135, 0, 1496}, - dictWord{134, 0, 567}, - dictWord{136, 0, 445}, - dictWord{ - 4, - 10, - 117, - }, - dictWord{6, 10, 372}, - dictWord{7, 10, 1905}, - dictWord{142, 10, 323}, - dictWord{4, 10, 722}, - dictWord{139, 10, 471}, - dictWord{6, 0, 697}, - dictWord{ - 134, - 0, - 996, - }, - dictWord{7, 11, 2007}, - dictWord{9, 11, 101}, - dictWord{9, 11, 450}, - dictWord{10, 11, 66}, - dictWord{10, 11, 842}, - dictWord{11, 11, 536}, - dictWord{ - 140, - 11, - 587, - }, - dictWord{132, 0, 577}, - dictWord{134, 0, 1336}, - dictWord{9, 10, 5}, - dictWord{12, 10, 216}, - dictWord{12, 10, 294}, - dictWord{12, 10, 298}, - dictWord{12, 10, 400}, - dictWord{12, 10, 518}, - dictWord{13, 10, 229}, - dictWord{143, 10, 139}, - dictWord{6, 0, 174}, - dictWord{138, 0, 917}, - dictWord{ - 134, - 10, - 1774, - }, - dictWord{5, 10, 12}, - dictWord{7, 10, 375}, - dictWord{9, 10, 88}, - dictWord{9, 10, 438}, - dictWord{11, 11, 62}, - dictWord{139, 10, 270}, - dictWord{ - 134, - 11, - 1766, - }, - dictWord{6, 11, 0}, - dictWord{7, 11, 84}, - dictWord{7, 10, 816}, - dictWord{7, 10, 1241}, - dictWord{9, 10, 283}, - dictWord{9, 10, 520}, - dictWord{10, 10, 213}, - dictWord{10, 10, 307}, - dictWord{10, 10, 463}, - dictWord{10, 10, 671}, - dictWord{10, 10, 746}, - dictWord{11, 10, 401}, - dictWord{11, 10, 794}, - dictWord{ - 11, - 11, - 895, - }, - dictWord{12, 10, 517}, - dictWord{17, 11, 11}, - dictWord{18, 10, 107}, - dictWord{147, 10, 115}, - dictWord{5, 0, 878}, - dictWord{133, 0, 972}, - dictWord{ - 6, - 11, - 1665, - }, - dictWord{7, 11, 256}, - dictWord{7, 11, 1388}, - dictWord{138, 11, 499}, - dictWord{4, 10, 258}, - dictWord{136, 10, 639}, - dictWord{4, 11, 22}, - dictWord{5, 11, 10}, - dictWord{6, 10, 22}, - dictWord{7, 11, 848}, - dictWord{7, 10, 903}, - dictWord{7, 10, 1963}, - dictWord{8, 11, 97}, - dictWord{138, 10, 577}, - dictWord{ - 5, - 10, - 681, - }, - dictWord{136, 10, 782}, - dictWord{133, 11, 481}, - dictWord{132, 0, 351}, - dictWord{4, 10, 664}, - dictWord{5, 10, 804}, - dictWord{139, 10, 1013}, - dictWord{6, 11, 134}, - dictWord{7, 11, 437}, - dictWord{7, 11, 959}, - dictWord{9, 11, 37}, - dictWord{14, 11, 285}, - dictWord{14, 11, 371}, - dictWord{144, 11, 60}, - dictWord{7, 11, 486}, - dictWord{8, 11, 155}, - dictWord{11, 11, 93}, - dictWord{140, 11, 164}, - dictWord{132, 0, 286}, - dictWord{7, 0, 438}, - dictWord{7, 0, 627}, - dictWord{7, 0, 1516}, - dictWord{8, 0, 40}, - dictWord{9, 0, 56}, - dictWord{9, 0, 294}, - dictWord{10, 0, 30}, - dictWord{11, 0, 969}, - dictWord{11, 0, 995}, - dictWord{146, 0, 148}, - dictWord{5, 11, 591}, - dictWord{135, 11, 337}, - dictWord{134, 0, 1950}, - dictWord{133, 10, 32}, - dictWord{138, 11, 500}, - dictWord{5, 11, 380}, - dictWord{ - 5, - 11, - 650, - }, - dictWord{136, 11, 310}, - dictWord{4, 11, 364}, - dictWord{7, 11, 1156}, - dictWord{7, 11, 1187}, - dictWord{137, 11, 409}, - dictWord{4, 0, 738}, - dictWord{134, 11, 482}, - dictWord{4, 11, 781}, - dictWord{6, 11, 487}, - dictWord{7, 11, 926}, - dictWord{8, 11, 263}, - dictWord{139, 11, 500}, - dictWord{135, 11, 418}, - dictWord{6, 0, 2047}, - dictWord{10, 0, 969}, - dictWord{4, 10, 289}, - dictWord{7, 10, 629}, - dictWord{7, 10, 1698}, - dictWord{7, 10, 1711}, - dictWord{ - 140, - 10, - 215, - }, - dictWord{6, 10, 450}, - dictWord{136, 10, 109}, - dictWord{134, 0, 818}, - dictWord{136, 10, 705}, - dictWord{133, 0, 866}, - dictWord{4, 11, 94}, - dictWord{ - 135, - 11, - 1265, - }, - dictWord{132, 11, 417}, - dictWord{134, 0, 1467}, - dictWord{135, 10, 1238}, - dictWord{4, 0, 972}, - dictWord{6, 0, 1851}, - dictWord{ - 134, - 0, - 1857, - }, - dictWord{134, 0, 355}, - dictWord{133, 0, 116}, - dictWord{132, 0, 457}, - dictWord{135, 11, 1411}, - dictWord{4, 11, 408}, - dictWord{4, 11, 741}, - dictWord{135, 11, 500}, - dictWord{134, 10, 26}, - dictWord{142, 11, 137}, - dictWord{5, 0, 527}, - dictWord{6, 0, 189}, - dictWord{7, 0, 859}, - dictWord{136, 0, 267}, - dictWord{11, 0, 104}, - dictWord{11, 0, 554}, - dictWord{15, 0, 60}, - dictWord{143, 0, 125}, - dictWord{134, 0, 1613}, - dictWord{4, 10, 414}, - dictWord{5, 10, 467}, - dictWord{ - 9, - 10, - 654, - }, - dictWord{10, 10, 451}, - dictWord{12, 10, 59}, - dictWord{141, 10, 375}, - dictWord{135, 10, 17}, - dictWord{134, 0, 116}, - dictWord{135, 11, 541}, - dictWord{135, 10, 955}, - dictWord{6, 11, 73}, - dictWord{135, 11, 177}, - dictWord{133, 11, 576}, - dictWord{134, 0, 886}, - dictWord{133, 0, 487}, - dictWord{ - 4, - 0, - 86, - }, - dictWord{5, 0, 667}, - dictWord{5, 0, 753}, - dictWord{6, 0, 316}, - dictWord{6, 0, 455}, - dictWord{135, 0, 946}, - dictWord{142, 11, 231}, - dictWord{150, 0, 45}, - dictWord{134, 0, 863}, - dictWord{134, 0, 1953}, - dictWord{6, 10, 280}, - dictWord{10, 10, 502}, - dictWord{11, 10, 344}, - dictWord{140, 10, 38}, - dictWord{4, 0, 79}, - dictWord{7, 0, 1773}, - dictWord{10, 0, 450}, - dictWord{11, 0, 589}, - dictWord{13, 0, 332}, - dictWord{13, 0, 493}, - dictWord{14, 0, 183}, - dictWord{14, 0, 334}, - dictWord{14, 0, 362}, - dictWord{14, 0, 368}, - dictWord{14, 0, 376}, - dictWord{14, 0, 379}, - dictWord{19, 0, 90}, - dictWord{19, 0, 103}, - dictWord{19, 0, 127}, - dictWord{ - 148, - 0, - 90, - }, - dictWord{5, 10, 45}, - dictWord{7, 10, 1161}, - dictWord{11, 10, 448}, - dictWord{11, 10, 880}, - dictWord{13, 10, 139}, - dictWord{13, 10, 407}, - dictWord{ - 15, - 10, - 16, - }, - dictWord{17, 10, 95}, - dictWord{18, 10, 66}, - dictWord{18, 10, 88}, - dictWord{18, 10, 123}, - dictWord{149, 10, 7}, - dictWord{136, 10, 777}, - dictWord{ - 4, - 10, - 410, - }, - dictWord{135, 10, 521}, - dictWord{135, 10, 1778}, - dictWord{135, 11, 538}, - dictWord{142, 0, 381}, - dictWord{133, 11, 413}, - dictWord{ - 134, - 0, - 1142, - }, - dictWord{6, 0, 1189}, - dictWord{136, 11, 495}, - dictWord{5, 0, 663}, - dictWord{6, 0, 1962}, - dictWord{134, 0, 2003}, - dictWord{7, 11, 54}, - dictWord{ - 8, - 11, - 312, - }, - dictWord{10, 11, 191}, - dictWord{10, 11, 614}, - dictWord{140, 11, 567}, - dictWord{132, 10, 436}, - dictWord{133, 0, 846}, - dictWord{10, 0, 528}, - dictWord{11, 0, 504}, - dictWord{7, 10, 1587}, - dictWord{135, 10, 1707}, - dictWord{5, 0, 378}, - dictWord{8, 0, 465}, - dictWord{9, 0, 286}, - dictWord{10, 0, 185}, - dictWord{ - 10, - 0, - 562, - }, - dictWord{10, 0, 635}, - dictWord{11, 0, 31}, - dictWord{11, 0, 393}, - dictWord{13, 0, 312}, - dictWord{18, 0, 65}, - dictWord{18, 0, 96}, - dictWord{147, 0, 89}, - dictWord{7, 0, 899}, - dictWord{14, 0, 325}, - dictWord{6, 11, 468}, - dictWord{7, 11, 567}, - dictWord{7, 11, 1478}, - dictWord{8, 11, 530}, - dictWord{142, 11, 290}, - dictWord{7, 0, 1880}, - dictWord{9, 0, 680}, - dictWord{139, 0, 798}, - dictWord{134, 0, 1770}, - dictWord{132, 0, 648}, - dictWord{150, 11, 35}, - dictWord{5, 0, 945}, - dictWord{6, 0, 1656}, - dictWord{6, 0, 1787}, - dictWord{7, 0, 167}, - dictWord{8, 0, 824}, - dictWord{9, 0, 391}, - dictWord{10, 0, 375}, - dictWord{139, 0, 185}, - dictWord{ - 6, - 11, - 484, - }, - dictWord{135, 11, 822}, - dictWord{134, 0, 2046}, - dictWord{7, 0, 1645}, - dictWord{8, 0, 352}, - dictWord{137, 0, 249}, - dictWord{132, 0, 152}, - dictWord{6, 0, 611}, - dictWord{135, 0, 1733}, - dictWord{6, 11, 1724}, - dictWord{135, 11, 2022}, - dictWord{133, 0, 1006}, - dictWord{141, 11, 96}, - dictWord{ - 5, - 0, - 420, - }, - dictWord{135, 0, 1449}, - dictWord{146, 11, 149}, - dictWord{135, 0, 832}, - dictWord{135, 10, 663}, - dictWord{133, 0, 351}, - dictWord{5, 0, 40}, - dictWord{ - 7, - 0, - 598, - }, - dictWord{7, 0, 1638}, - dictWord{8, 0, 78}, - dictWord{9, 0, 166}, - dictWord{9, 0, 640}, - dictWord{9, 0, 685}, - dictWord{9, 0, 773}, - dictWord{11, 0, 215}, - dictWord{13, 0, 65}, - dictWord{14, 0, 172}, - dictWord{14, 0, 317}, - dictWord{145, 0, 6}, - dictWord{8, 0, 60}, - dictWord{9, 0, 343}, - dictWord{139, 0, 769}, - dictWord{ - 134, - 0, - 1354, - }, - dictWord{132, 0, 724}, - dictWord{137, 0, 745}, - dictWord{132, 11, 474}, - dictWord{7, 0, 1951}, - dictWord{8, 0, 765}, - dictWord{8, 0, 772}, - dictWord{ - 140, - 0, - 671, - }, - dictWord{7, 0, 108}, - dictWord{8, 0, 219}, - dictWord{8, 0, 388}, - dictWord{9, 0, 775}, - dictWord{11, 0, 275}, - dictWord{140, 0, 464}, - dictWord{137, 0, 639}, - dictWord{135, 10, 503}, - dictWord{133, 11, 366}, - dictWord{5, 0, 15}, - dictWord{6, 0, 56}, - dictWord{7, 0, 1758}, - dictWord{8, 0, 500}, - dictWord{9, 0, 730}, - dictWord{ - 11, - 0, - 331, - }, - dictWord{13, 0, 150}, - dictWord{14, 0, 282}, - dictWord{5, 11, 305}, - dictWord{9, 11, 560}, - dictWord{141, 11, 208}, - dictWord{4, 10, 113}, - dictWord{ - 5, - 10, - 163, - }, - dictWord{5, 10, 735}, - dictWord{7, 10, 1009}, - dictWord{9, 10, 9}, - dictWord{9, 10, 771}, - dictWord{12, 10, 90}, - dictWord{13, 10, 138}, - dictWord{ - 13, - 10, - 410, - }, - dictWord{143, 10, 128}, - dictWord{4, 10, 324}, - dictWord{138, 10, 104}, - dictWord{135, 11, 466}, - dictWord{142, 11, 27}, - dictWord{134, 0, 1886}, - dictWord{5, 0, 205}, - dictWord{6, 0, 438}, - dictWord{9, 0, 711}, - dictWord{4, 11, 480}, - dictWord{6, 11, 167}, - dictWord{6, 11, 302}, - dictWord{6, 11, 1642}, - dictWord{ - 7, - 11, - 130, - }, - dictWord{7, 11, 656}, - dictWord{7, 11, 837}, - dictWord{7, 11, 1547}, - dictWord{7, 11, 1657}, - dictWord{8, 11, 429}, - dictWord{9, 11, 228}, - dictWord{ - 10, - 11, - 643, - }, - dictWord{13, 11, 289}, - dictWord{13, 11, 343}, - dictWord{147, 11, 101}, - dictWord{134, 0, 865}, - dictWord{6, 0, 2025}, - dictWord{136, 0, 965}, - dictWord{ - 7, - 11, - 278, - }, - dictWord{10, 11, 739}, - dictWord{11, 11, 708}, - dictWord{141, 11, 348}, - dictWord{133, 0, 534}, - dictWord{135, 11, 1922}, - dictWord{ - 137, - 0, - 691, - }, - dictWord{4, 10, 935}, - dictWord{133, 10, 823}, - dictWord{6, 0, 443}, - dictWord{9, 0, 237}, - dictWord{9, 0, 571}, - dictWord{9, 0, 695}, - dictWord{10, 0, 139}, - dictWord{11, 0, 715}, - dictWord{12, 0, 417}, - dictWord{141, 0, 421}, - dictWord{5, 10, 269}, - dictWord{7, 10, 434}, - dictWord{7, 10, 891}, - dictWord{8, 10, 339}, - dictWord{ - 9, - 10, - 702, - }, - dictWord{11, 10, 594}, - dictWord{11, 10, 718}, - dictWord{145, 10, 100}, - dictWord{6, 0, 1555}, - dictWord{7, 0, 878}, - dictWord{9, 10, 485}, - dictWord{141, 10, 264}, - dictWord{134, 10, 1713}, - dictWord{7, 10, 1810}, - dictWord{11, 10, 866}, - dictWord{12, 10, 103}, - dictWord{141, 10, 495}, - dictWord{ - 135, - 10, - 900, - }, - dictWord{6, 0, 1410}, - dictWord{9, 11, 316}, - dictWord{139, 11, 256}, - dictWord{4, 0, 995}, - dictWord{135, 0, 1033}, - dictWord{132, 0, 578}, - dictWord{10, 0, 881}, - dictWord{12, 0, 740}, - dictWord{12, 0, 743}, - dictWord{140, 0, 759}, - dictWord{132, 0, 822}, - dictWord{133, 0, 923}, - dictWord{142, 10, 143}, - dictWord{135, 11, 1696}, - dictWord{6, 11, 363}, - dictWord{7, 11, 1955}, - dictWord{136, 11, 725}, - dictWord{132, 0, 924}, - dictWord{133, 0, 665}, - dictWord{ - 135, - 10, - 2029, - }, - dictWord{135, 0, 1901}, - dictWord{4, 0, 265}, - dictWord{6, 0, 1092}, - dictWord{6, 0, 1417}, - dictWord{7, 0, 807}, - dictWord{135, 0, 950}, - dictWord{ - 5, - 0, - 93, - }, - dictWord{12, 0, 267}, - dictWord{141, 0, 498}, - dictWord{135, 0, 1451}, - dictWord{5, 11, 813}, - dictWord{135, 11, 2046}, - dictWord{5, 10, 625}, - dictWord{135, 10, 1617}, - dictWord{135, 0, 747}, - dictWord{6, 0, 788}, - dictWord{137, 0, 828}, - dictWord{7, 0, 184}, - dictWord{11, 0, 307}, - dictWord{11, 0, 400}, - dictWord{15, 0, 130}, - dictWord{5, 11, 712}, - dictWord{7, 11, 1855}, - dictWord{8, 10, 425}, - dictWord{8, 10, 693}, - dictWord{9, 10, 720}, - dictWord{10, 10, 380}, - dictWord{10, 10, 638}, - dictWord{11, 11, 17}, - dictWord{11, 10, 473}, - dictWord{12, 10, 61}, - dictWord{13, 11, 321}, - dictWord{144, 11, 67}, - dictWord{135, 0, 198}, - dictWord{6, 11, 320}, - dictWord{7, 11, 781}, - dictWord{7, 11, 1921}, - dictWord{9, 11, 55}, - dictWord{10, 11, 186}, - dictWord{10, 11, 273}, - dictWord{10, 11, 664}, - dictWord{10, 11, 801}, - dictWord{11, 11, 996}, - dictWord{11, 11, 997}, - dictWord{13, 11, 157}, - dictWord{142, 11, 170}, - dictWord{136, 11, 271}, - dictWord{ - 135, - 0, - 994, - }, - dictWord{7, 11, 103}, - dictWord{7, 11, 863}, - dictWord{11, 11, 184}, - dictWord{14, 11, 299}, - dictWord{145, 11, 62}, - dictWord{11, 10, 551}, - dictWord{142, 10, 159}, - dictWord{5, 0, 233}, - dictWord{5, 0, 320}, - dictWord{6, 0, 140}, - dictWord{8, 0, 295}, - dictWord{8, 0, 615}, - dictWord{136, 11, 615}, - dictWord{ - 133, - 0, - 978, - }, - dictWord{4, 0, 905}, - dictWord{6, 0, 1701}, - dictWord{137, 0, 843}, - dictWord{132, 10, 168}, - dictWord{4, 0, 974}, - dictWord{8, 0, 850}, - dictWord{ - 12, - 0, - 709, - }, - dictWord{12, 0, 768}, - dictWord{140, 0, 786}, - dictWord{135, 10, 91}, - dictWord{152, 0, 6}, - dictWord{138, 10, 532}, - dictWord{135, 10, 1884}, - dictWord{132, 0, 509}, - dictWord{6, 0, 1307}, - dictWord{135, 0, 273}, - dictWord{5, 11, 77}, - dictWord{7, 11, 1455}, - dictWord{10, 11, 843}, - dictWord{19, 11, 73}, - dictWord{150, 11, 5}, - dictWord{132, 11, 458}, - dictWord{135, 11, 1420}, - dictWord{6, 11, 109}, - dictWord{138, 11, 382}, - dictWord{6, 0, 201}, - dictWord{6, 11, 330}, - dictWord{7, 10, 70}, - dictWord{7, 11, 1084}, - dictWord{10, 10, 240}, - dictWord{11, 11, 142}, - dictWord{147, 10, 93}, - dictWord{7, 0, 1041}, - dictWord{ - 140, - 11, - 328, - }, - dictWord{133, 11, 354}, - dictWord{134, 0, 1040}, - dictWord{133, 0, 693}, - dictWord{134, 0, 774}, - dictWord{139, 0, 234}, - dictWord{132, 0, 336}, - dictWord{7, 0, 1399}, - dictWord{139, 10, 392}, - dictWord{20, 0, 22}, - dictWord{148, 11, 22}, - dictWord{5, 0, 802}, - dictWord{7, 0, 2021}, - dictWord{136, 0, 805}, - dictWord{ - 5, - 0, - 167, - }, - dictWord{5, 0, 899}, - dictWord{6, 0, 410}, - dictWord{137, 0, 777}, - dictWord{137, 0, 789}, - dictWord{134, 0, 1705}, - dictWord{7, 10, 655}, - dictWord{ - 135, - 10, - 1844, - }, - dictWord{4, 10, 145}, - dictWord{6, 10, 176}, - dictWord{7, 10, 395}, - dictWord{137, 10, 562}, - dictWord{132, 10, 501}, - dictWord{135, 0, 10}, - dictWord{5, 0, 11}, - dictWord{6, 0, 117}, - dictWord{6, 0, 485}, - dictWord{7, 0, 1133}, - dictWord{9, 0, 582}, - dictWord{9, 0, 594}, - dictWord{10, 0, 82}, - dictWord{11, 0, 21}, - dictWord{11, 0, 818}, - dictWord{12, 0, 535}, - dictWord{13, 0, 86}, - dictWord{20, 0, 91}, - dictWord{23, 0, 13}, - dictWord{134, 10, 509}, - dictWord{4, 0, 264}, - dictWord{ - 7, - 0, - 1067, - }, - dictWord{8, 0, 204}, - dictWord{8, 0, 385}, - dictWord{139, 0, 953}, - dictWord{139, 11, 737}, - dictWord{138, 0, 56}, - dictWord{134, 0, 1917}, - dictWord{ - 133, - 0, - 470, - }, - dictWord{10, 11, 657}, - dictWord{14, 11, 297}, - dictWord{142, 11, 361}, - dictWord{135, 11, 412}, - dictWord{7, 0, 1198}, - dictWord{7, 11, 1198}, - dictWord{8, 11, 556}, - dictWord{14, 11, 123}, - dictWord{14, 11, 192}, - dictWord{143, 11, 27}, - dictWord{7, 11, 1985}, - dictWord{14, 11, 146}, - dictWord{15, 11, 42}, - dictWord{16, 11, 23}, - dictWord{17, 11, 86}, - dictWord{146, 11, 17}, - dictWord{11, 0, 1015}, - dictWord{136, 11, 122}, - dictWord{4, 10, 114}, - dictWord{ - 9, - 10, - 492, - }, - dictWord{13, 10, 462}, - dictWord{142, 10, 215}, - dictWord{4, 10, 77}, - dictWord{5, 10, 361}, - dictWord{6, 10, 139}, - dictWord{6, 10, 401}, - dictWord{ - 6, - 10, - 404, - }, - dictWord{7, 10, 413}, - dictWord{7, 10, 715}, - dictWord{7, 10, 1716}, - dictWord{11, 10, 279}, - dictWord{12, 10, 179}, - dictWord{12, 10, 258}, - dictWord{ - 13, - 10, - 244, - }, - dictWord{142, 10, 358}, - dictWord{134, 10, 1717}, - dictWord{7, 10, 1061}, - dictWord{8, 10, 82}, - dictWord{11, 10, 250}, - dictWord{12, 10, 420}, - dictWord{141, 10, 184}, - dictWord{133, 0, 715}, - dictWord{135, 10, 724}, - dictWord{9, 0, 919}, - dictWord{9, 0, 922}, - dictWord{9, 0, 927}, - dictWord{9, 0, 933}, - dictWord{9, 0, 962}, - dictWord{9, 0, 1000}, - dictWord{9, 0, 1002}, - dictWord{9, 0, 1021}, - dictWord{12, 0, 890}, - dictWord{12, 0, 907}, - dictWord{12, 0, 930}, - dictWord{ - 15, - 0, - 207, - }, - dictWord{15, 0, 228}, - dictWord{15, 0, 238}, - dictWord{149, 0, 61}, - dictWord{8, 0, 794}, - dictWord{9, 0, 400}, - dictWord{10, 0, 298}, - dictWord{142, 0, 228}, - dictWord{5, 11, 430}, - dictWord{5, 11, 932}, - dictWord{6, 11, 131}, - dictWord{7, 11, 417}, - dictWord{9, 11, 522}, - dictWord{11, 11, 314}, - dictWord{141, 11, 390}, - dictWord{132, 0, 867}, - dictWord{8, 0, 724}, - dictWord{132, 11, 507}, - dictWord{137, 11, 261}, - dictWord{4, 11, 343}, - dictWord{133, 11, 511}, - dictWord{ - 6, - 0, - 190, - }, - dictWord{7, 0, 768}, - dictWord{135, 0, 1170}, - dictWord{6, 10, 513}, - dictWord{135, 10, 1052}, - dictWord{7, 11, 455}, - dictWord{138, 11, 591}, - dictWord{134, 0, 1066}, - dictWord{137, 10, 899}, - dictWord{14, 0, 67}, - dictWord{147, 0, 60}, - dictWord{4, 0, 948}, - dictWord{18, 0, 174}, - dictWord{146, 0, 176}, - dictWord{135, 0, 1023}, - dictWord{7, 10, 1417}, - dictWord{12, 10, 382}, - dictWord{17, 10, 48}, - dictWord{152, 10, 12}, - dictWord{134, 11, 575}, - dictWord{ - 132, - 0, - 764, - }, - dictWord{6, 10, 545}, - dictWord{7, 10, 565}, - dictWord{7, 10, 1669}, - dictWord{10, 10, 114}, - dictWord{11, 10, 642}, - dictWord{140, 10, 618}, - dictWord{ - 6, - 0, - 137, - }, - dictWord{9, 0, 75}, - dictWord{9, 0, 253}, - dictWord{10, 0, 194}, - dictWord{138, 0, 444}, - dictWord{4, 0, 756}, - dictWord{133, 10, 5}, - dictWord{8, 0, 1008}, - dictWord{135, 10, 192}, - dictWord{132, 0, 842}, - dictWord{11, 0, 643}, - dictWord{12, 0, 115}, - dictWord{136, 10, 763}, - dictWord{139, 0, 67}, - dictWord{ - 133, - 10, - 759, - }, - dictWord{4, 0, 821}, - dictWord{5, 0, 760}, - dictWord{7, 0, 542}, - dictWord{8, 0, 135}, - dictWord{8, 0, 496}, - dictWord{135, 11, 580}, - dictWord{7, 10, 370}, - dictWord{7, 10, 1007}, - dictWord{7, 10, 1177}, - dictWord{135, 10, 1565}, - dictWord{135, 10, 1237}, - dictWord{140, 0, 736}, - dictWord{7, 0, 319}, - dictWord{ - 7, - 0, - 355, - }, - dictWord{7, 0, 763}, - dictWord{10, 0, 389}, - dictWord{145, 0, 43}, - dictWord{8, 11, 333}, - dictWord{138, 11, 182}, - dictWord{4, 10, 87}, - dictWord{5, 10, 250}, - dictWord{141, 10, 298}, - dictWord{138, 0, 786}, - dictWord{134, 0, 2044}, - dictWord{8, 11, 330}, - dictWord{140, 11, 477}, - dictWord{135, 11, 1338}, - dictWord{132, 11, 125}, - dictWord{134, 0, 1030}, - dictWord{134, 0, 1083}, - dictWord{132, 11, 721}, - dictWord{135, 10, 814}, - dictWord{7, 11, 776}, - dictWord{ - 8, - 11, - 145, - }, - dictWord{147, 11, 56}, - dictWord{134, 0, 1226}, - dictWord{4, 10, 57}, - dictWord{7, 10, 1195}, - dictWord{7, 10, 1438}, - dictWord{7, 10, 1548}, - dictWord{ - 7, - 10, - 1835, - }, - dictWord{7, 10, 1904}, - dictWord{9, 10, 757}, - dictWord{10, 10, 604}, - dictWord{139, 10, 519}, - dictWord{7, 11, 792}, - dictWord{8, 11, 147}, - dictWord{10, 11, 821}, - dictWord{139, 11, 1021}, - dictWord{137, 11, 797}, - dictWord{4, 0, 58}, - dictWord{5, 0, 286}, - dictWord{6, 0, 319}, - dictWord{7, 0, 402}, - dictWord{ - 7, - 0, - 1254, - }, - dictWord{7, 0, 1903}, - dictWord{8, 0, 356}, - dictWord{140, 0, 408}, - dictWord{4, 0, 389}, - dictWord{4, 0, 815}, - dictWord{9, 0, 181}, - dictWord{9, 0, 255}, - dictWord{10, 0, 8}, - dictWord{10, 0, 29}, - dictWord{10, 0, 816}, - dictWord{11, 0, 311}, - dictWord{11, 0, 561}, - dictWord{12, 0, 67}, - dictWord{141, 0, 181}, - dictWord{ - 7, - 11, - 1472, - }, - dictWord{135, 11, 1554}, - dictWord{7, 11, 1071}, - dictWord{7, 11, 1541}, - dictWord{7, 11, 1767}, - dictWord{7, 11, 1806}, - dictWord{7, 11, 1999}, - dictWord{9, 11, 248}, - dictWord{10, 11, 400}, - dictWord{11, 11, 162}, - dictWord{11, 11, 178}, - dictWord{11, 11, 242}, - dictWord{12, 11, 605}, - dictWord{ - 15, - 11, - 26, - }, - dictWord{144, 11, 44}, - dictWord{5, 11, 168}, - dictWord{5, 11, 930}, - dictWord{8, 11, 74}, - dictWord{9, 11, 623}, - dictWord{12, 11, 500}, - dictWord{ - 12, - 11, - 579, - }, - dictWord{13, 11, 41}, - dictWord{143, 11, 93}, - dictWord{6, 11, 220}, - dictWord{7, 11, 1101}, - dictWord{141, 11, 105}, - dictWord{5, 0, 474}, - dictWord{ - 7, - 0, - 507, - }, - dictWord{4, 10, 209}, - dictWord{7, 11, 507}, - dictWord{135, 10, 902}, - dictWord{132, 0, 427}, - dictWord{6, 0, 413}, - dictWord{7, 10, 335}, - dictWord{ - 7, - 10, - 1437, - }, - dictWord{7, 10, 1668}, - dictWord{8, 10, 553}, - dictWord{8, 10, 652}, - dictWord{8, 10, 656}, - dictWord{9, 10, 558}, - dictWord{11, 10, 743}, - dictWord{ - 149, - 10, - 18, - }, - dictWord{132, 0, 730}, - dictWord{6, 11, 19}, - dictWord{7, 11, 1413}, - dictWord{139, 11, 428}, - dictWord{133, 0, 373}, - dictWord{132, 10, 559}, - dictWord{7, 11, 96}, - dictWord{8, 11, 401}, - dictWord{137, 11, 896}, - dictWord{7, 0, 799}, - dictWord{7, 0, 1972}, - dictWord{5, 10, 1017}, - dictWord{138, 10, 511}, - dictWord{135, 0, 1793}, - dictWord{7, 11, 1961}, - dictWord{7, 11, 1965}, - dictWord{8, 11, 702}, - dictWord{136, 11, 750}, - dictWord{8, 11, 150}, - dictWord{8, 11, 737}, - dictWord{140, 11, 366}, - dictWord{132, 0, 322}, - dictWord{133, 10, 709}, - dictWord{8, 11, 800}, - dictWord{9, 11, 148}, - dictWord{9, 11, 872}, - dictWord{ - 9, - 11, - 890, - }, - dictWord{11, 11, 309}, - dictWord{11, 11, 1001}, - dictWord{13, 11, 267}, - dictWord{141, 11, 323}, - dictWord{134, 10, 1745}, - dictWord{7, 0, 290}, - dictWord{136, 10, 206}, - dictWord{7, 0, 1651}, - dictWord{145, 0, 89}, - dictWord{139, 0, 2}, - dictWord{132, 0, 672}, - dictWord{6, 0, 1860}, - dictWord{8, 0, 905}, - dictWord{ - 10, - 0, - 844, - }, - dictWord{10, 0, 846}, - dictWord{10, 0, 858}, - dictWord{12, 0, 699}, - dictWord{12, 0, 746}, - dictWord{140, 0, 772}, - dictWord{135, 11, 424}, - dictWord{133, 11, 547}, - dictWord{133, 0, 737}, - dictWord{5, 11, 490}, - dictWord{6, 11, 615}, - dictWord{6, 11, 620}, - dictWord{135, 11, 683}, - dictWord{6, 0, 746}, - dictWord{134, 0, 1612}, - dictWord{132, 10, 776}, - dictWord{9, 11, 385}, - dictWord{149, 11, 17}, - dictWord{133, 0, 145}, - dictWord{135, 10, 1272}, - dictWord{ - 7, - 0, - 884, - }, - dictWord{140, 0, 124}, - dictWord{4, 0, 387}, - dictWord{135, 0, 1288}, - dictWord{5, 11, 133}, - dictWord{136, 10, 406}, - dictWord{136, 11, 187}, - dictWord{ - 6, - 0, - 679, - }, - dictWord{8, 11, 8}, - dictWord{138, 11, 0}, - dictWord{135, 0, 550}, - dictWord{135, 11, 798}, - dictWord{136, 11, 685}, - dictWord{7, 11, 1086}, - dictWord{145, 11, 46}, - dictWord{8, 10, 175}, - dictWord{10, 10, 168}, - dictWord{138, 10, 573}, - dictWord{135, 0, 1305}, - dictWord{4, 0, 576}, - dictWord{ - 135, - 0, - 1263, - }, - dictWord{6, 0, 686}, - dictWord{134, 0, 1563}, - dictWord{134, 0, 607}, - dictWord{5, 0, 919}, - dictWord{134, 0, 1673}, - dictWord{148, 0, 37}, - dictWord{ - 8, - 11, - 774, - }, - dictWord{10, 11, 670}, - dictWord{140, 11, 51}, - dictWord{133, 10, 784}, - dictWord{139, 10, 882}, - dictWord{4, 0, 82}, - dictWord{5, 0, 333}, - dictWord{ - 5, - 0, - 904, - }, - dictWord{6, 0, 207}, - dictWord{7, 0, 325}, - dictWord{7, 0, 1726}, - dictWord{8, 0, 101}, - dictWord{10, 0, 778}, - dictWord{139, 0, 220}, - dictWord{135, 11, 371}, - dictWord{132, 0, 958}, - dictWord{133, 0, 903}, - dictWord{4, 11, 127}, - dictWord{5, 11, 350}, - dictWord{6, 11, 356}, - dictWord{8, 11, 426}, - dictWord{9, 11, 572}, - dictWord{10, 11, 247}, - dictWord{139, 11, 312}, - dictWord{140, 0, 147}, - dictWord{6, 11, 59}, - dictWord{7, 11, 885}, - dictWord{9, 11, 603}, - dictWord{ - 141, - 11, - 397, - }, - dictWord{10, 0, 367}, - dictWord{9, 10, 14}, - dictWord{9, 10, 441}, - dictWord{139, 10, 9}, - dictWord{11, 10, 966}, - dictWord{12, 10, 287}, - dictWord{ - 13, - 10, - 342, - }, - dictWord{13, 10, 402}, - dictWord{15, 10, 110}, - dictWord{143, 10, 163}, - dictWord{134, 0, 690}, - dictWord{132, 0, 705}, - dictWord{9, 0, 651}, - dictWord{ - 11, - 0, - 971, - }, - dictWord{13, 0, 273}, - dictWord{7, 10, 1428}, - dictWord{7, 10, 1640}, - dictWord{7, 10, 1867}, - dictWord{9, 10, 169}, - dictWord{9, 10, 182}, - dictWord{ - 9, - 10, - 367, - }, - dictWord{9, 10, 478}, - dictWord{9, 10, 506}, - dictWord{9, 10, 551}, - dictWord{9, 10, 557}, - dictWord{9, 10, 648}, - dictWord{9, 10, 697}, - dictWord{ - 9, - 10, - 705, - }, - dictWord{9, 10, 725}, - dictWord{9, 10, 787}, - dictWord{9, 10, 794}, - dictWord{10, 10, 198}, - dictWord{10, 10, 214}, - dictWord{10, 10, 267}, - dictWord{ - 10, - 10, - 275, - }, - dictWord{10, 10, 456}, - dictWord{10, 10, 551}, - dictWord{10, 10, 561}, - dictWord{10, 10, 613}, - dictWord{10, 10, 627}, - dictWord{10, 10, 668}, - dictWord{10, 10, 675}, - dictWord{10, 10, 691}, - dictWord{10, 10, 695}, - dictWord{10, 10, 707}, - dictWord{10, 10, 715}, - dictWord{11, 10, 183}, - dictWord{ - 11, - 10, - 201, - }, - dictWord{11, 10, 262}, - dictWord{11, 10, 352}, - dictWord{11, 10, 439}, - dictWord{11, 10, 493}, - dictWord{11, 10, 572}, - dictWord{11, 10, 591}, - dictWord{ - 11, - 10, - 608, - }, - dictWord{11, 10, 611}, - dictWord{11, 10, 646}, - dictWord{11, 10, 674}, - dictWord{11, 10, 711}, - dictWord{11, 10, 751}, - dictWord{11, 10, 761}, - dictWord{11, 10, 776}, - dictWord{11, 10, 785}, - dictWord{11, 10, 850}, - dictWord{11, 10, 853}, - dictWord{11, 10, 862}, - dictWord{11, 10, 865}, - dictWord{ - 11, - 10, - 868, - }, - dictWord{11, 10, 875}, - dictWord{11, 10, 898}, - dictWord{11, 10, 902}, - dictWord{11, 10, 903}, - dictWord{11, 10, 910}, - dictWord{11, 10, 932}, - dictWord{ - 11, - 10, - 942, - }, - dictWord{11, 10, 957}, - dictWord{11, 10, 967}, - dictWord{11, 10, 972}, - dictWord{12, 10, 148}, - dictWord{12, 10, 195}, - dictWord{12, 10, 220}, - dictWord{12, 10, 237}, - dictWord{12, 10, 318}, - dictWord{12, 10, 339}, - dictWord{12, 10, 393}, - dictWord{12, 10, 445}, - dictWord{12, 10, 450}, - dictWord{ - 12, - 10, - 474, - }, - dictWord{12, 10, 505}, - dictWord{12, 10, 509}, - dictWord{12, 10, 533}, - dictWord{12, 10, 591}, - dictWord{12, 10, 594}, - dictWord{12, 10, 597}, - dictWord{ - 12, - 10, - 621, - }, - dictWord{12, 10, 633}, - dictWord{12, 10, 642}, - dictWord{13, 10, 59}, - dictWord{13, 10, 60}, - dictWord{13, 10, 145}, - dictWord{13, 10, 239}, - dictWord{13, 10, 250}, - dictWord{13, 10, 329}, - dictWord{13, 10, 344}, - dictWord{13, 10, 365}, - dictWord{13, 10, 372}, - dictWord{13, 10, 387}, - dictWord{ - 13, - 10, - 403, - }, - dictWord{13, 10, 414}, - dictWord{13, 10, 456}, - dictWord{13, 10, 470}, - dictWord{13, 10, 478}, - dictWord{13, 10, 483}, - dictWord{13, 10, 489}, - dictWord{ - 14, - 10, - 55, - }, - dictWord{14, 10, 57}, - dictWord{14, 10, 81}, - dictWord{14, 10, 90}, - dictWord{14, 10, 148}, - dictWord{14, 10, 239}, - dictWord{14, 10, 266}, - dictWord{ - 14, - 10, - 321, - }, - dictWord{14, 10, 326}, - dictWord{14, 10, 327}, - dictWord{14, 10, 330}, - dictWord{14, 10, 347}, - dictWord{14, 10, 355}, - dictWord{14, 10, 401}, - dictWord{14, 10, 404}, - dictWord{14, 10, 411}, - dictWord{14, 10, 414}, - dictWord{14, 10, 416}, - dictWord{14, 10, 420}, - dictWord{15, 10, 61}, - dictWord{ - 15, - 10, - 74, - }, - dictWord{15, 10, 87}, - dictWord{15, 10, 88}, - dictWord{15, 10, 94}, - dictWord{15, 10, 96}, - dictWord{15, 10, 116}, - dictWord{15, 10, 149}, - dictWord{ - 15, - 10, - 154, - }, - dictWord{16, 10, 50}, - dictWord{16, 10, 63}, - dictWord{16, 10, 73}, - dictWord{17, 10, 2}, - dictWord{17, 10, 66}, - dictWord{17, 10, 92}, - dictWord{17, 10, 103}, - dictWord{17, 10, 112}, - dictWord{17, 10, 120}, - dictWord{18, 10, 50}, - dictWord{18, 10, 54}, - dictWord{18, 10, 82}, - dictWord{18, 10, 86}, - dictWord{18, 10, 90}, - dictWord{18, 10, 111}, - dictWord{18, 10, 115}, - dictWord{18, 10, 156}, - dictWord{19, 10, 40}, - dictWord{19, 10, 79}, - dictWord{20, 10, 78}, - dictWord{149, 10, 22}, - dictWord{7, 0, 887}, - dictWord{5, 10, 161}, - dictWord{135, 10, 839}, - dictWord{142, 11, 98}, - dictWord{134, 0, 90}, - dictWord{138, 11, 356}, - dictWord{ - 135, - 11, - 441, - }, - dictWord{6, 11, 111}, - dictWord{7, 11, 4}, - dictWord{8, 11, 163}, - dictWord{8, 11, 776}, - dictWord{138, 11, 566}, - dictWord{134, 0, 908}, - dictWord{ - 134, - 0, - 1261, - }, - dictWord{7, 0, 813}, - dictWord{12, 0, 497}, - dictWord{141, 0, 56}, - dictWord{134, 0, 1235}, - dictWord{135, 0, 429}, - dictWord{135, 11, 1994}, - dictWord{138, 0, 904}, - dictWord{6, 0, 125}, - dictWord{7, 0, 1277}, - dictWord{137, 0, 772}, - dictWord{151, 0, 12}, - dictWord{4, 0, 841}, - dictWord{5, 0, 386}, - dictWord{ - 133, - 11, - 386, - }, - dictWord{5, 11, 297}, - dictWord{135, 11, 1038}, - dictWord{6, 0, 860}, - dictWord{6, 0, 1069}, - dictWord{135, 11, 309}, - dictWord{136, 0, 946}, - dictWord{135, 10, 1814}, - dictWord{141, 11, 418}, - dictWord{136, 11, 363}, - dictWord{10, 0, 768}, - dictWord{139, 0, 787}, - dictWord{22, 11, 30}, - dictWord{ - 150, - 11, - 33, - }, - dictWord{6, 0, 160}, - dictWord{7, 0, 1106}, - dictWord{9, 0, 770}, - dictWord{11, 0, 112}, - dictWord{140, 0, 413}, - dictWord{11, 11, 216}, - dictWord{ - 139, - 11, - 340, - }, - dictWord{136, 10, 139}, - dictWord{135, 11, 1390}, - dictWord{135, 11, 808}, - dictWord{132, 11, 280}, - dictWord{12, 0, 271}, - dictWord{17, 0, 109}, - dictWord{7, 10, 643}, - dictWord{136, 10, 236}, - dictWord{140, 11, 54}, - dictWord{4, 11, 421}, - dictWord{133, 11, 548}, - dictWord{11, 0, 719}, - dictWord{12, 0, 36}, - dictWord{141, 0, 337}, - dictWord{7, 0, 581}, - dictWord{9, 0, 644}, - dictWord{137, 0, 699}, - dictWord{11, 11, 511}, - dictWord{13, 11, 394}, - dictWord{14, 11, 298}, - dictWord{14, 11, 318}, - dictWord{146, 11, 103}, - dictWord{7, 0, 304}, - dictWord{9, 0, 646}, - dictWord{9, 0, 862}, - dictWord{11, 0, 696}, - dictWord{12, 0, 208}, - dictWord{15, 0, 79}, - dictWord{147, 0, 108}, - dictWord{4, 0, 631}, - dictWord{7, 0, 1126}, - dictWord{135, 0, 1536}, - dictWord{135, 11, 1527}, - dictWord{8, 0, 880}, - dictWord{10, 0, 869}, - dictWord{138, 0, 913}, - dictWord{7, 0, 1513}, - dictWord{5, 10, 54}, - dictWord{6, 11, 254}, - dictWord{9, 11, 109}, - dictWord{138, 11, 103}, - dictWord{135, 0, 981}, - dictWord{133, 11, 729}, - dictWord{132, 10, 744}, - dictWord{132, 0, 434}, - dictWord{134, 0, 550}, - dictWord{7, 0, 930}, - dictWord{10, 0, 476}, - dictWord{13, 0, 452}, - dictWord{19, 0, 104}, - dictWord{6, 11, 1630}, - dictWord{10, 10, 402}, - dictWord{146, 10, 55}, - dictWord{5, 0, 553}, - dictWord{138, 0, 824}, - dictWord{136, 0, 452}, - dictWord{8, 0, 151}, - dictWord{137, 10, 624}, - dictWord{132, 10, 572}, - dictWord{132, 0, 772}, - dictWord{133, 11, 671}, - dictWord{ - 133, - 0, - 292, - }, - dictWord{138, 0, 135}, - dictWord{132, 11, 889}, - dictWord{140, 11, 207}, - dictWord{9, 0, 504}, - dictWord{6, 10, 43}, - dictWord{7, 10, 38}, - dictWord{ - 8, - 10, - 248, - }, - dictWord{138, 10, 513}, - dictWord{6, 0, 1089}, - dictWord{135, 11, 1910}, - dictWord{4, 11, 627}, - dictWord{133, 11, 775}, - dictWord{135, 0, 783}, - dictWord{133, 10, 766}, - dictWord{133, 10, 363}, - dictWord{7, 0, 387}, - dictWord{135, 11, 387}, - dictWord{7, 0, 393}, - dictWord{10, 0, 603}, - dictWord{11, 0, 206}, - dictWord{7, 11, 202}, - dictWord{11, 11, 362}, - dictWord{11, 11, 948}, - dictWord{140, 11, 388}, - dictWord{6, 11, 507}, - dictWord{7, 11, 451}, - dictWord{8, 11, 389}, - dictWord{12, 11, 490}, - dictWord{13, 11, 16}, - dictWord{13, 11, 215}, - dictWord{13, 11, 351}, - dictWord{18, 11, 132}, - dictWord{147, 11, 125}, - dictWord{ - 4, - 0, - 912, - }, - dictWord{9, 0, 232}, - dictWord{135, 11, 841}, - dictWord{6, 10, 258}, - dictWord{140, 10, 409}, - dictWord{5, 10, 249}, - dictWord{148, 10, 82}, - dictWord{ - 136, - 11, - 566, - }, - dictWord{6, 0, 977}, - dictWord{135, 11, 1214}, - dictWord{7, 0, 1973}, - dictWord{136, 0, 716}, - dictWord{135, 0, 98}, - dictWord{133, 0, 733}, - dictWord{ - 5, - 11, - 912, - }, - dictWord{134, 11, 1695}, - dictWord{5, 10, 393}, - dictWord{6, 10, 378}, - dictWord{7, 10, 1981}, - dictWord{9, 10, 32}, - dictWord{9, 10, 591}, - dictWord{10, 10, 685}, - dictWord{10, 10, 741}, - dictWord{142, 10, 382}, - dictWord{133, 10, 788}, - dictWord{10, 0, 19}, - dictWord{11, 0, 911}, - dictWord{7, 10, 1968}, - dictWord{141, 10, 509}, - dictWord{5, 0, 668}, - dictWord{5, 11, 236}, - dictWord{6, 11, 572}, - dictWord{8, 11, 492}, - dictWord{11, 11, 618}, - dictWord{144, 11, 56}, - dictWord{135, 11, 1789}, - dictWord{4, 0, 360}, - dictWord{5, 0, 635}, - dictWord{5, 0, 700}, - dictWord{5, 10, 58}, - dictWord{5, 10, 171}, - dictWord{5, 10, 683}, - dictWord{ - 6, - 10, - 291, - }, - dictWord{6, 10, 566}, - dictWord{7, 10, 1650}, - dictWord{11, 10, 523}, - dictWord{12, 10, 273}, - dictWord{12, 10, 303}, - dictWord{15, 10, 39}, - dictWord{143, 10, 111}, - dictWord{133, 0, 901}, - dictWord{134, 10, 589}, - dictWord{5, 11, 190}, - dictWord{136, 11, 318}, - dictWord{140, 0, 656}, - dictWord{ - 7, - 0, - 726, - }, - dictWord{152, 0, 9}, - dictWord{4, 10, 917}, - dictWord{133, 10, 1005}, - dictWord{135, 10, 1598}, - dictWord{134, 11, 491}, - dictWord{4, 10, 919}, - dictWord{133, 11, 434}, - dictWord{137, 0, 72}, - dictWord{6, 0, 1269}, - dictWord{6, 0, 1566}, - dictWord{134, 0, 1621}, - dictWord{9, 0, 463}, - dictWord{10, 0, 595}, - dictWord{4, 10, 255}, - dictWord{5, 10, 302}, - dictWord{6, 10, 132}, - dictWord{7, 10, 128}, - dictWord{7, 10, 283}, - dictWord{7, 10, 1299}, - dictWord{10, 10, 52}, - dictWord{ - 10, - 10, - 514, - }, - dictWord{11, 10, 925}, - dictWord{13, 10, 92}, - dictWord{142, 10, 309}, - dictWord{135, 0, 1454}, - dictWord{134, 0, 1287}, - dictWord{11, 0, 600}, - dictWord{13, 0, 245}, - dictWord{137, 10, 173}, - dictWord{136, 0, 989}, - dictWord{7, 0, 164}, - dictWord{7, 0, 1571}, - dictWord{9, 0, 107}, - dictWord{140, 0, 225}, - dictWord{6, 0, 1061}, - dictWord{141, 10, 442}, - dictWord{4, 0, 27}, - dictWord{5, 0, 484}, - dictWord{5, 0, 510}, - dictWord{6, 0, 434}, - dictWord{7, 0, 1000}, - dictWord{ - 7, - 0, - 1098, - }, - dictWord{136, 0, 2}, - dictWord{7, 11, 85}, - dictWord{7, 11, 247}, - dictWord{8, 11, 585}, - dictWord{10, 11, 163}, - dictWord{138, 11, 316}, - dictWord{ - 11, - 11, - 103, - }, - dictWord{142, 11, 0}, - dictWord{134, 0, 1127}, - dictWord{4, 0, 460}, - dictWord{134, 0, 852}, - dictWord{134, 10, 210}, - dictWord{4, 0, 932}, - dictWord{ - 133, - 0, - 891, - }, - dictWord{6, 0, 588}, - dictWord{147, 11, 83}, - dictWord{8, 0, 625}, - dictWord{4, 10, 284}, - dictWord{134, 10, 223}, - dictWord{134, 0, 76}, - dictWord{8, 0, 92}, - dictWord{137, 0, 221}, - dictWord{4, 11, 124}, - dictWord{10, 11, 457}, - dictWord{11, 11, 121}, - dictWord{11, 11, 169}, - dictWord{11, 11, 422}, - dictWord{ - 11, - 11, - 870, - }, - dictWord{12, 11, 214}, - dictWord{13, 11, 389}, - dictWord{14, 11, 187}, - dictWord{143, 11, 77}, - dictWord{9, 11, 618}, - dictWord{138, 11, 482}, - dictWord{ - 4, - 10, - 218, - }, - dictWord{7, 10, 526}, - dictWord{143, 10, 137}, - dictWord{13, 0, 9}, - dictWord{14, 0, 104}, - dictWord{14, 0, 311}, - dictWord{4, 10, 270}, - dictWord{ - 5, - 10, - 192, - }, - dictWord{6, 10, 332}, - dictWord{135, 10, 1322}, - dictWord{140, 10, 661}, - dictWord{135, 11, 1193}, - dictWord{6, 11, 107}, - dictWord{7, 11, 638}, - dictWord{7, 11, 1632}, - dictWord{137, 11, 396}, - dictWord{132, 0, 763}, - dictWord{4, 0, 622}, - dictWord{5, 11, 370}, - dictWord{134, 11, 1756}, - dictWord{ - 133, - 0, - 253, - }, - dictWord{135, 0, 546}, - dictWord{9, 0, 73}, - dictWord{10, 0, 110}, - dictWord{14, 0, 185}, - dictWord{17, 0, 119}, - dictWord{133, 11, 204}, - dictWord{7, 0, 624}, - dictWord{7, 0, 916}, - dictWord{10, 0, 256}, - dictWord{139, 0, 87}, - dictWord{7, 10, 379}, - dictWord{8, 10, 481}, - dictWord{137, 10, 377}, - dictWord{5, 0, 212}, - dictWord{12, 0, 35}, - dictWord{13, 0, 382}, - dictWord{5, 11, 970}, - dictWord{134, 11, 1706}, - dictWord{9, 0, 746}, - dictWord{5, 10, 1003}, - dictWord{134, 10, 149}, - dictWord{10, 0, 150}, - dictWord{11, 0, 849}, - dictWord{13, 0, 330}, - dictWord{8, 10, 262}, - dictWord{9, 10, 627}, - dictWord{11, 10, 214}, - dictWord{11, 10, 404}, - dictWord{11, 10, 457}, - dictWord{11, 10, 780}, - dictWord{11, 10, 913}, - dictWord{13, 10, 401}, - dictWord{142, 10, 200}, - dictWord{134, 0, 1466}, - dictWord{ - 135, - 11, - 3, - }, - dictWord{6, 0, 1299}, - dictWord{4, 11, 35}, - dictWord{5, 11, 121}, - dictWord{5, 11, 483}, - dictWord{5, 11, 685}, - dictWord{6, 11, 489}, - dictWord{7, 11, 1204}, - dictWord{136, 11, 394}, - dictWord{135, 10, 742}, - dictWord{4, 10, 142}, - dictWord{136, 10, 304}, - dictWord{4, 11, 921}, - dictWord{133, 11, 1007}, - dictWord{ - 134, - 0, - 1518, - }, - dictWord{6, 0, 1229}, - dictWord{135, 0, 1175}, - dictWord{133, 0, 816}, - dictWord{12, 0, 159}, - dictWord{4, 10, 471}, - dictWord{4, 11, 712}, - dictWord{ - 5, - 10, - 51, - }, - dictWord{6, 10, 602}, - dictWord{7, 10, 925}, - dictWord{8, 10, 484}, - dictWord{138, 10, 195}, - dictWord{134, 11, 1629}, - dictWord{5, 0, 869}, - dictWord{ - 5, - 0, - 968, - }, - dictWord{6, 0, 1626}, - dictWord{8, 0, 734}, - dictWord{136, 0, 784}, - dictWord{4, 0, 542}, - dictWord{6, 0, 1716}, - dictWord{6, 0, 1727}, - dictWord{ - 7, - 0, - 1082, - }, - dictWord{7, 0, 1545}, - dictWord{8, 0, 56}, - dictWord{8, 0, 118}, - dictWord{8, 0, 412}, - dictWord{8, 0, 564}, - dictWord{9, 0, 888}, - dictWord{9, 0, 908}, - dictWord{ - 10, - 0, - 50, - }, - dictWord{10, 0, 423}, - dictWord{11, 0, 685}, - dictWord{11, 0, 697}, - dictWord{11, 0, 933}, - dictWord{12, 0, 299}, - dictWord{13, 0, 126}, - dictWord{ - 13, - 0, - 136, - }, - dictWord{13, 0, 170}, - dictWord{13, 0, 190}, - dictWord{136, 10, 688}, - dictWord{132, 10, 697}, - dictWord{4, 0, 232}, - dictWord{9, 0, 202}, - dictWord{ - 10, - 0, - 474, - }, - dictWord{140, 0, 433}, - dictWord{136, 0, 212}, - dictWord{6, 0, 108}, - dictWord{7, 0, 1003}, - dictWord{7, 0, 1181}, - dictWord{8, 0, 111}, - dictWord{ - 136, - 0, - 343, - }, - dictWord{5, 10, 221}, - dictWord{135, 11, 1255}, - dictWord{133, 11, 485}, - dictWord{134, 0, 1712}, - dictWord{142, 0, 216}, - dictWord{5, 0, 643}, - dictWord{ - 6, - 0, - 516, - }, - dictWord{4, 11, 285}, - dictWord{5, 11, 317}, - dictWord{6, 11, 301}, - dictWord{7, 11, 7}, - dictWord{8, 11, 153}, - dictWord{10, 11, 766}, - dictWord{ - 11, - 11, - 468, - }, - dictWord{12, 11, 467}, - dictWord{141, 11, 143}, - dictWord{4, 0, 133}, - dictWord{7, 0, 711}, - dictWord{7, 0, 1298}, - dictWord{135, 0, 1585}, - dictWord{ - 134, - 0, - 650, - }, - dictWord{135, 11, 512}, - dictWord{6, 0, 99}, - dictWord{7, 0, 1808}, - dictWord{145, 0, 57}, - dictWord{6, 0, 246}, - dictWord{6, 0, 574}, - dictWord{7, 0, 428}, - dictWord{9, 0, 793}, - dictWord{10, 0, 669}, - dictWord{11, 0, 485}, - dictWord{11, 0, 840}, - dictWord{12, 0, 300}, - dictWord{14, 0, 250}, - dictWord{145, 0, 55}, - dictWord{ - 4, - 10, - 132, - }, - dictWord{5, 10, 69}, - dictWord{135, 10, 1242}, - dictWord{136, 0, 1023}, - dictWord{7, 0, 302}, - dictWord{132, 10, 111}, - dictWord{135, 0, 1871}, - dictWord{132, 0, 728}, - dictWord{9, 0, 252}, - dictWord{132, 10, 767}, - dictWord{6, 0, 461}, - dictWord{7, 0, 1590}, - dictWord{7, 10, 1416}, - dictWord{7, 10, 2005}, - dictWord{8, 10, 131}, - dictWord{8, 10, 466}, - dictWord{9, 10, 672}, - dictWord{13, 10, 252}, - dictWord{148, 10, 103}, - dictWord{6, 0, 323}, - dictWord{135, 0, 1564}, - dictWord{7, 0, 461}, - dictWord{136, 0, 775}, - dictWord{6, 10, 44}, - dictWord{136, 10, 368}, - dictWord{139, 0, 172}, - dictWord{132, 0, 464}, - dictWord{4, 10, 570}, - dictWord{133, 10, 120}, - dictWord{137, 11, 269}, - dictWord{6, 10, 227}, - dictWord{135, 10, 1589}, - dictWord{6, 11, 1719}, - dictWord{6, 11, 1735}, - dictWord{ - 7, - 11, - 2016, - }, - dictWord{7, 11, 2020}, - dictWord{8, 11, 837}, - dictWord{137, 11, 852}, - dictWord{7, 0, 727}, - dictWord{146, 0, 73}, - dictWord{132, 0, 1023}, - dictWord{135, 11, 852}, - dictWord{135, 10, 1529}, - dictWord{136, 0, 577}, - dictWord{138, 11, 568}, - dictWord{134, 0, 1037}, - dictWord{8, 11, 67}, - dictWord{ - 138, - 11, - 419, - }, - dictWord{4, 0, 413}, - dictWord{5, 0, 677}, - dictWord{8, 0, 432}, - dictWord{140, 0, 280}, - dictWord{10, 0, 600}, - dictWord{6, 10, 1667}, - dictWord{ - 7, - 11, - 967, - }, - dictWord{7, 10, 2036}, - dictWord{141, 11, 11}, - dictWord{6, 10, 511}, - dictWord{140, 10, 132}, - dictWord{6, 0, 799}, - dictWord{5, 10, 568}, - dictWord{ - 6, - 10, - 138, - }, - dictWord{135, 10, 1293}, - dictWord{8, 0, 159}, - dictWord{4, 10, 565}, - dictWord{136, 10, 827}, - dictWord{7, 0, 646}, - dictWord{7, 0, 1730}, - dictWord{ - 11, - 0, - 446, - }, - dictWord{141, 0, 178}, - dictWord{4, 10, 922}, - dictWord{133, 10, 1023}, - dictWord{135, 11, 11}, - dictWord{132, 0, 395}, - dictWord{11, 0, 145}, - dictWord{135, 10, 1002}, - dictWord{9, 0, 174}, - dictWord{10, 0, 164}, - dictWord{11, 0, 440}, - dictWord{11, 0, 514}, - dictWord{11, 0, 841}, - dictWord{15, 0, 98}, - dictWord{149, 0, 20}, - dictWord{134, 0, 426}, - dictWord{10, 0, 608}, - dictWord{139, 0, 1002}, - dictWord{7, 11, 320}, - dictWord{8, 11, 51}, - dictWord{12, 11, 481}, - dictWord{12, 11, 570}, - dictWord{148, 11, 106}, - dictWord{9, 0, 977}, - dictWord{9, 0, 983}, - dictWord{132, 11, 445}, - dictWord{138, 0, 250}, - dictWord{139, 0, 100}, - dictWord{6, 0, 1982}, - dictWord{136, 10, 402}, - dictWord{133, 11, 239}, - dictWord{4, 10, 716}, - dictWord{141, 10, 31}, - dictWord{5, 0, 476}, - dictWord{7, 11, 83}, - dictWord{7, 11, 1990}, - dictWord{8, 11, 130}, - dictWord{139, 11, 720}, - dictWord{8, 10, 691}, - dictWord{136, 10, 731}, - dictWord{5, 11, 123}, - dictWord{ - 6, - 11, - 530, - }, - dictWord{7, 11, 348}, - dictWord{135, 11, 1419}, - dictWord{5, 0, 76}, - dictWord{6, 0, 458}, - dictWord{6, 0, 497}, - dictWord{7, 0, 868}, - dictWord{9, 0, 658}, - dictWord{10, 0, 594}, - dictWord{11, 0, 173}, - dictWord{11, 0, 566}, - dictWord{12, 0, 20}, - dictWord{12, 0, 338}, - dictWord{141, 0, 200}, - dictWord{9, 11, 139}, - dictWord{ - 10, - 11, - 399, - }, - dictWord{11, 11, 469}, - dictWord{12, 11, 634}, - dictWord{141, 11, 223}, - dictWord{9, 10, 840}, - dictWord{138, 10, 803}, - dictWord{133, 10, 847}, - dictWord{11, 11, 223}, - dictWord{140, 11, 168}, - dictWord{132, 11, 210}, - dictWord{8, 0, 447}, - dictWord{9, 10, 53}, - dictWord{9, 10, 268}, - dictWord{9, 10, 901}, - dictWord{10, 10, 518}, - dictWord{10, 10, 829}, - dictWord{11, 10, 188}, - dictWord{13, 10, 74}, - dictWord{14, 10, 46}, - dictWord{15, 10, 17}, - dictWord{15, 10, 33}, - dictWord{17, 10, 40}, - dictWord{18, 10, 36}, - dictWord{19, 10, 20}, - dictWord{22, 10, 1}, - dictWord{152, 10, 2}, - dictWord{4, 0, 526}, - dictWord{7, 0, 1029}, - dictWord{135, 0, 1054}, - dictWord{19, 11, 59}, - dictWord{150, 11, 2}, - dictWord{4, 0, 636}, - dictWord{6, 0, 1875}, - dictWord{6, 0, 1920}, - dictWord{9, 0, 999}, - dictWord{ - 12, - 0, - 807, - }, - dictWord{12, 0, 825}, - dictWord{15, 0, 179}, - dictWord{15, 0, 190}, - dictWord{18, 0, 182}, - dictWord{136, 10, 532}, - dictWord{6, 0, 1699}, - dictWord{ - 7, - 0, - 660, - }, - dictWord{7, 0, 1124}, - dictWord{17, 0, 31}, - dictWord{19, 0, 22}, - dictWord{151, 0, 14}, - dictWord{135, 10, 681}, - dictWord{132, 11, 430}, - dictWord{ - 140, - 10, - 677, - }, - dictWord{4, 10, 684}, - dictWord{136, 10, 384}, - dictWord{132, 11, 756}, - dictWord{133, 11, 213}, - dictWord{7, 0, 188}, - dictWord{7, 10, 110}, - dictWord{ - 8, - 10, - 290, - }, - dictWord{8, 10, 591}, - dictWord{9, 10, 382}, - dictWord{9, 10, 649}, - dictWord{11, 10, 71}, - dictWord{11, 10, 155}, - dictWord{11, 10, 313}, - dictWord{ - 12, - 10, - 5, - }, - dictWord{13, 10, 325}, - dictWord{142, 10, 287}, - dictWord{7, 10, 360}, - dictWord{7, 10, 425}, - dictWord{9, 10, 66}, - dictWord{9, 10, 278}, - dictWord{ - 138, - 10, - 644, - }, - dictWord{142, 11, 164}, - dictWord{4, 0, 279}, - dictWord{7, 0, 301}, - dictWord{137, 0, 362}, - dictWord{134, 11, 586}, - dictWord{135, 0, 1743}, - dictWord{4, 0, 178}, - dictWord{133, 0, 399}, - dictWord{4, 10, 900}, - dictWord{133, 10, 861}, - dictWord{5, 10, 254}, - dictWord{7, 10, 985}, - dictWord{136, 10, 73}, - dictWord{133, 11, 108}, - dictWord{7, 10, 1959}, - dictWord{136, 10, 683}, - dictWord{133, 11, 219}, - dictWord{4, 11, 193}, - dictWord{5, 11, 916}, - dictWord{ - 7, - 11, - 364, - }, - dictWord{10, 11, 398}, - dictWord{10, 11, 726}, - dictWord{11, 11, 317}, - dictWord{11, 11, 626}, - dictWord{12, 11, 142}, - dictWord{12, 11, 288}, - dictWord{ - 12, - 11, - 678, - }, - dictWord{13, 11, 313}, - dictWord{15, 11, 113}, - dictWord{18, 11, 114}, - dictWord{21, 11, 30}, - dictWord{150, 11, 53}, - dictWord{6, 11, 241}, - dictWord{7, 11, 907}, - dictWord{8, 11, 832}, - dictWord{9, 11, 342}, - dictWord{10, 11, 729}, - dictWord{11, 11, 284}, - dictWord{11, 11, 445}, - dictWord{11, 11, 651}, - dictWord{11, 11, 863}, - dictWord{13, 11, 398}, - dictWord{146, 11, 99}, - dictWord{132, 0, 872}, - dictWord{134, 0, 831}, - dictWord{134, 0, 1692}, - dictWord{ - 6, - 0, - 202, - }, - dictWord{6, 0, 1006}, - dictWord{9, 0, 832}, - dictWord{10, 0, 636}, - dictWord{11, 0, 208}, - dictWord{12, 0, 360}, - dictWord{17, 0, 118}, - dictWord{18, 0, 27}, - dictWord{20, 0, 67}, - dictWord{137, 11, 734}, - dictWord{132, 10, 725}, - dictWord{7, 11, 993}, - dictWord{138, 11, 666}, - dictWord{134, 0, 1954}, - dictWord{ - 134, - 10, - 196, - }, - dictWord{7, 0, 872}, - dictWord{10, 0, 516}, - dictWord{139, 0, 167}, - dictWord{133, 10, 831}, - dictWord{4, 11, 562}, - dictWord{9, 11, 254}, - dictWord{ - 139, - 11, - 879, - }, - dictWord{137, 0, 313}, - dictWord{4, 0, 224}, - dictWord{132, 11, 786}, - dictWord{11, 0, 24}, - dictWord{12, 0, 170}, - dictWord{136, 10, 723}, - dictWord{ - 5, - 0, - 546, - }, - dictWord{7, 0, 35}, - dictWord{8, 0, 11}, - dictWord{8, 0, 12}, - dictWord{9, 0, 315}, - dictWord{9, 0, 533}, - dictWord{10, 0, 802}, - dictWord{11, 0, 166}, - dictWord{ - 12, - 0, - 525, - }, - dictWord{142, 0, 243}, - dictWord{7, 0, 1937}, - dictWord{13, 10, 80}, - dictWord{13, 10, 437}, - dictWord{145, 10, 74}, - dictWord{5, 0, 241}, - dictWord{ - 8, - 0, - 242, - }, - dictWord{9, 0, 451}, - dictWord{10, 0, 667}, - dictWord{11, 0, 598}, - dictWord{140, 0, 429}, - dictWord{150, 0, 46}, - dictWord{6, 0, 1273}, - dictWord{ - 137, - 0, - 830, - }, - dictWord{5, 10, 848}, - dictWord{6, 10, 66}, - dictWord{136, 10, 764}, - dictWord{6, 0, 825}, - dictWord{134, 0, 993}, - dictWord{4, 0, 1006}, - dictWord{ - 10, - 0, - 327, - }, - dictWord{13, 0, 271}, - dictWord{4, 10, 36}, - dictWord{7, 10, 1387}, - dictWord{139, 10, 755}, - dictWord{134, 0, 1023}, - dictWord{135, 0, 1580}, - dictWord{ - 4, - 0, - 366, - }, - dictWord{137, 0, 516}, - dictWord{132, 10, 887}, - dictWord{6, 0, 1736}, - dictWord{135, 0, 1891}, - dictWord{6, 11, 216}, - dictWord{7, 11, 901}, - dictWord{ - 7, - 11, - 1343, - }, - dictWord{136, 11, 493}, - dictWord{6, 10, 165}, - dictWord{138, 10, 388}, - dictWord{7, 11, 341}, - dictWord{139, 11, 219}, - dictWord{4, 10, 719}, - dictWord{135, 10, 155}, - dictWord{134, 0, 1935}, - dictWord{132, 0, 826}, - dictWord{6, 0, 331}, - dictWord{6, 0, 1605}, - dictWord{8, 0, 623}, - dictWord{11, 0, 139}, - dictWord{139, 0, 171}, - dictWord{135, 11, 1734}, - dictWord{10, 11, 115}, - dictWord{11, 11, 420}, - dictWord{12, 11, 154}, - dictWord{13, 11, 404}, - dictWord{ - 14, - 11, - 346, - }, - dictWord{15, 11, 54}, - dictWord{143, 11, 112}, - dictWord{7, 0, 288}, - dictWord{4, 10, 353}, - dictWord{6, 10, 146}, - dictWord{6, 10, 1789}, - dictWord{ - 7, - 10, - 990, - }, - dictWord{7, 10, 1348}, - dictWord{9, 10, 665}, - dictWord{9, 10, 898}, - dictWord{11, 10, 893}, - dictWord{142, 10, 212}, - dictWord{6, 0, 916}, - dictWord{134, 0, 1592}, - dictWord{7, 0, 1888}, - dictWord{4, 10, 45}, - dictWord{135, 10, 1257}, - dictWord{5, 11, 1011}, - dictWord{136, 11, 701}, - dictWord{ - 139, - 11, - 596, - }, - dictWord{4, 11, 54}, - dictWord{5, 11, 666}, - dictWord{7, 11, 1039}, - dictWord{7, 11, 1130}, - dictWord{9, 11, 195}, - dictWord{138, 11, 302}, - dictWord{ - 134, - 0, - 1471, - }, - dictWord{134, 0, 1570}, - dictWord{132, 0, 394}, - dictWord{140, 10, 65}, - dictWord{136, 10, 816}, - dictWord{135, 0, 1931}, - dictWord{7, 0, 574}, - dictWord{135, 0, 1719}, - dictWord{134, 11, 467}, - dictWord{132, 0, 658}, - dictWord{9, 0, 781}, - dictWord{10, 0, 144}, - dictWord{11, 0, 385}, - dictWord{13, 0, 161}, - dictWord{13, 0, 228}, - dictWord{13, 0, 268}, - dictWord{20, 0, 107}, - dictWord{134, 11, 1669}, - dictWord{136, 0, 374}, - dictWord{135, 0, 735}, - dictWord{4, 0, 344}, - dictWord{6, 0, 498}, - dictWord{139, 0, 323}, - dictWord{7, 0, 586}, - dictWord{7, 0, 1063}, - dictWord{6, 10, 559}, - dictWord{134, 10, 1691}, - dictWord{137, 0, 155}, - dictWord{133, 0, 906}, - dictWord{7, 11, 122}, - dictWord{9, 11, 259}, - dictWord{10, 11, 84}, - dictWord{11, 11, 470}, - dictWord{12, 11, 541}, - dictWord{ - 141, - 11, - 379, - }, - dictWord{134, 0, 1139}, - dictWord{10, 0, 108}, - dictWord{139, 0, 116}, - dictWord{134, 10, 456}, - dictWord{133, 10, 925}, - dictWord{5, 11, 82}, - dictWord{ - 5, - 11, - 131, - }, - dictWord{7, 11, 1755}, - dictWord{8, 11, 31}, - dictWord{9, 11, 168}, - dictWord{9, 11, 764}, - dictWord{139, 11, 869}, - dictWord{134, 11, 605}, - dictWord{ - 5, - 11, - 278, - }, - dictWord{137, 11, 68}, - dictWord{4, 11, 163}, - dictWord{5, 11, 201}, - dictWord{5, 11, 307}, - dictWord{5, 11, 310}, - dictWord{6, 11, 335}, - dictWord{ - 7, - 11, - 284, - }, - dictWord{136, 11, 165}, - dictWord{135, 11, 1660}, - dictWord{6, 11, 33}, - dictWord{135, 11, 1244}, - dictWord{4, 0, 616}, - dictWord{136, 11, 483}, - dictWord{8, 0, 857}, - dictWord{8, 0, 902}, - dictWord{8, 0, 910}, - dictWord{10, 0, 879}, - dictWord{12, 0, 726}, - dictWord{4, 11, 199}, - dictWord{139, 11, 34}, - dictWord{136, 0, 692}, - dictWord{6, 10, 193}, - dictWord{7, 10, 240}, - dictWord{7, 10, 1682}, - dictWord{10, 10, 51}, - dictWord{10, 10, 640}, - dictWord{11, 10, 410}, - dictWord{13, 10, 82}, - dictWord{14, 10, 247}, - dictWord{14, 10, 331}, - dictWord{142, 10, 377}, - dictWord{6, 0, 823}, - dictWord{134, 0, 983}, - dictWord{ - 139, - 10, - 411, - }, - dictWord{132, 0, 305}, - dictWord{136, 10, 633}, - dictWord{138, 11, 203}, - dictWord{134, 0, 681}, - dictWord{6, 11, 326}, - dictWord{7, 11, 677}, - dictWord{137, 11, 425}, - dictWord{5, 0, 214}, - dictWord{7, 0, 603}, - dictWord{8, 0, 611}, - dictWord{9, 0, 686}, - dictWord{10, 0, 88}, - dictWord{11, 0, 459}, - dictWord{ - 11, - 0, - 496, - }, - dictWord{12, 0, 463}, - dictWord{12, 0, 590}, - dictWord{141, 0, 0}, - dictWord{136, 0, 1004}, - dictWord{142, 0, 23}, - dictWord{134, 0, 1703}, - dictWord{ - 147, - 11, - 8, - }, - dictWord{145, 11, 56}, - dictWord{135, 0, 1443}, - dictWord{4, 10, 237}, - dictWord{135, 10, 514}, - dictWord{6, 0, 714}, - dictWord{145, 0, 19}, - dictWord{ - 5, - 11, - 358, - }, - dictWord{7, 11, 473}, - dictWord{7, 11, 1184}, - dictWord{10, 11, 662}, - dictWord{13, 11, 212}, - dictWord{13, 11, 304}, - dictWord{13, 11, 333}, - dictWord{145, 11, 98}, - dictWord{4, 0, 737}, - dictWord{10, 0, 98}, - dictWord{11, 0, 294}, - dictWord{12, 0, 60}, - dictWord{12, 0, 437}, - dictWord{13, 0, 64}, - dictWord{ - 13, - 0, - 380, - }, - dictWord{142, 0, 430}, - dictWord{6, 10, 392}, - dictWord{7, 10, 65}, - dictWord{135, 10, 2019}, - dictWord{6, 0, 1758}, - dictWord{8, 0, 520}, - dictWord{ - 9, - 0, - 345, - }, - dictWord{9, 0, 403}, - dictWord{142, 0, 350}, - dictWord{5, 0, 47}, - dictWord{10, 0, 242}, - dictWord{138, 0, 579}, - dictWord{5, 0, 139}, - dictWord{7, 0, 1168}, - dictWord{138, 0, 539}, - dictWord{134, 0, 1459}, - dictWord{13, 0, 388}, - dictWord{141, 11, 388}, - dictWord{134, 0, 253}, - dictWord{7, 10, 1260}, - dictWord{ - 135, - 10, - 1790, - }, - dictWord{10, 0, 252}, - dictWord{9, 10, 222}, - dictWord{139, 10, 900}, - dictWord{140, 0, 745}, - dictWord{133, 11, 946}, - dictWord{4, 0, 107}, - dictWord{ - 7, - 0, - 613, - }, - dictWord{8, 0, 439}, - dictWord{8, 0, 504}, - dictWord{9, 0, 501}, - dictWord{10, 0, 383}, - dictWord{139, 0, 477}, - dictWord{135, 11, 1485}, - dictWord{ - 132, - 0, - 871, - }, - dictWord{7, 11, 411}, - dictWord{7, 11, 590}, - dictWord{8, 11, 631}, - dictWord{9, 11, 323}, - dictWord{10, 11, 355}, - dictWord{11, 11, 491}, - dictWord{ - 12, - 11, - 143, - }, - dictWord{12, 11, 402}, - dictWord{13, 11, 73}, - dictWord{14, 11, 408}, - dictWord{15, 11, 107}, - dictWord{146, 11, 71}, - dictWord{132, 0, 229}, - dictWord{132, 0, 903}, - dictWord{140, 0, 71}, - dictWord{133, 0, 549}, - dictWord{4, 0, 47}, - dictWord{6, 0, 373}, - dictWord{7, 0, 452}, - dictWord{7, 0, 543}, - dictWord{ - 7, - 0, - 1828, - }, - dictWord{7, 0, 1856}, - dictWord{9, 0, 6}, - dictWord{11, 0, 257}, - dictWord{139, 0, 391}, - dictWord{7, 11, 1467}, - dictWord{8, 11, 328}, - dictWord{ - 10, - 11, - 544, - }, - dictWord{11, 11, 955}, - dictWord{13, 11, 320}, - dictWord{145, 11, 83}, - dictWord{5, 0, 980}, - dictWord{134, 0, 1754}, - dictWord{136, 0, 865}, - dictWord{ - 5, - 0, - 705, - }, - dictWord{137, 0, 606}, - dictWord{7, 0, 161}, - dictWord{8, 10, 201}, - dictWord{136, 10, 605}, - dictWord{143, 11, 35}, - dictWord{5, 11, 835}, - dictWord{ - 6, - 11, - 483, - }, - dictWord{140, 10, 224}, - dictWord{7, 0, 536}, - dictWord{7, 0, 1331}, - dictWord{136, 0, 143}, - dictWord{134, 0, 1388}, - dictWord{5, 0, 724}, - dictWord{ - 10, - 0, - 305, - }, - dictWord{11, 0, 151}, - dictWord{12, 0, 33}, - dictWord{12, 0, 121}, - dictWord{12, 0, 381}, - dictWord{17, 0, 3}, - dictWord{17, 0, 27}, - dictWord{17, 0, 78}, - dictWord{18, 0, 18}, - dictWord{19, 0, 54}, - dictWord{149, 0, 5}, - dictWord{4, 10, 523}, - dictWord{133, 10, 638}, - dictWord{5, 0, 19}, - dictWord{134, 0, 533}, - dictWord{ - 5, - 0, - 395, - }, - dictWord{5, 0, 951}, - dictWord{134, 0, 1776}, - dictWord{135, 0, 1908}, - dictWord{132, 0, 846}, - dictWord{10, 0, 74}, - dictWord{11, 0, 663}, - dictWord{ - 12, - 0, - 210, - }, - dictWord{13, 0, 166}, - dictWord{13, 0, 310}, - dictWord{14, 0, 373}, - dictWord{18, 0, 95}, - dictWord{19, 0, 43}, - dictWord{6, 10, 242}, - dictWord{7, 10, 227}, - dictWord{7, 10, 1581}, - dictWord{8, 10, 104}, - dictWord{9, 10, 113}, - dictWord{9, 10, 220}, - dictWord{9, 10, 427}, - dictWord{10, 10, 239}, - dictWord{11, 10, 579}, - dictWord{11, 10, 1023}, - dictWord{13, 10, 4}, - dictWord{13, 10, 204}, - dictWord{13, 10, 316}, - dictWord{148, 10, 86}, - dictWord{9, 11, 716}, - dictWord{11, 11, 108}, - dictWord{13, 11, 123}, - dictWord{14, 11, 252}, - dictWord{19, 11, 38}, - dictWord{21, 11, 3}, - dictWord{151, 11, 11}, - dictWord{8, 0, 372}, - dictWord{9, 0, 122}, - dictWord{138, 0, 175}, - dictWord{132, 11, 677}, - dictWord{7, 11, 1374}, - dictWord{136, 11, 540}, - dictWord{135, 10, 861}, - dictWord{132, 0, 695}, - dictWord{ - 7, - 0, - 497, - }, - dictWord{9, 0, 387}, - dictWord{147, 0, 81}, - dictWord{136, 0, 937}, - dictWord{134, 0, 718}, - dictWord{7, 0, 1328}, - dictWord{136, 10, 494}, - dictWord{ - 132, - 11, - 331, - }, - dictWord{6, 0, 1581}, - dictWord{133, 11, 747}, - dictWord{5, 0, 284}, - dictWord{6, 0, 49}, - dictWord{6, 0, 350}, - dictWord{7, 0, 1}, - dictWord{7, 0, 377}, - dictWord{7, 0, 1693}, - dictWord{8, 0, 18}, - dictWord{8, 0, 678}, - dictWord{9, 0, 161}, - dictWord{9, 0, 585}, - dictWord{9, 0, 671}, - dictWord{9, 0, 839}, - dictWord{11, 0, 912}, - dictWord{141, 0, 427}, - dictWord{7, 10, 1306}, - dictWord{8, 10, 505}, - dictWord{9, 10, 482}, - dictWord{10, 10, 126}, - dictWord{11, 10, 225}, - dictWord{12, 10, 347}, - dictWord{12, 10, 449}, - dictWord{13, 10, 19}, - dictWord{14, 10, 218}, - dictWord{142, 10, 435}, - dictWord{10, 10, 764}, - dictWord{12, 10, 120}, - dictWord{ - 13, - 10, - 39, - }, - dictWord{145, 10, 127}, - dictWord{4, 0, 597}, - dictWord{133, 10, 268}, - dictWord{134, 0, 1094}, - dictWord{4, 0, 1008}, - dictWord{134, 0, 1973}, - dictWord{132, 0, 811}, - dictWord{139, 0, 908}, - dictWord{135, 0, 1471}, - dictWord{133, 11, 326}, - dictWord{4, 10, 384}, - dictWord{135, 10, 1022}, - dictWord{ - 7, - 0, - 1935, - }, - dictWord{8, 0, 324}, - dictWord{12, 0, 42}, - dictWord{4, 11, 691}, - dictWord{7, 11, 1935}, - dictWord{8, 11, 324}, - dictWord{9, 11, 35}, - dictWord{10, 11, 680}, - dictWord{11, 11, 364}, - dictWord{12, 11, 42}, - dictWord{13, 11, 357}, - dictWord{146, 11, 16}, - dictWord{135, 0, 2014}, - dictWord{7, 0, 2007}, - dictWord{ - 9, - 0, - 101, - }, - dictWord{9, 0, 450}, - dictWord{10, 0, 66}, - dictWord{10, 0, 842}, - dictWord{11, 0, 536}, - dictWord{12, 0, 587}, - dictWord{6, 11, 32}, - dictWord{7, 11, 385}, - dictWord{7, 11, 757}, - dictWord{7, 11, 1916}, - dictWord{8, 11, 37}, - dictWord{8, 11, 94}, - dictWord{8, 11, 711}, - dictWord{9, 11, 541}, - dictWord{10, 11, 162}, - dictWord{ - 10, - 11, - 795, - }, - dictWord{11, 11, 989}, - dictWord{11, 11, 1010}, - dictWord{12, 11, 14}, - dictWord{142, 11, 308}, - dictWord{139, 0, 586}, - dictWord{ - 135, - 10, - 1703, - }, - dictWord{7, 0, 1077}, - dictWord{11, 0, 28}, - dictWord{9, 10, 159}, - dictWord{140, 10, 603}, - dictWord{6, 0, 1221}, - dictWord{136, 10, 583}, - dictWord{ - 6, - 11, - 152, - }, - dictWord{6, 11, 349}, - dictWord{6, 11, 1682}, - dictWord{7, 11, 1252}, - dictWord{8, 11, 112}, - dictWord{9, 11, 435}, - dictWord{9, 11, 668}, - dictWord{ - 10, - 11, - 290, - }, - dictWord{10, 11, 319}, - dictWord{10, 11, 815}, - dictWord{11, 11, 180}, - dictWord{11, 11, 837}, - dictWord{12, 11, 240}, - dictWord{13, 11, 152}, - dictWord{13, 11, 219}, - dictWord{142, 11, 158}, - dictWord{139, 0, 62}, - dictWord{132, 10, 515}, - dictWord{8, 10, 632}, - dictWord{8, 10, 697}, - dictWord{ - 137, - 10, - 854, - }, - dictWord{134, 0, 1766}, - dictWord{132, 11, 581}, - dictWord{6, 11, 126}, - dictWord{7, 11, 573}, - dictWord{8, 11, 397}, - dictWord{142, 11, 44}, - dictWord{ - 150, - 0, - 28, - }, - dictWord{11, 0, 670}, - dictWord{22, 0, 25}, - dictWord{4, 10, 136}, - dictWord{133, 10, 551}, - dictWord{6, 0, 1665}, - dictWord{7, 0, 256}, - dictWord{ - 7, - 0, - 1388, - }, - dictWord{138, 0, 499}, - dictWord{4, 0, 22}, - dictWord{5, 0, 10}, - dictWord{7, 0, 1576}, - dictWord{136, 0, 97}, - dictWord{134, 10, 1782}, - dictWord{5, 0, 481}, - dictWord{7, 10, 1287}, - dictWord{9, 10, 44}, - dictWord{10, 10, 552}, - dictWord{10, 10, 642}, - dictWord{11, 10, 839}, - dictWord{12, 10, 274}, - dictWord{ - 12, - 10, - 275, - }, - dictWord{12, 10, 372}, - dictWord{13, 10, 91}, - dictWord{142, 10, 125}, - dictWord{133, 11, 926}, - dictWord{7, 11, 1232}, - dictWord{137, 11, 531}, - dictWord{6, 0, 134}, - dictWord{7, 0, 437}, - dictWord{7, 0, 1824}, - dictWord{9, 0, 37}, - dictWord{14, 0, 285}, - dictWord{142, 0, 371}, - dictWord{7, 0, 486}, - dictWord{8, 0, 155}, - dictWord{11, 0, 93}, - dictWord{140, 0, 164}, - dictWord{6, 0, 1391}, - dictWord{134, 0, 1442}, - dictWord{133, 11, 670}, - dictWord{133, 0, 591}, - dictWord{ - 6, - 10, - 147, - }, - dictWord{7, 10, 886}, - dictWord{7, 11, 1957}, - dictWord{9, 10, 753}, - dictWord{138, 10, 268}, - dictWord{5, 0, 380}, - dictWord{5, 0, 650}, - dictWord{ - 7, - 0, - 1173, - }, - dictWord{136, 0, 310}, - dictWord{4, 0, 364}, - dictWord{7, 0, 1156}, - dictWord{7, 0, 1187}, - dictWord{137, 0, 409}, - dictWord{135, 11, 1621}, - dictWord{ - 134, - 0, - 482, - }, - dictWord{133, 11, 506}, - dictWord{4, 0, 781}, - dictWord{6, 0, 487}, - dictWord{7, 0, 926}, - dictWord{8, 0, 263}, - dictWord{139, 0, 500}, - dictWord{ - 138, - 10, - 137, - }, - dictWord{135, 11, 242}, - dictWord{139, 11, 96}, - dictWord{133, 10, 414}, - dictWord{135, 10, 1762}, - dictWord{134, 0, 804}, - dictWord{5, 11, 834}, - dictWord{7, 11, 1202}, - dictWord{8, 11, 14}, - dictWord{9, 11, 481}, - dictWord{137, 11, 880}, - dictWord{134, 10, 599}, - dictWord{4, 0, 94}, - dictWord{135, 0, 1265}, - dictWord{4, 0, 415}, - dictWord{132, 0, 417}, - dictWord{5, 0, 348}, - dictWord{6, 0, 522}, - dictWord{6, 10, 1749}, - dictWord{7, 11, 1526}, - dictWord{138, 11, 465}, - dictWord{134, 10, 1627}, - dictWord{132, 0, 1012}, - dictWord{132, 10, 488}, - dictWord{4, 11, 357}, - dictWord{6, 11, 172}, - dictWord{7, 11, 143}, - dictWord{ - 137, - 11, - 413, - }, - dictWord{4, 10, 83}, - dictWord{4, 11, 590}, - dictWord{146, 11, 76}, - dictWord{140, 10, 676}, - dictWord{7, 11, 287}, - dictWord{8, 11, 355}, - dictWord{ - 9, - 11, - 293, - }, - dictWord{137, 11, 743}, - dictWord{134, 10, 278}, - dictWord{6, 0, 1803}, - dictWord{18, 0, 165}, - dictWord{24, 0, 21}, - dictWord{5, 11, 169}, - dictWord{ - 7, - 11, - 333, - }, - dictWord{136, 11, 45}, - dictWord{12, 10, 97}, - dictWord{140, 11, 97}, - dictWord{4, 0, 408}, - dictWord{4, 0, 741}, - dictWord{135, 0, 500}, - dictWord{ - 132, - 11, - 198, - }, - dictWord{7, 10, 388}, - dictWord{7, 10, 644}, - dictWord{139, 10, 781}, - dictWord{4, 11, 24}, - dictWord{5, 11, 140}, - dictWord{5, 11, 185}, - dictWord{ - 7, - 11, - 1500, - }, - dictWord{11, 11, 565}, - dictWord{139, 11, 838}, - dictWord{6, 0, 1321}, - dictWord{9, 0, 257}, - dictWord{7, 10, 229}, - dictWord{8, 10, 59}, - dictWord{ - 9, - 10, - 190, - }, - dictWord{10, 10, 378}, - dictWord{140, 10, 191}, - dictWord{4, 11, 334}, - dictWord{133, 11, 593}, - dictWord{135, 11, 1885}, - dictWord{134, 0, 1138}, - dictWord{4, 0, 249}, - dictWord{6, 0, 73}, - dictWord{135, 0, 177}, - dictWord{133, 0, 576}, - dictWord{142, 0, 231}, - dictWord{137, 0, 288}, - dictWord{132, 10, 660}, - dictWord{7, 10, 1035}, - dictWord{138, 10, 737}, - dictWord{135, 0, 1487}, - dictWord{6, 0, 989}, - dictWord{9, 0, 433}, - dictWord{7, 10, 690}, - dictWord{9, 10, 587}, - dictWord{140, 10, 521}, - dictWord{7, 0, 1264}, - dictWord{7, 0, 1678}, - dictWord{11, 0, 945}, - dictWord{12, 0, 341}, - dictWord{12, 0, 471}, - dictWord{140, 0, 569}, - dictWord{132, 11, 709}, - dictWord{133, 11, 897}, - dictWord{5, 11, 224}, - dictWord{13, 11, 174}, - dictWord{146, 11, 52}, - dictWord{135, 11, 1840}, - dictWord{ - 134, - 10, - 1744, - }, - dictWord{12, 0, 87}, - dictWord{16, 0, 74}, - dictWord{4, 10, 733}, - dictWord{9, 10, 194}, - dictWord{10, 10, 92}, - dictWord{11, 10, 198}, - dictWord{ - 12, - 10, - 84, - }, - dictWord{141, 10, 128}, - dictWord{140, 0, 779}, - dictWord{135, 0, 538}, - dictWord{4, 11, 608}, - dictWord{133, 11, 497}, - dictWord{133, 0, 413}, - dictWord{7, 11, 1375}, - dictWord{7, 11, 1466}, - dictWord{138, 11, 331}, - dictWord{136, 0, 495}, - dictWord{6, 11, 540}, - dictWord{136, 11, 136}, - dictWord{7, 0, 54}, - dictWord{8, 0, 312}, - dictWord{10, 0, 191}, - dictWord{10, 0, 614}, - dictWord{140, 0, 567}, - dictWord{6, 0, 468}, - dictWord{7, 0, 567}, - dictWord{7, 0, 1478}, - dictWord{ - 8, - 0, - 530, - }, - dictWord{14, 0, 290}, - dictWord{133, 11, 999}, - dictWord{4, 11, 299}, - dictWord{7, 10, 306}, - dictWord{135, 11, 1004}, - dictWord{142, 11, 296}, - dictWord{134, 0, 1484}, - dictWord{133, 10, 979}, - dictWord{6, 0, 609}, - dictWord{9, 0, 815}, - dictWord{12, 11, 137}, - dictWord{14, 11, 9}, - dictWord{14, 11, 24}, - dictWord{142, 11, 64}, - dictWord{133, 11, 456}, - dictWord{6, 0, 484}, - dictWord{135, 0, 822}, - dictWord{133, 10, 178}, - dictWord{136, 11, 180}, - dictWord{ - 132, - 11, - 755, - }, - dictWord{137, 0, 900}, - dictWord{135, 0, 1335}, - dictWord{6, 0, 1724}, - dictWord{135, 0, 2022}, - dictWord{135, 11, 1139}, - dictWord{5, 0, 640}, - dictWord{132, 10, 390}, - dictWord{6, 0, 1831}, - dictWord{138, 11, 633}, - dictWord{135, 11, 566}, - dictWord{4, 11, 890}, - dictWord{5, 11, 805}, - dictWord{5, 11, 819}, - dictWord{5, 11, 961}, - dictWord{6, 11, 396}, - dictWord{6, 11, 1631}, - dictWord{6, 11, 1678}, - dictWord{7, 11, 1967}, - dictWord{7, 11, 2041}, - dictWord{ - 9, - 11, - 630, - }, - dictWord{11, 11, 8}, - dictWord{11, 11, 1019}, - dictWord{12, 11, 176}, - dictWord{13, 11, 225}, - dictWord{14, 11, 292}, - dictWord{149, 11, 24}, - dictWord{ - 132, - 0, - 474, - }, - dictWord{134, 0, 1103}, - dictWord{135, 0, 1504}, - dictWord{134, 0, 1576}, - dictWord{6, 0, 961}, - dictWord{6, 0, 1034}, - dictWord{140, 0, 655}, - dictWord{11, 11, 514}, - dictWord{149, 11, 20}, - dictWord{5, 0, 305}, - dictWord{135, 11, 1815}, - dictWord{7, 11, 1505}, - dictWord{10, 11, 190}, - dictWord{ - 10, - 11, - 634, - }, - dictWord{11, 11, 792}, - dictWord{12, 11, 358}, - dictWord{140, 11, 447}, - dictWord{5, 11, 0}, - dictWord{6, 11, 536}, - dictWord{7, 11, 604}, - dictWord{ - 13, - 11, - 445, - }, - dictWord{145, 11, 126}, - dictWord{7, 0, 1236}, - dictWord{133, 10, 105}, - dictWord{4, 0, 480}, - dictWord{6, 0, 217}, - dictWord{6, 0, 302}, - dictWord{ - 6, - 0, - 1642, - }, - dictWord{7, 0, 130}, - dictWord{7, 0, 837}, - dictWord{7, 0, 1321}, - dictWord{7, 0, 1547}, - dictWord{7, 0, 1657}, - dictWord{8, 0, 429}, - dictWord{9, 0, 228}, - dictWord{13, 0, 289}, - dictWord{13, 0, 343}, - dictWord{19, 0, 101}, - dictWord{6, 11, 232}, - dictWord{6, 11, 412}, - dictWord{7, 11, 1074}, - dictWord{8, 11, 9}, - dictWord{ - 8, - 11, - 157, - }, - dictWord{8, 11, 786}, - dictWord{9, 11, 196}, - dictWord{9, 11, 352}, - dictWord{9, 11, 457}, - dictWord{10, 11, 337}, - dictWord{11, 11, 232}, - dictWord{ - 11, - 11, - 877, - }, - dictWord{12, 11, 480}, - dictWord{140, 11, 546}, - dictWord{5, 10, 438}, - dictWord{7, 11, 958}, - dictWord{9, 10, 694}, - dictWord{12, 10, 627}, - dictWord{ - 13, - 11, - 38, - }, - dictWord{141, 10, 210}, - dictWord{4, 11, 382}, - dictWord{136, 11, 579}, - dictWord{7, 0, 278}, - dictWord{10, 0, 739}, - dictWord{11, 0, 708}, - dictWord{ - 141, - 0, - 348, - }, - dictWord{4, 11, 212}, - dictWord{135, 11, 1206}, - dictWord{135, 11, 1898}, - dictWord{6, 0, 708}, - dictWord{6, 0, 1344}, - dictWord{152, 10, 11}, - dictWord{137, 11, 768}, - dictWord{134, 0, 1840}, - dictWord{140, 0, 233}, - dictWord{8, 10, 25}, - dictWord{138, 10, 826}, - dictWord{6, 0, 2017}, - dictWord{ - 133, - 11, - 655, - }, - dictWord{6, 0, 1488}, - dictWord{139, 11, 290}, - dictWord{132, 10, 308}, - dictWord{134, 0, 1590}, - dictWord{134, 0, 1800}, - dictWord{134, 0, 1259}, - dictWord{16, 0, 28}, - dictWord{6, 11, 231}, - dictWord{7, 11, 95}, - dictWord{136, 11, 423}, - dictWord{133, 11, 300}, - dictWord{135, 10, 150}, - dictWord{ - 136, - 10, - 649, - }, - dictWord{7, 11, 1874}, - dictWord{137, 11, 641}, - dictWord{6, 11, 237}, - dictWord{7, 11, 611}, - dictWord{8, 11, 100}, - dictWord{9, 11, 416}, - dictWord{ - 11, - 11, - 335, - }, - dictWord{12, 11, 173}, - dictWord{146, 11, 101}, - dictWord{137, 0, 45}, - dictWord{134, 10, 521}, - dictWord{17, 0, 36}, - dictWord{14, 11, 26}, - dictWord{ - 146, - 11, - 150, - }, - dictWord{7, 0, 1442}, - dictWord{14, 0, 22}, - dictWord{5, 10, 339}, - dictWord{15, 10, 41}, - dictWord{15, 10, 166}, - dictWord{147, 10, 66}, - dictWord{ - 8, - 0, - 378, - }, - dictWord{6, 11, 581}, - dictWord{135, 11, 1119}, - dictWord{134, 0, 1507}, - dictWord{147, 11, 117}, - dictWord{139, 0, 39}, - dictWord{134, 0, 1054}, - dictWord{6, 0, 363}, - dictWord{7, 0, 1955}, - dictWord{136, 0, 725}, - dictWord{134, 0, 2036}, - dictWord{133, 11, 199}, - dictWord{6, 0, 1871}, - dictWord{9, 0, 935}, - dictWord{9, 0, 961}, - dictWord{9, 0, 1004}, - dictWord{9, 0, 1016}, - dictWord{12, 0, 805}, - dictWord{12, 0, 852}, - dictWord{12, 0, 853}, - dictWord{12, 0, 869}, - dictWord{ - 12, - 0, - 882, - }, - dictWord{12, 0, 896}, - dictWord{12, 0, 906}, - dictWord{12, 0, 917}, - dictWord{12, 0, 940}, - dictWord{15, 0, 170}, - dictWord{15, 0, 176}, - dictWord{ - 15, - 0, - 188, - }, - dictWord{15, 0, 201}, - dictWord{15, 0, 205}, - dictWord{15, 0, 212}, - dictWord{15, 0, 234}, - dictWord{15, 0, 244}, - dictWord{18, 0, 181}, - dictWord{18, 0, 193}, - dictWord{18, 0, 196}, - dictWord{18, 0, 201}, - dictWord{18, 0, 202}, - dictWord{18, 0, 210}, - dictWord{18, 0, 217}, - dictWord{18, 0, 235}, - dictWord{18, 0, 236}, - dictWord{18, 0, 237}, - dictWord{21, 0, 54}, - dictWord{21, 0, 55}, - dictWord{21, 0, 58}, - dictWord{21, 0, 59}, - dictWord{152, 0, 22}, - dictWord{134, 10, 1628}, - dictWord{ - 137, - 0, - 805, - }, - dictWord{5, 0, 813}, - dictWord{135, 0, 2046}, - dictWord{142, 11, 42}, - dictWord{5, 0, 712}, - dictWord{6, 0, 1240}, - dictWord{11, 0, 17}, - dictWord{ - 13, - 0, - 321, - }, - dictWord{144, 0, 67}, - dictWord{132, 0, 617}, - dictWord{135, 10, 829}, - dictWord{6, 0, 320}, - dictWord{7, 0, 781}, - dictWord{7, 0, 1921}, - dictWord{9, 0, 55}, - dictWord{10, 0, 186}, - dictWord{10, 0, 273}, - dictWord{10, 0, 664}, - dictWord{10, 0, 801}, - dictWord{11, 0, 996}, - dictWord{11, 0, 997}, - dictWord{13, 0, 157}, - dictWord{142, 0, 170}, - dictWord{136, 0, 271}, - dictWord{5, 10, 486}, - dictWord{135, 10, 1349}, - dictWord{18, 11, 91}, - dictWord{147, 11, 70}, - dictWord{10, 0, 445}, - dictWord{7, 10, 1635}, - dictWord{8, 10, 17}, - dictWord{138, 10, 295}, - dictWord{136, 11, 404}, - dictWord{7, 0, 103}, - dictWord{7, 0, 863}, - dictWord{11, 0, 184}, - dictWord{145, 0, 62}, - dictWord{138, 10, 558}, - dictWord{137, 0, 659}, - dictWord{6, 11, 312}, - dictWord{6, 11, 1715}, - dictWord{10, 11, 584}, - dictWord{ - 11, - 11, - 546, - }, - dictWord{11, 11, 692}, - dictWord{12, 11, 259}, - dictWord{12, 11, 295}, - dictWord{13, 11, 46}, - dictWord{141, 11, 154}, - dictWord{134, 0, 676}, - dictWord{132, 11, 588}, - dictWord{4, 11, 231}, - dictWord{5, 11, 61}, - dictWord{6, 11, 104}, - dictWord{7, 11, 729}, - dictWord{7, 11, 964}, - dictWord{7, 11, 1658}, - dictWord{140, 11, 414}, - dictWord{6, 11, 263}, - dictWord{138, 11, 757}, - dictWord{11, 0, 337}, - dictWord{142, 0, 303}, - dictWord{135, 11, 1363}, - dictWord{ - 132, - 11, - 320, - }, - dictWord{140, 0, 506}, - dictWord{134, 10, 447}, - dictWord{5, 0, 77}, - dictWord{7, 0, 1455}, - dictWord{10, 0, 843}, - dictWord{147, 0, 73}, - dictWord{ - 7, - 10, - 577, - }, - dictWord{7, 10, 1432}, - dictWord{9, 10, 475}, - dictWord{9, 10, 505}, - dictWord{9, 10, 526}, - dictWord{9, 10, 609}, - dictWord{9, 10, 689}, - dictWord{ - 9, - 10, - 726, - }, - dictWord{9, 10, 735}, - dictWord{9, 10, 738}, - dictWord{10, 10, 556}, - dictWord{10, 10, 674}, - dictWord{10, 10, 684}, - dictWord{11, 10, 89}, - dictWord{ - 11, - 10, - 202, - }, - dictWord{11, 10, 272}, - dictWord{11, 10, 380}, - dictWord{11, 10, 415}, - dictWord{11, 10, 505}, - dictWord{11, 10, 537}, - dictWord{11, 10, 550}, - dictWord{11, 10, 562}, - dictWord{11, 10, 640}, - dictWord{11, 10, 667}, - dictWord{11, 10, 688}, - dictWord{11, 10, 847}, - dictWord{11, 10, 927}, - dictWord{ - 11, - 10, - 930, - }, - dictWord{11, 10, 940}, - dictWord{12, 10, 144}, - dictWord{12, 10, 325}, - dictWord{12, 10, 329}, - dictWord{12, 10, 389}, - dictWord{12, 10, 403}, - dictWord{ - 12, - 10, - 451, - }, - dictWord{12, 10, 515}, - dictWord{12, 10, 604}, - dictWord{12, 10, 616}, - dictWord{12, 10, 626}, - dictWord{13, 10, 66}, - dictWord{13, 10, 131}, - dictWord{13, 10, 167}, - dictWord{13, 10, 236}, - dictWord{13, 10, 368}, - dictWord{13, 10, 411}, - dictWord{13, 10, 434}, - dictWord{13, 10, 453}, - dictWord{ - 13, - 10, - 461, - }, - dictWord{13, 10, 474}, - dictWord{14, 10, 59}, - dictWord{14, 10, 60}, - dictWord{14, 10, 139}, - dictWord{14, 10, 152}, - dictWord{14, 10, 276}, - dictWord{ - 14, - 10, - 353, - }, - dictWord{14, 10, 402}, - dictWord{15, 10, 28}, - dictWord{15, 10, 81}, - dictWord{15, 10, 123}, - dictWord{15, 10, 152}, - dictWord{18, 10, 136}, - dictWord{148, 10, 88}, - dictWord{132, 0, 458}, - dictWord{135, 0, 1420}, - dictWord{6, 0, 109}, - dictWord{10, 0, 382}, - dictWord{4, 11, 405}, - dictWord{4, 10, 609}, - dictWord{7, 10, 756}, - dictWord{7, 11, 817}, - dictWord{9, 10, 544}, - dictWord{11, 10, 413}, - dictWord{14, 11, 58}, - dictWord{14, 10, 307}, - dictWord{16, 10, 25}, - dictWord{17, 11, 37}, - dictWord{146, 11, 124}, - dictWord{6, 0, 330}, - dictWord{7, 0, 1084}, - dictWord{11, 0, 142}, - dictWord{133, 11, 974}, - dictWord{4, 10, 930}, - dictWord{133, 10, 947}, - dictWord{5, 10, 939}, - dictWord{142, 11, 394}, - dictWord{16, 0, 91}, - dictWord{145, 0, 87}, - dictWord{5, 11, 235}, - dictWord{5, 10, 962}, - dictWord{7, 11, 1239}, - dictWord{11, 11, 131}, - dictWord{140, 11, 370}, - dictWord{11, 0, 492}, - dictWord{5, 10, 651}, - dictWord{8, 10, 170}, - dictWord{9, 10, 61}, - dictWord{9, 10, 63}, - dictWord{10, 10, 23}, - dictWord{10, 10, 37}, - dictWord{10, 10, 834}, - dictWord{11, 10, 4}, - dictWord{11, 10, 281}, - dictWord{11, 10, 503}, - dictWord{ - 11, - 10, - 677, - }, - dictWord{12, 10, 96}, - dictWord{12, 10, 130}, - dictWord{12, 10, 244}, - dictWord{14, 10, 5}, - dictWord{14, 10, 40}, - dictWord{14, 10, 162}, - dictWord{ - 14, - 10, - 202, - }, - dictWord{146, 10, 133}, - dictWord{4, 10, 406}, - dictWord{5, 10, 579}, - dictWord{12, 10, 492}, - dictWord{150, 10, 15}, - dictWord{9, 11, 137}, - dictWord{138, 11, 221}, - dictWord{134, 0, 1239}, - dictWord{11, 0, 211}, - dictWord{140, 0, 145}, - dictWord{7, 11, 390}, - dictWord{138, 11, 140}, - dictWord{ - 135, - 11, - 1418, - }, - dictWord{135, 11, 1144}, - dictWord{134, 0, 1049}, - dictWord{7, 0, 321}, - dictWord{6, 10, 17}, - dictWord{7, 10, 1001}, - dictWord{7, 10, 1982}, - dictWord{ - 9, - 10, - 886, - }, - dictWord{10, 10, 489}, - dictWord{10, 10, 800}, - dictWord{11, 10, 782}, - dictWord{12, 10, 320}, - dictWord{13, 10, 467}, - dictWord{14, 10, 145}, - dictWord{14, 10, 387}, - dictWord{143, 10, 119}, - dictWord{145, 10, 17}, - dictWord{5, 11, 407}, - dictWord{11, 11, 489}, - dictWord{19, 11, 37}, - dictWord{20, 11, 73}, - dictWord{150, 11, 38}, - dictWord{133, 10, 458}, - dictWord{135, 0, 1985}, - dictWord{7, 10, 1983}, - dictWord{8, 10, 0}, - dictWord{8, 10, 171}, - dictWord{ - 9, - 10, - 120, - }, - dictWord{9, 10, 732}, - dictWord{10, 10, 473}, - dictWord{11, 10, 656}, - dictWord{11, 10, 998}, - dictWord{18, 10, 0}, - dictWord{18, 10, 2}, - dictWord{ - 147, - 10, - 21, - }, - dictWord{5, 11, 325}, - dictWord{7, 11, 1483}, - dictWord{8, 11, 5}, - dictWord{8, 11, 227}, - dictWord{9, 11, 105}, - dictWord{10, 11, 585}, - dictWord{ - 140, - 11, - 614, - }, - dictWord{136, 0, 122}, - dictWord{132, 0, 234}, - dictWord{135, 11, 1196}, - dictWord{6, 0, 976}, - dictWord{6, 0, 1098}, - dictWord{134, 0, 1441}, - dictWord{ - 7, - 0, - 253, - }, - dictWord{136, 0, 549}, - dictWord{6, 11, 621}, - dictWord{13, 11, 504}, - dictWord{144, 11, 19}, - dictWord{132, 10, 519}, - dictWord{5, 0, 430}, - dictWord{ - 5, - 0, - 932, - }, - dictWord{6, 0, 131}, - dictWord{7, 0, 417}, - dictWord{9, 0, 522}, - dictWord{11, 0, 314}, - dictWord{141, 0, 390}, - dictWord{14, 0, 149}, - dictWord{14, 0, 399}, - dictWord{143, 0, 57}, - dictWord{5, 10, 907}, - dictWord{6, 10, 31}, - dictWord{6, 11, 218}, - dictWord{7, 10, 491}, - dictWord{7, 10, 530}, - dictWord{8, 10, 592}, - dictWord{11, 10, 53}, - dictWord{11, 10, 779}, - dictWord{12, 10, 167}, - dictWord{12, 10, 411}, - dictWord{14, 10, 14}, - dictWord{14, 10, 136}, - dictWord{15, 10, 72}, - dictWord{16, 10, 17}, - dictWord{144, 10, 72}, - dictWord{140, 11, 330}, - dictWord{7, 11, 454}, - dictWord{7, 11, 782}, - dictWord{136, 11, 768}, - dictWord{ - 132, - 0, - 507, - }, - dictWord{10, 11, 676}, - dictWord{140, 11, 462}, - dictWord{6, 0, 630}, - dictWord{9, 0, 811}, - dictWord{4, 10, 208}, - dictWord{5, 10, 106}, - dictWord{ - 6, - 10, - 531, - }, - dictWord{8, 10, 408}, - dictWord{9, 10, 188}, - dictWord{138, 10, 572}, - dictWord{4, 0, 343}, - dictWord{5, 0, 511}, - dictWord{134, 10, 1693}, - dictWord{ - 134, - 11, - 164, - }, - dictWord{132, 0, 448}, - dictWord{7, 0, 455}, - dictWord{138, 0, 591}, - dictWord{135, 0, 1381}, - dictWord{12, 10, 441}, - dictWord{150, 11, 50}, - dictWord{9, 10, 449}, - dictWord{10, 10, 192}, - dictWord{138, 10, 740}, - dictWord{6, 0, 575}, - dictWord{132, 10, 241}, - dictWord{134, 0, 1175}, - dictWord{ - 134, - 0, - 653, - }, - dictWord{134, 0, 1761}, - dictWord{134, 0, 1198}, - dictWord{132, 10, 259}, - dictWord{6, 11, 343}, - dictWord{7, 11, 195}, - dictWord{9, 11, 226}, - dictWord{ - 10, - 11, - 197, - }, - dictWord{10, 11, 575}, - dictWord{11, 11, 502}, - dictWord{139, 11, 899}, - dictWord{7, 0, 1127}, - dictWord{7, 0, 1572}, - dictWord{10, 0, 297}, - dictWord{10, 0, 422}, - dictWord{11, 0, 764}, - dictWord{11, 0, 810}, - dictWord{12, 0, 264}, - dictWord{13, 0, 102}, - dictWord{13, 0, 300}, - dictWord{13, 0, 484}, - dictWord{ - 14, - 0, - 147, - }, - dictWord{14, 0, 229}, - dictWord{17, 0, 71}, - dictWord{18, 0, 118}, - dictWord{147, 0, 120}, - dictWord{135, 11, 666}, - dictWord{132, 0, 678}, - dictWord{ - 4, - 10, - 173, - }, - dictWord{5, 10, 312}, - dictWord{5, 10, 512}, - dictWord{135, 10, 1285}, - dictWord{7, 10, 1603}, - dictWord{7, 10, 1691}, - dictWord{9, 10, 464}, - dictWord{11, 10, 195}, - dictWord{12, 10, 279}, - dictWord{12, 10, 448}, - dictWord{14, 10, 11}, - dictWord{147, 10, 102}, - dictWord{16, 0, 99}, - dictWord{146, 0, 164}, - dictWord{7, 11, 1125}, - dictWord{9, 11, 143}, - dictWord{11, 11, 61}, - dictWord{14, 11, 405}, - dictWord{150, 11, 21}, - dictWord{137, 11, 260}, - dictWord{ - 4, - 10, - 452, - }, - dictWord{5, 10, 583}, - dictWord{5, 10, 817}, - dictWord{6, 10, 433}, - dictWord{7, 10, 593}, - dictWord{7, 10, 720}, - dictWord{7, 10, 1378}, - dictWord{ - 8, - 10, - 161, - }, - dictWord{9, 10, 284}, - dictWord{10, 10, 313}, - dictWord{139, 10, 886}, - dictWord{132, 10, 547}, - dictWord{136, 10, 722}, - dictWord{14, 0, 35}, - dictWord{142, 0, 191}, - dictWord{141, 0, 45}, - dictWord{138, 0, 121}, - dictWord{132, 0, 125}, - dictWord{134, 0, 1622}, - dictWord{133, 11, 959}, - dictWord{ - 8, - 10, - 420, - }, - dictWord{139, 10, 193}, - dictWord{132, 0, 721}, - dictWord{135, 10, 409}, - dictWord{136, 0, 145}, - dictWord{7, 0, 792}, - dictWord{8, 0, 147}, - dictWord{ - 10, - 0, - 821, - }, - dictWord{11, 0, 970}, - dictWord{11, 0, 1021}, - dictWord{136, 11, 173}, - dictWord{134, 11, 266}, - dictWord{132, 0, 715}, - dictWord{7, 0, 1999}, - dictWord{138, 10, 308}, - dictWord{133, 0, 531}, - dictWord{5, 0, 168}, - dictWord{5, 0, 930}, - dictWord{8, 0, 74}, - dictWord{9, 0, 623}, - dictWord{12, 0, 500}, - dictWord{ - 140, - 0, - 579, - }, - dictWord{144, 0, 65}, - dictWord{138, 11, 246}, - dictWord{6, 0, 220}, - dictWord{7, 0, 1101}, - dictWord{13, 0, 105}, - dictWord{142, 11, 314}, - dictWord{ - 5, - 10, - 1002, - }, - dictWord{136, 10, 745}, - dictWord{134, 0, 960}, - dictWord{20, 0, 0}, - dictWord{148, 11, 0}, - dictWord{4, 0, 1005}, - dictWord{4, 10, 239}, - dictWord{ - 6, - 10, - 477, - }, - dictWord{7, 10, 1607}, - dictWord{11, 10, 68}, - dictWord{139, 10, 617}, - dictWord{6, 0, 19}, - dictWord{7, 0, 1413}, - dictWord{139, 0, 428}, - dictWord{ - 149, - 10, - 13, - }, - dictWord{7, 0, 96}, - dictWord{8, 0, 401}, - dictWord{8, 0, 703}, - dictWord{9, 0, 896}, - dictWord{136, 11, 300}, - dictWord{134, 0, 1595}, - dictWord{145, 0, 116}, - dictWord{136, 0, 1021}, - dictWord{7, 0, 1961}, - dictWord{7, 0, 1965}, - dictWord{7, 0, 2030}, - dictWord{8, 0, 150}, - dictWord{8, 0, 702}, - dictWord{8, 0, 737}, - dictWord{ - 8, - 0, - 750, - }, - dictWord{140, 0, 366}, - dictWord{11, 11, 75}, - dictWord{142, 11, 267}, - dictWord{132, 10, 367}, - dictWord{8, 0, 800}, - dictWord{9, 0, 148}, - dictWord{ - 9, - 0, - 872, - }, - dictWord{9, 0, 890}, - dictWord{11, 0, 309}, - dictWord{11, 0, 1001}, - dictWord{13, 0, 267}, - dictWord{13, 0, 323}, - dictWord{5, 11, 427}, - dictWord{ - 5, - 11, - 734, - }, - dictWord{7, 11, 478}, - dictWord{136, 11, 52}, - dictWord{7, 11, 239}, - dictWord{11, 11, 217}, - dictWord{142, 11, 165}, - dictWord{132, 11, 323}, - dictWord{140, 11, 419}, - dictWord{13, 0, 299}, - dictWord{142, 0, 75}, - dictWord{6, 11, 87}, - dictWord{6, 11, 1734}, - dictWord{7, 11, 20}, - dictWord{7, 11, 1056}, - dictWord{ - 8, - 11, - 732, - }, - dictWord{9, 11, 406}, - dictWord{9, 11, 911}, - dictWord{138, 11, 694}, - dictWord{134, 0, 1383}, - dictWord{132, 10, 694}, - dictWord{ - 133, - 11, - 613, - }, - dictWord{137, 0, 779}, - dictWord{4, 0, 598}, - dictWord{140, 10, 687}, - dictWord{6, 0, 970}, - dictWord{135, 0, 424}, - dictWord{133, 0, 547}, - dictWord{ - 7, - 11, - 32, - }, - dictWord{7, 11, 984}, - dictWord{8, 11, 85}, - dictWord{8, 11, 709}, - dictWord{9, 11, 579}, - dictWord{9, 11, 847}, - dictWord{9, 11, 856}, - dictWord{10, 11, 799}, - dictWord{11, 11, 258}, - dictWord{11, 11, 1007}, - dictWord{12, 11, 331}, - dictWord{12, 11, 615}, - dictWord{13, 11, 188}, - dictWord{13, 11, 435}, - dictWord{ - 14, - 11, - 8, - }, - dictWord{15, 11, 165}, - dictWord{16, 11, 27}, - dictWord{148, 11, 40}, - dictWord{6, 0, 1222}, - dictWord{134, 0, 1385}, - dictWord{132, 0, 876}, - dictWord{ - 138, - 11, - 151, - }, - dictWord{135, 10, 213}, - dictWord{4, 11, 167}, - dictWord{135, 11, 82}, - dictWord{133, 0, 133}, - dictWord{6, 11, 24}, - dictWord{7, 11, 74}, - dictWord{ - 7, - 11, - 678, - }, - dictWord{137, 11, 258}, - dictWord{5, 11, 62}, - dictWord{6, 11, 534}, - dictWord{7, 11, 684}, - dictWord{7, 11, 1043}, - dictWord{7, 11, 1072}, - dictWord{ - 8, - 11, - 280, - }, - dictWord{8, 11, 541}, - dictWord{8, 11, 686}, - dictWord{10, 11, 519}, - dictWord{11, 11, 252}, - dictWord{140, 11, 282}, - dictWord{136, 0, 187}, - dictWord{8, 0, 8}, - dictWord{10, 0, 0}, - dictWord{10, 0, 818}, - dictWord{139, 0, 988}, - dictWord{132, 11, 359}, - dictWord{11, 0, 429}, - dictWord{15, 0, 51}, - dictWord{ - 135, - 10, - 1672, - }, - dictWord{136, 0, 685}, - dictWord{5, 11, 211}, - dictWord{7, 11, 88}, - dictWord{136, 11, 627}, - dictWord{134, 0, 472}, - dictWord{136, 0, 132}, - dictWord{ - 6, - 11, - 145, - }, - dictWord{141, 11, 336}, - dictWord{4, 10, 751}, - dictWord{11, 10, 390}, - dictWord{140, 10, 32}, - dictWord{6, 0, 938}, - dictWord{6, 0, 1060}, - dictWord{ - 4, - 11, - 263, - }, - dictWord{4, 10, 409}, - dictWord{133, 10, 78}, - dictWord{137, 0, 874}, - dictWord{8, 0, 774}, - dictWord{10, 0, 670}, - dictWord{12, 0, 51}, - dictWord{ - 4, - 11, - 916, - }, - dictWord{6, 10, 473}, - dictWord{7, 10, 1602}, - dictWord{10, 10, 698}, - dictWord{12, 10, 212}, - dictWord{13, 10, 307}, - dictWord{145, 10, 105}, - dictWord{146, 0, 92}, - dictWord{143, 10, 156}, - dictWord{132, 0, 830}, - dictWord{137, 0, 701}, - dictWord{4, 11, 599}, - dictWord{6, 11, 1634}, - dictWord{7, 11, 5}, - dictWord{7, 11, 55}, - dictWord{7, 11, 67}, - dictWord{7, 11, 97}, - dictWord{7, 11, 691}, - dictWord{7, 11, 979}, - dictWord{7, 11, 1697}, - dictWord{8, 11, 207}, - dictWord{ - 8, - 11, - 214, - }, - dictWord{8, 11, 231}, - dictWord{8, 11, 294}, - dictWord{8, 11, 336}, - dictWord{8, 11, 428}, - dictWord{8, 11, 451}, - dictWord{8, 11, 460}, - dictWord{8, 11, 471}, - dictWord{8, 11, 622}, - dictWord{8, 11, 626}, - dictWord{8, 11, 679}, - dictWord{8, 11, 759}, - dictWord{8, 11, 829}, - dictWord{9, 11, 11}, - dictWord{9, 11, 246}, - dictWord{ - 9, - 11, - 484, - }, - dictWord{9, 11, 573}, - dictWord{9, 11, 706}, - dictWord{9, 11, 762}, - dictWord{9, 11, 798}, - dictWord{9, 11, 855}, - dictWord{9, 11, 870}, - dictWord{ - 9, - 11, - 912, - }, - dictWord{10, 11, 303}, - dictWord{10, 11, 335}, - dictWord{10, 11, 424}, - dictWord{10, 11, 461}, - dictWord{10, 11, 543}, - dictWord{10, 11, 759}, - dictWord{10, 11, 814}, - dictWord{11, 11, 59}, - dictWord{11, 11, 199}, - dictWord{11, 11, 235}, - dictWord{11, 11, 475}, - dictWord{11, 11, 590}, - dictWord{11, 11, 929}, - dictWord{11, 11, 963}, - dictWord{12, 11, 114}, - dictWord{12, 11, 182}, - dictWord{12, 11, 226}, - dictWord{12, 11, 332}, - dictWord{12, 11, 439}, - dictWord{ - 12, - 11, - 575, - }, - dictWord{12, 11, 598}, - dictWord{13, 11, 8}, - dictWord{13, 11, 125}, - dictWord{13, 11, 194}, - dictWord{13, 11, 287}, - dictWord{14, 11, 197}, - dictWord{ - 14, - 11, - 383, - }, - dictWord{15, 11, 53}, - dictWord{17, 11, 63}, - dictWord{19, 11, 46}, - dictWord{19, 11, 98}, - dictWord{19, 11, 106}, - dictWord{148, 11, 85}, - dictWord{ - 4, - 0, - 127, - }, - dictWord{5, 0, 350}, - dictWord{6, 0, 356}, - dictWord{8, 0, 426}, - dictWord{9, 0, 572}, - dictWord{10, 0, 247}, - dictWord{139, 0, 312}, - dictWord{134, 0, 1215}, - dictWord{6, 0, 59}, - dictWord{9, 0, 603}, - dictWord{13, 0, 397}, - dictWord{7, 11, 1853}, - dictWord{138, 11, 437}, - dictWord{134, 0, 1762}, - dictWord{ - 147, - 11, - 126, - }, - dictWord{135, 10, 883}, - dictWord{13, 0, 293}, - dictWord{142, 0, 56}, - dictWord{133, 10, 617}, - dictWord{139, 10, 50}, - dictWord{5, 11, 187}, - dictWord{ - 7, - 10, - 1518, - }, - dictWord{139, 10, 694}, - dictWord{135, 0, 441}, - dictWord{6, 0, 111}, - dictWord{7, 0, 4}, - dictWord{8, 0, 163}, - dictWord{8, 0, 776}, - dictWord{ - 138, - 0, - 566, - }, - dictWord{132, 0, 806}, - dictWord{4, 11, 215}, - dictWord{9, 11, 38}, - dictWord{10, 11, 3}, - dictWord{11, 11, 23}, - dictWord{11, 11, 127}, - dictWord{ - 139, - 11, - 796, - }, - dictWord{14, 0, 233}, - dictWord{4, 10, 546}, - dictWord{135, 10, 2042}, - dictWord{135, 0, 1994}, - dictWord{134, 0, 1739}, - dictWord{135, 11, 1530}, - dictWord{136, 0, 393}, - dictWord{5, 0, 297}, - dictWord{7, 0, 1038}, - dictWord{14, 0, 359}, - dictWord{19, 0, 52}, - dictWord{148, 0, 47}, - dictWord{135, 0, 309}, - dictWord{ - 4, - 10, - 313, - }, - dictWord{133, 10, 577}, - dictWord{8, 10, 184}, - dictWord{141, 10, 433}, - dictWord{135, 10, 935}, - dictWord{12, 10, 186}, - dictWord{ - 12, - 10, - 292, - }, - dictWord{14, 10, 100}, - dictWord{146, 10, 70}, - dictWord{136, 0, 363}, - dictWord{14, 0, 175}, - dictWord{11, 10, 402}, - dictWord{12, 10, 109}, - dictWord{ - 12, - 10, - 431, - }, - dictWord{13, 10, 179}, - dictWord{13, 10, 206}, - dictWord{14, 10, 217}, - dictWord{16, 10, 3}, - dictWord{148, 10, 53}, - dictWord{5, 10, 886}, - dictWord{ - 6, - 10, - 46, - }, - dictWord{6, 10, 1790}, - dictWord{7, 10, 14}, - dictWord{7, 10, 732}, - dictWord{7, 10, 1654}, - dictWord{8, 10, 95}, - dictWord{8, 10, 327}, - dictWord{ - 8, - 10, - 616, - }, - dictWord{9, 10, 892}, - dictWord{10, 10, 598}, - dictWord{10, 10, 769}, - dictWord{11, 10, 134}, - dictWord{11, 10, 747}, - dictWord{12, 10, 378}, - dictWord{ - 142, - 10, - 97, - }, - dictWord{136, 0, 666}, - dictWord{135, 0, 1675}, - dictWord{6, 0, 655}, - dictWord{134, 0, 1600}, - dictWord{135, 0, 808}, - dictWord{133, 10, 1021}, - dictWord{4, 11, 28}, - dictWord{5, 11, 440}, - dictWord{7, 11, 248}, - dictWord{11, 11, 833}, - dictWord{140, 11, 344}, - dictWord{134, 11, 1654}, - dictWord{ - 132, - 0, - 280, - }, - dictWord{140, 0, 54}, - dictWord{4, 0, 421}, - dictWord{133, 0, 548}, - dictWord{132, 10, 153}, - dictWord{6, 11, 339}, - dictWord{135, 11, 923}, - dictWord{ - 133, - 11, - 853, - }, - dictWord{133, 10, 798}, - dictWord{132, 10, 587}, - dictWord{6, 11, 249}, - dictWord{7, 11, 1234}, - dictWord{139, 11, 573}, - dictWord{6, 10, 598}, - dictWord{7, 10, 42}, - dictWord{8, 10, 695}, - dictWord{10, 10, 212}, - dictWord{11, 10, 158}, - dictWord{14, 10, 196}, - dictWord{145, 10, 85}, - dictWord{7, 0, 249}, - dictWord{5, 10, 957}, - dictWord{133, 10, 1008}, - dictWord{4, 10, 129}, - dictWord{135, 10, 465}, - dictWord{6, 0, 254}, - dictWord{7, 0, 842}, - dictWord{7, 0, 1659}, - dictWord{9, 0, 109}, - dictWord{10, 0, 103}, - dictWord{7, 10, 908}, - dictWord{7, 10, 1201}, - dictWord{9, 10, 755}, - dictWord{11, 10, 906}, - dictWord{12, 10, 527}, - dictWord{146, 10, 7}, - dictWord{5, 0, 262}, - dictWord{136, 10, 450}, - dictWord{144, 0, 1}, - dictWord{10, 11, 201}, - dictWord{142, 11, 319}, - dictWord{7, 11, 49}, - dictWord{ - 7, - 11, - 392, - }, - dictWord{8, 11, 20}, - dictWord{8, 11, 172}, - dictWord{8, 11, 690}, - dictWord{9, 11, 383}, - dictWord{9, 11, 845}, - dictWord{10, 11, 48}, - dictWord{ - 11, - 11, - 293, - }, - dictWord{11, 11, 832}, - dictWord{11, 11, 920}, - dictWord{141, 11, 221}, - dictWord{5, 11, 858}, - dictWord{133, 11, 992}, - dictWord{134, 0, 805}, - dictWord{139, 10, 1003}, - dictWord{6, 0, 1630}, - dictWord{134, 11, 307}, - dictWord{7, 11, 1512}, - dictWord{135, 11, 1794}, - dictWord{6, 11, 268}, - dictWord{ - 137, - 11, - 62, - }, - dictWord{135, 10, 1868}, - dictWord{133, 0, 671}, - dictWord{4, 0, 989}, - dictWord{8, 0, 972}, - dictWord{136, 0, 998}, - dictWord{132, 11, 423}, - dictWord{132, 0, 889}, - dictWord{135, 0, 1382}, - dictWord{135, 0, 1910}, - dictWord{7, 10, 965}, - dictWord{7, 10, 1460}, - dictWord{135, 10, 1604}, - dictWord{ - 4, - 0, - 627, - }, - dictWord{5, 0, 775}, - dictWord{138, 11, 106}, - dictWord{134, 11, 348}, - dictWord{7, 0, 202}, - dictWord{11, 0, 362}, - dictWord{11, 0, 948}, - dictWord{ - 140, - 0, - 388, - }, - dictWord{138, 11, 771}, - dictWord{6, 11, 613}, - dictWord{136, 11, 223}, - dictWord{6, 0, 560}, - dictWord{7, 0, 451}, - dictWord{8, 0, 389}, - dictWord{ - 12, - 0, - 490, - }, - dictWord{13, 0, 16}, - dictWord{13, 0, 215}, - dictWord{13, 0, 351}, - dictWord{18, 0, 132}, - dictWord{147, 0, 125}, - dictWord{135, 0, 841}, - dictWord{ - 136, - 0, - 566, - }, - dictWord{136, 0, 938}, - dictWord{132, 11, 670}, - dictWord{5, 0, 912}, - dictWord{6, 0, 1695}, - dictWord{140, 11, 55}, - dictWord{9, 11, 40}, - dictWord{ - 139, - 11, - 136, - }, - dictWord{7, 0, 1361}, - dictWord{7, 10, 982}, - dictWord{10, 10, 32}, - dictWord{143, 10, 56}, - dictWord{11, 11, 259}, - dictWord{140, 11, 270}, - dictWord{ - 5, - 0, - 236, - }, - dictWord{6, 0, 572}, - dictWord{8, 0, 492}, - dictWord{11, 0, 618}, - dictWord{144, 0, 56}, - dictWord{8, 11, 572}, - dictWord{9, 11, 310}, - dictWord{9, 11, 682}, - dictWord{137, 11, 698}, - dictWord{134, 0, 1854}, - dictWord{5, 0, 190}, - dictWord{136, 0, 318}, - dictWord{133, 10, 435}, - dictWord{135, 0, 1376}, - dictWord{ - 4, - 11, - 296, - }, - dictWord{6, 11, 352}, - dictWord{7, 11, 401}, - dictWord{7, 11, 1410}, - dictWord{7, 11, 1594}, - dictWord{7, 11, 1674}, - dictWord{8, 11, 63}, - dictWord{ - 8, - 11, - 660, - }, - dictWord{137, 11, 74}, - dictWord{7, 0, 349}, - dictWord{5, 10, 85}, - dictWord{6, 10, 419}, - dictWord{7, 10, 305}, - dictWord{7, 10, 361}, - dictWord{7, 10, 1337}, - dictWord{8, 10, 71}, - dictWord{140, 10, 519}, - dictWord{4, 11, 139}, - dictWord{4, 11, 388}, - dictWord{140, 11, 188}, - dictWord{6, 0, 1972}, - dictWord{6, 0, 2013}, - dictWord{8, 0, 951}, - dictWord{10, 0, 947}, - dictWord{10, 0, 974}, - dictWord{10, 0, 1018}, - dictWord{142, 0, 476}, - dictWord{140, 10, 688}, - dictWord{ - 135, - 10, - 740, - }, - dictWord{5, 10, 691}, - dictWord{7, 10, 345}, - dictWord{9, 10, 94}, - dictWord{140, 10, 169}, - dictWord{9, 0, 344}, - dictWord{5, 10, 183}, - dictWord{6, 10, 582}, - dictWord{10, 10, 679}, - dictWord{140, 10, 435}, - dictWord{135, 10, 511}, - dictWord{132, 0, 850}, - dictWord{8, 11, 441}, - dictWord{10, 11, 314}, - dictWord{ - 143, - 11, - 3, - }, - dictWord{7, 10, 1993}, - dictWord{136, 10, 684}, - dictWord{4, 11, 747}, - dictWord{6, 11, 290}, - dictWord{6, 10, 583}, - dictWord{7, 11, 649}, - dictWord{ - 7, - 11, - 1479, - }, - dictWord{135, 11, 1583}, - dictWord{133, 11, 232}, - dictWord{133, 10, 704}, - dictWord{134, 0, 910}, - dictWord{4, 10, 179}, - dictWord{5, 10, 198}, - dictWord{133, 10, 697}, - dictWord{7, 10, 347}, - dictWord{7, 10, 971}, - dictWord{8, 10, 181}, - dictWord{138, 10, 711}, - dictWord{136, 11, 525}, - dictWord{ - 14, - 0, - 19, - }, - dictWord{14, 0, 28}, - dictWord{144, 0, 29}, - dictWord{7, 0, 85}, - dictWord{7, 0, 247}, - dictWord{8, 0, 585}, - dictWord{138, 0, 163}, - dictWord{4, 0, 487}, - dictWord{ - 7, - 11, - 472, - }, - dictWord{7, 11, 1801}, - dictWord{10, 11, 748}, - dictWord{141, 11, 458}, - dictWord{4, 10, 243}, - dictWord{5, 10, 203}, - dictWord{7, 10, 19}, - dictWord{ - 7, - 10, - 71, - }, - dictWord{7, 10, 113}, - dictWord{10, 10, 405}, - dictWord{11, 10, 357}, - dictWord{142, 10, 240}, - dictWord{7, 10, 1450}, - dictWord{139, 10, 99}, - dictWord{132, 11, 425}, - dictWord{138, 0, 145}, - dictWord{147, 0, 83}, - dictWord{6, 10, 492}, - dictWord{137, 11, 247}, - dictWord{4, 0, 1013}, - dictWord{ - 134, - 0, - 2033, - }, - dictWord{5, 10, 134}, - dictWord{6, 10, 408}, - dictWord{6, 10, 495}, - dictWord{135, 10, 1593}, - dictWord{135, 0, 1922}, - dictWord{134, 11, 1768}, - dictWord{4, 0, 124}, - dictWord{10, 0, 457}, - dictWord{11, 0, 121}, - dictWord{11, 0, 169}, - dictWord{11, 0, 870}, - dictWord{11, 0, 874}, - dictWord{12, 0, 214}, - dictWord{ - 14, - 0, - 187, - }, - dictWord{143, 0, 77}, - dictWord{5, 0, 557}, - dictWord{135, 0, 1457}, - dictWord{139, 0, 66}, - dictWord{5, 11, 943}, - dictWord{6, 11, 1779}, - dictWord{ - 142, - 10, - 4, - }, - dictWord{4, 10, 248}, - dictWord{4, 10, 665}, - dictWord{7, 10, 137}, - dictWord{137, 10, 349}, - dictWord{7, 0, 1193}, - dictWord{5, 11, 245}, - dictWord{ - 6, - 11, - 576, - }, - dictWord{7, 11, 582}, - dictWord{136, 11, 225}, - dictWord{144, 0, 82}, - dictWord{7, 10, 1270}, - dictWord{139, 10, 612}, - dictWord{5, 0, 454}, - dictWord{ - 10, - 0, - 352, - }, - dictWord{138, 11, 352}, - dictWord{18, 0, 57}, - dictWord{5, 10, 371}, - dictWord{135, 10, 563}, - dictWord{135, 0, 1333}, - dictWord{6, 0, 107}, - dictWord{ - 7, - 0, - 638, - }, - dictWord{7, 0, 1632}, - dictWord{9, 0, 396}, - dictWord{134, 11, 610}, - dictWord{5, 0, 370}, - dictWord{134, 0, 1756}, - dictWord{4, 10, 374}, - dictWord{ - 7, - 10, - 547, - }, - dictWord{7, 10, 1700}, - dictWord{7, 10, 1833}, - dictWord{139, 10, 858}, - dictWord{133, 0, 204}, - dictWord{6, 0, 1305}, - dictWord{9, 10, 311}, - dictWord{ - 141, - 10, - 42, - }, - dictWord{5, 0, 970}, - dictWord{134, 0, 1706}, - dictWord{6, 10, 1647}, - dictWord{7, 10, 1552}, - dictWord{7, 10, 2010}, - dictWord{9, 10, 494}, - dictWord{137, 10, 509}, - dictWord{13, 11, 455}, - dictWord{15, 11, 99}, - dictWord{15, 11, 129}, - dictWord{144, 11, 68}, - dictWord{135, 0, 3}, - dictWord{4, 0, 35}, - dictWord{ - 5, - 0, - 121, - }, - dictWord{5, 0, 483}, - dictWord{5, 0, 685}, - dictWord{6, 0, 489}, - dictWord{6, 0, 782}, - dictWord{6, 0, 1032}, - dictWord{7, 0, 1204}, - dictWord{136, 0, 394}, - dictWord{4, 0, 921}, - dictWord{133, 0, 1007}, - dictWord{8, 11, 360}, - dictWord{138, 11, 63}, - dictWord{135, 0, 1696}, - dictWord{134, 0, 1519}, - dictWord{ - 132, - 11, - 443, - }, - dictWord{135, 11, 944}, - dictWord{6, 10, 123}, - dictWord{7, 10, 214}, - dictWord{9, 10, 728}, - dictWord{10, 10, 157}, - dictWord{11, 10, 346}, - dictWord{11, 10, 662}, - dictWord{143, 10, 106}, - dictWord{137, 0, 981}, - dictWord{135, 10, 1435}, - dictWord{134, 0, 1072}, - dictWord{132, 0, 712}, - dictWord{ - 134, - 0, - 1629, - }, - dictWord{134, 0, 728}, - dictWord{4, 11, 298}, - dictWord{137, 11, 483}, - dictWord{6, 0, 1177}, - dictWord{6, 0, 1271}, - dictWord{5, 11, 164}, - dictWord{ - 7, - 11, - 121, - }, - dictWord{142, 11, 189}, - dictWord{7, 0, 1608}, - dictWord{4, 10, 707}, - dictWord{5, 10, 588}, - dictWord{6, 10, 393}, - dictWord{13, 10, 106}, - dictWord{ - 18, - 10, - 49, - }, - dictWord{147, 10, 41}, - dictWord{23, 0, 16}, - dictWord{151, 11, 16}, - dictWord{6, 10, 211}, - dictWord{7, 10, 1690}, - dictWord{11, 10, 486}, - dictWord{140, 10, 369}, - dictWord{133, 0, 485}, - dictWord{19, 11, 15}, - dictWord{149, 11, 27}, - dictWord{4, 11, 172}, - dictWord{9, 11, 611}, - dictWord{10, 11, 436}, - dictWord{12, 11, 673}, - dictWord{141, 11, 255}, - dictWord{5, 11, 844}, - dictWord{10, 11, 484}, - dictWord{11, 11, 754}, - dictWord{12, 11, 457}, - dictWord{ - 14, - 11, - 171, - }, - dictWord{14, 11, 389}, - dictWord{146, 11, 153}, - dictWord{4, 0, 285}, - dictWord{5, 0, 27}, - dictWord{5, 0, 317}, - dictWord{6, 0, 301}, - dictWord{7, 0, 7}, - dictWord{ - 8, - 0, - 153, - }, - dictWord{10, 0, 766}, - dictWord{11, 0, 468}, - dictWord{12, 0, 467}, - dictWord{141, 0, 143}, - dictWord{134, 0, 1462}, - dictWord{9, 11, 263}, - dictWord{ - 10, - 11, - 147, - }, - dictWord{138, 11, 492}, - dictWord{133, 11, 537}, - dictWord{6, 0, 1945}, - dictWord{6, 0, 1986}, - dictWord{6, 0, 1991}, - dictWord{134, 0, 2038}, - dictWord{134, 10, 219}, - dictWord{137, 11, 842}, - dictWord{14, 0, 52}, - dictWord{17, 0, 50}, - dictWord{5, 10, 582}, - dictWord{6, 10, 1646}, - dictWord{7, 10, 99}, - dictWord{7, 10, 1962}, - dictWord{7, 10, 1986}, - dictWord{8, 10, 515}, - dictWord{8, 10, 773}, - dictWord{9, 10, 23}, - dictWord{9, 10, 491}, - dictWord{12, 10, 620}, - dictWord{142, 10, 93}, - dictWord{138, 11, 97}, - dictWord{20, 0, 21}, - dictWord{20, 0, 44}, - dictWord{133, 10, 851}, - dictWord{136, 0, 819}, - dictWord{139, 0, 917}, - dictWord{5, 11, 230}, - dictWord{5, 11, 392}, - dictWord{6, 11, 420}, - dictWord{8, 10, 762}, - dictWord{8, 10, 812}, - dictWord{9, 11, 568}, - dictWord{9, 10, 910}, - dictWord{140, 11, 612}, - dictWord{135, 0, 784}, - dictWord{15, 0, 135}, - dictWord{143, 11, 135}, - dictWord{10, 0, 454}, - dictWord{140, 0, 324}, - dictWord{4, 11, 0}, - dictWord{5, 11, 41}, - dictWord{7, 11, 1459}, - dictWord{7, 11, 1469}, - dictWord{7, 11, 1618}, - dictWord{7, 11, 1859}, - dictWord{9, 11, 549}, - dictWord{139, 11, 905}, - dictWord{4, 10, 98}, - dictWord{7, 10, 1365}, - dictWord{9, 10, 422}, - dictWord{9, 10, 670}, - dictWord{10, 10, 775}, - dictWord{11, 10, 210}, - dictWord{13, 10, 26}, - dictWord{13, 10, 457}, - dictWord{141, 10, 476}, - dictWord{6, 0, 1719}, - dictWord{6, 0, 1735}, - dictWord{7, 0, 2016}, - dictWord{7, 0, 2020}, - dictWord{8, 0, 837}, - dictWord{137, 0, 852}, - dictWord{133, 11, 696}, - dictWord{135, 0, 852}, - dictWord{132, 0, 952}, - dictWord{134, 10, 1730}, - dictWord{132, 11, 771}, - dictWord{ - 138, - 0, - 568, - }, - dictWord{137, 0, 448}, - dictWord{139, 0, 146}, - dictWord{8, 0, 67}, - dictWord{138, 0, 419}, - dictWord{133, 11, 921}, - dictWord{137, 10, 147}, - dictWord{134, 0, 1826}, - dictWord{10, 0, 657}, - dictWord{14, 0, 297}, - dictWord{142, 0, 361}, - dictWord{6, 0, 666}, - dictWord{6, 0, 767}, - dictWord{134, 0, 1542}, - dictWord{139, 0, 729}, - dictWord{6, 11, 180}, - dictWord{7, 11, 1137}, - dictWord{8, 11, 751}, - dictWord{139, 11, 805}, - dictWord{4, 11, 183}, - dictWord{7, 11, 271}, - dictWord{11, 11, 824}, - dictWord{11, 11, 952}, - dictWord{13, 11, 278}, - dictWord{13, 11, 339}, - dictWord{13, 11, 482}, - dictWord{14, 11, 424}, - dictWord{ - 148, - 11, - 99, - }, - dictWord{4, 0, 669}, - dictWord{5, 11, 477}, - dictWord{5, 11, 596}, - dictWord{6, 11, 505}, - dictWord{7, 11, 1221}, - dictWord{11, 11, 907}, - dictWord{ - 12, - 11, - 209, - }, - dictWord{141, 11, 214}, - dictWord{135, 11, 1215}, - dictWord{5, 0, 402}, - dictWord{6, 10, 30}, - dictWord{11, 10, 56}, - dictWord{139, 10, 305}, - dictWord{ - 7, - 11, - 564, - }, - dictWord{142, 11, 168}, - dictWord{139, 0, 152}, - dictWord{7, 0, 912}, - dictWord{135, 10, 1614}, - dictWord{4, 10, 150}, - dictWord{5, 10, 303}, - dictWord{134, 10, 327}, - dictWord{7, 0, 320}, - dictWord{8, 0, 51}, - dictWord{9, 0, 868}, - dictWord{10, 0, 833}, - dictWord{12, 0, 481}, - dictWord{12, 0, 570}, - dictWord{ - 148, - 0, - 106, - }, - dictWord{132, 0, 445}, - dictWord{7, 11, 274}, - dictWord{11, 11, 263}, - dictWord{11, 11, 479}, - dictWord{11, 11, 507}, - dictWord{140, 11, 277}, - dictWord{10, 0, 555}, - dictWord{11, 0, 308}, - dictWord{19, 0, 95}, - dictWord{6, 11, 1645}, - dictWord{8, 10, 192}, - dictWord{10, 10, 78}, - dictWord{141, 10, 359}, - dictWord{135, 10, 786}, - dictWord{6, 11, 92}, - dictWord{6, 11, 188}, - dictWord{7, 11, 1269}, - dictWord{7, 11, 1524}, - dictWord{7, 11, 1876}, - dictWord{10, 11, 228}, - dictWord{139, 11, 1020}, - dictWord{4, 11, 459}, - dictWord{133, 11, 966}, - dictWord{11, 0, 386}, - dictWord{6, 10, 1638}, - dictWord{7, 10, 79}, - dictWord{ - 7, - 10, - 496, - }, - dictWord{9, 10, 138}, - dictWord{10, 10, 336}, - dictWord{12, 10, 412}, - dictWord{12, 10, 440}, - dictWord{142, 10, 305}, - dictWord{133, 0, 239}, - dictWord{ - 7, - 0, - 83, - }, - dictWord{7, 0, 1990}, - dictWord{8, 0, 130}, - dictWord{139, 0, 720}, - dictWord{138, 11, 709}, - dictWord{4, 0, 143}, - dictWord{5, 0, 550}, - dictWord{ - 133, - 0, - 752, - }, - dictWord{5, 0, 123}, - dictWord{6, 0, 530}, - dictWord{7, 0, 348}, - dictWord{135, 0, 1419}, - dictWord{135, 0, 2024}, - dictWord{6, 11, 18}, - dictWord{7, 11, 179}, - dictWord{7, 11, 721}, - dictWord{7, 11, 932}, - dictWord{8, 11, 548}, - dictWord{8, 11, 757}, - dictWord{9, 11, 54}, - dictWord{9, 11, 65}, - dictWord{9, 11, 532}, - dictWord{ - 9, - 11, - 844, - }, - dictWord{10, 11, 113}, - dictWord{10, 11, 117}, - dictWord{10, 11, 236}, - dictWord{10, 11, 315}, - dictWord{10, 11, 430}, - dictWord{10, 11, 798}, - dictWord{11, 11, 153}, - dictWord{11, 11, 351}, - dictWord{11, 11, 375}, - dictWord{12, 11, 78}, - dictWord{12, 11, 151}, - dictWord{12, 11, 392}, - dictWord{ - 14, - 11, - 248, - }, - dictWord{143, 11, 23}, - dictWord{7, 10, 204}, - dictWord{7, 10, 415}, - dictWord{8, 10, 42}, - dictWord{10, 10, 85}, - dictWord{139, 10, 564}, - dictWord{ - 134, - 0, - 958, - }, - dictWord{133, 11, 965}, - dictWord{132, 0, 210}, - dictWord{135, 11, 1429}, - dictWord{138, 11, 480}, - dictWord{134, 11, 182}, - dictWord{ - 139, - 11, - 345, - }, - dictWord{10, 11, 65}, - dictWord{10, 11, 488}, - dictWord{138, 11, 497}, - dictWord{4, 10, 3}, - dictWord{5, 10, 247}, - dictWord{5, 10, 644}, - dictWord{ - 7, - 10, - 744, - }, - dictWord{7, 10, 1207}, - dictWord{7, 10, 1225}, - dictWord{7, 10, 1909}, - dictWord{146, 10, 147}, - dictWord{132, 0, 430}, - dictWord{5, 10, 285}, - dictWord{ - 9, - 10, - 67, - }, - dictWord{13, 10, 473}, - dictWord{143, 10, 82}, - dictWord{144, 11, 16}, - dictWord{7, 11, 1162}, - dictWord{9, 11, 588}, - dictWord{10, 11, 260}, - dictWord{151, 10, 8}, - dictWord{133, 0, 213}, - dictWord{138, 0, 7}, - dictWord{135, 0, 801}, - dictWord{134, 11, 1786}, - dictWord{135, 11, 308}, - dictWord{6, 0, 936}, - dictWord{134, 0, 1289}, - dictWord{133, 0, 108}, - dictWord{132, 0, 885}, - dictWord{133, 0, 219}, - dictWord{139, 0, 587}, - dictWord{4, 0, 193}, - dictWord{5, 0, 916}, - dictWord{6, 0, 1041}, - dictWord{7, 0, 364}, - dictWord{10, 0, 398}, - dictWord{10, 0, 726}, - dictWord{11, 0, 317}, - dictWord{11, 0, 626}, - dictWord{12, 0, 142}, - dictWord{12, 0, 288}, - dictWord{12, 0, 678}, - dictWord{13, 0, 313}, - dictWord{15, 0, 113}, - dictWord{146, 0, 114}, - dictWord{135, 0, 1165}, - dictWord{6, 0, 241}, - dictWord{ - 9, - 0, - 342, - }, - dictWord{10, 0, 729}, - dictWord{11, 0, 284}, - dictWord{11, 0, 445}, - dictWord{11, 0, 651}, - dictWord{11, 0, 863}, - dictWord{13, 0, 398}, - dictWord{ - 146, - 0, - 99, - }, - dictWord{7, 0, 907}, - dictWord{136, 0, 832}, - dictWord{9, 0, 303}, - dictWord{4, 10, 29}, - dictWord{6, 10, 532}, - dictWord{7, 10, 1628}, - dictWord{7, 10, 1648}, - dictWord{9, 10, 350}, - dictWord{10, 10, 433}, - dictWord{11, 10, 97}, - dictWord{11, 10, 557}, - dictWord{11, 10, 745}, - dictWord{12, 10, 289}, - dictWord{ - 12, - 10, - 335, - }, - dictWord{12, 10, 348}, - dictWord{12, 10, 606}, - dictWord{13, 10, 116}, - dictWord{13, 10, 233}, - dictWord{13, 10, 466}, - dictWord{14, 10, 181}, - dictWord{ - 14, - 10, - 209, - }, - dictWord{14, 10, 232}, - dictWord{14, 10, 236}, - dictWord{14, 10, 300}, - dictWord{16, 10, 41}, - dictWord{148, 10, 97}, - dictWord{7, 11, 423}, - dictWord{7, 10, 1692}, - dictWord{136, 11, 588}, - dictWord{6, 0, 931}, - dictWord{134, 0, 1454}, - dictWord{5, 10, 501}, - dictWord{7, 10, 1704}, - dictWord{9, 10, 553}, - dictWord{11, 10, 520}, - dictWord{12, 10, 557}, - dictWord{141, 10, 249}, - dictWord{136, 11, 287}, - dictWord{4, 0, 562}, - dictWord{9, 0, 254}, - dictWord{ - 139, - 0, - 879, - }, - dictWord{132, 0, 786}, - dictWord{14, 11, 32}, - dictWord{18, 11, 85}, - dictWord{20, 11, 2}, - dictWord{152, 11, 16}, - dictWord{135, 0, 1294}, - dictWord{ - 7, - 11, - 723, - }, - dictWord{135, 11, 1135}, - dictWord{6, 0, 216}, - dictWord{7, 0, 901}, - dictWord{7, 0, 1343}, - dictWord{8, 0, 493}, - dictWord{134, 11, 403}, - dictWord{ - 7, - 11, - 719, - }, - dictWord{8, 11, 809}, - dictWord{136, 11, 834}, - dictWord{5, 11, 210}, - dictWord{6, 11, 213}, - dictWord{7, 11, 60}, - dictWord{10, 11, 364}, - dictWord{ - 139, - 11, - 135, - }, - dictWord{7, 0, 341}, - dictWord{11, 0, 219}, - dictWord{5, 11, 607}, - dictWord{8, 11, 326}, - dictWord{136, 11, 490}, - dictWord{4, 11, 701}, - dictWord{ - 5, - 11, - 472, - }, - dictWord{5, 11, 639}, - dictWord{7, 11, 1249}, - dictWord{9, 11, 758}, - dictWord{139, 11, 896}, - dictWord{135, 11, 380}, - dictWord{135, 11, 1947}, - dictWord{139, 0, 130}, - dictWord{135, 0, 1734}, - dictWord{10, 0, 115}, - dictWord{11, 0, 420}, - dictWord{12, 0, 154}, - dictWord{13, 0, 404}, - dictWord{14, 0, 346}, - dictWord{143, 0, 54}, - dictWord{134, 10, 129}, - dictWord{4, 11, 386}, - dictWord{7, 11, 41}, - dictWord{8, 11, 405}, - dictWord{9, 11, 497}, - dictWord{11, 11, 110}, - dictWord{11, 11, 360}, - dictWord{15, 11, 37}, - dictWord{144, 11, 84}, - dictWord{141, 11, 282}, - dictWord{5, 11, 46}, - dictWord{7, 11, 1452}, - dictWord{7, 11, 1480}, - dictWord{8, 11, 634}, - dictWord{140, 11, 472}, - dictWord{4, 11, 524}, - dictWord{136, 11, 810}, - dictWord{10, 11, 238}, - dictWord{141, 11, 33}, - dictWord{ - 133, - 0, - 604, - }, - dictWord{5, 0, 1011}, - dictWord{136, 0, 701}, - dictWord{8, 0, 856}, - dictWord{8, 0, 858}, - dictWord{8, 0, 879}, - dictWord{12, 0, 702}, - dictWord{142, 0, 447}, - dictWord{4, 0, 54}, - dictWord{5, 0, 666}, - dictWord{7, 0, 1039}, - dictWord{7, 0, 1130}, - dictWord{9, 0, 195}, - dictWord{138, 0, 302}, - dictWord{4, 10, 25}, - dictWord{ - 5, - 10, - 60, - }, - dictWord{6, 10, 504}, - dictWord{7, 10, 614}, - dictWord{7, 10, 1155}, - dictWord{140, 10, 0}, - dictWord{7, 10, 1248}, - dictWord{11, 10, 621}, - dictWord{ - 139, - 10, - 702, - }, - dictWord{133, 11, 997}, - dictWord{137, 10, 321}, - dictWord{134, 0, 1669}, - dictWord{134, 0, 1791}, - dictWord{4, 10, 379}, - dictWord{ - 135, - 10, - 1397, - }, - dictWord{138, 11, 372}, - dictWord{5, 11, 782}, - dictWord{5, 11, 829}, - dictWord{134, 11, 1738}, - dictWord{135, 0, 1228}, - dictWord{4, 10, 118}, - dictWord{6, 10, 274}, - dictWord{6, 10, 361}, - dictWord{7, 10, 75}, - dictWord{141, 10, 441}, - dictWord{132, 0, 623}, - dictWord{9, 11, 279}, - dictWord{10, 11, 407}, - dictWord{14, 11, 84}, - dictWord{150, 11, 18}, - dictWord{137, 10, 841}, - dictWord{135, 0, 798}, - dictWord{140, 10, 693}, - dictWord{5, 10, 314}, - dictWord{6, 10, 221}, - dictWord{7, 10, 419}, - dictWord{10, 10, 650}, - dictWord{11, 10, 396}, - dictWord{12, 10, 156}, - dictWord{13, 10, 369}, - dictWord{14, 10, 333}, - dictWord{ - 145, - 10, - 47, - }, - dictWord{135, 11, 1372}, - dictWord{7, 0, 122}, - dictWord{9, 0, 259}, - dictWord{10, 0, 84}, - dictWord{11, 0, 470}, - dictWord{12, 0, 541}, - dictWord{ - 141, - 0, - 379, - }, - dictWord{134, 0, 837}, - dictWord{8, 0, 1013}, - dictWord{4, 11, 78}, - dictWord{5, 11, 96}, - dictWord{5, 11, 182}, - dictWord{7, 11, 1724}, - dictWord{ - 7, - 11, - 1825, - }, - dictWord{10, 11, 394}, - dictWord{10, 11, 471}, - dictWord{11, 11, 532}, - dictWord{14, 11, 340}, - dictWord{145, 11, 88}, - dictWord{134, 0, 577}, - dictWord{135, 11, 1964}, - dictWord{132, 10, 913}, - dictWord{134, 0, 460}, - dictWord{8, 0, 891}, - dictWord{10, 0, 901}, - dictWord{10, 0, 919}, - dictWord{10, 0, 932}, - dictWord{12, 0, 715}, - dictWord{12, 0, 728}, - dictWord{12, 0, 777}, - dictWord{14, 0, 457}, - dictWord{144, 0, 103}, - dictWord{5, 0, 82}, - dictWord{5, 0, 131}, - dictWord{ - 7, - 0, - 1755, - }, - dictWord{8, 0, 31}, - dictWord{9, 0, 168}, - dictWord{9, 0, 764}, - dictWord{139, 0, 869}, - dictWord{136, 10, 475}, - dictWord{6, 0, 605}, - dictWord{ - 5, - 10, - 1016, - }, - dictWord{9, 11, 601}, - dictWord{9, 11, 619}, - dictWord{10, 11, 505}, - dictWord{10, 11, 732}, - dictWord{11, 11, 355}, - dictWord{140, 11, 139}, - dictWord{ - 7, - 10, - 602, - }, - dictWord{8, 10, 179}, - dictWord{10, 10, 781}, - dictWord{140, 10, 126}, - dictWord{134, 0, 1246}, - dictWord{6, 10, 329}, - dictWord{138, 10, 111}, - dictWord{6, 11, 215}, - dictWord{7, 11, 1028}, - dictWord{7, 11, 1473}, - dictWord{7, 11, 1721}, - dictWord{9, 11, 424}, - dictWord{138, 11, 779}, - dictWord{5, 0, 278}, - dictWord{137, 0, 68}, - dictWord{6, 0, 932}, - dictWord{6, 0, 1084}, - dictWord{144, 0, 86}, - dictWord{4, 0, 163}, - dictWord{5, 0, 201}, - dictWord{5, 0, 307}, - dictWord{ - 5, - 0, - 310, - }, - dictWord{6, 0, 335}, - dictWord{7, 0, 284}, - dictWord{7, 0, 1660}, - dictWord{136, 0, 165}, - dictWord{136, 0, 781}, - dictWord{134, 0, 707}, - dictWord{6, 0, 33}, - dictWord{135, 0, 1244}, - dictWord{5, 10, 821}, - dictWord{6, 11, 67}, - dictWord{6, 10, 1687}, - dictWord{7, 11, 258}, - dictWord{7, 11, 1630}, - dictWord{9, 11, 354}, - dictWord{9, 11, 675}, - dictWord{10, 11, 830}, - dictWord{14, 11, 80}, - dictWord{145, 11, 80}, - dictWord{6, 11, 141}, - dictWord{7, 11, 225}, - dictWord{9, 11, 59}, - dictWord{9, 11, 607}, - dictWord{10, 11, 312}, - dictWord{11, 11, 687}, - dictWord{12, 11, 555}, - dictWord{13, 11, 373}, - dictWord{13, 11, 494}, - dictWord{148, 11, 58}, - dictWord{134, 0, 1113}, - dictWord{9, 0, 388}, - dictWord{5, 10, 71}, - dictWord{7, 10, 1407}, - dictWord{9, 10, 704}, - dictWord{10, 10, 261}, - dictWord{10, 10, 619}, - dictWord{11, 10, 547}, - dictWord{11, 10, 619}, - dictWord{143, 10, 157}, - dictWord{7, 0, 1953}, - dictWord{136, 0, 720}, - dictWord{138, 0, 203}, - dictWord{ - 7, - 10, - 2008, - }, - dictWord{9, 10, 337}, - dictWord{138, 10, 517}, - dictWord{6, 0, 326}, - dictWord{7, 0, 677}, - dictWord{137, 0, 425}, - dictWord{139, 11, 81}, - dictWord{ - 7, - 0, - 1316, - }, - dictWord{7, 0, 1412}, - dictWord{7, 0, 1839}, - dictWord{9, 0, 589}, - dictWord{11, 0, 241}, - dictWord{11, 0, 676}, - dictWord{11, 0, 811}, - dictWord{11, 0, 891}, - dictWord{12, 0, 140}, - dictWord{12, 0, 346}, - dictWord{12, 0, 479}, - dictWord{13, 0, 140}, - dictWord{13, 0, 381}, - dictWord{14, 0, 188}, - dictWord{18, 0, 30}, - dictWord{148, 0, 108}, - dictWord{5, 0, 416}, - dictWord{6, 10, 86}, - dictWord{6, 10, 603}, - dictWord{7, 10, 292}, - dictWord{7, 10, 561}, - dictWord{8, 10, 257}, - dictWord{ - 8, - 10, - 382, - }, - dictWord{9, 10, 721}, - dictWord{9, 10, 778}, - dictWord{11, 10, 581}, - dictWord{140, 10, 466}, - dictWord{4, 10, 486}, - dictWord{133, 10, 491}, - dictWord{134, 0, 1300}, - dictWord{132, 10, 72}, - dictWord{7, 0, 847}, - dictWord{6, 10, 265}, - dictWord{7, 11, 430}, - dictWord{139, 11, 46}, - dictWord{5, 11, 602}, - dictWord{6, 11, 106}, - dictWord{7, 11, 1786}, - dictWord{7, 11, 1821}, - dictWord{7, 11, 2018}, - dictWord{9, 11, 418}, - dictWord{137, 11, 763}, - dictWord{5, 0, 358}, - dictWord{7, 0, 535}, - dictWord{7, 0, 1184}, - dictWord{10, 0, 662}, - dictWord{13, 0, 212}, - dictWord{13, 0, 304}, - dictWord{13, 0, 333}, - dictWord{145, 0, 98}, - dictWord{ - 5, - 11, - 65, - }, - dictWord{6, 11, 416}, - dictWord{7, 11, 1720}, - dictWord{7, 11, 1924}, - dictWord{8, 11, 677}, - dictWord{10, 11, 109}, - dictWord{11, 11, 14}, - dictWord{ - 11, - 11, - 70, - }, - dictWord{11, 11, 569}, - dictWord{11, 11, 735}, - dictWord{15, 11, 153}, - dictWord{148, 11, 80}, - dictWord{6, 0, 1823}, - dictWord{8, 0, 839}, - dictWord{ - 8, - 0, - 852, - }, - dictWord{8, 0, 903}, - dictWord{10, 0, 940}, - dictWord{12, 0, 707}, - dictWord{140, 0, 775}, - dictWord{135, 11, 1229}, - dictWord{6, 0, 1522}, - dictWord{ - 140, - 0, - 654, - }, - dictWord{136, 11, 595}, - dictWord{139, 0, 163}, - dictWord{141, 0, 314}, - dictWord{132, 0, 978}, - dictWord{4, 0, 601}, - dictWord{6, 0, 2035}, - dictWord{137, 10, 234}, - dictWord{5, 10, 815}, - dictWord{6, 10, 1688}, - dictWord{134, 10, 1755}, - dictWord{133, 0, 946}, - dictWord{136, 0, 434}, - dictWord{ - 6, - 10, - 197, - }, - dictWord{136, 10, 205}, - dictWord{7, 0, 411}, - dictWord{7, 0, 590}, - dictWord{8, 0, 631}, - dictWord{9, 0, 323}, - dictWord{10, 0, 355}, - dictWord{11, 0, 491}, - dictWord{12, 0, 143}, - dictWord{12, 0, 402}, - dictWord{13, 0, 73}, - dictWord{14, 0, 408}, - dictWord{15, 0, 107}, - dictWord{146, 0, 71}, - dictWord{7, 0, 1467}, - dictWord{ - 8, - 0, - 328, - }, - dictWord{10, 0, 544}, - dictWord{11, 0, 955}, - dictWord{12, 0, 13}, - dictWord{13, 0, 320}, - dictWord{145, 0, 83}, - dictWord{142, 0, 410}, - dictWord{ - 11, - 0, - 511, - }, - dictWord{13, 0, 394}, - dictWord{14, 0, 298}, - dictWord{14, 0, 318}, - dictWord{146, 0, 103}, - dictWord{6, 10, 452}, - dictWord{7, 10, 312}, - dictWord{ - 138, - 10, - 219, - }, - dictWord{138, 10, 589}, - dictWord{4, 10, 333}, - dictWord{9, 10, 176}, - dictWord{12, 10, 353}, - dictWord{141, 10, 187}, - dictWord{135, 11, 329}, - dictWord{132, 11, 469}, - dictWord{5, 0, 835}, - dictWord{134, 0, 483}, - dictWord{134, 11, 1743}, - dictWord{5, 11, 929}, - dictWord{6, 11, 340}, - dictWord{8, 11, 376}, - dictWord{136, 11, 807}, - dictWord{134, 10, 1685}, - dictWord{132, 0, 677}, - dictWord{5, 11, 218}, - dictWord{7, 11, 1610}, - dictWord{138, 11, 83}, - dictWord{ - 5, - 11, - 571, - }, - dictWord{135, 11, 1842}, - dictWord{132, 11, 455}, - dictWord{137, 0, 70}, - dictWord{135, 0, 1405}, - dictWord{7, 10, 135}, - dictWord{8, 10, 7}, - dictWord{ - 8, - 10, - 62, - }, - dictWord{9, 10, 243}, - dictWord{10, 10, 658}, - dictWord{10, 10, 697}, - dictWord{11, 10, 456}, - dictWord{139, 10, 756}, - dictWord{9, 10, 395}, - dictWord{138, 10, 79}, - dictWord{137, 0, 108}, - dictWord{6, 11, 161}, - dictWord{7, 11, 372}, - dictWord{137, 11, 597}, - dictWord{132, 11, 349}, - dictWord{ - 132, - 0, - 777, - }, - dictWord{132, 0, 331}, - dictWord{135, 10, 631}, - dictWord{133, 0, 747}, - dictWord{6, 11, 432}, - dictWord{6, 11, 608}, - dictWord{139, 11, 322}, - dictWord{138, 10, 835}, - dictWord{5, 11, 468}, - dictWord{7, 11, 1809}, - dictWord{10, 11, 325}, - dictWord{11, 11, 856}, - dictWord{12, 11, 345}, - dictWord{ - 143, - 11, - 104, - }, - dictWord{133, 11, 223}, - dictWord{7, 10, 406}, - dictWord{7, 10, 459}, - dictWord{8, 10, 606}, - dictWord{139, 10, 726}, - dictWord{132, 11, 566}, - dictWord{142, 0, 68}, - dictWord{4, 11, 59}, - dictWord{135, 11, 1394}, - dictWord{6, 11, 436}, - dictWord{139, 11, 481}, - dictWord{4, 11, 48}, - dictWord{5, 11, 271}, - dictWord{135, 11, 953}, - dictWord{139, 11, 170}, - dictWord{5, 11, 610}, - dictWord{136, 11, 457}, - dictWord{133, 11, 755}, - dictWord{135, 11, 1217}, - dictWord{ - 133, - 10, - 612, - }, - dictWord{132, 11, 197}, - dictWord{132, 0, 505}, - dictWord{4, 10, 372}, - dictWord{7, 10, 482}, - dictWord{8, 10, 158}, - dictWord{9, 10, 602}, - dictWord{ - 9, - 10, - 615, - }, - dictWord{10, 10, 245}, - dictWord{10, 10, 678}, - dictWord{10, 10, 744}, - dictWord{11, 10, 248}, - dictWord{139, 10, 806}, - dictWord{133, 0, 326}, - dictWord{5, 10, 854}, - dictWord{135, 10, 1991}, - dictWord{4, 0, 691}, - dictWord{146, 0, 16}, - dictWord{6, 0, 628}, - dictWord{9, 0, 35}, - dictWord{10, 0, 680}, - dictWord{10, 0, 793}, - dictWord{11, 0, 364}, - dictWord{13, 0, 357}, - dictWord{143, 0, 164}, - dictWord{138, 0, 654}, - dictWord{6, 0, 32}, - dictWord{7, 0, 385}, - dictWord{ - 7, - 0, - 757, - }, - dictWord{7, 0, 1916}, - dictWord{8, 0, 37}, - dictWord{8, 0, 94}, - dictWord{8, 0, 711}, - dictWord{9, 0, 541}, - dictWord{10, 0, 162}, - dictWord{10, 0, 795}, - dictWord{ - 11, - 0, - 989, - }, - dictWord{11, 0, 1010}, - dictWord{12, 0, 14}, - dictWord{142, 0, 308}, - dictWord{133, 11, 217}, - dictWord{6, 0, 152}, - dictWord{6, 0, 349}, - dictWord{ - 6, - 0, - 1682, - }, - dictWord{7, 0, 1252}, - dictWord{8, 0, 112}, - dictWord{9, 0, 435}, - dictWord{9, 0, 668}, - dictWord{10, 0, 290}, - dictWord{10, 0, 319}, - dictWord{10, 0, 815}, - dictWord{11, 0, 180}, - dictWord{11, 0, 837}, - dictWord{12, 0, 240}, - dictWord{13, 0, 152}, - dictWord{13, 0, 219}, - dictWord{142, 0, 158}, - dictWord{4, 0, 581}, - dictWord{134, 0, 726}, - dictWord{5, 10, 195}, - dictWord{135, 10, 1685}, - dictWord{6, 0, 126}, - dictWord{7, 0, 573}, - dictWord{8, 0, 397}, - dictWord{142, 0, 44}, - dictWord{138, 0, 89}, - dictWord{7, 10, 1997}, - dictWord{8, 10, 730}, - dictWord{139, 10, 1006}, - dictWord{134, 0, 1531}, - dictWord{134, 0, 1167}, - dictWord{ - 5, - 0, - 926, - }, - dictWord{12, 0, 203}, - dictWord{133, 10, 751}, - dictWord{4, 11, 165}, - dictWord{7, 11, 1398}, - dictWord{135, 11, 1829}, - dictWord{7, 0, 1232}, - dictWord{137, 0, 531}, - dictWord{135, 10, 821}, - dictWord{134, 0, 943}, - dictWord{133, 0, 670}, - dictWord{4, 0, 880}, - dictWord{139, 0, 231}, - dictWord{ - 134, - 0, - 1617, - }, - dictWord{135, 0, 1957}, - dictWord{5, 11, 9}, - dictWord{7, 11, 297}, - dictWord{7, 11, 966}, - dictWord{140, 11, 306}, - dictWord{6, 0, 975}, - dictWord{ - 134, - 0, - 985, - }, - dictWord{5, 10, 950}, - dictWord{5, 10, 994}, - dictWord{134, 10, 351}, - dictWord{12, 11, 21}, - dictWord{151, 11, 7}, - dictWord{5, 11, 146}, - dictWord{ - 6, - 11, - 411, - }, - dictWord{138, 11, 721}, - dictWord{7, 0, 242}, - dictWord{135, 0, 1942}, - dictWord{6, 11, 177}, - dictWord{135, 11, 467}, - dictWord{5, 0, 421}, - dictWord{ - 7, - 10, - 47, - }, - dictWord{137, 10, 684}, - dictWord{5, 0, 834}, - dictWord{7, 0, 1202}, - dictWord{8, 0, 14}, - dictWord{9, 0, 481}, - dictWord{137, 0, 880}, - dictWord{138, 0, 465}, - dictWord{6, 0, 688}, - dictWord{9, 0, 834}, - dictWord{132, 10, 350}, - dictWord{132, 0, 855}, - dictWord{4, 0, 357}, - dictWord{6, 0, 172}, - dictWord{7, 0, 143}, - dictWord{137, 0, 413}, - dictWord{133, 11, 200}, - dictWord{132, 0, 590}, - dictWord{7, 10, 1812}, - dictWord{13, 10, 259}, - dictWord{13, 10, 356}, - dictWord{ - 14, - 10, - 242, - }, - dictWord{147, 10, 114}, - dictWord{133, 10, 967}, - dictWord{11, 0, 114}, - dictWord{4, 10, 473}, - dictWord{7, 10, 623}, - dictWord{8, 10, 808}, - dictWord{ - 9, - 10, - 871, - }, - dictWord{9, 10, 893}, - dictWord{11, 10, 431}, - dictWord{12, 10, 112}, - dictWord{12, 10, 217}, - dictWord{12, 10, 243}, - dictWord{12, 10, 562}, - dictWord{ - 12, - 10, - 663, - }, - dictWord{12, 10, 683}, - dictWord{13, 10, 141}, - dictWord{13, 10, 197}, - dictWord{13, 10, 227}, - dictWord{13, 10, 406}, - dictWord{13, 10, 487}, - dictWord{14, 10, 156}, - dictWord{14, 10, 203}, - dictWord{14, 10, 224}, - dictWord{14, 10, 256}, - dictWord{18, 10, 58}, - dictWord{150, 10, 0}, - dictWord{ - 138, - 10, - 286, - }, - dictWord{4, 10, 222}, - dictWord{7, 10, 286}, - dictWord{136, 10, 629}, - dictWord{5, 0, 169}, - dictWord{7, 0, 333}, - dictWord{136, 0, 45}, - dictWord{ - 134, - 11, - 481, - }, - dictWord{132, 0, 198}, - dictWord{4, 0, 24}, - dictWord{5, 0, 140}, - dictWord{5, 0, 185}, - dictWord{7, 0, 1500}, - dictWord{11, 0, 565}, - dictWord{11, 0, 838}, - dictWord{4, 11, 84}, - dictWord{7, 11, 1482}, - dictWord{10, 11, 76}, - dictWord{138, 11, 142}, - dictWord{133, 0, 585}, - dictWord{141, 10, 306}, - dictWord{ - 133, - 11, - 1015, - }, - dictWord{4, 11, 315}, - dictWord{5, 11, 507}, - dictWord{135, 11, 1370}, - dictWord{136, 10, 146}, - dictWord{6, 0, 691}, - dictWord{134, 0, 1503}, - dictWord{ - 4, - 0, - 334, - }, - dictWord{133, 0, 593}, - dictWord{4, 10, 465}, - dictWord{135, 10, 1663}, - dictWord{142, 11, 173}, - dictWord{135, 0, 913}, - dictWord{12, 0, 116}, - dictWord{134, 11, 1722}, - dictWord{134, 0, 1360}, - dictWord{132, 0, 802}, - dictWord{8, 11, 222}, - dictWord{8, 11, 476}, - dictWord{9, 11, 238}, - dictWord{ - 11, - 11, - 516, - }, - dictWord{11, 11, 575}, - dictWord{15, 11, 109}, - dictWord{146, 11, 100}, - dictWord{6, 0, 308}, - dictWord{9, 0, 673}, - dictWord{7, 10, 138}, - dictWord{ - 7, - 10, - 517, - }, - dictWord{139, 10, 238}, - dictWord{132, 0, 709}, - dictWord{6, 0, 1876}, - dictWord{6, 0, 1895}, - dictWord{9, 0, 994}, - dictWord{9, 0, 1006}, - dictWord{ - 12, - 0, - 829, - }, - dictWord{12, 0, 888}, - dictWord{12, 0, 891}, - dictWord{146, 0, 185}, - dictWord{148, 10, 94}, - dictWord{4, 0, 228}, - dictWord{133, 0, 897}, - dictWord{ - 7, - 0, - 1840, - }, - dictWord{5, 10, 495}, - dictWord{7, 10, 834}, - dictWord{9, 10, 733}, - dictWord{139, 10, 378}, - dictWord{133, 10, 559}, - dictWord{6, 10, 21}, - dictWord{ - 6, - 10, - 1737, - }, - dictWord{7, 10, 1444}, - dictWord{136, 10, 224}, - dictWord{4, 0, 608}, - dictWord{133, 0, 497}, - dictWord{6, 11, 40}, - dictWord{135, 11, 1781}, - dictWord{134, 0, 1573}, - dictWord{135, 0, 2039}, - dictWord{6, 0, 540}, - dictWord{136, 0, 136}, - dictWord{4, 0, 897}, - dictWord{5, 0, 786}, - dictWord{133, 10, 519}, - dictWord{6, 0, 1878}, - dictWord{6, 0, 1884}, - dictWord{9, 0, 938}, - dictWord{9, 0, 948}, - dictWord{9, 0, 955}, - dictWord{9, 0, 973}, - dictWord{9, 0, 1012}, - dictWord{ - 12, - 0, - 895, - }, - dictWord{12, 0, 927}, - dictWord{143, 0, 254}, - dictWord{134, 0, 1469}, - dictWord{133, 0, 999}, - dictWord{4, 0, 299}, - dictWord{135, 0, 1004}, - dictWord{ - 4, - 0, - 745, - }, - dictWord{133, 0, 578}, - dictWord{136, 11, 574}, - dictWord{133, 0, 456}, - dictWord{134, 0, 1457}, - dictWord{7, 0, 1679}, - dictWord{132, 10, 402}, - dictWord{7, 0, 693}, - dictWord{8, 0, 180}, - dictWord{12, 0, 163}, - dictWord{8, 10, 323}, - dictWord{136, 10, 479}, - dictWord{11, 10, 580}, - dictWord{142, 10, 201}, - dictWord{5, 10, 59}, - dictWord{135, 10, 672}, - dictWord{132, 11, 354}, - dictWord{146, 10, 34}, - dictWord{4, 0, 755}, - dictWord{135, 11, 1558}, - dictWord{ - 7, - 0, - 1740, - }, - dictWord{146, 0, 48}, - dictWord{4, 10, 85}, - dictWord{135, 10, 549}, - dictWord{139, 0, 338}, - dictWord{133, 10, 94}, - dictWord{134, 0, 1091}, - dictWord{135, 11, 469}, - dictWord{12, 0, 695}, - dictWord{12, 0, 704}, - dictWord{20, 0, 113}, - dictWord{5, 11, 830}, - dictWord{14, 11, 338}, - dictWord{148, 11, 81}, - dictWord{135, 0, 1464}, - dictWord{6, 10, 11}, - dictWord{135, 10, 187}, - dictWord{135, 0, 975}, - dictWord{13, 0, 335}, - dictWord{132, 10, 522}, - dictWord{ - 134, - 0, - 1979, - }, - dictWord{5, 11, 496}, - dictWord{135, 11, 203}, - dictWord{4, 10, 52}, - dictWord{135, 10, 661}, - dictWord{7, 0, 1566}, - dictWord{8, 0, 269}, - dictWord{ - 9, - 0, - 212, - }, - dictWord{9, 0, 718}, - dictWord{14, 0, 15}, - dictWord{14, 0, 132}, - dictWord{142, 0, 227}, - dictWord{4, 0, 890}, - dictWord{5, 0, 805}, - dictWord{5, 0, 819}, - dictWord{ - 5, - 0, - 961, - }, - dictWord{6, 0, 396}, - dictWord{6, 0, 1631}, - dictWord{6, 0, 1678}, - dictWord{7, 0, 1967}, - dictWord{7, 0, 2041}, - dictWord{9, 0, 630}, - dictWord{11, 0, 8}, - dictWord{11, 0, 1019}, - dictWord{12, 0, 176}, - dictWord{13, 0, 225}, - dictWord{14, 0, 292}, - dictWord{21, 0, 24}, - dictWord{4, 10, 383}, - dictWord{133, 10, 520}, - dictWord{134, 11, 547}, - dictWord{135, 11, 1748}, - dictWord{5, 11, 88}, - dictWord{137, 11, 239}, - dictWord{146, 11, 128}, - dictWord{7, 11, 650}, - dictWord{ - 135, - 11, - 1310, - }, - dictWord{4, 10, 281}, - dictWord{5, 10, 38}, - dictWord{7, 10, 194}, - dictWord{7, 10, 668}, - dictWord{7, 10, 1893}, - dictWord{137, 10, 397}, - dictWord{135, 0, 1815}, - dictWord{9, 10, 635}, - dictWord{139, 10, 559}, - dictWord{7, 0, 1505}, - dictWord{10, 0, 190}, - dictWord{10, 0, 634}, - dictWord{11, 0, 792}, - dictWord{12, 0, 358}, - dictWord{140, 0, 447}, - dictWord{5, 0, 0}, - dictWord{6, 0, 536}, - dictWord{7, 0, 604}, - dictWord{13, 0, 445}, - dictWord{145, 0, 126}, - dictWord{ - 7, - 11, - 1076, - }, - dictWord{9, 11, 80}, - dictWord{11, 11, 78}, - dictWord{11, 11, 421}, - dictWord{11, 11, 534}, - dictWord{140, 11, 545}, - dictWord{8, 0, 966}, - dictWord{ - 10, - 0, - 1023, - }, - dictWord{14, 11, 369}, - dictWord{146, 11, 72}, - dictWord{135, 11, 1641}, - dictWord{6, 0, 232}, - dictWord{6, 0, 412}, - dictWord{7, 0, 1074}, - dictWord{ - 8, - 0, - 9, - }, - dictWord{8, 0, 157}, - dictWord{8, 0, 786}, - dictWord{9, 0, 196}, - dictWord{9, 0, 352}, - dictWord{9, 0, 457}, - dictWord{10, 0, 337}, - dictWord{11, 0, 232}, - dictWord{ - 11, - 0, - 877, - }, - dictWord{12, 0, 480}, - dictWord{140, 0, 546}, - dictWord{135, 0, 958}, - dictWord{4, 0, 382}, - dictWord{136, 0, 579}, - dictWord{4, 0, 212}, - dictWord{ - 135, - 0, - 1206, - }, - dictWord{4, 11, 497}, - dictWord{5, 11, 657}, - dictWord{135, 11, 1584}, - dictWord{132, 0, 681}, - dictWord{8, 0, 971}, - dictWord{138, 0, 965}, - dictWord{ - 5, - 10, - 448, - }, - dictWord{136, 10, 535}, - dictWord{14, 0, 16}, - dictWord{146, 0, 44}, - dictWord{11, 0, 584}, - dictWord{11, 0, 616}, - dictWord{14, 0, 275}, - dictWord{ - 11, - 11, - 584, - }, - dictWord{11, 11, 616}, - dictWord{142, 11, 275}, - dictWord{136, 11, 13}, - dictWord{7, 10, 610}, - dictWord{135, 10, 1501}, - dictWord{7, 11, 642}, - dictWord{8, 11, 250}, - dictWord{11, 11, 123}, - dictWord{11, 11, 137}, - dictWord{13, 11, 48}, - dictWord{142, 11, 95}, - dictWord{133, 0, 655}, - dictWord{17, 0, 67}, - dictWord{147, 0, 74}, - dictWord{134, 0, 751}, - dictWord{134, 0, 1967}, - dictWord{6, 0, 231}, - dictWord{136, 0, 423}, - dictWord{5, 0, 300}, - dictWord{138, 0, 1016}, - dictWord{4, 10, 319}, - dictWord{5, 10, 699}, - dictWord{138, 10, 673}, - dictWord{6, 0, 237}, - dictWord{7, 0, 611}, - dictWord{8, 0, 100}, - dictWord{9, 0, 416}, - dictWord{ - 11, - 0, - 335, - }, - dictWord{12, 0, 173}, - dictWord{18, 0, 101}, - dictWord{6, 10, 336}, - dictWord{8, 10, 552}, - dictWord{9, 10, 285}, - dictWord{10, 10, 99}, - dictWord{ - 139, - 10, - 568, - }, - dictWord{134, 0, 1370}, - dictWord{7, 10, 1406}, - dictWord{9, 10, 218}, - dictWord{141, 10, 222}, - dictWord{133, 10, 256}, - dictWord{ - 135, - 0, - 1208, - }, - dictWord{14, 11, 213}, - dictWord{148, 11, 38}, - dictWord{6, 0, 1219}, - dictWord{135, 11, 1642}, - dictWord{13, 0, 417}, - dictWord{14, 0, 129}, - dictWord{143, 0, 15}, - dictWord{10, 11, 545}, - dictWord{140, 11, 301}, - dictWord{17, 10, 39}, - dictWord{148, 10, 36}, - dictWord{133, 0, 199}, - dictWord{4, 11, 904}, - dictWord{133, 11, 794}, - dictWord{12, 0, 427}, - dictWord{146, 0, 38}, - dictWord{134, 0, 949}, - dictWord{8, 0, 665}, - dictWord{135, 10, 634}, - dictWord{ - 132, - 10, - 618, - }, - dictWord{135, 10, 259}, - dictWord{132, 10, 339}, - dictWord{133, 11, 761}, - dictWord{141, 10, 169}, - dictWord{132, 10, 759}, - dictWord{5, 0, 688}, - dictWord{7, 0, 539}, - dictWord{135, 0, 712}, - dictWord{7, 11, 386}, - dictWord{138, 11, 713}, - dictWord{134, 0, 1186}, - dictWord{6, 11, 7}, - dictWord{6, 11, 35}, - dictWord{ - 7, - 11, - 147, - }, - dictWord{7, 11, 1069}, - dictWord{7, 11, 1568}, - dictWord{7, 11, 1575}, - dictWord{7, 11, 1917}, - dictWord{8, 11, 43}, - dictWord{8, 11, 208}, - dictWord{ - 9, - 11, - 128, - }, - dictWord{9, 11, 866}, - dictWord{10, 11, 20}, - dictWord{11, 11, 981}, - dictWord{147, 11, 33}, - dictWord{7, 11, 893}, - dictWord{8, 10, 482}, - dictWord{141, 11, 424}, - dictWord{6, 0, 312}, - dictWord{6, 0, 1715}, - dictWord{10, 0, 584}, - dictWord{11, 0, 546}, - dictWord{11, 0, 692}, - dictWord{12, 0, 259}, - dictWord{ - 12, - 0, - 295, - }, - dictWord{13, 0, 46}, - dictWord{141, 0, 154}, - dictWord{5, 10, 336}, - dictWord{6, 10, 341}, - dictWord{6, 10, 478}, - dictWord{6, 10, 1763}, - dictWord{ - 136, - 10, - 386, - }, - dictWord{137, 0, 151}, - dictWord{132, 0, 588}, - dictWord{152, 0, 4}, - dictWord{6, 11, 322}, - dictWord{9, 11, 552}, - dictWord{11, 11, 274}, - dictWord{ - 13, - 11, - 209, - }, - dictWord{13, 11, 499}, - dictWord{14, 11, 85}, - dictWord{15, 11, 126}, - dictWord{145, 11, 70}, - dictWord{135, 10, 73}, - dictWord{4, 0, 231}, - dictWord{ - 5, - 0, - 61, - }, - dictWord{6, 0, 104}, - dictWord{7, 0, 729}, - dictWord{7, 0, 964}, - dictWord{7, 0, 1658}, - dictWord{140, 0, 414}, - dictWord{6, 0, 263}, - dictWord{138, 0, 757}, - dictWord{135, 10, 1971}, - dictWord{4, 0, 612}, - dictWord{133, 0, 561}, - dictWord{132, 0, 320}, - dictWord{135, 10, 1344}, - dictWord{8, 11, 83}, - dictWord{ - 8, - 11, - 817, - }, - dictWord{9, 11, 28}, - dictWord{9, 11, 29}, - dictWord{9, 11, 885}, - dictWord{10, 11, 387}, - dictWord{11, 11, 633}, - dictWord{11, 11, 740}, - dictWord{ - 13, - 11, - 235, - }, - dictWord{13, 11, 254}, - dictWord{15, 11, 143}, - dictWord{143, 11, 146}, - dictWord{5, 10, 396}, - dictWord{134, 10, 501}, - dictWord{140, 11, 49}, - dictWord{132, 0, 225}, - dictWord{4, 10, 929}, - dictWord{5, 10, 799}, - dictWord{8, 10, 46}, - dictWord{136, 10, 740}, - dictWord{4, 0, 405}, - dictWord{7, 0, 817}, - dictWord{ - 14, - 0, - 58, - }, - dictWord{17, 0, 37}, - dictWord{146, 0, 124}, - dictWord{133, 0, 974}, - dictWord{4, 11, 412}, - dictWord{133, 11, 581}, - dictWord{4, 10, 892}, - dictWord{ - 133, - 10, - 770, - }, - dictWord{4, 0, 996}, - dictWord{134, 0, 2026}, - dictWord{4, 0, 527}, - dictWord{5, 0, 235}, - dictWord{7, 0, 1239}, - dictWord{11, 0, 131}, - dictWord{ - 140, - 0, - 370, - }, - dictWord{9, 0, 16}, - dictWord{13, 0, 386}, - dictWord{135, 11, 421}, - dictWord{7, 0, 956}, - dictWord{7, 0, 1157}, - dictWord{7, 0, 1506}, - dictWord{7, 0, 1606}, - dictWord{7, 0, 1615}, - dictWord{7, 0, 1619}, - dictWord{7, 0, 1736}, - dictWord{7, 0, 1775}, - dictWord{8, 0, 590}, - dictWord{9, 0, 324}, - dictWord{9, 0, 736}, - dictWord{ - 9, - 0, - 774, - }, - dictWord{9, 0, 776}, - dictWord{9, 0, 784}, - dictWord{10, 0, 567}, - dictWord{10, 0, 708}, - dictWord{11, 0, 518}, - dictWord{11, 0, 613}, - dictWord{11, 0, 695}, - dictWord{11, 0, 716}, - dictWord{11, 0, 739}, - dictWord{11, 0, 770}, - dictWord{11, 0, 771}, - dictWord{11, 0, 848}, - dictWord{11, 0, 857}, - dictWord{11, 0, 931}, - dictWord{ - 11, - 0, - 947, - }, - dictWord{12, 0, 326}, - dictWord{12, 0, 387}, - dictWord{12, 0, 484}, - dictWord{12, 0, 528}, - dictWord{12, 0, 552}, - dictWord{12, 0, 613}, - dictWord{ - 13, - 0, - 189, - }, - dictWord{13, 0, 256}, - dictWord{13, 0, 340}, - dictWord{13, 0, 432}, - dictWord{13, 0, 436}, - dictWord{13, 0, 440}, - dictWord{13, 0, 454}, - dictWord{14, 0, 174}, - dictWord{14, 0, 220}, - dictWord{14, 0, 284}, - dictWord{14, 0, 390}, - dictWord{145, 0, 121}, - dictWord{135, 10, 158}, - dictWord{9, 0, 137}, - dictWord{138, 0, 221}, - dictWord{4, 11, 110}, - dictWord{10, 11, 415}, - dictWord{10, 11, 597}, - dictWord{142, 11, 206}, - dictWord{141, 11, 496}, - dictWord{135, 11, 205}, - dictWord{ - 151, - 10, - 25, - }, - dictWord{135, 11, 778}, - dictWord{7, 11, 1656}, - dictWord{7, 10, 2001}, - dictWord{9, 11, 369}, - dictWord{10, 11, 338}, - dictWord{10, 11, 490}, - dictWord{11, 11, 154}, - dictWord{11, 11, 545}, - dictWord{11, 11, 775}, - dictWord{13, 11, 77}, - dictWord{141, 11, 274}, - dictWord{4, 11, 444}, - dictWord{ - 10, - 11, - 146, - }, - dictWord{140, 11, 9}, - dictWord{7, 0, 390}, - dictWord{138, 0, 140}, - dictWord{135, 0, 1144}, - dictWord{134, 0, 464}, - dictWord{7, 10, 1461}, - dictWord{ - 140, - 10, - 91, - }, - dictWord{132, 10, 602}, - dictWord{4, 11, 283}, - dictWord{135, 11, 1194}, - dictWord{5, 0, 407}, - dictWord{11, 0, 204}, - dictWord{11, 0, 243}, - dictWord{ - 11, - 0, - 489, - }, - dictWord{12, 0, 293}, - dictWord{19, 0, 37}, - dictWord{20, 0, 73}, - dictWord{150, 0, 38}, - dictWord{7, 0, 1218}, - dictWord{136, 0, 303}, - dictWord{ - 5, - 0, - 325, - }, - dictWord{8, 0, 5}, - dictWord{8, 0, 227}, - dictWord{9, 0, 105}, - dictWord{10, 0, 585}, - dictWord{12, 0, 614}, - dictWord{4, 10, 13}, - dictWord{5, 10, 567}, - dictWord{ - 7, - 10, - 1498, - }, - dictWord{9, 10, 124}, - dictWord{11, 10, 521}, - dictWord{140, 10, 405}, - dictWord{135, 10, 1006}, - dictWord{7, 0, 800}, - dictWord{10, 0, 12}, - dictWord{134, 11, 1720}, - dictWord{135, 0, 1783}, - dictWord{132, 10, 735}, - dictWord{138, 10, 812}, - dictWord{4, 10, 170}, - dictWord{135, 10, 323}, - dictWord{ - 6, - 0, - 621, - }, - dictWord{13, 0, 504}, - dictWord{144, 0, 89}, - dictWord{5, 10, 304}, - dictWord{135, 10, 1403}, - dictWord{137, 11, 216}, - dictWord{6, 0, 920}, - dictWord{ - 6, - 0, - 1104, - }, - dictWord{9, 11, 183}, - dictWord{139, 11, 286}, - dictWord{4, 0, 376}, - dictWord{133, 10, 742}, - dictWord{134, 0, 218}, - dictWord{8, 0, 641}, - dictWord{ - 11, - 0, - 388, - }, - dictWord{140, 0, 580}, - dictWord{7, 0, 454}, - dictWord{7, 0, 782}, - dictWord{8, 0, 768}, - dictWord{140, 0, 686}, - dictWord{137, 11, 33}, - dictWord{ - 133, - 10, - 111, - }, - dictWord{144, 0, 0}, - dictWord{10, 0, 676}, - dictWord{140, 0, 462}, - dictWord{6, 0, 164}, - dictWord{136, 11, 735}, - dictWord{133, 10, 444}, - dictWord{ - 150, - 0, - 50, - }, - dictWord{7, 11, 1862}, - dictWord{12, 11, 491}, - dictWord{12, 11, 520}, - dictWord{13, 11, 383}, - dictWord{14, 11, 244}, - dictWord{146, 11, 12}, - dictWord{ - 5, - 11, - 132, - }, - dictWord{9, 11, 486}, - dictWord{9, 11, 715}, - dictWord{10, 11, 458}, - dictWord{11, 11, 373}, - dictWord{11, 11, 668}, - dictWord{11, 11, 795}, - dictWord{11, 11, 897}, - dictWord{12, 11, 272}, - dictWord{12, 11, 424}, - dictWord{12, 11, 539}, - dictWord{12, 11, 558}, - dictWord{14, 11, 245}, - dictWord{ - 14, - 11, - 263, - }, - dictWord{14, 11, 264}, - dictWord{14, 11, 393}, - dictWord{142, 11, 403}, - dictWord{8, 10, 123}, - dictWord{15, 10, 6}, - dictWord{144, 10, 7}, - dictWord{ - 6, - 0, - 285, - }, - dictWord{8, 0, 654}, - dictWord{11, 0, 749}, - dictWord{12, 0, 190}, - dictWord{12, 0, 327}, - dictWord{13, 0, 120}, - dictWord{13, 0, 121}, - dictWord{13, 0, 327}, - dictWord{15, 0, 47}, - dictWord{146, 0, 40}, - dictWord{5, 11, 8}, - dictWord{6, 11, 89}, - dictWord{6, 11, 400}, - dictWord{7, 11, 1569}, - dictWord{7, 11, 1623}, - dictWord{ - 7, - 11, - 1850, - }, - dictWord{8, 11, 218}, - dictWord{8, 11, 422}, - dictWord{9, 11, 570}, - dictWord{138, 11, 626}, - dictWord{6, 11, 387}, - dictWord{7, 11, 882}, - dictWord{141, 11, 111}, - dictWord{6, 0, 343}, - dictWord{7, 0, 195}, - dictWord{9, 0, 226}, - dictWord{10, 0, 197}, - dictWord{10, 0, 575}, - dictWord{11, 0, 502}, - dictWord{ - 11, - 0, - 899, - }, - dictWord{6, 11, 224}, - dictWord{7, 11, 877}, - dictWord{137, 11, 647}, - dictWord{5, 10, 937}, - dictWord{135, 10, 100}, - dictWord{135, 11, 790}, - dictWord{150, 0, 29}, - dictWord{147, 0, 8}, - dictWord{134, 0, 1812}, - dictWord{149, 0, 8}, - dictWord{135, 11, 394}, - dictWord{7, 0, 1125}, - dictWord{9, 0, 143}, - dictWord{ - 11, - 0, - 61, - }, - dictWord{14, 0, 405}, - dictWord{150, 0, 21}, - dictWord{10, 11, 755}, - dictWord{147, 11, 29}, - dictWord{9, 11, 378}, - dictWord{141, 11, 162}, - dictWord{135, 10, 922}, - dictWord{5, 10, 619}, - dictWord{133, 10, 698}, - dictWord{134, 0, 1327}, - dictWord{6, 0, 1598}, - dictWord{137, 0, 575}, - dictWord{ - 9, - 11, - 569, - }, - dictWord{12, 11, 12}, - dictWord{12, 11, 81}, - dictWord{12, 11, 319}, - dictWord{13, 11, 69}, - dictWord{14, 11, 259}, - dictWord{16, 11, 87}, - dictWord{ - 17, - 11, - 1, - }, - dictWord{17, 11, 21}, - dictWord{17, 11, 24}, - dictWord{18, 11, 15}, - dictWord{18, 11, 56}, - dictWord{18, 11, 59}, - dictWord{18, 11, 127}, - dictWord{18, 11, 154}, - dictWord{19, 11, 19}, - dictWord{148, 11, 31}, - dictWord{6, 0, 895}, - dictWord{135, 11, 1231}, - dictWord{5, 0, 959}, - dictWord{7, 11, 124}, - dictWord{136, 11, 38}, - dictWord{5, 11, 261}, - dictWord{7, 11, 78}, - dictWord{7, 11, 199}, - dictWord{8, 11, 815}, - dictWord{9, 11, 126}, - dictWord{138, 11, 342}, - dictWord{5, 10, 917}, - dictWord{134, 10, 1659}, - dictWord{7, 0, 1759}, - dictWord{5, 11, 595}, - dictWord{135, 11, 1863}, - dictWord{136, 0, 173}, - dictWord{134, 0, 266}, - dictWord{ - 142, - 0, - 261, - }, - dictWord{132, 11, 628}, - dictWord{5, 10, 251}, - dictWord{5, 10, 956}, - dictWord{8, 10, 268}, - dictWord{9, 10, 214}, - dictWord{146, 10, 142}, - dictWord{ - 7, - 11, - 266, - }, - dictWord{136, 11, 804}, - dictWord{135, 11, 208}, - dictWord{6, 11, 79}, - dictWord{7, 11, 1021}, - dictWord{135, 11, 1519}, - dictWord{11, 11, 704}, - dictWord{141, 11, 396}, - dictWord{5, 10, 346}, - dictWord{5, 10, 711}, - dictWord{136, 10, 390}, - dictWord{136, 11, 741}, - dictWord{134, 11, 376}, - dictWord{ - 134, - 0, - 1427, - }, - dictWord{6, 0, 1033}, - dictWord{6, 0, 1217}, - dictWord{136, 0, 300}, - dictWord{133, 10, 624}, - dictWord{6, 11, 100}, - dictWord{7, 11, 244}, - dictWord{ - 7, - 11, - 632, - }, - dictWord{7, 11, 1609}, - dictWord{8, 11, 178}, - dictWord{8, 11, 638}, - dictWord{141, 11, 58}, - dictWord{6, 0, 584}, - dictWord{5, 10, 783}, - dictWord{ - 7, - 10, - 1998, - }, - dictWord{135, 10, 2047}, - dictWord{5, 0, 427}, - dictWord{5, 0, 734}, - dictWord{7, 0, 478}, - dictWord{136, 0, 52}, - dictWord{7, 0, 239}, - dictWord{ - 11, - 0, - 217, - }, - dictWord{142, 0, 165}, - dictWord{134, 0, 1129}, - dictWord{6, 0, 168}, - dictWord{6, 0, 1734}, - dictWord{7, 0, 20}, - dictWord{7, 0, 1056}, - dictWord{8, 0, 732}, - dictWord{9, 0, 406}, - dictWord{9, 0, 911}, - dictWord{138, 0, 694}, - dictWord{132, 10, 594}, - dictWord{133, 11, 791}, - dictWord{7, 11, 686}, - dictWord{8, 11, 33}, - dictWord{8, 11, 238}, - dictWord{10, 11, 616}, - dictWord{11, 11, 467}, - dictWord{11, 11, 881}, - dictWord{13, 11, 217}, - dictWord{13, 11, 253}, - dictWord{ - 142, - 11, - 268, - }, - dictWord{137, 11, 476}, - dictWord{134, 0, 418}, - dictWord{133, 0, 613}, - dictWord{132, 0, 632}, - dictWord{132, 11, 447}, - dictWord{7, 0, 32}, - dictWord{ - 7, - 0, - 984, - }, - dictWord{8, 0, 85}, - dictWord{8, 0, 709}, - dictWord{9, 0, 579}, - dictWord{9, 0, 847}, - dictWord{9, 0, 856}, - dictWord{10, 0, 799}, - dictWord{11, 0, 258}, - dictWord{ - 11, - 0, - 1007, - }, - dictWord{12, 0, 331}, - dictWord{12, 0, 615}, - dictWord{13, 0, 188}, - dictWord{13, 0, 435}, - dictWord{14, 0, 8}, - dictWord{15, 0, 165}, - dictWord{ - 16, - 0, - 27, - }, - dictWord{20, 0, 40}, - dictWord{144, 11, 35}, - dictWord{4, 11, 128}, - dictWord{5, 11, 415}, - dictWord{6, 11, 462}, - dictWord{7, 11, 294}, - dictWord{7, 11, 578}, - dictWord{10, 11, 710}, - dictWord{139, 11, 86}, - dictWord{5, 0, 694}, - dictWord{136, 0, 909}, - dictWord{7, 0, 1109}, - dictWord{11, 0, 7}, - dictWord{5, 10, 37}, - dictWord{ - 6, - 10, - 39, - }, - dictWord{6, 10, 451}, - dictWord{7, 10, 218}, - dictWord{7, 10, 1166}, - dictWord{7, 10, 1687}, - dictWord{8, 10, 662}, - dictWord{144, 10, 2}, - dictWord{ - 136, - 11, - 587, - }, - dictWord{6, 11, 427}, - dictWord{7, 11, 1018}, - dictWord{138, 11, 692}, - dictWord{4, 11, 195}, - dictWord{6, 10, 508}, - dictWord{135, 11, 802}, - dictWord{4, 0, 167}, - dictWord{135, 0, 82}, - dictWord{5, 0, 62}, - dictWord{6, 0, 24}, - dictWord{6, 0, 534}, - dictWord{7, 0, 74}, - dictWord{7, 0, 678}, - dictWord{7, 0, 684}, - dictWord{ - 7, - 0, - 1043, - }, - dictWord{7, 0, 1072}, - dictWord{8, 0, 280}, - dictWord{8, 0, 541}, - dictWord{8, 0, 686}, - dictWord{9, 0, 258}, - dictWord{10, 0, 519}, - dictWord{11, 0, 252}, - dictWord{140, 0, 282}, - dictWord{138, 0, 33}, - dictWord{4, 0, 359}, - dictWord{133, 11, 738}, - dictWord{7, 0, 980}, - dictWord{9, 0, 328}, - dictWord{13, 0, 186}, - dictWord{13, 0, 364}, - dictWord{7, 10, 635}, - dictWord{7, 10, 796}, - dictWord{8, 10, 331}, - dictWord{9, 10, 330}, - dictWord{9, 10, 865}, - dictWord{10, 10, 119}, - dictWord{ - 10, - 10, - 235, - }, - dictWord{11, 10, 111}, - dictWord{11, 10, 129}, - dictWord{11, 10, 240}, - dictWord{12, 10, 31}, - dictWord{12, 10, 66}, - dictWord{12, 10, 222}, - dictWord{12, 10, 269}, - dictWord{12, 10, 599}, - dictWord{12, 10, 684}, - dictWord{12, 10, 689}, - dictWord{12, 10, 691}, - dictWord{142, 10, 345}, - dictWord{ - 137, - 10, - 527, - }, - dictWord{6, 0, 596}, - dictWord{7, 0, 585}, - dictWord{135, 10, 702}, - dictWord{134, 11, 1683}, - dictWord{133, 0, 211}, - dictWord{6, 0, 145}, - dictWord{ - 141, - 0, - 336, - }, - dictWord{134, 0, 1130}, - dictWord{7, 0, 873}, - dictWord{6, 10, 37}, - dictWord{7, 10, 1666}, - dictWord{8, 10, 195}, - dictWord{8, 10, 316}, - dictWord{ - 9, - 10, - 178, - }, - dictWord{9, 10, 276}, - dictWord{9, 10, 339}, - dictWord{9, 10, 536}, - dictWord{10, 10, 102}, - dictWord{10, 10, 362}, - dictWord{10, 10, 785}, - dictWord{ - 11, - 10, - 55, - }, - dictWord{11, 10, 149}, - dictWord{11, 10, 773}, - dictWord{13, 10, 416}, - dictWord{13, 10, 419}, - dictWord{14, 10, 38}, - dictWord{14, 10, 41}, - dictWord{ - 142, - 10, - 210, - }, - dictWord{8, 0, 840}, - dictWord{136, 0, 841}, - dictWord{132, 0, 263}, - dictWord{5, 11, 3}, - dictWord{8, 11, 578}, - dictWord{9, 11, 118}, - dictWord{ - 10, - 11, - 705, - }, - dictWord{12, 11, 383}, - dictWord{141, 11, 279}, - dictWord{132, 0, 916}, - dictWord{133, 11, 229}, - dictWord{133, 10, 645}, - dictWord{15, 0, 155}, - dictWord{16, 0, 79}, - dictWord{8, 11, 102}, - dictWord{10, 11, 578}, - dictWord{10, 11, 672}, - dictWord{12, 11, 496}, - dictWord{13, 11, 408}, - dictWord{14, 11, 121}, - dictWord{145, 11, 106}, - dictWord{4, 0, 599}, - dictWord{5, 0, 592}, - dictWord{6, 0, 1634}, - dictWord{7, 0, 5}, - dictWord{7, 0, 55}, - dictWord{7, 0, 67}, - dictWord{7, 0, 97}, - dictWord{7, 0, 691}, - dictWord{7, 0, 979}, - dictWord{7, 0, 1600}, - dictWord{7, 0, 1697}, - dictWord{8, 0, 207}, - dictWord{8, 0, 214}, - dictWord{8, 0, 231}, - dictWord{8, 0, 294}, - dictWord{8, 0, 336}, - dictWord{8, 0, 428}, - dictWord{8, 0, 471}, - dictWord{8, 0, 622}, - dictWord{8, 0, 626}, - dictWord{8, 0, 679}, - dictWord{8, 0, 759}, - dictWord{8, 0, 829}, - dictWord{9, 0, 11}, - dictWord{9, 0, 246}, - dictWord{9, 0, 484}, - dictWord{9, 0, 573}, - dictWord{9, 0, 706}, - dictWord{9, 0, 762}, - dictWord{9, 0, 798}, - dictWord{9, 0, 855}, - dictWord{9, 0, 870}, - dictWord{9, 0, 912}, - dictWord{10, 0, 303}, - dictWord{10, 0, 335}, - dictWord{10, 0, 424}, - dictWord{10, 0, 461}, - dictWord{10, 0, 543}, - dictWord{ - 10, - 0, - 759, - }, - dictWord{10, 0, 814}, - dictWord{11, 0, 59}, - dictWord{11, 0, 199}, - dictWord{11, 0, 235}, - dictWord{11, 0, 590}, - dictWord{11, 0, 631}, - dictWord{11, 0, 929}, - dictWord{11, 0, 963}, - dictWord{11, 0, 987}, - dictWord{12, 0, 114}, - dictWord{12, 0, 182}, - dictWord{12, 0, 226}, - dictWord{12, 0, 332}, - dictWord{12, 0, 439}, - dictWord{12, 0, 575}, - dictWord{12, 0, 598}, - dictWord{12, 0, 675}, - dictWord{13, 0, 8}, - dictWord{13, 0, 125}, - dictWord{13, 0, 194}, - dictWord{13, 0, 287}, - dictWord{ - 14, - 0, - 197, - }, - dictWord{14, 0, 383}, - dictWord{15, 0, 53}, - dictWord{17, 0, 63}, - dictWord{19, 0, 46}, - dictWord{19, 0, 98}, - dictWord{19, 0, 106}, - dictWord{148, 0, 85}, - dictWord{ - 7, - 0, - 1356, - }, - dictWord{132, 10, 290}, - dictWord{6, 10, 70}, - dictWord{7, 10, 1292}, - dictWord{10, 10, 762}, - dictWord{139, 10, 288}, - dictWord{150, 11, 55}, - dictWord{4, 0, 593}, - dictWord{8, 11, 115}, - dictWord{8, 11, 350}, - dictWord{9, 11, 489}, - dictWord{10, 11, 128}, - dictWord{11, 11, 306}, - dictWord{12, 11, 373}, - dictWord{14, 11, 30}, - dictWord{17, 11, 79}, - dictWord{147, 11, 80}, - dictWord{135, 11, 1235}, - dictWord{134, 0, 1392}, - dictWord{4, 11, 230}, - dictWord{ - 133, - 11, - 702, - }, - dictWord{147, 0, 126}, - dictWord{7, 10, 131}, - dictWord{7, 10, 422}, - dictWord{8, 10, 210}, - dictWord{140, 10, 573}, - dictWord{134, 0, 1179}, - dictWord{ - 139, - 11, - 435, - }, - dictWord{139, 10, 797}, - dictWord{134, 11, 1728}, - dictWord{4, 0, 162}, - dictWord{18, 11, 26}, - dictWord{19, 11, 42}, - dictWord{20, 11, 43}, - dictWord{21, 11, 0}, - dictWord{23, 11, 27}, - dictWord{152, 11, 14}, - dictWord{132, 10, 936}, - dictWord{6, 0, 765}, - dictWord{5, 10, 453}, - dictWord{134, 10, 441}, - dictWord{133, 0, 187}, - dictWord{135, 0, 1286}, - dictWord{6, 0, 635}, - dictWord{6, 0, 904}, - dictWord{6, 0, 1210}, - dictWord{134, 0, 1489}, - dictWord{4, 0, 215}, - dictWord{ - 8, - 0, - 890, - }, - dictWord{9, 0, 38}, - dictWord{10, 0, 923}, - dictWord{11, 0, 23}, - dictWord{11, 0, 127}, - dictWord{139, 0, 796}, - dictWord{6, 0, 1165}, - dictWord{ - 134, - 0, - 1306, - }, - dictWord{7, 0, 716}, - dictWord{13, 0, 97}, - dictWord{141, 0, 251}, - dictWord{132, 10, 653}, - dictWord{136, 0, 657}, - dictWord{146, 10, 80}, - dictWord{ - 5, - 11, - 622, - }, - dictWord{7, 11, 1032}, - dictWord{11, 11, 26}, - dictWord{11, 11, 213}, - dictWord{11, 11, 707}, - dictWord{12, 11, 380}, - dictWord{13, 11, 226}, - dictWord{141, 11, 355}, - dictWord{6, 0, 299}, - dictWord{5, 11, 70}, - dictWord{6, 11, 334}, - dictWord{9, 11, 171}, - dictWord{11, 11, 637}, - dictWord{12, 11, 202}, - dictWord{14, 11, 222}, - dictWord{145, 11, 42}, - dictWord{142, 0, 134}, - dictWord{4, 11, 23}, - dictWord{5, 11, 313}, - dictWord{5, 11, 1014}, - dictWord{6, 11, 50}, - dictWord{ - 6, - 11, - 51, - }, - dictWord{7, 11, 142}, - dictWord{7, 11, 384}, - dictWord{9, 11, 783}, - dictWord{139, 11, 741}, - dictWord{4, 11, 141}, - dictWord{7, 11, 559}, - dictWord{ - 8, - 11, - 640, - }, - dictWord{9, 11, 460}, - dictWord{12, 11, 183}, - dictWord{141, 11, 488}, - dictWord{136, 11, 614}, - dictWord{7, 10, 1368}, - dictWord{8, 10, 232}, - dictWord{8, 10, 361}, - dictWord{10, 10, 682}, - dictWord{138, 10, 742}, - dictWord{137, 10, 534}, - dictWord{6, 0, 1082}, - dictWord{140, 0, 658}, - dictWord{ - 137, - 10, - 27, - }, - dictWord{135, 0, 2002}, - dictWord{142, 10, 12}, - dictWord{4, 0, 28}, - dictWord{5, 0, 440}, - dictWord{7, 0, 248}, - dictWord{11, 0, 833}, - dictWord{140, 0, 344}, - dictWord{7, 10, 736}, - dictWord{139, 10, 264}, - dictWord{134, 10, 1657}, - dictWord{134, 0, 1654}, - dictWord{138, 0, 531}, - dictWord{5, 11, 222}, - dictWord{ - 9, - 11, - 140, - }, - dictWord{138, 11, 534}, - dictWord{6, 0, 634}, - dictWord{6, 0, 798}, - dictWord{134, 0, 840}, - dictWord{138, 11, 503}, - dictWord{135, 10, 127}, - dictWord{133, 0, 853}, - dictWord{5, 11, 154}, - dictWord{7, 11, 1491}, - dictWord{10, 11, 379}, - dictWord{138, 11, 485}, - dictWord{6, 0, 249}, - dictWord{7, 0, 1234}, - dictWord{139, 0, 573}, - dictWord{133, 11, 716}, - dictWord{7, 11, 1570}, - dictWord{140, 11, 542}, - dictWord{136, 10, 364}, - dictWord{138, 0, 527}, - dictWord{ - 4, - 11, - 91, - }, - dictWord{5, 11, 388}, - dictWord{5, 11, 845}, - dictWord{6, 11, 206}, - dictWord{6, 11, 252}, - dictWord{6, 11, 365}, - dictWord{7, 11, 136}, - dictWord{7, 11, 531}, - dictWord{8, 11, 264}, - dictWord{136, 11, 621}, - dictWord{134, 0, 1419}, - dictWord{135, 11, 1441}, - dictWord{7, 0, 49}, - dictWord{7, 0, 392}, - dictWord{8, 0, 20}, - dictWord{8, 0, 172}, - dictWord{8, 0, 690}, - dictWord{9, 0, 383}, - dictWord{9, 0, 845}, - dictWord{10, 0, 48}, - dictWord{11, 0, 293}, - dictWord{11, 0, 832}, - dictWord{ - 11, - 0, - 920, - }, - dictWord{11, 0, 984}, - dictWord{141, 0, 221}, - dictWord{5, 0, 858}, - dictWord{133, 0, 992}, - dictWord{5, 0, 728}, - dictWord{137, 10, 792}, - dictWord{ - 5, - 10, - 909, - }, - dictWord{9, 10, 849}, - dictWord{138, 10, 805}, - dictWord{7, 0, 525}, - dictWord{7, 0, 1579}, - dictWord{8, 0, 497}, - dictWord{136, 0, 573}, - dictWord{6, 0, 268}, - dictWord{137, 0, 62}, - dictWord{135, 11, 576}, - dictWord{134, 0, 1201}, - dictWord{5, 11, 771}, - dictWord{5, 11, 863}, - dictWord{5, 11, 898}, - dictWord{ - 6, - 11, - 1632, - }, - dictWord{6, 11, 1644}, - dictWord{134, 11, 1780}, - dictWord{133, 11, 331}, - dictWord{7, 0, 193}, - dictWord{7, 0, 1105}, - dictWord{10, 0, 495}, - dictWord{ - 7, - 10, - 397, - }, - dictWord{8, 10, 124}, - dictWord{8, 10, 619}, - dictWord{9, 10, 305}, - dictWord{11, 10, 40}, - dictWord{12, 10, 349}, - dictWord{13, 10, 134}, - dictWord{ - 13, - 10, - 295, - }, - dictWord{14, 10, 155}, - dictWord{15, 10, 120}, - dictWord{146, 10, 105}, - dictWord{138, 0, 106}, - dictWord{6, 0, 859}, - dictWord{5, 11, 107}, - dictWord{ - 7, - 11, - 201, - }, - dictWord{136, 11, 518}, - dictWord{6, 11, 446}, - dictWord{135, 11, 1817}, - dictWord{13, 0, 23}, - dictWord{4, 10, 262}, - dictWord{135, 10, 342}, - dictWord{133, 10, 641}, - dictWord{137, 11, 851}, - dictWord{6, 0, 925}, - dictWord{137, 0, 813}, - dictWord{132, 11, 504}, - dictWord{6, 0, 613}, - dictWord{ - 136, - 0, - 223, - }, - dictWord{4, 10, 99}, - dictWord{6, 10, 250}, - dictWord{6, 10, 346}, - dictWord{8, 10, 127}, - dictWord{138, 10, 81}, - dictWord{136, 0, 953}, - dictWord{ - 132, - 10, - 915, - }, - dictWord{139, 11, 892}, - dictWord{5, 10, 75}, - dictWord{9, 10, 517}, - dictWord{10, 10, 470}, - dictWord{12, 10, 155}, - dictWord{141, 10, 224}, - dictWord{ - 4, - 0, - 666, - }, - dictWord{7, 0, 1017}, - dictWord{7, 11, 996}, - dictWord{138, 11, 390}, - dictWord{5, 11, 883}, - dictWord{133, 11, 975}, - dictWord{14, 10, 83}, - dictWord{ - 142, - 11, - 83, - }, - dictWord{4, 0, 670}, - dictWord{5, 11, 922}, - dictWord{134, 11, 1707}, - dictWord{135, 0, 216}, - dictWord{9, 0, 40}, - dictWord{11, 0, 136}, - dictWord{ - 135, - 11, - 787, - }, - dictWord{5, 10, 954}, - dictWord{5, 11, 993}, - dictWord{7, 11, 515}, - dictWord{137, 11, 91}, - dictWord{139, 0, 259}, - dictWord{7, 0, 1114}, - dictWord{ - 9, - 0, - 310, - }, - dictWord{9, 0, 682}, - dictWord{10, 0, 440}, - dictWord{13, 0, 40}, - dictWord{6, 10, 304}, - dictWord{8, 10, 418}, - dictWord{11, 10, 341}, - dictWord{ - 139, - 10, - 675, - }, - dictWord{14, 0, 296}, - dictWord{9, 10, 410}, - dictWord{139, 10, 425}, - dictWord{10, 11, 377}, - dictWord{12, 11, 363}, - dictWord{13, 11, 68}, - dictWord{ - 13, - 11, - 94, - }, - dictWord{14, 11, 108}, - dictWord{142, 11, 306}, - dictWord{7, 0, 1401}, - dictWord{135, 0, 1476}, - dictWord{4, 0, 296}, - dictWord{6, 0, 475}, - dictWord{ - 7, - 0, - 401, - }, - dictWord{7, 0, 1410}, - dictWord{7, 0, 1594}, - dictWord{7, 0, 1674}, - dictWord{8, 0, 63}, - dictWord{8, 0, 660}, - dictWord{137, 0, 74}, - dictWord{4, 0, 139}, - dictWord{4, 0, 388}, - dictWord{140, 0, 188}, - dictWord{132, 0, 797}, - dictWord{132, 11, 766}, - dictWord{5, 11, 103}, - dictWord{7, 11, 921}, - dictWord{8, 11, 580}, - dictWord{8, 11, 593}, - dictWord{8, 11, 630}, - dictWord{138, 11, 28}, - dictWord{4, 11, 911}, - dictWord{5, 11, 867}, - dictWord{133, 11, 1013}, - dictWord{134, 10, 14}, - dictWord{134, 0, 1572}, - dictWord{134, 10, 1708}, - dictWord{21, 0, 39}, - dictWord{5, 10, 113}, - dictWord{6, 10, 243}, - dictWord{7, 10, 1865}, - dictWord{ - 11, - 10, - 161, - }, - dictWord{16, 10, 37}, - dictWord{145, 10, 99}, - dictWord{7, 11, 1563}, - dictWord{141, 11, 182}, - dictWord{5, 11, 135}, - dictWord{6, 11, 519}, - dictWord{ - 7, - 11, - 1722, - }, - dictWord{10, 11, 271}, - dictWord{11, 11, 261}, - dictWord{145, 11, 54}, - dictWord{132, 10, 274}, - dictWord{134, 0, 1594}, - dictWord{4, 11, 300}, - dictWord{5, 11, 436}, - dictWord{135, 11, 484}, - dictWord{4, 0, 747}, - dictWord{6, 0, 290}, - dictWord{7, 0, 649}, - dictWord{7, 0, 1479}, - dictWord{135, 0, 1583}, - dictWord{133, 11, 535}, - dictWord{147, 11, 82}, - dictWord{133, 0, 232}, - dictWord{137, 0, 887}, - dictWord{135, 10, 166}, - dictWord{136, 0, 521}, - dictWord{4, 0, 14}, - dictWord{7, 0, 472}, - dictWord{7, 0, 1801}, - dictWord{10, 0, 748}, - dictWord{141, 0, 458}, - dictWord{134, 0, 741}, - dictWord{134, 0, 992}, - dictWord{16, 0, 111}, - dictWord{137, 10, 304}, - dictWord{4, 0, 425}, - dictWord{5, 11, 387}, - dictWord{7, 11, 557}, - dictWord{12, 11, 547}, - dictWord{142, 11, 86}, - dictWord{ - 135, - 11, - 1747, - }, - dictWord{5, 10, 654}, - dictWord{135, 11, 1489}, - dictWord{7, 0, 789}, - dictWord{4, 11, 6}, - dictWord{5, 11, 708}, - dictWord{136, 11, 75}, - dictWord{ - 6, - 10, - 273, - }, - dictWord{10, 10, 188}, - dictWord{13, 10, 377}, - dictWord{146, 10, 77}, - dictWord{6, 0, 1593}, - dictWord{4, 11, 303}, - dictWord{7, 11, 619}, - dictWord{ - 10, - 11, - 547, - }, - dictWord{10, 11, 687}, - dictWord{11, 11, 122}, - dictWord{140, 11, 601}, - dictWord{134, 0, 1768}, - dictWord{135, 10, 410}, - dictWord{138, 11, 772}, - dictWord{11, 0, 233}, - dictWord{139, 10, 524}, - dictWord{5, 0, 943}, - dictWord{134, 0, 1779}, - dictWord{134, 10, 1785}, - dictWord{136, 11, 529}, - dictWord{ - 132, - 0, - 955, - }, - dictWord{5, 0, 245}, - dictWord{6, 0, 576}, - dictWord{7, 0, 582}, - dictWord{136, 0, 225}, - dictWord{132, 10, 780}, - dictWord{142, 0, 241}, - dictWord{ - 134, - 0, - 1943, - }, - dictWord{4, 11, 106}, - dictWord{7, 11, 310}, - dictWord{7, 11, 1785}, - dictWord{10, 11, 690}, - dictWord{139, 11, 717}, - dictWord{134, 0, 1284}, - dictWord{5, 11, 890}, - dictWord{133, 11, 988}, - dictWord{6, 11, 626}, - dictWord{142, 11, 431}, - dictWord{10, 11, 706}, - dictWord{145, 11, 32}, - dictWord{ - 137, - 11, - 332, - }, - dictWord{132, 11, 698}, - dictWord{135, 0, 709}, - dictWord{5, 10, 948}, - dictWord{138, 11, 17}, - dictWord{136, 0, 554}, - dictWord{134, 0, 1564}, - dictWord{139, 10, 941}, - dictWord{132, 0, 443}, - dictWord{134, 0, 909}, - dictWord{134, 11, 84}, - dictWord{142, 0, 280}, - dictWord{4, 10, 532}, - dictWord{5, 10, 706}, - dictWord{135, 10, 662}, - dictWord{132, 0, 729}, - dictWord{5, 10, 837}, - dictWord{6, 10, 1651}, - dictWord{139, 10, 985}, - dictWord{135, 10, 1861}, - dictWord{ - 4, - 0, - 348, - }, - dictWord{152, 11, 3}, - dictWord{5, 11, 986}, - dictWord{6, 11, 130}, - dictWord{7, 11, 1582}, - dictWord{8, 11, 458}, - dictWord{10, 11, 101}, - dictWord{ - 10, - 11, - 318, - }, - dictWord{138, 11, 823}, - dictWord{134, 0, 758}, - dictWord{4, 0, 298}, - dictWord{137, 0, 848}, - dictWord{4, 10, 330}, - dictWord{7, 10, 933}, - dictWord{ - 7, - 10, - 2012, - }, - dictWord{136, 10, 292}, - dictWord{7, 11, 1644}, - dictWord{137, 11, 129}, - dictWord{6, 0, 1422}, - dictWord{9, 0, 829}, - dictWord{135, 10, 767}, - dictWord{5, 0, 164}, - dictWord{7, 0, 121}, - dictWord{142, 0, 189}, - dictWord{7, 0, 812}, - dictWord{7, 0, 1261}, - dictWord{7, 0, 1360}, - dictWord{9, 0, 632}, - dictWord{ - 140, - 0, - 352, - }, - dictWord{135, 11, 1788}, - dictWord{139, 0, 556}, - dictWord{135, 11, 997}, - dictWord{145, 10, 114}, - dictWord{4, 0, 172}, - dictWord{9, 0, 611}, - dictWord{10, 0, 436}, - dictWord{12, 0, 673}, - dictWord{13, 0, 255}, - dictWord{137, 10, 883}, - dictWord{11, 0, 530}, - dictWord{138, 10, 274}, - dictWord{133, 0, 844}, - dictWord{134, 0, 984}, - dictWord{13, 0, 232}, - dictWord{18, 0, 35}, - dictWord{4, 10, 703}, - dictWord{135, 10, 207}, - dictWord{132, 10, 571}, - dictWord{9, 0, 263}, - dictWord{10, 0, 147}, - dictWord{138, 0, 492}, - dictWord{7, 11, 1756}, - dictWord{137, 11, 98}, - dictWord{5, 10, 873}, - dictWord{5, 10, 960}, - dictWord{8, 10, 823}, - dictWord{137, 10, 881}, - dictWord{133, 0, 537}, - dictWord{132, 0, 859}, - dictWord{7, 11, 1046}, - dictWord{139, 11, 160}, - dictWord{137, 0, 842}, - dictWord{ - 139, - 10, - 283, - }, - dictWord{5, 10, 33}, - dictWord{6, 10, 470}, - dictWord{139, 10, 424}, - dictWord{6, 11, 45}, - dictWord{7, 11, 433}, - dictWord{8, 11, 129}, - dictWord{ - 9, - 11, - 21, - }, - dictWord{10, 11, 392}, - dictWord{11, 11, 79}, - dictWord{12, 11, 499}, - dictWord{13, 11, 199}, - dictWord{141, 11, 451}, - dictWord{135, 0, 1291}, - dictWord{135, 10, 1882}, - dictWord{7, 11, 558}, - dictWord{136, 11, 353}, - dictWord{134, 0, 1482}, - dictWord{5, 0, 230}, - dictWord{5, 0, 392}, - dictWord{6, 0, 420}, - dictWord{9, 0, 568}, - dictWord{140, 0, 612}, - dictWord{6, 0, 262}, - dictWord{7, 10, 90}, - dictWord{7, 10, 664}, - dictWord{7, 10, 830}, - dictWord{7, 10, 1380}, - dictWord{ - 7, - 10, - 2025, - }, - dictWord{8, 11, 81}, - dictWord{8, 10, 448}, - dictWord{8, 10, 828}, - dictWord{9, 11, 189}, - dictWord{9, 11, 201}, - dictWord{11, 11, 478}, - dictWord{ - 11, - 11, - 712, - }, - dictWord{141, 11, 338}, - dictWord{142, 0, 31}, - dictWord{5, 11, 353}, - dictWord{151, 11, 26}, - dictWord{132, 0, 753}, - dictWord{4, 0, 0}, - dictWord{ - 5, - 0, - 41, - }, - dictWord{7, 0, 1459}, - dictWord{7, 0, 1469}, - dictWord{7, 0, 1859}, - dictWord{9, 0, 549}, - dictWord{139, 0, 905}, - dictWord{9, 10, 417}, - dictWord{ - 137, - 10, - 493, - }, - dictWord{135, 11, 1113}, - dictWord{133, 0, 696}, - dictWord{141, 11, 448}, - dictWord{134, 10, 295}, - dictWord{132, 0, 834}, - dictWord{4, 0, 771}, - dictWord{5, 10, 1019}, - dictWord{6, 11, 25}, - dictWord{7, 11, 855}, - dictWord{7, 11, 1258}, - dictWord{144, 11, 32}, - dictWord{134, 0, 1076}, - dictWord{133, 0, 921}, - dictWord{133, 0, 674}, - dictWord{4, 11, 4}, - dictWord{7, 11, 1118}, - dictWord{7, 11, 1320}, - dictWord{7, 11, 1706}, - dictWord{8, 11, 277}, - dictWord{9, 11, 622}, - dictWord{10, 11, 9}, - dictWord{11, 11, 724}, - dictWord{12, 11, 350}, - dictWord{12, 11, 397}, - dictWord{13, 11, 28}, - dictWord{13, 11, 159}, - dictWord{15, 11, 89}, - dictWord{18, 11, 5}, - dictWord{19, 11, 9}, - dictWord{20, 11, 34}, - dictWord{150, 11, 47}, - dictWord{134, 10, 208}, - dictWord{6, 0, 444}, - dictWord{136, 0, 308}, - dictWord{ - 6, - 0, - 180, - }, - dictWord{7, 0, 1137}, - dictWord{8, 0, 751}, - dictWord{139, 0, 805}, - dictWord{4, 0, 183}, - dictWord{7, 0, 271}, - dictWord{11, 0, 824}, - dictWord{ - 11, - 0, - 952, - }, - dictWord{13, 0, 278}, - dictWord{13, 0, 339}, - dictWord{13, 0, 482}, - dictWord{14, 0, 424}, - dictWord{148, 0, 99}, - dictWord{7, 11, 317}, - dictWord{ - 135, - 11, - 569, - }, - dictWord{4, 0, 19}, - dictWord{5, 0, 477}, - dictWord{5, 0, 596}, - dictWord{6, 0, 505}, - dictWord{7, 0, 1221}, - dictWord{11, 0, 907}, - dictWord{12, 0, 209}, - dictWord{141, 0, 214}, - dictWord{135, 0, 1215}, - dictWord{6, 0, 271}, - dictWord{7, 0, 398}, - dictWord{8, 0, 387}, - dictWord{10, 0, 344}, - dictWord{7, 10, 448}, - dictWord{ - 7, - 10, - 1629, - }, - dictWord{7, 10, 1813}, - dictWord{8, 10, 442}, - dictWord{9, 10, 710}, - dictWord{10, 10, 282}, - dictWord{138, 10, 722}, - dictWord{11, 10, 844}, - dictWord{12, 10, 104}, - dictWord{140, 10, 625}, - dictWord{134, 11, 255}, - dictWord{133, 10, 787}, - dictWord{134, 0, 1645}, - dictWord{11, 11, 956}, - dictWord{ - 151, - 11, - 3, - }, - dictWord{6, 0, 92}, - dictWord{6, 0, 188}, - dictWord{7, 0, 209}, - dictWord{7, 0, 1269}, - dictWord{7, 0, 1524}, - dictWord{7, 0, 1876}, - dictWord{8, 0, 661}, - dictWord{10, 0, 42}, - dictWord{10, 0, 228}, - dictWord{11, 0, 58}, - dictWord{11, 0, 1020}, - dictWord{12, 0, 58}, - dictWord{12, 0, 118}, - dictWord{141, 0, 32}, - dictWord{ - 4, - 0, - 459, - }, - dictWord{133, 0, 966}, - dictWord{4, 11, 536}, - dictWord{7, 11, 1141}, - dictWord{10, 11, 723}, - dictWord{139, 11, 371}, - dictWord{140, 0, 330}, - dictWord{134, 0, 1557}, - dictWord{7, 11, 285}, - dictWord{135, 11, 876}, - dictWord{136, 10, 491}, - dictWord{135, 11, 560}, - dictWord{6, 0, 18}, - dictWord{7, 0, 179}, - dictWord{7, 0, 932}, - dictWord{8, 0, 548}, - dictWord{8, 0, 757}, - dictWord{9, 0, 54}, - dictWord{9, 0, 65}, - dictWord{9, 0, 532}, - dictWord{9, 0, 844}, - dictWord{10, 0, 113}, - dictWord{10, 0, 117}, - dictWord{10, 0, 315}, - dictWord{10, 0, 560}, - dictWord{10, 0, 622}, - dictWord{10, 0, 798}, - dictWord{11, 0, 153}, - dictWord{11, 0, 351}, - dictWord{ - 11, - 0, - 375, - }, - dictWord{12, 0, 78}, - dictWord{12, 0, 151}, - dictWord{12, 0, 392}, - dictWord{12, 0, 666}, - dictWord{14, 0, 248}, - dictWord{143, 0, 23}, - dictWord{ - 6, - 0, - 1742, - }, - dictWord{132, 11, 690}, - dictWord{4, 10, 403}, - dictWord{5, 10, 441}, - dictWord{7, 10, 450}, - dictWord{10, 10, 840}, - dictWord{11, 10, 101}, - dictWord{ - 12, - 10, - 193, - }, - dictWord{141, 10, 430}, - dictWord{133, 0, 965}, - dictWord{134, 0, 182}, - dictWord{10, 0, 65}, - dictWord{10, 0, 488}, - dictWord{138, 0, 497}, - dictWord{135, 11, 1346}, - dictWord{6, 0, 973}, - dictWord{6, 0, 1158}, - dictWord{10, 11, 200}, - dictWord{19, 11, 2}, - dictWord{151, 11, 22}, - dictWord{4, 11, 190}, - dictWord{133, 11, 554}, - dictWord{133, 10, 679}, - dictWord{7, 0, 328}, - dictWord{137, 10, 326}, - dictWord{133, 11, 1001}, - dictWord{9, 0, 588}, - dictWord{ - 138, - 0, - 260, - }, - dictWord{133, 11, 446}, - dictWord{135, 10, 1128}, - dictWord{135, 10, 1796}, - dictWord{147, 11, 119}, - dictWord{134, 0, 1786}, - dictWord{ - 6, - 0, - 1328, - }, - dictWord{6, 0, 1985}, - dictWord{8, 0, 962}, - dictWord{138, 0, 1017}, - dictWord{135, 0, 308}, - dictWord{11, 0, 508}, - dictWord{4, 10, 574}, - dictWord{ - 7, - 10, - 350, - }, - dictWord{7, 10, 1024}, - dictWord{8, 10, 338}, - dictWord{9, 10, 677}, - dictWord{138, 10, 808}, - dictWord{138, 11, 752}, - dictWord{135, 10, 1081}, - dictWord{137, 11, 96}, - dictWord{7, 10, 1676}, - dictWord{135, 10, 2037}, - dictWord{136, 0, 588}, - dictWord{132, 11, 304}, - dictWord{133, 0, 614}, - dictWord{ - 140, - 0, - 793, - }, - dictWord{136, 0, 287}, - dictWord{137, 10, 297}, - dictWord{141, 10, 37}, - dictWord{6, 11, 53}, - dictWord{6, 11, 199}, - dictWord{7, 11, 1408}, - dictWord{ - 8, - 11, - 32, - }, - dictWord{8, 11, 93}, - dictWord{9, 11, 437}, - dictWord{10, 11, 397}, - dictWord{10, 11, 629}, - dictWord{11, 11, 593}, - dictWord{11, 11, 763}, - dictWord{ - 13, - 11, - 326, - }, - dictWord{145, 11, 35}, - dictWord{134, 11, 105}, - dictWord{9, 11, 320}, - dictWord{10, 11, 506}, - dictWord{138, 11, 794}, - dictWord{5, 11, 114}, - dictWord{5, 11, 255}, - dictWord{141, 11, 285}, - dictWord{140, 0, 290}, - dictWord{7, 11, 2035}, - dictWord{8, 11, 19}, - dictWord{9, 11, 89}, - dictWord{138, 11, 831}, - dictWord{134, 0, 1136}, - dictWord{7, 0, 719}, - dictWord{8, 0, 796}, - dictWord{8, 0, 809}, - dictWord{8, 0, 834}, - dictWord{6, 10, 306}, - dictWord{7, 10, 1140}, - dictWord{ - 7, - 10, - 1340, - }, - dictWord{8, 10, 133}, - dictWord{138, 10, 449}, - dictWord{139, 10, 1011}, - dictWord{5, 0, 210}, - dictWord{6, 0, 213}, - dictWord{7, 0, 60}, - dictWord{ - 10, - 0, - 364, - }, - dictWord{139, 0, 135}, - dictWord{5, 0, 607}, - dictWord{8, 0, 326}, - dictWord{136, 0, 490}, - dictWord{138, 11, 176}, - dictWord{132, 0, 701}, - dictWord{ - 5, - 0, - 472, - }, - dictWord{7, 0, 380}, - dictWord{137, 0, 758}, - dictWord{135, 0, 1947}, - dictWord{6, 0, 1079}, - dictWord{138, 0, 278}, - dictWord{138, 11, 391}, - dictWord{ - 5, - 10, - 329, - }, - dictWord{8, 10, 260}, - dictWord{139, 11, 156}, - dictWord{4, 0, 386}, - dictWord{7, 0, 41}, - dictWord{8, 0, 405}, - dictWord{8, 0, 728}, - dictWord{9, 0, 497}, - dictWord{11, 0, 110}, - dictWord{11, 0, 360}, - dictWord{15, 0, 37}, - dictWord{144, 0, 84}, - dictWord{5, 0, 46}, - dictWord{7, 0, 1452}, - dictWord{7, 0, 1480}, - dictWord{ - 8, - 0, - 634, - }, - dictWord{140, 0, 472}, - dictWord{136, 0, 961}, - dictWord{4, 0, 524}, - dictWord{136, 0, 810}, - dictWord{10, 0, 238}, - dictWord{141, 0, 33}, - dictWord{ - 132, - 10, - 657, - }, - dictWord{152, 10, 7}, - dictWord{133, 0, 532}, - dictWord{5, 0, 997}, - dictWord{135, 10, 1665}, - dictWord{7, 11, 594}, - dictWord{7, 11, 851}, - dictWord{ - 7, - 11, - 1858, - }, - dictWord{9, 11, 411}, - dictWord{9, 11, 574}, - dictWord{9, 11, 666}, - dictWord{9, 11, 737}, - dictWord{10, 11, 346}, - dictWord{10, 11, 712}, - dictWord{ - 11, - 11, - 246, - }, - dictWord{11, 11, 432}, - dictWord{11, 11, 517}, - dictWord{11, 11, 647}, - dictWord{11, 11, 679}, - dictWord{11, 11, 727}, - dictWord{12, 11, 304}, - dictWord{12, 11, 305}, - dictWord{12, 11, 323}, - dictWord{12, 11, 483}, - dictWord{12, 11, 572}, - dictWord{12, 11, 593}, - dictWord{12, 11, 602}, - dictWord{ - 13, - 11, - 95, - }, - dictWord{13, 11, 101}, - dictWord{13, 11, 171}, - dictWord{13, 11, 315}, - dictWord{13, 11, 378}, - dictWord{13, 11, 425}, - dictWord{13, 11, 475}, - dictWord{ - 14, - 11, - 63, - }, - dictWord{14, 11, 380}, - dictWord{14, 11, 384}, - dictWord{15, 11, 133}, - dictWord{18, 11, 112}, - dictWord{148, 11, 72}, - dictWord{5, 11, 955}, - dictWord{136, 11, 814}, - dictWord{134, 0, 1301}, - dictWord{5, 10, 66}, - dictWord{7, 10, 1896}, - dictWord{136, 10, 288}, - dictWord{133, 11, 56}, - dictWord{ - 134, - 10, - 1643, - }, - dictWord{6, 0, 1298}, - dictWord{148, 11, 100}, - dictWord{5, 0, 782}, - dictWord{5, 0, 829}, - dictWord{6, 0, 671}, - dictWord{6, 0, 1156}, - dictWord{6, 0, 1738}, - dictWord{137, 11, 621}, - dictWord{4, 0, 306}, - dictWord{5, 0, 570}, - dictWord{7, 0, 1347}, - dictWord{5, 10, 91}, - dictWord{5, 10, 648}, - dictWord{5, 10, 750}, - dictWord{ - 5, - 10, - 781, - }, - dictWord{6, 10, 54}, - dictWord{6, 10, 112}, - dictWord{6, 10, 402}, - dictWord{6, 10, 1732}, - dictWord{7, 10, 315}, - dictWord{7, 10, 749}, - dictWord{ - 7, - 10, - 1900, - }, - dictWord{9, 10, 78}, - dictWord{9, 10, 508}, - dictWord{10, 10, 611}, - dictWord{10, 10, 811}, - dictWord{11, 10, 510}, - dictWord{11, 10, 728}, - dictWord{ - 13, - 10, - 36, - }, - dictWord{14, 10, 39}, - dictWord{16, 10, 83}, - dictWord{17, 10, 124}, - dictWord{148, 10, 30}, - dictWord{8, 10, 570}, - dictWord{9, 11, 477}, - dictWord{ - 141, - 11, - 78, - }, - dictWord{4, 11, 639}, - dictWord{10, 11, 4}, - dictWord{10, 10, 322}, - dictWord{10, 10, 719}, - dictWord{11, 10, 407}, - dictWord{11, 11, 638}, - dictWord{ - 12, - 11, - 177, - }, - dictWord{148, 11, 57}, - dictWord{7, 0, 1823}, - dictWord{139, 0, 693}, - dictWord{7, 0, 759}, - dictWord{5, 11, 758}, - dictWord{8, 10, 125}, - dictWord{ - 8, - 10, - 369, - }, - dictWord{8, 10, 524}, - dictWord{10, 10, 486}, - dictWord{11, 10, 13}, - dictWord{11, 10, 381}, - dictWord{11, 10, 736}, - dictWord{11, 10, 766}, - dictWord{ - 11, - 10, - 845, - }, - dictWord{13, 10, 114}, - dictWord{13, 10, 292}, - dictWord{142, 10, 47}, - dictWord{7, 0, 1932}, - dictWord{6, 10, 1684}, - dictWord{6, 10, 1731}, - dictWord{7, 10, 356}, - dictWord{8, 10, 54}, - dictWord{8, 10, 221}, - dictWord{9, 10, 225}, - dictWord{9, 10, 356}, - dictWord{10, 10, 77}, - dictWord{10, 10, 446}, - dictWord{ - 10, - 10, - 731, - }, - dictWord{12, 10, 404}, - dictWord{141, 10, 491}, - dictWord{135, 11, 552}, - dictWord{135, 11, 1112}, - dictWord{4, 0, 78}, - dictWord{5, 0, 96}, - dictWord{ - 5, - 0, - 182, - }, - dictWord{6, 0, 1257}, - dictWord{7, 0, 1724}, - dictWord{7, 0, 1825}, - dictWord{10, 0, 394}, - dictWord{10, 0, 471}, - dictWord{11, 0, 532}, - dictWord{ - 14, - 0, - 340, - }, - dictWord{145, 0, 88}, - dictWord{139, 11, 328}, - dictWord{135, 0, 1964}, - dictWord{132, 10, 411}, - dictWord{4, 10, 80}, - dictWord{5, 10, 44}, - dictWord{ - 137, - 11, - 133, - }, - dictWord{5, 11, 110}, - dictWord{6, 11, 169}, - dictWord{6, 11, 1702}, - dictWord{7, 11, 400}, - dictWord{8, 11, 538}, - dictWord{9, 11, 184}, - dictWord{ - 9, - 11, - 524, - }, - dictWord{140, 11, 218}, - dictWord{4, 0, 521}, - dictWord{5, 10, 299}, - dictWord{7, 10, 1083}, - dictWord{140, 11, 554}, - dictWord{6, 11, 133}, - dictWord{ - 9, - 11, - 353, - }, - dictWord{12, 11, 628}, - dictWord{146, 11, 79}, - dictWord{6, 0, 215}, - dictWord{7, 0, 584}, - dictWord{7, 0, 1028}, - dictWord{7, 0, 1473}, - dictWord{ - 7, - 0, - 1721, - }, - dictWord{9, 0, 424}, - dictWord{138, 0, 779}, - dictWord{7, 0, 857}, - dictWord{7, 0, 1209}, - dictWord{7, 10, 1713}, - dictWord{9, 10, 537}, - dictWord{ - 10, - 10, - 165, - }, - dictWord{12, 10, 219}, - dictWord{140, 10, 561}, - dictWord{4, 10, 219}, - dictWord{6, 11, 93}, - dictWord{7, 11, 1422}, - dictWord{7, 10, 1761}, - dictWord{ - 7, - 11, - 1851, - }, - dictWord{8, 11, 673}, - dictWord{9, 10, 86}, - dictWord{9, 11, 529}, - dictWord{140, 11, 43}, - dictWord{137, 11, 371}, - dictWord{136, 0, 671}, - dictWord{ - 5, - 0, - 328, - }, - dictWord{135, 0, 918}, - dictWord{132, 0, 529}, - dictWord{9, 11, 25}, - dictWord{10, 11, 467}, - dictWord{138, 11, 559}, - dictWord{4, 11, 335}, - dictWord{ - 135, - 11, - 942, - }, - dictWord{134, 0, 716}, - dictWord{134, 0, 1509}, - dictWord{6, 0, 67}, - dictWord{7, 0, 258}, - dictWord{7, 0, 1630}, - dictWord{9, 0, 354}, - dictWord{ - 9, - 0, - 675, - }, - dictWord{10, 0, 830}, - dictWord{14, 0, 80}, - dictWord{17, 0, 80}, - dictWord{140, 10, 428}, - dictWord{134, 0, 1112}, - dictWord{6, 0, 141}, - dictWord{7, 0, 225}, - dictWord{9, 0, 59}, - dictWord{9, 0, 607}, - dictWord{10, 0, 312}, - dictWord{11, 0, 687}, - dictWord{12, 0, 555}, - dictWord{13, 0, 373}, - dictWord{13, 0, 494}, - dictWord{ - 148, - 0, - 58, - }, - dictWord{133, 10, 514}, - dictWord{8, 11, 39}, - dictWord{10, 11, 773}, - dictWord{11, 11, 84}, - dictWord{12, 11, 205}, - dictWord{142, 11, 1}, - dictWord{ - 8, - 0, - 783, - }, - dictWord{5, 11, 601}, - dictWord{133, 11, 870}, - dictWord{136, 11, 594}, - dictWord{4, 10, 55}, - dictWord{5, 10, 301}, - dictWord{6, 10, 571}, - dictWord{ - 14, - 10, - 49, - }, - dictWord{146, 10, 102}, - dictWord{132, 11, 181}, - dictWord{134, 11, 1652}, - dictWord{133, 10, 364}, - dictWord{4, 11, 97}, - dictWord{5, 11, 147}, - dictWord{6, 11, 286}, - dictWord{7, 11, 1362}, - dictWord{141, 11, 176}, - dictWord{4, 10, 76}, - dictWord{7, 10, 1550}, - dictWord{9, 10, 306}, - dictWord{9, 10, 430}, - dictWord{9, 10, 663}, - dictWord{10, 10, 683}, - dictWord{11, 10, 427}, - dictWord{11, 10, 753}, - dictWord{12, 10, 334}, - dictWord{12, 10, 442}, - dictWord{ - 14, - 10, - 258, - }, - dictWord{14, 10, 366}, - dictWord{143, 10, 131}, - dictWord{137, 10, 52}, - dictWord{6, 0, 955}, - dictWord{134, 0, 1498}, - dictWord{6, 11, 375}, - dictWord{ - 7, - 11, - 169, - }, - dictWord{7, 11, 254}, - dictWord{136, 11, 780}, - dictWord{7, 0, 430}, - dictWord{11, 0, 46}, - dictWord{14, 0, 343}, - dictWord{142, 11, 343}, - dictWord{ - 135, - 0, - 1183, - }, - dictWord{5, 0, 602}, - dictWord{7, 0, 2018}, - dictWord{9, 0, 418}, - dictWord{9, 0, 803}, - dictWord{135, 11, 1447}, - dictWord{8, 0, 677}, - dictWord{ - 135, - 11, - 1044, - }, - dictWord{139, 11, 285}, - dictWord{4, 10, 656}, - dictWord{135, 10, 779}, - dictWord{135, 10, 144}, - dictWord{5, 11, 629}, - dictWord{ - 135, - 11, - 1549, - }, - dictWord{135, 10, 1373}, - dictWord{138, 11, 209}, - dictWord{7, 10, 554}, - dictWord{7, 10, 605}, - dictWord{141, 10, 10}, - dictWord{5, 10, 838}, - dictWord{ - 5, - 10, - 841, - }, - dictWord{134, 10, 1649}, - dictWord{133, 10, 1012}, - dictWord{6, 0, 1357}, - dictWord{134, 0, 1380}, - dictWord{144, 0, 53}, - dictWord{6, 0, 590}, - dictWord{7, 10, 365}, - dictWord{7, 10, 1357}, - dictWord{7, 10, 1497}, - dictWord{8, 10, 154}, - dictWord{141, 10, 281}, - dictWord{133, 10, 340}, - dictWord{ - 132, - 11, - 420, - }, - dictWord{135, 0, 329}, - dictWord{147, 11, 32}, - dictWord{4, 0, 469}, - dictWord{10, 11, 429}, - dictWord{139, 10, 495}, - dictWord{8, 10, 261}, - dictWord{ - 9, - 10, - 144, - }, - dictWord{9, 10, 466}, - dictWord{10, 10, 370}, - dictWord{12, 10, 470}, - dictWord{13, 10, 144}, - dictWord{142, 10, 348}, - dictWord{142, 0, 460}, - dictWord{4, 11, 325}, - dictWord{9, 10, 897}, - dictWord{138, 11, 125}, - dictWord{6, 0, 1743}, - dictWord{6, 10, 248}, - dictWord{9, 10, 546}, - dictWord{10, 10, 535}, - dictWord{11, 10, 681}, - dictWord{141, 10, 135}, - dictWord{4, 0, 990}, - dictWord{5, 0, 929}, - dictWord{6, 0, 340}, - dictWord{8, 0, 376}, - dictWord{8, 0, 807}, - dictWord{ - 8, - 0, - 963, - }, - dictWord{8, 0, 980}, - dictWord{138, 0, 1007}, - dictWord{134, 0, 1603}, - dictWord{140, 0, 250}, - dictWord{4, 11, 714}, - dictWord{133, 11, 469}, - dictWord{134, 10, 567}, - dictWord{136, 10, 445}, - dictWord{5, 0, 218}, - dictWord{7, 0, 1610}, - dictWord{8, 0, 646}, - dictWord{10, 0, 83}, - dictWord{11, 11, 138}, - dictWord{140, 11, 40}, - dictWord{7, 0, 1512}, - dictWord{135, 0, 1794}, - dictWord{135, 11, 1216}, - dictWord{11, 0, 0}, - dictWord{16, 0, 78}, - dictWord{132, 11, 718}, - dictWord{133, 0, 571}, - dictWord{132, 0, 455}, - dictWord{134, 0, 1012}, - dictWord{5, 11, 124}, - dictWord{5, 11, 144}, - dictWord{6, 11, 548}, - dictWord{7, 11, 15}, - dictWord{7, 11, 153}, - dictWord{137, 11, 629}, - dictWord{142, 11, 10}, - dictWord{6, 11, 75}, - dictWord{7, 11, 1531}, - dictWord{8, 11, 416}, - dictWord{9, 11, 240}, - dictWord{9, 11, 275}, - dictWord{10, 11, 100}, - dictWord{11, 11, 658}, - dictWord{11, 11, 979}, - dictWord{12, 11, 86}, - dictWord{13, 11, 468}, - dictWord{14, 11, 66}, - dictWord{14, 11, 207}, - dictWord{15, 11, 20}, - dictWord{15, 11, 25}, - dictWord{144, 11, 58}, - dictWord{132, 10, 577}, - dictWord{5, 11, 141}, - dictWord{ - 5, - 11, - 915, - }, - dictWord{6, 11, 1783}, - dictWord{7, 11, 211}, - dictWord{7, 11, 698}, - dictWord{7, 11, 1353}, - dictWord{9, 11, 83}, - dictWord{9, 11, 281}, - dictWord{ - 10, - 11, - 376, - }, - dictWord{10, 11, 431}, - dictWord{11, 11, 543}, - dictWord{12, 11, 664}, - dictWord{13, 11, 280}, - dictWord{13, 11, 428}, - dictWord{14, 11, 61}, - dictWord{ - 14, - 11, - 128, - }, - dictWord{17, 11, 52}, - dictWord{145, 11, 81}, - dictWord{6, 0, 161}, - dictWord{7, 0, 372}, - dictWord{137, 0, 597}, - dictWord{132, 0, 349}, - dictWord{ - 10, - 11, - 702, - }, - dictWord{139, 11, 245}, - dictWord{134, 0, 524}, - dictWord{134, 10, 174}, - dictWord{6, 0, 432}, - dictWord{9, 0, 751}, - dictWord{139, 0, 322}, - dictWord{147, 11, 94}, - dictWord{4, 11, 338}, - dictWord{133, 11, 400}, - dictWord{5, 0, 468}, - dictWord{10, 0, 325}, - dictWord{11, 0, 856}, - dictWord{12, 0, 345}, - dictWord{143, 0, 104}, - dictWord{133, 0, 223}, - dictWord{132, 0, 566}, - dictWord{4, 11, 221}, - dictWord{5, 11, 659}, - dictWord{5, 11, 989}, - dictWord{7, 11, 697}, - dictWord{7, 11, 1211}, - dictWord{138, 11, 284}, - dictWord{135, 11, 1070}, - dictWord{4, 0, 59}, - dictWord{135, 0, 1394}, - dictWord{6, 0, 436}, - dictWord{11, 0, 481}, - dictWord{5, 10, 878}, - dictWord{133, 10, 972}, - dictWord{4, 0, 48}, - dictWord{5, 0, 271}, - dictWord{135, 0, 953}, - dictWord{5, 0, 610}, - dictWord{136, 0, 457}, - dictWord{ - 4, - 0, - 773, - }, - dictWord{5, 0, 618}, - dictWord{137, 0, 756}, - dictWord{133, 0, 755}, - dictWord{135, 0, 1217}, - dictWord{138, 11, 507}, - dictWord{132, 10, 351}, - dictWord{132, 0, 197}, - dictWord{143, 11, 78}, - dictWord{4, 11, 188}, - dictWord{7, 11, 805}, - dictWord{11, 11, 276}, - dictWord{142, 11, 293}, - dictWord{ - 5, - 11, - 884, - }, - dictWord{139, 11, 991}, - dictWord{132, 10, 286}, - dictWord{10, 0, 259}, - dictWord{10, 0, 428}, - dictWord{7, 10, 438}, - dictWord{7, 10, 627}, - dictWord{ - 7, - 10, - 1516, - }, - dictWord{8, 10, 40}, - dictWord{9, 10, 56}, - dictWord{9, 10, 294}, - dictWord{11, 10, 969}, - dictWord{11, 10, 995}, - dictWord{146, 10, 148}, - dictWord{ - 4, - 0, - 356, - }, - dictWord{5, 0, 217}, - dictWord{5, 0, 492}, - dictWord{5, 0, 656}, - dictWord{8, 0, 544}, - dictWord{136, 11, 544}, - dictWord{5, 0, 259}, - dictWord{6, 0, 1230}, - dictWord{7, 0, 414}, - dictWord{7, 0, 854}, - dictWord{142, 0, 107}, - dictWord{132, 0, 1007}, - dictWord{15, 0, 14}, - dictWord{144, 0, 5}, - dictWord{6, 0, 1580}, - dictWord{ - 132, - 10, - 738, - }, - dictWord{132, 11, 596}, - dictWord{132, 0, 673}, - dictWord{133, 10, 866}, - dictWord{6, 0, 1843}, - dictWord{135, 11, 1847}, - dictWord{4, 0, 165}, - dictWord{7, 0, 1398}, - dictWord{135, 0, 1829}, - dictWord{135, 11, 1634}, - dictWord{147, 11, 65}, - dictWord{6, 0, 885}, - dictWord{6, 0, 1009}, - dictWord{ - 137, - 0, - 809, - }, - dictWord{133, 10, 116}, - dictWord{132, 10, 457}, - dictWord{136, 11, 770}, - dictWord{9, 0, 498}, - dictWord{12, 0, 181}, - dictWord{10, 11, 361}, - dictWord{142, 11, 316}, - dictWord{134, 11, 595}, - dictWord{5, 0, 9}, - dictWord{7, 0, 297}, - dictWord{7, 0, 966}, - dictWord{140, 0, 306}, - dictWord{4, 11, 89}, - dictWord{ - 5, - 11, - 489, - }, - dictWord{6, 11, 315}, - dictWord{7, 11, 553}, - dictWord{7, 11, 1745}, - dictWord{138, 11, 243}, - dictWord{134, 0, 1487}, - dictWord{132, 0, 437}, - dictWord{ - 5, - 0, - 146, - }, - dictWord{6, 0, 411}, - dictWord{138, 0, 721}, - dictWord{5, 10, 527}, - dictWord{6, 10, 189}, - dictWord{135, 10, 859}, - dictWord{11, 10, 104}, - dictWord{ - 11, - 10, - 554, - }, - dictWord{15, 10, 60}, - dictWord{143, 10, 125}, - dictWord{6, 11, 1658}, - dictWord{9, 11, 3}, - dictWord{10, 11, 154}, - dictWord{11, 11, 641}, - dictWord{13, 11, 85}, - dictWord{13, 11, 201}, - dictWord{141, 11, 346}, - dictWord{6, 0, 177}, - dictWord{135, 0, 467}, - dictWord{134, 0, 1377}, - dictWord{ - 134, - 10, - 116, - }, - dictWord{136, 11, 645}, - dictWord{4, 11, 166}, - dictWord{5, 11, 505}, - dictWord{6, 11, 1670}, - dictWord{137, 11, 110}, - dictWord{133, 10, 487}, - dictWord{ - 4, - 10, - 86, - }, - dictWord{5, 10, 667}, - dictWord{5, 10, 753}, - dictWord{6, 10, 316}, - dictWord{6, 10, 455}, - dictWord{135, 10, 946}, - dictWord{133, 0, 200}, - dictWord{132, 0, 959}, - dictWord{6, 0, 1928}, - dictWord{134, 0, 1957}, - dictWord{139, 11, 203}, - dictWord{150, 10, 45}, - dictWord{4, 10, 79}, - dictWord{7, 10, 1773}, - dictWord{10, 10, 450}, - dictWord{11, 10, 589}, - dictWord{13, 10, 332}, - dictWord{13, 10, 493}, - dictWord{14, 10, 183}, - dictWord{14, 10, 334}, - dictWord{ - 14, - 10, - 362, - }, - dictWord{14, 10, 368}, - dictWord{14, 10, 376}, - dictWord{14, 10, 379}, - dictWord{19, 10, 90}, - dictWord{19, 10, 103}, - dictWord{19, 10, 127}, - dictWord{148, 10, 90}, - dictWord{6, 0, 1435}, - dictWord{135, 11, 1275}, - dictWord{134, 0, 481}, - dictWord{7, 11, 445}, - dictWord{8, 11, 307}, - dictWord{8, 11, 704}, - dictWord{10, 11, 41}, - dictWord{10, 11, 439}, - dictWord{11, 11, 237}, - dictWord{11, 11, 622}, - dictWord{140, 11, 201}, - dictWord{135, 11, 869}, - dictWord{ - 4, - 0, - 84, - }, - dictWord{7, 0, 1482}, - dictWord{10, 0, 76}, - dictWord{138, 0, 142}, - dictWord{11, 11, 277}, - dictWord{144, 11, 14}, - dictWord{135, 11, 1977}, - dictWord{ - 4, - 11, - 189, - }, - dictWord{5, 11, 713}, - dictWord{136, 11, 57}, - dictWord{133, 0, 1015}, - dictWord{138, 11, 371}, - dictWord{4, 0, 315}, - dictWord{5, 0, 507}, - dictWord{ - 135, - 0, - 1370, - }, - dictWord{4, 11, 552}, - dictWord{142, 10, 381}, - dictWord{9, 0, 759}, - dictWord{16, 0, 31}, - dictWord{16, 0, 39}, - dictWord{16, 0, 75}, - dictWord{18, 0, 24}, - dictWord{20, 0, 42}, - dictWord{152, 0, 1}, - dictWord{134, 0, 712}, - dictWord{134, 0, 1722}, - dictWord{133, 10, 663}, - dictWord{133, 10, 846}, - dictWord{ - 8, - 0, - 222, - }, - dictWord{8, 0, 476}, - dictWord{9, 0, 238}, - dictWord{11, 0, 516}, - dictWord{11, 0, 575}, - dictWord{15, 0, 109}, - dictWord{146, 0, 100}, - dictWord{7, 0, 1402}, - dictWord{7, 0, 1414}, - dictWord{12, 0, 456}, - dictWord{5, 10, 378}, - dictWord{8, 10, 465}, - dictWord{9, 10, 286}, - dictWord{10, 10, 185}, - dictWord{10, 10, 562}, - dictWord{10, 10, 635}, - dictWord{11, 10, 31}, - dictWord{11, 10, 393}, - dictWord{13, 10, 312}, - dictWord{18, 10, 65}, - dictWord{18, 10, 96}, - dictWord{147, 10, 89}, - dictWord{4, 0, 986}, - dictWord{6, 0, 1958}, - dictWord{6, 0, 2032}, - dictWord{8, 0, 934}, - dictWord{138, 0, 985}, - dictWord{7, 10, 1880}, - dictWord{9, 10, 680}, - dictWord{139, 10, 798}, - dictWord{134, 10, 1770}, - dictWord{145, 11, 49}, - dictWord{132, 11, 614}, - dictWord{132, 10, 648}, - dictWord{5, 10, 945}, - dictWord{ - 6, - 10, - 1656, - }, - dictWord{6, 10, 1787}, - dictWord{7, 10, 167}, - dictWord{8, 10, 824}, - dictWord{9, 10, 391}, - dictWord{10, 10, 375}, - dictWord{139, 10, 185}, - dictWord{138, 11, 661}, - dictWord{7, 0, 1273}, - dictWord{135, 11, 1945}, - dictWord{7, 0, 706}, - dictWord{7, 0, 1058}, - dictWord{138, 0, 538}, - dictWord{7, 10, 1645}, - dictWord{8, 10, 352}, - dictWord{137, 10, 249}, - dictWord{132, 10, 152}, - dictWord{11, 0, 92}, - dictWord{11, 0, 196}, - dictWord{11, 0, 409}, - dictWord{11, 0, 450}, - dictWord{11, 0, 666}, - dictWord{11, 0, 777}, - dictWord{12, 0, 262}, - dictWord{13, 0, 385}, - dictWord{13, 0, 393}, - dictWord{15, 0, 115}, - dictWord{16, 0, 45}, - dictWord{145, 0, 82}, - dictWord{133, 10, 1006}, - dictWord{6, 0, 40}, - dictWord{135, 0, 1781}, - dictWord{9, 11, 614}, - dictWord{139, 11, 327}, - dictWord{5, 10, 420}, - dictWord{135, 10, 1449}, - dictWord{135, 0, 431}, - dictWord{10, 0, 97}, - dictWord{135, 10, 832}, - dictWord{6, 0, 423}, - dictWord{7, 0, 665}, - dictWord{ - 135, - 0, - 1210, - }, - dictWord{7, 0, 237}, - dictWord{8, 0, 664}, - dictWord{9, 0, 42}, - dictWord{9, 0, 266}, - dictWord{9, 0, 380}, - dictWord{9, 0, 645}, - dictWord{10, 0, 177}, - dictWord{ - 138, - 0, - 276, - }, - dictWord{7, 0, 264}, - dictWord{133, 10, 351}, - dictWord{8, 0, 213}, - dictWord{5, 10, 40}, - dictWord{7, 10, 598}, - dictWord{7, 10, 1638}, - dictWord{ - 9, - 10, - 166, - }, - dictWord{9, 10, 640}, - dictWord{9, 10, 685}, - dictWord{9, 10, 773}, - dictWord{11, 10, 215}, - dictWord{13, 10, 65}, - dictWord{14, 10, 172}, - dictWord{ - 14, - 10, - 317, - }, - dictWord{145, 10, 6}, - dictWord{5, 11, 84}, - dictWord{134, 11, 163}, - dictWord{8, 10, 60}, - dictWord{9, 10, 343}, - dictWord{139, 10, 769}, - dictWord{ - 137, - 0, - 455, - }, - dictWord{133, 11, 410}, - dictWord{8, 0, 906}, - dictWord{12, 0, 700}, - dictWord{12, 0, 706}, - dictWord{140, 0, 729}, - dictWord{21, 11, 33}, - dictWord{ - 150, - 11, - 40, - }, - dictWord{7, 10, 1951}, - dictWord{8, 10, 765}, - dictWord{8, 10, 772}, - dictWord{140, 10, 671}, - dictWord{7, 10, 108}, - dictWord{8, 10, 219}, - dictWord{ - 8, - 10, - 388, - }, - dictWord{9, 10, 639}, - dictWord{9, 10, 775}, - dictWord{11, 10, 275}, - dictWord{140, 10, 464}, - dictWord{5, 11, 322}, - dictWord{7, 11, 1941}, - dictWord{ - 8, - 11, - 186, - }, - dictWord{9, 11, 262}, - dictWord{10, 11, 187}, - dictWord{14, 11, 208}, - dictWord{146, 11, 130}, - dictWord{139, 0, 624}, - dictWord{8, 0, 574}, - dictWord{ - 5, - 11, - 227, - }, - dictWord{140, 11, 29}, - dictWord{7, 11, 1546}, - dictWord{11, 11, 299}, - dictWord{142, 11, 407}, - dictWord{5, 10, 15}, - dictWord{6, 10, 56}, - dictWord{ - 7, - 10, - 1758, - }, - dictWord{8, 10, 500}, - dictWord{9, 10, 730}, - dictWord{11, 10, 331}, - dictWord{13, 10, 150}, - dictWord{142, 10, 282}, - dictWord{7, 11, 1395}, - dictWord{8, 11, 486}, - dictWord{9, 11, 236}, - dictWord{9, 11, 878}, - dictWord{10, 11, 218}, - dictWord{11, 11, 95}, - dictWord{19, 11, 17}, - dictWord{147, 11, 31}, - dictWord{135, 11, 2043}, - dictWord{4, 0, 354}, - dictWord{146, 11, 4}, - dictWord{140, 11, 80}, - dictWord{135, 0, 1558}, - dictWord{134, 10, 1886}, - dictWord{ - 5, - 10, - 205, - }, - dictWord{6, 10, 438}, - dictWord{137, 10, 711}, - dictWord{133, 11, 522}, - dictWord{133, 10, 534}, - dictWord{7, 0, 235}, - dictWord{7, 0, 1475}, - dictWord{ - 15, - 0, - 68, - }, - dictWord{146, 0, 120}, - dictWord{137, 10, 691}, - dictWord{4, 0, 942}, - dictWord{6, 0, 1813}, - dictWord{8, 0, 917}, - dictWord{10, 0, 884}, - dictWord{ - 12, - 0, - 696, - }, - dictWord{12, 0, 717}, - dictWord{12, 0, 723}, - dictWord{12, 0, 738}, - dictWord{12, 0, 749}, - dictWord{12, 0, 780}, - dictWord{16, 0, 97}, - dictWord{146, 0, 169}, - dictWord{6, 10, 443}, - dictWord{8, 11, 562}, - dictWord{9, 10, 237}, - dictWord{9, 10, 571}, - dictWord{9, 10, 695}, - dictWord{10, 10, 139}, - dictWord{11, 10, 715}, - dictWord{12, 10, 417}, - dictWord{141, 10, 421}, - dictWord{135, 0, 957}, - dictWord{133, 0, 830}, - dictWord{134, 11, 1771}, - dictWord{146, 0, 23}, - dictWord{ - 5, - 0, - 496, - }, - dictWord{6, 0, 694}, - dictWord{7, 0, 203}, - dictWord{7, 11, 1190}, - dictWord{137, 11, 620}, - dictWord{137, 11, 132}, - dictWord{6, 0, 547}, - dictWord{ - 134, - 0, - 1549, - }, - dictWord{8, 11, 258}, - dictWord{9, 11, 208}, - dictWord{137, 11, 359}, - dictWord{4, 0, 864}, - dictWord{5, 0, 88}, - dictWord{137, 0, 239}, - dictWord{ - 135, - 11, - 493, - }, - dictWord{4, 11, 317}, - dictWord{135, 11, 1279}, - dictWord{132, 11, 477}, - dictWord{4, 10, 578}, - dictWord{5, 11, 63}, - dictWord{133, 11, 509}, - dictWord{ - 7, - 0, - 650, - }, - dictWord{135, 0, 1310}, - dictWord{7, 0, 1076}, - dictWord{9, 0, 80}, - dictWord{11, 0, 78}, - dictWord{11, 0, 421}, - dictWord{11, 0, 534}, - dictWord{ - 140, - 0, - 545, - }, - dictWord{132, 11, 288}, - dictWord{12, 0, 553}, - dictWord{14, 0, 118}, - dictWord{133, 10, 923}, - dictWord{7, 0, 274}, - dictWord{11, 0, 479}, - dictWord{ - 139, - 0, - 507, - }, - dictWord{8, 11, 89}, - dictWord{8, 11, 620}, - dictWord{9, 11, 49}, - dictWord{10, 11, 774}, - dictWord{11, 11, 628}, - dictWord{12, 11, 322}, - dictWord{ - 143, - 11, - 124, - }, - dictWord{4, 0, 497}, - dictWord{135, 0, 1584}, - dictWord{7, 0, 261}, - dictWord{7, 0, 1115}, - dictWord{7, 0, 1354}, - dictWord{7, 0, 1404}, - dictWord{ - 7, - 0, - 1588, - }, - dictWord{7, 0, 1705}, - dictWord{7, 0, 1902}, - dictWord{9, 0, 465}, - dictWord{10, 0, 248}, - dictWord{10, 0, 349}, - dictWord{10, 0, 647}, - dictWord{11, 0, 527}, - dictWord{11, 0, 660}, - dictWord{11, 0, 669}, - dictWord{12, 0, 529}, - dictWord{13, 0, 305}, - dictWord{132, 10, 924}, - dictWord{133, 10, 665}, - dictWord{ - 136, - 0, - 13, - }, - dictWord{6, 0, 791}, - dictWord{138, 11, 120}, - dictWord{7, 0, 642}, - dictWord{8, 0, 250}, - dictWord{11, 0, 123}, - dictWord{11, 0, 137}, - dictWord{13, 0, 48}, - dictWord{142, 0, 95}, - dictWord{4, 10, 265}, - dictWord{7, 10, 807}, - dictWord{135, 10, 950}, - dictWord{5, 10, 93}, - dictWord{140, 10, 267}, - dictWord{135, 0, 1429}, - dictWord{4, 0, 949}, - dictWord{10, 0, 885}, - dictWord{10, 0, 891}, - dictWord{10, 0, 900}, - dictWord{10, 0, 939}, - dictWord{12, 0, 760}, - dictWord{142, 0, 449}, - dictWord{139, 11, 366}, - dictWord{132, 0, 818}, - dictWord{134, 11, 85}, - dictWord{135, 10, 994}, - dictWord{7, 0, 330}, - dictWord{5, 10, 233}, - dictWord{5, 10, 320}, - dictWord{6, 10, 140}, - dictWord{136, 10, 295}, - dictWord{4, 0, 1004}, - dictWord{8, 0, 982}, - dictWord{136, 0, 993}, - dictWord{133, 10, 978}, - dictWord{4, 10, 905}, - dictWord{6, 10, 1701}, - dictWord{137, 10, 843}, - dictWord{10, 0, 545}, - dictWord{140, 0, 301}, - dictWord{6, 0, 947}, - dictWord{134, 0, 1062}, - dictWord{ - 134, - 0, - 1188, - }, - dictWord{4, 0, 904}, - dictWord{5, 0, 794}, - dictWord{152, 10, 6}, - dictWord{134, 0, 1372}, - dictWord{135, 11, 608}, - dictWord{5, 11, 279}, - dictWord{ - 6, - 11, - 235, - }, - dictWord{7, 11, 468}, - dictWord{8, 11, 446}, - dictWord{9, 11, 637}, - dictWord{10, 11, 717}, - dictWord{11, 11, 738}, - dictWord{140, 11, 514}, - dictWord{ - 132, - 10, - 509, - }, - dictWord{5, 11, 17}, - dictWord{6, 11, 371}, - dictWord{137, 11, 528}, - dictWord{132, 0, 693}, - dictWord{4, 11, 115}, - dictWord{5, 11, 669}, - dictWord{ - 6, - 11, - 407, - }, - dictWord{8, 11, 311}, - dictWord{11, 11, 10}, - dictWord{141, 11, 5}, - dictWord{11, 0, 377}, - dictWord{7, 10, 273}, - dictWord{137, 11, 381}, - dictWord{ - 135, - 0, - 695, - }, - dictWord{7, 0, 386}, - dictWord{138, 0, 713}, - dictWord{135, 10, 1041}, - dictWord{134, 0, 1291}, - dictWord{6, 0, 7}, - dictWord{6, 0, 35}, - dictWord{ - 7, - 0, - 147, - }, - dictWord{7, 0, 1069}, - dictWord{7, 0, 1568}, - dictWord{7, 0, 1575}, - dictWord{7, 0, 1917}, - dictWord{8, 0, 43}, - dictWord{8, 0, 208}, - dictWord{9, 0, 128}, - dictWord{ - 9, - 0, - 866, - }, - dictWord{10, 0, 20}, - dictWord{11, 0, 981}, - dictWord{147, 0, 33}, - dictWord{7, 0, 893}, - dictWord{141, 0, 424}, - dictWord{139, 10, 234}, - dictWord{ - 150, - 11, - 56, - }, - dictWord{5, 11, 779}, - dictWord{5, 11, 807}, - dictWord{6, 11, 1655}, - dictWord{134, 11, 1676}, - dictWord{5, 10, 802}, - dictWord{7, 10, 2021}, - dictWord{136, 10, 805}, - dictWord{4, 11, 196}, - dictWord{5, 10, 167}, - dictWord{5, 11, 558}, - dictWord{5, 10, 899}, - dictWord{5, 11, 949}, - dictWord{6, 10, 410}, - dictWord{137, 10, 777}, - dictWord{137, 10, 789}, - dictWord{134, 10, 1705}, - dictWord{8, 0, 904}, - dictWord{140, 0, 787}, - dictWord{6, 0, 322}, - dictWord{9, 0, 552}, - dictWord{11, 0, 274}, - dictWord{13, 0, 209}, - dictWord{13, 0, 499}, - dictWord{14, 0, 85}, - dictWord{15, 0, 126}, - dictWord{145, 0, 70}, - dictWord{135, 10, 10}, - dictWord{ - 5, - 10, - 11, - }, - dictWord{6, 10, 117}, - dictWord{6, 10, 485}, - dictWord{7, 10, 1133}, - dictWord{9, 10, 582}, - dictWord{9, 10, 594}, - dictWord{11, 10, 21}, - dictWord{ - 11, - 10, - 818, - }, - dictWord{12, 10, 535}, - dictWord{141, 10, 86}, - dictWord{4, 10, 264}, - dictWord{7, 10, 1067}, - dictWord{8, 10, 204}, - dictWord{8, 10, 385}, - dictWord{139, 10, 953}, - dictWord{132, 11, 752}, - dictWord{138, 10, 56}, - dictWord{133, 10, 470}, - dictWord{6, 0, 1808}, - dictWord{8, 0, 83}, - dictWord{8, 0, 742}, - dictWord{8, 0, 817}, - dictWord{9, 0, 28}, - dictWord{9, 0, 29}, - dictWord{9, 0, 885}, - dictWord{10, 0, 387}, - dictWord{11, 0, 633}, - dictWord{11, 0, 740}, - dictWord{13, 0, 235}, - dictWord{13, 0, 254}, - dictWord{15, 0, 143}, - dictWord{143, 0, 146}, - dictWord{140, 0, 49}, - dictWord{134, 0, 1832}, - dictWord{4, 11, 227}, - dictWord{5, 11, 159}, - dictWord{5, 11, 409}, - dictWord{7, 11, 80}, - dictWord{10, 11, 294}, - dictWord{10, 11, 479}, - dictWord{12, 11, 418}, - dictWord{14, 11, 50}, - dictWord{14, 11, 249}, - dictWord{142, 11, 295}, - dictWord{7, 11, 1470}, - dictWord{8, 11, 66}, - dictWord{8, 11, 137}, - dictWord{8, 11, 761}, - dictWord{9, 11, 638}, - dictWord{11, 11, 80}, - dictWord{11, 11, 212}, - dictWord{11, 11, 368}, - dictWord{11, 11, 418}, - dictWord{12, 11, 8}, - dictWord{13, 11, 15}, - dictWord{16, 11, 61}, - dictWord{17, 11, 59}, - dictWord{19, 11, 28}, - dictWord{148, 11, 84}, - dictWord{139, 10, 1015}, - dictWord{138, 11, 468}, - dictWord{135, 0, 421}, - dictWord{6, 0, 415}, - dictWord{ - 7, - 0, - 1049, - }, - dictWord{137, 0, 442}, - dictWord{6, 11, 38}, - dictWord{7, 11, 1220}, - dictWord{8, 11, 185}, - dictWord{8, 11, 256}, - dictWord{9, 11, 22}, - dictWord{ - 9, - 11, - 331, - }, - dictWord{10, 11, 738}, - dictWord{11, 11, 205}, - dictWord{11, 11, 540}, - dictWord{11, 11, 746}, - dictWord{13, 11, 399}, - dictWord{13, 11, 465}, - dictWord{ - 14, - 11, - 88, - }, - dictWord{142, 11, 194}, - dictWord{139, 0, 289}, - dictWord{133, 10, 715}, - dictWord{4, 0, 110}, - dictWord{10, 0, 415}, - dictWord{10, 0, 597}, - dictWord{142, 0, 206}, - dictWord{4, 11, 159}, - dictWord{6, 11, 115}, - dictWord{7, 11, 252}, - dictWord{7, 11, 257}, - dictWord{7, 11, 1928}, - dictWord{8, 11, 69}, - dictWord{ - 9, - 11, - 384, - }, - dictWord{10, 11, 91}, - dictWord{10, 11, 615}, - dictWord{12, 11, 375}, - dictWord{14, 11, 235}, - dictWord{18, 11, 117}, - dictWord{147, 11, 123}, - dictWord{5, 11, 911}, - dictWord{136, 11, 278}, - dictWord{7, 0, 205}, - dictWord{7, 0, 2000}, - dictWord{8, 10, 794}, - dictWord{9, 10, 400}, - dictWord{10, 10, 298}, - dictWord{142, 10, 228}, - dictWord{135, 11, 1774}, - dictWord{4, 11, 151}, - dictWord{7, 11, 1567}, - dictWord{8, 11, 351}, - dictWord{137, 11, 322}, - dictWord{ - 136, - 10, - 724, - }, - dictWord{133, 11, 990}, - dictWord{7, 0, 1539}, - dictWord{11, 0, 512}, - dictWord{13, 0, 205}, - dictWord{19, 0, 30}, - dictWord{22, 0, 36}, - dictWord{23, 0, 19}, - dictWord{135, 11, 1539}, - dictWord{5, 11, 194}, - dictWord{7, 11, 1662}, - dictWord{9, 11, 90}, - dictWord{140, 11, 180}, - dictWord{6, 10, 190}, - dictWord{ - 7, - 10, - 768, - }, - dictWord{135, 10, 1170}, - dictWord{134, 0, 1340}, - dictWord{4, 0, 283}, - dictWord{135, 0, 1194}, - dictWord{133, 11, 425}, - dictWord{133, 11, 971}, - dictWord{12, 0, 549}, - dictWord{14, 10, 67}, - dictWord{147, 10, 60}, - dictWord{135, 10, 1023}, - dictWord{134, 0, 1720}, - dictWord{138, 11, 587}, - dictWord{ - 5, - 11, - 72, - }, - dictWord{6, 11, 264}, - dictWord{7, 11, 21}, - dictWord{7, 11, 46}, - dictWord{7, 11, 2013}, - dictWord{8, 11, 215}, - dictWord{8, 11, 513}, - dictWord{10, 11, 266}, - dictWord{139, 11, 22}, - dictWord{5, 0, 319}, - dictWord{135, 0, 534}, - dictWord{6, 10, 137}, - dictWord{9, 10, 75}, - dictWord{9, 10, 253}, - dictWord{10, 10, 194}, - dictWord{138, 10, 444}, - dictWord{7, 0, 1180}, - dictWord{20, 0, 112}, - dictWord{6, 11, 239}, - dictWord{7, 11, 118}, - dictWord{10, 11, 95}, - dictWord{11, 11, 603}, - dictWord{13, 11, 443}, - dictWord{14, 11, 160}, - dictWord{143, 11, 4}, - dictWord{134, 11, 431}, - dictWord{5, 11, 874}, - dictWord{6, 11, 1677}, - dictWord{ - 11, - 10, - 643, - }, - dictWord{12, 10, 115}, - dictWord{143, 11, 0}, - dictWord{134, 0, 967}, - dictWord{6, 11, 65}, - dictWord{7, 11, 939}, - dictWord{7, 11, 1172}, - dictWord{ - 7, - 11, - 1671, - }, - dictWord{9, 11, 540}, - dictWord{10, 11, 696}, - dictWord{11, 11, 265}, - dictWord{11, 11, 732}, - dictWord{11, 11, 928}, - dictWord{11, 11, 937}, - dictWord{ - 12, - 11, - 399, - }, - dictWord{13, 11, 438}, - dictWord{149, 11, 19}, - dictWord{137, 11, 200}, - dictWord{135, 0, 1940}, - dictWord{5, 10, 760}, - dictWord{7, 10, 542}, - dictWord{8, 10, 135}, - dictWord{136, 10, 496}, - dictWord{140, 11, 44}, - dictWord{7, 11, 1655}, - dictWord{136, 11, 305}, - dictWord{7, 10, 319}, - dictWord{ - 7, - 10, - 355, - }, - dictWord{7, 10, 763}, - dictWord{10, 10, 389}, - dictWord{145, 10, 43}, - dictWord{136, 0, 735}, - dictWord{138, 10, 786}, - dictWord{137, 11, 19}, - dictWord{132, 11, 696}, - dictWord{5, 0, 132}, - dictWord{9, 0, 486}, - dictWord{9, 0, 715}, - dictWord{10, 0, 458}, - dictWord{11, 0, 373}, - dictWord{11, 0, 668}, - dictWord{ - 11, - 0, - 795, - }, - dictWord{11, 0, 897}, - dictWord{12, 0, 272}, - dictWord{12, 0, 424}, - dictWord{12, 0, 539}, - dictWord{12, 0, 558}, - dictWord{14, 0, 245}, - dictWord{ - 14, - 0, - 263, - }, - dictWord{14, 0, 264}, - dictWord{14, 0, 393}, - dictWord{142, 0, 403}, - dictWord{10, 0, 38}, - dictWord{139, 0, 784}, - dictWord{132, 0, 838}, - dictWord{ - 4, - 11, - 302, - }, - dictWord{135, 11, 1766}, - dictWord{133, 0, 379}, - dictWord{5, 0, 8}, - dictWord{6, 0, 89}, - dictWord{6, 0, 400}, - dictWord{7, 0, 1569}, - dictWord{7, 0, 1623}, - dictWord{7, 0, 1850}, - dictWord{8, 0, 218}, - dictWord{8, 0, 422}, - dictWord{9, 0, 570}, - dictWord{10, 0, 626}, - dictWord{4, 11, 726}, - dictWord{133, 11, 630}, - dictWord{ - 4, - 0, - 1017, - }, - dictWord{138, 0, 660}, - dictWord{6, 0, 387}, - dictWord{7, 0, 882}, - dictWord{141, 0, 111}, - dictWord{6, 0, 224}, - dictWord{7, 0, 877}, - dictWord{ - 137, - 0, - 647, - }, - dictWord{4, 10, 58}, - dictWord{5, 10, 286}, - dictWord{6, 10, 319}, - dictWord{7, 10, 402}, - dictWord{7, 10, 1254}, - dictWord{7, 10, 1903}, - dictWord{ - 8, - 10, - 356, - }, - dictWord{140, 10, 408}, - dictWord{135, 0, 790}, - dictWord{9, 0, 510}, - dictWord{10, 0, 53}, - dictWord{4, 10, 389}, - dictWord{9, 10, 181}, - dictWord{ - 10, - 10, - 29, - }, - dictWord{10, 10, 816}, - dictWord{11, 10, 311}, - dictWord{11, 10, 561}, - dictWord{12, 10, 67}, - dictWord{141, 10, 181}, - dictWord{142, 0, 458}, - dictWord{ - 6, - 11, - 118, - }, - dictWord{7, 11, 215}, - dictWord{7, 11, 1521}, - dictWord{140, 11, 11}, - dictWord{134, 0, 954}, - dictWord{135, 0, 394}, - dictWord{134, 0, 1367}, - dictWord{5, 11, 225}, - dictWord{133, 10, 373}, - dictWord{132, 0, 882}, - dictWord{7, 0, 1409}, - dictWord{135, 10, 1972}, - dictWord{135, 10, 1793}, - dictWord{ - 4, - 11, - 370, - }, - dictWord{5, 11, 756}, - dictWord{135, 11, 1326}, - dictWord{150, 11, 13}, - dictWord{7, 11, 354}, - dictWord{10, 11, 410}, - dictWord{139, 11, 815}, - dictWord{6, 11, 1662}, - dictWord{7, 11, 48}, - dictWord{8, 11, 771}, - dictWord{10, 11, 116}, - dictWord{13, 11, 104}, - dictWord{14, 11, 105}, - dictWord{14, 11, 184}, - dictWord{15, 11, 168}, - dictWord{19, 11, 92}, - dictWord{148, 11, 68}, - dictWord{7, 0, 124}, - dictWord{136, 0, 38}, - dictWord{5, 0, 261}, - dictWord{7, 0, 78}, - dictWord{ - 7, - 0, - 199, - }, - dictWord{8, 0, 815}, - dictWord{9, 0, 126}, - dictWord{10, 0, 342}, - dictWord{140, 0, 647}, - dictWord{4, 0, 628}, - dictWord{140, 0, 724}, - dictWord{7, 0, 266}, - dictWord{8, 0, 804}, - dictWord{7, 10, 1651}, - dictWord{145, 10, 89}, - dictWord{135, 0, 208}, - dictWord{134, 0, 1178}, - dictWord{6, 0, 79}, - dictWord{135, 0, 1519}, - dictWord{132, 10, 672}, - dictWord{133, 10, 737}, - dictWord{136, 0, 741}, - dictWord{132, 11, 120}, - dictWord{4, 0, 710}, - dictWord{6, 0, 376}, - dictWord{ - 134, - 0, - 606, - }, - dictWord{134, 0, 1347}, - dictWord{134, 0, 1494}, - dictWord{6, 0, 850}, - dictWord{6, 0, 1553}, - dictWord{137, 0, 821}, - dictWord{5, 10, 145}, - dictWord{ - 134, - 11, - 593, - }, - dictWord{7, 0, 1311}, - dictWord{140, 0, 135}, - dictWord{4, 0, 467}, - dictWord{5, 0, 405}, - dictWord{134, 0, 544}, - dictWord{5, 11, 820}, - dictWord{ - 135, - 11, - 931, - }, - dictWord{6, 0, 100}, - dictWord{7, 0, 244}, - dictWord{7, 0, 632}, - dictWord{7, 0, 1609}, - dictWord{8, 0, 178}, - dictWord{8, 0, 638}, - dictWord{141, 0, 58}, - dictWord{4, 10, 387}, - dictWord{135, 10, 1288}, - dictWord{6, 11, 151}, - dictWord{6, 11, 1675}, - dictWord{7, 11, 383}, - dictWord{151, 11, 10}, - dictWord{ - 132, - 0, - 481, - }, - dictWord{135, 10, 550}, - dictWord{134, 0, 1378}, - dictWord{6, 11, 1624}, - dictWord{11, 11, 11}, - dictWord{12, 11, 422}, - dictWord{13, 11, 262}, - dictWord{142, 11, 360}, - dictWord{133, 0, 791}, - dictWord{4, 11, 43}, - dictWord{5, 11, 344}, - dictWord{133, 11, 357}, - dictWord{7, 0, 1227}, - dictWord{140, 0, 978}, - dictWord{7, 0, 686}, - dictWord{8, 0, 33}, - dictWord{8, 0, 238}, - dictWord{10, 0, 616}, - dictWord{11, 0, 467}, - dictWord{11, 0, 881}, - dictWord{13, 0, 217}, - dictWord{ - 13, - 0, - 253, - }, - dictWord{142, 0, 268}, - dictWord{137, 0, 857}, - dictWord{8, 0, 467}, - dictWord{8, 0, 1006}, - dictWord{7, 11, 148}, - dictWord{8, 11, 284}, - dictWord{ - 141, - 11, - 63, - }, - dictWord{4, 10, 576}, - dictWord{135, 10, 1263}, - dictWord{133, 11, 888}, - dictWord{5, 10, 919}, - dictWord{134, 10, 1673}, - dictWord{20, 10, 37}, - dictWord{148, 11, 37}, - dictWord{132, 0, 447}, - dictWord{132, 11, 711}, - dictWord{4, 0, 128}, - dictWord{5, 0, 415}, - dictWord{6, 0, 462}, - dictWord{7, 0, 294}, - dictWord{ - 7, - 0, - 578, - }, - dictWord{10, 0, 710}, - dictWord{139, 0, 86}, - dictWord{4, 10, 82}, - dictWord{5, 10, 333}, - dictWord{5, 10, 904}, - dictWord{6, 10, 207}, - dictWord{7, 10, 325}, - dictWord{7, 10, 1726}, - dictWord{8, 10, 101}, - dictWord{10, 10, 778}, - dictWord{139, 10, 220}, - dictWord{136, 0, 587}, - dictWord{137, 11, 440}, - dictWord{ - 133, - 10, - 903, - }, - dictWord{6, 0, 427}, - dictWord{7, 0, 1018}, - dictWord{138, 0, 692}, - dictWord{4, 0, 195}, - dictWord{135, 0, 802}, - dictWord{140, 10, 147}, - dictWord{ - 134, - 0, - 1546, - }, - dictWord{134, 0, 684}, - dictWord{132, 10, 705}, - dictWord{136, 0, 345}, - dictWord{11, 11, 678}, - dictWord{140, 11, 307}, - dictWord{ - 133, - 0, - 365, - }, - dictWord{134, 0, 1683}, - dictWord{4, 11, 65}, - dictWord{5, 11, 479}, - dictWord{5, 11, 1004}, - dictWord{7, 11, 1913}, - dictWord{8, 11, 317}, - dictWord{ - 9, - 11, - 302, - }, - dictWord{10, 11, 612}, - dictWord{141, 11, 22}, - dictWord{138, 0, 472}, - dictWord{4, 11, 261}, - dictWord{135, 11, 510}, - dictWord{134, 10, 90}, - dictWord{142, 0, 433}, - dictWord{151, 0, 28}, - dictWord{4, 11, 291}, - dictWord{7, 11, 101}, - dictWord{9, 11, 515}, - dictWord{12, 11, 152}, - dictWord{12, 11, 443}, - dictWord{13, 11, 392}, - dictWord{142, 11, 357}, - dictWord{140, 0, 997}, - dictWord{5, 0, 3}, - dictWord{8, 0, 578}, - dictWord{9, 0, 118}, - dictWord{10, 0, 705}, - dictWord{ - 141, - 0, - 279, - }, - dictWord{135, 11, 1266}, - dictWord{7, 10, 813}, - dictWord{12, 10, 497}, - dictWord{141, 10, 56}, - dictWord{133, 0, 229}, - dictWord{6, 10, 125}, - dictWord{135, 10, 1277}, - dictWord{8, 0, 102}, - dictWord{10, 0, 578}, - dictWord{10, 0, 672}, - dictWord{12, 0, 496}, - dictWord{13, 0, 408}, - dictWord{14, 0, 121}, - dictWord{17, 0, 106}, - dictWord{151, 10, 12}, - dictWord{6, 0, 866}, - dictWord{134, 0, 1080}, - dictWord{136, 0, 1022}, - dictWord{4, 11, 130}, - dictWord{135, 11, 843}, - dictWord{5, 11, 42}, - dictWord{5, 11, 879}, - dictWord{7, 11, 245}, - dictWord{7, 11, 324}, - dictWord{7, 11, 1532}, - dictWord{11, 11, 463}, - dictWord{11, 11, 472}, - dictWord{13, 11, 363}, - dictWord{144, 11, 52}, - dictWord{150, 0, 55}, - dictWord{8, 0, 115}, - dictWord{8, 0, 350}, - dictWord{9, 0, 489}, - dictWord{10, 0, 128}, - dictWord{ - 11, - 0, - 306, - }, - dictWord{12, 0, 373}, - dictWord{14, 0, 30}, - dictWord{17, 0, 79}, - dictWord{19, 0, 80}, - dictWord{4, 11, 134}, - dictWord{133, 11, 372}, - dictWord{ - 134, - 0, - 657, - }, - dictWord{134, 0, 933}, - dictWord{135, 11, 1147}, - dictWord{4, 0, 230}, - dictWord{133, 0, 702}, - dictWord{134, 0, 1728}, - dictWord{4, 0, 484}, - dictWord{ - 18, - 0, - 26, - }, - dictWord{19, 0, 42}, - dictWord{20, 0, 43}, - dictWord{21, 0, 0}, - dictWord{23, 0, 27}, - dictWord{152, 0, 14}, - dictWord{7, 0, 185}, - dictWord{135, 0, 703}, - dictWord{ - 6, - 0, - 417, - }, - dictWord{10, 0, 618}, - dictWord{7, 10, 1106}, - dictWord{9, 10, 770}, - dictWord{11, 10, 112}, - dictWord{140, 10, 413}, - dictWord{134, 0, 803}, - dictWord{132, 11, 644}, - dictWord{134, 0, 1262}, - dictWord{7, 11, 540}, - dictWord{12, 10, 271}, - dictWord{145, 10, 109}, - dictWord{135, 11, 123}, - dictWord{ - 132, - 0, - 633, - }, - dictWord{134, 11, 623}, - dictWord{4, 11, 908}, - dictWord{5, 11, 359}, - dictWord{5, 11, 508}, - dictWord{6, 11, 1723}, - dictWord{7, 11, 343}, - dictWord{ - 7, - 11, - 1996, - }, - dictWord{135, 11, 2026}, - dictWord{135, 0, 479}, - dictWord{10, 0, 262}, - dictWord{7, 10, 304}, - dictWord{9, 10, 646}, - dictWord{9, 10, 862}, - dictWord{ - 11, - 10, - 696, - }, - dictWord{12, 10, 208}, - dictWord{15, 10, 79}, - dictWord{147, 10, 108}, - dictWord{4, 11, 341}, - dictWord{135, 11, 480}, - dictWord{134, 0, 830}, - dictWord{5, 0, 70}, - dictWord{5, 0, 622}, - dictWord{6, 0, 334}, - dictWord{7, 0, 1032}, - dictWord{9, 0, 171}, - dictWord{11, 0, 26}, - dictWord{11, 0, 213}, - dictWord{ - 11, - 0, - 637, - }, - dictWord{11, 0, 707}, - dictWord{12, 0, 202}, - dictWord{12, 0, 380}, - dictWord{13, 0, 226}, - dictWord{13, 0, 355}, - dictWord{14, 0, 222}, - dictWord{145, 0, 42}, - dictWord{135, 10, 981}, - dictWord{143, 0, 217}, - dictWord{137, 11, 114}, - dictWord{4, 0, 23}, - dictWord{4, 0, 141}, - dictWord{5, 0, 313}, - dictWord{5, 0, 1014}, - dictWord{6, 0, 50}, - dictWord{6, 0, 51}, - dictWord{7, 0, 142}, - dictWord{7, 0, 384}, - dictWord{7, 0, 559}, - dictWord{8, 0, 640}, - dictWord{9, 0, 460}, - dictWord{9, 0, 783}, - dictWord{11, 0, 741}, - dictWord{12, 0, 183}, - dictWord{141, 0, 488}, - dictWord{141, 0, 360}, - dictWord{7, 0, 1586}, - dictWord{7, 11, 1995}, - dictWord{8, 11, 299}, - dictWord{11, 11, 890}, - dictWord{140, 11, 674}, - dictWord{132, 10, 434}, - dictWord{7, 0, 652}, - dictWord{134, 10, 550}, - dictWord{7, 0, 766}, - dictWord{5, 10, 553}, - dictWord{138, 10, 824}, - dictWord{7, 0, 737}, - dictWord{8, 0, 298}, - dictWord{136, 10, 452}, - dictWord{4, 11, 238}, - dictWord{5, 11, 503}, - dictWord{6, 11, 179}, - dictWord{7, 11, 2003}, - dictWord{8, 11, 381}, - dictWord{8, 11, 473}, - dictWord{9, 11, 149}, - dictWord{10, 11, 183}, - dictWord{15, 11, 45}, - dictWord{143, 11, 86}, - dictWord{133, 10, 292}, - dictWord{5, 0, 222}, - dictWord{9, 0, 655}, - dictWord{138, 0, 534}, - dictWord{138, 10, 135}, - dictWord{4, 11, 121}, - dictWord{5, 11, 156}, - dictWord{5, 11, 349}, - dictWord{9, 11, 136}, - dictWord{10, 11, 605}, - dictWord{14, 11, 342}, - dictWord{147, 11, 107}, - dictWord{137, 0, 906}, - dictWord{6, 0, 1013}, - dictWord{134, 0, 1250}, - dictWord{6, 0, 1956}, - dictWord{6, 0, 2009}, - dictWord{8, 0, 991}, - dictWord{144, 0, 120}, - dictWord{135, 11, 1192}, - dictWord{ - 138, - 0, - 503, - }, - dictWord{5, 0, 154}, - dictWord{7, 0, 1491}, - dictWord{10, 0, 379}, - dictWord{138, 0, 485}, - dictWord{6, 0, 1867}, - dictWord{6, 0, 1914}, - dictWord{6, 0, 1925}, - dictWord{9, 0, 917}, - dictWord{9, 0, 925}, - dictWord{9, 0, 932}, - dictWord{9, 0, 951}, - dictWord{9, 0, 1007}, - dictWord{9, 0, 1013}, - dictWord{12, 0, 806}, - dictWord{ - 12, - 0, - 810, - }, - dictWord{12, 0, 814}, - dictWord{12, 0, 816}, - dictWord{12, 0, 824}, - dictWord{12, 0, 832}, - dictWord{12, 0, 837}, - dictWord{12, 0, 863}, - dictWord{ - 12, - 0, - 868, - }, - dictWord{12, 0, 870}, - dictWord{12, 0, 889}, - dictWord{12, 0, 892}, - dictWord{12, 0, 900}, - dictWord{12, 0, 902}, - dictWord{12, 0, 908}, - dictWord{12, 0, 933}, - dictWord{12, 0, 942}, - dictWord{12, 0, 949}, - dictWord{12, 0, 954}, - dictWord{15, 0, 175}, - dictWord{15, 0, 203}, - dictWord{15, 0, 213}, - dictWord{15, 0, 218}, - dictWord{15, 0, 225}, - dictWord{15, 0, 231}, - dictWord{15, 0, 239}, - dictWord{15, 0, 248}, - dictWord{15, 0, 252}, - dictWord{18, 0, 190}, - dictWord{18, 0, 204}, - dictWord{ - 18, - 0, - 215, - }, - dictWord{18, 0, 216}, - dictWord{18, 0, 222}, - dictWord{18, 0, 225}, - dictWord{18, 0, 230}, - dictWord{18, 0, 239}, - dictWord{18, 0, 241}, - dictWord{ - 21, - 0, - 42, - }, - dictWord{21, 0, 43}, - dictWord{21, 0, 44}, - dictWord{21, 0, 45}, - dictWord{21, 0, 46}, - dictWord{21, 0, 53}, - dictWord{24, 0, 27}, - dictWord{152, 0, 31}, - dictWord{ - 133, - 0, - 716, - }, - dictWord{135, 0, 844}, - dictWord{4, 0, 91}, - dictWord{5, 0, 388}, - dictWord{5, 0, 845}, - dictWord{6, 0, 206}, - dictWord{6, 0, 252}, - dictWord{6, 0, 365}, - dictWord{ - 7, - 0, - 136, - }, - dictWord{7, 0, 531}, - dictWord{136, 0, 621}, - dictWord{7, 10, 393}, - dictWord{10, 10, 603}, - dictWord{139, 10, 206}, - dictWord{6, 11, 80}, - dictWord{ - 6, - 11, - 1694, - }, - dictWord{7, 11, 173}, - dictWord{7, 11, 1974}, - dictWord{9, 11, 547}, - dictWord{10, 11, 730}, - dictWord{14, 11, 18}, - dictWord{150, 11, 39}, - dictWord{137, 0, 748}, - dictWord{4, 11, 923}, - dictWord{134, 11, 1711}, - dictWord{4, 10, 912}, - dictWord{137, 10, 232}, - dictWord{7, 10, 98}, - dictWord{7, 10, 1973}, - dictWord{136, 10, 716}, - dictWord{14, 0, 103}, - dictWord{133, 10, 733}, - dictWord{132, 11, 595}, - dictWord{12, 0, 158}, - dictWord{18, 0, 8}, - dictWord{19, 0, 62}, - dictWord{20, 0, 6}, - dictWord{22, 0, 4}, - dictWord{23, 0, 2}, - dictWord{23, 0, 9}, - dictWord{5, 11, 240}, - dictWord{6, 11, 459}, - dictWord{7, 11, 12}, - dictWord{7, 11, 114}, - dictWord{7, 11, 502}, - dictWord{7, 11, 1751}, - dictWord{7, 11, 1753}, - dictWord{7, 11, 1805}, - dictWord{8, 11, 658}, - dictWord{9, 11, 1}, - dictWord{11, 11, 959}, - dictWord{13, 11, 446}, - dictWord{142, 11, 211}, - dictWord{135, 0, 576}, - dictWord{5, 0, 771}, - dictWord{5, 0, 863}, - dictWord{5, 0, 898}, - dictWord{6, 0, 648}, - dictWord{ - 6, - 0, - 1632, - }, - dictWord{6, 0, 1644}, - dictWord{134, 0, 1780}, - dictWord{133, 0, 331}, - dictWord{7, 11, 633}, - dictWord{7, 11, 905}, - dictWord{7, 11, 909}, - dictWord{ - 7, - 11, - 1538, - }, - dictWord{9, 11, 767}, - dictWord{140, 11, 636}, - dictWord{140, 0, 632}, - dictWord{5, 0, 107}, - dictWord{7, 0, 201}, - dictWord{136, 0, 518}, - dictWord{ - 6, - 0, - 446, - }, - dictWord{7, 0, 1817}, - dictWord{134, 11, 490}, - dictWord{9, 0, 851}, - dictWord{141, 0, 510}, - dictWord{7, 11, 250}, - dictWord{8, 11, 506}, - dictWord{ - 136, - 11, - 507, - }, - dictWord{4, 0, 504}, - dictWord{137, 10, 72}, - dictWord{132, 11, 158}, - dictWord{4, 11, 140}, - dictWord{7, 11, 362}, - dictWord{8, 11, 209}, - dictWord{ - 9, - 11, - 10, - }, - dictWord{9, 11, 160}, - dictWord{9, 11, 503}, - dictWord{10, 11, 689}, - dictWord{11, 11, 350}, - dictWord{11, 11, 553}, - dictWord{11, 11, 725}, - dictWord{ - 12, - 11, - 252, - }, - dictWord{12, 11, 583}, - dictWord{13, 11, 192}, - dictWord{13, 11, 352}, - dictWord{14, 11, 269}, - dictWord{14, 11, 356}, - dictWord{148, 11, 50}, - dictWord{6, 11, 597}, - dictWord{135, 11, 1318}, - dictWord{135, 10, 1454}, - dictWord{5, 0, 883}, - dictWord{5, 0, 975}, - dictWord{8, 0, 392}, - dictWord{148, 0, 7}, - dictWord{6, 11, 228}, - dictWord{7, 11, 1341}, - dictWord{9, 11, 408}, - dictWord{138, 11, 343}, - dictWord{11, 11, 348}, - dictWord{11, 10, 600}, - dictWord{12, 11, 99}, - dictWord{13, 10, 245}, - dictWord{18, 11, 1}, - dictWord{18, 11, 11}, - dictWord{147, 11, 4}, - dictWord{134, 11, 296}, - dictWord{5, 0, 922}, - dictWord{134, 0, 1707}, - dictWord{132, 11, 557}, - dictWord{4, 11, 548}, - dictWord{7, 10, 164}, - dictWord{7, 10, 1571}, - dictWord{9, 10, 107}, - dictWord{140, 10, 225}, - dictWord{ - 7, - 11, - 197, - }, - dictWord{8, 11, 142}, - dictWord{8, 11, 325}, - dictWord{9, 11, 150}, - dictWord{9, 11, 596}, - dictWord{10, 11, 350}, - dictWord{10, 11, 353}, - dictWord{ - 11, - 11, - 74, - }, - dictWord{11, 11, 315}, - dictWord{14, 11, 423}, - dictWord{143, 11, 141}, - dictWord{5, 0, 993}, - dictWord{7, 0, 515}, - dictWord{137, 0, 91}, - dictWord{4, 0, 131}, - dictWord{8, 0, 200}, - dictWord{5, 10, 484}, - dictWord{5, 10, 510}, - dictWord{6, 10, 434}, - dictWord{7, 10, 1000}, - dictWord{7, 10, 1098}, - dictWord{136, 10, 2}, - dictWord{152, 0, 10}, - dictWord{4, 11, 62}, - dictWord{5, 11, 83}, - dictWord{6, 11, 399}, - dictWord{6, 11, 579}, - dictWord{7, 11, 692}, - dictWord{7, 11, 846}, - dictWord{ - 7, - 11, - 1015, - }, - dictWord{7, 11, 1799}, - dictWord{8, 11, 403}, - dictWord{9, 11, 394}, - dictWord{10, 11, 133}, - dictWord{12, 11, 4}, - dictWord{12, 11, 297}, - dictWord{ - 12, - 11, - 452, - }, - dictWord{16, 11, 81}, - dictWord{18, 11, 19}, - dictWord{18, 11, 25}, - dictWord{21, 11, 14}, - dictWord{22, 11, 12}, - dictWord{151, 11, 18}, - dictWord{ - 140, - 11, - 459, - }, - dictWord{132, 11, 177}, - dictWord{7, 0, 1433}, - dictWord{9, 0, 365}, - dictWord{137, 11, 365}, - dictWord{132, 10, 460}, - dictWord{5, 0, 103}, - dictWord{ - 6, - 0, - 2004, - }, - dictWord{7, 0, 921}, - dictWord{8, 0, 580}, - dictWord{8, 0, 593}, - dictWord{8, 0, 630}, - dictWord{10, 0, 28}, - dictWord{5, 11, 411}, - dictWord{ - 135, - 11, - 653, - }, - dictWord{4, 10, 932}, - dictWord{133, 10, 891}, - dictWord{4, 0, 911}, - dictWord{5, 0, 867}, - dictWord{5, 0, 1013}, - dictWord{7, 0, 2034}, - dictWord{8, 0, 798}, - dictWord{136, 0, 813}, - dictWord{7, 11, 439}, - dictWord{10, 11, 727}, - dictWord{11, 11, 260}, - dictWord{139, 11, 684}, - dictWord{136, 10, 625}, - dictWord{ - 5, - 11, - 208, - }, - dictWord{7, 11, 753}, - dictWord{135, 11, 1528}, - dictWord{5, 0, 461}, - dictWord{7, 0, 1925}, - dictWord{12, 0, 39}, - dictWord{13, 0, 265}, - dictWord{ - 13, - 0, - 439, - }, - dictWord{134, 10, 76}, - dictWord{6, 0, 853}, - dictWord{8, 10, 92}, - dictWord{137, 10, 221}, - dictWord{5, 0, 135}, - dictWord{6, 0, 519}, - dictWord{7, 0, 1722}, - dictWord{10, 0, 271}, - dictWord{11, 0, 261}, - dictWord{145, 0, 54}, - dictWord{139, 11, 814}, - dictWord{14, 0, 338}, - dictWord{148, 0, 81}, - dictWord{4, 0, 300}, - dictWord{133, 0, 436}, - dictWord{5, 0, 419}, - dictWord{5, 0, 687}, - dictWord{7, 0, 864}, - dictWord{9, 0, 470}, - dictWord{135, 11, 864}, - dictWord{9, 0, 836}, - dictWord{ - 133, - 11, - 242, - }, - dictWord{134, 0, 1937}, - dictWord{4, 10, 763}, - dictWord{133, 11, 953}, - dictWord{132, 10, 622}, - dictWord{132, 0, 393}, - dictWord{ - 133, - 10, - 253, - }, - dictWord{8, 0, 357}, - dictWord{10, 0, 745}, - dictWord{14, 0, 426}, - dictWord{17, 0, 94}, - dictWord{19, 0, 57}, - dictWord{135, 10, 546}, - dictWord{5, 11, 615}, - dictWord{146, 11, 37}, - dictWord{9, 10, 73}, - dictWord{10, 10, 110}, - dictWord{14, 10, 185}, - dictWord{145, 10, 119}, - dictWord{11, 0, 703}, - dictWord{7, 10, 624}, - dictWord{7, 10, 916}, - dictWord{10, 10, 256}, - dictWord{139, 10, 87}, - dictWord{133, 11, 290}, - dictWord{5, 10, 212}, - dictWord{12, 10, 35}, - dictWord{ - 141, - 10, - 382, - }, - dictWord{132, 11, 380}, - dictWord{5, 11, 52}, - dictWord{7, 11, 277}, - dictWord{9, 11, 368}, - dictWord{139, 11, 791}, - dictWord{133, 0, 387}, - dictWord{ - 10, - 11, - 138, - }, - dictWord{139, 11, 476}, - dictWord{4, 0, 6}, - dictWord{5, 0, 708}, - dictWord{136, 0, 75}, - dictWord{7, 0, 1351}, - dictWord{9, 0, 581}, - dictWord{10, 0, 639}, - dictWord{11, 0, 453}, - dictWord{140, 0, 584}, - dictWord{132, 0, 303}, - dictWord{138, 0, 772}, - dictWord{135, 10, 1175}, - dictWord{4, 0, 749}, - dictWord{ - 5, - 10, - 816, - }, - dictWord{6, 11, 256}, - dictWord{7, 11, 307}, - dictWord{7, 11, 999}, - dictWord{7, 11, 1481}, - dictWord{7, 11, 1732}, - dictWord{7, 11, 1738}, - dictWord{ - 8, - 11, - 265, - }, - dictWord{9, 11, 414}, - dictWord{11, 11, 316}, - dictWord{12, 11, 52}, - dictWord{13, 11, 420}, - dictWord{147, 11, 100}, - dictWord{135, 11, 1296}, - dictWord{ - 6, - 0, - 1065, - }, - dictWord{5, 10, 869}, - dictWord{5, 10, 968}, - dictWord{6, 10, 1626}, - dictWord{8, 10, 734}, - dictWord{136, 10, 784}, - dictWord{4, 10, 542}, - dictWord{ - 6, - 10, - 1716, - }, - dictWord{6, 10, 1727}, - dictWord{7, 10, 1082}, - dictWord{7, 10, 1545}, - dictWord{8, 10, 56}, - dictWord{8, 10, 118}, - dictWord{8, 10, 412}, - dictWord{ - 8, - 10, - 564, - }, - dictWord{9, 10, 888}, - dictWord{9, 10, 908}, - dictWord{10, 10, 50}, - dictWord{10, 10, 423}, - dictWord{11, 10, 685}, - dictWord{11, 10, 697}, - dictWord{11, 10, 933}, - dictWord{12, 10, 299}, - dictWord{13, 10, 126}, - dictWord{13, 10, 136}, - dictWord{13, 10, 170}, - dictWord{141, 10, 190}, - dictWord{ - 134, - 0, - 226, - }, - dictWord{4, 0, 106}, - dictWord{7, 0, 310}, - dictWord{11, 0, 717}, - dictWord{133, 11, 723}, - dictWord{5, 0, 890}, - dictWord{5, 0, 988}, - dictWord{4, 10, 232}, - dictWord{9, 10, 202}, - dictWord{10, 10, 474}, - dictWord{140, 10, 433}, - dictWord{6, 0, 626}, - dictWord{142, 0, 431}, - dictWord{10, 0, 706}, - dictWord{150, 0, 44}, - dictWord{13, 0, 51}, - dictWord{6, 10, 108}, - dictWord{7, 10, 1003}, - dictWord{7, 10, 1181}, - dictWord{8, 10, 111}, - dictWord{136, 10, 343}, - dictWord{132, 0, 698}, - dictWord{5, 11, 109}, - dictWord{6, 11, 1784}, - dictWord{7, 11, 1895}, - dictWord{12, 11, 296}, - dictWord{140, 11, 302}, - dictWord{134, 0, 828}, - dictWord{ - 134, - 10, - 1712, - }, - dictWord{138, 0, 17}, - dictWord{7, 0, 1929}, - dictWord{4, 10, 133}, - dictWord{5, 11, 216}, - dictWord{7, 10, 711}, - dictWord{7, 10, 1298}, - dictWord{ - 7, - 10, - 1585, - }, - dictWord{7, 11, 1879}, - dictWord{9, 11, 141}, - dictWord{9, 11, 270}, - dictWord{9, 11, 679}, - dictWord{10, 11, 159}, - dictWord{10, 11, 553}, - dictWord{ - 11, - 11, - 197, - }, - dictWord{11, 11, 438}, - dictWord{12, 11, 538}, - dictWord{12, 11, 559}, - dictWord{13, 11, 193}, - dictWord{13, 11, 423}, - dictWord{14, 11, 144}, - dictWord{14, 11, 166}, - dictWord{14, 11, 167}, - dictWord{15, 11, 67}, - dictWord{147, 11, 84}, - dictWord{141, 11, 127}, - dictWord{7, 11, 1872}, - dictWord{ - 137, - 11, - 81, - }, - dictWord{6, 10, 99}, - dictWord{7, 10, 1808}, - dictWord{145, 10, 57}, - dictWord{134, 11, 391}, - dictWord{5, 0, 689}, - dictWord{6, 0, 84}, - dictWord{7, 0, 1250}, - dictWord{6, 10, 574}, - dictWord{7, 10, 428}, - dictWord{10, 10, 669}, - dictWord{11, 10, 485}, - dictWord{11, 10, 840}, - dictWord{12, 10, 300}, - dictWord{ - 142, - 10, - 250, - }, - dictWord{7, 11, 322}, - dictWord{136, 11, 249}, - dictWord{7, 11, 432}, - dictWord{135, 11, 1649}, - dictWord{135, 10, 1871}, - dictWord{137, 10, 252}, - dictWord{6, 11, 155}, - dictWord{140, 11, 234}, - dictWord{7, 0, 871}, - dictWord{19, 0, 27}, - dictWord{147, 11, 27}, - dictWord{140, 0, 498}, - dictWord{5, 0, 986}, - dictWord{6, 0, 130}, - dictWord{138, 0, 823}, - dictWord{6, 0, 1793}, - dictWord{7, 0, 1582}, - dictWord{8, 0, 458}, - dictWord{10, 0, 101}, - dictWord{10, 0, 318}, - dictWord{ - 10, - 0, - 945, - }, - dictWord{12, 0, 734}, - dictWord{16, 0, 104}, - dictWord{18, 0, 177}, - dictWord{6, 10, 323}, - dictWord{135, 10, 1564}, - dictWord{5, 11, 632}, - dictWord{ - 138, - 11, - 526, - }, - dictWord{10, 0, 435}, - dictWord{7, 10, 461}, - dictWord{136, 10, 775}, - dictWord{6, 11, 144}, - dictWord{7, 11, 948}, - dictWord{7, 11, 1042}, - dictWord{ - 7, - 11, - 1857, - }, - dictWord{8, 11, 235}, - dictWord{8, 11, 461}, - dictWord{9, 11, 453}, - dictWord{9, 11, 530}, - dictWord{10, 11, 354}, - dictWord{17, 11, 77}, - dictWord{ - 19, - 11, - 99, - }, - dictWord{148, 11, 79}, - dictWord{138, 0, 966}, - dictWord{7, 0, 1644}, - dictWord{137, 0, 129}, - dictWord{135, 0, 997}, - dictWord{136, 0, 502}, - dictWord{ - 5, - 11, - 196, - }, - dictWord{6, 11, 486}, - dictWord{7, 11, 212}, - dictWord{8, 11, 309}, - dictWord{136, 11, 346}, - dictWord{7, 10, 727}, - dictWord{146, 10, 73}, - dictWord{132, 0, 823}, - dictWord{132, 11, 686}, - dictWord{135, 0, 1927}, - dictWord{4, 0, 762}, - dictWord{7, 0, 1756}, - dictWord{137, 0, 98}, - dictWord{136, 10, 577}, - dictWord{24, 0, 8}, - dictWord{4, 11, 30}, - dictWord{5, 11, 43}, - dictWord{152, 11, 8}, - dictWord{7, 0, 1046}, - dictWord{139, 0, 160}, - dictWord{7, 0, 492}, - dictWord{ - 4, - 10, - 413, - }, - dictWord{5, 10, 677}, - dictWord{7, 11, 492}, - dictWord{8, 10, 432}, - dictWord{140, 10, 280}, - dictWord{6, 0, 45}, - dictWord{7, 0, 433}, - dictWord{8, 0, 129}, - dictWord{9, 0, 21}, - dictWord{10, 0, 392}, - dictWord{11, 0, 79}, - dictWord{12, 0, 499}, - dictWord{13, 0, 199}, - dictWord{141, 0, 451}, - dictWord{7, 0, 558}, - dictWord{ - 136, - 0, - 353, - }, - dictWord{4, 11, 220}, - dictWord{7, 11, 1535}, - dictWord{9, 11, 93}, - dictWord{139, 11, 474}, - dictWord{7, 10, 646}, - dictWord{7, 10, 1730}, - dictWord{ - 11, - 10, - 446, - }, - dictWord{141, 10, 178}, - dictWord{133, 0, 785}, - dictWord{134, 0, 1145}, - dictWord{8, 0, 81}, - dictWord{9, 0, 189}, - dictWord{9, 0, 201}, - dictWord{ - 11, - 0, - 478, - }, - dictWord{11, 0, 712}, - dictWord{141, 0, 338}, - dictWord{5, 0, 353}, - dictWord{151, 0, 26}, - dictWord{11, 0, 762}, - dictWord{132, 10, 395}, - dictWord{ - 134, - 0, - 2024, - }, - dictWord{4, 0, 611}, - dictWord{133, 0, 606}, - dictWord{9, 10, 174}, - dictWord{10, 10, 164}, - dictWord{11, 10, 440}, - dictWord{11, 10, 841}, - dictWord{ - 143, - 10, - 98, - }, - dictWord{134, 10, 426}, - dictWord{10, 10, 608}, - dictWord{139, 10, 1002}, - dictWord{138, 10, 250}, - dictWord{6, 0, 25}, - dictWord{7, 0, 855}, - dictWord{7, 0, 1258}, - dictWord{144, 0, 32}, - dictWord{7, 11, 1725}, - dictWord{138, 11, 393}, - dictWord{5, 11, 263}, - dictWord{134, 11, 414}, - dictWord{6, 0, 2011}, - dictWord{133, 10, 476}, - dictWord{4, 0, 4}, - dictWord{7, 0, 1118}, - dictWord{7, 0, 1320}, - dictWord{7, 0, 1706}, - dictWord{8, 0, 277}, - dictWord{9, 0, 622}, - dictWord{ - 10, - 0, - 9, - }, - dictWord{11, 0, 724}, - dictWord{12, 0, 350}, - dictWord{12, 0, 397}, - dictWord{13, 0, 28}, - dictWord{13, 0, 159}, - dictWord{15, 0, 89}, - dictWord{18, 0, 5}, - dictWord{ - 19, - 0, - 9, - }, - dictWord{20, 0, 34}, - dictWord{22, 0, 47}, - dictWord{6, 11, 178}, - dictWord{6, 11, 1750}, - dictWord{8, 11, 251}, - dictWord{9, 11, 690}, - dictWord{ - 10, - 11, - 155, - }, - dictWord{10, 11, 196}, - dictWord{10, 11, 373}, - dictWord{11, 11, 698}, - dictWord{13, 11, 155}, - dictWord{148, 11, 93}, - dictWord{5, 11, 97}, - dictWord{ - 137, - 11, - 393, - }, - dictWord{7, 0, 764}, - dictWord{11, 0, 461}, - dictWord{12, 0, 172}, - dictWord{5, 10, 76}, - dictWord{6, 10, 458}, - dictWord{6, 10, 497}, - dictWord{ - 7, - 10, - 868, - }, - dictWord{9, 10, 658}, - dictWord{10, 10, 594}, - dictWord{11, 10, 566}, - dictWord{12, 10, 338}, - dictWord{141, 10, 200}, - dictWord{134, 0, 1449}, - dictWord{138, 11, 40}, - dictWord{134, 11, 1639}, - dictWord{134, 0, 1445}, - dictWord{6, 0, 1168}, - dictWord{4, 10, 526}, - dictWord{7, 10, 1029}, - dictWord{ - 135, - 10, - 1054, - }, - dictWord{4, 11, 191}, - dictWord{7, 11, 934}, - dictWord{8, 11, 647}, - dictWord{145, 11, 97}, - dictWord{132, 10, 636}, - dictWord{6, 0, 233}, - dictWord{ - 7, - 10, - 660, - }, - dictWord{7, 10, 1124}, - dictWord{17, 10, 31}, - dictWord{19, 10, 22}, - dictWord{151, 10, 14}, - dictWord{6, 10, 1699}, - dictWord{136, 11, 110}, - dictWord{ - 12, - 11, - 246, - }, - dictWord{15, 11, 162}, - dictWord{19, 11, 64}, - dictWord{20, 11, 8}, - dictWord{20, 11, 95}, - dictWord{22, 11, 24}, - dictWord{152, 11, 17}, - dictWord{ - 5, - 11, - 165, - }, - dictWord{9, 11, 346}, - dictWord{138, 11, 655}, - dictWord{5, 11, 319}, - dictWord{135, 11, 534}, - dictWord{134, 0, 255}, - dictWord{9, 0, 216}, - dictWord{ - 8, - 11, - 128, - }, - dictWord{139, 11, 179}, - dictWord{9, 0, 183}, - dictWord{139, 0, 286}, - dictWord{11, 0, 956}, - dictWord{151, 0, 3}, - dictWord{4, 0, 536}, - dictWord{ - 7, - 0, - 1141, - }, - dictWord{10, 0, 723}, - dictWord{139, 0, 371}, - dictWord{4, 10, 279}, - dictWord{7, 10, 301}, - dictWord{137, 10, 362}, - dictWord{7, 0, 285}, - dictWord{ - 5, - 11, - 57, - }, - dictWord{6, 11, 101}, - dictWord{6, 11, 1663}, - dictWord{7, 11, 132}, - dictWord{7, 11, 1048}, - dictWord{7, 11, 1154}, - dictWord{7, 11, 1415}, - dictWord{ - 7, - 11, - 1507, - }, - dictWord{12, 11, 493}, - dictWord{15, 11, 105}, - dictWord{151, 11, 15}, - dictWord{5, 11, 459}, - dictWord{7, 11, 1073}, - dictWord{7, 10, 1743}, - dictWord{ - 8, - 11, - 241, - }, - dictWord{136, 11, 334}, - dictWord{4, 10, 178}, - dictWord{133, 10, 399}, - dictWord{135, 0, 560}, - dictWord{132, 0, 690}, - dictWord{135, 0, 1246}, - dictWord{18, 0, 157}, - dictWord{147, 0, 63}, - dictWord{10, 0, 599}, - dictWord{11, 0, 33}, - dictWord{12, 0, 571}, - dictWord{149, 0, 1}, - dictWord{6, 11, 324}, - dictWord{ - 6, - 11, - 520, - }, - dictWord{7, 11, 338}, - dictWord{7, 11, 1616}, - dictWord{7, 11, 1729}, - dictWord{8, 11, 228}, - dictWord{9, 11, 69}, - dictWord{139, 11, 750}, - dictWord{ - 7, - 0, - 1862, - }, - dictWord{12, 0, 491}, - dictWord{12, 0, 520}, - dictWord{13, 0, 383}, - dictWord{142, 0, 244}, - dictWord{135, 11, 734}, - dictWord{134, 10, 1692}, - dictWord{10, 0, 448}, - dictWord{11, 0, 630}, - dictWord{17, 0, 117}, - dictWord{6, 10, 202}, - dictWord{7, 11, 705}, - dictWord{12, 10, 360}, - dictWord{17, 10, 118}, - dictWord{18, 10, 27}, - dictWord{148, 10, 67}, - dictWord{4, 11, 73}, - dictWord{6, 11, 612}, - dictWord{7, 11, 927}, - dictWord{7, 11, 1822}, - dictWord{8, 11, 217}, - dictWord{ - 9, - 11, - 472, - }, - dictWord{9, 11, 765}, - dictWord{9, 11, 766}, - dictWord{10, 11, 408}, - dictWord{11, 11, 51}, - dictWord{11, 11, 793}, - dictWord{12, 11, 266}, - dictWord{ - 15, - 11, - 158, - }, - dictWord{20, 11, 89}, - dictWord{150, 11, 32}, - dictWord{4, 0, 190}, - dictWord{133, 0, 554}, - dictWord{133, 0, 1001}, - dictWord{5, 11, 389}, - dictWord{ - 8, - 11, - 636, - }, - dictWord{137, 11, 229}, - dictWord{5, 0, 446}, - dictWord{7, 10, 872}, - dictWord{10, 10, 516}, - dictWord{139, 10, 167}, - dictWord{137, 10, 313}, - dictWord{132, 10, 224}, - dictWord{134, 0, 1313}, - dictWord{5, 10, 546}, - dictWord{7, 10, 35}, - dictWord{8, 10, 11}, - dictWord{8, 10, 12}, - dictWord{9, 10, 315}, - dictWord{9, 10, 533}, - dictWord{10, 10, 802}, - dictWord{11, 10, 166}, - dictWord{12, 10, 525}, - dictWord{142, 10, 243}, - dictWord{6, 0, 636}, - dictWord{137, 0, 837}, - dictWord{5, 10, 241}, - dictWord{8, 10, 242}, - dictWord{9, 10, 451}, - dictWord{10, 10, 667}, - dictWord{11, 10, 598}, - dictWord{140, 10, 429}, - dictWord{22, 10, 46}, - dictWord{150, 11, 46}, - dictWord{136, 11, 472}, - dictWord{11, 0, 278}, - dictWord{142, 0, 73}, - dictWord{141, 11, 185}, - dictWord{132, 0, 868}, - dictWord{ - 134, - 0, - 972, - }, - dictWord{4, 10, 366}, - dictWord{137, 10, 516}, - dictWord{138, 0, 1010}, - dictWord{5, 11, 189}, - dictWord{6, 10, 1736}, - dictWord{7, 11, 442}, - dictWord{ - 7, - 11, - 443, - }, - dictWord{8, 11, 281}, - dictWord{12, 11, 174}, - dictWord{13, 11, 83}, - dictWord{141, 11, 261}, - dictWord{139, 11, 384}, - dictWord{6, 11, 2}, - dictWord{ - 7, - 11, - 191, - }, - dictWord{7, 11, 446}, - dictWord{7, 11, 758}, - dictWord{7, 11, 1262}, - dictWord{7, 11, 1737}, - dictWord{8, 11, 22}, - dictWord{8, 11, 270}, - dictWord{ - 8, - 11, - 612, - }, - dictWord{9, 11, 4}, - dictWord{9, 11, 167}, - dictWord{9, 11, 312}, - dictWord{9, 11, 436}, - dictWord{10, 11, 156}, - dictWord{10, 11, 216}, - dictWord{ - 10, - 11, - 311, - }, - dictWord{10, 11, 623}, - dictWord{11, 11, 72}, - dictWord{11, 11, 330}, - dictWord{11, 11, 455}, - dictWord{12, 11, 101}, - dictWord{12, 11, 321}, - dictWord{ - 12, - 11, - 504, - }, - dictWord{12, 11, 530}, - dictWord{12, 11, 543}, - dictWord{13, 11, 17}, - dictWord{13, 11, 156}, - dictWord{13, 11, 334}, - dictWord{14, 11, 48}, - dictWord{15, 11, 70}, - dictWord{17, 11, 60}, - dictWord{148, 11, 64}, - dictWord{6, 10, 331}, - dictWord{136, 10, 623}, - dictWord{135, 0, 1231}, - dictWord{132, 0, 304}, - dictWord{6, 11, 60}, - dictWord{7, 11, 670}, - dictWord{7, 11, 1327}, - dictWord{8, 11, 411}, - dictWord{8, 11, 435}, - dictWord{9, 11, 653}, - dictWord{9, 11, 740}, - dictWord{10, 11, 385}, - dictWord{11, 11, 222}, - dictWord{11, 11, 324}, - dictWord{11, 11, 829}, - dictWord{140, 11, 611}, - dictWord{7, 0, 506}, - dictWord{6, 11, 166}, - dictWord{7, 11, 374}, - dictWord{135, 11, 1174}, - dictWord{14, 11, 43}, - dictWord{146, 11, 21}, - dictWord{135, 11, 1694}, - dictWord{135, 10, 1888}, - dictWord{ - 5, - 11, - 206, - }, - dictWord{134, 11, 398}, - dictWord{135, 11, 50}, - dictWord{150, 0, 26}, - dictWord{6, 0, 53}, - dictWord{6, 0, 199}, - dictWord{7, 0, 1408}, - dictWord{ - 8, - 0, - 32, - }, - dictWord{8, 0, 93}, - dictWord{10, 0, 397}, - dictWord{10, 0, 629}, - dictWord{11, 0, 593}, - dictWord{11, 0, 763}, - dictWord{13, 0, 326}, - dictWord{145, 0, 35}, - dictWord{134, 0, 105}, - dictWord{132, 10, 394}, - dictWord{4, 0, 843}, - dictWord{138, 0, 794}, - dictWord{11, 0, 704}, - dictWord{141, 0, 396}, - dictWord{5, 0, 114}, - dictWord{5, 0, 255}, - dictWord{141, 0, 285}, - dictWord{6, 0, 619}, - dictWord{7, 0, 898}, - dictWord{7, 0, 1092}, - dictWord{8, 0, 485}, - dictWord{18, 0, 28}, - dictWord{ - 19, - 0, - 116, - }, - dictWord{135, 10, 1931}, - dictWord{9, 0, 145}, - dictWord{7, 10, 574}, - dictWord{135, 10, 1719}, - dictWord{7, 0, 2035}, - dictWord{8, 0, 19}, - dictWord{ - 9, - 0, - 89, - }, - dictWord{138, 0, 831}, - dictWord{132, 10, 658}, - dictWord{6, 11, 517}, - dictWord{7, 11, 1159}, - dictWord{10, 11, 621}, - dictWord{139, 11, 192}, - dictWord{ - 7, - 0, - 1933, - }, - dictWord{7, 11, 1933}, - dictWord{9, 10, 781}, - dictWord{10, 10, 144}, - dictWord{11, 10, 385}, - dictWord{13, 10, 161}, - dictWord{13, 10, 228}, - dictWord{13, 10, 268}, - dictWord{148, 10, 107}, - dictWord{136, 10, 374}, - dictWord{10, 11, 223}, - dictWord{139, 11, 645}, - dictWord{135, 0, 1728}, - dictWord{ - 7, - 11, - 64, - }, - dictWord{7, 11, 289}, - dictWord{136, 11, 245}, - dictWord{4, 10, 344}, - dictWord{6, 10, 498}, - dictWord{139, 10, 323}, - dictWord{136, 0, 746}, - dictWord{ - 135, - 10, - 1063, - }, - dictWord{137, 10, 155}, - dictWord{4, 0, 987}, - dictWord{6, 0, 1964}, - dictWord{6, 0, 1974}, - dictWord{6, 0, 1990}, - dictWord{136, 0, 995}, - dictWord{133, 11, 609}, - dictWord{133, 10, 906}, - dictWord{134, 0, 1550}, - dictWord{134, 0, 874}, - dictWord{5, 11, 129}, - dictWord{6, 11, 61}, - dictWord{ - 135, - 11, - 947, - }, - dictWord{4, 0, 1018}, - dictWord{6, 0, 1938}, - dictWord{6, 0, 2021}, - dictWord{134, 0, 2039}, - dictWord{132, 0, 814}, - dictWord{11, 0, 126}, - dictWord{ - 139, - 0, - 287, - }, - dictWord{134, 0, 1264}, - dictWord{5, 0, 955}, - dictWord{136, 0, 814}, - dictWord{141, 11, 506}, - dictWord{132, 11, 314}, - dictWord{6, 0, 981}, - dictWord{139, 11, 1000}, - dictWord{5, 0, 56}, - dictWord{8, 0, 892}, - dictWord{8, 0, 915}, - dictWord{140, 0, 776}, - dictWord{148, 0, 100}, - dictWord{10, 0, 4}, - dictWord{ - 10, - 0, - 13, - }, - dictWord{11, 0, 638}, - dictWord{148, 0, 57}, - dictWord{148, 11, 74}, - dictWord{5, 0, 738}, - dictWord{132, 10, 616}, - dictWord{133, 11, 637}, - dictWord{ - 136, - 10, - 692, - }, - dictWord{133, 0, 758}, - dictWord{132, 10, 305}, - dictWord{137, 11, 590}, - dictWord{5, 11, 280}, - dictWord{135, 11, 1226}, - dictWord{ - 134, - 11, - 494, - }, - dictWord{135, 0, 1112}, - dictWord{133, 11, 281}, - dictWord{13, 0, 44}, - dictWord{14, 0, 214}, - dictWord{5, 10, 214}, - dictWord{7, 10, 603}, - dictWord{ - 8, - 10, - 611, - }, - dictWord{9, 10, 686}, - dictWord{10, 10, 88}, - dictWord{11, 10, 459}, - dictWord{11, 10, 496}, - dictWord{12, 10, 463}, - dictWord{140, 10, 590}, - dictWord{ - 139, - 0, - 328, - }, - dictWord{135, 11, 1064}, - dictWord{137, 0, 133}, - dictWord{7, 0, 168}, - dictWord{13, 0, 196}, - dictWord{141, 0, 237}, - dictWord{134, 10, 1703}, - dictWord{134, 0, 1152}, - dictWord{135, 0, 1245}, - dictWord{5, 0, 110}, - dictWord{6, 0, 169}, - dictWord{6, 0, 1702}, - dictWord{7, 0, 400}, - dictWord{8, 0, 538}, - dictWord{ - 9, - 0, - 184, - }, - dictWord{9, 0, 524}, - dictWord{140, 0, 218}, - dictWord{6, 0, 1816}, - dictWord{10, 0, 871}, - dictWord{12, 0, 769}, - dictWord{140, 0, 785}, - dictWord{ - 132, - 11, - 630, - }, - dictWord{7, 11, 33}, - dictWord{7, 11, 120}, - dictWord{8, 11, 489}, - dictWord{9, 11, 319}, - dictWord{10, 11, 820}, - dictWord{11, 11, 1004}, - dictWord{ - 12, - 11, - 379, - }, - dictWord{13, 11, 117}, - dictWord{13, 11, 412}, - dictWord{14, 11, 25}, - dictWord{15, 11, 52}, - dictWord{15, 11, 161}, - dictWord{16, 11, 47}, - dictWord{149, 11, 2}, - dictWord{6, 0, 133}, - dictWord{8, 0, 413}, - dictWord{9, 0, 353}, - dictWord{139, 0, 993}, - dictWord{145, 10, 19}, - dictWord{4, 11, 937}, - dictWord{ - 133, - 11, - 801, - }, - dictWord{134, 0, 978}, - dictWord{6, 0, 93}, - dictWord{6, 0, 1508}, - dictWord{7, 0, 1422}, - dictWord{7, 0, 1851}, - dictWord{8, 0, 673}, - dictWord{9, 0, 529}, - dictWord{140, 0, 43}, - dictWord{6, 0, 317}, - dictWord{10, 0, 512}, - dictWord{4, 10, 737}, - dictWord{11, 10, 294}, - dictWord{12, 10, 60}, - dictWord{12, 10, 437}, - dictWord{13, 10, 64}, - dictWord{13, 10, 380}, - dictWord{142, 10, 430}, - dictWord{9, 0, 371}, - dictWord{7, 11, 1591}, - dictWord{144, 11, 43}, - dictWord{6, 10, 1758}, - dictWord{8, 10, 520}, - dictWord{9, 10, 345}, - dictWord{9, 10, 403}, - dictWord{142, 10, 350}, - dictWord{5, 0, 526}, - dictWord{10, 10, 242}, - dictWord{ - 138, - 10, - 579, - }, - dictWord{9, 0, 25}, - dictWord{10, 0, 467}, - dictWord{138, 0, 559}, - dictWord{5, 10, 139}, - dictWord{7, 10, 1168}, - dictWord{138, 10, 539}, - dictWord{ - 4, - 0, - 335, - }, - dictWord{135, 0, 942}, - dictWord{140, 0, 754}, - dictWord{132, 11, 365}, - dictWord{11, 0, 182}, - dictWord{142, 0, 195}, - dictWord{142, 11, 29}, - dictWord{ - 5, - 11, - 7, - }, - dictWord{139, 11, 774}, - dictWord{4, 11, 746}, - dictWord{135, 11, 1090}, - dictWord{8, 0, 39}, - dictWord{10, 0, 773}, - dictWord{11, 0, 84}, - dictWord{ - 12, - 0, - 205, - }, - dictWord{142, 0, 1}, - dictWord{5, 0, 601}, - dictWord{5, 0, 870}, - dictWord{5, 11, 360}, - dictWord{136, 11, 237}, - dictWord{132, 0, 181}, - dictWord{ - 136, - 0, - 370, - }, - dictWord{134, 0, 1652}, - dictWord{8, 0, 358}, - dictWord{4, 10, 107}, - dictWord{7, 10, 613}, - dictWord{8, 10, 439}, - dictWord{8, 10, 504}, - dictWord{ - 9, - 10, - 501, - }, - dictWord{10, 10, 383}, - dictWord{139, 10, 477}, - dictWord{132, 10, 229}, - dictWord{137, 11, 785}, - dictWord{4, 0, 97}, - dictWord{5, 0, 147}, - dictWord{ - 6, - 0, - 286, - }, - dictWord{7, 0, 1362}, - dictWord{141, 0, 176}, - dictWord{6, 0, 537}, - dictWord{7, 0, 788}, - dictWord{7, 0, 1816}, - dictWord{132, 10, 903}, - dictWord{ - 140, - 10, - 71, - }, - dictWord{6, 0, 743}, - dictWord{134, 0, 1223}, - dictWord{6, 0, 375}, - dictWord{7, 0, 169}, - dictWord{7, 0, 254}, - dictWord{8, 0, 780}, - dictWord{135, 11, 1493}, - dictWord{7, 0, 1714}, - dictWord{4, 10, 47}, - dictWord{6, 10, 373}, - dictWord{7, 10, 452}, - dictWord{7, 10, 543}, - dictWord{7, 10, 1856}, - dictWord{9, 10, 6}, - dictWord{ - 11, - 10, - 257, - }, - dictWord{139, 10, 391}, - dictWord{6, 0, 896}, - dictWord{136, 0, 1003}, - dictWord{135, 0, 1447}, - dictWord{137, 11, 341}, - dictWord{5, 10, 980}, - dictWord{134, 10, 1754}, - dictWord{145, 11, 22}, - dictWord{4, 11, 277}, - dictWord{5, 11, 608}, - dictWord{6, 11, 493}, - dictWord{7, 11, 457}, - dictWord{ - 140, - 11, - 384, - }, - dictWord{7, 10, 536}, - dictWord{7, 10, 1331}, - dictWord{136, 10, 143}, - dictWord{140, 0, 744}, - dictWord{7, 11, 27}, - dictWord{135, 11, 316}, - dictWord{ - 18, - 0, - 126, - }, - dictWord{5, 10, 19}, - dictWord{134, 10, 533}, - dictWord{4, 0, 788}, - dictWord{11, 0, 41}, - dictWord{5, 11, 552}, - dictWord{5, 11, 586}, - dictWord{ - 5, - 11, - 676, - }, - dictWord{6, 11, 448}, - dictWord{8, 11, 244}, - dictWord{11, 11, 1}, - dictWord{11, 11, 41}, - dictWord{13, 11, 3}, - dictWord{16, 11, 54}, - dictWord{17, 11, 4}, - dictWord{146, 11, 13}, - dictWord{4, 0, 985}, - dictWord{6, 0, 1801}, - dictWord{4, 11, 401}, - dictWord{137, 11, 264}, - dictWord{5, 10, 395}, - dictWord{5, 10, 951}, - dictWord{134, 10, 1776}, - dictWord{5, 0, 629}, - dictWord{135, 0, 1549}, - dictWord{11, 10, 663}, - dictWord{12, 10, 210}, - dictWord{13, 10, 166}, - dictWord{ - 13, - 10, - 310, - }, - dictWord{14, 10, 373}, - dictWord{147, 10, 43}, - dictWord{9, 11, 543}, - dictWord{10, 11, 524}, - dictWord{11, 11, 30}, - dictWord{12, 11, 524}, - dictWord{ - 14, - 11, - 315, - }, - dictWord{16, 11, 18}, - dictWord{20, 11, 26}, - dictWord{148, 11, 65}, - dictWord{4, 11, 205}, - dictWord{5, 11, 623}, - dictWord{7, 11, 104}, - dictWord{ - 136, - 11, - 519, - }, - dictWord{5, 0, 293}, - dictWord{134, 0, 601}, - dictWord{7, 11, 579}, - dictWord{9, 11, 41}, - dictWord{9, 11, 244}, - dictWord{9, 11, 669}, - dictWord{ - 10, - 11, - 5, - }, - dictWord{11, 11, 861}, - dictWord{11, 11, 951}, - dictWord{139, 11, 980}, - dictWord{132, 11, 717}, - dictWord{132, 10, 695}, - dictWord{7, 10, 497}, - dictWord{ - 9, - 10, - 387, - }, - dictWord{147, 10, 81}, - dictWord{132, 0, 420}, - dictWord{142, 0, 37}, - dictWord{6, 0, 1134}, - dictWord{6, 0, 1900}, - dictWord{12, 0, 830}, - dictWord{ - 12, - 0, - 878, - }, - dictWord{12, 0, 894}, - dictWord{15, 0, 221}, - dictWord{143, 0, 245}, - dictWord{132, 11, 489}, - dictWord{7, 0, 1570}, - dictWord{140, 0, 542}, - dictWord{ - 8, - 0, - 933, - }, - dictWord{136, 0, 957}, - dictWord{6, 0, 1371}, - dictWord{7, 0, 31}, - dictWord{8, 0, 373}, - dictWord{5, 10, 284}, - dictWord{6, 10, 49}, - dictWord{6, 10, 350}, - dictWord{7, 10, 377}, - dictWord{7, 10, 1693}, - dictWord{8, 10, 678}, - dictWord{9, 10, 161}, - dictWord{9, 10, 585}, - dictWord{9, 10, 671}, - dictWord{9, 10, 839}, - dictWord{11, 10, 912}, - dictWord{141, 10, 427}, - dictWord{135, 11, 892}, - dictWord{4, 0, 325}, - dictWord{138, 0, 125}, - dictWord{139, 11, 47}, - dictWord{ - 132, - 10, - 597, - }, - dictWord{138, 0, 323}, - dictWord{6, 0, 1547}, - dictWord{7, 11, 1605}, - dictWord{9, 11, 473}, - dictWord{11, 11, 962}, - dictWord{146, 11, 139}, - dictWord{ - 139, - 10, - 908, - }, - dictWord{7, 11, 819}, - dictWord{9, 11, 26}, - dictWord{9, 11, 392}, - dictWord{10, 11, 152}, - dictWord{10, 11, 226}, - dictWord{11, 11, 19}, - dictWord{ - 12, - 11, - 276, - }, - dictWord{12, 11, 426}, - dictWord{12, 11, 589}, - dictWord{13, 11, 460}, - dictWord{15, 11, 97}, - dictWord{19, 11, 48}, - dictWord{148, 11, 104}, - dictWord{135, 11, 51}, - dictWord{4, 0, 718}, - dictWord{135, 0, 1216}, - dictWord{6, 0, 1896}, - dictWord{6, 0, 1905}, - dictWord{6, 0, 1912}, - dictWord{9, 0, 947}, - dictWord{ - 9, - 0, - 974, - }, - dictWord{12, 0, 809}, - dictWord{12, 0, 850}, - dictWord{12, 0, 858}, - dictWord{12, 0, 874}, - dictWord{12, 0, 887}, - dictWord{12, 0, 904}, - dictWord{ - 12, - 0, - 929, - }, - dictWord{12, 0, 948}, - dictWord{12, 0, 952}, - dictWord{15, 0, 198}, - dictWord{15, 0, 206}, - dictWord{15, 0, 220}, - dictWord{15, 0, 227}, - dictWord{15, 0, 247}, - dictWord{18, 0, 188}, - dictWord{21, 0, 48}, - dictWord{21, 0, 50}, - dictWord{24, 0, 25}, - dictWord{24, 0, 29}, - dictWord{7, 11, 761}, - dictWord{7, 11, 1051}, - dictWord{ - 137, - 11, - 545, - }, - dictWord{5, 0, 124}, - dictWord{5, 0, 144}, - dictWord{6, 0, 548}, - dictWord{7, 0, 15}, - dictWord{7, 0, 153}, - dictWord{137, 0, 629}, - dictWord{ - 135, - 11, - 606, - }, - dictWord{135, 10, 2014}, - dictWord{7, 10, 2007}, - dictWord{9, 11, 46}, - dictWord{9, 10, 101}, - dictWord{9, 10, 450}, - dictWord{10, 10, 66}, - dictWord{ - 10, - 10, - 842, - }, - dictWord{11, 10, 536}, - dictWord{140, 10, 587}, - dictWord{6, 0, 75}, - dictWord{7, 0, 1531}, - dictWord{8, 0, 416}, - dictWord{9, 0, 240}, - dictWord{9, 0, 275}, - dictWord{10, 0, 100}, - dictWord{11, 0, 658}, - dictWord{11, 0, 979}, - dictWord{12, 0, 86}, - dictWord{14, 0, 207}, - dictWord{15, 0, 20}, - dictWord{143, 0, 25}, - dictWord{ - 5, - 0, - 141, - }, - dictWord{5, 0, 915}, - dictWord{6, 0, 1783}, - dictWord{7, 0, 211}, - dictWord{7, 0, 698}, - dictWord{7, 0, 1353}, - dictWord{9, 0, 83}, - dictWord{9, 0, 281}, - dictWord{ - 10, - 0, - 376, - }, - dictWord{10, 0, 431}, - dictWord{11, 0, 543}, - dictWord{12, 0, 664}, - dictWord{13, 0, 280}, - dictWord{13, 0, 428}, - dictWord{14, 0, 61}, - dictWord{ - 14, - 0, - 128, - }, - dictWord{17, 0, 52}, - dictWord{145, 0, 81}, - dictWord{132, 11, 674}, - dictWord{135, 0, 533}, - dictWord{149, 0, 6}, - dictWord{132, 11, 770}, - dictWord{ - 133, - 0, - 538, - }, - dictWord{5, 11, 79}, - dictWord{7, 11, 1027}, - dictWord{7, 11, 1477}, - dictWord{139, 11, 52}, - dictWord{139, 10, 62}, - dictWord{4, 0, 338}, - dictWord{ - 133, - 0, - 400, - }, - dictWord{5, 11, 789}, - dictWord{134, 11, 195}, - dictWord{4, 11, 251}, - dictWord{4, 11, 688}, - dictWord{7, 11, 513}, - dictWord{7, 11, 1284}, - dictWord{ - 9, - 11, - 87, - }, - dictWord{138, 11, 365}, - dictWord{134, 10, 1766}, - dictWord{6, 0, 0}, - dictWord{7, 0, 84}, - dictWord{11, 0, 895}, - dictWord{145, 0, 11}, - dictWord{ - 139, - 0, - 892, - }, - dictWord{4, 0, 221}, - dictWord{5, 0, 659}, - dictWord{7, 0, 697}, - dictWord{7, 0, 1211}, - dictWord{138, 0, 284}, - dictWord{133, 0, 989}, - dictWord{ - 133, - 11, - 889, - }, - dictWord{4, 11, 160}, - dictWord{5, 11, 330}, - dictWord{7, 11, 1434}, - dictWord{136, 11, 174}, - dictWord{6, 10, 1665}, - dictWord{7, 10, 256}, - dictWord{ - 7, - 10, - 1388, - }, - dictWord{10, 10, 499}, - dictWord{139, 10, 670}, - dictWord{7, 0, 848}, - dictWord{4, 10, 22}, - dictWord{5, 10, 10}, - dictWord{136, 10, 97}, - dictWord{ - 138, - 0, - 507, - }, - dictWord{133, 10, 481}, - dictWord{4, 0, 188}, - dictWord{135, 0, 805}, - dictWord{5, 0, 884}, - dictWord{6, 0, 732}, - dictWord{139, 0, 991}, - dictWord{ - 135, - 11, - 968, - }, - dictWord{11, 11, 636}, - dictWord{15, 11, 145}, - dictWord{17, 11, 34}, - dictWord{19, 11, 50}, - dictWord{151, 11, 20}, - dictWord{7, 0, 959}, - dictWord{ - 16, - 0, - 60, - }, - dictWord{6, 10, 134}, - dictWord{7, 10, 437}, - dictWord{9, 10, 37}, - dictWord{14, 10, 285}, - dictWord{142, 10, 371}, - dictWord{7, 10, 486}, - dictWord{ - 8, - 10, - 155, - }, - dictWord{11, 10, 93}, - dictWord{140, 10, 164}, - dictWord{134, 0, 1653}, - dictWord{7, 0, 337}, - dictWord{133, 10, 591}, - dictWord{6, 0, 1989}, - dictWord{ - 8, - 0, - 922, - }, - dictWord{8, 0, 978}, - dictWord{133, 11, 374}, - dictWord{132, 0, 638}, - dictWord{138, 0, 500}, - dictWord{133, 11, 731}, - dictWord{5, 10, 380}, - dictWord{ - 5, - 10, - 650, - }, - dictWord{136, 10, 310}, - dictWord{138, 11, 381}, - dictWord{4, 10, 364}, - dictWord{7, 10, 1156}, - dictWord{7, 10, 1187}, - dictWord{137, 10, 409}, - dictWord{137, 11, 224}, - dictWord{140, 0, 166}, - dictWord{134, 10, 482}, - dictWord{4, 11, 626}, - dictWord{5, 11, 642}, - dictWord{6, 11, 425}, - dictWord{ - 10, - 11, - 202, - }, - dictWord{139, 11, 141}, - dictWord{4, 10, 781}, - dictWord{6, 10, 487}, - dictWord{7, 10, 926}, - dictWord{8, 10, 263}, - dictWord{139, 10, 500}, - dictWord{ - 135, - 0, - 418, - }, - dictWord{4, 10, 94}, - dictWord{135, 10, 1265}, - dictWord{136, 0, 760}, - dictWord{132, 10, 417}, - dictWord{136, 11, 835}, - dictWord{5, 10, 348}, - dictWord{134, 10, 522}, - dictWord{6, 0, 1277}, - dictWord{134, 0, 1538}, - dictWord{139, 11, 541}, - dictWord{135, 11, 1597}, - dictWord{5, 11, 384}, - dictWord{ - 8, - 11, - 455, - }, - dictWord{140, 11, 48}, - dictWord{136, 0, 770}, - dictWord{5, 11, 264}, - dictWord{134, 11, 184}, - dictWord{4, 0, 89}, - dictWord{5, 0, 489}, - dictWord{ - 6, - 0, - 315, - }, - dictWord{7, 0, 553}, - dictWord{7, 0, 1745}, - dictWord{138, 0, 243}, - dictWord{4, 10, 408}, - dictWord{4, 10, 741}, - dictWord{135, 10, 500}, - dictWord{ - 134, - 0, - 1396, - }, - dictWord{133, 0, 560}, - dictWord{6, 0, 1658}, - dictWord{9, 0, 3}, - dictWord{10, 0, 154}, - dictWord{11, 0, 641}, - dictWord{13, 0, 85}, - dictWord{13, 0, 201}, - dictWord{141, 0, 346}, - dictWord{135, 11, 1595}, - dictWord{5, 11, 633}, - dictWord{6, 11, 28}, - dictWord{7, 11, 219}, - dictWord{135, 11, 1323}, - dictWord{ - 9, - 11, - 769, - }, - dictWord{140, 11, 185}, - dictWord{135, 11, 785}, - dictWord{7, 11, 359}, - dictWord{8, 11, 243}, - dictWord{140, 11, 175}, - dictWord{138, 0, 586}, - dictWord{ - 7, - 0, - 1271, - }, - dictWord{134, 10, 73}, - dictWord{132, 11, 105}, - dictWord{4, 0, 166}, - dictWord{5, 0, 505}, - dictWord{134, 0, 1670}, - dictWord{133, 10, 576}, - dictWord{4, 11, 324}, - dictWord{138, 11, 104}, - dictWord{142, 10, 231}, - dictWord{6, 0, 637}, - dictWord{7, 10, 1264}, - dictWord{7, 10, 1678}, - dictWord{ - 11, - 10, - 945, - }, - dictWord{12, 10, 341}, - dictWord{12, 10, 471}, - dictWord{12, 10, 569}, - dictWord{23, 11, 21}, - dictWord{151, 11, 23}, - dictWord{8, 11, 559}, - dictWord{ - 141, - 11, - 109, - }, - dictWord{134, 0, 1947}, - dictWord{7, 0, 445}, - dictWord{8, 0, 307}, - dictWord{8, 0, 704}, - dictWord{10, 0, 41}, - dictWord{10, 0, 439}, - dictWord{ - 11, - 0, - 237, - }, - dictWord{11, 0, 622}, - dictWord{140, 0, 201}, - dictWord{135, 11, 963}, - dictWord{135, 0, 1977}, - dictWord{4, 0, 189}, - dictWord{5, 0, 713}, - dictWord{ - 136, - 0, - 57, - }, - dictWord{138, 0, 371}, - dictWord{135, 10, 538}, - dictWord{132, 0, 552}, - dictWord{6, 0, 883}, - dictWord{133, 10, 413}, - dictWord{6, 0, 923}, - dictWord{ - 132, - 11, - 758, - }, - dictWord{138, 11, 215}, - dictWord{136, 10, 495}, - dictWord{7, 10, 54}, - dictWord{8, 10, 312}, - dictWord{10, 10, 191}, - dictWord{10, 10, 614}, - dictWord{140, 10, 567}, - dictWord{7, 11, 351}, - dictWord{139, 11, 128}, - dictWord{7, 0, 875}, - dictWord{6, 10, 468}, - dictWord{7, 10, 1478}, - dictWord{8, 10, 530}, - dictWord{142, 10, 290}, - dictWord{135, 0, 1788}, - dictWord{17, 0, 49}, - dictWord{133, 11, 918}, - dictWord{12, 11, 398}, - dictWord{20, 11, 39}, - dictWord{ - 21, - 11, - 11, - }, - dictWord{150, 11, 41}, - dictWord{10, 0, 661}, - dictWord{6, 10, 484}, - dictWord{135, 10, 822}, - dictWord{135, 0, 1945}, - dictWord{134, 0, 794}, - dictWord{ - 137, - 10, - 900, - }, - dictWord{135, 10, 1335}, - dictWord{6, 10, 1724}, - dictWord{135, 10, 2022}, - dictWord{132, 11, 340}, - dictWord{134, 0, 1135}, - dictWord{ - 4, - 0, - 784, - }, - dictWord{133, 0, 745}, - dictWord{5, 0, 84}, - dictWord{134, 0, 163}, - dictWord{133, 0, 410}, - dictWord{4, 0, 976}, - dictWord{5, 11, 985}, - dictWord{7, 11, 509}, - dictWord{7, 11, 529}, - dictWord{145, 11, 96}, - dictWord{132, 10, 474}, - dictWord{134, 0, 703}, - dictWord{135, 11, 1919}, - dictWord{5, 0, 322}, - dictWord{ - 8, - 0, - 186, - }, - dictWord{9, 0, 262}, - dictWord{10, 0, 187}, - dictWord{142, 0, 208}, - dictWord{135, 10, 1504}, - dictWord{133, 0, 227}, - dictWord{9, 0, 560}, - dictWord{ - 13, - 0, - 208, - }, - dictWord{133, 10, 305}, - dictWord{132, 11, 247}, - dictWord{7, 0, 1395}, - dictWord{8, 0, 486}, - dictWord{9, 0, 236}, - dictWord{9, 0, 878}, - dictWord{ - 10, - 0, - 218, - }, - dictWord{11, 0, 95}, - dictWord{19, 0, 17}, - dictWord{147, 0, 31}, - dictWord{7, 0, 2043}, - dictWord{8, 0, 672}, - dictWord{141, 0, 448}, - dictWord{4, 11, 184}, - dictWord{5, 11, 390}, - dictWord{6, 11, 337}, - dictWord{7, 11, 23}, - dictWord{7, 11, 494}, - dictWord{7, 11, 618}, - dictWord{7, 11, 1456}, - dictWord{8, 11, 27}, - dictWord{ - 8, - 11, - 599, - }, - dictWord{10, 11, 153}, - dictWord{139, 11, 710}, - dictWord{135, 0, 466}, - dictWord{135, 10, 1236}, - dictWord{6, 0, 167}, - dictWord{7, 0, 186}, - dictWord{7, 0, 656}, - dictWord{10, 0, 643}, - dictWord{4, 10, 480}, - dictWord{6, 10, 302}, - dictWord{6, 10, 1642}, - dictWord{7, 10, 837}, - dictWord{7, 10, 1547}, - dictWord{ - 7, - 10, - 1657, - }, - dictWord{8, 10, 429}, - dictWord{9, 10, 228}, - dictWord{13, 10, 289}, - dictWord{13, 10, 343}, - dictWord{147, 10, 101}, - dictWord{134, 0, 1428}, - dictWord{134, 0, 1440}, - dictWord{5, 0, 412}, - dictWord{7, 10, 278}, - dictWord{10, 10, 739}, - dictWord{11, 10, 708}, - dictWord{141, 10, 348}, - dictWord{ - 134, - 0, - 1118, - }, - dictWord{136, 0, 562}, - dictWord{148, 11, 46}, - dictWord{9, 0, 316}, - dictWord{139, 0, 256}, - dictWord{134, 0, 1771}, - dictWord{135, 0, 1190}, - dictWord{137, 0, 132}, - dictWord{10, 11, 227}, - dictWord{11, 11, 497}, - dictWord{11, 11, 709}, - dictWord{140, 11, 415}, - dictWord{143, 0, 66}, - dictWord{6, 11, 360}, - dictWord{7, 11, 1664}, - dictWord{136, 11, 478}, - dictWord{144, 10, 28}, - dictWord{4, 0, 317}, - dictWord{135, 0, 1279}, - dictWord{5, 0, 63}, - dictWord{ - 133, - 0, - 509, - }, - dictWord{136, 11, 699}, - dictWord{145, 10, 36}, - dictWord{134, 0, 1475}, - dictWord{11, 11, 343}, - dictWord{142, 11, 127}, - dictWord{132, 11, 739}, - dictWord{132, 0, 288}, - dictWord{135, 11, 1757}, - dictWord{8, 0, 89}, - dictWord{8, 0, 620}, - dictWord{9, 0, 608}, - dictWord{11, 0, 628}, - dictWord{12, 0, 322}, - dictWord{143, 0, 124}, - dictWord{134, 0, 1225}, - dictWord{7, 0, 1189}, - dictWord{4, 11, 67}, - dictWord{5, 11, 422}, - dictWord{6, 10, 363}, - dictWord{7, 11, 1037}, - dictWord{7, 11, 1289}, - dictWord{7, 11, 1555}, - dictWord{7, 10, 1955}, - dictWord{8, 10, 725}, - dictWord{9, 11, 741}, - dictWord{145, 11, 108}, - dictWord{ - 134, - 0, - 1468, - }, - dictWord{6, 0, 689}, - dictWord{134, 0, 1451}, - dictWord{138, 0, 120}, - dictWord{151, 0, 1}, - dictWord{137, 10, 805}, - dictWord{142, 0, 329}, - dictWord{ - 5, - 10, - 813, - }, - dictWord{135, 10, 2046}, - dictWord{135, 0, 226}, - dictWord{138, 11, 96}, - dictWord{7, 0, 1855}, - dictWord{5, 10, 712}, - dictWord{11, 10, 17}, - dictWord{13, 10, 321}, - dictWord{144, 10, 67}, - dictWord{9, 0, 461}, - dictWord{6, 10, 320}, - dictWord{7, 10, 781}, - dictWord{7, 10, 1921}, - dictWord{9, 10, 55}, - dictWord{ - 10, - 10, - 186, - }, - dictWord{10, 10, 273}, - dictWord{10, 10, 664}, - dictWord{10, 10, 801}, - dictWord{11, 10, 996}, - dictWord{11, 10, 997}, - dictWord{13, 10, 157}, - dictWord{142, 10, 170}, - dictWord{8, 11, 203}, - dictWord{8, 10, 271}, - dictWord{11, 11, 823}, - dictWord{11, 11, 846}, - dictWord{12, 11, 482}, - dictWord{ - 13, - 11, - 133, - }, - dictWord{13, 11, 277}, - dictWord{13, 11, 302}, - dictWord{13, 11, 464}, - dictWord{14, 11, 205}, - dictWord{142, 11, 221}, - dictWord{135, 0, 1346}, - dictWord{4, 11, 449}, - dictWord{133, 11, 718}, - dictWord{134, 0, 85}, - dictWord{14, 0, 299}, - dictWord{7, 10, 103}, - dictWord{7, 10, 863}, - dictWord{11, 10, 184}, - dictWord{145, 10, 62}, - dictWord{4, 11, 355}, - dictWord{6, 11, 311}, - dictWord{9, 11, 256}, - dictWord{138, 11, 404}, - dictWord{137, 10, 659}, - dictWord{ - 138, - 11, - 758, - }, - dictWord{133, 11, 827}, - dictWord{5, 11, 64}, - dictWord{140, 11, 581}, - dictWord{134, 0, 1171}, - dictWord{4, 11, 442}, - dictWord{7, 11, 1047}, - dictWord{ - 7, - 11, - 1352, - }, - dictWord{135, 11, 1643}, - dictWord{132, 0, 980}, - dictWord{5, 11, 977}, - dictWord{6, 11, 288}, - dictWord{7, 11, 528}, - dictWord{135, 11, 1065}, - dictWord{5, 0, 279}, - dictWord{6, 0, 235}, - dictWord{7, 0, 468}, - dictWord{8, 0, 446}, - dictWord{9, 0, 637}, - dictWord{10, 0, 717}, - dictWord{11, 0, 738}, - dictWord{ - 140, - 0, - 514, - }, - dictWord{132, 0, 293}, - dictWord{11, 10, 337}, - dictWord{142, 10, 303}, - dictWord{136, 11, 285}, - dictWord{5, 0, 17}, - dictWord{6, 0, 371}, - dictWord{ - 9, - 0, - 528, - }, - dictWord{12, 0, 364}, - dictWord{132, 11, 254}, - dictWord{5, 10, 77}, - dictWord{7, 10, 1455}, - dictWord{10, 10, 843}, - dictWord{147, 10, 73}, - dictWord{ - 150, - 0, - 5, - }, - dictWord{132, 10, 458}, - dictWord{6, 11, 12}, - dictWord{7, 11, 1219}, - dictWord{145, 11, 73}, - dictWord{135, 10, 1420}, - dictWord{6, 10, 109}, - dictWord{138, 10, 382}, - dictWord{135, 11, 125}, - dictWord{6, 10, 330}, - dictWord{7, 10, 1084}, - dictWord{139, 10, 142}, - dictWord{6, 11, 369}, - dictWord{ - 6, - 11, - 502, - }, - dictWord{7, 11, 1036}, - dictWord{8, 11, 348}, - dictWord{9, 11, 452}, - dictWord{10, 11, 26}, - dictWord{11, 11, 224}, - dictWord{11, 11, 387}, - dictWord{ - 11, - 11, - 772, - }, - dictWord{12, 11, 95}, - dictWord{12, 11, 629}, - dictWord{13, 11, 195}, - dictWord{13, 11, 207}, - dictWord{13, 11, 241}, - dictWord{14, 11, 260}, - dictWord{ - 14, - 11, - 270, - }, - dictWord{143, 11, 140}, - dictWord{132, 11, 269}, - dictWord{5, 11, 480}, - dictWord{7, 11, 532}, - dictWord{7, 11, 1197}, - dictWord{7, 11, 1358}, - dictWord{8, 11, 291}, - dictWord{11, 11, 349}, - dictWord{142, 11, 396}, - dictWord{150, 0, 48}, - dictWord{10, 0, 601}, - dictWord{13, 0, 353}, - dictWord{141, 0, 376}, - dictWord{5, 0, 779}, - dictWord{5, 0, 807}, - dictWord{6, 0, 1655}, - dictWord{134, 0, 1676}, - dictWord{142, 11, 223}, - dictWord{4, 0, 196}, - dictWord{5, 0, 558}, - dictWord{133, 0, 949}, - dictWord{148, 11, 15}, - dictWord{135, 11, 1764}, - dictWord{134, 0, 1322}, - dictWord{132, 0, 752}, - dictWord{139, 0, 737}, - dictWord{ - 135, - 11, - 657, - }, - dictWord{136, 11, 533}, - dictWord{135, 0, 412}, - dictWord{4, 0, 227}, - dictWord{5, 0, 159}, - dictWord{5, 0, 409}, - dictWord{7, 0, 80}, - dictWord{8, 0, 556}, - dictWord{10, 0, 479}, - dictWord{12, 0, 418}, - dictWord{14, 0, 50}, - dictWord{14, 0, 123}, - dictWord{14, 0, 192}, - dictWord{14, 0, 249}, - dictWord{14, 0, 295}, - dictWord{143, 0, 27}, - dictWord{7, 0, 1470}, - dictWord{8, 0, 66}, - dictWord{8, 0, 137}, - dictWord{8, 0, 761}, - dictWord{9, 0, 638}, - dictWord{11, 0, 80}, - dictWord{11, 0, 212}, - dictWord{11, 0, 368}, - dictWord{11, 0, 418}, - dictWord{12, 0, 8}, - dictWord{13, 0, 15}, - dictWord{16, 0, 61}, - dictWord{17, 0, 59}, - dictWord{19, 0, 28}, - dictWord{ - 148, - 0, - 84, - }, - dictWord{135, 10, 1985}, - dictWord{4, 11, 211}, - dictWord{4, 11, 332}, - dictWord{5, 11, 335}, - dictWord{6, 11, 238}, - dictWord{7, 11, 269}, - dictWord{ - 7, - 11, - 811, - }, - dictWord{7, 11, 1797}, - dictWord{8, 10, 122}, - dictWord{8, 11, 836}, - dictWord{9, 11, 507}, - dictWord{141, 11, 242}, - dictWord{6, 0, 683}, - dictWord{ - 134, - 0, - 1252, - }, - dictWord{4, 0, 873}, - dictWord{132, 10, 234}, - dictWord{134, 0, 835}, - dictWord{6, 0, 38}, - dictWord{7, 0, 1220}, - dictWord{8, 0, 185}, - dictWord{8, 0, 256}, - dictWord{9, 0, 22}, - dictWord{9, 0, 331}, - dictWord{10, 0, 738}, - dictWord{11, 0, 205}, - dictWord{11, 0, 540}, - dictWord{11, 0, 746}, - dictWord{13, 0, 465}, - dictWord{ - 14, - 0, - 88, - }, - dictWord{142, 0, 194}, - dictWord{138, 0, 986}, - dictWord{5, 11, 1009}, - dictWord{12, 11, 582}, - dictWord{146, 11, 131}, - dictWord{4, 0, 159}, - dictWord{ - 6, - 0, - 115, - }, - dictWord{7, 0, 252}, - dictWord{7, 0, 257}, - dictWord{7, 0, 1928}, - dictWord{8, 0, 69}, - dictWord{9, 0, 384}, - dictWord{10, 0, 91}, - dictWord{10, 0, 615}, - dictWord{ - 12, - 0, - 375, - }, - dictWord{14, 0, 235}, - dictWord{18, 0, 117}, - dictWord{147, 0, 123}, - dictWord{133, 0, 911}, - dictWord{136, 0, 278}, - dictWord{5, 10, 430}, - dictWord{ - 5, - 10, - 932, - }, - dictWord{6, 10, 131}, - dictWord{7, 10, 417}, - dictWord{9, 10, 522}, - dictWord{11, 10, 314}, - dictWord{141, 10, 390}, - dictWord{14, 10, 149}, - dictWord{14, 10, 399}, - dictWord{143, 10, 57}, - dictWord{4, 0, 151}, - dictWord{7, 0, 1567}, - dictWord{136, 0, 749}, - dictWord{5, 11, 228}, - dictWord{6, 11, 203}, - dictWord{ - 7, - 11, - 156, - }, - dictWord{8, 11, 347}, - dictWord{137, 11, 265}, - dictWord{132, 10, 507}, - dictWord{10, 0, 989}, - dictWord{140, 0, 956}, - dictWord{133, 0, 990}, - dictWord{5, 0, 194}, - dictWord{6, 0, 927}, - dictWord{7, 0, 1662}, - dictWord{9, 0, 90}, - dictWord{140, 0, 564}, - dictWord{4, 10, 343}, - dictWord{133, 10, 511}, - dictWord{133, 0, 425}, - dictWord{7, 10, 455}, - dictWord{138, 10, 591}, - dictWord{4, 0, 774}, - dictWord{7, 11, 476}, - dictWord{7, 11, 1592}, - dictWord{138, 11, 87}, - dictWord{5, 0, 971}, - dictWord{135, 10, 1381}, - dictWord{5, 11, 318}, - dictWord{147, 11, 121}, - dictWord{5, 11, 291}, - dictWord{7, 11, 765}, - dictWord{9, 11, 389}, - dictWord{140, 11, 548}, - dictWord{134, 10, 575}, - dictWord{4, 0, 827}, - dictWord{12, 0, 646}, - dictWord{12, 0, 705}, - dictWord{12, 0, 712}, - dictWord{140, 0, 714}, - dictWord{139, 0, 752}, - dictWord{137, 0, 662}, - dictWord{5, 0, 72}, - dictWord{6, 0, 264}, - dictWord{7, 0, 21}, - dictWord{7, 0, 46}, - dictWord{7, 0, 2013}, - dictWord{ - 8, - 0, - 215, - }, - dictWord{8, 0, 513}, - dictWord{10, 0, 266}, - dictWord{139, 0, 22}, - dictWord{139, 11, 522}, - dictWord{6, 0, 239}, - dictWord{7, 0, 118}, - dictWord{10, 0, 95}, - dictWord{11, 0, 603}, - dictWord{13, 0, 443}, - dictWord{14, 0, 160}, - dictWord{143, 0, 4}, - dictWord{6, 0, 431}, - dictWord{134, 0, 669}, - dictWord{7, 10, 1127}, - dictWord{ - 7, - 10, - 1572, - }, - dictWord{10, 10, 297}, - dictWord{10, 10, 422}, - dictWord{11, 10, 764}, - dictWord{11, 10, 810}, - dictWord{12, 10, 264}, - dictWord{13, 10, 102}, - dictWord{13, 10, 300}, - dictWord{13, 10, 484}, - dictWord{14, 10, 147}, - dictWord{14, 10, 229}, - dictWord{17, 10, 71}, - dictWord{18, 10, 118}, - dictWord{ - 147, - 10, - 120, - }, - dictWord{5, 0, 874}, - dictWord{6, 0, 1677}, - dictWord{15, 0, 0}, - dictWord{10, 11, 525}, - dictWord{139, 11, 82}, - dictWord{6, 0, 65}, - dictWord{7, 0, 939}, - dictWord{ - 7, - 0, - 1172, - }, - dictWord{7, 0, 1671}, - dictWord{9, 0, 540}, - dictWord{10, 0, 696}, - dictWord{11, 0, 265}, - dictWord{11, 0, 732}, - dictWord{11, 0, 928}, - dictWord{ - 11, - 0, - 937, - }, - dictWord{141, 0, 438}, - dictWord{134, 0, 1350}, - dictWord{136, 11, 547}, - dictWord{132, 11, 422}, - dictWord{5, 11, 355}, - dictWord{145, 11, 0}, - dictWord{137, 11, 905}, - dictWord{5, 0, 682}, - dictWord{135, 0, 1887}, - dictWord{132, 0, 809}, - dictWord{4, 0, 696}, - dictWord{133, 11, 865}, - dictWord{6, 0, 1074}, - dictWord{6, 0, 1472}, - dictWord{14, 10, 35}, - dictWord{142, 10, 191}, - dictWord{5, 11, 914}, - dictWord{134, 11, 1625}, - dictWord{133, 11, 234}, - dictWord{ - 135, - 11, - 1383, - }, - dictWord{137, 11, 780}, - dictWord{132, 10, 125}, - dictWord{4, 0, 726}, - dictWord{133, 0, 630}, - dictWord{8, 0, 802}, - dictWord{136, 0, 838}, - dictWord{132, 10, 721}, - dictWord{6, 0, 1337}, - dictWord{7, 0, 776}, - dictWord{19, 0, 56}, - dictWord{136, 10, 145}, - dictWord{132, 0, 970}, - dictWord{7, 10, 792}, - dictWord{8, 10, 147}, - dictWord{10, 10, 821}, - dictWord{139, 10, 1021}, - dictWord{139, 10, 970}, - dictWord{8, 0, 940}, - dictWord{137, 0, 797}, - dictWord{ - 135, - 11, - 1312, - }, - dictWord{9, 0, 248}, - dictWord{10, 0, 400}, - dictWord{7, 11, 816}, - dictWord{7, 11, 1241}, - dictWord{7, 10, 1999}, - dictWord{9, 11, 283}, - dictWord{ - 9, - 11, - 520, - }, - dictWord{10, 11, 213}, - dictWord{10, 11, 307}, - dictWord{10, 11, 463}, - dictWord{10, 11, 671}, - dictWord{10, 11, 746}, - dictWord{11, 11, 401}, - dictWord{ - 11, - 11, - 794, - }, - dictWord{12, 11, 517}, - dictWord{18, 11, 107}, - dictWord{147, 11, 115}, - dictWord{6, 0, 1951}, - dictWord{134, 0, 2040}, - dictWord{ - 135, - 11, - 339, - }, - dictWord{13, 0, 41}, - dictWord{15, 0, 93}, - dictWord{5, 10, 168}, - dictWord{5, 10, 930}, - dictWord{8, 10, 74}, - dictWord{9, 10, 623}, - dictWord{12, 10, 500}, - dictWord{140, 10, 579}, - dictWord{6, 0, 118}, - dictWord{7, 0, 215}, - dictWord{7, 0, 1521}, - dictWord{140, 0, 11}, - dictWord{6, 10, 220}, - dictWord{7, 10, 1101}, - dictWord{141, 10, 105}, - dictWord{6, 11, 421}, - dictWord{7, 11, 61}, - dictWord{7, 11, 1540}, - dictWord{10, 11, 11}, - dictWord{138, 11, 501}, - dictWord{7, 0, 615}, - dictWord{138, 0, 251}, - dictWord{140, 11, 631}, - dictWord{135, 0, 1044}, - dictWord{6, 10, 19}, - dictWord{7, 10, 1413}, - dictWord{139, 10, 428}, - dictWord{ - 133, - 0, - 225, - }, - dictWord{7, 10, 96}, - dictWord{8, 10, 401}, - dictWord{8, 10, 703}, - dictWord{137, 10, 896}, - dictWord{145, 10, 116}, - dictWord{6, 11, 102}, - dictWord{ - 7, - 11, - 72, - }, - dictWord{15, 11, 142}, - dictWord{147, 11, 67}, - dictWord{7, 10, 1961}, - dictWord{7, 10, 1965}, - dictWord{8, 10, 702}, - dictWord{136, 10, 750}, - dictWord{ - 7, - 10, - 2030, - }, - dictWord{8, 10, 150}, - dictWord{8, 10, 737}, - dictWord{12, 10, 366}, - dictWord{151, 11, 30}, - dictWord{4, 0, 370}, - dictWord{5, 0, 756}, - dictWord{ - 7, - 0, - 1326, - }, - dictWord{135, 11, 823}, - dictWord{8, 10, 800}, - dictWord{9, 10, 148}, - dictWord{9, 10, 872}, - dictWord{9, 10, 890}, - dictWord{11, 10, 309}, - dictWord{ - 11, - 10, - 1001, - }, - dictWord{13, 10, 267}, - dictWord{141, 10, 323}, - dictWord{6, 0, 1662}, - dictWord{7, 0, 48}, - dictWord{8, 0, 771}, - dictWord{10, 0, 116}, - dictWord{ - 13, - 0, - 104, - }, - dictWord{14, 0, 105}, - dictWord{14, 0, 184}, - dictWord{15, 0, 168}, - dictWord{19, 0, 92}, - dictWord{148, 0, 68}, - dictWord{10, 0, 209}, - dictWord{ - 135, - 11, - 1870, - }, - dictWord{7, 11, 68}, - dictWord{8, 11, 48}, - dictWord{8, 11, 88}, - dictWord{8, 11, 582}, - dictWord{8, 11, 681}, - dictWord{9, 11, 373}, - dictWord{9, 11, 864}, - dictWord{11, 11, 157}, - dictWord{11, 11, 336}, - dictWord{11, 11, 843}, - dictWord{148, 11, 27}, - dictWord{134, 0, 930}, - dictWord{4, 11, 88}, - dictWord{5, 11, 137}, - dictWord{5, 11, 174}, - dictWord{5, 11, 777}, - dictWord{6, 11, 1664}, - dictWord{6, 11, 1725}, - dictWord{7, 11, 77}, - dictWord{7, 11, 426}, - dictWord{7, 11, 1317}, - dictWord{7, 11, 1355}, - dictWord{8, 11, 126}, - dictWord{8, 11, 563}, - dictWord{9, 11, 523}, - dictWord{9, 11, 750}, - dictWord{10, 11, 310}, - dictWord{10, 11, 836}, - dictWord{11, 11, 42}, - dictWord{11, 11, 318}, - dictWord{11, 11, 731}, - dictWord{12, 11, 68}, - dictWord{12, 11, 92}, - dictWord{12, 11, 507}, - dictWord{12, 11, 692}, - dictWord{13, 11, 81}, - dictWord{13, 11, 238}, - dictWord{13, 11, 374}, - dictWord{18, 11, 138}, - dictWord{19, 11, 78}, - dictWord{19, 11, 111}, - dictWord{20, 11, 55}, - dictWord{20, 11, 77}, - dictWord{148, 11, 92}, - dictWord{4, 11, 938}, - dictWord{135, 11, 1831}, - dictWord{5, 10, 547}, - dictWord{7, 10, 424}, - dictWord{ - 8, - 11, - 617, - }, - dictWord{138, 11, 351}, - dictWord{6, 0, 1286}, - dictWord{6, 11, 1668}, - dictWord{7, 11, 1499}, - dictWord{8, 11, 117}, - dictWord{9, 11, 314}, - dictWord{ - 138, - 11, - 174, - }, - dictWord{6, 0, 759}, - dictWord{6, 0, 894}, - dictWord{7, 11, 707}, - dictWord{139, 11, 563}, - dictWord{4, 0, 120}, - dictWord{135, 0, 1894}, - dictWord{ - 9, - 0, - 385, - }, - dictWord{149, 0, 17}, - dictWord{138, 0, 429}, - dictWord{133, 11, 403}, - dictWord{5, 0, 820}, - dictWord{135, 0, 931}, - dictWord{10, 0, 199}, - dictWord{ - 133, - 10, - 133, - }, - dictWord{6, 0, 151}, - dictWord{6, 0, 1675}, - dictWord{7, 0, 383}, - dictWord{151, 0, 10}, - dictWord{6, 0, 761}, - dictWord{136, 10, 187}, - dictWord{ - 8, - 0, - 365, - }, - dictWord{10, 10, 0}, - dictWord{10, 10, 818}, - dictWord{139, 10, 988}, - dictWord{4, 11, 44}, - dictWord{5, 11, 311}, - dictWord{6, 11, 156}, - dictWord{ - 7, - 11, - 639, - }, - dictWord{7, 11, 762}, - dictWord{7, 11, 1827}, - dictWord{9, 11, 8}, - dictWord{9, 11, 462}, - dictWord{148, 11, 83}, - dictWord{4, 11, 346}, - dictWord{7, 11, 115}, - dictWord{9, 11, 180}, - dictWord{9, 11, 456}, - dictWord{138, 11, 363}, - dictWord{136, 10, 685}, - dictWord{7, 0, 1086}, - dictWord{145, 0, 46}, - dictWord{ - 6, - 0, - 1624, - }, - dictWord{11, 0, 11}, - dictWord{12, 0, 422}, - dictWord{13, 0, 444}, - dictWord{142, 0, 360}, - dictWord{6, 0, 1020}, - dictWord{6, 0, 1260}, - dictWord{ - 134, - 0, - 1589, - }, - dictWord{4, 0, 43}, - dictWord{5, 0, 344}, - dictWord{5, 0, 357}, - dictWord{14, 0, 472}, - dictWord{150, 0, 58}, - dictWord{6, 0, 1864}, - dictWord{6, 0, 1866}, - dictWord{6, 0, 1868}, - dictWord{6, 0, 1869}, - dictWord{6, 0, 1874}, - dictWord{6, 0, 1877}, - dictWord{6, 0, 1903}, - dictWord{6, 0, 1911}, - dictWord{9, 0, 920}, - dictWord{ - 9, - 0, - 921, - }, - dictWord{9, 0, 924}, - dictWord{9, 0, 946}, - dictWord{9, 0, 959}, - dictWord{9, 0, 963}, - dictWord{9, 0, 970}, - dictWord{9, 0, 997}, - dictWord{9, 0, 1008}, - dictWord{ - 9, - 0, - 1017, - }, - dictWord{12, 0, 795}, - dictWord{12, 0, 797}, - dictWord{12, 0, 798}, - dictWord{12, 0, 800}, - dictWord{12, 0, 803}, - dictWord{12, 0, 811}, - dictWord{ - 12, - 0, - 820, - }, - dictWord{12, 0, 821}, - dictWord{12, 0, 839}, - dictWord{12, 0, 841}, - dictWord{12, 0, 848}, - dictWord{12, 0, 911}, - dictWord{12, 0, 921}, - dictWord{12, 0, 922}, - dictWord{12, 0, 925}, - dictWord{12, 0, 937}, - dictWord{12, 0, 944}, - dictWord{12, 0, 945}, - dictWord{12, 0, 953}, - dictWord{15, 0, 184}, - dictWord{15, 0, 191}, - dictWord{15, 0, 199}, - dictWord{15, 0, 237}, - dictWord{15, 0, 240}, - dictWord{15, 0, 243}, - dictWord{15, 0, 246}, - dictWord{18, 0, 203}, - dictWord{21, 0, 40}, - dictWord{ - 21, - 0, - 52, - }, - dictWord{21, 0, 57}, - dictWord{24, 0, 23}, - dictWord{24, 0, 28}, - dictWord{152, 0, 30}, - dictWord{134, 0, 725}, - dictWord{145, 11, 58}, - dictWord{133, 0, 888}, - dictWord{137, 10, 874}, - dictWord{4, 0, 711}, - dictWord{8, 10, 774}, - dictWord{10, 10, 670}, - dictWord{140, 10, 51}, - dictWord{144, 11, 40}, - dictWord{ - 6, - 11, - 185, - }, - dictWord{7, 11, 1899}, - dictWord{139, 11, 673}, - dictWord{137, 10, 701}, - dictWord{137, 0, 440}, - dictWord{4, 11, 327}, - dictWord{5, 11, 478}, - dictWord{ - 7, - 11, - 1332, - }, - dictWord{8, 11, 753}, - dictWord{140, 11, 227}, - dictWord{4, 10, 127}, - dictWord{5, 10, 350}, - dictWord{6, 10, 356}, - dictWord{8, 10, 426}, - dictWord{ - 9, - 10, - 572, - }, - dictWord{10, 10, 247}, - dictWord{139, 10, 312}, - dictWord{5, 11, 1020}, - dictWord{133, 11, 1022}, - dictWord{4, 11, 103}, - dictWord{ - 133, - 11, - 401, - }, - dictWord{6, 0, 1913}, - dictWord{6, 0, 1926}, - dictWord{6, 0, 1959}, - dictWord{9, 0, 914}, - dictWord{9, 0, 939}, - dictWord{9, 0, 952}, - dictWord{9, 0, 979}, - dictWord{ - 9, - 0, - 990, - }, - dictWord{9, 0, 998}, - dictWord{9, 0, 1003}, - dictWord{9, 0, 1023}, - dictWord{12, 0, 827}, - dictWord{12, 0, 834}, - dictWord{12, 0, 845}, - dictWord{ - 12, - 0, - 912, - }, - dictWord{12, 0, 935}, - dictWord{12, 0, 951}, - dictWord{15, 0, 172}, - dictWord{15, 0, 174}, - dictWord{18, 0, 198}, - dictWord{149, 0, 63}, - dictWord{5, 0, 958}, - dictWord{5, 0, 987}, - dictWord{4, 11, 499}, - dictWord{135, 11, 1421}, - dictWord{7, 0, 885}, - dictWord{6, 10, 59}, - dictWord{6, 10, 1762}, - dictWord{9, 10, 603}, - dictWord{141, 10, 397}, - dictWord{10, 11, 62}, - dictWord{141, 11, 164}, - dictWord{4, 0, 847}, - dictWord{135, 0, 326}, - dictWord{11, 0, 276}, - dictWord{142, 0, 293}, - dictWord{4, 0, 65}, - dictWord{5, 0, 479}, - dictWord{5, 0, 1004}, - dictWord{7, 0, 1913}, - dictWord{8, 0, 317}, - dictWord{9, 0, 302}, - dictWord{10, 0, 612}, - dictWord{ - 13, - 0, - 22, - }, - dictWord{132, 11, 96}, - dictWord{4, 0, 261}, - dictWord{135, 0, 510}, - dictWord{135, 0, 1514}, - dictWord{6, 10, 111}, - dictWord{7, 10, 4}, - dictWord{8, 10, 163}, - dictWord{8, 10, 776}, - dictWord{138, 10, 566}, - dictWord{4, 0, 291}, - dictWord{9, 0, 515}, - dictWord{12, 0, 152}, - dictWord{12, 0, 443}, - dictWord{13, 0, 392}, - dictWord{142, 0, 357}, - dictWord{7, 11, 399}, - dictWord{135, 11, 1492}, - dictWord{4, 0, 589}, - dictWord{139, 0, 282}, - dictWord{6, 11, 563}, - dictWord{ - 135, - 10, - 1994, - }, - dictWord{5, 10, 297}, - dictWord{135, 10, 1038}, - dictWord{4, 0, 130}, - dictWord{7, 0, 843}, - dictWord{135, 0, 1562}, - dictWord{5, 0, 42}, - dictWord{ - 5, - 0, - 879, - }, - dictWord{7, 0, 245}, - dictWord{7, 0, 324}, - dictWord{7, 0, 1532}, - dictWord{11, 0, 463}, - dictWord{11, 0, 472}, - dictWord{13, 0, 363}, - dictWord{144, 0, 52}, - dictWord{4, 0, 134}, - dictWord{133, 0, 372}, - dictWord{133, 0, 680}, - dictWord{136, 10, 363}, - dictWord{6, 0, 1997}, - dictWord{8, 0, 935}, - dictWord{136, 0, 977}, - dictWord{4, 0, 810}, - dictWord{135, 0, 1634}, - dictWord{135, 10, 1675}, - dictWord{7, 0, 1390}, - dictWord{4, 11, 910}, - dictWord{133, 11, 832}, - dictWord{ - 7, - 10, - 808, - }, - dictWord{8, 11, 266}, - dictWord{139, 11, 578}, - dictWord{132, 0, 644}, - dictWord{4, 0, 982}, - dictWord{138, 0, 867}, - dictWord{132, 10, 280}, - dictWord{ - 135, - 0, - 540, - }, - dictWord{140, 10, 54}, - dictWord{135, 0, 123}, - dictWord{134, 0, 1978}, - dictWord{4, 10, 421}, - dictWord{133, 10, 548}, - dictWord{6, 0, 623}, - dictWord{136, 0, 789}, - dictWord{4, 0, 908}, - dictWord{5, 0, 359}, - dictWord{5, 0, 508}, - dictWord{6, 0, 1723}, - dictWord{7, 0, 343}, - dictWord{7, 0, 1996}, - dictWord{ - 135, - 0, - 2026, - }, - dictWord{134, 0, 1220}, - dictWord{4, 0, 341}, - dictWord{135, 0, 480}, - dictWord{6, 10, 254}, - dictWord{9, 10, 109}, - dictWord{138, 10, 103}, - dictWord{ - 134, - 0, - 888, - }, - dictWord{8, 11, 528}, - dictWord{137, 11, 348}, - dictWord{7, 0, 1995}, - dictWord{8, 0, 299}, - dictWord{11, 0, 890}, - dictWord{12, 0, 674}, - dictWord{ - 4, - 11, - 20, - }, - dictWord{133, 11, 616}, - dictWord{135, 11, 1094}, - dictWord{134, 10, 1630}, - dictWord{4, 0, 238}, - dictWord{5, 0, 503}, - dictWord{6, 0, 179}, - dictWord{ - 7, - 0, - 2003, - }, - dictWord{8, 0, 381}, - dictWord{8, 0, 473}, - dictWord{9, 0, 149}, - dictWord{10, 0, 788}, - dictWord{15, 0, 45}, - dictWord{15, 0, 86}, - dictWord{20, 0, 110}, - dictWord{150, 0, 57}, - dictWord{133, 10, 671}, - dictWord{4, 11, 26}, - dictWord{5, 11, 429}, - dictWord{6, 11, 245}, - dictWord{7, 11, 704}, - dictWord{7, 11, 1379}, - dictWord{135, 11, 1474}, - dictWord{4, 0, 121}, - dictWord{5, 0, 156}, - dictWord{5, 0, 349}, - dictWord{9, 0, 431}, - dictWord{10, 0, 605}, - dictWord{142, 0, 342}, - dictWord{ - 7, - 11, - 943, - }, - dictWord{139, 11, 614}, - dictWord{132, 10, 889}, - dictWord{132, 11, 621}, - dictWord{7, 10, 1382}, - dictWord{7, 11, 1382}, - dictWord{ - 135, - 10, - 1910, - }, - dictWord{132, 10, 627}, - dictWord{133, 10, 775}, - dictWord{133, 11, 542}, - dictWord{133, 11, 868}, - dictWord{136, 11, 433}, - dictWord{6, 0, 1373}, - dictWord{7, 0, 1011}, - dictWord{11, 10, 362}, - dictWord{11, 10, 948}, - dictWord{140, 10, 388}, - dictWord{6, 0, 80}, - dictWord{7, 0, 173}, - dictWord{9, 0, 547}, - dictWord{10, 0, 730}, - dictWord{14, 0, 18}, - dictWord{22, 0, 39}, - dictWord{135, 11, 1495}, - dictWord{6, 0, 1694}, - dictWord{135, 0, 1974}, - dictWord{140, 0, 196}, - dictWord{4, 0, 923}, - dictWord{6, 0, 507}, - dictWord{6, 0, 1711}, - dictWord{7, 10, 451}, - dictWord{8, 10, 389}, - dictWord{12, 10, 490}, - dictWord{13, 10, 16}, - dictWord{ - 13, - 10, - 215, - }, - dictWord{13, 10, 351}, - dictWord{18, 10, 132}, - dictWord{147, 10, 125}, - dictWord{6, 0, 646}, - dictWord{134, 0, 1047}, - dictWord{135, 10, 841}, - dictWord{136, 10, 566}, - dictWord{6, 0, 1611}, - dictWord{135, 0, 1214}, - dictWord{139, 0, 926}, - dictWord{132, 11, 525}, - dictWord{132, 0, 595}, - dictWord{ - 5, - 0, - 240, - }, - dictWord{6, 0, 459}, - dictWord{7, 0, 12}, - dictWord{7, 0, 114}, - dictWord{7, 0, 949}, - dictWord{7, 0, 1753}, - dictWord{7, 0, 1805}, - dictWord{8, 0, 658}, - dictWord{ - 9, - 0, - 1, - }, - dictWord{11, 0, 959}, - dictWord{141, 0, 446}, - dictWord{5, 10, 912}, - dictWord{134, 10, 1695}, - dictWord{132, 0, 446}, - dictWord{7, 11, 62}, - dictWord{ - 12, - 11, - 45, - }, - dictWord{147, 11, 112}, - dictWord{5, 10, 236}, - dictWord{6, 10, 572}, - dictWord{8, 10, 492}, - dictWord{11, 10, 618}, - dictWord{144, 10, 56}, - dictWord{ - 5, - 10, - 190, - }, - dictWord{136, 10, 318}, - dictWord{135, 10, 1376}, - dictWord{4, 11, 223}, - dictWord{6, 11, 359}, - dictWord{11, 11, 3}, - dictWord{13, 11, 108}, - dictWord{ - 14, - 11, - 89, - }, - dictWord{144, 11, 22}, - dictWord{132, 11, 647}, - dictWord{134, 0, 490}, - dictWord{134, 0, 491}, - dictWord{134, 0, 1584}, - dictWord{ - 135, - 11, - 685, - }, - dictWord{138, 11, 220}, - dictWord{7, 0, 250}, - dictWord{136, 0, 507}, - dictWord{132, 0, 158}, - dictWord{4, 0, 140}, - dictWord{7, 0, 362}, - dictWord{8, 0, 209}, - dictWord{9, 0, 10}, - dictWord{9, 0, 160}, - dictWord{9, 0, 503}, - dictWord{9, 0, 614}, - dictWord{10, 0, 689}, - dictWord{11, 0, 327}, - dictWord{11, 0, 553}, - dictWord{ - 11, - 0, - 725, - }, - dictWord{11, 0, 767}, - dictWord{12, 0, 252}, - dictWord{12, 0, 583}, - dictWord{13, 0, 192}, - dictWord{14, 0, 269}, - dictWord{14, 0, 356}, - dictWord{148, 0, 50}, - dictWord{19, 0, 1}, - dictWord{19, 0, 26}, - dictWord{150, 0, 9}, - dictWord{132, 11, 109}, - dictWord{6, 0, 228}, - dictWord{7, 0, 1341}, - dictWord{9, 0, 408}, - dictWord{ - 138, - 0, - 343, - }, - dictWord{4, 0, 373}, - dictWord{5, 0, 283}, - dictWord{6, 0, 480}, - dictWord{7, 0, 609}, - dictWord{10, 0, 860}, - dictWord{138, 0, 878}, - dictWord{6, 0, 779}, - dictWord{134, 0, 1209}, - dictWord{4, 0, 557}, - dictWord{7, 11, 263}, - dictWord{7, 11, 628}, - dictWord{136, 11, 349}, - dictWord{132, 0, 548}, - dictWord{7, 0, 197}, - dictWord{8, 0, 142}, - dictWord{8, 0, 325}, - dictWord{9, 0, 150}, - dictWord{9, 0, 596}, - dictWord{10, 0, 350}, - dictWord{10, 0, 353}, - dictWord{11, 0, 74}, - dictWord{ - 11, - 0, - 315, - }, - dictWord{12, 0, 662}, - dictWord{12, 0, 681}, - dictWord{14, 0, 423}, - dictWord{143, 0, 141}, - dictWord{4, 11, 40}, - dictWord{10, 11, 67}, - dictWord{ - 11, - 11, - 117, - }, - dictWord{11, 11, 768}, - dictWord{139, 11, 935}, - dictWord{7, 11, 992}, - dictWord{8, 11, 301}, - dictWord{9, 11, 722}, - dictWord{12, 11, 63}, - dictWord{ - 13, - 11, - 29, - }, - dictWord{14, 11, 161}, - dictWord{143, 11, 18}, - dictWord{6, 0, 1490}, - dictWord{138, 11, 532}, - dictWord{5, 0, 580}, - dictWord{7, 0, 378}, - dictWord{ - 7, - 0, - 674, - }, - dictWord{7, 0, 1424}, - dictWord{15, 0, 83}, - dictWord{16, 0, 11}, - dictWord{15, 11, 83}, - dictWord{144, 11, 11}, - dictWord{6, 0, 1057}, - dictWord{6, 0, 1335}, - dictWord{10, 0, 316}, - dictWord{7, 10, 85}, - dictWord{7, 10, 247}, - dictWord{8, 10, 585}, - dictWord{138, 10, 163}, - dictWord{4, 0, 169}, - dictWord{5, 0, 83}, - dictWord{ - 6, - 0, - 399, - }, - dictWord{6, 0, 579}, - dictWord{6, 0, 1513}, - dictWord{7, 0, 692}, - dictWord{7, 0, 846}, - dictWord{7, 0, 1015}, - dictWord{7, 0, 1799}, - dictWord{8, 0, 403}, - dictWord{9, 0, 394}, - dictWord{10, 0, 133}, - dictWord{12, 0, 4}, - dictWord{12, 0, 297}, - dictWord{12, 0, 452}, - dictWord{16, 0, 81}, - dictWord{18, 0, 25}, - dictWord{21, 0, 14}, - dictWord{22, 0, 12}, - dictWord{151, 0, 18}, - dictWord{134, 0, 1106}, - dictWord{7, 0, 1546}, - dictWord{11, 0, 299}, - dictWord{142, 0, 407}, - dictWord{134, 0, 1192}, - dictWord{132, 0, 177}, - dictWord{5, 0, 411}, - dictWord{135, 0, 653}, - dictWord{7, 0, 439}, - dictWord{10, 0, 727}, - dictWord{11, 0, 260}, - dictWord{139, 0, 684}, - dictWord{138, 10, 145}, - dictWord{147, 10, 83}, - dictWord{5, 0, 208}, - dictWord{7, 0, 753}, - dictWord{135, 0, 1528}, - dictWord{137, 11, 617}, - dictWord{ - 135, - 10, - 1922, - }, - dictWord{135, 11, 825}, - dictWord{11, 0, 422}, - dictWord{13, 0, 389}, - dictWord{4, 10, 124}, - dictWord{10, 10, 457}, - dictWord{11, 10, 121}, - dictWord{ - 11, - 10, - 169, - }, - dictWord{11, 10, 870}, - dictWord{12, 10, 214}, - dictWord{14, 10, 187}, - dictWord{143, 10, 77}, - dictWord{11, 0, 615}, - dictWord{15, 0, 58}, - dictWord{ - 11, - 11, - 615, - }, - dictWord{143, 11, 58}, - dictWord{9, 0, 618}, - dictWord{138, 0, 482}, - dictWord{6, 0, 1952}, - dictWord{6, 0, 1970}, - dictWord{142, 0, 505}, - dictWord{ - 7, - 10, - 1193, - }, - dictWord{135, 11, 1838}, - dictWord{133, 0, 242}, - dictWord{135, 10, 1333}, - dictWord{6, 10, 107}, - dictWord{7, 10, 638}, - dictWord{ - 7, - 10, - 1632, - }, - dictWord{137, 10, 396}, - dictWord{133, 0, 953}, - dictWord{5, 10, 370}, - dictWord{134, 10, 1756}, - dictWord{5, 11, 28}, - dictWord{6, 11, 204}, - dictWord{ - 10, - 11, - 320, - }, - dictWord{10, 11, 583}, - dictWord{13, 11, 502}, - dictWord{14, 11, 72}, - dictWord{14, 11, 274}, - dictWord{14, 11, 312}, - dictWord{14, 11, 344}, - dictWord{15, 11, 159}, - dictWord{16, 11, 62}, - dictWord{16, 11, 69}, - dictWord{17, 11, 30}, - dictWord{18, 11, 42}, - dictWord{18, 11, 53}, - dictWord{18, 11, 84}, - dictWord{18, 11, 140}, - dictWord{19, 11, 68}, - dictWord{19, 11, 85}, - dictWord{20, 11, 5}, - dictWord{20, 11, 45}, - dictWord{20, 11, 101}, - dictWord{22, 11, 7}, - dictWord{ - 150, - 11, - 20, - }, - dictWord{4, 11, 558}, - dictWord{6, 11, 390}, - dictWord{7, 11, 162}, - dictWord{7, 11, 689}, - dictWord{9, 11, 360}, - dictWord{138, 11, 653}, - dictWord{ - 11, - 0, - 802, - }, - dictWord{141, 0, 67}, - dictWord{133, 10, 204}, - dictWord{133, 0, 290}, - dictWord{5, 10, 970}, - dictWord{134, 10, 1706}, - dictWord{132, 0, 380}, - dictWord{5, 0, 52}, - dictWord{7, 0, 277}, - dictWord{9, 0, 368}, - dictWord{139, 0, 791}, - dictWord{5, 11, 856}, - dictWord{6, 11, 1672}, - dictWord{6, 11, 1757}, - dictWord{ - 6, - 11, - 1781, - }, - dictWord{7, 11, 1150}, - dictWord{7, 11, 1425}, - dictWord{7, 11, 1453}, - dictWord{140, 11, 513}, - dictWord{5, 11, 92}, - dictWord{7, 10, 3}, - dictWord{ - 10, - 11, - 736, - }, - dictWord{140, 11, 102}, - dictWord{4, 0, 112}, - dictWord{5, 0, 653}, - dictWord{5, 10, 483}, - dictWord{5, 10, 685}, - dictWord{6, 10, 489}, - dictWord{ - 7, - 10, - 1204, - }, - dictWord{136, 10, 394}, - dictWord{132, 10, 921}, - dictWord{6, 0, 1028}, - dictWord{133, 10, 1007}, - dictWord{5, 11, 590}, - dictWord{9, 11, 213}, - dictWord{145, 11, 91}, - dictWord{135, 10, 1696}, - dictWord{10, 0, 138}, - dictWord{139, 0, 476}, - dictWord{5, 0, 725}, - dictWord{5, 0, 727}, - dictWord{135, 0, 1811}, - dictWord{4, 0, 979}, - dictWord{6, 0, 1821}, - dictWord{6, 0, 1838}, - dictWord{8, 0, 876}, - dictWord{8, 0, 883}, - dictWord{8, 0, 889}, - dictWord{8, 0, 893}, - dictWord{ - 8, - 0, - 895, - }, - dictWord{10, 0, 934}, - dictWord{12, 0, 720}, - dictWord{14, 0, 459}, - dictWord{148, 0, 123}, - dictWord{135, 11, 551}, - dictWord{4, 0, 38}, - dictWord{6, 0, 435}, - dictWord{7, 0, 307}, - dictWord{7, 0, 999}, - dictWord{7, 0, 1481}, - dictWord{7, 0, 1732}, - dictWord{7, 0, 1738}, - dictWord{8, 0, 371}, - dictWord{9, 0, 414}, - dictWord{ - 11, - 0, - 316, - }, - dictWord{12, 0, 52}, - dictWord{13, 0, 420}, - dictWord{147, 0, 100}, - dictWord{135, 0, 1296}, - dictWord{132, 10, 712}, - dictWord{134, 10, 1629}, - dictWord{133, 0, 723}, - dictWord{134, 0, 651}, - dictWord{136, 11, 191}, - dictWord{9, 11, 791}, - dictWord{10, 11, 93}, - dictWord{11, 11, 301}, - dictWord{16, 11, 13}, - dictWord{17, 11, 23}, - dictWord{18, 11, 135}, - dictWord{19, 11, 12}, - dictWord{20, 11, 1}, - dictWord{20, 11, 12}, - dictWord{148, 11, 14}, - dictWord{136, 11, 503}, - dictWord{6, 11, 466}, - dictWord{135, 11, 671}, - dictWord{6, 0, 1200}, - dictWord{134, 0, 1330}, - dictWord{135, 0, 1255}, - dictWord{134, 0, 986}, - dictWord{ - 5, - 0, - 109, - }, - dictWord{6, 0, 1784}, - dictWord{7, 0, 1895}, - dictWord{12, 0, 296}, - dictWord{140, 0, 302}, - dictWord{135, 11, 983}, - dictWord{133, 10, 485}, - dictWord{ - 134, - 0, - 660, - }, - dictWord{134, 0, 800}, - dictWord{5, 0, 216}, - dictWord{5, 0, 294}, - dictWord{6, 0, 591}, - dictWord{7, 0, 1879}, - dictWord{9, 0, 141}, - dictWord{9, 0, 270}, - dictWord{9, 0, 679}, - dictWord{10, 0, 159}, - dictWord{11, 0, 197}, - dictWord{11, 0, 438}, - dictWord{12, 0, 538}, - dictWord{12, 0, 559}, - dictWord{14, 0, 144}, - dictWord{ - 14, - 0, - 167, - }, - dictWord{15, 0, 67}, - dictWord{4, 10, 285}, - dictWord{5, 10, 317}, - dictWord{6, 10, 301}, - dictWord{7, 10, 7}, - dictWord{8, 10, 153}, - dictWord{ - 10, - 10, - 766, - }, - dictWord{11, 10, 468}, - dictWord{12, 10, 467}, - dictWord{141, 10, 143}, - dictWord{136, 0, 945}, - dictWord{134, 0, 1090}, - dictWord{137, 0, 81}, - dictWord{12, 11, 468}, - dictWord{19, 11, 96}, - dictWord{148, 11, 24}, - dictWord{134, 0, 391}, - dictWord{138, 11, 241}, - dictWord{7, 0, 322}, - dictWord{136, 0, 249}, - dictWord{134, 0, 1412}, - dictWord{135, 11, 795}, - dictWord{5, 0, 632}, - dictWord{138, 0, 526}, - dictWord{136, 10, 819}, - dictWord{6, 0, 144}, - dictWord{7, 0, 948}, - dictWord{7, 0, 1042}, - dictWord{8, 0, 235}, - dictWord{8, 0, 461}, - dictWord{9, 0, 453}, - dictWord{9, 0, 796}, - dictWord{10, 0, 354}, - dictWord{17, 0, 77}, - dictWord{ - 135, - 11, - 954, - }, - dictWord{139, 10, 917}, - dictWord{6, 0, 940}, - dictWord{134, 0, 1228}, - dictWord{4, 0, 362}, - dictWord{7, 0, 52}, - dictWord{135, 0, 303}, - dictWord{ - 6, - 11, - 549, - }, - dictWord{8, 11, 34}, - dictWord{8, 11, 283}, - dictWord{9, 11, 165}, - dictWord{138, 11, 475}, - dictWord{7, 11, 370}, - dictWord{7, 11, 1007}, - dictWord{ - 7, - 11, - 1177, - }, - dictWord{135, 11, 1565}, - dictWord{5, 11, 652}, - dictWord{5, 11, 701}, - dictWord{135, 11, 449}, - dictWord{5, 0, 196}, - dictWord{6, 0, 486}, - dictWord{ - 7, - 0, - 212, - }, - dictWord{8, 0, 309}, - dictWord{136, 0, 346}, - dictWord{6, 10, 1719}, - dictWord{6, 10, 1735}, - dictWord{7, 10, 2016}, - dictWord{7, 10, 2020}, - dictWord{ - 8, - 10, - 837, - }, - dictWord{137, 10, 852}, - dictWord{6, 11, 159}, - dictWord{6, 11, 364}, - dictWord{7, 11, 516}, - dictWord{7, 11, 1439}, - dictWord{137, 11, 518}, - dictWord{135, 0, 1912}, - dictWord{135, 0, 1290}, - dictWord{132, 0, 686}, - dictWord{141, 11, 151}, - dictWord{138, 0, 625}, - dictWord{136, 0, 706}, - dictWord{ - 138, - 10, - 568, - }, - dictWord{139, 0, 412}, - dictWord{4, 0, 30}, - dictWord{133, 0, 43}, - dictWord{8, 10, 67}, - dictWord{138, 10, 419}, - dictWord{7, 0, 967}, - dictWord{ - 141, - 0, - 11, - }, - dictWord{12, 0, 758}, - dictWord{14, 0, 441}, - dictWord{142, 0, 462}, - dictWord{10, 10, 657}, - dictWord{14, 10, 297}, - dictWord{142, 10, 361}, - dictWord{ - 139, - 10, - 729, - }, - dictWord{4, 0, 220}, - dictWord{135, 0, 1535}, - dictWord{7, 11, 501}, - dictWord{9, 11, 111}, - dictWord{10, 11, 141}, - dictWord{11, 11, 332}, - dictWord{ - 13, - 11, - 43, - }, - dictWord{13, 11, 429}, - dictWord{14, 11, 130}, - dictWord{14, 11, 415}, - dictWord{145, 11, 102}, - dictWord{4, 0, 950}, - dictWord{6, 0, 1859}, - dictWord{ - 7, - 0, - 11, - }, - dictWord{8, 0, 873}, - dictWord{12, 0, 710}, - dictWord{12, 0, 718}, - dictWord{12, 0, 748}, - dictWord{12, 0, 765}, - dictWord{148, 0, 124}, - dictWord{ - 5, - 11, - 149, - }, - dictWord{5, 11, 935}, - dictWord{136, 11, 233}, - dictWord{142, 11, 291}, - dictWord{134, 0, 1579}, - dictWord{7, 0, 890}, - dictWord{8, 10, 51}, - dictWord{ - 9, - 10, - 868, - }, - dictWord{10, 10, 833}, - dictWord{12, 10, 481}, - dictWord{12, 10, 570}, - dictWord{148, 10, 106}, - dictWord{141, 0, 2}, - dictWord{132, 10, 445}, - dictWord{136, 11, 801}, - dictWord{135, 0, 1774}, - dictWord{7, 0, 1725}, - dictWord{138, 0, 393}, - dictWord{5, 0, 263}, - dictWord{134, 0, 414}, - dictWord{ - 132, - 11, - 322, - }, - dictWord{133, 10, 239}, - dictWord{7, 0, 456}, - dictWord{7, 10, 1990}, - dictWord{8, 10, 130}, - dictWord{139, 10, 720}, - dictWord{137, 0, 818}, - dictWord{ - 5, - 10, - 123, - }, - dictWord{6, 10, 530}, - dictWord{7, 10, 348}, - dictWord{135, 10, 1419}, - dictWord{135, 10, 2024}, - dictWord{6, 0, 178}, - dictWord{6, 0, 1750}, - dictWord{8, 0, 251}, - dictWord{9, 0, 690}, - dictWord{10, 0, 155}, - dictWord{10, 0, 196}, - dictWord{10, 0, 373}, - dictWord{11, 0, 698}, - dictWord{13, 0, 155}, - dictWord{ - 148, - 0, - 93, - }, - dictWord{5, 0, 97}, - dictWord{137, 0, 393}, - dictWord{134, 0, 674}, - dictWord{11, 0, 223}, - dictWord{140, 0, 168}, - dictWord{132, 10, 210}, - dictWord{ - 139, - 11, - 464, - }, - dictWord{6, 0, 1639}, - dictWord{146, 0, 159}, - dictWord{139, 11, 2}, - dictWord{7, 0, 934}, - dictWord{8, 0, 647}, - dictWord{17, 0, 97}, - dictWord{19, 0, 59}, - dictWord{150, 0, 2}, - dictWord{132, 0, 191}, - dictWord{5, 0, 165}, - dictWord{9, 0, 346}, - dictWord{10, 0, 655}, - dictWord{11, 0, 885}, - dictWord{4, 10, 430}, - dictWord{135, 11, 357}, - dictWord{133, 0, 877}, - dictWord{5, 10, 213}, - dictWord{133, 11, 406}, - dictWord{8, 0, 128}, - dictWord{139, 0, 179}, - dictWord{6, 11, 69}, - dictWord{135, 11, 117}, - dictWord{135, 0, 1297}, - dictWord{11, 11, 43}, - dictWord{13, 11, 72}, - dictWord{141, 11, 142}, - dictWord{135, 11, 1830}, - dictWord{ - 142, - 0, - 164, - }, - dictWord{5, 0, 57}, - dictWord{6, 0, 101}, - dictWord{6, 0, 586}, - dictWord{6, 0, 1663}, - dictWord{7, 0, 132}, - dictWord{7, 0, 1154}, - dictWord{7, 0, 1415}, - dictWord{7, 0, 1507}, - dictWord{12, 0, 493}, - dictWord{15, 0, 105}, - dictWord{151, 0, 15}, - dictWord{5, 0, 459}, - dictWord{7, 0, 1073}, - dictWord{8, 0, 241}, - dictWord{ - 136, - 0, - 334, - }, - dictWord{133, 11, 826}, - dictWord{133, 10, 108}, - dictWord{5, 10, 219}, - dictWord{10, 11, 132}, - dictWord{11, 11, 191}, - dictWord{11, 11, 358}, - dictWord{139, 11, 460}, - dictWord{6, 0, 324}, - dictWord{6, 0, 520}, - dictWord{7, 0, 338}, - dictWord{7, 0, 1729}, - dictWord{8, 0, 228}, - dictWord{139, 0, 750}, - dictWord{ - 21, - 0, - 30, - }, - dictWord{22, 0, 53}, - dictWord{4, 10, 193}, - dictWord{5, 10, 916}, - dictWord{7, 10, 364}, - dictWord{10, 10, 398}, - dictWord{10, 10, 726}, - dictWord{ - 11, - 10, - 317, - }, - dictWord{11, 10, 626}, - dictWord{12, 10, 142}, - dictWord{12, 10, 288}, - dictWord{12, 10, 678}, - dictWord{13, 10, 313}, - dictWord{15, 10, 113}, - dictWord{146, 10, 114}, - dictWord{6, 11, 110}, - dictWord{135, 11, 1681}, - dictWord{135, 0, 910}, - dictWord{6, 10, 241}, - dictWord{7, 10, 907}, - dictWord{8, 10, 832}, - dictWord{9, 10, 342}, - dictWord{10, 10, 729}, - dictWord{11, 10, 284}, - dictWord{11, 10, 445}, - dictWord{11, 10, 651}, - dictWord{11, 10, 863}, - dictWord{ - 13, - 10, - 398, - }, - dictWord{146, 10, 99}, - dictWord{7, 0, 705}, - dictWord{9, 0, 734}, - dictWord{5, 11, 1000}, - dictWord{7, 11, 733}, - dictWord{137, 11, 583}, - dictWord{4, 0, 73}, - dictWord{6, 0, 612}, - dictWord{7, 0, 927}, - dictWord{7, 0, 1822}, - dictWord{8, 0, 217}, - dictWord{9, 0, 765}, - dictWord{9, 0, 766}, - dictWord{10, 0, 408}, - dictWord{ - 11, - 0, - 51, - }, - dictWord{11, 0, 793}, - dictWord{12, 0, 266}, - dictWord{15, 0, 158}, - dictWord{20, 0, 89}, - dictWord{150, 0, 32}, - dictWord{7, 0, 1330}, - dictWord{4, 11, 297}, - dictWord{6, 11, 529}, - dictWord{7, 11, 152}, - dictWord{7, 11, 713}, - dictWord{7, 11, 1845}, - dictWord{8, 11, 710}, - dictWord{8, 11, 717}, - dictWord{140, 11, 639}, - dictWord{5, 0, 389}, - dictWord{136, 0, 636}, - dictWord{134, 0, 1409}, - dictWord{4, 10, 562}, - dictWord{9, 10, 254}, - dictWord{139, 10, 879}, - dictWord{134, 0, 893}, - dictWord{132, 10, 786}, - dictWord{4, 11, 520}, - dictWord{135, 11, 575}, - dictWord{136, 0, 21}, - dictWord{140, 0, 721}, - dictWord{136, 0, 959}, - dictWord{ - 7, - 11, - 1428, - }, - dictWord{7, 11, 1640}, - dictWord{9, 11, 169}, - dictWord{9, 11, 182}, - dictWord{9, 11, 367}, - dictWord{9, 11, 478}, - dictWord{9, 11, 506}, - dictWord{ - 9, - 11, - 551, - }, - dictWord{9, 11, 648}, - dictWord{9, 11, 651}, - dictWord{9, 11, 697}, - dictWord{9, 11, 705}, - dictWord{9, 11, 725}, - dictWord{9, 11, 787}, - dictWord{9, 11, 794}, - dictWord{10, 11, 198}, - dictWord{10, 11, 214}, - dictWord{10, 11, 267}, - dictWord{10, 11, 275}, - dictWord{10, 11, 456}, - dictWord{10, 11, 551}, - dictWord{ - 10, - 11, - 561, - }, - dictWord{10, 11, 613}, - dictWord{10, 11, 627}, - dictWord{10, 11, 668}, - dictWord{10, 11, 675}, - dictWord{10, 11, 691}, - dictWord{10, 11, 695}, - dictWord{10, 11, 707}, - dictWord{10, 11, 715}, - dictWord{11, 11, 183}, - dictWord{11, 11, 201}, - dictWord{11, 11, 244}, - dictWord{11, 11, 262}, - dictWord{ - 11, - 11, - 352, - }, - dictWord{11, 11, 439}, - dictWord{11, 11, 493}, - dictWord{11, 11, 572}, - dictWord{11, 11, 591}, - dictWord{11, 11, 608}, - dictWord{11, 11, 611}, - dictWord{ - 11, - 11, - 646, - }, - dictWord{11, 11, 674}, - dictWord{11, 11, 711}, - dictWord{11, 11, 751}, - dictWord{11, 11, 761}, - dictWord{11, 11, 776}, - dictWord{11, 11, 785}, - dictWord{11, 11, 850}, - dictWord{11, 11, 853}, - dictWord{11, 11, 862}, - dictWord{11, 11, 865}, - dictWord{11, 11, 868}, - dictWord{11, 11, 898}, - dictWord{ - 11, - 11, - 902, - }, - dictWord{11, 11, 903}, - dictWord{11, 11, 910}, - dictWord{11, 11, 932}, - dictWord{11, 11, 942}, - dictWord{11, 11, 957}, - dictWord{11, 11, 967}, - dictWord{ - 11, - 11, - 972, - }, - dictWord{12, 11, 148}, - dictWord{12, 11, 195}, - dictWord{12, 11, 220}, - dictWord{12, 11, 237}, - dictWord{12, 11, 318}, - dictWord{12, 11, 339}, - dictWord{12, 11, 393}, - dictWord{12, 11, 445}, - dictWord{12, 11, 450}, - dictWord{12, 11, 474}, - dictWord{12, 11, 509}, - dictWord{12, 11, 533}, - dictWord{ - 12, - 11, - 591, - }, - dictWord{12, 11, 594}, - dictWord{12, 11, 597}, - dictWord{12, 11, 621}, - dictWord{12, 11, 633}, - dictWord{12, 11, 642}, - dictWord{13, 11, 59}, - dictWord{ - 13, - 11, - 60, - }, - dictWord{13, 11, 145}, - dictWord{13, 11, 239}, - dictWord{13, 11, 250}, - dictWord{13, 11, 273}, - dictWord{13, 11, 329}, - dictWord{13, 11, 344}, - dictWord{13, 11, 365}, - dictWord{13, 11, 372}, - dictWord{13, 11, 387}, - dictWord{13, 11, 403}, - dictWord{13, 11, 414}, - dictWord{13, 11, 456}, - dictWord{ - 13, - 11, - 478, - }, - dictWord{13, 11, 483}, - dictWord{13, 11, 489}, - dictWord{14, 11, 55}, - dictWord{14, 11, 57}, - dictWord{14, 11, 81}, - dictWord{14, 11, 90}, - dictWord{ - 14, - 11, - 148, - }, - dictWord{14, 11, 239}, - dictWord{14, 11, 266}, - dictWord{14, 11, 321}, - dictWord{14, 11, 326}, - dictWord{14, 11, 327}, - dictWord{14, 11, 330}, - dictWord{ - 14, - 11, - 347, - }, - dictWord{14, 11, 355}, - dictWord{14, 11, 401}, - dictWord{14, 11, 411}, - dictWord{14, 11, 414}, - dictWord{14, 11, 416}, - dictWord{14, 11, 420}, - dictWord{15, 11, 61}, - dictWord{15, 11, 74}, - dictWord{15, 11, 87}, - dictWord{15, 11, 88}, - dictWord{15, 11, 94}, - dictWord{15, 11, 96}, - dictWord{15, 11, 116}, - dictWord{15, 11, 149}, - dictWord{15, 11, 154}, - dictWord{16, 11, 50}, - dictWord{16, 11, 63}, - dictWord{16, 11, 73}, - dictWord{17, 11, 2}, - dictWord{17, 11, 66}, - dictWord{ - 17, - 11, - 92, - }, - dictWord{17, 11, 103}, - dictWord{17, 11, 112}, - dictWord{18, 11, 50}, - dictWord{18, 11, 54}, - dictWord{18, 11, 82}, - dictWord{18, 11, 86}, - dictWord{ - 18, - 11, - 90, - }, - dictWord{18, 11, 111}, - dictWord{18, 11, 115}, - dictWord{18, 11, 156}, - dictWord{19, 11, 40}, - dictWord{19, 11, 79}, - dictWord{20, 11, 78}, - dictWord{ - 149, - 11, - 22, - }, - dictWord{137, 11, 170}, - dictWord{134, 0, 1433}, - dictWord{135, 11, 1307}, - dictWord{139, 11, 411}, - dictWord{5, 0, 189}, - dictWord{7, 0, 442}, - dictWord{7, 0, 443}, - dictWord{8, 0, 281}, - dictWord{12, 0, 174}, - dictWord{141, 0, 261}, - dictWord{6, 10, 216}, - dictWord{7, 10, 901}, - dictWord{7, 10, 1343}, - dictWord{136, 10, 493}, - dictWord{5, 11, 397}, - dictWord{6, 11, 154}, - dictWord{7, 10, 341}, - dictWord{7, 11, 676}, - dictWord{8, 11, 443}, - dictWord{8, 11, 609}, - dictWord{ - 9, - 11, - 24, - }, - dictWord{9, 11, 325}, - dictWord{10, 11, 35}, - dictWord{11, 10, 219}, - dictWord{11, 11, 535}, - dictWord{11, 11, 672}, - dictWord{11, 11, 1018}, - dictWord{12, 11, 637}, - dictWord{144, 11, 30}, - dictWord{6, 0, 2}, - dictWord{7, 0, 191}, - dictWord{7, 0, 446}, - dictWord{7, 0, 1262}, - dictWord{7, 0, 1737}, - dictWord{8, 0, 22}, - dictWord{8, 0, 270}, - dictWord{8, 0, 612}, - dictWord{9, 0, 4}, - dictWord{9, 0, 312}, - dictWord{9, 0, 436}, - dictWord{9, 0, 626}, - dictWord{10, 0, 216}, - dictWord{10, 0, 311}, - dictWord{10, 0, 521}, - dictWord{10, 0, 623}, - dictWord{11, 0, 72}, - dictWord{11, 0, 330}, - dictWord{11, 0, 455}, - dictWord{12, 0, 321}, - dictWord{12, 0, 504}, - dictWord{12, 0, 530}, - dictWord{12, 0, 543}, - dictWord{13, 0, 17}, - dictWord{13, 0, 156}, - dictWord{13, 0, 334}, - dictWord{14, 0, 131}, - dictWord{17, 0, 60}, - dictWord{ - 148, - 0, - 64, - }, - dictWord{7, 0, 354}, - dictWord{10, 0, 410}, - dictWord{139, 0, 815}, - dictWord{139, 10, 130}, - dictWord{7, 10, 1734}, - dictWord{137, 11, 631}, - dictWord{ - 12, - 0, - 425, - }, - dictWord{15, 0, 112}, - dictWord{10, 10, 115}, - dictWord{11, 10, 420}, - dictWord{13, 10, 404}, - dictWord{14, 10, 346}, - dictWord{143, 10, 54}, - dictWord{ - 6, - 0, - 60, - }, - dictWord{6, 0, 166}, - dictWord{7, 0, 374}, - dictWord{7, 0, 670}, - dictWord{7, 0, 1327}, - dictWord{8, 0, 411}, - dictWord{8, 0, 435}, - dictWord{9, 0, 653}, - dictWord{ - 9, - 0, - 740, - }, - dictWord{10, 0, 385}, - dictWord{11, 0, 222}, - dictWord{11, 0, 324}, - dictWord{11, 0, 829}, - dictWord{140, 0, 611}, - dictWord{7, 0, 1611}, - dictWord{ - 13, - 0, - 14, - }, - dictWord{15, 0, 44}, - dictWord{19, 0, 13}, - dictWord{148, 0, 76}, - dictWord{133, 11, 981}, - dictWord{4, 11, 56}, - dictWord{7, 11, 1791}, - dictWord{8, 11, 607}, - dictWord{8, 11, 651}, - dictWord{11, 11, 465}, - dictWord{11, 11, 835}, - dictWord{12, 11, 337}, - dictWord{141, 11, 480}, - dictWord{6, 0, 1478}, - dictWord{ - 5, - 10, - 1011, - }, - dictWord{136, 10, 701}, - dictWord{139, 0, 596}, - dictWord{5, 0, 206}, - dictWord{134, 0, 398}, - dictWord{4, 10, 54}, - dictWord{5, 10, 666}, - dictWord{ - 7, - 10, - 1039, - }, - dictWord{7, 10, 1130}, - dictWord{9, 10, 195}, - dictWord{138, 10, 302}, - dictWord{7, 0, 50}, - dictWord{9, 11, 158}, - dictWord{138, 11, 411}, - dictWord{ - 135, - 11, - 1120, - }, - dictWord{6, 0, 517}, - dictWord{7, 0, 1159}, - dictWord{10, 0, 621}, - dictWord{11, 0, 192}, - dictWord{134, 10, 1669}, - dictWord{4, 0, 592}, - dictWord{ - 6, - 0, - 600, - }, - dictWord{135, 0, 1653}, - dictWord{10, 0, 223}, - dictWord{139, 0, 645}, - dictWord{136, 11, 139}, - dictWord{7, 0, 64}, - dictWord{136, 0, 245}, - dictWord{ - 142, - 0, - 278, - }, - dictWord{6, 11, 622}, - dictWord{135, 11, 1030}, - dictWord{136, 0, 604}, - dictWord{134, 0, 1502}, - dictWord{138, 0, 265}, - dictWord{ - 141, - 11, - 168, - }, - dictWord{7, 0, 1763}, - dictWord{140, 0, 310}, - dictWord{7, 10, 798}, - dictWord{139, 11, 719}, - dictWord{7, 11, 160}, - dictWord{10, 11, 624}, - dictWord{ - 142, - 11, - 279, - }, - dictWord{132, 11, 363}, - dictWord{7, 10, 122}, - dictWord{9, 10, 259}, - dictWord{10, 10, 84}, - dictWord{11, 10, 470}, - dictWord{12, 10, 541}, - dictWord{141, 10, 379}, - dictWord{5, 0, 129}, - dictWord{6, 0, 61}, - dictWord{135, 0, 947}, - dictWord{134, 0, 1356}, - dictWord{135, 11, 1191}, - dictWord{13, 0, 505}, - dictWord{141, 0, 506}, - dictWord{11, 0, 1000}, - dictWord{5, 10, 82}, - dictWord{5, 10, 131}, - dictWord{7, 10, 1755}, - dictWord{8, 10, 31}, - dictWord{9, 10, 168}, - dictWord{9, 10, 764}, - dictWord{139, 10, 869}, - dictWord{134, 0, 966}, - dictWord{134, 10, 605}, - dictWord{134, 11, 292}, - dictWord{5, 11, 177}, - dictWord{ - 6, - 11, - 616, - }, - dictWord{7, 11, 827}, - dictWord{9, 11, 525}, - dictWord{138, 11, 656}, - dictWord{135, 11, 1486}, - dictWord{138, 11, 31}, - dictWord{5, 10, 278}, - dictWord{137, 10, 68}, - dictWord{4, 10, 163}, - dictWord{5, 10, 201}, - dictWord{5, 10, 307}, - dictWord{5, 10, 310}, - dictWord{6, 10, 335}, - dictWord{7, 10, 284}, - dictWord{136, 10, 165}, - dictWord{6, 0, 839}, - dictWord{135, 10, 1660}, - dictWord{136, 10, 781}, - dictWord{6, 10, 33}, - dictWord{135, 10, 1244}, - dictWord{ - 133, - 0, - 637, - }, - dictWord{4, 11, 161}, - dictWord{133, 11, 631}, - dictWord{137, 0, 590}, - dictWord{7, 10, 1953}, - dictWord{136, 10, 720}, - dictWord{5, 0, 280}, - dictWord{ - 7, - 0, - 1226, - }, - dictWord{138, 10, 203}, - dictWord{134, 0, 1386}, - dictWord{5, 0, 281}, - dictWord{6, 0, 1026}, - dictWord{6, 10, 326}, - dictWord{7, 10, 677}, - dictWord{ - 137, - 10, - 425, - }, - dictWord{7, 11, 1557}, - dictWord{135, 11, 1684}, - dictWord{135, 0, 1064}, - dictWord{9, 11, 469}, - dictWord{9, 11, 709}, - dictWord{12, 11, 512}, - dictWord{14, 11, 65}, - dictWord{145, 11, 12}, - dictWord{134, 0, 917}, - dictWord{10, 11, 229}, - dictWord{11, 11, 73}, - dictWord{11, 11, 376}, - dictWord{ - 139, - 11, - 433, - }, - dictWord{7, 0, 555}, - dictWord{9, 0, 192}, - dictWord{13, 0, 30}, - dictWord{13, 0, 49}, - dictWord{15, 0, 150}, - dictWord{16, 0, 76}, - dictWord{20, 0, 52}, - dictWord{ - 7, - 10, - 1316, - }, - dictWord{7, 10, 1412}, - dictWord{7, 10, 1839}, - dictWord{9, 10, 589}, - dictWord{11, 10, 241}, - dictWord{11, 10, 676}, - dictWord{11, 10, 811}, - dictWord{11, 10, 891}, - dictWord{12, 10, 140}, - dictWord{12, 10, 346}, - dictWord{12, 10, 479}, - dictWord{13, 10, 381}, - dictWord{14, 10, 188}, - dictWord{ - 146, - 10, - 30, - }, - dictWord{149, 0, 15}, - dictWord{6, 0, 1882}, - dictWord{6, 0, 1883}, - dictWord{6, 0, 1897}, - dictWord{9, 0, 945}, - dictWord{9, 0, 1014}, - dictWord{9, 0, 1020}, - dictWord{12, 0, 823}, - dictWord{12, 0, 842}, - dictWord{12, 0, 866}, - dictWord{12, 0, 934}, - dictWord{15, 0, 242}, - dictWord{146, 0, 208}, - dictWord{6, 0, 965}, - dictWord{134, 0, 1499}, - dictWord{7, 0, 33}, - dictWord{7, 0, 120}, - dictWord{8, 0, 489}, - dictWord{9, 0, 319}, - dictWord{10, 0, 820}, - dictWord{11, 0, 1004}, - dictWord{ - 12, - 0, - 379, - }, - dictWord{12, 0, 679}, - dictWord{13, 0, 117}, - dictWord{13, 0, 412}, - dictWord{14, 0, 25}, - dictWord{15, 0, 52}, - dictWord{15, 0, 161}, - dictWord{16, 0, 47}, - dictWord{149, 0, 2}, - dictWord{6, 11, 558}, - dictWord{7, 11, 651}, - dictWord{8, 11, 421}, - dictWord{9, 11, 0}, - dictWord{138, 11, 34}, - dictWord{4, 0, 937}, - dictWord{ - 5, - 0, - 801, - }, - dictWord{7, 0, 473}, - dictWord{5, 10, 358}, - dictWord{7, 10, 1184}, - dictWord{10, 10, 662}, - dictWord{13, 10, 212}, - dictWord{13, 10, 304}, - dictWord{ - 13, - 10, - 333, - }, - dictWord{145, 10, 98}, - dictWord{132, 0, 877}, - dictWord{6, 0, 693}, - dictWord{134, 0, 824}, - dictWord{132, 0, 365}, - dictWord{7, 11, 1832}, - dictWord{ - 138, - 11, - 374, - }, - dictWord{5, 0, 7}, - dictWord{139, 0, 774}, - dictWord{4, 0, 734}, - dictWord{5, 0, 662}, - dictWord{134, 0, 430}, - dictWord{4, 0, 746}, - dictWord{ - 135, - 0, - 1090, - }, - dictWord{5, 0, 360}, - dictWord{8, 0, 237}, - dictWord{10, 0, 231}, - dictWord{147, 0, 124}, - dictWord{138, 11, 348}, - dictWord{6, 11, 6}, - dictWord{7, 11, 81}, - dictWord{7, 11, 771}, - dictWord{7, 11, 1731}, - dictWord{9, 11, 405}, - dictWord{138, 11, 421}, - dictWord{6, 0, 740}, - dictWord{137, 0, 822}, - dictWord{ - 133, - 10, - 946, - }, - dictWord{7, 0, 1485}, - dictWord{136, 0, 929}, - dictWord{7, 10, 411}, - dictWord{8, 10, 631}, - dictWord{9, 10, 323}, - dictWord{10, 10, 355}, - dictWord{ - 11, - 10, - 491, - }, - dictWord{12, 10, 143}, - dictWord{12, 10, 402}, - dictWord{13, 10, 73}, - dictWord{14, 10, 408}, - dictWord{15, 10, 107}, - dictWord{146, 10, 71}, - dictWord{ - 135, - 10, - 590, - }, - dictWord{5, 11, 881}, - dictWord{133, 11, 885}, - dictWord{150, 11, 25}, - dictWord{4, 0, 852}, - dictWord{5, 11, 142}, - dictWord{134, 11, 546}, - dictWord{7, 10, 1467}, - dictWord{8, 10, 328}, - dictWord{10, 10, 544}, - dictWord{11, 10, 955}, - dictWord{13, 10, 320}, - dictWord{145, 10, 83}, - dictWord{9, 0, 17}, - dictWord{10, 0, 291}, - dictWord{11, 10, 511}, - dictWord{13, 10, 394}, - dictWord{14, 10, 298}, - dictWord{14, 10, 318}, - dictWord{146, 10, 103}, - dictWord{5, 11, 466}, - dictWord{11, 11, 571}, - dictWord{12, 11, 198}, - dictWord{13, 11, 283}, - dictWord{14, 11, 186}, - dictWord{15, 11, 21}, - dictWord{143, 11, 103}, - dictWord{ - 134, - 0, - 1001, - }, - dictWord{4, 11, 185}, - dictWord{5, 11, 257}, - dictWord{5, 11, 839}, - dictWord{5, 11, 936}, - dictWord{7, 11, 171}, - dictWord{9, 11, 399}, - dictWord{ - 10, - 11, - 258, - }, - dictWord{10, 11, 395}, - dictWord{10, 11, 734}, - dictWord{11, 11, 1014}, - dictWord{12, 11, 23}, - dictWord{13, 11, 350}, - dictWord{14, 11, 150}, - dictWord{147, 11, 6}, - dictWord{143, 0, 35}, - dictWord{132, 0, 831}, - dictWord{5, 10, 835}, - dictWord{134, 10, 483}, - dictWord{4, 0, 277}, - dictWord{5, 0, 608}, - dictWord{ - 6, - 0, - 493, - }, - dictWord{7, 0, 457}, - dictWord{12, 0, 384}, - dictWord{7, 11, 404}, - dictWord{7, 11, 1377}, - dictWord{7, 11, 1430}, - dictWord{7, 11, 2017}, - dictWord{ - 8, - 11, - 149, - }, - dictWord{8, 11, 239}, - dictWord{8, 11, 512}, - dictWord{8, 11, 793}, - dictWord{8, 11, 818}, - dictWord{9, 11, 474}, - dictWord{9, 11, 595}, - dictWord{ - 10, - 11, - 122, - }, - dictWord{10, 11, 565}, - dictWord{10, 11, 649}, - dictWord{10, 11, 783}, - dictWord{11, 11, 239}, - dictWord{11, 11, 295}, - dictWord{11, 11, 447}, - dictWord{ - 11, - 11, - 528, - }, - dictWord{11, 11, 639}, - dictWord{11, 11, 800}, - dictWord{11, 11, 936}, - dictWord{12, 11, 25}, - dictWord{12, 11, 73}, - dictWord{12, 11, 77}, - dictWord{12, 11, 157}, - dictWord{12, 11, 316}, - dictWord{12, 11, 390}, - dictWord{12, 11, 391}, - dictWord{12, 11, 394}, - dictWord{12, 11, 395}, - dictWord{ - 12, - 11, - 478, - }, - dictWord{12, 11, 503}, - dictWord{12, 11, 592}, - dictWord{12, 11, 680}, - dictWord{13, 11, 50}, - dictWord{13, 11, 53}, - dictWord{13, 11, 132}, - dictWord{ - 13, - 11, - 198, - }, - dictWord{13, 11, 275}, - dictWord{13, 11, 322}, - dictWord{13, 11, 415}, - dictWord{14, 11, 71}, - dictWord{14, 11, 257}, - dictWord{14, 11, 395}, - dictWord{15, 11, 71}, - dictWord{15, 11, 136}, - dictWord{17, 11, 123}, - dictWord{18, 11, 93}, - dictWord{147, 11, 58}, - dictWord{134, 0, 1351}, - dictWord{7, 0, 27}, - dictWord{135, 0, 316}, - dictWord{136, 11, 712}, - dictWord{136, 0, 984}, - dictWord{133, 0, 552}, - dictWord{137, 0, 264}, - dictWord{132, 0, 401}, - dictWord{6, 0, 710}, - dictWord{6, 0, 1111}, - dictWord{134, 0, 1343}, - dictWord{134, 0, 1211}, - dictWord{9, 0, 543}, - dictWord{10, 0, 524}, - dictWord{11, 0, 108}, - dictWord{11, 0, 653}, - dictWord{12, 0, 524}, - dictWord{13, 0, 123}, - dictWord{14, 0, 252}, - dictWord{16, 0, 18}, - dictWord{19, 0, 38}, - dictWord{20, 0, 26}, - dictWord{20, 0, 65}, - dictWord{ - 21, - 0, - 3, - }, - dictWord{151, 0, 11}, - dictWord{4, 0, 205}, - dictWord{5, 0, 623}, - dictWord{7, 0, 104}, - dictWord{8, 0, 519}, - dictWord{137, 0, 716}, - dictWord{132, 10, 677}, - dictWord{4, 11, 377}, - dictWord{152, 11, 13}, - dictWord{135, 11, 1673}, - dictWord{7, 0, 579}, - dictWord{9, 0, 41}, - dictWord{9, 0, 244}, - dictWord{9, 0, 669}, - dictWord{ - 10, - 0, - 5, - }, - dictWord{11, 0, 861}, - dictWord{11, 0, 951}, - dictWord{139, 0, 980}, - dictWord{132, 0, 717}, - dictWord{136, 0, 1011}, - dictWord{132, 0, 805}, - dictWord{ - 4, - 11, - 180, - }, - dictWord{135, 11, 1906}, - dictWord{132, 10, 777}, - dictWord{132, 10, 331}, - dictWord{132, 0, 489}, - dictWord{6, 0, 1024}, - dictWord{4, 11, 491}, - dictWord{133, 10, 747}, - dictWord{135, 11, 1182}, - dictWord{4, 11, 171}, - dictWord{138, 11, 234}, - dictWord{4, 11, 586}, - dictWord{7, 11, 1186}, - dictWord{ - 138, - 11, - 631, - }, - dictWord{135, 0, 892}, - dictWord{135, 11, 336}, - dictWord{9, 11, 931}, - dictWord{10, 11, 334}, - dictWord{148, 11, 71}, - dictWord{137, 0, 473}, - dictWord{6, 0, 864}, - dictWord{12, 0, 659}, - dictWord{139, 11, 926}, - dictWord{7, 0, 819}, - dictWord{9, 0, 26}, - dictWord{9, 0, 392}, - dictWord{10, 0, 152}, - dictWord{ - 10, - 0, - 226, - }, - dictWord{11, 0, 19}, - dictWord{12, 0, 276}, - dictWord{12, 0, 426}, - dictWord{12, 0, 589}, - dictWord{13, 0, 460}, - dictWord{15, 0, 97}, - dictWord{19, 0, 48}, - dictWord{148, 0, 104}, - dictWord{135, 0, 51}, - dictWord{133, 10, 326}, - dictWord{4, 10, 691}, - dictWord{146, 10, 16}, - dictWord{9, 0, 130}, - dictWord{11, 0, 765}, - dictWord{10, 10, 680}, - dictWord{10, 10, 793}, - dictWord{141, 10, 357}, - dictWord{133, 11, 765}, - dictWord{8, 0, 229}, - dictWord{6, 10, 32}, - dictWord{7, 10, 385}, - dictWord{7, 10, 757}, - dictWord{7, 10, 1916}, - dictWord{8, 10, 94}, - dictWord{8, 10, 711}, - dictWord{9, 10, 541}, - dictWord{10, 10, 162}, - dictWord{10, 10, 795}, - dictWord{11, 10, 989}, - dictWord{11, 10, 1010}, - dictWord{12, 10, 14}, - dictWord{142, 10, 308}, - dictWord{7, 11, 474}, - dictWord{137, 11, 578}, - dictWord{ - 132, - 0, - 674, - }, - dictWord{132, 0, 770}, - dictWord{5, 0, 79}, - dictWord{7, 0, 1027}, - dictWord{7, 0, 1477}, - dictWord{139, 0, 52}, - dictWord{133, 11, 424}, - dictWord{ - 134, - 0, - 1666, - }, - dictWord{6, 0, 409}, - dictWord{6, 10, 349}, - dictWord{6, 10, 1682}, - dictWord{7, 10, 1252}, - dictWord{8, 10, 112}, - dictWord{8, 11, 714}, - dictWord{ - 9, - 10, - 435, - }, - dictWord{9, 10, 668}, - dictWord{10, 10, 290}, - dictWord{10, 10, 319}, - dictWord{10, 10, 815}, - dictWord{11, 10, 180}, - dictWord{11, 10, 837}, - dictWord{ - 12, - 10, - 240, - }, - dictWord{13, 10, 152}, - dictWord{13, 10, 219}, - dictWord{142, 10, 158}, - dictWord{5, 0, 789}, - dictWord{134, 0, 195}, - dictWord{4, 0, 251}, - dictWord{ - 4, - 0, - 688, - }, - dictWord{7, 0, 513}, - dictWord{135, 0, 1284}, - dictWord{132, 10, 581}, - dictWord{9, 11, 420}, - dictWord{10, 11, 269}, - dictWord{10, 11, 285}, - dictWord{10, 11, 576}, - dictWord{11, 11, 397}, - dictWord{13, 11, 175}, - dictWord{145, 11, 90}, - dictWord{6, 10, 126}, - dictWord{7, 10, 573}, - dictWord{8, 10, 397}, - dictWord{142, 10, 44}, - dictWord{132, 11, 429}, - dictWord{133, 0, 889}, - dictWord{4, 0, 160}, - dictWord{5, 0, 330}, - dictWord{7, 0, 1434}, - dictWord{136, 0, 174}, - dictWord{7, 11, 18}, - dictWord{7, 11, 699}, - dictWord{7, 11, 1966}, - dictWord{8, 11, 752}, - dictWord{9, 11, 273}, - dictWord{9, 11, 412}, - dictWord{9, 11, 703}, - dictWord{ - 10, - 11, - 71, - }, - dictWord{10, 11, 427}, - dictWord{10, 11, 508}, - dictWord{146, 11, 97}, - dictWord{6, 0, 872}, - dictWord{134, 0, 899}, - dictWord{133, 10, 926}, - dictWord{134, 0, 1126}, - dictWord{134, 0, 918}, - dictWord{4, 11, 53}, - dictWord{5, 11, 186}, - dictWord{135, 11, 752}, - dictWord{7, 0, 268}, - dictWord{136, 0, 569}, - dictWord{134, 0, 1224}, - dictWord{6, 0, 1361}, - dictWord{7, 10, 1232}, - dictWord{137, 10, 531}, - dictWord{8, 11, 575}, - dictWord{10, 11, 289}, - dictWord{ - 139, - 11, - 319, - }, - dictWord{133, 10, 670}, - dictWord{132, 11, 675}, - dictWord{133, 0, 374}, - dictWord{135, 10, 1957}, - dictWord{133, 0, 731}, - dictWord{11, 0, 190}, - dictWord{15, 0, 49}, - dictWord{11, 11, 190}, - dictWord{143, 11, 49}, - dictWord{4, 0, 626}, - dictWord{5, 0, 506}, - dictWord{5, 0, 642}, - dictWord{6, 0, 425}, - dictWord{ - 10, - 0, - 202, - }, - dictWord{139, 0, 141}, - dictWord{137, 0, 444}, - dictWord{7, 10, 242}, - dictWord{135, 10, 1942}, - dictWord{6, 11, 209}, - dictWord{8, 11, 468}, - dictWord{ - 9, - 11, - 210, - }, - dictWord{11, 11, 36}, - dictWord{12, 11, 28}, - dictWord{12, 11, 630}, - dictWord{13, 11, 21}, - dictWord{13, 11, 349}, - dictWord{14, 11, 7}, - dictWord{ - 145, - 11, - 13, - }, - dictWord{4, 11, 342}, - dictWord{135, 11, 1179}, - dictWord{5, 10, 834}, - dictWord{7, 10, 1202}, - dictWord{8, 10, 14}, - dictWord{9, 10, 481}, - dictWord{ - 137, - 10, - 880, - }, - dictWord{4, 11, 928}, - dictWord{133, 11, 910}, - dictWord{4, 11, 318}, - dictWord{4, 11, 496}, - dictWord{7, 11, 856}, - dictWord{139, 11, 654}, - dictWord{136, 0, 835}, - dictWord{7, 0, 1526}, - dictWord{138, 10, 465}, - dictWord{151, 0, 17}, - dictWord{135, 0, 477}, - dictWord{4, 10, 357}, - dictWord{6, 10, 172}, - dictWord{7, 10, 143}, - dictWord{137, 10, 413}, - dictWord{6, 0, 1374}, - dictWord{138, 0, 994}, - dictWord{18, 0, 76}, - dictWord{132, 10, 590}, - dictWord{7, 0, 287}, - dictWord{8, 0, 355}, - dictWord{9, 0, 293}, - dictWord{137, 0, 743}, - dictWord{134, 0, 1389}, - dictWord{7, 11, 915}, - dictWord{8, 11, 247}, - dictWord{147, 11, 0}, - dictWord{ - 4, - 11, - 202, - }, - dictWord{5, 11, 382}, - dictWord{6, 11, 454}, - dictWord{7, 11, 936}, - dictWord{7, 11, 1803}, - dictWord{8, 11, 758}, - dictWord{9, 11, 375}, - dictWord{ - 9, - 11, - 895, - }, - dictWord{10, 11, 743}, - dictWord{10, 11, 792}, - dictWord{11, 11, 978}, - dictWord{11, 11, 1012}, - dictWord{142, 11, 109}, - dictWord{5, 0, 384}, - dictWord{8, 0, 455}, - dictWord{140, 0, 48}, - dictWord{132, 11, 390}, - dictWord{5, 10, 169}, - dictWord{7, 10, 333}, - dictWord{136, 10, 45}, - dictWord{5, 0, 264}, - dictWord{134, 0, 184}, - dictWord{138, 11, 791}, - dictWord{133, 11, 717}, - dictWord{132, 10, 198}, - dictWord{6, 11, 445}, - dictWord{7, 11, 332}, - dictWord{ - 137, - 11, - 909, - }, - dictWord{136, 0, 1001}, - dictWord{4, 10, 24}, - dictWord{5, 10, 140}, - dictWord{5, 10, 185}, - dictWord{7, 10, 1500}, - dictWord{11, 10, 565}, - dictWord{ - 139, - 10, - 838, - }, - dictWord{134, 11, 578}, - dictWord{5, 0, 633}, - dictWord{6, 0, 28}, - dictWord{135, 0, 1323}, - dictWord{132, 0, 851}, - dictWord{136, 11, 267}, - dictWord{ - 7, - 0, - 359, - }, - dictWord{8, 0, 243}, - dictWord{140, 0, 175}, - dictWord{4, 10, 334}, - dictWord{133, 10, 593}, - dictWord{141, 11, 87}, - dictWord{136, 11, 766}, - dictWord{10, 0, 287}, - dictWord{12, 0, 138}, - dictWord{10, 11, 287}, - dictWord{140, 11, 138}, - dictWord{4, 0, 105}, - dictWord{132, 0, 740}, - dictWord{140, 10, 116}, - dictWord{134, 0, 857}, - dictWord{135, 11, 1841}, - dictWord{6, 0, 1402}, - dictWord{137, 0, 819}, - dictWord{132, 11, 584}, - dictWord{132, 10, 709}, - dictWord{ - 133, - 10, - 897, - }, - dictWord{5, 0, 224}, - dictWord{13, 0, 174}, - dictWord{146, 0, 52}, - dictWord{135, 10, 1840}, - dictWord{4, 10, 608}, - dictWord{133, 10, 497}, - dictWord{139, 11, 60}, - dictWord{4, 0, 758}, - dictWord{135, 0, 1649}, - dictWord{4, 11, 226}, - dictWord{4, 11, 326}, - dictWord{135, 11, 1770}, - dictWord{5, 11, 426}, - dictWord{8, 11, 30}, - dictWord{9, 11, 2}, - dictWord{11, 11, 549}, - dictWord{147, 11, 122}, - dictWord{135, 10, 2039}, - dictWord{6, 10, 540}, - dictWord{ - 136, - 10, - 136, - }, - dictWord{4, 0, 573}, - dictWord{8, 0, 655}, - dictWord{4, 10, 897}, - dictWord{133, 10, 786}, - dictWord{7, 0, 351}, - dictWord{139, 0, 128}, - dictWord{ - 133, - 10, - 999, - }, - dictWord{4, 10, 299}, - dictWord{135, 10, 1004}, - dictWord{133, 0, 918}, - dictWord{132, 11, 345}, - dictWord{4, 11, 385}, - dictWord{7, 11, 265}, - dictWord{135, 11, 587}, - dictWord{133, 10, 456}, - dictWord{136, 10, 180}, - dictWord{6, 0, 687}, - dictWord{134, 0, 1537}, - dictWord{4, 11, 347}, - dictWord{ - 5, - 11, - 423, - }, - dictWord{5, 11, 996}, - dictWord{135, 11, 1329}, - dictWord{132, 10, 755}, - dictWord{7, 11, 1259}, - dictWord{9, 11, 125}, - dictWord{11, 11, 65}, - dictWord{140, 11, 285}, - dictWord{5, 11, 136}, - dictWord{6, 11, 136}, - dictWord{136, 11, 644}, - dictWord{134, 0, 1525}, - dictWord{4, 0, 1009}, - dictWord{ - 135, - 0, - 1139, - }, - dictWord{139, 10, 338}, - dictWord{132, 0, 340}, - dictWord{135, 10, 1464}, - dictWord{8, 0, 847}, - dictWord{10, 0, 861}, - dictWord{10, 0, 876}, - dictWord{ - 10, - 0, - 889, - }, - dictWord{10, 0, 922}, - dictWord{10, 0, 929}, - dictWord{10, 0, 933}, - dictWord{12, 0, 784}, - dictWord{140, 0, 791}, - dictWord{139, 0, 176}, - dictWord{ - 9, - 11, - 134, - }, - dictWord{10, 11, 2}, - dictWord{10, 11, 27}, - dictWord{10, 11, 333}, - dictWord{11, 11, 722}, - dictWord{143, 11, 1}, - dictWord{4, 11, 433}, - dictWord{ - 133, - 11, - 719, - }, - dictWord{5, 0, 985}, - dictWord{7, 0, 509}, - dictWord{7, 0, 529}, - dictWord{145, 0, 96}, - dictWord{132, 0, 615}, - dictWord{4, 10, 890}, - dictWord{ - 5, - 10, - 805, - }, - dictWord{5, 10, 819}, - dictWord{5, 10, 961}, - dictWord{6, 10, 396}, - dictWord{6, 10, 1631}, - dictWord{6, 10, 1678}, - dictWord{7, 10, 1967}, - dictWord{ - 7, - 10, - 2041, - }, - dictWord{9, 10, 630}, - dictWord{11, 10, 8}, - dictWord{11, 10, 1019}, - dictWord{12, 10, 176}, - dictWord{13, 10, 225}, - dictWord{14, 10, 292}, - dictWord{ - 149, - 10, - 24, - }, - dictWord{135, 0, 1919}, - dictWord{134, 0, 1131}, - dictWord{144, 11, 21}, - dictWord{144, 11, 51}, - dictWord{135, 10, 1815}, - dictWord{4, 0, 247}, - dictWord{7, 10, 1505}, - dictWord{10, 10, 190}, - dictWord{10, 10, 634}, - dictWord{11, 10, 792}, - dictWord{12, 10, 358}, - dictWord{140, 10, 447}, - dictWord{ - 5, - 10, - 0, - }, - dictWord{6, 10, 536}, - dictWord{7, 10, 604}, - dictWord{13, 10, 445}, - dictWord{145, 10, 126}, - dictWord{4, 0, 184}, - dictWord{5, 0, 390}, - dictWord{6, 0, 337}, - dictWord{7, 0, 23}, - dictWord{7, 0, 494}, - dictWord{7, 0, 618}, - dictWord{7, 0, 1456}, - dictWord{8, 0, 27}, - dictWord{8, 0, 599}, - dictWord{10, 0, 153}, - dictWord{ - 139, - 0, - 710, - }, - dictWord{6, 10, 232}, - dictWord{6, 10, 412}, - dictWord{7, 10, 1074}, - dictWord{8, 10, 9}, - dictWord{8, 10, 157}, - dictWord{8, 10, 786}, - dictWord{9, 10, 196}, - dictWord{9, 10, 352}, - dictWord{9, 10, 457}, - dictWord{10, 10, 337}, - dictWord{11, 10, 232}, - dictWord{11, 10, 877}, - dictWord{12, 10, 480}, - dictWord{ - 140, - 10, - 546, - }, - dictWord{13, 0, 38}, - dictWord{135, 10, 958}, - dictWord{4, 10, 382}, - dictWord{136, 10, 579}, - dictWord{4, 10, 212}, - dictWord{135, 10, 1206}, - dictWord{ - 4, - 11, - 555, - }, - dictWord{8, 11, 536}, - dictWord{138, 11, 288}, - dictWord{11, 11, 139}, - dictWord{139, 11, 171}, - dictWord{9, 11, 370}, - dictWord{138, 11, 90}, - dictWord{132, 0, 1015}, - dictWord{134, 0, 1088}, - dictWord{5, 10, 655}, - dictWord{135, 11, 977}, - dictWord{134, 0, 1585}, - dictWord{17, 10, 67}, - dictWord{ - 147, - 10, - 74, - }, - dictWord{10, 0, 227}, - dictWord{11, 0, 497}, - dictWord{11, 0, 709}, - dictWord{140, 0, 415}, - dictWord{6, 0, 360}, - dictWord{7, 0, 1664}, - dictWord{ - 136, - 0, - 478, - }, - dictWord{7, 0, 95}, - dictWord{6, 10, 231}, - dictWord{136, 10, 423}, - dictWord{140, 11, 65}, - dictWord{4, 11, 257}, - dictWord{135, 11, 2031}, - dictWord{ - 135, - 11, - 1768, - }, - dictWord{133, 10, 300}, - dictWord{139, 11, 211}, - dictWord{136, 0, 699}, - dictWord{6, 10, 237}, - dictWord{7, 10, 611}, - dictWord{8, 10, 100}, - dictWord{9, 10, 416}, - dictWord{11, 10, 335}, - dictWord{12, 10, 173}, - dictWord{146, 10, 101}, - dictWord{14, 0, 26}, - dictWord{146, 0, 150}, - dictWord{6, 0, 581}, - dictWord{135, 0, 1119}, - dictWord{135, 10, 1208}, - dictWord{132, 0, 739}, - dictWord{6, 11, 83}, - dictWord{6, 11, 1733}, - dictWord{135, 11, 1389}, - dictWord{ - 137, - 0, - 869, - }, - dictWord{4, 0, 67}, - dictWord{5, 0, 422}, - dictWord{7, 0, 1037}, - dictWord{7, 0, 1289}, - dictWord{7, 0, 1555}, - dictWord{9, 0, 741}, - dictWord{145, 0, 108}, - dictWord{133, 10, 199}, - dictWord{12, 10, 427}, - dictWord{146, 10, 38}, - dictWord{136, 0, 464}, - dictWord{142, 0, 42}, - dictWord{10, 0, 96}, - dictWord{8, 11, 501}, - dictWord{137, 11, 696}, - dictWord{134, 11, 592}, - dictWord{4, 0, 512}, - dictWord{4, 0, 966}, - dictWord{5, 0, 342}, - dictWord{6, 0, 1855}, - dictWord{8, 0, 869}, - dictWord{8, 0, 875}, - dictWord{8, 0, 901}, - dictWord{144, 0, 26}, - dictWord{8, 0, 203}, - dictWord{11, 0, 823}, - dictWord{11, 0, 846}, - dictWord{12, 0, 482}, - dictWord{ - 13, - 0, - 277, - }, - dictWord{13, 0, 302}, - dictWord{13, 0, 464}, - dictWord{14, 0, 205}, - dictWord{142, 0, 221}, - dictWord{4, 0, 449}, - dictWord{133, 0, 718}, - dictWord{ - 7, - 11, - 1718, - }, - dictWord{9, 11, 95}, - dictWord{9, 11, 274}, - dictWord{10, 11, 279}, - dictWord{10, 11, 317}, - dictWord{10, 11, 420}, - dictWord{11, 11, 303}, - dictWord{ - 11, - 11, - 808, - }, - dictWord{12, 11, 134}, - dictWord{12, 11, 367}, - dictWord{13, 11, 149}, - dictWord{13, 11, 347}, - dictWord{14, 11, 349}, - dictWord{14, 11, 406}, - dictWord{18, 11, 22}, - dictWord{18, 11, 89}, - dictWord{18, 11, 122}, - dictWord{147, 11, 47}, - dictWord{133, 11, 26}, - dictWord{4, 0, 355}, - dictWord{6, 0, 311}, - dictWord{ - 9, - 0, - 256, - }, - dictWord{138, 0, 404}, - dictWord{132, 11, 550}, - dictWord{10, 0, 758}, - dictWord{6, 10, 312}, - dictWord{6, 10, 1715}, - dictWord{10, 10, 584}, - dictWord{11, 10, 546}, - dictWord{11, 10, 692}, - dictWord{12, 10, 259}, - dictWord{12, 10, 295}, - dictWord{13, 10, 46}, - dictWord{141, 10, 154}, - dictWord{ - 136, - 11, - 822, - }, - dictWord{5, 0, 827}, - dictWord{4, 11, 902}, - dictWord{5, 11, 809}, - dictWord{6, 11, 122}, - dictWord{135, 11, 896}, - dictWord{5, 0, 64}, - dictWord{140, 0, 581}, - dictWord{4, 0, 442}, - dictWord{6, 0, 739}, - dictWord{7, 0, 1047}, - dictWord{7, 0, 1352}, - dictWord{7, 0, 1643}, - dictWord{7, 11, 1911}, - dictWord{9, 11, 449}, - dictWord{10, 11, 192}, - dictWord{138, 11, 740}, - dictWord{135, 11, 262}, - dictWord{132, 10, 588}, - dictWord{133, 11, 620}, - dictWord{5, 0, 977}, - dictWord{ - 6, - 0, - 288, - }, - dictWord{7, 0, 528}, - dictWord{4, 11, 34}, - dictWord{5, 11, 574}, - dictWord{7, 11, 279}, - dictWord{7, 11, 1624}, - dictWord{136, 11, 601}, - dictWord{ - 6, - 0, - 1375, - }, - dictWord{4, 10, 231}, - dictWord{5, 10, 61}, - dictWord{6, 10, 104}, - dictWord{7, 10, 729}, - dictWord{7, 10, 964}, - dictWord{7, 10, 1658}, - dictWord{ - 140, - 10, - 414, - }, - dictWord{6, 10, 263}, - dictWord{138, 10, 757}, - dictWord{132, 10, 320}, - dictWord{4, 0, 254}, - dictWord{7, 0, 1309}, - dictWord{5, 11, 332}, - dictWord{ - 135, - 11, - 1309, - }, - dictWord{6, 11, 261}, - dictWord{8, 11, 182}, - dictWord{139, 11, 943}, - dictWord{132, 10, 225}, - dictWord{6, 0, 12}, - dictWord{135, 0, 1219}, - dictWord{4, 0, 275}, - dictWord{12, 0, 376}, - dictWord{6, 11, 1721}, - dictWord{141, 11, 490}, - dictWord{4, 11, 933}, - dictWord{133, 11, 880}, - dictWord{6, 0, 951}, - dictWord{6, 0, 1109}, - dictWord{6, 0, 1181}, - dictWord{7, 0, 154}, - dictWord{4, 10, 405}, - dictWord{7, 10, 817}, - dictWord{14, 10, 58}, - dictWord{17, 10, 37}, - dictWord{ - 146, - 10, - 124, - }, - dictWord{6, 0, 1520}, - dictWord{133, 10, 974}, - dictWord{134, 0, 1753}, - dictWord{6, 0, 369}, - dictWord{6, 0, 502}, - dictWord{7, 0, 1036}, - dictWord{ - 8, - 0, - 348, - }, - dictWord{9, 0, 452}, - dictWord{10, 0, 26}, - dictWord{11, 0, 224}, - dictWord{11, 0, 387}, - dictWord{11, 0, 772}, - dictWord{12, 0, 95}, - dictWord{12, 0, 629}, - dictWord{13, 0, 195}, - dictWord{13, 0, 207}, - dictWord{13, 0, 241}, - dictWord{14, 0, 260}, - dictWord{14, 0, 270}, - dictWord{143, 0, 140}, - dictWord{132, 0, 269}, - dictWord{5, 0, 480}, - dictWord{7, 0, 532}, - dictWord{7, 0, 1197}, - dictWord{7, 0, 1358}, - dictWord{8, 0, 291}, - dictWord{11, 0, 349}, - dictWord{142, 0, 396}, - dictWord{ - 5, - 10, - 235, - }, - dictWord{7, 10, 1239}, - dictWord{11, 10, 131}, - dictWord{140, 10, 370}, - dictWord{7, 10, 956}, - dictWord{7, 10, 1157}, - dictWord{7, 10, 1506}, - dictWord{ - 7, - 10, - 1606, - }, - dictWord{7, 10, 1615}, - dictWord{7, 10, 1619}, - dictWord{7, 10, 1736}, - dictWord{7, 10, 1775}, - dictWord{8, 10, 590}, - dictWord{9, 10, 324}, - dictWord{9, 10, 736}, - dictWord{9, 10, 774}, - dictWord{9, 10, 776}, - dictWord{9, 10, 784}, - dictWord{10, 10, 567}, - dictWord{10, 10, 708}, - dictWord{11, 10, 518}, - dictWord{11, 10, 613}, - dictWord{11, 10, 695}, - dictWord{11, 10, 716}, - dictWord{11, 10, 739}, - dictWord{11, 10, 770}, - dictWord{11, 10, 771}, - dictWord{ - 11, - 10, - 848, - }, - dictWord{11, 10, 857}, - dictWord{11, 10, 931}, - dictWord{11, 10, 947}, - dictWord{12, 10, 326}, - dictWord{12, 10, 387}, - dictWord{12, 10, 484}, - dictWord{ - 12, - 10, - 528, - }, - dictWord{12, 10, 552}, - dictWord{12, 10, 613}, - dictWord{13, 10, 189}, - dictWord{13, 10, 256}, - dictWord{13, 10, 340}, - dictWord{13, 10, 432}, - dictWord{13, 10, 436}, - dictWord{13, 10, 440}, - dictWord{13, 10, 454}, - dictWord{14, 10, 174}, - dictWord{14, 10, 220}, - dictWord{14, 10, 284}, - dictWord{ - 14, - 10, - 390, - }, - dictWord{145, 10, 121}, - dictWord{8, 11, 598}, - dictWord{9, 11, 664}, - dictWord{138, 11, 441}, - dictWord{9, 10, 137}, - dictWord{138, 10, 221}, - dictWord{133, 11, 812}, - dictWord{148, 0, 15}, - dictWord{134, 0, 1341}, - dictWord{6, 0, 1017}, - dictWord{4, 11, 137}, - dictWord{7, 11, 1178}, - dictWord{ - 135, - 11, - 1520, - }, - dictWord{7, 10, 390}, - dictWord{138, 10, 140}, - dictWord{7, 11, 1260}, - dictWord{135, 11, 1790}, - dictWord{137, 11, 191}, - dictWord{ - 135, - 10, - 1144, - }, - dictWord{6, 0, 1810}, - dictWord{7, 0, 657}, - dictWord{8, 0, 886}, - dictWord{10, 0, 857}, - dictWord{14, 0, 440}, - dictWord{144, 0, 96}, - dictWord{8, 0, 533}, - dictWord{6, 11, 1661}, - dictWord{7, 11, 1975}, - dictWord{7, 11, 2009}, - dictWord{135, 11, 2011}, - dictWord{6, 0, 1453}, - dictWord{134, 10, 464}, - dictWord{ - 132, - 11, - 715, - }, - dictWord{5, 10, 407}, - dictWord{11, 10, 204}, - dictWord{11, 10, 243}, - dictWord{11, 10, 489}, - dictWord{12, 10, 293}, - dictWord{19, 10, 37}, - dictWord{20, 10, 73}, - dictWord{150, 10, 38}, - dictWord{133, 11, 703}, - dictWord{4, 0, 211}, - dictWord{7, 0, 1483}, - dictWord{5, 10, 325}, - dictWord{8, 10, 5}, - dictWord{ - 8, - 10, - 227, - }, - dictWord{9, 10, 105}, - dictWord{10, 10, 585}, - dictWord{140, 10, 614}, - dictWord{4, 0, 332}, - dictWord{5, 0, 335}, - dictWord{6, 0, 238}, - dictWord{ - 7, - 0, - 269, - }, - dictWord{7, 0, 811}, - dictWord{7, 0, 1797}, - dictWord{8, 0, 836}, - dictWord{9, 0, 507}, - dictWord{141, 0, 242}, - dictWord{5, 11, 89}, - dictWord{7, 11, 1915}, - dictWord{9, 11, 185}, - dictWord{9, 11, 235}, - dictWord{9, 11, 496}, - dictWord{10, 11, 64}, - dictWord{10, 11, 270}, - dictWord{10, 11, 403}, - dictWord{10, 11, 469}, - dictWord{10, 11, 529}, - dictWord{10, 11, 590}, - dictWord{11, 11, 140}, - dictWord{11, 11, 860}, - dictWord{13, 11, 1}, - dictWord{13, 11, 422}, - dictWord{14, 11, 341}, - dictWord{14, 11, 364}, - dictWord{17, 11, 93}, - dictWord{18, 11, 113}, - dictWord{19, 11, 97}, - dictWord{147, 11, 113}, - dictWord{133, 11, 695}, - dictWord{ - 16, - 0, - 19, - }, - dictWord{5, 11, 6}, - dictWord{6, 11, 183}, - dictWord{6, 10, 621}, - dictWord{7, 11, 680}, - dictWord{7, 11, 978}, - dictWord{7, 11, 1013}, - dictWord{7, 11, 1055}, - dictWord{12, 11, 230}, - dictWord{13, 11, 172}, - dictWord{13, 10, 504}, - dictWord{146, 11, 29}, - dictWord{136, 0, 156}, - dictWord{133, 0, 1009}, - dictWord{ - 6, - 11, - 29, - }, - dictWord{139, 11, 63}, - dictWord{134, 0, 820}, - dictWord{134, 10, 218}, - dictWord{7, 10, 454}, - dictWord{7, 10, 782}, - dictWord{8, 10, 768}, - dictWord{ - 140, - 10, - 686, - }, - dictWord{5, 0, 228}, - dictWord{6, 0, 203}, - dictWord{7, 0, 156}, - dictWord{8, 0, 347}, - dictWord{9, 0, 265}, - dictWord{18, 0, 39}, - dictWord{20, 0, 54}, - dictWord{21, 0, 31}, - dictWord{22, 0, 3}, - dictWord{23, 0, 0}, - dictWord{15, 11, 8}, - dictWord{18, 11, 39}, - dictWord{20, 11, 54}, - dictWord{21, 11, 31}, - dictWord{22, 11, 3}, - dictWord{151, 11, 0}, - dictWord{7, 0, 1131}, - dictWord{135, 0, 1468}, - dictWord{144, 10, 0}, - dictWord{134, 0, 1276}, - dictWord{10, 10, 676}, - dictWord{ - 140, - 10, - 462, - }, - dictWord{132, 11, 311}, - dictWord{134, 11, 1740}, - dictWord{7, 11, 170}, - dictWord{8, 11, 90}, - dictWord{8, 11, 177}, - dictWord{8, 11, 415}, - dictWord{ - 11, - 11, - 714, - }, - dictWord{142, 11, 281}, - dictWord{134, 10, 164}, - dictWord{6, 0, 1792}, - dictWord{138, 0, 849}, - dictWord{150, 10, 50}, - dictWord{5, 0, 291}, - dictWord{5, 0, 318}, - dictWord{7, 0, 765}, - dictWord{9, 0, 389}, - dictWord{12, 0, 548}, - dictWord{8, 11, 522}, - dictWord{142, 11, 328}, - dictWord{11, 11, 91}, - dictWord{ - 13, - 11, - 129, - }, - dictWord{15, 11, 101}, - dictWord{145, 11, 125}, - dictWord{4, 11, 494}, - dictWord{6, 11, 74}, - dictWord{7, 11, 44}, - dictWord{7, 11, 407}, - dictWord{ - 8, - 11, - 551, - }, - dictWord{12, 11, 17}, - dictWord{15, 11, 5}, - dictWord{148, 11, 11}, - dictWord{4, 11, 276}, - dictWord{133, 11, 296}, - dictWord{6, 10, 343}, - dictWord{ - 7, - 10, - 195, - }, - dictWord{7, 11, 1777}, - dictWord{9, 10, 226}, - dictWord{10, 10, 197}, - dictWord{10, 10, 575}, - dictWord{11, 10, 502}, - dictWord{139, 10, 899}, - dictWord{ - 10, - 0, - 525, - }, - dictWord{139, 0, 82}, - dictWord{14, 0, 453}, - dictWord{4, 11, 7}, - dictWord{5, 11, 90}, - dictWord{5, 11, 158}, - dictWord{6, 11, 542}, - dictWord{7, 11, 221}, - dictWord{7, 11, 1574}, - dictWord{9, 11, 490}, - dictWord{10, 11, 540}, - dictWord{11, 11, 443}, - dictWord{139, 11, 757}, - dictWord{135, 0, 666}, - dictWord{ - 22, - 10, - 29, - }, - dictWord{150, 11, 29}, - dictWord{4, 0, 422}, - dictWord{147, 10, 8}, - dictWord{5, 0, 355}, - dictWord{145, 0, 0}, - dictWord{6, 0, 1873}, - dictWord{9, 0, 918}, - dictWord{7, 11, 588}, - dictWord{9, 11, 175}, - dictWord{138, 11, 530}, - dictWord{143, 11, 31}, - dictWord{11, 0, 165}, - dictWord{7, 10, 1125}, - dictWord{9, 10, 143}, - dictWord{14, 10, 405}, - dictWord{150, 10, 21}, - dictWord{9, 0, 260}, - dictWord{137, 0, 905}, - dictWord{5, 11, 872}, - dictWord{6, 11, 57}, - dictWord{6, 11, 479}, - dictWord{ - 6, - 11, - 562, - }, - dictWord{7, 11, 471}, - dictWord{7, 11, 1060}, - dictWord{9, 11, 447}, - dictWord{9, 11, 454}, - dictWord{141, 11, 6}, - dictWord{138, 11, 704}, - dictWord{133, 0, 865}, - dictWord{5, 0, 914}, - dictWord{134, 0, 1625}, - dictWord{133, 0, 234}, - dictWord{7, 0, 1383}, - dictWord{5, 11, 31}, - dictWord{6, 11, 614}, - dictWord{145, 11, 61}, - dictWord{7, 11, 1200}, - dictWord{138, 11, 460}, - dictWord{6, 11, 424}, - dictWord{135, 11, 1866}, - dictWord{136, 0, 306}, - dictWord{ - 5, - 10, - 959, - }, - dictWord{12, 11, 30}, - dictWord{13, 11, 148}, - dictWord{14, 11, 87}, - dictWord{14, 11, 182}, - dictWord{16, 11, 42}, - dictWord{18, 11, 92}, - dictWord{ - 148, - 11, - 70, - }, - dictWord{6, 0, 1919}, - dictWord{6, 0, 1921}, - dictWord{9, 0, 923}, - dictWord{9, 0, 930}, - dictWord{9, 0, 941}, - dictWord{9, 0, 949}, - dictWord{9, 0, 987}, - dictWord{ - 9, - 0, - 988, - }, - dictWord{9, 0, 992}, - dictWord{12, 0, 802}, - dictWord{12, 0, 815}, - dictWord{12, 0, 856}, - dictWord{12, 0, 885}, - dictWord{12, 0, 893}, - dictWord{ - 12, - 0, - 898, - }, - dictWord{12, 0, 919}, - dictWord{12, 0, 920}, - dictWord{12, 0, 941}, - dictWord{12, 0, 947}, - dictWord{15, 0, 183}, - dictWord{15, 0, 185}, - dictWord{15, 0, 189}, - dictWord{15, 0, 197}, - dictWord{15, 0, 202}, - dictWord{15, 0, 233}, - dictWord{18, 0, 218}, - dictWord{18, 0, 219}, - dictWord{18, 0, 233}, - dictWord{143, 11, 156}, - dictWord{135, 10, 1759}, - dictWord{136, 10, 173}, - dictWord{13, 0, 163}, - dictWord{13, 0, 180}, - dictWord{18, 0, 78}, - dictWord{20, 0, 35}, - dictWord{5, 11, 13}, - dictWord{134, 11, 142}, - dictWord{134, 10, 266}, - dictWord{6, 11, 97}, - dictWord{7, 11, 116}, - dictWord{8, 11, 322}, - dictWord{8, 11, 755}, - dictWord{9, 11, 548}, - dictWord{10, 11, 714}, - dictWord{11, 11, 884}, - dictWord{141, 11, 324}, - dictWord{135, 0, 1312}, - dictWord{9, 0, 814}, - dictWord{137, 11, 676}, - dictWord{ - 133, - 0, - 707, - }, - dictWord{135, 0, 1493}, - dictWord{6, 0, 421}, - dictWord{7, 0, 61}, - dictWord{7, 0, 1540}, - dictWord{10, 0, 11}, - dictWord{138, 0, 501}, - dictWord{12, 0, 733}, - dictWord{12, 0, 766}, - dictWord{7, 11, 866}, - dictWord{135, 11, 1163}, - dictWord{137, 0, 341}, - dictWord{142, 0, 98}, - dictWord{145, 11, 115}, - dictWord{ - 135, - 11, - 1111, - }, - dictWord{136, 10, 300}, - dictWord{136, 0, 1014}, - dictWord{8, 11, 1}, - dictWord{9, 11, 112}, - dictWord{138, 11, 326}, - dictWord{132, 11, 730}, - dictWord{5, 11, 488}, - dictWord{6, 11, 527}, - dictWord{7, 11, 489}, - dictWord{7, 11, 1636}, - dictWord{8, 11, 121}, - dictWord{8, 11, 144}, - dictWord{8, 11, 359}, - dictWord{ - 9, - 11, - 193, - }, - dictWord{9, 11, 241}, - dictWord{9, 11, 336}, - dictWord{9, 11, 882}, - dictWord{11, 11, 266}, - dictWord{11, 11, 372}, - dictWord{11, 11, 944}, - dictWord{ - 12, - 11, - 401, - }, - dictWord{140, 11, 641}, - dictWord{6, 0, 971}, - dictWord{134, 0, 1121}, - dictWord{6, 0, 102}, - dictWord{7, 0, 72}, - dictWord{15, 0, 142}, - dictWord{ - 147, - 0, - 67, - }, - dictWord{151, 0, 30}, - dictWord{135, 0, 823}, - dictWord{134, 0, 1045}, - dictWord{5, 10, 427}, - dictWord{5, 10, 734}, - dictWord{7, 10, 478}, - dictWord{ - 136, - 10, - 52, - }, - dictWord{7, 0, 1930}, - dictWord{11, 10, 217}, - dictWord{142, 10, 165}, - dictWord{6, 0, 1512}, - dictWord{135, 0, 1870}, - dictWord{9, 11, 31}, - dictWord{ - 10, - 11, - 244, - }, - dictWord{10, 11, 699}, - dictWord{12, 11, 149}, - dictWord{141, 11, 497}, - dictWord{133, 11, 377}, - dictWord{145, 11, 101}, - dictWord{ - 10, - 11, - 158, - }, - dictWord{13, 11, 13}, - dictWord{13, 11, 137}, - dictWord{13, 11, 258}, - dictWord{14, 11, 111}, - dictWord{14, 11, 225}, - dictWord{14, 11, 253}, - dictWord{ - 14, - 11, - 304, - }, - dictWord{14, 11, 339}, - dictWord{14, 11, 417}, - dictWord{146, 11, 33}, - dictWord{6, 0, 87}, - dictWord{6, 10, 1734}, - dictWord{7, 10, 20}, - dictWord{ - 7, - 10, - 1056, - }, - dictWord{8, 10, 732}, - dictWord{9, 10, 406}, - dictWord{9, 10, 911}, - dictWord{138, 10, 694}, - dictWord{134, 0, 1243}, - dictWord{137, 0, 245}, - dictWord{ - 7, - 0, - 68, - }, - dictWord{8, 0, 48}, - dictWord{8, 0, 88}, - dictWord{8, 0, 582}, - dictWord{8, 0, 681}, - dictWord{9, 0, 373}, - dictWord{9, 0, 864}, - dictWord{11, 0, 157}, - dictWord{ - 11, - 0, - 336, - }, - dictWord{11, 0, 843}, - dictWord{148, 0, 27}, - dictWord{8, 11, 663}, - dictWord{144, 11, 8}, - dictWord{133, 10, 613}, - dictWord{4, 0, 88}, - dictWord{ - 5, - 0, - 137, - }, - dictWord{5, 0, 174}, - dictWord{5, 0, 777}, - dictWord{6, 0, 1664}, - dictWord{6, 0, 1725}, - dictWord{7, 0, 77}, - dictWord{7, 0, 426}, - dictWord{7, 0, 1317}, - dictWord{ - 7, - 0, - 1355, - }, - dictWord{8, 0, 126}, - dictWord{8, 0, 563}, - dictWord{9, 0, 523}, - dictWord{9, 0, 750}, - dictWord{10, 0, 310}, - dictWord{10, 0, 836}, - dictWord{11, 0, 42}, - dictWord{11, 0, 318}, - dictWord{11, 0, 731}, - dictWord{12, 0, 68}, - dictWord{12, 0, 92}, - dictWord{12, 0, 507}, - dictWord{12, 0, 692}, - dictWord{13, 0, 81}, - dictWord{ - 13, - 0, - 238, - }, - dictWord{13, 0, 374}, - dictWord{14, 0, 436}, - dictWord{18, 0, 138}, - dictWord{19, 0, 78}, - dictWord{19, 0, 111}, - dictWord{20, 0, 55}, - dictWord{20, 0, 77}, - dictWord{148, 0, 92}, - dictWord{141, 0, 418}, - dictWord{4, 0, 938}, - dictWord{137, 0, 625}, - dictWord{138, 0, 351}, - dictWord{5, 11, 843}, - dictWord{7, 10, 32}, - dictWord{ - 7, - 10, - 984, - }, - dictWord{8, 10, 85}, - dictWord{8, 10, 709}, - dictWord{9, 10, 579}, - dictWord{9, 10, 847}, - dictWord{9, 10, 856}, - dictWord{10, 10, 799}, - dictWord{ - 11, - 10, - 258, - }, - dictWord{11, 10, 1007}, - dictWord{12, 10, 331}, - dictWord{12, 10, 615}, - dictWord{13, 10, 188}, - dictWord{13, 10, 435}, - dictWord{14, 10, 8}, - dictWord{ - 15, - 10, - 165, - }, - dictWord{16, 10, 27}, - dictWord{148, 10, 40}, - dictWord{6, 0, 1668}, - dictWord{7, 0, 1499}, - dictWord{8, 0, 117}, - dictWord{9, 0, 314}, - dictWord{ - 138, - 0, - 174, - }, - dictWord{135, 0, 707}, - dictWord{132, 11, 554}, - dictWord{133, 11, 536}, - dictWord{5, 0, 403}, - dictWord{5, 11, 207}, - dictWord{9, 11, 79}, - dictWord{ - 11, - 11, - 625, - }, - dictWord{145, 11, 7}, - dictWord{132, 11, 424}, - dictWord{136, 11, 785}, - dictWord{4, 10, 167}, - dictWord{135, 10, 82}, - dictWord{9, 0, 7}, - dictWord{ - 23, - 0, - 6, - }, - dictWord{9, 11, 7}, - dictWord{151, 11, 6}, - dictWord{6, 0, 282}, - dictWord{5, 10, 62}, - dictWord{6, 10, 534}, - dictWord{7, 10, 74}, - dictWord{7, 10, 678}, - dictWord{ - 7, - 10, - 684, - }, - dictWord{7, 10, 1043}, - dictWord{7, 10, 1072}, - dictWord{8, 10, 280}, - dictWord{8, 10, 541}, - dictWord{8, 10, 686}, - dictWord{9, 10, 258}, - dictWord{ - 10, - 10, - 519, - }, - dictWord{11, 10, 252}, - dictWord{140, 10, 282}, - dictWord{138, 10, 33}, - dictWord{132, 10, 359}, - dictWord{4, 0, 44}, - dictWord{5, 0, 311}, - dictWord{ - 6, - 0, - 156, - }, - dictWord{7, 0, 639}, - dictWord{7, 0, 762}, - dictWord{7, 0, 1827}, - dictWord{9, 0, 8}, - dictWord{9, 0, 462}, - dictWord{148, 0, 83}, - dictWord{7, 11, 769}, - dictWord{ - 9, - 11, - 18, - }, - dictWord{138, 11, 358}, - dictWord{4, 0, 346}, - dictWord{7, 0, 115}, - dictWord{9, 0, 180}, - dictWord{9, 0, 456}, - dictWord{10, 0, 363}, - dictWord{ - 4, - 11, - 896, - }, - dictWord{134, 11, 1777}, - dictWord{133, 10, 211}, - dictWord{7, 0, 761}, - dictWord{7, 0, 1051}, - dictWord{137, 0, 545}, - dictWord{6, 10, 145}, - dictWord{ - 141, - 10, - 336, - }, - dictWord{7, 11, 750}, - dictWord{9, 11, 223}, - dictWord{11, 11, 27}, - dictWord{11, 11, 466}, - dictWord{12, 11, 624}, - dictWord{14, 11, 265}, - dictWord{146, 11, 61}, - dictWord{6, 0, 752}, - dictWord{6, 0, 768}, - dictWord{6, 0, 1195}, - dictWord{6, 0, 1254}, - dictWord{6, 0, 1619}, - dictWord{137, 0, 835}, - dictWord{ - 6, - 0, - 1936, - }, - dictWord{8, 0, 930}, - dictWord{136, 0, 960}, - dictWord{132, 10, 263}, - dictWord{132, 11, 249}, - dictWord{12, 0, 653}, - dictWord{132, 10, 916}, - dictWord{4, 11, 603}, - dictWord{133, 11, 661}, - dictWord{8, 0, 344}, - dictWord{4, 11, 11}, - dictWord{6, 11, 128}, - dictWord{7, 11, 231}, - dictWord{7, 11, 1533}, - dictWord{138, 11, 725}, - dictWord{134, 0, 1483}, - dictWord{134, 0, 875}, - dictWord{6, 0, 185}, - dictWord{7, 0, 1899}, - dictWord{9, 0, 875}, - dictWord{139, 0, 673}, - dictWord{15, 10, 155}, - dictWord{144, 10, 79}, - dictWord{7, 0, 93}, - dictWord{7, 0, 210}, - dictWord{7, 0, 1223}, - dictWord{8, 0, 451}, - dictWord{8, 0, 460}, - dictWord{ - 11, - 0, - 353, - }, - dictWord{11, 0, 475}, - dictWord{4, 10, 599}, - dictWord{6, 10, 1634}, - dictWord{7, 10, 67}, - dictWord{7, 10, 691}, - dictWord{7, 10, 979}, - dictWord{ - 7, - 10, - 1697, - }, - dictWord{8, 10, 207}, - dictWord{8, 10, 214}, - dictWord{8, 10, 231}, - dictWord{8, 10, 294}, - dictWord{8, 10, 336}, - dictWord{8, 10, 428}, - dictWord{ - 8, - 10, - 471, - }, - dictWord{8, 10, 622}, - dictWord{8, 10, 626}, - dictWord{8, 10, 679}, - dictWord{8, 10, 759}, - dictWord{8, 10, 829}, - dictWord{9, 10, 11}, - dictWord{9, 10, 246}, - dictWord{9, 10, 484}, - dictWord{9, 10, 573}, - dictWord{9, 10, 706}, - dictWord{9, 10, 762}, - dictWord{9, 10, 798}, - dictWord{9, 10, 855}, - dictWord{9, 10, 870}, - dictWord{ - 9, - 10, - 912, - }, - dictWord{10, 10, 303}, - dictWord{10, 10, 335}, - dictWord{10, 10, 424}, - dictWord{10, 10, 461}, - dictWord{10, 10, 543}, - dictWord{10, 10, 759}, - dictWord{10, 10, 814}, - dictWord{11, 10, 59}, - dictWord{11, 10, 235}, - dictWord{11, 10, 590}, - dictWord{11, 10, 929}, - dictWord{11, 10, 963}, - dictWord{ - 11, - 10, - 987, - }, - dictWord{12, 10, 114}, - dictWord{12, 10, 182}, - dictWord{12, 10, 226}, - dictWord{12, 10, 332}, - dictWord{12, 10, 439}, - dictWord{12, 10, 575}, - dictWord{ - 12, - 10, - 598, - }, - dictWord{12, 10, 675}, - dictWord{13, 10, 8}, - dictWord{13, 10, 125}, - dictWord{13, 10, 194}, - dictWord{13, 10, 287}, - dictWord{14, 10, 197}, - dictWord{14, 10, 383}, - dictWord{15, 10, 53}, - dictWord{17, 10, 63}, - dictWord{19, 10, 46}, - dictWord{19, 10, 98}, - dictWord{19, 10, 106}, - dictWord{148, 10, 85}, - dictWord{132, 11, 476}, - dictWord{4, 0, 327}, - dictWord{5, 0, 478}, - dictWord{7, 0, 1332}, - dictWord{136, 0, 753}, - dictWord{5, 0, 1020}, - dictWord{133, 0, 1022}, - dictWord{135, 11, 1807}, - dictWord{4, 0, 103}, - dictWord{133, 0, 401}, - dictWord{4, 0, 499}, - dictWord{135, 0, 1421}, - dictWord{10, 0, 207}, - dictWord{13, 0, 164}, - dictWord{147, 10, 126}, - dictWord{9, 11, 20}, - dictWord{10, 11, 324}, - dictWord{139, 11, 488}, - dictWord{132, 0, 96}, - dictWord{9, 11, 280}, - dictWord{ - 138, - 11, - 134, - }, - dictWord{135, 0, 968}, - dictWord{133, 10, 187}, - dictWord{135, 10, 1286}, - dictWord{5, 11, 112}, - dictWord{6, 11, 103}, - dictWord{134, 11, 150}, - dictWord{8, 0, 914}, - dictWord{10, 0, 3}, - dictWord{4, 10, 215}, - dictWord{9, 10, 38}, - dictWord{11, 10, 23}, - dictWord{11, 10, 127}, - dictWord{139, 10, 796}, - dictWord{ - 135, - 0, - 399, - }, - dictWord{6, 0, 563}, - dictWord{137, 0, 224}, - dictWord{6, 0, 704}, - dictWord{134, 0, 1214}, - dictWord{4, 11, 708}, - dictWord{8, 11, 15}, - dictWord{ - 9, - 11, - 50, - }, - dictWord{9, 11, 386}, - dictWord{11, 11, 18}, - dictWord{11, 11, 529}, - dictWord{140, 11, 228}, - dictWord{4, 11, 563}, - dictWord{7, 11, 109}, - dictWord{ - 7, - 11, - 592, - }, - dictWord{7, 11, 637}, - dictWord{7, 11, 770}, - dictWord{7, 11, 1701}, - dictWord{8, 11, 436}, - dictWord{8, 11, 463}, - dictWord{9, 11, 60}, - dictWord{9, 11, 335}, - dictWord{9, 11, 904}, - dictWord{10, 11, 73}, - dictWord{11, 11, 434}, - dictWord{12, 11, 585}, - dictWord{13, 11, 331}, - dictWord{18, 11, 110}, - dictWord{ - 148, - 11, - 60, - }, - dictWord{134, 0, 1559}, - dictWord{132, 11, 502}, - dictWord{6, 11, 347}, - dictWord{138, 11, 161}, - dictWord{4, 11, 33}, - dictWord{5, 11, 102}, - dictWord{ - 5, - 11, - 500, - }, - dictWord{6, 11, 284}, - dictWord{7, 11, 1079}, - dictWord{7, 11, 1423}, - dictWord{7, 11, 1702}, - dictWord{8, 11, 470}, - dictWord{9, 11, 554}, - dictWord{ - 9, - 11, - 723, - }, - dictWord{139, 11, 333}, - dictWord{7, 11, 246}, - dictWord{135, 11, 840}, - dictWord{6, 11, 10}, - dictWord{8, 11, 571}, - dictWord{9, 11, 739}, - dictWord{ - 143, - 11, - 91, - }, - dictWord{8, 0, 861}, - dictWord{10, 0, 905}, - dictWord{12, 0, 730}, - dictWord{12, 0, 789}, - dictWord{133, 11, 626}, - dictWord{134, 0, 946}, - dictWord{ - 5, - 0, - 746, - }, - dictWord{12, 0, 333}, - dictWord{14, 0, 332}, - dictWord{12, 11, 333}, - dictWord{142, 11, 332}, - dictWord{5, 11, 18}, - dictWord{6, 11, 526}, - dictWord{ - 13, - 11, - 24, - }, - dictWord{13, 11, 110}, - dictWord{19, 11, 5}, - dictWord{147, 11, 44}, - dictWord{4, 0, 910}, - dictWord{5, 0, 832}, - dictWord{135, 10, 2002}, - dictWord{ - 10, - 11, - 768, - }, - dictWord{139, 11, 787}, - dictWord{4, 11, 309}, - dictWord{5, 11, 462}, - dictWord{7, 11, 970}, - dictWord{135, 11, 1097}, - dictWord{4, 10, 28}, - dictWord{ - 5, - 10, - 440, - }, - dictWord{7, 10, 248}, - dictWord{11, 10, 833}, - dictWord{140, 10, 344}, - dictWord{134, 10, 1654}, - dictWord{6, 0, 632}, - dictWord{6, 0, 652}, - dictWord{ - 6, - 0, - 1272, - }, - dictWord{6, 0, 1384}, - dictWord{134, 0, 1560}, - dictWord{134, 11, 1704}, - dictWord{6, 0, 1393}, - dictWord{133, 10, 853}, - dictWord{6, 10, 249}, - dictWord{7, 10, 1234}, - dictWord{139, 10, 573}, - dictWord{5, 11, 86}, - dictWord{7, 11, 743}, - dictWord{9, 11, 85}, - dictWord{10, 11, 281}, - dictWord{10, 11, 432}, - dictWord{11, 11, 490}, - dictWord{12, 11, 251}, - dictWord{13, 11, 118}, - dictWord{14, 11, 378}, - dictWord{146, 11, 143}, - dictWord{5, 11, 524}, - dictWord{ - 133, - 11, - 744, - }, - dictWord{134, 0, 1514}, - dictWord{10, 0, 201}, - dictWord{142, 0, 319}, - dictWord{7, 0, 717}, - dictWord{10, 0, 510}, - dictWord{7, 10, 392}, - dictWord{ - 8, - 10, - 20, - }, - dictWord{8, 10, 172}, - dictWord{8, 10, 690}, - dictWord{9, 10, 383}, - dictWord{9, 10, 845}, - dictWord{11, 10, 293}, - dictWord{11, 10, 832}, - dictWord{ - 11, - 10, - 920, - }, - dictWord{11, 10, 984}, - dictWord{141, 10, 221}, - dictWord{134, 0, 1381}, - dictWord{5, 10, 858}, - dictWord{133, 10, 992}, - dictWord{8, 0, 528}, - dictWord{137, 0, 348}, - dictWord{10, 11, 107}, - dictWord{140, 11, 436}, - dictWord{4, 0, 20}, - dictWord{133, 0, 616}, - dictWord{134, 0, 1251}, - dictWord{ - 132, - 11, - 927, - }, - dictWord{10, 11, 123}, - dictWord{12, 11, 670}, - dictWord{13, 11, 371}, - dictWord{14, 11, 142}, - dictWord{146, 11, 94}, - dictWord{134, 0, 1163}, - dictWord{ - 7, - 11, - 1149, - }, - dictWord{137, 11, 156}, - dictWord{134, 0, 307}, - dictWord{133, 11, 778}, - dictWord{7, 0, 1091}, - dictWord{135, 0, 1765}, - dictWord{ - 5, - 11, - 502, - }, - dictWord{6, 10, 268}, - dictWord{137, 10, 62}, - dictWord{8, 11, 196}, - dictWord{10, 11, 283}, - dictWord{139, 11, 406}, - dictWord{4, 0, 26}, - dictWord{ - 5, - 0, - 429, - }, - dictWord{6, 0, 245}, - dictWord{7, 0, 704}, - dictWord{7, 0, 1379}, - dictWord{135, 0, 1474}, - dictWord{133, 11, 855}, - dictWord{132, 0, 881}, - dictWord{ - 4, - 0, - 621, - }, - dictWord{135, 11, 1596}, - dictWord{7, 11, 1400}, - dictWord{9, 11, 446}, - dictWord{138, 11, 45}, - dictWord{6, 0, 736}, - dictWord{138, 10, 106}, - dictWord{133, 0, 542}, - dictWord{134, 0, 348}, - dictWord{133, 0, 868}, - dictWord{136, 0, 433}, - dictWord{135, 0, 1495}, - dictWord{138, 0, 771}, - dictWord{ - 6, - 10, - 613, - }, - dictWord{136, 10, 223}, - dictWord{138, 0, 215}, - dictWord{141, 0, 124}, - dictWord{136, 11, 391}, - dictWord{135, 11, 172}, - dictWord{132, 10, 670}, - dictWord{140, 0, 55}, - dictWord{9, 10, 40}, - dictWord{139, 10, 136}, - dictWord{7, 0, 62}, - dictWord{147, 0, 112}, - dictWord{132, 0, 856}, - dictWord{132, 11, 568}, - dictWord{12, 0, 270}, - dictWord{139, 10, 259}, - dictWord{8, 0, 572}, - dictWord{137, 0, 698}, - dictWord{4, 11, 732}, - dictWord{9, 10, 310}, - dictWord{137, 10, 682}, - dictWord{142, 10, 296}, - dictWord{134, 0, 939}, - dictWord{136, 11, 733}, - dictWord{135, 11, 1435}, - dictWord{7, 10, 1401}, - dictWord{135, 10, 1476}, - dictWord{6, 0, 352}, - dictWord{4, 10, 296}, - dictWord{7, 10, 401}, - dictWord{7, 10, 1410}, - dictWord{7, 10, 1594}, - dictWord{7, 10, 1674}, - dictWord{8, 10, 63}, - dictWord{ - 8, - 10, - 660, - }, - dictWord{137, 10, 74}, - dictWord{4, 11, 428}, - dictWord{133, 11, 668}, - dictWord{4, 10, 139}, - dictWord{4, 10, 388}, - dictWord{140, 10, 188}, - dictWord{7, 11, 2015}, - dictWord{140, 11, 665}, - dictWord{132, 0, 647}, - dictWord{146, 0, 10}, - dictWord{138, 0, 220}, - dictWord{142, 0, 464}, - dictWord{ - 132, - 0, - 109, - }, - dictWord{134, 0, 1746}, - dictWord{6, 0, 515}, - dictWord{4, 10, 747}, - dictWord{6, 11, 1623}, - dictWord{6, 11, 1681}, - dictWord{7, 10, 649}, - dictWord{ - 7, - 10, - 1479, - }, - dictWord{135, 10, 1583}, - dictWord{133, 10, 232}, - dictWord{135, 0, 566}, - dictWord{137, 10, 887}, - dictWord{4, 0, 40}, - dictWord{10, 0, 67}, - dictWord{ - 11, - 0, - 117, - }, - dictWord{11, 0, 768}, - dictWord{139, 0, 935}, - dictWord{132, 0, 801}, - dictWord{7, 0, 992}, - dictWord{8, 0, 301}, - dictWord{9, 0, 722}, - dictWord{ - 12, - 0, - 63, - }, - dictWord{13, 0, 29}, - dictWord{14, 0, 161}, - dictWord{143, 0, 18}, - dictWord{139, 0, 923}, - dictWord{6, 11, 1748}, - dictWord{8, 11, 715}, - dictWord{9, 11, 802}, - dictWord{10, 11, 46}, - dictWord{10, 11, 819}, - dictWord{13, 11, 308}, - dictWord{14, 11, 351}, - dictWord{14, 11, 363}, - dictWord{146, 11, 67}, - dictWord{ - 137, - 11, - 745, - }, - dictWord{7, 0, 1145}, - dictWord{4, 10, 14}, - dictWord{7, 10, 1801}, - dictWord{10, 10, 748}, - dictWord{141, 10, 458}, - dictWord{4, 11, 63}, - dictWord{ - 5, - 11, - 347, - }, - dictWord{134, 11, 474}, - dictWord{135, 0, 568}, - dictWord{4, 10, 425}, - dictWord{7, 11, 577}, - dictWord{7, 11, 1432}, - dictWord{9, 11, 475}, - dictWord{ - 9, - 11, - 505, - }, - dictWord{9, 11, 526}, - dictWord{9, 11, 609}, - dictWord{9, 11, 689}, - dictWord{9, 11, 726}, - dictWord{9, 11, 735}, - dictWord{9, 11, 738}, - dictWord{ - 10, - 11, - 556, - }, - dictWord{10, 11, 674}, - dictWord{10, 11, 684}, - dictWord{11, 11, 89}, - dictWord{11, 11, 202}, - dictWord{11, 11, 272}, - dictWord{11, 11, 380}, - dictWord{ - 11, - 11, - 415, - }, - dictWord{11, 11, 505}, - dictWord{11, 11, 537}, - dictWord{11, 11, 550}, - dictWord{11, 11, 562}, - dictWord{11, 11, 640}, - dictWord{11, 11, 667}, - dictWord{11, 11, 688}, - dictWord{11, 11, 847}, - dictWord{11, 11, 927}, - dictWord{11, 11, 930}, - dictWord{11, 11, 940}, - dictWord{12, 11, 144}, - dictWord{ - 12, - 11, - 325, - }, - dictWord{12, 11, 329}, - dictWord{12, 11, 389}, - dictWord{12, 11, 403}, - dictWord{12, 11, 451}, - dictWord{12, 11, 515}, - dictWord{12, 11, 604}, - dictWord{ - 12, - 11, - 616, - }, - dictWord{12, 11, 626}, - dictWord{13, 11, 66}, - dictWord{13, 11, 131}, - dictWord{13, 11, 167}, - dictWord{13, 11, 236}, - dictWord{13, 11, 368}, - dictWord{13, 11, 411}, - dictWord{13, 11, 434}, - dictWord{13, 11, 453}, - dictWord{13, 11, 461}, - dictWord{13, 11, 474}, - dictWord{14, 11, 59}, - dictWord{14, 11, 60}, - dictWord{14, 11, 139}, - dictWord{14, 11, 152}, - dictWord{14, 11, 276}, - dictWord{14, 11, 353}, - dictWord{14, 11, 402}, - dictWord{15, 11, 28}, - dictWord{ - 15, - 11, - 81, - }, - dictWord{15, 11, 123}, - dictWord{15, 11, 152}, - dictWord{18, 11, 136}, - dictWord{148, 11, 88}, - dictWord{137, 0, 247}, - dictWord{135, 11, 1622}, - dictWord{ - 9, - 11, - 544, - }, - dictWord{11, 11, 413}, - dictWord{144, 11, 25}, - dictWord{4, 0, 645}, - dictWord{7, 0, 825}, - dictWord{6, 10, 1768}, - dictWord{135, 11, 89}, - dictWord{140, 0, 328}, - dictWord{5, 10, 943}, - dictWord{134, 10, 1779}, - dictWord{134, 0, 1363}, - dictWord{5, 10, 245}, - dictWord{6, 10, 576}, - dictWord{7, 10, 582}, - dictWord{136, 10, 225}, - dictWord{134, 0, 1280}, - dictWord{5, 11, 824}, - dictWord{133, 11, 941}, - dictWord{7, 11, 440}, - dictWord{8, 11, 230}, - dictWord{ - 139, - 11, - 106, - }, - dictWord{5, 0, 28}, - dictWord{6, 0, 204}, - dictWord{10, 0, 320}, - dictWord{10, 0, 583}, - dictWord{13, 0, 502}, - dictWord{14, 0, 72}, - dictWord{14, 0, 274}, - dictWord{14, 0, 312}, - dictWord{14, 0, 344}, - dictWord{15, 0, 159}, - dictWord{16, 0, 62}, - dictWord{16, 0, 69}, - dictWord{17, 0, 30}, - dictWord{18, 0, 42}, - dictWord{ - 18, - 0, - 53, - }, - dictWord{18, 0, 84}, - dictWord{18, 0, 140}, - dictWord{19, 0, 68}, - dictWord{19, 0, 85}, - dictWord{20, 0, 5}, - dictWord{20, 0, 45}, - dictWord{20, 0, 101}, - dictWord{ - 22, - 0, - 7, - }, - dictWord{150, 0, 20}, - dictWord{4, 0, 558}, - dictWord{6, 0, 390}, - dictWord{7, 0, 162}, - dictWord{7, 0, 689}, - dictWord{9, 0, 360}, - dictWord{138, 0, 653}, - dictWord{134, 0, 764}, - dictWord{6, 0, 862}, - dictWord{137, 0, 833}, - dictWord{5, 0, 856}, - dictWord{6, 0, 1672}, - dictWord{6, 0, 1757}, - dictWord{134, 0, 1781}, - dictWord{ - 5, - 0, - 92, - }, - dictWord{10, 0, 736}, - dictWord{140, 0, 102}, - dictWord{6, 0, 1927}, - dictWord{6, 0, 1944}, - dictWord{8, 0, 924}, - dictWord{8, 0, 948}, - dictWord{ - 10, - 0, - 967, - }, - dictWord{138, 0, 978}, - dictWord{134, 0, 1479}, - dictWord{5, 0, 590}, - dictWord{8, 0, 360}, - dictWord{9, 0, 213}, - dictWord{138, 0, 63}, - dictWord{ - 134, - 0, - 1521, - }, - dictWord{6, 0, 709}, - dictWord{134, 0, 891}, - dictWord{132, 10, 443}, - dictWord{13, 0, 477}, - dictWord{14, 0, 120}, - dictWord{148, 0, 61}, - dictWord{ - 4, - 11, - 914, - }, - dictWord{5, 11, 800}, - dictWord{133, 11, 852}, - dictWord{10, 11, 54}, - dictWord{141, 11, 115}, - dictWord{4, 11, 918}, - dictWord{133, 11, 876}, - dictWord{139, 11, 152}, - dictWord{4, 11, 92}, - dictWord{133, 11, 274}, - dictWord{135, 11, 1901}, - dictWord{9, 11, 800}, - dictWord{10, 11, 693}, - dictWord{ - 11, - 11, - 482, - }, - dictWord{11, 11, 734}, - dictWord{139, 11, 789}, - dictWord{9, 0, 483}, - dictWord{132, 10, 298}, - dictWord{6, 0, 1213}, - dictWord{141, 11, 498}, - dictWord{135, 11, 1451}, - dictWord{133, 11, 743}, - dictWord{4, 0, 1022}, - dictWord{10, 0, 1000}, - dictWord{12, 0, 957}, - dictWord{12, 0, 980}, - dictWord{ - 12, - 0, - 1013, - }, - dictWord{14, 0, 481}, - dictWord{144, 0, 116}, - dictWord{8, 0, 503}, - dictWord{17, 0, 29}, - dictWord{4, 11, 49}, - dictWord{7, 11, 280}, - dictWord{ - 135, - 11, - 1633, - }, - dictWord{135, 0, 1712}, - dictWord{134, 0, 466}, - dictWord{136, 11, 47}, - dictWord{5, 10, 164}, - dictWord{7, 10, 121}, - dictWord{142, 10, 189}, - dictWord{ - 7, - 10, - 812, - }, - dictWord{7, 10, 1261}, - dictWord{7, 10, 1360}, - dictWord{9, 10, 632}, - dictWord{140, 10, 352}, - dictWord{139, 10, 556}, - dictWord{132, 0, 731}, - dictWord{5, 11, 272}, - dictWord{5, 11, 908}, - dictWord{5, 11, 942}, - dictWord{7, 11, 1008}, - dictWord{7, 11, 1560}, - dictWord{8, 11, 197}, - dictWord{9, 11, 47}, - dictWord{11, 11, 538}, - dictWord{139, 11, 742}, - dictWord{4, 10, 172}, - dictWord{9, 10, 611}, - dictWord{10, 10, 436}, - dictWord{12, 10, 673}, - dictWord{ - 141, - 10, - 255, - }, - dictWord{133, 10, 844}, - dictWord{10, 0, 484}, - dictWord{11, 0, 754}, - dictWord{12, 0, 457}, - dictWord{14, 0, 171}, - dictWord{14, 0, 389}, - dictWord{ - 146, - 0, - 153, - }, - dictWord{9, 10, 263}, - dictWord{10, 10, 147}, - dictWord{138, 10, 492}, - dictWord{137, 11, 891}, - dictWord{138, 0, 241}, - dictWord{133, 10, 537}, - dictWord{6, 0, 2005}, - dictWord{136, 0, 964}, - dictWord{137, 10, 842}, - dictWord{151, 11, 8}, - dictWord{4, 11, 407}, - dictWord{132, 11, 560}, - dictWord{ - 135, - 11, - 1884, - }, - dictWord{6, 0, 1100}, - dictWord{134, 0, 1242}, - dictWord{135, 0, 954}, - dictWord{5, 10, 230}, - dictWord{5, 10, 392}, - dictWord{6, 10, 420}, - dictWord{ - 9, - 10, - 568, - }, - dictWord{140, 10, 612}, - dictWord{4, 11, 475}, - dictWord{11, 11, 35}, - dictWord{11, 11, 90}, - dictWord{13, 11, 7}, - dictWord{13, 11, 71}, - dictWord{ - 13, - 11, - 177, - }, - dictWord{142, 11, 422}, - dictWord{136, 11, 332}, - dictWord{135, 0, 1958}, - dictWord{6, 0, 549}, - dictWord{8, 0, 34}, - dictWord{8, 0, 283}, - dictWord{ - 9, - 0, - 165, - }, - dictWord{138, 0, 475}, - dictWord{10, 0, 952}, - dictWord{12, 0, 966}, - dictWord{140, 0, 994}, - dictWord{5, 0, 652}, - dictWord{5, 0, 701}, - dictWord{ - 135, - 0, - 449, - }, - dictWord{4, 0, 655}, - dictWord{7, 0, 850}, - dictWord{17, 0, 75}, - dictWord{146, 0, 137}, - dictWord{4, 0, 146}, - dictWord{7, 0, 1618}, - dictWord{8, 0, 670}, - dictWord{ - 5, - 10, - 41, - }, - dictWord{7, 10, 1459}, - dictWord{7, 10, 1469}, - dictWord{7, 10, 1859}, - dictWord{9, 10, 549}, - dictWord{139, 10, 905}, - dictWord{133, 10, 696}, - dictWord{6, 0, 159}, - dictWord{6, 0, 364}, - dictWord{7, 0, 516}, - dictWord{137, 0, 518}, - dictWord{135, 0, 1439}, - dictWord{6, 11, 222}, - dictWord{7, 11, 636}, - dictWord{ - 7, - 11, - 1620, - }, - dictWord{8, 11, 409}, - dictWord{9, 11, 693}, - dictWord{139, 11, 77}, - dictWord{13, 0, 151}, - dictWord{141, 11, 45}, - dictWord{6, 0, 1027}, - dictWord{ - 4, - 11, - 336, - }, - dictWord{132, 10, 771}, - dictWord{139, 11, 392}, - dictWord{10, 11, 121}, - dictWord{11, 11, 175}, - dictWord{149, 11, 16}, - dictWord{8, 0, 950}, - dictWord{138, 0, 983}, - dictWord{133, 10, 921}, - dictWord{135, 0, 993}, - dictWord{6, 10, 180}, - dictWord{7, 10, 1137}, - dictWord{8, 10, 751}, - dictWord{ - 139, - 10, - 805, - }, - dictWord{7, 0, 501}, - dictWord{9, 0, 111}, - dictWord{10, 0, 141}, - dictWord{11, 0, 332}, - dictWord{13, 0, 43}, - dictWord{13, 0, 429}, - dictWord{14, 0, 130}, - dictWord{14, 0, 415}, - dictWord{145, 0, 102}, - dictWord{4, 10, 183}, - dictWord{5, 11, 882}, - dictWord{7, 10, 271}, - dictWord{11, 10, 824}, - dictWord{11, 10, 952}, - dictWord{13, 10, 278}, - dictWord{13, 10, 339}, - dictWord{13, 10, 482}, - dictWord{14, 10, 424}, - dictWord{148, 10, 99}, - dictWord{4, 10, 19}, - dictWord{5, 10, 477}, - dictWord{5, 10, 596}, - dictWord{6, 10, 505}, - dictWord{7, 10, 1221}, - dictWord{11, 10, 907}, - dictWord{12, 10, 209}, - dictWord{141, 10, 214}, - dictWord{ - 135, - 10, - 1215, - }, - dictWord{133, 0, 452}, - dictWord{132, 11, 426}, - dictWord{5, 0, 149}, - dictWord{136, 0, 233}, - dictWord{133, 0, 935}, - dictWord{6, 11, 58}, - dictWord{ - 7, - 11, - 654, - }, - dictWord{7, 11, 745}, - dictWord{7, 11, 1969}, - dictWord{8, 11, 240}, - dictWord{8, 11, 675}, - dictWord{9, 11, 479}, - dictWord{9, 11, 731}, - dictWord{ - 10, - 11, - 330, - }, - dictWord{10, 11, 593}, - dictWord{10, 11, 817}, - dictWord{11, 11, 32}, - dictWord{11, 11, 133}, - dictWord{11, 11, 221}, - dictWord{145, 11, 68}, - dictWord{ - 12, - 0, - 582, - }, - dictWord{18, 0, 131}, - dictWord{7, 11, 102}, - dictWord{137, 11, 538}, - dictWord{136, 0, 801}, - dictWord{134, 10, 1645}, - dictWord{132, 0, 70}, - dictWord{6, 10, 92}, - dictWord{6, 10, 188}, - dictWord{7, 10, 1269}, - dictWord{7, 10, 1524}, - dictWord{7, 10, 1876}, - dictWord{10, 10, 228}, - dictWord{139, 10, 1020}, - dictWord{4, 10, 459}, - dictWord{133, 10, 966}, - dictWord{138, 0, 369}, - dictWord{16, 0, 36}, - dictWord{140, 10, 330}, - dictWord{141, 11, 366}, - dictWord{ - 7, - 0, - 721, - }, - dictWord{10, 0, 236}, - dictWord{12, 0, 204}, - dictWord{6, 10, 18}, - dictWord{7, 10, 932}, - dictWord{8, 10, 757}, - dictWord{9, 10, 54}, - dictWord{9, 10, 65}, - dictWord{9, 10, 844}, - dictWord{10, 10, 113}, - dictWord{10, 10, 315}, - dictWord{10, 10, 798}, - dictWord{11, 10, 153}, - dictWord{12, 10, 151}, - dictWord{12, 10, 392}, - dictWord{12, 10, 666}, - dictWord{142, 10, 248}, - dictWord{7, 0, 241}, - dictWord{10, 0, 430}, - dictWord{8, 10, 548}, - dictWord{9, 10, 532}, - dictWord{10, 10, 117}, - dictWord{11, 10, 351}, - dictWord{11, 10, 375}, - dictWord{143, 10, 23}, - dictWord{134, 10, 1742}, - dictWord{133, 10, 965}, - dictWord{133, 11, 566}, - dictWord{ - 6, - 11, - 48, - }, - dictWord{135, 11, 63}, - dictWord{134, 10, 182}, - dictWord{10, 10, 65}, - dictWord{10, 10, 488}, - dictWord{138, 10, 497}, - dictWord{6, 11, 114}, - dictWord{7, 11, 1224}, - dictWord{7, 11, 1556}, - dictWord{136, 11, 3}, - dictWord{134, 0, 1817}, - dictWord{8, 11, 576}, - dictWord{137, 11, 267}, - dictWord{ - 6, - 0, - 1078, - }, - dictWord{144, 0, 16}, - dictWord{9, 10, 588}, - dictWord{138, 10, 260}, - dictWord{138, 0, 1021}, - dictWord{5, 0, 406}, - dictWord{134, 0, 2022}, - dictWord{133, 11, 933}, - dictWord{6, 0, 69}, - dictWord{135, 0, 117}, - dictWord{7, 0, 1830}, - dictWord{136, 11, 427}, - dictWord{4, 0, 432}, - dictWord{135, 0, 824}, - dictWord{134, 10, 1786}, - dictWord{133, 0, 826}, - dictWord{139, 11, 67}, - dictWord{133, 11, 759}, - dictWord{135, 10, 308}, - dictWord{137, 0, 816}, - dictWord{ - 133, - 0, - 1000, - }, - dictWord{4, 0, 297}, - dictWord{6, 0, 529}, - dictWord{7, 0, 152}, - dictWord{7, 0, 713}, - dictWord{7, 0, 1845}, - dictWord{8, 0, 710}, - dictWord{8, 0, 717}, - dictWord{12, 0, 639}, - dictWord{140, 0, 685}, - dictWord{7, 0, 423}, - dictWord{136, 10, 588}, - dictWord{136, 10, 287}, - dictWord{136, 0, 510}, - dictWord{ - 134, - 0, - 1048, - }, - dictWord{6, 0, 618}, - dictWord{7, 11, 56}, - dictWord{7, 11, 1989}, - dictWord{8, 11, 337}, - dictWord{8, 11, 738}, - dictWord{9, 11, 600}, - dictWord{ - 10, - 11, - 483, - }, - dictWord{12, 11, 37}, - dictWord{13, 11, 447}, - dictWord{142, 11, 92}, - dictWord{4, 0, 520}, - dictWord{135, 0, 575}, - dictWord{8, 0, 990}, - dictWord{ - 138, - 0, - 977, - }, - dictWord{135, 11, 774}, - dictWord{9, 11, 347}, - dictWord{11, 11, 24}, - dictWord{140, 11, 170}, - dictWord{136, 11, 379}, - dictWord{140, 10, 290}, - dictWord{132, 11, 328}, - dictWord{4, 0, 321}, - dictWord{134, 0, 569}, - dictWord{4, 11, 101}, - dictWord{135, 11, 1171}, - dictWord{7, 0, 723}, - dictWord{7, 0, 1135}, - dictWord{5, 11, 833}, - dictWord{136, 11, 744}, - dictWord{7, 10, 719}, - dictWord{8, 10, 809}, - dictWord{136, 10, 834}, - dictWord{8, 0, 921}, - dictWord{136, 10, 796}, - dictWord{5, 10, 210}, - dictWord{6, 10, 213}, - dictWord{7, 10, 60}, - dictWord{10, 10, 364}, - dictWord{139, 10, 135}, - dictWord{5, 0, 397}, - dictWord{6, 0, 154}, - dictWord{7, 0, 676}, - dictWord{8, 0, 443}, - dictWord{8, 0, 609}, - dictWord{9, 0, 24}, - dictWord{9, 0, 325}, - dictWord{10, 0, 35}, - dictWord{11, 0, 535}, - dictWord{11, 0, 672}, - dictWord{11, 0, 1018}, - dictWord{12, 0, 637}, - dictWord{16, 0, 30}, - dictWord{5, 10, 607}, - dictWord{8, 10, 326}, - dictWord{136, 10, 490}, - dictWord{4, 10, 701}, - dictWord{5, 10, 472}, - dictWord{6, 11, 9}, - dictWord{6, 11, 397}, - dictWord{7, 11, 53}, - dictWord{7, 11, 1742}, - dictWord{9, 10, 758}, - dictWord{10, 11, 632}, - dictWord{ - 11, - 11, - 828, - }, - dictWord{140, 11, 146}, - dictWord{135, 10, 380}, - dictWord{135, 10, 1947}, - dictWord{148, 11, 109}, - dictWord{10, 10, 278}, - dictWord{ - 138, - 11, - 278, - }, - dictWord{134, 0, 856}, - dictWord{7, 0, 139}, - dictWord{4, 10, 386}, - dictWord{8, 10, 405}, - dictWord{8, 10, 728}, - dictWord{9, 10, 497}, - dictWord{ - 11, - 10, - 110, - }, - dictWord{11, 10, 360}, - dictWord{15, 10, 37}, - dictWord{144, 10, 84}, - dictWord{141, 0, 282}, - dictWord{133, 0, 981}, - dictWord{5, 0, 288}, - dictWord{ - 7, - 10, - 1452, - }, - dictWord{7, 10, 1480}, - dictWord{8, 10, 634}, - dictWord{140, 10, 472}, - dictWord{7, 0, 1890}, - dictWord{8, 11, 367}, - dictWord{10, 11, 760}, - dictWord{ - 14, - 11, - 79, - }, - dictWord{20, 11, 17}, - dictWord{152, 11, 0}, - dictWord{4, 10, 524}, - dictWord{136, 10, 810}, - dictWord{4, 0, 56}, - dictWord{7, 0, 1791}, - dictWord{ - 8, - 0, - 607, - }, - dictWord{8, 0, 651}, - dictWord{11, 0, 465}, - dictWord{11, 0, 835}, - dictWord{12, 0, 337}, - dictWord{141, 0, 480}, - dictWord{10, 10, 238}, - dictWord{ - 141, - 10, - 33, - }, - dictWord{11, 11, 417}, - dictWord{12, 11, 223}, - dictWord{140, 11, 265}, - dictWord{9, 0, 158}, - dictWord{10, 0, 411}, - dictWord{140, 0, 261}, - dictWord{ - 133, - 10, - 532, - }, - dictWord{133, 10, 997}, - dictWord{12, 11, 186}, - dictWord{12, 11, 292}, - dictWord{14, 11, 100}, - dictWord{146, 11, 70}, - dictWord{6, 0, 1403}, - dictWord{136, 0, 617}, - dictWord{134, 0, 1205}, - dictWord{139, 0, 563}, - dictWord{4, 0, 242}, - dictWord{134, 0, 333}, - dictWord{4, 11, 186}, - dictWord{5, 11, 157}, - dictWord{8, 11, 168}, - dictWord{138, 11, 6}, - dictWord{132, 0, 369}, - dictWord{133, 11, 875}, - dictWord{5, 10, 782}, - dictWord{5, 10, 829}, - dictWord{ - 134, - 10, - 1738, - }, - dictWord{134, 0, 622}, - dictWord{135, 11, 1272}, - dictWord{6, 0, 1407}, - dictWord{7, 11, 111}, - dictWord{136, 11, 581}, - dictWord{7, 10, 1823}, - dictWord{139, 10, 693}, - dictWord{7, 0, 160}, - dictWord{10, 0, 624}, - dictWord{142, 0, 279}, - dictWord{132, 0, 363}, - dictWord{10, 11, 589}, - dictWord{12, 11, 111}, - dictWord{13, 11, 260}, - dictWord{14, 11, 82}, - dictWord{18, 11, 63}, - dictWord{147, 11, 45}, - dictWord{7, 11, 1364}, - dictWord{7, 11, 1907}, - dictWord{ - 141, - 11, - 158, - }, - dictWord{4, 11, 404}, - dictWord{4, 11, 659}, - dictWord{135, 11, 675}, - dictWord{13, 11, 211}, - dictWord{14, 11, 133}, - dictWord{14, 11, 204}, - dictWord{ - 15, - 11, - 64, - }, - dictWord{15, 11, 69}, - dictWord{15, 11, 114}, - dictWord{16, 11, 10}, - dictWord{19, 11, 23}, - dictWord{19, 11, 35}, - dictWord{19, 11, 39}, - dictWord{ - 19, - 11, - 51, - }, - dictWord{19, 11, 71}, - dictWord{19, 11, 75}, - dictWord{152, 11, 15}, - dictWord{4, 10, 78}, - dictWord{5, 10, 96}, - dictWord{5, 10, 182}, - dictWord{7, 10, 1724}, - dictWord{7, 10, 1825}, - dictWord{10, 10, 394}, - dictWord{10, 10, 471}, - dictWord{11, 10, 532}, - dictWord{14, 10, 340}, - dictWord{145, 10, 88}, - dictWord{ - 135, - 10, - 1964, - }, - dictWord{133, 11, 391}, - dictWord{11, 11, 887}, - dictWord{14, 11, 365}, - dictWord{142, 11, 375}, - dictWord{5, 11, 540}, - dictWord{6, 11, 1697}, - dictWord{7, 11, 222}, - dictWord{136, 11, 341}, - dictWord{134, 11, 78}, - dictWord{9, 0, 601}, - dictWord{9, 0, 619}, - dictWord{10, 0, 505}, - dictWord{10, 0, 732}, - dictWord{11, 0, 355}, - dictWord{140, 0, 139}, - dictWord{134, 0, 292}, - dictWord{139, 0, 174}, - dictWord{5, 0, 177}, - dictWord{6, 0, 616}, - dictWord{7, 0, 827}, - dictWord{ - 9, - 0, - 525, - }, - dictWord{138, 0, 656}, - dictWord{10, 0, 31}, - dictWord{6, 10, 215}, - dictWord{7, 10, 1028}, - dictWord{7, 10, 1473}, - dictWord{7, 10, 1721}, - dictWord{ - 9, - 10, - 424, - }, - dictWord{138, 10, 779}, - dictWord{135, 10, 584}, - dictWord{136, 11, 293}, - dictWord{134, 0, 685}, - dictWord{135, 11, 1868}, - dictWord{ - 133, - 11, - 460, - }, - dictWord{7, 0, 647}, - dictWord{6, 10, 67}, - dictWord{7, 10, 1630}, - dictWord{9, 10, 354}, - dictWord{9, 10, 675}, - dictWord{10, 10, 830}, - dictWord{ - 14, - 10, - 80, - }, - dictWord{145, 10, 80}, - dictWord{4, 0, 161}, - dictWord{133, 0, 631}, - dictWord{6, 10, 141}, - dictWord{7, 10, 225}, - dictWord{9, 10, 59}, - dictWord{9, 10, 607}, - dictWord{10, 10, 312}, - dictWord{11, 10, 687}, - dictWord{12, 10, 555}, - dictWord{13, 10, 373}, - dictWord{13, 10, 494}, - dictWord{148, 10, 58}, - dictWord{ - 7, - 11, - 965, - }, - dictWord{7, 11, 1460}, - dictWord{135, 11, 1604}, - dictWord{136, 10, 783}, - dictWord{134, 11, 388}, - dictWord{6, 0, 722}, - dictWord{6, 0, 1267}, - dictWord{ - 4, - 11, - 511, - }, - dictWord{9, 11, 333}, - dictWord{9, 11, 379}, - dictWord{10, 11, 602}, - dictWord{11, 11, 441}, - dictWord{11, 11, 723}, - dictWord{11, 11, 976}, - dictWord{140, 11, 357}, - dictWord{134, 0, 1797}, - dictWord{135, 0, 1684}, - dictWord{9, 0, 469}, - dictWord{9, 0, 709}, - dictWord{12, 0, 512}, - dictWord{14, 0, 65}, - dictWord{17, 0, 12}, - dictWord{5, 11, 938}, - dictWord{136, 11, 707}, - dictWord{7, 0, 1230}, - dictWord{136, 0, 531}, - dictWord{10, 0, 229}, - dictWord{11, 0, 73}, - dictWord{ - 11, - 0, - 376, - }, - dictWord{139, 0, 433}, - dictWord{12, 0, 268}, - dictWord{12, 0, 640}, - dictWord{142, 0, 119}, - dictWord{7, 10, 430}, - dictWord{139, 10, 46}, - dictWord{ - 6, - 0, - 558, - }, - dictWord{7, 0, 651}, - dictWord{8, 0, 421}, - dictWord{9, 0, 0}, - dictWord{10, 0, 34}, - dictWord{139, 0, 1008}, - dictWord{6, 0, 106}, - dictWord{7, 0, 1786}, - dictWord{7, 0, 1821}, - dictWord{9, 0, 102}, - dictWord{9, 0, 763}, - dictWord{5, 10, 602}, - dictWord{7, 10, 2018}, - dictWord{137, 10, 418}, - dictWord{5, 0, 65}, - dictWord{ - 6, - 0, - 416, - }, - dictWord{7, 0, 1720}, - dictWord{7, 0, 1924}, - dictWord{10, 0, 109}, - dictWord{11, 0, 14}, - dictWord{11, 0, 70}, - dictWord{11, 0, 569}, - dictWord{11, 0, 735}, - dictWord{15, 0, 153}, - dictWord{20, 0, 80}, - dictWord{136, 10, 677}, - dictWord{135, 11, 1625}, - dictWord{137, 11, 772}, - dictWord{136, 0, 595}, - dictWord{ - 6, - 11, - 469, - }, - dictWord{7, 11, 1709}, - dictWord{138, 11, 515}, - dictWord{7, 0, 1832}, - dictWord{138, 0, 374}, - dictWord{9, 0, 106}, - dictWord{9, 0, 163}, - dictWord{ - 9, - 0, - 296, - }, - dictWord{10, 0, 167}, - dictWord{10, 0, 172}, - dictWord{10, 0, 777}, - dictWord{139, 0, 16}, - dictWord{6, 0, 6}, - dictWord{7, 0, 81}, - dictWord{7, 0, 771}, - dictWord{ - 7, - 0, - 1731, - }, - dictWord{9, 0, 405}, - dictWord{138, 0, 421}, - dictWord{4, 11, 500}, - dictWord{135, 11, 938}, - dictWord{5, 11, 68}, - dictWord{134, 11, 383}, - dictWord{ - 5, - 0, - 881, - }, - dictWord{133, 0, 885}, - dictWord{6, 0, 854}, - dictWord{6, 0, 1132}, - dictWord{6, 0, 1495}, - dictWord{6, 0, 1526}, - dictWord{6, 0, 1533}, - dictWord{ - 134, - 0, - 1577, - }, - dictWord{4, 11, 337}, - dictWord{6, 11, 353}, - dictWord{7, 11, 1934}, - dictWord{8, 11, 488}, - dictWord{137, 11, 429}, - dictWord{7, 11, 236}, - dictWord{ - 7, - 11, - 1795, - }, - dictWord{8, 11, 259}, - dictWord{9, 11, 135}, - dictWord{9, 11, 177}, - dictWord{10, 11, 825}, - dictWord{11, 11, 115}, - dictWord{11, 11, 370}, - dictWord{ - 11, - 11, - 405, - }, - dictWord{11, 11, 604}, - dictWord{12, 11, 10}, - dictWord{12, 11, 667}, - dictWord{12, 11, 669}, - dictWord{13, 11, 76}, - dictWord{14, 11, 310}, - dictWord{15, 11, 76}, - dictWord{15, 11, 147}, - dictWord{148, 11, 23}, - dictWord{5, 0, 142}, - dictWord{134, 0, 546}, - dictWord{4, 11, 15}, - dictWord{5, 11, 22}, - dictWord{ - 6, - 11, - 244, - }, - dictWord{7, 11, 40}, - dictWord{7, 11, 200}, - dictWord{7, 11, 906}, - dictWord{7, 11, 1199}, - dictWord{9, 11, 616}, - dictWord{10, 11, 716}, - dictWord{ - 11, - 11, - 635, - }, - dictWord{11, 11, 801}, - dictWord{140, 11, 458}, - dictWord{5, 0, 466}, - dictWord{11, 0, 571}, - dictWord{12, 0, 198}, - dictWord{13, 0, 283}, - dictWord{ - 14, - 0, - 186, - }, - dictWord{15, 0, 21}, - dictWord{15, 0, 103}, - dictWord{135, 10, 329}, - dictWord{4, 0, 185}, - dictWord{5, 0, 257}, - dictWord{5, 0, 839}, - dictWord{5, 0, 936}, - dictWord{9, 0, 399}, - dictWord{10, 0, 258}, - dictWord{10, 0, 395}, - dictWord{10, 0, 734}, - dictWord{11, 0, 1014}, - dictWord{12, 0, 23}, - dictWord{13, 0, 350}, - dictWord{ - 14, - 0, - 150, - }, - dictWord{19, 0, 6}, - dictWord{135, 11, 1735}, - dictWord{12, 11, 36}, - dictWord{141, 11, 337}, - dictWord{5, 11, 598}, - dictWord{7, 11, 791}, - dictWord{ - 8, - 11, - 108, - }, - dictWord{137, 11, 123}, - dictWord{132, 10, 469}, - dictWord{7, 0, 404}, - dictWord{7, 0, 1377}, - dictWord{7, 0, 1430}, - dictWord{7, 0, 2017}, - dictWord{ - 8, - 0, - 149, - }, - dictWord{8, 0, 239}, - dictWord{8, 0, 512}, - dictWord{8, 0, 793}, - dictWord{8, 0, 818}, - dictWord{9, 0, 474}, - dictWord{9, 0, 595}, - dictWord{10, 0, 122}, - dictWord{10, 0, 565}, - dictWord{10, 0, 649}, - dictWord{10, 0, 783}, - dictWord{11, 0, 239}, - dictWord{11, 0, 295}, - dictWord{11, 0, 447}, - dictWord{11, 0, 528}, - dictWord{ - 11, - 0, - 639, - }, - dictWord{11, 0, 800}, - dictWord{12, 0, 25}, - dictWord{12, 0, 77}, - dictWord{12, 0, 157}, - dictWord{12, 0, 256}, - dictWord{12, 0, 316}, - dictWord{12, 0, 390}, - dictWord{12, 0, 391}, - dictWord{12, 0, 395}, - dictWord{12, 0, 478}, - dictWord{12, 0, 503}, - dictWord{12, 0, 592}, - dictWord{12, 0, 680}, - dictWord{13, 0, 50}, - dictWord{13, 0, 53}, - dictWord{13, 0, 132}, - dictWord{13, 0, 198}, - dictWord{13, 0, 322}, - dictWord{13, 0, 415}, - dictWord{13, 0, 511}, - dictWord{14, 0, 71}, - dictWord{ - 14, - 0, - 395, - }, - dictWord{15, 0, 71}, - dictWord{15, 0, 136}, - dictWord{17, 0, 123}, - dictWord{18, 0, 93}, - dictWord{147, 0, 58}, - dictWord{136, 0, 712}, - dictWord{ - 134, - 10, - 1743, - }, - dictWord{5, 10, 929}, - dictWord{6, 10, 340}, - dictWord{8, 10, 376}, - dictWord{136, 10, 807}, - dictWord{6, 0, 1848}, - dictWord{8, 0, 860}, - dictWord{ - 10, - 0, - 856, - }, - dictWord{10, 0, 859}, - dictWord{10, 0, 925}, - dictWord{10, 0, 941}, - dictWord{140, 0, 762}, - dictWord{6, 0, 629}, - dictWord{6, 0, 906}, - dictWord{9, 0, 810}, - dictWord{140, 0, 652}, - dictWord{5, 10, 218}, - dictWord{7, 10, 1610}, - dictWord{138, 10, 83}, - dictWord{7, 10, 1512}, - dictWord{135, 10, 1794}, - dictWord{ - 4, - 0, - 377, - }, - dictWord{24, 0, 13}, - dictWord{4, 11, 155}, - dictWord{7, 11, 1689}, - dictWord{11, 10, 0}, - dictWord{144, 10, 78}, - dictWord{4, 11, 164}, - dictWord{5, 11, 151}, - dictWord{5, 11, 730}, - dictWord{5, 11, 741}, - dictWord{7, 11, 498}, - dictWord{7, 11, 870}, - dictWord{7, 11, 1542}, - dictWord{12, 11, 213}, - dictWord{14, 11, 36}, - dictWord{14, 11, 391}, - dictWord{17, 11, 111}, - dictWord{18, 11, 6}, - dictWord{18, 11, 46}, - dictWord{18, 11, 151}, - dictWord{19, 11, 36}, - dictWord{20, 11, 32}, - dictWord{20, 11, 56}, - dictWord{20, 11, 69}, - dictWord{20, 11, 102}, - dictWord{21, 11, 4}, - dictWord{22, 11, 8}, - dictWord{22, 11, 10}, - dictWord{22, 11, 14}, - dictWord{ - 150, - 11, - 31, - }, - dictWord{7, 0, 1842}, - dictWord{133, 10, 571}, - dictWord{4, 10, 455}, - dictWord{4, 11, 624}, - dictWord{135, 11, 1752}, - dictWord{134, 0, 1501}, - dictWord{4, 11, 492}, - dictWord{5, 11, 451}, - dictWord{6, 10, 161}, - dictWord{7, 10, 372}, - dictWord{137, 10, 597}, - dictWord{132, 10, 349}, - dictWord{4, 0, 180}, - dictWord{135, 0, 1906}, - dictWord{135, 11, 835}, - dictWord{141, 11, 70}, - dictWord{132, 0, 491}, - dictWord{137, 10, 751}, - dictWord{6, 10, 432}, - dictWord{ - 139, - 10, - 322, - }, - dictWord{4, 0, 171}, - dictWord{138, 0, 234}, - dictWord{6, 11, 113}, - dictWord{135, 11, 436}, - dictWord{4, 0, 586}, - dictWord{7, 0, 1186}, - dictWord{ - 138, - 0, - 631, - }, - dictWord{5, 10, 468}, - dictWord{10, 10, 325}, - dictWord{11, 10, 856}, - dictWord{12, 10, 345}, - dictWord{143, 10, 104}, - dictWord{5, 10, 223}, - dictWord{10, 11, 592}, - dictWord{10, 11, 753}, - dictWord{12, 11, 317}, - dictWord{12, 11, 355}, - dictWord{12, 11, 465}, - dictWord{12, 11, 469}, - dictWord{ - 12, - 11, - 560, - }, - dictWord{12, 11, 578}, - dictWord{141, 11, 243}, - dictWord{132, 10, 566}, - dictWord{135, 11, 520}, - dictWord{4, 10, 59}, - dictWord{135, 10, 1394}, - dictWord{6, 10, 436}, - dictWord{139, 10, 481}, - dictWord{9, 0, 931}, - dictWord{10, 0, 334}, - dictWord{20, 0, 71}, - dictWord{4, 10, 48}, - dictWord{5, 10, 271}, - dictWord{ - 7, - 10, - 953, - }, - dictWord{135, 11, 1878}, - dictWord{11, 0, 170}, - dictWord{5, 10, 610}, - dictWord{136, 10, 457}, - dictWord{133, 10, 755}, - dictWord{6, 0, 1587}, - dictWord{135, 10, 1217}, - dictWord{4, 10, 197}, - dictWord{149, 11, 26}, - dictWord{133, 11, 585}, - dictWord{137, 11, 521}, - dictWord{133, 0, 765}, - dictWord{ - 133, - 10, - 217, - }, - dictWord{139, 11, 586}, - dictWord{133, 0, 424}, - dictWord{9, 11, 752}, - dictWord{12, 11, 610}, - dictWord{13, 11, 431}, - dictWord{16, 11, 59}, - dictWord{146, 11, 109}, - dictWord{136, 0, 714}, - dictWord{7, 0, 685}, - dictWord{132, 11, 307}, - dictWord{9, 0, 420}, - dictWord{10, 0, 269}, - dictWord{10, 0, 285}, - dictWord{10, 0, 576}, - dictWord{11, 0, 397}, - dictWord{13, 0, 175}, - dictWord{145, 0, 90}, - dictWord{132, 0, 429}, - dictWord{133, 11, 964}, - dictWord{9, 11, 463}, - dictWord{138, 11, 595}, - dictWord{7, 0, 18}, - dictWord{7, 0, 699}, - dictWord{7, 0, 1966}, - dictWord{8, 0, 752}, - dictWord{9, 0, 273}, - dictWord{9, 0, 412}, - dictWord{ - 9, - 0, - 703, - }, - dictWord{10, 0, 71}, - dictWord{10, 0, 427}, - dictWord{138, 0, 508}, - dictWord{4, 10, 165}, - dictWord{7, 10, 1398}, - dictWord{135, 10, 1829}, - dictWord{ - 4, - 0, - 53, - }, - dictWord{5, 0, 186}, - dictWord{7, 0, 752}, - dictWord{7, 0, 828}, - dictWord{142, 0, 116}, - dictWord{8, 0, 575}, - dictWord{10, 0, 289}, - dictWord{139, 0, 319}, - dictWord{132, 0, 675}, - dictWord{134, 0, 1424}, - dictWord{4, 11, 75}, - dictWord{5, 11, 180}, - dictWord{6, 11, 500}, - dictWord{7, 11, 58}, - dictWord{7, 11, 710}, - dictWord{138, 11, 645}, - dictWord{133, 11, 649}, - dictWord{6, 11, 276}, - dictWord{7, 11, 282}, - dictWord{7, 11, 879}, - dictWord{7, 11, 924}, - dictWord{8, 11, 459}, - dictWord{9, 11, 599}, - dictWord{9, 11, 754}, - dictWord{11, 11, 574}, - dictWord{12, 11, 128}, - dictWord{12, 11, 494}, - dictWord{13, 11, 52}, - dictWord{13, 11, 301}, - dictWord{15, 11, 30}, - dictWord{143, 11, 132}, - dictWord{6, 0, 647}, - dictWord{134, 0, 1095}, - dictWord{5, 10, 9}, - dictWord{7, 10, 297}, - dictWord{7, 10, 966}, - dictWord{140, 10, 306}, - dictWord{132, 11, 200}, - dictWord{134, 0, 1334}, - dictWord{5, 10, 146}, - dictWord{6, 10, 411}, - dictWord{138, 10, 721}, - dictWord{ - 6, - 0, - 209, - }, - dictWord{6, 0, 1141}, - dictWord{6, 0, 1288}, - dictWord{8, 0, 468}, - dictWord{9, 0, 210}, - dictWord{11, 0, 36}, - dictWord{12, 0, 28}, - dictWord{12, 0, 630}, - dictWord{13, 0, 21}, - dictWord{13, 0, 349}, - dictWord{14, 0, 7}, - dictWord{145, 0, 13}, - dictWord{6, 10, 177}, - dictWord{135, 10, 467}, - dictWord{4, 0, 342}, - dictWord{ - 135, - 0, - 1179, - }, - dictWord{10, 11, 454}, - dictWord{140, 11, 324}, - dictWord{4, 0, 928}, - dictWord{133, 0, 910}, - dictWord{7, 0, 1838}, - dictWord{6, 11, 225}, - dictWord{ - 137, - 11, - 211, - }, - dictWord{16, 0, 101}, - dictWord{20, 0, 115}, - dictWord{20, 0, 118}, - dictWord{148, 0, 122}, - dictWord{4, 0, 496}, - dictWord{135, 0, 856}, - dictWord{ - 4, - 0, - 318, - }, - dictWord{11, 0, 654}, - dictWord{7, 11, 718}, - dictWord{139, 11, 102}, - dictWord{8, 11, 58}, - dictWord{9, 11, 724}, - dictWord{11, 11, 809}, - dictWord{ - 13, - 11, - 113, - }, - dictWord{145, 11, 72}, - dictWord{5, 10, 200}, - dictWord{6, 11, 345}, - dictWord{135, 11, 1247}, - dictWord{8, 11, 767}, - dictWord{8, 11, 803}, - dictWord{ - 9, - 11, - 301, - }, - dictWord{137, 11, 903}, - dictWord{7, 0, 915}, - dictWord{8, 0, 247}, - dictWord{19, 0, 0}, - dictWord{7, 11, 1949}, - dictWord{136, 11, 674}, - dictWord{ - 4, - 0, - 202, - }, - dictWord{5, 0, 382}, - dictWord{6, 0, 454}, - dictWord{7, 0, 936}, - dictWord{7, 0, 1803}, - dictWord{8, 0, 758}, - dictWord{9, 0, 375}, - dictWord{9, 0, 895}, - dictWord{ - 10, - 0, - 743, - }, - dictWord{10, 0, 792}, - dictWord{11, 0, 978}, - dictWord{11, 0, 1012}, - dictWord{142, 0, 109}, - dictWord{7, 0, 1150}, - dictWord{7, 0, 1425}, - dictWord{ - 7, - 0, - 1453, - }, - dictWord{140, 0, 513}, - dictWord{134, 11, 259}, - dictWord{138, 0, 791}, - dictWord{11, 0, 821}, - dictWord{12, 0, 110}, - dictWord{12, 0, 153}, - dictWord{ - 18, - 0, - 41, - }, - dictWord{150, 0, 19}, - dictWord{134, 10, 481}, - dictWord{132, 0, 796}, - dictWord{6, 0, 445}, - dictWord{9, 0, 909}, - dictWord{136, 11, 254}, - dictWord{ - 10, - 0, - 776, - }, - dictWord{13, 0, 345}, - dictWord{142, 0, 425}, - dictWord{4, 10, 84}, - dictWord{7, 10, 1482}, - dictWord{10, 10, 76}, - dictWord{138, 10, 142}, - dictWord{ - 135, - 11, - 742, - }, - dictWord{6, 0, 578}, - dictWord{133, 10, 1015}, - dictWord{6, 0, 1387}, - dictWord{4, 10, 315}, - dictWord{5, 10, 507}, - dictWord{135, 10, 1370}, - dictWord{4, 0, 438}, - dictWord{133, 0, 555}, - dictWord{136, 0, 766}, - dictWord{133, 11, 248}, - dictWord{134, 10, 1722}, - dictWord{4, 11, 116}, - dictWord{5, 11, 95}, - dictWord{5, 11, 445}, - dictWord{7, 11, 1688}, - dictWord{8, 11, 29}, - dictWord{9, 11, 272}, - dictWord{11, 11, 509}, - dictWord{139, 11, 915}, - dictWord{135, 0, 541}, - dictWord{133, 11, 543}, - dictWord{8, 10, 222}, - dictWord{8, 10, 476}, - dictWord{9, 10, 238}, - dictWord{11, 10, 516}, - dictWord{11, 10, 575}, - dictWord{ - 15, - 10, - 109, - }, - dictWord{146, 10, 100}, - dictWord{6, 0, 880}, - dictWord{134, 0, 1191}, - dictWord{5, 11, 181}, - dictWord{136, 11, 41}, - dictWord{134, 0, 1506}, - dictWord{132, 11, 681}, - dictWord{7, 11, 25}, - dictWord{8, 11, 202}, - dictWord{138, 11, 536}, - dictWord{139, 0, 983}, - dictWord{137, 0, 768}, - dictWord{132, 0, 584}, - dictWord{9, 11, 423}, - dictWord{140, 11, 89}, - dictWord{8, 11, 113}, - dictWord{9, 11, 877}, - dictWord{10, 11, 554}, - dictWord{11, 11, 83}, - dictWord{12, 11, 136}, - dictWord{147, 11, 109}, - dictWord{7, 10, 706}, - dictWord{7, 10, 1058}, - dictWord{138, 10, 538}, - dictWord{133, 11, 976}, - dictWord{4, 11, 206}, - dictWord{ - 135, - 11, - 746, - }, - dictWord{136, 11, 526}, - dictWord{140, 0, 737}, - dictWord{11, 10, 92}, - dictWord{11, 10, 196}, - dictWord{11, 10, 409}, - dictWord{11, 10, 450}, - dictWord{11, 10, 666}, - dictWord{11, 10, 777}, - dictWord{12, 10, 262}, - dictWord{13, 10, 385}, - dictWord{13, 10, 393}, - dictWord{15, 10, 115}, - dictWord{ - 16, - 10, - 45, - }, - dictWord{145, 10, 82}, - dictWord{4, 0, 226}, - dictWord{4, 0, 326}, - dictWord{7, 0, 1770}, - dictWord{4, 11, 319}, - dictWord{5, 11, 699}, - dictWord{138, 11, 673}, - dictWord{6, 10, 40}, - dictWord{135, 10, 1781}, - dictWord{5, 0, 426}, - dictWord{8, 0, 30}, - dictWord{9, 0, 2}, - dictWord{11, 0, 549}, - dictWord{147, 0, 122}, - dictWord{ - 6, - 0, - 1161, - }, - dictWord{134, 0, 1329}, - dictWord{138, 10, 97}, - dictWord{6, 10, 423}, - dictWord{7, 10, 665}, - dictWord{135, 10, 1210}, - dictWord{7, 11, 13}, - dictWord{ - 8, - 11, - 226, - }, - dictWord{10, 11, 537}, - dictWord{11, 11, 570}, - dictWord{11, 11, 605}, - dictWord{11, 11, 799}, - dictWord{11, 11, 804}, - dictWord{12, 11, 85}, - dictWord{12, 11, 516}, - dictWord{12, 11, 623}, - dictWord{13, 11, 112}, - dictWord{13, 11, 361}, - dictWord{14, 11, 77}, - dictWord{14, 11, 78}, - dictWord{17, 11, 28}, - dictWord{147, 11, 110}, - dictWord{132, 11, 769}, - dictWord{132, 11, 551}, - dictWord{132, 11, 728}, - dictWord{147, 0, 117}, - dictWord{9, 11, 57}, - dictWord{ - 9, - 11, - 459, - }, - dictWord{10, 11, 425}, - dictWord{11, 11, 119}, - dictWord{12, 11, 184}, - dictWord{12, 11, 371}, - dictWord{13, 11, 358}, - dictWord{145, 11, 51}, - dictWord{ - 5, - 11, - 188, - }, - dictWord{5, 11, 814}, - dictWord{8, 11, 10}, - dictWord{9, 11, 421}, - dictWord{9, 11, 729}, - dictWord{10, 11, 609}, - dictWord{139, 11, 689}, - dictWord{134, 11, 624}, - dictWord{135, 11, 298}, - dictWord{135, 0, 462}, - dictWord{4, 0, 345}, - dictWord{139, 10, 624}, - dictWord{136, 10, 574}, - dictWord{ - 4, - 0, - 385, - }, - dictWord{7, 0, 265}, - dictWord{135, 0, 587}, - dictWord{6, 0, 808}, - dictWord{132, 11, 528}, - dictWord{133, 0, 398}, - dictWord{132, 10, 354}, - dictWord{ - 4, - 0, - 347, - }, - dictWord{5, 0, 423}, - dictWord{5, 0, 996}, - dictWord{135, 0, 1329}, - dictWord{135, 10, 1558}, - dictWord{7, 0, 1259}, - dictWord{9, 0, 125}, - dictWord{ - 139, - 0, - 65, - }, - dictWord{5, 0, 136}, - dictWord{6, 0, 136}, - dictWord{136, 0, 644}, - dictWord{5, 11, 104}, - dictWord{6, 11, 173}, - dictWord{135, 11, 1631}, - dictWord{ - 135, - 0, - 469, - }, - dictWord{133, 10, 830}, - dictWord{4, 0, 278}, - dictWord{5, 0, 465}, - dictWord{135, 0, 1367}, - dictWord{7, 11, 810}, - dictWord{8, 11, 138}, - dictWord{ - 8, - 11, - 342, - }, - dictWord{9, 11, 84}, - dictWord{10, 11, 193}, - dictWord{11, 11, 883}, - dictWord{140, 11, 359}, - dictWord{5, 10, 496}, - dictWord{135, 10, 203}, - dictWord{ - 4, - 0, - 433, - }, - dictWord{133, 0, 719}, - dictWord{6, 11, 95}, - dictWord{134, 10, 547}, - dictWord{5, 10, 88}, - dictWord{137, 10, 239}, - dictWord{6, 11, 406}, - dictWord{ - 10, - 11, - 409, - }, - dictWord{10, 11, 447}, - dictWord{11, 11, 44}, - dictWord{140, 11, 100}, - dictWord{134, 0, 1423}, - dictWord{7, 10, 650}, - dictWord{135, 10, 1310}, - dictWord{134, 0, 749}, - dictWord{135, 11, 1243}, - dictWord{135, 0, 1363}, - dictWord{6, 0, 381}, - dictWord{7, 0, 645}, - dictWord{7, 0, 694}, - dictWord{8, 0, 546}, - dictWord{7, 10, 1076}, - dictWord{9, 10, 80}, - dictWord{11, 10, 78}, - dictWord{11, 10, 421}, - dictWord{11, 10, 534}, - dictWord{140, 10, 545}, - dictWord{ - 134, - 11, - 1636, - }, - dictWord{135, 11, 1344}, - dictWord{12, 0, 277}, - dictWord{7, 10, 274}, - dictWord{11, 10, 479}, - dictWord{139, 10, 507}, - dictWord{6, 0, 705}, - dictWord{ - 6, - 0, - 783, - }, - dictWord{6, 0, 1275}, - dictWord{6, 0, 1481}, - dictWord{4, 11, 282}, - dictWord{7, 11, 1034}, - dictWord{11, 11, 398}, - dictWord{11, 11, 634}, - dictWord{ - 12, - 11, - 1, - }, - dictWord{12, 11, 79}, - dictWord{12, 11, 544}, - dictWord{14, 11, 237}, - dictWord{17, 11, 10}, - dictWord{146, 11, 20}, - dictWord{134, 0, 453}, - dictWord{ - 4, - 0, - 555, - }, - dictWord{8, 0, 536}, - dictWord{10, 0, 288}, - dictWord{11, 0, 1005}, - dictWord{4, 10, 497}, - dictWord{135, 10, 1584}, - dictWord{5, 11, 118}, - dictWord{ - 5, - 11, - 499, - }, - dictWord{6, 11, 476}, - dictWord{7, 11, 600}, - dictWord{7, 11, 888}, - dictWord{135, 11, 1096}, - dictWord{138, 0, 987}, - dictWord{7, 0, 1107}, - dictWord{ - 7, - 10, - 261, - }, - dictWord{7, 10, 1115}, - dictWord{7, 10, 1354}, - dictWord{7, 10, 1588}, - dictWord{7, 10, 1705}, - dictWord{7, 10, 1902}, - dictWord{9, 10, 465}, - dictWord{10, 10, 248}, - dictWord{10, 10, 349}, - dictWord{10, 10, 647}, - dictWord{11, 10, 527}, - dictWord{11, 10, 660}, - dictWord{11, 10, 669}, - dictWord{ - 12, - 10, - 529, - }, - dictWord{141, 10, 305}, - dictWord{7, 11, 296}, - dictWord{7, 11, 596}, - dictWord{8, 11, 560}, - dictWord{8, 11, 586}, - dictWord{9, 11, 612}, - dictWord{ - 11, - 11, - 100, - }, - dictWord{11, 11, 304}, - dictWord{12, 11, 46}, - dictWord{13, 11, 89}, - dictWord{14, 11, 112}, - dictWord{145, 11, 122}, - dictWord{9, 0, 370}, - dictWord{ - 138, - 0, - 90, - }, - dictWord{136, 10, 13}, - dictWord{132, 0, 860}, - dictWord{7, 10, 642}, - dictWord{8, 10, 250}, - dictWord{11, 10, 123}, - dictWord{11, 10, 137}, - dictWord{ - 13, - 10, - 48, - }, - dictWord{142, 10, 95}, - dictWord{135, 10, 1429}, - dictWord{137, 11, 321}, - dictWord{132, 0, 257}, - dictWord{135, 0, 2031}, - dictWord{7, 0, 1768}, - dictWord{7, 11, 1599}, - dictWord{7, 11, 1723}, - dictWord{8, 11, 79}, - dictWord{8, 11, 106}, - dictWord{8, 11, 190}, - dictWord{8, 11, 302}, - dictWord{8, 11, 383}, - dictWord{9, 11, 119}, - dictWord{9, 11, 233}, - dictWord{9, 11, 298}, - dictWord{9, 11, 419}, - dictWord{9, 11, 471}, - dictWord{10, 11, 181}, - dictWord{10, 11, 406}, - dictWord{11, 11, 57}, - dictWord{11, 11, 85}, - dictWord{11, 11, 120}, - dictWord{11, 11, 177}, - dictWord{11, 11, 296}, - dictWord{11, 11, 382}, - dictWord{11, 11, 454}, - dictWord{11, 11, 758}, - dictWord{11, 11, 999}, - dictWord{12, 11, 27}, - dictWord{12, 11, 98}, - dictWord{12, 11, 131}, - dictWord{12, 11, 245}, - dictWord{ - 12, - 11, - 312, - }, - dictWord{12, 11, 446}, - dictWord{12, 11, 454}, - dictWord{13, 11, 25}, - dictWord{13, 11, 98}, - dictWord{13, 11, 426}, - dictWord{13, 11, 508}, - dictWord{ - 14, - 11, - 6, - }, - dictWord{14, 11, 163}, - dictWord{14, 11, 272}, - dictWord{14, 11, 277}, - dictWord{14, 11, 370}, - dictWord{15, 11, 95}, - dictWord{15, 11, 138}, - dictWord{ - 15, - 11, - 167, - }, - dictWord{17, 11, 18}, - dictWord{17, 11, 38}, - dictWord{20, 11, 96}, - dictWord{149, 11, 32}, - dictWord{5, 11, 722}, - dictWord{134, 11, 1759}, - dictWord{145, 11, 16}, - dictWord{6, 0, 1071}, - dictWord{134, 0, 1561}, - dictWord{10, 10, 545}, - dictWord{140, 10, 301}, - dictWord{6, 0, 83}, - dictWord{6, 0, 1733}, - dictWord{135, 0, 1389}, - dictWord{4, 0, 835}, - dictWord{135, 0, 1818}, - dictWord{133, 11, 258}, - dictWord{4, 10, 904}, - dictWord{133, 10, 794}, - dictWord{ - 134, - 0, - 2006, - }, - dictWord{5, 11, 30}, - dictWord{7, 11, 495}, - dictWord{8, 11, 134}, - dictWord{9, 11, 788}, - dictWord{140, 11, 438}, - dictWord{135, 11, 2004}, - dictWord{ - 137, - 0, - 696, - }, - dictWord{5, 11, 50}, - dictWord{6, 11, 439}, - dictWord{7, 11, 780}, - dictWord{135, 11, 1040}, - dictWord{7, 11, 772}, - dictWord{7, 11, 1104}, - dictWord{ - 7, - 11, - 1647, - }, - dictWord{11, 11, 269}, - dictWord{11, 11, 539}, - dictWord{11, 11, 607}, - dictWord{11, 11, 627}, - dictWord{11, 11, 706}, - dictWord{11, 11, 975}, - dictWord{12, 11, 248}, - dictWord{12, 11, 311}, - dictWord{12, 11, 434}, - dictWord{12, 11, 600}, - dictWord{12, 11, 622}, - dictWord{13, 11, 297}, - dictWord{ - 13, - 11, - 367, - }, - dictWord{13, 11, 485}, - dictWord{14, 11, 69}, - dictWord{14, 11, 409}, - dictWord{143, 11, 108}, - dictWord{5, 11, 1}, - dictWord{6, 11, 81}, - dictWord{ - 138, - 11, - 520, - }, - dictWord{7, 0, 1718}, - dictWord{9, 0, 95}, - dictWord{9, 0, 274}, - dictWord{10, 0, 279}, - dictWord{10, 0, 317}, - dictWord{10, 0, 420}, - dictWord{11, 0, 303}, - dictWord{11, 0, 808}, - dictWord{12, 0, 134}, - dictWord{12, 0, 367}, - dictWord{13, 0, 149}, - dictWord{13, 0, 347}, - dictWord{14, 0, 349}, - dictWord{14, 0, 406}, - dictWord{ - 18, - 0, - 22, - }, - dictWord{18, 0, 89}, - dictWord{18, 0, 122}, - dictWord{147, 0, 47}, - dictWord{5, 11, 482}, - dictWord{8, 11, 98}, - dictWord{9, 11, 172}, - dictWord{10, 11, 222}, - dictWord{10, 11, 700}, - dictWord{10, 11, 822}, - dictWord{11, 11, 302}, - dictWord{11, 11, 778}, - dictWord{12, 11, 50}, - dictWord{12, 11, 127}, - dictWord{ - 12, - 11, - 396, - }, - dictWord{13, 11, 62}, - dictWord{13, 11, 328}, - dictWord{14, 11, 122}, - dictWord{147, 11, 72}, - dictWord{7, 10, 386}, - dictWord{138, 10, 713}, - dictWord{ - 6, - 10, - 7, - }, - dictWord{6, 10, 35}, - dictWord{7, 10, 147}, - dictWord{7, 10, 1069}, - dictWord{7, 10, 1568}, - dictWord{7, 10, 1575}, - dictWord{7, 10, 1917}, - dictWord{ - 8, - 10, - 43, - }, - dictWord{8, 10, 208}, - dictWord{9, 10, 128}, - dictWord{9, 10, 866}, - dictWord{10, 10, 20}, - dictWord{11, 10, 981}, - dictWord{147, 10, 33}, - dictWord{ - 133, - 0, - 26, - }, - dictWord{132, 0, 550}, - dictWord{5, 11, 2}, - dictWord{7, 11, 1494}, - dictWord{136, 11, 589}, - dictWord{6, 11, 512}, - dictWord{7, 11, 797}, - dictWord{ - 8, - 11, - 253, - }, - dictWord{9, 11, 77}, - dictWord{10, 11, 1}, - dictWord{10, 11, 129}, - dictWord{10, 11, 225}, - dictWord{11, 11, 118}, - dictWord{11, 11, 226}, - dictWord{ - 11, - 11, - 251, - }, - dictWord{11, 11, 430}, - dictWord{11, 11, 701}, - dictWord{11, 11, 974}, - dictWord{11, 11, 982}, - dictWord{12, 11, 64}, - dictWord{12, 11, 260}, - dictWord{ - 12, - 11, - 488, - }, - dictWord{140, 11, 690}, - dictWord{7, 10, 893}, - dictWord{141, 10, 424}, - dictWord{134, 0, 901}, - dictWord{136, 0, 822}, - dictWord{4, 0, 902}, - dictWord{5, 0, 809}, - dictWord{134, 0, 122}, - dictWord{6, 0, 807}, - dictWord{134, 0, 1366}, - dictWord{7, 0, 262}, - dictWord{5, 11, 748}, - dictWord{134, 11, 553}, - dictWord{133, 0, 620}, - dictWord{4, 0, 34}, - dictWord{5, 0, 574}, - dictWord{7, 0, 279}, - dictWord{7, 0, 1624}, - dictWord{136, 0, 601}, - dictWord{9, 0, 170}, - dictWord{ - 6, - 10, - 322, - }, - dictWord{9, 10, 552}, - dictWord{11, 10, 274}, - dictWord{13, 10, 209}, - dictWord{13, 10, 499}, - dictWord{14, 10, 85}, - dictWord{15, 10, 126}, - dictWord{ - 145, - 10, - 70, - }, - dictWord{132, 0, 537}, - dictWord{4, 11, 12}, - dictWord{7, 11, 420}, - dictWord{7, 11, 522}, - dictWord{7, 11, 809}, - dictWord{8, 11, 797}, - dictWord{ - 141, - 11, - 88, - }, - dictWord{133, 0, 332}, - dictWord{8, 10, 83}, - dictWord{8, 10, 742}, - dictWord{8, 10, 817}, - dictWord{9, 10, 28}, - dictWord{9, 10, 29}, - dictWord{9, 10, 885}, - dictWord{10, 10, 387}, - dictWord{11, 10, 633}, - dictWord{11, 10, 740}, - dictWord{13, 10, 235}, - dictWord{13, 10, 254}, - dictWord{15, 10, 143}, - dictWord{ - 143, - 10, - 146, - }, - dictWord{6, 0, 1909}, - dictWord{9, 0, 964}, - dictWord{12, 0, 822}, - dictWord{12, 0, 854}, - dictWord{12, 0, 865}, - dictWord{12, 0, 910}, - dictWord{12, 0, 938}, - dictWord{15, 0, 169}, - dictWord{15, 0, 208}, - dictWord{15, 0, 211}, - dictWord{18, 0, 205}, - dictWord{18, 0, 206}, - dictWord{18, 0, 220}, - dictWord{18, 0, 223}, - dictWord{152, 0, 24}, - dictWord{140, 10, 49}, - dictWord{5, 11, 528}, - dictWord{135, 11, 1580}, - dictWord{6, 0, 261}, - dictWord{8, 0, 182}, - dictWord{139, 0, 943}, - dictWord{134, 0, 1721}, - dictWord{4, 0, 933}, - dictWord{133, 0, 880}, - dictWord{136, 11, 321}, - dictWord{5, 11, 266}, - dictWord{9, 11, 290}, - dictWord{9, 11, 364}, - dictWord{10, 11, 293}, - dictWord{11, 11, 606}, - dictWord{142, 11, 45}, - dictWord{6, 0, 1609}, - dictWord{4, 11, 50}, - dictWord{6, 11, 510}, - dictWord{6, 11, 594}, - dictWord{9, 11, 121}, - dictWord{10, 11, 49}, - dictWord{10, 11, 412}, - dictWord{139, 11, 834}, - dictWord{7, 0, 895}, - dictWord{136, 11, 748}, - dictWord{132, 11, 466}, - dictWord{4, 10, 110}, - dictWord{10, 10, 415}, - dictWord{10, 10, 597}, - dictWord{142, 10, 206}, - dictWord{133, 0, 812}, - dictWord{135, 11, 281}, - dictWord{ - 6, - 0, - 1890, - }, - dictWord{6, 0, 1902}, - dictWord{6, 0, 1916}, - dictWord{9, 0, 929}, - dictWord{9, 0, 942}, - dictWord{9, 0, 975}, - dictWord{9, 0, 984}, - dictWord{9, 0, 986}, - dictWord{ - 9, - 0, - 1011, - }, - dictWord{9, 0, 1019}, - dictWord{12, 0, 804}, - dictWord{12, 0, 851}, - dictWord{12, 0, 867}, - dictWord{12, 0, 916}, - dictWord{12, 0, 923}, - dictWord{ - 15, - 0, - 194, - }, - dictWord{15, 0, 204}, - dictWord{15, 0, 210}, - dictWord{15, 0, 222}, - dictWord{15, 0, 223}, - dictWord{15, 0, 229}, - dictWord{15, 0, 250}, - dictWord{ - 18, - 0, - 179, - }, - dictWord{18, 0, 186}, - dictWord{18, 0, 192}, - dictWord{7, 10, 205}, - dictWord{135, 10, 2000}, - dictWord{132, 11, 667}, - dictWord{135, 0, 778}, - dictWord{ - 4, - 0, - 137, - }, - dictWord{7, 0, 1178}, - dictWord{135, 0, 1520}, - dictWord{134, 0, 1314}, - dictWord{4, 11, 242}, - dictWord{134, 11, 333}, - dictWord{6, 0, 1661}, - dictWord{7, 0, 1975}, - dictWord{7, 0, 2009}, - dictWord{135, 0, 2011}, - dictWord{134, 0, 1591}, - dictWord{4, 10, 283}, - dictWord{135, 10, 1194}, - dictWord{ - 11, - 0, - 820, - }, - dictWord{150, 0, 51}, - dictWord{4, 11, 39}, - dictWord{5, 11, 36}, - dictWord{7, 11, 1843}, - dictWord{8, 11, 407}, - dictWord{11, 11, 144}, - dictWord{ - 140, - 11, - 523, - }, - dictWord{134, 10, 1720}, - dictWord{4, 11, 510}, - dictWord{7, 11, 29}, - dictWord{7, 11, 66}, - dictWord{7, 11, 1980}, - dictWord{10, 11, 487}, - dictWord{ - 10, - 11, - 809, - }, - dictWord{146, 11, 9}, - dictWord{5, 0, 89}, - dictWord{7, 0, 1915}, - dictWord{9, 0, 185}, - dictWord{9, 0, 235}, - dictWord{10, 0, 64}, - dictWord{10, 0, 270}, - dictWord{10, 0, 403}, - dictWord{10, 0, 469}, - dictWord{10, 0, 529}, - dictWord{10, 0, 590}, - dictWord{11, 0, 140}, - dictWord{11, 0, 860}, - dictWord{13, 0, 1}, - dictWord{ - 13, - 0, - 422, - }, - dictWord{14, 0, 341}, - dictWord{14, 0, 364}, - dictWord{17, 0, 93}, - dictWord{18, 0, 113}, - dictWord{19, 0, 97}, - dictWord{147, 0, 113}, - dictWord{133, 0, 695}, - dictWord{6, 0, 987}, - dictWord{134, 0, 1160}, - dictWord{5, 0, 6}, - dictWord{6, 0, 183}, - dictWord{7, 0, 680}, - dictWord{7, 0, 978}, - dictWord{7, 0, 1013}, - dictWord{ - 7, - 0, - 1055, - }, - dictWord{12, 0, 230}, - dictWord{13, 0, 172}, - dictWord{146, 0, 29}, - dictWord{134, 11, 570}, - dictWord{132, 11, 787}, - dictWord{134, 11, 518}, - dictWord{ - 6, - 0, - 29, - }, - dictWord{139, 0, 63}, - dictWord{132, 11, 516}, - dictWord{136, 11, 821}, - dictWord{132, 0, 311}, - dictWord{134, 0, 1740}, - dictWord{7, 0, 170}, - dictWord{8, 0, 90}, - dictWord{8, 0, 177}, - dictWord{8, 0, 415}, - dictWord{11, 0, 714}, - dictWord{14, 0, 281}, - dictWord{136, 10, 735}, - dictWord{134, 0, 1961}, - dictWord{ - 135, - 11, - 1405, - }, - dictWord{4, 11, 10}, - dictWord{7, 11, 917}, - dictWord{139, 11, 786}, - dictWord{5, 10, 132}, - dictWord{9, 10, 486}, - dictWord{9, 10, 715}, - dictWord{ - 10, - 10, - 458, - }, - dictWord{11, 10, 373}, - dictWord{11, 10, 668}, - dictWord{11, 10, 795}, - dictWord{11, 10, 897}, - dictWord{12, 10, 272}, - dictWord{12, 10, 424}, - dictWord{12, 10, 539}, - dictWord{12, 10, 558}, - dictWord{14, 10, 245}, - dictWord{14, 10, 263}, - dictWord{14, 10, 264}, - dictWord{14, 10, 393}, - dictWord{ - 142, - 10, - 403, - }, - dictWord{11, 0, 91}, - dictWord{13, 0, 129}, - dictWord{15, 0, 101}, - dictWord{145, 0, 125}, - dictWord{135, 0, 1132}, - dictWord{4, 0, 494}, - dictWord{6, 0, 74}, - dictWord{7, 0, 44}, - dictWord{7, 0, 407}, - dictWord{12, 0, 17}, - dictWord{15, 0, 5}, - dictWord{148, 0, 11}, - dictWord{133, 10, 379}, - dictWord{5, 0, 270}, - dictWord{ - 5, - 11, - 684, - }, - dictWord{6, 10, 89}, - dictWord{6, 10, 400}, - dictWord{7, 10, 1569}, - dictWord{7, 10, 1623}, - dictWord{7, 10, 1850}, - dictWord{8, 10, 218}, - dictWord{ - 8, - 10, - 422, - }, - dictWord{9, 10, 570}, - dictWord{138, 10, 626}, - dictWord{4, 0, 276}, - dictWord{133, 0, 296}, - dictWord{6, 0, 1523}, - dictWord{134, 11, 27}, - dictWord{ - 6, - 10, - 387, - }, - dictWord{7, 10, 882}, - dictWord{141, 10, 111}, - dictWord{6, 10, 224}, - dictWord{7, 10, 877}, - dictWord{137, 10, 647}, - dictWord{135, 10, 790}, - dictWord{ - 4, - 0, - 7, - }, - dictWord{5, 0, 90}, - dictWord{5, 0, 158}, - dictWord{6, 0, 542}, - dictWord{7, 0, 221}, - dictWord{7, 0, 1574}, - dictWord{9, 0, 490}, - dictWord{10, 0, 540}, - dictWord{ - 11, - 0, - 443, - }, - dictWord{139, 0, 757}, - dictWord{7, 0, 588}, - dictWord{9, 0, 175}, - dictWord{138, 0, 530}, - dictWord{135, 10, 394}, - dictWord{142, 11, 23}, - dictWord{ - 134, - 0, - 786, - }, - dictWord{135, 0, 580}, - dictWord{7, 0, 88}, - dictWord{136, 0, 627}, - dictWord{5, 0, 872}, - dictWord{6, 0, 57}, - dictWord{7, 0, 471}, - dictWord{9, 0, 447}, - dictWord{137, 0, 454}, - dictWord{6, 11, 342}, - dictWord{6, 11, 496}, - dictWord{8, 11, 275}, - dictWord{137, 11, 206}, - dictWord{4, 11, 909}, - dictWord{133, 11, 940}, - dictWord{6, 0, 735}, - dictWord{132, 11, 891}, - dictWord{8, 0, 845}, - dictWord{8, 0, 916}, - dictWord{135, 10, 1409}, - dictWord{5, 0, 31}, - dictWord{134, 0, 614}, - dictWord{11, 0, 458}, - dictWord{12, 0, 15}, - dictWord{140, 0, 432}, - dictWord{8, 0, 330}, - dictWord{140, 0, 477}, - dictWord{4, 0, 530}, - dictWord{5, 0, 521}, - dictWord{ - 7, - 0, - 1200, - }, - dictWord{10, 0, 460}, - dictWord{132, 11, 687}, - dictWord{6, 0, 424}, - dictWord{135, 0, 1866}, - dictWord{9, 0, 569}, - dictWord{12, 0, 12}, - dictWord{ - 12, - 0, - 81, - }, - dictWord{12, 0, 319}, - dictWord{13, 0, 69}, - dictWord{14, 0, 259}, - dictWord{16, 0, 87}, - dictWord{17, 0, 1}, - dictWord{17, 0, 21}, - dictWord{17, 0, 24}, - dictWord{ - 18, - 0, - 15, - }, - dictWord{18, 0, 56}, - dictWord{18, 0, 59}, - dictWord{18, 0, 127}, - dictWord{18, 0, 154}, - dictWord{19, 0, 19}, - dictWord{148, 0, 31}, - dictWord{7, 0, 1302}, - dictWord{136, 10, 38}, - dictWord{134, 11, 253}, - dictWord{5, 10, 261}, - dictWord{7, 10, 78}, - dictWord{7, 10, 199}, - dictWord{8, 10, 815}, - dictWord{9, 10, 126}, - dictWord{138, 10, 342}, - dictWord{5, 0, 595}, - dictWord{135, 0, 1863}, - dictWord{6, 11, 41}, - dictWord{141, 11, 160}, - dictWord{5, 0, 13}, - dictWord{134, 0, 142}, - dictWord{6, 0, 97}, - dictWord{7, 0, 116}, - dictWord{8, 0, 322}, - dictWord{8, 0, 755}, - dictWord{9, 0, 548}, - dictWord{10, 0, 714}, - dictWord{11, 0, 884}, - dictWord{13, 0, 324}, - dictWord{7, 11, 1304}, - dictWord{138, 11, 477}, - dictWord{132, 10, 628}, - dictWord{134, 11, 1718}, - dictWord{7, 10, 266}, - dictWord{136, 10, 804}, - dictWord{135, 10, 208}, - dictWord{7, 0, 1021}, - dictWord{6, 10, 79}, - dictWord{135, 10, 1519}, - dictWord{7, 0, 1472}, - dictWord{135, 0, 1554}, - dictWord{6, 11, 362}, - dictWord{146, 11, 51}, - dictWord{7, 0, 1071}, - dictWord{7, 0, 1541}, - dictWord{7, 0, 1767}, - dictWord{7, 0, 1806}, - dictWord{11, 0, 162}, - dictWord{11, 0, 242}, - dictWord{11, 0, 452}, - dictWord{12, 0, 605}, - dictWord{15, 0, 26}, - dictWord{144, 0, 44}, - dictWord{136, 10, 741}, - dictWord{133, 11, 115}, - dictWord{145, 0, 115}, - dictWord{134, 10, 376}, - dictWord{6, 0, 1406}, - dictWord{134, 0, 1543}, - dictWord{5, 11, 193}, - dictWord{12, 11, 178}, - dictWord{13, 11, 130}, - dictWord{ - 145, - 11, - 84, - }, - dictWord{135, 0, 1111}, - dictWord{8, 0, 1}, - dictWord{9, 0, 650}, - dictWord{10, 0, 326}, - dictWord{5, 11, 705}, - dictWord{137, 11, 606}, - dictWord{5, 0, 488}, - dictWord{6, 0, 527}, - dictWord{7, 0, 489}, - dictWord{7, 0, 1636}, - dictWord{8, 0, 121}, - dictWord{8, 0, 144}, - dictWord{8, 0, 359}, - dictWord{9, 0, 193}, - dictWord{9, 0, 241}, - dictWord{9, 0, 336}, - dictWord{9, 0, 882}, - dictWord{11, 0, 266}, - dictWord{11, 0, 372}, - dictWord{11, 0, 944}, - dictWord{12, 0, 401}, - dictWord{140, 0, 641}, - dictWord{135, 11, 174}, - dictWord{6, 0, 267}, - dictWord{7, 10, 244}, - dictWord{7, 10, 632}, - dictWord{7, 10, 1609}, - dictWord{8, 10, 178}, - dictWord{8, 10, 638}, - dictWord{141, 10, 58}, - dictWord{134, 0, 1983}, - dictWord{134, 0, 1155}, - dictWord{134, 0, 1575}, - dictWord{134, 0, 1438}, - dictWord{9, 0, 31}, - dictWord{ - 10, - 0, - 244, - }, - dictWord{10, 0, 699}, - dictWord{12, 0, 149}, - dictWord{141, 0, 497}, - dictWord{133, 0, 377}, - dictWord{4, 11, 122}, - dictWord{5, 11, 796}, - dictWord{ - 5, - 11, - 952, - }, - dictWord{6, 11, 1660}, - dictWord{6, 11, 1671}, - dictWord{8, 11, 567}, - dictWord{9, 11, 687}, - dictWord{9, 11, 742}, - dictWord{10, 11, 686}, - dictWord{ - 11, - 11, - 356, - }, - dictWord{11, 11, 682}, - dictWord{140, 11, 281}, - dictWord{145, 0, 101}, - dictWord{11, 11, 0}, - dictWord{144, 11, 78}, - dictWord{5, 11, 179}, - dictWord{ - 5, - 10, - 791, - }, - dictWord{7, 11, 1095}, - dictWord{135, 11, 1213}, - dictWord{8, 11, 372}, - dictWord{9, 11, 122}, - dictWord{138, 11, 175}, - dictWord{7, 10, 686}, - dictWord{8, 10, 33}, - dictWord{8, 10, 238}, - dictWord{10, 10, 616}, - dictWord{11, 10, 467}, - dictWord{11, 10, 881}, - dictWord{13, 10, 217}, - dictWord{13, 10, 253}, - dictWord{142, 10, 268}, - dictWord{9, 0, 476}, - dictWord{4, 11, 66}, - dictWord{7, 11, 722}, - dictWord{135, 11, 904}, - dictWord{7, 11, 352}, - dictWord{137, 11, 684}, - dictWord{135, 0, 2023}, - dictWord{135, 0, 1836}, - dictWord{132, 10, 447}, - dictWord{5, 0, 843}, - dictWord{144, 0, 35}, - dictWord{137, 11, 779}, - dictWord{ - 141, - 11, - 35, - }, - dictWord{4, 10, 128}, - dictWord{5, 10, 415}, - dictWord{6, 10, 462}, - dictWord{7, 10, 294}, - dictWord{7, 10, 578}, - dictWord{10, 10, 710}, - dictWord{ - 139, - 10, - 86, - }, - dictWord{132, 0, 554}, - dictWord{133, 0, 536}, - dictWord{136, 10, 587}, - dictWord{5, 0, 207}, - dictWord{9, 0, 79}, - dictWord{11, 0, 625}, - dictWord{ - 145, - 0, - 7, - }, - dictWord{7, 0, 1371}, - dictWord{6, 10, 427}, - dictWord{138, 10, 692}, - dictWord{4, 0, 424}, - dictWord{4, 10, 195}, - dictWord{135, 10, 802}, - dictWord{ - 8, - 0, - 785, - }, - dictWord{133, 11, 564}, - dictWord{135, 0, 336}, - dictWord{4, 0, 896}, - dictWord{6, 0, 1777}, - dictWord{134, 11, 556}, - dictWord{137, 11, 103}, - dictWord{134, 10, 1683}, - dictWord{7, 11, 544}, - dictWord{8, 11, 719}, - dictWord{138, 11, 61}, - dictWord{138, 10, 472}, - dictWord{4, 11, 5}, - dictWord{5, 11, 498}, - dictWord{136, 11, 637}, - dictWord{7, 0, 750}, - dictWord{9, 0, 223}, - dictWord{11, 0, 27}, - dictWord{11, 0, 466}, - dictWord{12, 0, 624}, - dictWord{14, 0, 265}, - dictWord{ - 146, - 0, - 61, - }, - dictWord{12, 0, 238}, - dictWord{18, 0, 155}, - dictWord{12, 11, 238}, - dictWord{146, 11, 155}, - dictWord{151, 10, 28}, - dictWord{133, 11, 927}, - dictWord{12, 0, 383}, - dictWord{5, 10, 3}, - dictWord{8, 10, 578}, - dictWord{9, 10, 118}, - dictWord{10, 10, 705}, - dictWord{141, 10, 279}, - dictWord{4, 11, 893}, - dictWord{ - 5, - 11, - 780, - }, - dictWord{133, 11, 893}, - dictWord{4, 0, 603}, - dictWord{133, 0, 661}, - dictWord{4, 0, 11}, - dictWord{6, 0, 128}, - dictWord{7, 0, 231}, - dictWord{ - 7, - 0, - 1533, - }, - dictWord{10, 0, 725}, - dictWord{5, 10, 229}, - dictWord{5, 11, 238}, - dictWord{135, 11, 1350}, - dictWord{8, 10, 102}, - dictWord{10, 10, 578}, - dictWord{ - 10, - 10, - 672, - }, - dictWord{12, 10, 496}, - dictWord{13, 10, 408}, - dictWord{14, 10, 121}, - dictWord{145, 10, 106}, - dictWord{132, 0, 476}, - dictWord{134, 0, 1552}, - dictWord{134, 11, 1729}, - dictWord{8, 10, 115}, - dictWord{8, 10, 350}, - dictWord{9, 10, 489}, - dictWord{10, 10, 128}, - dictWord{11, 10, 306}, - dictWord{ - 12, - 10, - 373, - }, - dictWord{14, 10, 30}, - dictWord{17, 10, 79}, - dictWord{19, 10, 80}, - dictWord{150, 10, 55}, - dictWord{135, 0, 1807}, - dictWord{4, 0, 680}, - dictWord{ - 4, - 11, - 60, - }, - dictWord{7, 11, 760}, - dictWord{7, 11, 1800}, - dictWord{8, 11, 314}, - dictWord{9, 11, 700}, - dictWord{139, 11, 487}, - dictWord{4, 10, 230}, - dictWord{ - 5, - 10, - 702, - }, - dictWord{148, 11, 94}, - dictWord{132, 11, 228}, - dictWord{139, 0, 435}, - dictWord{9, 0, 20}, - dictWord{10, 0, 324}, - dictWord{10, 0, 807}, - dictWord{ - 139, - 0, - 488, - }, - dictWord{6, 10, 1728}, - dictWord{136, 11, 419}, - dictWord{4, 10, 484}, - dictWord{18, 10, 26}, - dictWord{19, 10, 42}, - dictWord{20, 10, 43}, - dictWord{ - 21, - 10, - 0, - }, - dictWord{23, 10, 27}, - dictWord{152, 10, 14}, - dictWord{135, 0, 1431}, - dictWord{133, 11, 828}, - dictWord{5, 0, 112}, - dictWord{6, 0, 103}, - dictWord{ - 6, - 0, - 150, - }, - dictWord{7, 0, 1303}, - dictWord{9, 0, 292}, - dictWord{10, 0, 481}, - dictWord{20, 0, 13}, - dictWord{7, 11, 176}, - dictWord{7, 11, 178}, - dictWord{7, 11, 1110}, - dictWord{10, 11, 481}, - dictWord{148, 11, 13}, - dictWord{138, 0, 356}, - dictWord{4, 11, 51}, - dictWord{5, 11, 39}, - dictWord{6, 11, 4}, - dictWord{7, 11, 591}, - dictWord{ - 7, - 11, - 849, - }, - dictWord{7, 11, 951}, - dictWord{7, 11, 1129}, - dictWord{7, 11, 1613}, - dictWord{7, 11, 1760}, - dictWord{7, 11, 1988}, - dictWord{9, 11, 434}, - dictWord{10, 11, 754}, - dictWord{11, 11, 25}, - dictWord{11, 11, 37}, - dictWord{139, 11, 414}, - dictWord{6, 0, 1963}, - dictWord{134, 0, 2000}, - dictWord{ - 132, - 10, - 633, - }, - dictWord{6, 0, 1244}, - dictWord{133, 11, 902}, - dictWord{135, 11, 928}, - dictWord{140, 0, 18}, - dictWord{138, 0, 204}, - dictWord{135, 11, 1173}, - dictWord{134, 0, 867}, - dictWord{4, 0, 708}, - dictWord{8, 0, 15}, - dictWord{9, 0, 50}, - dictWord{9, 0, 386}, - dictWord{11, 0, 18}, - dictWord{11, 0, 529}, - dictWord{140, 0, 228}, - dictWord{134, 11, 270}, - dictWord{4, 0, 563}, - dictWord{7, 0, 109}, - dictWord{7, 0, 592}, - dictWord{7, 0, 637}, - dictWord{7, 0, 770}, - dictWord{8, 0, 463}, - dictWord{ - 9, - 0, - 60, - }, - dictWord{9, 0, 335}, - dictWord{9, 0, 904}, - dictWord{10, 0, 73}, - dictWord{11, 0, 434}, - dictWord{12, 0, 585}, - dictWord{13, 0, 331}, - dictWord{18, 0, 110}, - dictWord{148, 0, 60}, - dictWord{132, 0, 502}, - dictWord{14, 11, 359}, - dictWord{19, 11, 52}, - dictWord{148, 11, 47}, - dictWord{6, 11, 377}, - dictWord{7, 11, 1025}, - dictWord{9, 11, 613}, - dictWord{145, 11, 104}, - dictWord{6, 0, 347}, - dictWord{10, 0, 161}, - dictWord{5, 10, 70}, - dictWord{5, 10, 622}, - dictWord{6, 10, 334}, - dictWord{ - 7, - 10, - 1032, - }, - dictWord{9, 10, 171}, - dictWord{11, 10, 26}, - dictWord{11, 10, 213}, - dictWord{11, 10, 637}, - dictWord{11, 10, 707}, - dictWord{12, 10, 202}, - dictWord{12, 10, 380}, - dictWord{13, 10, 226}, - dictWord{13, 10, 355}, - dictWord{14, 10, 222}, - dictWord{145, 10, 42}, - dictWord{132, 11, 416}, - dictWord{4, 0, 33}, - dictWord{5, 0, 102}, - dictWord{6, 0, 284}, - dictWord{7, 0, 1079}, - dictWord{7, 0, 1423}, - dictWord{7, 0, 1702}, - dictWord{8, 0, 470}, - dictWord{9, 0, 554}, - dictWord{ - 9, - 0, - 723, - }, - dictWord{11, 0, 333}, - dictWord{142, 11, 372}, - dictWord{5, 11, 152}, - dictWord{5, 11, 197}, - dictWord{7, 11, 340}, - dictWord{7, 11, 867}, - dictWord{ - 10, - 11, - 548, - }, - dictWord{10, 11, 581}, - dictWord{11, 11, 6}, - dictWord{12, 11, 3}, - dictWord{12, 11, 19}, - dictWord{14, 11, 110}, - dictWord{142, 11, 289}, - dictWord{ - 7, - 0, - 246, - }, - dictWord{135, 0, 840}, - dictWord{6, 0, 10}, - dictWord{8, 0, 571}, - dictWord{9, 0, 739}, - dictWord{143, 0, 91}, - dictWord{6, 0, 465}, - dictWord{7, 0, 1465}, - dictWord{ - 4, - 10, - 23, - }, - dictWord{4, 10, 141}, - dictWord{5, 10, 313}, - dictWord{5, 10, 1014}, - dictWord{6, 10, 50}, - dictWord{7, 10, 142}, - dictWord{7, 10, 559}, - dictWord{ - 8, - 10, - 640, - }, - dictWord{9, 10, 460}, - dictWord{9, 10, 783}, - dictWord{11, 10, 741}, - dictWord{12, 10, 183}, - dictWord{141, 10, 488}, - dictWord{133, 0, 626}, - dictWord{ - 136, - 0, - 614, - }, - dictWord{138, 0, 237}, - dictWord{7, 11, 34}, - dictWord{7, 11, 190}, - dictWord{8, 11, 28}, - dictWord{8, 11, 141}, - dictWord{8, 11, 444}, - dictWord{ - 8, - 11, - 811, - }, - dictWord{9, 11, 468}, - dictWord{11, 11, 334}, - dictWord{12, 11, 24}, - dictWord{12, 11, 386}, - dictWord{140, 11, 576}, - dictWord{133, 11, 757}, - dictWord{ - 5, - 0, - 18, - }, - dictWord{6, 0, 526}, - dictWord{13, 0, 24}, - dictWord{13, 0, 110}, - dictWord{19, 0, 5}, - dictWord{147, 0, 44}, - dictWord{6, 0, 506}, - dictWord{134, 11, 506}, - dictWord{135, 11, 1553}, - dictWord{4, 0, 309}, - dictWord{5, 0, 462}, - dictWord{7, 0, 970}, - dictWord{7, 0, 1097}, - dictWord{22, 0, 30}, - dictWord{22, 0, 33}, - dictWord{ - 7, - 11, - 1385, - }, - dictWord{11, 11, 582}, - dictWord{11, 11, 650}, - dictWord{11, 11, 901}, - dictWord{11, 11, 949}, - dictWord{12, 11, 232}, - dictWord{12, 11, 236}, - dictWord{13, 11, 413}, - dictWord{13, 11, 501}, - dictWord{146, 11, 116}, - dictWord{9, 0, 140}, - dictWord{5, 10, 222}, - dictWord{138, 10, 534}, - dictWord{6, 0, 1056}, - dictWord{137, 10, 906}, - dictWord{134, 0, 1704}, - dictWord{138, 10, 503}, - dictWord{134, 0, 1036}, - dictWord{5, 10, 154}, - dictWord{7, 10, 1491}, - dictWord{ - 10, - 10, - 379, - }, - dictWord{138, 10, 485}, - dictWord{4, 11, 383}, - dictWord{133, 10, 716}, - dictWord{134, 0, 1315}, - dictWord{5, 0, 86}, - dictWord{7, 0, 743}, - dictWord{ - 9, - 0, - 85, - }, - dictWord{10, 0, 281}, - dictWord{10, 0, 432}, - dictWord{11, 0, 825}, - dictWord{12, 0, 251}, - dictWord{13, 0, 118}, - dictWord{142, 0, 378}, - dictWord{ - 8, - 0, - 264, - }, - dictWord{4, 10, 91}, - dictWord{5, 10, 388}, - dictWord{5, 10, 845}, - dictWord{6, 10, 206}, - dictWord{6, 10, 252}, - dictWord{6, 10, 365}, - dictWord{7, 10, 136}, - dictWord{7, 10, 531}, - dictWord{136, 10, 621}, - dictWord{5, 0, 524}, - dictWord{133, 0, 744}, - dictWord{5, 11, 277}, - dictWord{141, 11, 247}, - dictWord{ - 132, - 11, - 435, - }, - dictWord{10, 0, 107}, - dictWord{140, 0, 436}, - dictWord{132, 0, 927}, - dictWord{10, 0, 123}, - dictWord{12, 0, 670}, - dictWord{146, 0, 94}, - dictWord{ - 7, - 0, - 1149, - }, - dictWord{9, 0, 156}, - dictWord{138, 0, 957}, - dictWord{5, 11, 265}, - dictWord{6, 11, 212}, - dictWord{135, 11, 28}, - dictWord{133, 0, 778}, - dictWord{ - 133, - 0, - 502, - }, - dictWord{8, 0, 196}, - dictWord{10, 0, 283}, - dictWord{139, 0, 406}, - dictWord{135, 10, 576}, - dictWord{136, 11, 535}, - dictWord{134, 0, 1312}, - dictWord{ - 5, - 10, - 771, - }, - dictWord{5, 10, 863}, - dictWord{5, 10, 898}, - dictWord{6, 10, 1632}, - dictWord{6, 10, 1644}, - dictWord{134, 10, 1780}, - dictWord{5, 0, 855}, - dictWord{5, 10, 331}, - dictWord{135, 11, 1487}, - dictWord{132, 11, 702}, - dictWord{5, 11, 808}, - dictWord{135, 11, 2045}, - dictWord{7, 0, 1400}, - dictWord{ - 9, - 0, - 446, - }, - dictWord{138, 0, 45}, - dictWord{140, 10, 632}, - dictWord{132, 0, 1003}, - dictWord{5, 11, 166}, - dictWord{8, 11, 739}, - dictWord{140, 11, 511}, - dictWord{ - 5, - 10, - 107, - }, - dictWord{7, 10, 201}, - dictWord{136, 10, 518}, - dictWord{6, 10, 446}, - dictWord{135, 10, 1817}, - dictWord{134, 0, 1532}, - dictWord{ - 134, - 0, - 1097, - }, - dictWord{4, 11, 119}, - dictWord{5, 11, 170}, - dictWord{5, 11, 447}, - dictWord{7, 11, 1708}, - dictWord{7, 11, 1889}, - dictWord{9, 11, 357}, - dictWord{ - 9, - 11, - 719, - }, - dictWord{12, 11, 486}, - dictWord{140, 11, 596}, - dictWord{9, 10, 851}, - dictWord{141, 10, 510}, - dictWord{7, 0, 612}, - dictWord{8, 0, 545}, - dictWord{ - 8, - 0, - 568, - }, - dictWord{8, 0, 642}, - dictWord{9, 0, 717}, - dictWord{10, 0, 541}, - dictWord{10, 0, 763}, - dictWord{11, 0, 449}, - dictWord{12, 0, 489}, - dictWord{13, 0, 153}, - dictWord{13, 0, 296}, - dictWord{14, 0, 138}, - dictWord{14, 0, 392}, - dictWord{15, 0, 50}, - dictWord{16, 0, 6}, - dictWord{16, 0, 12}, - dictWord{20, 0, 9}, - dictWord{ - 132, - 10, - 504, - }, - dictWord{4, 11, 450}, - dictWord{135, 11, 1158}, - dictWord{11, 0, 54}, - dictWord{13, 0, 173}, - dictWord{13, 0, 294}, - dictWord{5, 10, 883}, - dictWord{ - 5, - 10, - 975, - }, - dictWord{8, 10, 392}, - dictWord{148, 10, 7}, - dictWord{13, 0, 455}, - dictWord{15, 0, 99}, - dictWord{15, 0, 129}, - dictWord{144, 0, 68}, - dictWord{135, 0, 172}, - dictWord{132, 11, 754}, - dictWord{5, 10, 922}, - dictWord{134, 10, 1707}, - dictWord{134, 0, 1029}, - dictWord{17, 11, 39}, - dictWord{148, 11, 36}, - dictWord{ - 4, - 0, - 568, - }, - dictWord{5, 10, 993}, - dictWord{7, 10, 515}, - dictWord{137, 10, 91}, - dictWord{132, 0, 732}, - dictWord{10, 0, 617}, - dictWord{138, 11, 617}, - dictWord{ - 134, - 0, - 974, - }, - dictWord{7, 0, 989}, - dictWord{10, 0, 377}, - dictWord{12, 0, 363}, - dictWord{13, 0, 68}, - dictWord{13, 0, 94}, - dictWord{14, 0, 108}, - dictWord{ - 142, - 0, - 306, - }, - dictWord{136, 0, 733}, - dictWord{132, 0, 428}, - dictWord{7, 0, 1789}, - dictWord{135, 11, 1062}, - dictWord{7, 0, 2015}, - dictWord{140, 0, 665}, - dictWord{135, 10, 1433}, - dictWord{5, 0, 287}, - dictWord{7, 10, 921}, - dictWord{8, 10, 580}, - dictWord{8, 10, 593}, - dictWord{8, 10, 630}, - dictWord{138, 10, 28}, - dictWord{138, 0, 806}, - dictWord{4, 10, 911}, - dictWord{5, 10, 867}, - dictWord{5, 10, 1013}, - dictWord{7, 10, 2034}, - dictWord{8, 10, 798}, - dictWord{136, 10, 813}, - dictWord{134, 0, 1539}, - dictWord{8, 11, 523}, - dictWord{150, 11, 34}, - dictWord{135, 11, 740}, - dictWord{7, 11, 238}, - dictWord{7, 11, 2033}, - dictWord{ - 8, - 11, - 120, - }, - dictWord{8, 11, 188}, - dictWord{8, 11, 659}, - dictWord{9, 11, 598}, - dictWord{10, 11, 466}, - dictWord{12, 11, 342}, - dictWord{12, 11, 588}, - dictWord{ - 13, - 11, - 503, - }, - dictWord{14, 11, 246}, - dictWord{143, 11, 92}, - dictWord{7, 0, 1563}, - dictWord{141, 0, 182}, - dictWord{5, 10, 135}, - dictWord{6, 10, 519}, - dictWord{ - 7, - 10, - 1722, - }, - dictWord{10, 10, 271}, - dictWord{11, 10, 261}, - dictWord{145, 10, 54}, - dictWord{14, 10, 338}, - dictWord{148, 10, 81}, - dictWord{7, 0, 484}, - dictWord{ - 4, - 10, - 300, - }, - dictWord{133, 10, 436}, - dictWord{145, 11, 114}, - dictWord{6, 0, 1623}, - dictWord{134, 0, 1681}, - dictWord{133, 11, 640}, - dictWord{4, 11, 201}, - dictWord{7, 11, 1744}, - dictWord{8, 11, 602}, - dictWord{11, 11, 247}, - dictWord{11, 11, 826}, - dictWord{145, 11, 65}, - dictWord{8, 11, 164}, - dictWord{ - 146, - 11, - 62, - }, - dictWord{6, 0, 1833}, - dictWord{6, 0, 1861}, - dictWord{136, 0, 878}, - dictWord{134, 0, 1569}, - dictWord{8, 10, 357}, - dictWord{10, 10, 745}, - dictWord{ - 14, - 10, - 426, - }, - dictWord{17, 10, 94}, - dictWord{147, 10, 57}, - dictWord{12, 0, 93}, - dictWord{12, 0, 501}, - dictWord{13, 0, 362}, - dictWord{14, 0, 151}, - dictWord{15, 0, 40}, - dictWord{15, 0, 59}, - dictWord{16, 0, 46}, - dictWord{17, 0, 25}, - dictWord{18, 0, 14}, - dictWord{18, 0, 134}, - dictWord{19, 0, 25}, - dictWord{19, 0, 69}, - dictWord{ - 20, - 0, - 16, - }, - dictWord{20, 0, 19}, - dictWord{20, 0, 66}, - dictWord{21, 0, 23}, - dictWord{21, 0, 25}, - dictWord{150, 0, 42}, - dictWord{6, 0, 1748}, - dictWord{8, 0, 715}, - dictWord{ - 9, - 0, - 802, - }, - dictWord{10, 0, 46}, - dictWord{10, 0, 819}, - dictWord{13, 0, 308}, - dictWord{14, 0, 351}, - dictWord{14, 0, 363}, - dictWord{146, 0, 67}, - dictWord{ - 132, - 0, - 994, - }, - dictWord{4, 0, 63}, - dictWord{133, 0, 347}, - dictWord{132, 0, 591}, - dictWord{133, 0, 749}, - dictWord{7, 11, 1577}, - dictWord{10, 11, 304}, - dictWord{ - 10, - 11, - 549, - }, - dictWord{11, 11, 424}, - dictWord{12, 11, 365}, - dictWord{13, 11, 220}, - dictWord{13, 11, 240}, - dictWord{142, 11, 33}, - dictWord{133, 0, 366}, - dictWord{ - 7, - 0, - 557, - }, - dictWord{12, 0, 547}, - dictWord{14, 0, 86}, - dictWord{133, 10, 387}, - dictWord{135, 0, 1747}, - dictWord{132, 11, 907}, - dictWord{5, 11, 100}, - dictWord{10, 11, 329}, - dictWord{12, 11, 416}, - dictWord{149, 11, 29}, - dictWord{4, 10, 6}, - dictWord{5, 10, 708}, - dictWord{136, 10, 75}, - dictWord{7, 10, 1351}, - dictWord{9, 10, 581}, - dictWord{10, 10, 639}, - dictWord{11, 10, 453}, - dictWord{140, 10, 584}, - dictWord{7, 0, 89}, - dictWord{132, 10, 303}, - dictWord{138, 10, 772}, - dictWord{132, 11, 176}, - dictWord{5, 11, 636}, - dictWord{5, 11, 998}, - dictWord{8, 11, 26}, - dictWord{137, 11, 358}, - dictWord{7, 11, 9}, - dictWord{7, 11, 1508}, - dictWord{9, 11, 317}, - dictWord{10, 11, 210}, - dictWord{10, 11, 292}, - dictWord{10, 11, 533}, - dictWord{11, 11, 555}, - dictWord{12, 11, 526}, - dictWord{ - 12, - 11, - 607, - }, - dictWord{13, 11, 263}, - dictWord{13, 11, 459}, - dictWord{142, 11, 271}, - dictWord{134, 0, 1463}, - dictWord{6, 0, 772}, - dictWord{6, 0, 1137}, - dictWord{ - 139, - 11, - 595, - }, - dictWord{7, 0, 977}, - dictWord{139, 11, 66}, - dictWord{138, 0, 893}, - dictWord{20, 0, 48}, - dictWord{148, 11, 48}, - dictWord{5, 0, 824}, - dictWord{ - 133, - 0, - 941, - }, - dictWord{134, 11, 295}, - dictWord{7, 0, 1543}, - dictWord{7, 0, 1785}, - dictWord{10, 0, 690}, - dictWord{4, 10, 106}, - dictWord{139, 10, 717}, - dictWord{ - 7, - 0, - 440, - }, - dictWord{8, 0, 230}, - dictWord{139, 0, 106}, - dictWord{5, 10, 890}, - dictWord{133, 10, 988}, - dictWord{6, 10, 626}, - dictWord{142, 10, 431}, - dictWord{ - 10, - 11, - 127, - }, - dictWord{141, 11, 27}, - dictWord{17, 0, 32}, - dictWord{10, 10, 706}, - dictWord{150, 10, 44}, - dictWord{132, 0, 216}, - dictWord{137, 0, 332}, - dictWord{4, 10, 698}, - dictWord{136, 11, 119}, - dictWord{139, 11, 267}, - dictWord{138, 10, 17}, - dictWord{11, 11, 526}, - dictWord{11, 11, 939}, - dictWord{ - 141, - 11, - 290, - }, - dictWord{7, 11, 1167}, - dictWord{11, 11, 934}, - dictWord{13, 11, 391}, - dictWord{145, 11, 76}, - dictWord{139, 11, 39}, - dictWord{134, 10, 84}, - dictWord{ - 4, - 0, - 914, - }, - dictWord{5, 0, 800}, - dictWord{133, 0, 852}, - dictWord{10, 0, 416}, - dictWord{141, 0, 115}, - dictWord{7, 0, 564}, - dictWord{142, 0, 168}, - dictWord{ - 4, - 0, - 918, - }, - dictWord{133, 0, 876}, - dictWord{134, 0, 1764}, - dictWord{152, 0, 3}, - dictWord{4, 0, 92}, - dictWord{5, 0, 274}, - dictWord{7, 11, 126}, - dictWord{136, 11, 84}, - dictWord{140, 10, 498}, - dictWord{136, 11, 790}, - dictWord{8, 0, 501}, - dictWord{5, 10, 986}, - dictWord{6, 10, 130}, - dictWord{7, 10, 1582}, - dictWord{ - 8, - 10, - 458, - }, - dictWord{10, 10, 101}, - dictWord{10, 10, 318}, - dictWord{138, 10, 823}, - dictWord{6, 11, 64}, - dictWord{12, 11, 377}, - dictWord{141, 11, 309}, - dictWord{ - 5, - 0, - 743, - }, - dictWord{138, 0, 851}, - dictWord{4, 0, 49}, - dictWord{7, 0, 280}, - dictWord{135, 0, 1633}, - dictWord{134, 0, 879}, - dictWord{136, 0, 47}, - dictWord{ - 7, - 10, - 1644, - }, - dictWord{137, 10, 129}, - dictWord{132, 0, 865}, - dictWord{134, 0, 1202}, - dictWord{9, 11, 34}, - dictWord{139, 11, 484}, - dictWord{135, 10, 997}, - dictWord{5, 0, 272}, - dictWord{5, 0, 908}, - dictWord{5, 0, 942}, - dictWord{8, 0, 197}, - dictWord{9, 0, 47}, - dictWord{11, 0, 538}, - dictWord{139, 0, 742}, - dictWord{ - 6, - 11, - 1700, - }, - dictWord{7, 11, 26}, - dictWord{7, 11, 293}, - dictWord{7, 11, 382}, - dictWord{7, 11, 1026}, - dictWord{7, 11, 1087}, - dictWord{7, 11, 2027}, - dictWord{ - 8, - 11, - 24, - }, - dictWord{8, 11, 114}, - dictWord{8, 11, 252}, - dictWord{8, 11, 727}, - dictWord{8, 11, 729}, - dictWord{9, 11, 30}, - dictWord{9, 11, 199}, - dictWord{9, 11, 231}, - dictWord{9, 11, 251}, - dictWord{9, 11, 334}, - dictWord{9, 11, 361}, - dictWord{9, 11, 488}, - dictWord{9, 11, 712}, - dictWord{10, 11, 55}, - dictWord{10, 11, 60}, - dictWord{ - 10, - 11, - 232, - }, - dictWord{10, 11, 332}, - dictWord{10, 11, 384}, - dictWord{10, 11, 396}, - dictWord{10, 11, 504}, - dictWord{10, 11, 542}, - dictWord{10, 11, 652}, - dictWord{11, 11, 20}, - dictWord{11, 11, 48}, - dictWord{11, 11, 207}, - dictWord{11, 11, 291}, - dictWord{11, 11, 298}, - dictWord{11, 11, 342}, - dictWord{ - 11, - 11, - 365, - }, - dictWord{11, 11, 394}, - dictWord{11, 11, 620}, - dictWord{11, 11, 705}, - dictWord{11, 11, 1017}, - dictWord{12, 11, 123}, - dictWord{12, 11, 340}, - dictWord{12, 11, 406}, - dictWord{12, 11, 643}, - dictWord{13, 11, 61}, - dictWord{13, 11, 269}, - dictWord{13, 11, 311}, - dictWord{13, 11, 319}, - dictWord{13, 11, 486}, - dictWord{14, 11, 234}, - dictWord{15, 11, 62}, - dictWord{15, 11, 85}, - dictWord{16, 11, 71}, - dictWord{18, 11, 119}, - dictWord{148, 11, 105}, - dictWord{ - 6, - 0, - 1455, - }, - dictWord{150, 11, 37}, - dictWord{135, 10, 1927}, - dictWord{135, 0, 1911}, - dictWord{137, 0, 891}, - dictWord{7, 10, 1756}, - dictWord{137, 10, 98}, - dictWord{7, 10, 1046}, - dictWord{139, 10, 160}, - dictWord{132, 0, 761}, - dictWord{6, 11, 379}, - dictWord{7, 11, 270}, - dictWord{7, 11, 1116}, - dictWord{ - 8, - 11, - 176, - }, - dictWord{8, 11, 183}, - dictWord{9, 11, 432}, - dictWord{9, 11, 661}, - dictWord{12, 11, 247}, - dictWord{12, 11, 617}, - dictWord{146, 11, 125}, - dictWord{ - 6, - 10, - 45, - }, - dictWord{7, 10, 433}, - dictWord{8, 10, 129}, - dictWord{9, 10, 21}, - dictWord{10, 10, 392}, - dictWord{11, 10, 79}, - dictWord{12, 10, 499}, - dictWord{ - 13, - 10, - 199, - }, - dictWord{141, 10, 451}, - dictWord{4, 0, 407}, - dictWord{5, 11, 792}, - dictWord{133, 11, 900}, - dictWord{132, 0, 560}, - dictWord{135, 0, 183}, - dictWord{ - 13, - 0, - 490, - }, - dictWord{7, 10, 558}, - dictWord{136, 10, 353}, - dictWord{4, 0, 475}, - dictWord{6, 0, 731}, - dictWord{11, 0, 35}, - dictWord{13, 0, 71}, - dictWord{13, 0, 177}, - dictWord{14, 0, 422}, - dictWord{133, 10, 785}, - dictWord{8, 10, 81}, - dictWord{9, 10, 189}, - dictWord{9, 10, 201}, - dictWord{11, 10, 478}, - dictWord{11, 10, 712}, - dictWord{141, 10, 338}, - dictWord{4, 0, 418}, - dictWord{4, 0, 819}, - dictWord{133, 10, 353}, - dictWord{151, 10, 26}, - dictWord{4, 11, 901}, - dictWord{ - 133, - 11, - 776, - }, - dictWord{132, 0, 575}, - dictWord{7, 0, 818}, - dictWord{16, 0, 92}, - dictWord{17, 0, 14}, - dictWord{17, 0, 45}, - dictWord{18, 0, 75}, - dictWord{148, 0, 18}, - dictWord{ - 6, - 0, - 222, - }, - dictWord{7, 0, 636}, - dictWord{7, 0, 1620}, - dictWord{8, 0, 409}, - dictWord{9, 0, 693}, - dictWord{139, 0, 77}, - dictWord{6, 10, 25}, - dictWord{7, 10, 855}, - dictWord{7, 10, 1258}, - dictWord{144, 10, 32}, - dictWord{6, 0, 1880}, - dictWord{6, 0, 1887}, - dictWord{6, 0, 1918}, - dictWord{6, 0, 1924}, - dictWord{9, 0, 967}, - dictWord{9, 0, 995}, - dictWord{9, 0, 1015}, - dictWord{12, 0, 826}, - dictWord{12, 0, 849}, - dictWord{12, 0, 857}, - dictWord{12, 0, 860}, - dictWord{12, 0, 886}, - dictWord{ - 12, - 0, - 932, - }, - dictWord{18, 0, 228}, - dictWord{18, 0, 231}, - dictWord{146, 0, 240}, - dictWord{134, 0, 633}, - dictWord{134, 0, 1308}, - dictWord{4, 11, 37}, - dictWord{ - 5, - 11, - 334, - }, - dictWord{135, 11, 1253}, - dictWord{10, 0, 86}, - dictWord{4, 10, 4}, - dictWord{7, 10, 1118}, - dictWord{7, 10, 1320}, - dictWord{7, 10, 1706}, - dictWord{ - 8, - 10, - 277, - }, - dictWord{9, 10, 622}, - dictWord{11, 10, 724}, - dictWord{12, 10, 350}, - dictWord{12, 10, 397}, - dictWord{13, 10, 28}, - dictWord{13, 10, 159}, - dictWord{ - 15, - 10, - 89, - }, - dictWord{18, 10, 5}, - dictWord{19, 10, 9}, - dictWord{20, 10, 34}, - dictWord{150, 10, 47}, - dictWord{132, 11, 508}, - dictWord{137, 11, 448}, - dictWord{ - 12, - 11, - 107, - }, - dictWord{146, 11, 31}, - dictWord{132, 0, 817}, - dictWord{134, 0, 663}, - dictWord{133, 0, 882}, - dictWord{134, 0, 914}, - dictWord{132, 11, 540}, - dictWord{132, 11, 533}, - dictWord{136, 11, 608}, - dictWord{8, 0, 885}, - dictWord{138, 0, 865}, - dictWord{132, 0, 426}, - dictWord{6, 0, 58}, - dictWord{7, 0, 745}, - dictWord{7, 0, 1969}, - dictWord{8, 0, 399}, - dictWord{8, 0, 675}, - dictWord{9, 0, 479}, - dictWord{9, 0, 731}, - dictWord{10, 0, 330}, - dictWord{10, 0, 593}, - dictWord{ - 10, - 0, - 817, - }, - dictWord{11, 0, 32}, - dictWord{11, 0, 133}, - dictWord{11, 0, 221}, - dictWord{145, 0, 68}, - dictWord{134, 10, 255}, - dictWord{7, 0, 102}, - dictWord{ - 137, - 0, - 538, - }, - dictWord{137, 10, 216}, - dictWord{7, 11, 253}, - dictWord{136, 11, 549}, - dictWord{135, 11, 912}, - dictWord{9, 10, 183}, - dictWord{139, 10, 286}, - dictWord{11, 10, 956}, - dictWord{151, 10, 3}, - dictWord{8, 11, 527}, - dictWord{18, 11, 60}, - dictWord{147, 11, 24}, - dictWord{4, 10, 536}, - dictWord{7, 10, 1141}, - dictWord{10, 10, 723}, - dictWord{139, 10, 371}, - dictWord{133, 11, 920}, - dictWord{7, 0, 876}, - dictWord{135, 10, 285}, - dictWord{135, 10, 560}, - dictWord{ - 132, - 10, - 690, - }, - dictWord{142, 11, 126}, - dictWord{11, 10, 33}, - dictWord{12, 10, 571}, - dictWord{149, 10, 1}, - dictWord{133, 0, 566}, - dictWord{9, 0, 139}, - dictWord{ - 10, - 0, - 399, - }, - dictWord{11, 0, 469}, - dictWord{12, 0, 634}, - dictWord{13, 0, 223}, - dictWord{132, 11, 483}, - dictWord{6, 0, 48}, - dictWord{135, 0, 63}, - dictWord{18, 0, 12}, - dictWord{7, 10, 1862}, - dictWord{12, 10, 491}, - dictWord{12, 10, 520}, - dictWord{13, 10, 383}, - dictWord{142, 10, 244}, - dictWord{135, 11, 1665}, - dictWord{132, 11, 448}, - dictWord{9, 11, 495}, - dictWord{146, 11, 104}, - dictWord{6, 0, 114}, - dictWord{7, 0, 1224}, - dictWord{7, 0, 1556}, - dictWord{136, 0, 3}, - dictWord{ - 4, - 10, - 190, - }, - dictWord{133, 10, 554}, - dictWord{8, 0, 576}, - dictWord{9, 0, 267}, - dictWord{133, 10, 1001}, - dictWord{133, 10, 446}, - dictWord{133, 0, 933}, - dictWord{139, 11, 1009}, - dictWord{8, 11, 653}, - dictWord{13, 11, 93}, - dictWord{147, 11, 14}, - dictWord{6, 0, 692}, - dictWord{6, 0, 821}, - dictWord{134, 0, 1077}, - dictWord{5, 11, 172}, - dictWord{135, 11, 801}, - dictWord{138, 0, 752}, - dictWord{4, 0, 375}, - dictWord{134, 0, 638}, - dictWord{134, 0, 1011}, - dictWord{ - 140, - 11, - 540, - }, - dictWord{9, 0, 96}, - dictWord{133, 11, 260}, - dictWord{139, 11, 587}, - dictWord{135, 10, 1231}, - dictWord{12, 0, 30}, - dictWord{13, 0, 148}, - dictWord{ - 14, - 0, - 87, - }, - dictWord{14, 0, 182}, - dictWord{16, 0, 42}, - dictWord{20, 0, 70}, - dictWord{132, 10, 304}, - dictWord{6, 0, 1398}, - dictWord{7, 0, 56}, - dictWord{7, 0, 1989}, - dictWord{8, 0, 337}, - dictWord{8, 0, 738}, - dictWord{9, 0, 600}, - dictWord{12, 0, 37}, - dictWord{13, 0, 447}, - dictWord{142, 0, 92}, - dictWord{138, 0, 666}, - dictWord{ - 5, - 0, - 394, - }, - dictWord{7, 0, 487}, - dictWord{136, 0, 246}, - dictWord{9, 0, 437}, - dictWord{6, 10, 53}, - dictWord{6, 10, 199}, - dictWord{7, 10, 1408}, - dictWord{8, 10, 32}, - dictWord{8, 10, 93}, - dictWord{10, 10, 397}, - dictWord{10, 10, 629}, - dictWord{11, 10, 593}, - dictWord{11, 10, 763}, - dictWord{13, 10, 326}, - dictWord{145, 10, 35}, - dictWord{134, 10, 105}, - dictWord{9, 0, 320}, - dictWord{10, 0, 506}, - dictWord{138, 10, 794}, - dictWord{7, 11, 57}, - dictWord{8, 11, 167}, - dictWord{8, 11, 375}, - dictWord{9, 11, 82}, - dictWord{9, 11, 561}, - dictWord{10, 11, 620}, - dictWord{10, 11, 770}, - dictWord{11, 10, 704}, - dictWord{141, 10, 396}, - dictWord{6, 0, 1003}, - dictWord{5, 10, 114}, - dictWord{5, 10, 255}, - dictWord{141, 10, 285}, - dictWord{7, 0, 866}, - dictWord{135, 0, 1163}, - dictWord{133, 11, 531}, - dictWord{ - 132, - 0, - 328, - }, - dictWord{7, 10, 2035}, - dictWord{8, 10, 19}, - dictWord{9, 10, 89}, - dictWord{138, 10, 831}, - dictWord{8, 11, 194}, - dictWord{136, 11, 756}, - dictWord{ - 136, - 0, - 1000, - }, - dictWord{5, 11, 453}, - dictWord{134, 11, 441}, - dictWord{4, 0, 101}, - dictWord{5, 0, 833}, - dictWord{7, 0, 1171}, - dictWord{136, 0, 744}, - dictWord{ - 133, - 0, - 726, - }, - dictWord{136, 10, 746}, - dictWord{138, 0, 176}, - dictWord{6, 0, 9}, - dictWord{6, 0, 397}, - dictWord{7, 0, 53}, - dictWord{7, 0, 1742}, - dictWord{10, 0, 632}, - dictWord{11, 0, 828}, - dictWord{140, 0, 146}, - dictWord{135, 11, 22}, - dictWord{145, 11, 64}, - dictWord{132, 0, 839}, - dictWord{11, 0, 417}, - dictWord{12, 0, 223}, - dictWord{140, 0, 265}, - dictWord{4, 11, 102}, - dictWord{7, 11, 815}, - dictWord{7, 11, 1699}, - dictWord{139, 11, 964}, - dictWord{5, 10, 955}, - dictWord{ - 136, - 10, - 814, - }, - dictWord{6, 0, 1931}, - dictWord{6, 0, 2007}, - dictWord{18, 0, 246}, - dictWord{146, 0, 247}, - dictWord{8, 0, 198}, - dictWord{11, 0, 29}, - dictWord{140, 0, 534}, - dictWord{135, 0, 1771}, - dictWord{6, 0, 846}, - dictWord{7, 11, 1010}, - dictWord{11, 11, 733}, - dictWord{11, 11, 759}, - dictWord{12, 11, 563}, - dictWord{ - 13, - 11, - 34, - }, - dictWord{14, 11, 101}, - dictWord{18, 11, 45}, - dictWord{146, 11, 129}, - dictWord{4, 0, 186}, - dictWord{5, 0, 157}, - dictWord{8, 0, 168}, - dictWord{138, 0, 6}, - dictWord{132, 11, 899}, - dictWord{133, 10, 56}, - dictWord{148, 10, 100}, - dictWord{133, 0, 875}, - dictWord{5, 0, 773}, - dictWord{5, 0, 991}, - dictWord{6, 0, 1635}, - dictWord{134, 0, 1788}, - dictWord{6, 0, 1274}, - dictWord{9, 0, 477}, - dictWord{141, 0, 78}, - dictWord{4, 0, 639}, - dictWord{7, 0, 111}, - dictWord{8, 0, 581}, - dictWord{ - 12, - 0, - 177, - }, - dictWord{6, 11, 52}, - dictWord{9, 11, 104}, - dictWord{9, 11, 559}, - dictWord{10, 10, 4}, - dictWord{10, 10, 13}, - dictWord{11, 10, 638}, - dictWord{ - 12, - 11, - 308, - }, - dictWord{19, 11, 87}, - dictWord{148, 10, 57}, - dictWord{132, 11, 604}, - dictWord{4, 11, 301}, - dictWord{133, 10, 738}, - dictWord{133, 10, 758}, - dictWord{134, 0, 1747}, - dictWord{7, 11, 1440}, - dictWord{11, 11, 854}, - dictWord{11, 11, 872}, - dictWord{11, 11, 921}, - dictWord{12, 11, 551}, - dictWord{ - 13, - 11, - 472, - }, - dictWord{142, 11, 367}, - dictWord{7, 0, 1364}, - dictWord{7, 0, 1907}, - dictWord{141, 0, 158}, - dictWord{134, 0, 873}, - dictWord{4, 0, 404}, - dictWord{ - 4, - 0, - 659, - }, - dictWord{7, 0, 552}, - dictWord{135, 0, 675}, - dictWord{135, 10, 1112}, - dictWord{139, 10, 328}, - dictWord{7, 11, 508}, - dictWord{137, 10, 133}, - dictWord{133, 0, 391}, - dictWord{5, 10, 110}, - dictWord{6, 10, 169}, - dictWord{6, 10, 1702}, - dictWord{7, 10, 400}, - dictWord{8, 10, 538}, - dictWord{9, 10, 184}, - dictWord{ - 9, - 10, - 524, - }, - dictWord{140, 10, 218}, - dictWord{6, 11, 310}, - dictWord{7, 11, 1849}, - dictWord{8, 11, 72}, - dictWord{8, 11, 272}, - dictWord{8, 11, 431}, - dictWord{ - 9, - 11, - 12, - }, - dictWord{9, 11, 351}, - dictWord{10, 11, 563}, - dictWord{10, 11, 630}, - dictWord{10, 11, 810}, - dictWord{11, 11, 367}, - dictWord{11, 11, 599}, - dictWord{11, 11, 686}, - dictWord{140, 11, 672}, - dictWord{5, 0, 540}, - dictWord{6, 0, 1697}, - dictWord{136, 0, 668}, - dictWord{132, 0, 883}, - dictWord{134, 0, 78}, - dictWord{12, 0, 628}, - dictWord{18, 0, 79}, - dictWord{6, 10, 133}, - dictWord{9, 10, 353}, - dictWord{139, 10, 993}, - dictWord{6, 11, 181}, - dictWord{7, 11, 537}, - dictWord{ - 8, - 11, - 64, - }, - dictWord{9, 11, 127}, - dictWord{10, 11, 496}, - dictWord{12, 11, 510}, - dictWord{141, 11, 384}, - dictWord{6, 10, 93}, - dictWord{7, 10, 1422}, - dictWord{ - 7, - 10, - 1851, - }, - dictWord{8, 10, 673}, - dictWord{9, 10, 529}, - dictWord{140, 10, 43}, - dictWord{137, 10, 371}, - dictWord{134, 0, 1460}, - dictWord{134, 0, 962}, - dictWord{4, 11, 244}, - dictWord{135, 11, 233}, - dictWord{9, 10, 25}, - dictWord{10, 10, 467}, - dictWord{138, 10, 559}, - dictWord{4, 10, 335}, - dictWord{ - 135, - 10, - 942, - }, - dictWord{133, 0, 460}, - dictWord{135, 11, 334}, - dictWord{134, 11, 1650}, - dictWord{4, 0, 199}, - dictWord{139, 0, 34}, - dictWord{5, 10, 601}, - dictWord{ - 8, - 10, - 39, - }, - dictWord{10, 10, 773}, - dictWord{11, 10, 84}, - dictWord{12, 10, 205}, - dictWord{142, 10, 1}, - dictWord{133, 10, 870}, - dictWord{134, 0, 388}, - dictWord{14, 0, 474}, - dictWord{148, 0, 120}, - dictWord{133, 11, 369}, - dictWord{139, 0, 271}, - dictWord{4, 0, 511}, - dictWord{9, 0, 333}, - dictWord{9, 0, 379}, - dictWord{ - 10, - 0, - 602, - }, - dictWord{11, 0, 441}, - dictWord{11, 0, 723}, - dictWord{11, 0, 976}, - dictWord{12, 0, 357}, - dictWord{132, 10, 181}, - dictWord{134, 0, 608}, - dictWord{134, 10, 1652}, - dictWord{22, 0, 49}, - dictWord{137, 11, 338}, - dictWord{140, 0, 988}, - dictWord{134, 0, 617}, - dictWord{5, 0, 938}, - dictWord{136, 0, 707}, - dictWord{132, 10, 97}, - dictWord{5, 10, 147}, - dictWord{6, 10, 286}, - dictWord{7, 10, 1362}, - dictWord{141, 10, 176}, - dictWord{6, 0, 756}, - dictWord{ - 134, - 0, - 1149, - }, - dictWord{133, 11, 896}, - dictWord{6, 10, 375}, - dictWord{7, 10, 169}, - dictWord{7, 10, 254}, - dictWord{136, 10, 780}, - dictWord{134, 0, 1583}, - dictWord{135, 10, 1447}, - dictWord{139, 0, 285}, - dictWord{7, 11, 1117}, - dictWord{8, 11, 393}, - dictWord{136, 11, 539}, - dictWord{135, 0, 344}, - dictWord{ - 6, - 0, - 469, - }, - dictWord{7, 0, 1709}, - dictWord{138, 0, 515}, - dictWord{5, 10, 629}, - dictWord{135, 10, 1549}, - dictWord{5, 11, 4}, - dictWord{5, 11, 810}, - dictWord{ - 6, - 11, - 13, - }, - dictWord{6, 11, 538}, - dictWord{6, 11, 1690}, - dictWord{6, 11, 1726}, - dictWord{7, 11, 499}, - dictWord{7, 11, 1819}, - dictWord{8, 11, 148}, - dictWord{ - 8, - 11, - 696, - }, - dictWord{8, 11, 791}, - dictWord{12, 11, 125}, - dictWord{13, 11, 54}, - dictWord{143, 11, 9}, - dictWord{135, 11, 1268}, - dictWord{137, 0, 404}, - dictWord{ - 132, - 0, - 500, - }, - dictWord{5, 0, 68}, - dictWord{134, 0, 383}, - dictWord{11, 0, 216}, - dictWord{139, 0, 340}, - dictWord{4, 11, 925}, - dictWord{5, 11, 803}, - dictWord{ - 8, - 11, - 698, - }, - dictWord{138, 11, 828}, - dictWord{4, 0, 337}, - dictWord{6, 0, 353}, - dictWord{7, 0, 1934}, - dictWord{8, 0, 488}, - dictWord{137, 0, 429}, - dictWord{7, 0, 236}, - dictWord{7, 0, 1795}, - dictWord{8, 0, 259}, - dictWord{9, 0, 135}, - dictWord{9, 0, 177}, - dictWord{9, 0, 860}, - dictWord{10, 0, 825}, - dictWord{11, 0, 115}, - dictWord{ - 11, - 0, - 370, - }, - dictWord{11, 0, 405}, - dictWord{11, 0, 604}, - dictWord{12, 0, 10}, - dictWord{12, 0, 667}, - dictWord{12, 0, 669}, - dictWord{13, 0, 76}, - dictWord{14, 0, 310}, - dictWord{15, 0, 76}, - dictWord{15, 0, 147}, - dictWord{148, 0, 23}, - dictWord{4, 0, 15}, - dictWord{4, 0, 490}, - dictWord{5, 0, 22}, - dictWord{6, 0, 244}, - dictWord{7, 0, 40}, - dictWord{7, 0, 200}, - dictWord{7, 0, 906}, - dictWord{7, 0, 1199}, - dictWord{9, 0, 616}, - dictWord{10, 0, 716}, - dictWord{11, 0, 635}, - dictWord{11, 0, 801}, - dictWord{ - 140, - 0, - 458, - }, - dictWord{12, 0, 756}, - dictWord{132, 10, 420}, - dictWord{134, 0, 1504}, - dictWord{6, 0, 757}, - dictWord{133, 11, 383}, - dictWord{6, 0, 1266}, - dictWord{ - 135, - 0, - 1735, - }, - dictWord{5, 0, 598}, - dictWord{7, 0, 791}, - dictWord{8, 0, 108}, - dictWord{9, 0, 123}, - dictWord{7, 10, 1570}, - dictWord{140, 10, 542}, - dictWord{ - 142, - 11, - 410, - }, - dictWord{9, 11, 660}, - dictWord{138, 11, 347}, -} diff --git a/src/vendor/github.com/andybalholm/brotli/symbol_list.go b/src/vendor/github.com/andybalholm/brotli/symbol_list.go deleted file mode 100644 index c5cb49e5..00000000 --- a/src/vendor/github.com/andybalholm/brotli/symbol_list.go +++ /dev/null @@ -1,22 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Utilities for building Huffman decoding tables. */ - -type symbolList struct { - storage []uint16 - offset int -} - -func symbolListGet(sl symbolList, i int) uint16 { - return sl.storage[i+sl.offset] -} - -func symbolListPut(sl symbolList, i int, val uint16) { - sl.storage[i+sl.offset] = val -} diff --git a/src/vendor/github.com/andybalholm/brotli/transform.go b/src/vendor/github.com/andybalholm/brotli/transform.go deleted file mode 100644 index d2c043a6..00000000 --- a/src/vendor/github.com/andybalholm/brotli/transform.go +++ /dev/null @@ -1,641 +0,0 @@ -package brotli - -const ( - transformIdentity = 0 - transformOmitLast1 = 1 - transformOmitLast2 = 2 - transformOmitLast3 = 3 - transformOmitLast4 = 4 - transformOmitLast5 = 5 - transformOmitLast6 = 6 - transformOmitLast7 = 7 - transformOmitLast8 = 8 - transformOmitLast9 = 9 - transformUppercaseFirst = 10 - transformUppercaseAll = 11 - transformOmitFirst1 = 12 - transformOmitFirst2 = 13 - transformOmitFirst3 = 14 - transformOmitFirst4 = 15 - transformOmitFirst5 = 16 - transformOmitFirst6 = 17 - transformOmitFirst7 = 18 - transformOmitFirst8 = 19 - transformOmitFirst9 = 20 - transformShiftFirst = 21 - transformShiftAll = 22 + iota - 22 - numTransformTypes -) - -const transformsMaxCutOff = transformOmitLast9 - -type transforms struct { - prefix_suffix_size uint16 - prefix_suffix []byte - prefix_suffix_map []uint16 - num_transforms uint32 - transforms []byte - params []byte - cutOffTransforms [transformsMaxCutOff + 1]int16 -} - -func transformPrefixId(t *transforms, I int) byte { - return t.transforms[(I*3)+0] -} - -func transformType(t *transforms, I int) byte { - return t.transforms[(I*3)+1] -} - -func transformSuffixId(t *transforms, I int) byte { - return t.transforms[(I*3)+2] -} - -func transformPrefix(t *transforms, I int) []byte { - return t.prefix_suffix[t.prefix_suffix_map[transformPrefixId(t, I)]:] -} - -func transformSuffix(t *transforms, I int) []byte { - return t.prefix_suffix[t.prefix_suffix_map[transformSuffixId(t, I)]:] -} - -/* RFC 7932 transforms string data */ -const kPrefixSuffix string = "\001 \002, \010 of the \004 of \002s \001.\005 and \004 " + "in \001\"\004 to \002\">\001\n\002. \001]\005 for \003 a \006 " + "that \001'\006 with \006 from \004 by \001(\006. T" + "he \004 on \004 as \004 is \004ing \002\n\t\001:\003ed " + "\002=\"\004 at \003ly \001,\002='\005.com/\007. This \005" + " not \003er \003al \004ful \004ive \005less \004es" + "t \004ize \002\xc2\xa0\004ous \005 the \002e \000" - -var kPrefixSuffixMap = [50]uint16{ - 0x00, - 0x02, - 0x05, - 0x0E, - 0x13, - 0x16, - 0x18, - 0x1E, - 0x23, - 0x25, - 0x2A, - 0x2D, - 0x2F, - 0x32, - 0x34, - 0x3A, - 0x3E, - 0x45, - 0x47, - 0x4E, - 0x55, - 0x5A, - 0x5C, - 0x63, - 0x68, - 0x6D, - 0x72, - 0x77, - 0x7A, - 0x7C, - 0x80, - 0x83, - 0x88, - 0x8C, - 0x8E, - 0x91, - 0x97, - 0x9F, - 0xA5, - 0xA9, - 0xAD, - 0xB2, - 0xB7, - 0xBD, - 0xC2, - 0xC7, - 0xCA, - 0xCF, - 0xD5, - 0xD8, -} - -/* RFC 7932 transforms */ -var kTransformsData = []byte{ - 49, - transformIdentity, - 49, - 49, - transformIdentity, - 0, - 0, - transformIdentity, - 0, - 49, - transformOmitFirst1, - 49, - 49, - transformUppercaseFirst, - 0, - 49, - transformIdentity, - 47, - 0, - transformIdentity, - 49, - 4, - transformIdentity, - 0, - 49, - transformIdentity, - 3, - 49, - transformUppercaseFirst, - 49, - 49, - transformIdentity, - 6, - 49, - transformOmitFirst2, - 49, - 49, - transformOmitLast1, - 49, - 1, - transformIdentity, - 0, - 49, - transformIdentity, - 1, - 0, - transformUppercaseFirst, - 0, - 49, - transformIdentity, - 7, - 49, - transformIdentity, - 9, - 48, - transformIdentity, - 0, - 49, - transformIdentity, - 8, - 49, - transformIdentity, - 5, - 49, - transformIdentity, - 10, - 49, - transformIdentity, - 11, - 49, - transformOmitLast3, - 49, - 49, - transformIdentity, - 13, - 49, - transformIdentity, - 14, - 49, - transformOmitFirst3, - 49, - 49, - transformOmitLast2, - 49, - 49, - transformIdentity, - 15, - 49, - transformIdentity, - 16, - 0, - transformUppercaseFirst, - 49, - 49, - transformIdentity, - 12, - 5, - transformIdentity, - 49, - 0, - transformIdentity, - 1, - 49, - transformOmitFirst4, - 49, - 49, - transformIdentity, - 18, - 49, - transformIdentity, - 17, - 49, - transformIdentity, - 19, - 49, - transformIdentity, - 20, - 49, - transformOmitFirst5, - 49, - 49, - transformOmitFirst6, - 49, - 47, - transformIdentity, - 49, - 49, - transformOmitLast4, - 49, - 49, - transformIdentity, - 22, - 49, - transformUppercaseAll, - 49, - 49, - transformIdentity, - 23, - 49, - transformIdentity, - 24, - 49, - transformIdentity, - 25, - 49, - transformOmitLast7, - 49, - 49, - transformOmitLast1, - 26, - 49, - transformIdentity, - 27, - 49, - transformIdentity, - 28, - 0, - transformIdentity, - 12, - 49, - transformIdentity, - 29, - 49, - transformOmitFirst9, - 49, - 49, - transformOmitFirst7, - 49, - 49, - transformOmitLast6, - 49, - 49, - transformIdentity, - 21, - 49, - transformUppercaseFirst, - 1, - 49, - transformOmitLast8, - 49, - 49, - transformIdentity, - 31, - 49, - transformIdentity, - 32, - 47, - transformIdentity, - 3, - 49, - transformOmitLast5, - 49, - 49, - transformOmitLast9, - 49, - 0, - transformUppercaseFirst, - 1, - 49, - transformUppercaseFirst, - 8, - 5, - transformIdentity, - 21, - 49, - transformUppercaseAll, - 0, - 49, - transformUppercaseFirst, - 10, - 49, - transformIdentity, - 30, - 0, - transformIdentity, - 5, - 35, - transformIdentity, - 49, - 47, - transformIdentity, - 2, - 49, - transformUppercaseFirst, - 17, - 49, - transformIdentity, - 36, - 49, - transformIdentity, - 33, - 5, - transformIdentity, - 0, - 49, - transformUppercaseFirst, - 21, - 49, - transformUppercaseFirst, - 5, - 49, - transformIdentity, - 37, - 0, - transformIdentity, - 30, - 49, - transformIdentity, - 38, - 0, - transformUppercaseAll, - 0, - 49, - transformIdentity, - 39, - 0, - transformUppercaseAll, - 49, - 49, - transformIdentity, - 34, - 49, - transformUppercaseAll, - 8, - 49, - transformUppercaseFirst, - 12, - 0, - transformIdentity, - 21, - 49, - transformIdentity, - 40, - 0, - transformUppercaseFirst, - 12, - 49, - transformIdentity, - 41, - 49, - transformIdentity, - 42, - 49, - transformUppercaseAll, - 17, - 49, - transformIdentity, - 43, - 0, - transformUppercaseFirst, - 5, - 49, - transformUppercaseAll, - 10, - 0, - transformIdentity, - 34, - 49, - transformUppercaseFirst, - 33, - 49, - transformIdentity, - 44, - 49, - transformUppercaseAll, - 5, - 45, - transformIdentity, - 49, - 0, - transformIdentity, - 33, - 49, - transformUppercaseFirst, - 30, - 49, - transformUppercaseAll, - 30, - 49, - transformIdentity, - 46, - 49, - transformUppercaseAll, - 1, - 49, - transformUppercaseFirst, - 34, - 0, - transformUppercaseFirst, - 33, - 0, - transformUppercaseAll, - 30, - 0, - transformUppercaseAll, - 1, - 49, - transformUppercaseAll, - 33, - 49, - transformUppercaseAll, - 21, - 49, - transformUppercaseAll, - 12, - 0, - transformUppercaseAll, - 5, - 49, - transformUppercaseAll, - 34, - 0, - transformUppercaseAll, - 12, - 0, - transformUppercaseFirst, - 30, - 0, - transformUppercaseAll, - 34, - 0, - transformUppercaseFirst, - 34, -} - -var kBrotliTransforms = transforms{ - 217, - []byte(kPrefixSuffix), - kPrefixSuffixMap[:], - 121, - kTransformsData, - nil, /* no extra parameters */ - [transformsMaxCutOff + 1]int16{0, 12, 27, 23, 42, 63, 56, 48, 59, 64}, -} - -func getTransforms() *transforms { - return &kBrotliTransforms -} - -func toUpperCase(p []byte) int { - if p[0] < 0xC0 { - if p[0] >= 'a' && p[0] <= 'z' { - p[0] ^= 32 - } - - return 1 - } - - /* An overly simplified uppercasing model for UTF-8. */ - if p[0] < 0xE0 { - p[1] ^= 32 - return 2 - } - - /* An arbitrary transform for three byte characters. */ - p[2] ^= 5 - - return 3 -} - -func shiftTransform(word []byte, word_len int, parameter uint16) int { - /* Limited sign extension: scalar < (1 << 24). */ - var scalar uint32 = (uint32(parameter) & 0x7FFF) + (0x1000000 - (uint32(parameter) & 0x8000)) - if word[0] < 0x80 { - /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */ - scalar += uint32(word[0]) - - word[0] = byte(scalar & 0x7F) - return 1 - } else if word[0] < 0xC0 { - /* Continuation / 10AAAAAA. */ - return 1 - } else if word[0] < 0xE0 { - /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */ - if word_len < 2 { - return 1 - } - scalar += uint32(word[1]&0x3F | (word[0]&0x1F)<<6) - word[0] = byte(0xC0 | (scalar>>6)&0x1F) - word[1] = byte(uint32(word[1]&0xC0) | scalar&0x3F) - return 2 - } else if word[0] < 0xF0 { - /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */ - if word_len < 3 { - return word_len - } - scalar += uint32(word[2])&0x3F | uint32(word[1]&0x3F)<<6 | uint32(word[0]&0x0F)<<12 - word[0] = byte(0xE0 | (scalar>>12)&0x0F) - word[1] = byte(uint32(word[1]&0xC0) | (scalar>>6)&0x3F) - word[2] = byte(uint32(word[2]&0xC0) | scalar&0x3F) - return 3 - } else if word[0] < 0xF8 { - /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */ - if word_len < 4 { - return word_len - } - scalar += uint32(word[3])&0x3F | uint32(word[2]&0x3F)<<6 | uint32(word[1]&0x3F)<<12 | uint32(word[0]&0x07)<<18 - word[0] = byte(0xF0 | (scalar>>18)&0x07) - word[1] = byte(uint32(word[1]&0xC0) | (scalar>>12)&0x3F) - word[2] = byte(uint32(word[2]&0xC0) | (scalar>>6)&0x3F) - word[3] = byte(uint32(word[3]&0xC0) | scalar&0x3F) - return 4 - } - - return 1 -} - -func transformDictionaryWord(dst []byte, word []byte, len int, trans *transforms, transform_idx int) int { - var idx int = 0 - var prefix []byte = transformPrefix(trans, transform_idx) - var type_ byte = transformType(trans, transform_idx) - var suffix []byte = transformSuffix(trans, transform_idx) - { - var prefix_len int = int(prefix[0]) - prefix = prefix[1:] - for { - tmp1 := prefix_len - prefix_len-- - if tmp1 == 0 { - break - } - dst[idx] = prefix[0] - idx++ - prefix = prefix[1:] - } - } - { - var t int = int(type_) - var i int = 0 - if t <= transformOmitLast9 { - len -= t - } else if t >= transformOmitFirst1 && t <= transformOmitFirst9 { - var skip int = t - (transformOmitFirst1 - 1) - word = word[skip:] - len -= skip - } - - for i < len { - dst[idx] = word[i] - idx++ - i++ - } - if t == transformUppercaseFirst { - toUpperCase(dst[idx-len:]) - } else if t == transformUppercaseAll { - var uppercase []byte = dst - uppercase = uppercase[idx-len:] - for len > 0 { - var step int = toUpperCase(uppercase) - uppercase = uppercase[step:] - len -= step - } - } else if t == transformShiftFirst { - var param uint16 = uint16(trans.params[transform_idx*2]) + uint16(trans.params[transform_idx*2+1])<<8 - shiftTransform(dst[idx-len:], int(len), param) - } else if t == transformShiftAll { - var param uint16 = uint16(trans.params[transform_idx*2]) + uint16(trans.params[transform_idx*2+1])<<8 - var shift []byte = dst - shift = shift[idx-len:] - for len > 0 { - var step int = shiftTransform(shift, int(len), param) - shift = shift[step:] - len -= step - } - } - } - { - var suffix_len int = int(suffix[0]) - suffix = suffix[1:] - for { - tmp2 := suffix_len - suffix_len-- - if tmp2 == 0 { - break - } - dst[idx] = suffix[0] - idx++ - suffix = suffix[1:] - } - return idx - } -} diff --git a/src/vendor/github.com/andybalholm/brotli/utf8_util.go b/src/vendor/github.com/andybalholm/brotli/utf8_util.go deleted file mode 100644 index 3244247e..00000000 --- a/src/vendor/github.com/andybalholm/brotli/utf8_util.go +++ /dev/null @@ -1,70 +0,0 @@ -package brotli - -/* Copyright 2013 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Heuristics for deciding about the UTF8-ness of strings. */ - -const kMinUTF8Ratio float64 = 0.75 - -/* Returns 1 if at least min_fraction of the bytes between pos and - pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise - returns 0. */ -func parseAsUTF8(symbol *int, input []byte, size uint) uint { - /* ASCII */ - if input[0]&0x80 == 0 { - *symbol = int(input[0]) - if *symbol > 0 { - return 1 - } - } - - /* 2-byte UTF8 */ - if size > 1 && input[0]&0xE0 == 0xC0 && input[1]&0xC0 == 0x80 { - *symbol = (int(input[0])&0x1F)<<6 | int(input[1])&0x3F - if *symbol > 0x7F { - return 2 - } - } - - /* 3-byte UFT8 */ - if size > 2 && input[0]&0xF0 == 0xE0 && input[1]&0xC0 == 0x80 && input[2]&0xC0 == 0x80 { - *symbol = (int(input[0])&0x0F)<<12 | (int(input[1])&0x3F)<<6 | int(input[2])&0x3F - if *symbol > 0x7FF { - return 3 - } - } - - /* 4-byte UFT8 */ - if size > 3 && input[0]&0xF8 == 0xF0 && input[1]&0xC0 == 0x80 && input[2]&0xC0 == 0x80 && input[3]&0xC0 == 0x80 { - *symbol = (int(input[0])&0x07)<<18 | (int(input[1])&0x3F)<<12 | (int(input[2])&0x3F)<<6 | int(input[3])&0x3F - if *symbol > 0xFFFF && *symbol <= 0x10FFFF { - return 4 - } - } - - /* Not UTF8, emit a special symbol above the UTF8-code space */ - *symbol = 0x110000 | int(input[0]) - - return 1 -} - -/* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/ -func isMostlyUTF8(data []byte, pos uint, mask uint, length uint, min_fraction float64) bool { - var size_utf8 uint = 0 - var i uint = 0 - for i < length { - var symbol int - current_data := data[(pos+i)&mask:] - var bytes_read uint = parseAsUTF8(&symbol, current_data, length-i) - i += bytes_read - if symbol < 0x110000 { - size_utf8 += bytes_read - } - } - - return float64(size_utf8) > min_fraction*float64(length) -} diff --git a/src/vendor/github.com/andybalholm/brotli/write_bits.go b/src/vendor/github.com/andybalholm/brotli/write_bits.go deleted file mode 100644 index 87299011..00000000 --- a/src/vendor/github.com/andybalholm/brotli/write_bits.go +++ /dev/null @@ -1,52 +0,0 @@ -package brotli - -import "encoding/binary" - -/* Copyright 2010 Google Inc. All Rights Reserved. - - Distributed under MIT license. - See file LICENSE for detail or copy at https://opensource.org/licenses/MIT -*/ - -/* Write bits into a byte array. */ - -/* This function writes bits into bytes in increasing addresses, and within - a byte least-significant-bit first. - - The function can write up to 56 bits in one go with WriteBits - Example: let's assume that 3 bits (Rs below) have been written already: - - BYTE-0 BYTE+1 BYTE+2 - - 0000 0RRR 0000 0000 0000 0000 - - Now, we could write 5 or less bits in MSB by just sifting by 3 - and OR'ing to BYTE-0. - - For n bits, we take the last 5 bits, OR that with high bits in BYTE-0, - and locate the rest in BYTE+1, BYTE+2, etc. */ -func writeBits(n_bits uint, bits uint64, pos *uint, array []byte) { - /* This branch of the code can write up to 56 bits at a time, - 7 bits are lost by being perhaps already in *p and at least - 1 bit is needed to initialize the bit-stream ahead (i.e. if 7 - bits are in *p and we write 57 bits, then the next write will - access a byte that was never initialized). */ - p := array[*pos>>3:] - v := uint64(p[0]) - v |= bits << (*pos & 7) - binary.LittleEndian.PutUint64(p, v) - *pos += n_bits -} - -func writeSingleBit(bit bool, pos *uint, array []byte) { - if bit { - writeBits(1, 1, pos, array) - } else { - writeBits(1, 0, pos, array) - } -} - -func writeBitsPrepareStorage(pos uint, array []byte) { - assert(pos&7 == 0) - array[pos>>3] = 0 -} diff --git a/src/vendor/github.com/andybalholm/brotli/writer.go b/src/vendor/github.com/andybalholm/brotli/writer.go deleted file mode 100644 index ce8b80fd..00000000 --- a/src/vendor/github.com/andybalholm/brotli/writer.go +++ /dev/null @@ -1,162 +0,0 @@ -package brotli - -import ( - "errors" - "io" - - "github.com/andybalholm/brotli/matchfinder" -) - -const ( - BestSpeed = 0 - BestCompression = 11 - DefaultCompression = 6 -) - -// WriterOptions configures Writer. -type WriterOptions struct { - // Quality controls the compression-speed vs compression-density trade-offs. - // The higher the quality, the slower the compression. Range is 0 to 11. - Quality int - // LGWin is the base 2 logarithm of the sliding window size. - // Range is 10 to 24. 0 indicates automatic configuration based on Quality. - LGWin int -} - -var ( - errEncode = errors.New("brotli: encode error") - errWriterClosed = errors.New("brotli: Writer is closed") -) - -// Writes to the returned writer are compressed and written to dst. -// It is the caller's responsibility to call Close on the Writer when done. -// Writes may be buffered and not flushed until Close. -func NewWriter(dst io.Writer) *Writer { - return NewWriterLevel(dst, DefaultCompression) -} - -// NewWriterLevel is like NewWriter but specifies the compression level instead -// of assuming DefaultCompression. -// The compression level can be DefaultCompression or any integer value between -// BestSpeed and BestCompression inclusive. -func NewWriterLevel(dst io.Writer, level int) *Writer { - return NewWriterOptions(dst, WriterOptions{ - Quality: level, - }) -} - -// NewWriterOptions is like NewWriter but specifies WriterOptions -func NewWriterOptions(dst io.Writer, options WriterOptions) *Writer { - w := new(Writer) - w.options = options - w.Reset(dst) - return w -} - -// Reset discards the Writer's state and makes it equivalent to the result of -// its original state from NewWriter or NewWriterLevel, but writing to dst -// instead. This permits reusing a Writer rather than allocating a new one. -func (w *Writer) Reset(dst io.Writer) { - encoderInitState(w) - w.params.quality = w.options.Quality - if w.options.LGWin > 0 { - w.params.lgwin = uint(w.options.LGWin) - } - w.dst = dst - w.err = nil -} - -func (w *Writer) writeChunk(p []byte, op int) (n int, err error) { - if w.dst == nil { - return 0, errWriterClosed - } - if w.err != nil { - return 0, w.err - } - - for { - availableIn := uint(len(p)) - nextIn := p - success := encoderCompressStream(w, op, &availableIn, &nextIn) - bytesConsumed := len(p) - int(availableIn) - p = p[bytesConsumed:] - n += bytesConsumed - if !success { - return n, errEncode - } - - if len(p) == 0 || w.err != nil { - return n, w.err - } - } -} - -// Flush outputs encoded data for all input provided to Write. The resulting -// output can be decoded to match all input before Flush, but the stream is -// not yet complete until after Close. -// Flush has a negative impact on compression. -func (w *Writer) Flush() error { - _, err := w.writeChunk(nil, operationFlush) - return err -} - -// Close flushes remaining data to the decorated writer. -func (w *Writer) Close() error { - // If stream is already closed, it is reported by `writeChunk`. - _, err := w.writeChunk(nil, operationFinish) - w.dst = nil - return err -} - -// Write implements io.Writer. Flush or Close must be called to ensure that the -// encoded bytes are actually flushed to the underlying Writer. -func (w *Writer) Write(p []byte) (n int, err error) { - return w.writeChunk(p, operationProcess) -} - -type nopCloser struct { - io.Writer -} - -func (nopCloser) Close() error { return nil } - -// NewWriterV2 is like NewWriterLevel, but it uses the new implementation -// based on the matchfinder package. It currently supports up to level 9; -// if a higher level is specified, level 9 will be used. -func NewWriterV2(dst io.Writer, level int) *matchfinder.Writer { - if level < 0 { - level = 0 - } else if level > 9 { - level = 9 - } - var mf matchfinder.MatchFinder - switch level { - case 0, 1: - mf = &matchfinder.ZFast{MaxDistance: 1 << 20} - case 2: - mf = &matchfinder.ZDFast{MaxDistance: 1 << 20} - case 3: - mf = &matchfinder.ZM{MaxDistance: 1 << 20} - case 4: - mf = &matchfinder.Trio{MaxDistance: 1 << 20} - case 5, 6: - mf = &matchfinder.Bargain1{MaxDistance: 1 << 20} - case 7: - mf = &matchfinder.Bargain2{MaxDistance: 1 << 20, Skip: true} - case 8: - mf = &matchfinder.Bargain2{MaxDistance: 1 << 20} - case 9: - mf = &matchfinder.Bargain3{MaxDistance: 1 << 20} - } - - w := &matchfinder.Writer{ - Dest: dst, - MatchFinder: mf, - Encoder: &Encoder{}, - BlockSize: 1 << 16, - } - if level < 1 { - w.Encoder = &FastEncoder{} - } - return w -} diff --git a/src/vendor/github.com/fxamacker/cbor/v2/cache.go b/src/vendor/github.com/fxamacker/cbor/v2/cache.go index 5743f3eb..345c6b71 100644 --- a/src/vendor/github.com/fxamacker/cbor/v2/cache.go +++ b/src/vendor/github.com/fxamacker/cbor/v2/cache.go @@ -41,18 +41,21 @@ const ( ) type typeInfo struct { - elemTypeInfo *typeInfo - keyTypeInfo *typeInfo - typ reflect.Type - kind reflect.Kind - nonPtrType reflect.Type - nonPtrKind reflect.Kind - spclType specialType + elemTypeInfo *typeInfo + keyTypeInfo *typeInfo + typ reflect.Type + kind reflect.Kind + nonPtrType reflect.Type + nonPtrKind reflect.Kind + spclType specialType + keyNeedsHashableValueCheck bool } -func newTypeInfo(t reflect.Type) *typeInfo { +func newTypeInfo(t reflect.Type, newTypeInfos map[reflect.Type]*typeInfo) *typeInfo { tInfo := typeInfo{typ: t, kind: t.Kind()} + newTypeInfos[t] = &tInfo + for t.Kind() == reflect.Pointer { t = t.Elem() } @@ -82,15 +85,34 @@ func newTypeInfo(t reflect.Type) *typeInfo { switch k { case reflect.Array, reflect.Slice: - tInfo.elemTypeInfo = getTypeInfo(t.Elem()) + tInfo.elemTypeInfo = getTypeInfoWithNewTypeInfos(t.Elem(), newTypeInfos) case reflect.Map: - tInfo.keyTypeInfo = getTypeInfo(t.Key()) - tInfo.elemTypeInfo = getTypeInfo(t.Elem()) + tInfo.keyTypeInfo = getTypeInfoWithNewTypeInfos(t.Key(), newTypeInfos) + tInfo.keyNeedsHashableValueCheck = needsHashableValueCheck(t.Key()) + tInfo.elemTypeInfo = getTypeInfoWithNewTypeInfos(t.Elem(), newTypeInfos) } return &tInfo } +// needsHashableValueCheck returns true if the hashability of a value of +// the given type can't be determined by the static type. +func needsHashableValueCheck(typ reflect.Type) bool { + switch typ.Kind() { + case reflect.Interface: + return true + case reflect.Array: + return needsHashableValueCheck(typ.Elem()) + case reflect.Struct: + for i := 0; i < typ.NumField(); i++ { + if needsHashableValueCheck(typ.Field(i).Type) { + return true + } + } + } + return false +} + type decodingStructType struct { fields decodingFields fieldIndicesByName map[string]int // Only populated if toArray is false @@ -387,25 +409,112 @@ func getEncodingStructToArrayType(t reflect.Type, flds fields) (*encodingStructT return structType, nil } +type inProgressEncodeFuncs struct { + encodeFuncs + complete bool + indirectUsed bool +} + func getEncodeFunc(t reflect.Type) (encodeFunc, isEmptyFunc, isZeroFunc) { if v, _ := encodeFuncCache.Load(t); v != nil { fs := v.(encodeFuncs) return fs.ef, fs.ief, fs.izf } - ef, ief, izf := getEncodeFuncInternal(t) - encodeFuncCache.Store(t, encodeFuncs{ef, ief, izf}) - return ef, ief, izf + var rebuild bool + newEncodeFuncs := make(map[reflect.Type]*inProgressEncodeFuncs) + for unsupportedTypeCount := 0; ; { + getEncodeFuncInternal(t, newEncodeFuncs) + newEncodeFuncs, rebuild = needRebuild(newEncodeFuncs) + if !rebuild { + break + } + if _, unsupported := newEncodeFuncs[t]; unsupported { + break + } + // Every rebuild must find at least one new unsupported type. + // This check is to ensure termination. + if len(newEncodeFuncs) <= unsupportedTypeCount { + newEncodeFuncs[t] = &inProgressEncodeFuncs{complete: true} + break + } + unsupportedTypeCount = len(newEncodeFuncs) + } + for typ, fs := range newEncodeFuncs { + encodeFuncCache.Store(typ, fs.encodeFuncs) + } + return newEncodeFuncs[t].ef, newEncodeFuncs[t].ief, newEncodeFuncs[t].izf +} + +// needRebuild returns true if a type in the inProgressEncodeFuncs has a nil encodeFunc +// and was also indirectly used. +// In other words, rebuild is needed if a type: +// - was used in a closure encodeFunc during type building and +// - was resolved to be unsupported when type building was completed. +// If rebuild is needed, resolved unsupported types are returned as seed for the next rebuilding; +// otherwise, the unmodified newEncodeFuncs is returned. +// NOTE: rebuilding is not needed if all types are supported. +func needRebuild(newEncodeFuncs map[reflect.Type]*inProgressEncodeFuncs) (map[reflect.Type]*inProgressEncodeFuncs, bool) { + rebuild := false + unsupported := make(map[reflect.Type]*inProgressEncodeFuncs) + for typ, fs := range newEncodeFuncs { + if fs.ef == nil { + if fs.indirectUsed { + rebuild = true + } + unsupported[typ] = &inProgressEncodeFuncs{encodeFuncs: fs.encodeFuncs, complete: true} + } + } + if !rebuild { + return newEncodeFuncs, false + } + return unsupported, true +} + +func getEncodeFuncWithNewEncodeFuncs(t reflect.Type, newEncodeFuncs map[reflect.Type]*inProgressEncodeFuncs) encodeFunc { + if fs, found := newEncodeFuncs[t]; found { + if fs.complete { + return fs.ef + } + fs.indirectUsed = true + return func(e *bytes.Buffer, em *encMode, v reflect.Value) error { + if fs.ef == nil { + return &UnsupportedTypeError{t} + } + return fs.ef(e, em, v) + } + } + + if v, _ := encodeFuncCache.Load(t); v != nil { + fs := v.(encodeFuncs) + return fs.ef + } + + ef, _, _ := getEncodeFuncInternal(t, newEncodeFuncs) + return ef } func getTypeInfo(t reflect.Type) *typeInfo { if v, _ := typeInfoCache.Load(t); v != nil { return v.(*typeInfo) } - tInfo := newTypeInfo(t) - typeInfoCache.Store(t, tInfo) + newTypeInfos := make(map[reflect.Type]*typeInfo) + tInfo := newTypeInfo(t, newTypeInfos) + for typ, ti := range newTypeInfos { + typeInfoCache.Store(typ, ti) + } return tInfo } +func getTypeInfoWithNewTypeInfos(t reflect.Type, newTypeInfos map[reflect.Type]*typeInfo) *typeInfo { + if tInfo, found := newTypeInfos[t]; found { + return tInfo + } + if v, _ := typeInfoCache.Load(t); v != nil { + return v.(*typeInfo) + } + return newTypeInfo(t, newTypeInfos) +} + func hasToArrayOption(tag string) bool { s := ",toarray" idx := strings.Index(tag, s) diff --git a/src/vendor/github.com/fxamacker/cbor/v2/decode.go b/src/vendor/github.com/fxamacker/cbor/v2/decode.go index 1d3e63d0..80b1f678 100644 --- a/src/vendor/github.com/fxamacker/cbor/v2/decode.go +++ b/src/vendor/github.com/fxamacker/cbor/v2/decode.go @@ -93,7 +93,7 @@ import ( // and NaN float values decode to time.Time's zero value. // // To unmarshal CBOR null (0xf6) and undefined (0xf7) values into a -// slice/map/pointer, Unmarshal sets Go value to nil. Because null is often +// slice/map/pointer/interface, Unmarshal sets Go value to nil. Because null is often // used to mean "not present", unmarshaling CBOR null and undefined value // into any other Go type has no effect and returns no error. // @@ -1076,7 +1076,7 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore if opts.DefaultByteStringType != nil && opts.DefaultByteStringType.Kind() != reflect.String && - (opts.DefaultByteStringType.Kind() != reflect.Slice || opts.DefaultByteStringType.Elem().Kind() != reflect.Uint8) { + (opts.DefaultByteStringType.Kind() != reflect.Slice || opts.DefaultByteStringType.Elem() != typeByte) { return nil, fmt.Errorf("cbor: invalid DefaultByteStringType: %s is not of kind string or []uint8", opts.DefaultByteStringType) } @@ -1402,9 +1402,19 @@ func (d *decoder) value(v any) error { // parseToValue decodes CBOR data to value. It assumes data is well-formed, // and does not perform bounds checking. func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo + // Strip self-described CBOR tag number before checking for CBOR null/undefined, + // so that 55799(null) decodes the same as null. + for d.nextCBORType() == cborTypeTag { + off := d.off + _, _, tagNum := d.getHead() + if tagNum != tagNumSelfDescribedCBOR { + d.off = off + break + } + } - // Decode CBOR nil or CBOR undefined to pointer value by setting pointer value to nil. - if d.nextCBORNil() && v.Kind() == reflect.Pointer { + // Decode CBOR null or undefined values into a pointer or interface by setting it to nil. + if d.nextCBORNil() && (v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface) { d.skip() v.SetZero() return nil @@ -1412,8 +1422,20 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin if tInfo.spclType == specialTypeIface { if !v.IsNil() { + // Decode into the value in the interface only if the value is a non-nil pointer. + // Any other value in the interface is unaddressable and can't be decoded into. + e := v.Elem() + if e.Kind() != reflect.Pointer || e.IsNil() { + cType := d.nextCBORType() + d.skip() + return &UnmarshalTypeError{ + CBORType: cType.String(), + GoType: tInfo.nonPtrType.String(), + } + } + // Use value type - v = v.Elem() + v = e tInfo = getTypeInfo(v.Type()) } else { //nolint:gocritic // Create and use registered type if CBOR data is registered tag @@ -1453,16 +1475,6 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin v = v.Elem() } - // Strip self-described CBOR tag number. - for d.nextCBORType() == cborTypeTag { - off := d.off - _, _, tagNum := d.getHead() - if tagNum != tagNumSelfDescribedCBOR { - d.off = off - break - } - } - // Check validity of supported built-in tags. off := d.off for d.nextCBORType() == cborTypeTag { @@ -1595,13 +1607,6 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin return fillFloat(t, f, v) default: // ai <= 24 - if d.dm.simpleValues.rejected[SimpleValue(val)] { //nolint:gosec - return &UnacceptableDataItemError{ - CBORType: t.String(), - Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", //nolint:gosec - } - } - switch ai { case additionalInformationAsFalse, additionalInformationAsTrue: @@ -1769,6 +1774,7 @@ func (d *decoder) parseToTime() (time.Time, bool, error) { } return t, true, nil } + d.skip() return time.Time{}, false, &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String()} case cborTypeTextString: @@ -1845,6 +1851,7 @@ func (d *decoder) parseToTime() (time.Time, bool, error) { return time.Unix(int64(seconds), int64(fractional*1e9)), true, nil default: + d.skip() return time.Time{}, false, &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String()} } } @@ -2155,12 +2162,6 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (any, error) { //nolint:gocyc case cborTypePrimitives: _, ai, val := d.getHead() - if ai <= 24 && d.dm.simpleValues.rejected[SimpleValue(val)] { //nolint:gosec - return nil, &UnacceptableDataItemError{ - CBORType: t.String(), - Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", //nolint:gosec - } - } if ai < 20 || ai == 24 { return SimpleValue(val), nil //nolint:gosec } @@ -2484,9 +2485,7 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli v.Set(reflect.MakeMapWithSize(tInfo.nonPtrType, mapsize)) } keyType, eleType := tInfo.keyTypeInfo.typ, tInfo.elemTypeInfo.typ - reuseKey, reuseEle := isImmutableKind(tInfo.keyTypeInfo.kind), isImmutableKind(tInfo.elemTypeInfo.kind) var keyValue, eleValue reflect.Value - keyIsInterfaceType := keyType == typeIntf // If key type is interface{}, need to check if key value is hashable. var err, lastErr error keyCount := v.Len() var existingKeys map[any]bool // Store existing map keys, used for detecting duplicate map key. @@ -2503,7 +2502,7 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli // Parse CBOR map key. if !keyValue.IsValid() { keyValue = reflect.New(keyType).Elem() - } else if !reuseKey { + } else { keyValue.SetZero() } if lastErr = d.parseToValue(keyValue, tInfo.keyTypeInfo); lastErr != nil { @@ -2515,22 +2514,28 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli } // Detect if CBOR map key can be used as Go map key. - if keyIsInterfaceType && keyValue.Elem().IsValid() { - if !isHashableValue(keyValue.Elem()) { - var converted bool - if d.dm.mapKeyByteString == MapKeyByteStringAllowed { - var k any - k, converted = convertByteSliceToByteString(keyValue.Elem().Interface()) - if converted { - keyValue.Set(reflect.ValueOf(k)) + if tInfo.keyNeedsHashableValueCheck { + containedKeyValue := keyValue + if keyValue.Kind() == reflect.Interface { + containedKeyValue = keyValue.Elem() + } + if containedKeyValue.IsValid() { + if !isHashableValue(containedKeyValue) { + var converted bool + if d.dm.mapKeyByteString == MapKeyByteStringAllowed { + var k any + k, converted = convertByteSliceToByteString(containedKeyValue.Interface()) + if converted { + keyValue.Set(reflect.ValueOf(k)) + } } - } - if !converted { - if err == nil { - err = &InvalidMapKeyTypeError{keyValue.Elem().Type().String()} + if !converted { + if err == nil { + err = &InvalidMapKeyTypeError{containedKeyValue.Type().String()} + } + d.skip() + continue } - d.skip() - continue } } } @@ -2538,7 +2543,7 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli // Parse CBOR map value. if !eleValue.IsValid() { eleValue = reflect.New(eleType).Elem() - } else if !reuseEle { + } else { eleValue.SetZero() } if lastErr := d.parseToValue(eleValue, tInfo.elemTypeInfo); lastErr != nil { @@ -2578,6 +2583,7 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli func (d *decoder) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error { structType, structTypeErr := getDecodingStructType(tInfo.nonPtrType) if structTypeErr != nil { + d.skip() return structTypeErr } @@ -2712,6 +2718,7 @@ func (d *decoder) decodeToStructField(v reflect.Value, f *decodingField, tInfo * func (d *decoder) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo structType, structTypeErr := getDecodingStructType(tInfo.nonPtrType) if structTypeErr != nil { + d.skip() return structTypeErr } @@ -3044,7 +3051,6 @@ func (d *decoder) nextCBORNil() bool { type jsonUnmarshaler interface{ UnmarshalJSON([]byte) error } var ( - typeIntf = reflect.TypeOf([]any(nil)).Elem() typeTime = reflect.TypeOf(time.Time{}) typeBigInt = reflect.TypeOf(big.Int{}) typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem() @@ -3054,6 +3060,7 @@ var ( typeJSONUnmarshaler = reflect.TypeOf((*jsonUnmarshaler)(nil)).Elem() typeString = reflect.TypeOf("") typeByteSlice = reflect.TypeOf([]byte(nil)) + typeByte = reflect.TypeOf(byte(0)) ) func fillNil(_ cborType, v reflect.Value) error { @@ -3246,34 +3253,40 @@ func fillTextString(t cborType, val []byte, v reflect.Value, tum TextUnmarshaler return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} } -func isImmutableKind(k reflect.Kind) bool { - switch k { - case reflect.Bool, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64, - reflect.String: - return true - - default: - return false - } -} - func isHashableValue(rv reflect.Value) bool { switch rv.Kind() { case reflect.Slice, reflect.Map, reflect.Func: return false - case reflect.Struct: - switch rv.Type() { + case reflect.Struct, reflect.Interface: + switch rt := rv.Type(); rt { case typeTag: tag := rv.Interface().(Tag) return isHashableValue(reflect.ValueOf(tag.Content)) + case typeTime: + return true case typeBigInt: return false + default: + // Both Type.Comparable() and Value.Comparable() checks are needed. + // - Type.Comparable() returns true for interface types, so + // Value.Comparable() is needed to check the dynamic value. + // - Value.Comparable() returns true for zero-length array of interface, + // array, or struct type (as of go1.27.1), so Type.Comparable() is + // needed to reject zero-length array of uncomparable type. + return rt.Comparable() && rv.Comparable() + } + + case reflect.Array: + switch rt := rv.Type(); rt.Elem().Kind() { + case reflect.Slice, reflect.Map, reflect.Func: + return false + + case reflect.Struct, reflect.Array, reflect.Interface: + return rt.Comparable() && rv.Comparable() } } + return true } diff --git a/src/vendor/github.com/fxamacker/cbor/v2/encode.go b/src/vendor/github.com/fxamacker/cbor/v2/encode.go index e65a29d8..f68abf79 100644 --- a/src/vendor/github.com/fxamacker/cbor/v2/encode.go +++ b/src/vendor/github.com/fxamacker/cbor/v2/encode.go @@ -16,6 +16,7 @@ import ( "reflect" "sort" "strconv" + "strings" "sync" "time" @@ -307,55 +308,53 @@ func (icm InfConvertMode) valid() bool { return icm >= 0 && icm < maxInfConvert } -// TimeMode specifies how to encode time.Time values in compliance with RFC 8949 (CBOR): -// - Section 3.4.1: Standard Date/Time String -// - Section 3.4.2: Epoch-Based Date/Time -// For more info, see: -// - https://www.rfc-editor.org/rfc/rfc8949.html -// NOTE: User applications that prefer to encode time with fractional seconds to an integer -// (instead of floating point or text string) can use a CBOR tag number not assigned by IANA: -// 1. Define a user-defined type in Go with just a time.Time or int64 as its data. -// 2. Implement the cbor.Marshaler and cbor.Unmarshaler interface for that user-defined type -// to encode or decode the tagged data item with an enclosed integer content. +// TimeMode selects the RFC 8949 (CBOR) format to use when encoding time.Time values: +// - Section 3.4.1: Standard Date/Time String (CBOR tag 0) +// - Section 3.4.2: Epoch-Based Date/Time (CBOR tag 1, integer or floating-point) +// +// To emit CBOR tag number 0 or 1, use EncOptions{TimeTag: EncTagRequired}. +// +// RFC 8949 specifies fractional seconds as text or floating-point, but not as integers. +// User-defined types can use integer-based format for fractional seconds by implementing +// cbor.Marshaler and cbor.Unmarshaler (without CBOR tag number 0 or 1). type TimeMode int const ( - // TimeUnix causes time.Time to encode to a CBOR time (tag 1) with an integer content - // representing seconds elapsed (with 1-second precision) since UNIX Epoch UTC. - // The TimeUnix option is location independent and has a clear precision guarantee. + // TimeUnix encodes to the integer format specified by RFC 8949 for whole seconds, + // with 1-second precision. For fractional seconds, use other TimeMode options or + // a custom CBOR time format (see TimeMode and cbor.Marshaler). TimeUnix TimeMode = iota - // TimeUnixMicro causes time.Time to encode to a CBOR time (tag 1) with a floating point content - // representing seconds elapsed (with up to 1-microsecond precision) since UNIX Epoch UTC. - // NOTE: The floating point content is encoded to the shortest floating-point encoding that preserves - // the 64-bit floating point value. I.e., the floating point encoding can be IEEE 764: - // binary64, binary32, or binary16 depending on the content's value. + // TimeUnixMicro encodes to the floating-point format specified by RFC 8949 for + // fractional seconds, with up to 1-microsecond precision that decreases for times + // far from 1970. Like all binary floating-point formats, IEEE 754 binary64 + // (float64) cannot represent most decimal fractions exactly. + // For more precision, use TimeRFC3339NanoUTC or a custom CBOR time format (see + // TimeMode and cbor.Marshaler) to store fractional seconds in an integer. TimeUnixMicro - // TimeUnixDynamic causes time.Time to encode to a CBOR time (tag 1) with either an integer content or - // a floating point content, depending on the content's value. This option is equivalent to dynamically - // choosing TimeUnix if time.Time doesn't have fractional seconds, and using TimeUnixMicro if time.Time - // has fractional seconds. + // TimeUnixDynamic encodes to the integer or floating-point format specified by + // RFC 8949. It encodes to an integer if the time rounded to microseconds is a + // whole second, and otherwise to the floating-point format. Like all binary + // floating-point formats, IEEE 754 binary64 (float64) cannot represent most decimal + // fractions exactly. For precision details and alternative formats, see TimeMode + // and TimeUnixMicro. TimeUnixDynamic - // TimeRFC3339 causes time.Time to encode to a CBOR time (tag 0) with a text string content - // representing the time using 1-second precision in RFC3339 format. If the time.Time has a - // non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339. - // NOTE: User applications can avoid including the RFC3339 numeric offset by: - // - providing a time.Time value set to UTC, or - // - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option. + // TimeRFC3339 encodes to the text format specified by RFC 8949, with 1-second + // precision and the UTC offset of the time.Time. To always encode "Z" (zero + // offset), use UTC time.Time values or TimeRFC3339NanoUTC. + // For fractional seconds, use other TimeMode options or a custom CBOR time format + // (see TimeMode and cbor.Marshaler). TimeRFC3339 - // TimeRFC3339Nano causes time.Time to encode to a CBOR time (tag 0) with a text string content - // representing the time using 1-nanosecond precision in RFC3339 format. If the time.Time has a - // non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339. - // NOTE: User applications can avoid including the RFC3339 numeric offset by: - // - providing a time.Time value set to UTC, or - // - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option. + // TimeRFC3339Nano encodes to the text format specified by RFC 8949, with + // 1-nanosecond precision and the UTC offset of the time.Time. To always encode + // "Z" (zero offset), use UTC time.Time values or TimeRFC3339NanoUTC. TimeRFC3339Nano - // TimeRFC3339NanoUTC causes time.Time to encode to a CBOR time (tag 0) with a text string content - // representing UTC time using nanosecond precision in RFC3339 format. + // TimeRFC3339NanoUTC encodes to the text format specified by RFC 8949, with + // 1-nanosecond precision and the time converted to UTC ("Z"). TimeRFC3339NanoUTC maxTimeMode @@ -1057,7 +1056,7 @@ func putEncodeBuffer(e *bytes.Buffer) { type encodeFunc func(e *bytes.Buffer, em *encMode, v reflect.Value) error type isEmptyFunc func(em *encMode, v reflect.Value) (empty bool, err error) -type isZeroFunc func(v reflect.Value) (zero bool, err error) +type isZeroFunc func(em *encMode, v reflect.Value) (zero bool, err error) func encode(e *bytes.Buffer, em *encMode, v reflect.Value) error { if !v.IsValid() { @@ -1568,7 +1567,7 @@ func encodeStruct(e *bytes.Buffer, em *encMode, v reflect.Value) (err error) { } } if f.omitZero { - zero, err := f.izf(fv) + zero, err := f.izf(em, fv) if err != nil { return err } @@ -1630,6 +1629,13 @@ func encodeIntf(e *bytes.Buffer, em *encMode, v reflect.Value) error { return encode(e, em, v.Elem()) } +// Inclusive range of Unix seconds within which Time.UnixNano is defined +// for any nanosecond fraction. +const ( + minUnixNanoSecs = math.MinInt64 / 1_000_000_000 + maxUnixNanoSecs = math.MaxInt64/1_000_000_000 - 1 +) + func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { t := v.Interface().(time.Time) if t.IsZero() { @@ -1643,6 +1649,7 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { } encodeHead(e, byte(cborTypeTag), uint64(tagNumber)) } + var s string switch em.time { case TimeUnix: secs := t.Unix() @@ -1650,7 +1657,17 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { case TimeUnixMicro: t = t.UTC().Round(time.Microsecond) - f := float64(t.UnixNano()) / 1e9 + var f float64 + if secs := t.Unix(); secs >= minUnixNanoSecs && secs <= maxUnixNanoSecs { + // Unix seconds within [minUnixNanoSecs, maxUnixNanoSecs] + // are encoded from time.UnixNano to keep encoded data unchanged. + f = float64(t.UnixNano()) / 1e9 + } else { + // Unix seconds outside [minUnixNanoSecs, maxUnixNanoSecs] + // are encoded from Unix seconds and nanoseconds. + nsecs := t.Nanosecond() + f = float64(secs) + float64(nsecs)/1e9 + } return encodeFloat(e, em, reflect.ValueOf(f)) case TimeUnixDynamic: @@ -1663,17 +1680,28 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { return encodeFloat(e, em, reflect.ValueOf(f)) case TimeRFC3339: - s := t.Format(time.RFC3339) - return encodeString(e, em, reflect.ValueOf(s)) + s = t.Format(time.RFC3339) case TimeRFC3339NanoUTC: - s := t.UTC().Format(time.RFC3339Nano) - return encodeString(e, em, reflect.ValueOf(s)) + s = t.UTC().Format(time.RFC3339Nano) default: // TimeRFC3339Nano - s := t.Format(time.RFC3339Nano) - return encodeString(e, em, reflect.ValueOf(s)) + s = t.Format(time.RFC3339Nano) + } + if isWrongYearFromGo(t, s) { + return &UnsupportedValueError{msg: "time.Time formatted by Go with a wrong year"} } + return encodeString(e, em, reflect.ValueOf(s)) +} + +// isWrongYearFromGo reports whether s, the text Go formatted from t, has a wrong year. +// Go's standard library can return wrong results for times in the ~257-year range about +// 292 billion years ago, extended by the size of any negative UTC offset. +func isWrongYearFromGo(t time.Time, s string) bool { + // When t plus one week is before year 0, the text must have a '-' prefix + // with any time zone offset under one week. + const cutoff = -62167219200 - 7*24*60*60 // 0000-01-01T00:00:00Z minus one week for time zone offsets + return t.Unix() < cutoff && !strings.HasPrefix(s, "-") } func encodeBigInt(e *bytes.Buffer, em *encMode, v reflect.Value) error { @@ -1718,10 +1746,15 @@ func encodeBigInt(e *bytes.Buffer, em *encMode, v reflect.Value) error { type binaryMarshalerEncoder struct { alternateEncode encodeFunc alternateIsEmpty isEmptyFunc + alternateIsZero isZeroFunc + isZeroFunc isZeroFunc } func (bme binaryMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect.Value) error { if em.binaryMarshaler != BinaryMarshalerByteString { + if bme.alternateEncode == nil { + return &UnsupportedTypeError{Type: v.Type()} + } return bme.alternateEncode(e, em, v) } @@ -1746,6 +1779,9 @@ func (bme binaryMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect func (bme binaryMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, error) { if em.binaryMarshaler != BinaryMarshalerByteString { + if bme.alternateIsEmpty == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } return bme.alternateIsEmpty(em, v) } @@ -1762,13 +1798,28 @@ func (bme binaryMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, e return len(data) == 0, nil } +func (bme binaryMarshalerEncoder) isZero(em *encMode, v reflect.Value) (bool, error) { + if em.binaryMarshaler != BinaryMarshalerByteString { + if bme.alternateEncode == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } + return bme.alternateIsZero(em, v) + } + return bme.isZeroFunc(em, v) +} + type textMarshalerEncoder struct { alternateEncode encodeFunc alternateIsEmpty isEmptyFunc + alternateIsZero isZeroFunc + isZeroFunc isZeroFunc } func (tme textMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect.Value) error { if em.textMarshaler == TextMarshalerNone { + if tme.alternateEncode == nil { + return &UnsupportedTypeError{Type: v.Type()} + } return tme.alternateEncode(e, em, v) } @@ -1794,6 +1845,9 @@ func (tme textMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect.V func (tme textMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, error) { if em.textMarshaler == TextMarshalerNone { + if tme.alternateIsEmpty == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } return tme.alternateIsEmpty(em, v) } @@ -1810,13 +1864,28 @@ func (tme textMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, err return len(data) == 0, nil } +func (tme textMarshalerEncoder) isZero(em *encMode, v reflect.Value) (bool, error) { + if em.textMarshaler == TextMarshalerNone { + if tme.alternateEncode == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } + return tme.alternateIsZero(em, v) + } + return tme.isZeroFunc(em, v) +} + type jsonMarshalerEncoder struct { alternateEncode encodeFunc alternateIsEmpty isEmptyFunc + alternateIsZero isZeroFunc + isZeroFunc isZeroFunc } func (jme jsonMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect.Value) error { if em.jsonMarshalerTranscoder == nil { + if jme.alternateEncode == nil { + return &UnsupportedTypeError{Type: v.Type()} + } return jme.alternateEncode(e, em, v) } @@ -1855,6 +1924,9 @@ func (jme jsonMarshalerEncoder) encode(e *bytes.Buffer, em *encMode, v reflect.V func (jme jsonMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, error) { if em.jsonMarshalerTranscoder == nil { + if jme.alternateIsEmpty == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } return jme.alternateIsEmpty(em, v) } @@ -1863,6 +1935,16 @@ func (jme jsonMarshalerEncoder) isEmpty(em *encMode, v reflect.Value) (bool, err return false, nil } +func (jme jsonMarshalerEncoder) isZero(em *encMode, v reflect.Value) (bool, error) { + if em.jsonMarshalerTranscoder == nil { + if jme.alternateEncode == nil { + return false, &UnsupportedTypeError{Type: v.Type()} + } + return jme.alternateIsZero(em, v) + } + return jme.isZeroFunc(em, v) +} + func encodeMarshalerType(e *bytes.Buffer, em *encMode, v reflect.Value) error { if em.tagsMd == TagsForbidden && v.Type() == typeRawTag { return errors.New("cbor: cannot encode cbor.RawTag when TagsMd is TagsForbidden") @@ -1977,10 +2059,22 @@ var ( typeByteString = reflect.TypeOf(ByteString("")) ) -func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf isZeroFunc) { +func getEncodeFuncInternal(t reflect.Type, newEncodeFuncs map[reflect.Type]*inProgressEncodeFuncs) (ef encodeFunc, ief isEmptyFunc, izf isZeroFunc) { + // baseIzf stores the original izf before marshaler encoders unwinding. + var baseIzf isZeroFunc + + fs := &inProgressEncodeFuncs{} + newEncodeFuncs[t] = fs + defer func() { + fs.ef = ef + fs.ief = ief + fs.izf = izf + fs.complete = true + }() + k := t.Kind() if k == reflect.Pointer { - return getEncodeIndirectValueFunc(t), isEmptyPtr, getIsZeroFunc(t) + return getEncodeIndirectValueFunc(t, newEncodeFuncs), isEmptyPtr, getIsZeroFunc(t) } switch t { case typeSimpleValue: @@ -2010,9 +2104,12 @@ func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf bme := binaryMarshalerEncoder{ alternateEncode: ef, alternateIsEmpty: ief, + alternateIsZero: izfOrDefault(t, izf), + isZeroFunc: baseIzf, } ef = bme.encode ief = bme.isEmpty + izf = bme.isZero }() } if reflect.PointerTo(t).Implements(typeTextMarshaler) { @@ -2021,9 +2118,12 @@ func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf tme := textMarshalerEncoder{ alternateEncode: ef, alternateIsEmpty: ief, + alternateIsZero: izfOrDefault(t, izf), + isZeroFunc: baseIzf, } ef = tme.encode ief = tme.isEmpty + izf = tme.isZero }() } if reflect.PointerTo(t).Implements(typeJSONMarshaler) { @@ -2033,12 +2133,20 @@ func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf jme := jsonMarshalerEncoder{ alternateEncode: ef, alternateIsEmpty: ief, + alternateIsZero: izfOrDefault(t, izf), + isZeroFunc: baseIzf, } ef = jme.encode ief = jme.isEmpty + izf = jme.isZero }() } + // Capture base izf before marshaler encoder unwinding. + defer func() { + baseIzf = izfOrDefault(t, izf) + }() + switch k { case reflect.Bool: return encodeBool, isEmptyBool, getIsZeroFunc(t) @@ -2062,14 +2170,14 @@ func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf fallthrough case reflect.Array: - f, _, _ := getEncodeFunc(t.Elem()) + f := getEncodeFuncWithNewEncodeFuncs(t.Elem(), newEncodeFuncs) if f == nil { return nil, nil, nil } return arrayEncodeFunc{f: f}.encode, isEmptySlice, getIsZeroFunc(t) case reflect.Map: - f := getEncodeMapFunc(t) + f := getEncodeMapFunc(t, newEncodeFuncs) if f == nil { return nil, nil, nil } @@ -2093,11 +2201,11 @@ func getEncodeFuncInternal(t reflect.Type) (ef encodeFunc, ief isEmptyFunc, izf return nil, nil, nil } -func getEncodeIndirectValueFunc(t reflect.Type) encodeFunc { +func getEncodeIndirectValueFunc(t reflect.Type, newEncodeFuncs map[reflect.Type]*inProgressEncodeFuncs) encodeFunc { for t.Kind() == reflect.Pointer { t = t.Elem() } - f, _, _ := getEncodeFunc(t) + f := getEncodeFuncWithNewEncodeFuncs(t, newEncodeFuncs) if f == nil { return nil } @@ -2244,7 +2352,7 @@ func getIsZeroFunc(t reflect.Type) isZeroFunc { // isZeroInterfaceCustom returns true for nil or pointer-to-nil values, // and delegates to the custom IsZero() implementation otherwise. -func isZeroInterfaceCustom(v reflect.Value) (bool, error) { +func isZeroInterfaceCustom(_ *encMode, v reflect.Value) (bool, error) { kind := v.Kind() switch kind { @@ -2266,7 +2374,7 @@ func isZeroInterfaceCustom(v reflect.Value) (bool, error) { // isZeroPointerCustom returns true for nil values, // and delegates to the custom IsZero() implementation otherwise. -func isZeroPointerCustom(v reflect.Value) (bool, error) { +func isZeroPointerCustom(_ *encMode, v reflect.Value) (bool, error) { if v.IsNil() { return true, nil } @@ -2274,12 +2382,12 @@ func isZeroPointerCustom(v reflect.Value) (bool, error) { } // isZeroCustom delegates to the custom IsZero() implementation. -func isZeroCustom(v reflect.Value) (bool, error) { +func isZeroCustom(_ *encMode, v reflect.Value) (bool, error) { return v.Interface().(isZeroer).IsZero(), nil } // isZeroAddrCustom delegates to the custom IsZero() implementation of the addr of the value. -func isZeroAddrCustom(v reflect.Value) (bool, error) { +func isZeroAddrCustom(_ *encMode, v reflect.Value) (bool, error) { if !v.CanAddr() { // Temporarily box v so we can take the address. v2 := reflect.New(v.Type()).Elem() @@ -2290,7 +2398,7 @@ func isZeroAddrCustom(v reflect.Value) (bool, error) { } // isZeroDefault calls reflect.Value#IsZero() -func isZeroDefault(v reflect.Value) (bool, error) { +func isZeroDefault(_ *encMode, v reflect.Value) (bool, error) { if !v.IsValid() { // v is zero value return true, nil @@ -2299,10 +2407,17 @@ func isZeroDefault(v reflect.Value) (bool, error) { } // isZeroFieldStruct is used to determine whether to omit toarray structs -func isZeroFieldStruct(v reflect.Value) (bool, error) { +func isZeroFieldStruct(_ *encMode, v reflect.Value) (bool, error) { structType, err := getEncodingStructType(v.Type()) if err != nil { return false, err } return len(structType.fields) == 0, nil } + +func izfOrDefault(t reflect.Type, izf isZeroFunc) isZeroFunc { + if izf == nil { + return getIsZeroFunc(t) + } + return izf +} diff --git a/src/vendor/github.com/fxamacker/cbor/v2/encode_map.go b/src/vendor/github.com/fxamacker/cbor/v2/encode_map.go index 2871bfda..d115d76c 100644 --- a/src/vendor/github.com/fxamacker/cbor/v2/encode_map.go +++ b/src/vendor/github.com/fxamacker/cbor/v2/encode_map.go @@ -64,9 +64,9 @@ func (me *mapKeyValueEncodeFunc) encodeKeyValues(e *bytes.Buffer, em *encMode, v return nil } -func getEncodeMapFunc(t reflect.Type) encodeFunc { - kf, _, _ := getEncodeFunc(t.Key()) - ef, _, _ := getEncodeFunc(t.Elem()) +func getEncodeMapFunc(t reflect.Type, newEncodeFuncs map[reflect.Type]*inProgressEncodeFuncs) encodeFunc { + kf := getEncodeFuncWithNewEncodeFuncs(t.Key(), newEncodeFuncs) + ef := getEncodeFuncWithNewEncodeFuncs(t.Elem(), newEncodeFuncs) if kf == nil || ef == nil { return nil } diff --git a/src/vendor/github.com/fxamacker/cbor/v2/valid.go b/src/vendor/github.com/fxamacker/cbor/v2/valid.go index 850b9501..51149f35 100644 --- a/src/vendor/github.com/fxamacker/cbor/v2/valid.go +++ b/src/vendor/github.com/fxamacker/cbor/v2/valid.go @@ -100,7 +100,7 @@ func (d *decoder) wellformed(allowExtraData bool, checkBuiltinTags bool) error { // wellformedInternal checks data's well-formedness and returns max depth and error. func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, error) { //nolint:gocyclo - t, _, val, indefiniteLength, err := d.wellformedHeadWithIndefiniteLengthFlag() + t, ai, val, indefiniteLength, err := d.wellformedHeadWithIndefiniteLengthFlag() if err != nil { return 0, err } @@ -170,6 +170,14 @@ func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, err } depth = maxDepth + case cborTypePrimitives: + if ai <= 24 && d.dm.simpleValues != nil && d.dm.simpleValues.rejected[SimpleValue(val)] { //nolint:gosec + return 0, &UnacceptableDataItemError{ + CBORType: t.String(), + Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", //nolint:gosec + } + } + case cborTypeTag: if d.dm.tagsMd == TagsForbidden { return 0, &TagsMdError{} diff --git a/src/vendor/github.com/gofiber/fiber/v3/.golangci.yml b/src/vendor/github.com/gofiber/fiber/v3/.golangci.yml index 1f9ec94e..da07991a 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/.golangci.yml +++ b/src/vendor/github.com/gofiber/fiber/v3/.golangci.yml @@ -128,6 +128,11 @@ linters: no-printf-like: true misspell: locale: US + modernize: + disable: + # reflect's Fields()/Methods() iterators cost a closure per loop + # (~40B, 3 allocs); the index form stays allocation-free + - stditerators nolintlint: require-explanation: true require-specific: true @@ -260,6 +265,18 @@ linters: - linters: - nolintlint text: directive `.*` is unused for linter "revive" + # helpers.go and internal/fieldname/fieldname.go deliberately call + # fasthttp's deprecated VisitAll (not the replacement All) to stay + # zero-alloc: All returns an iterator closure that escapes to the heap on + # every call. An inline //nolint:staticcheck cannot police this reliably + # because the golangci-lint CI cache can carry staticcheck facts from + # before these calls existed, surfacing no SA1019 finding and making + # nolintlint report the directive as unused. Exclude the finding at report + # time instead so it is robust to cache state. + - path: (helpers|fieldname)\.go + linters: + - staticcheck + text: 'SA1019: .*VisitAll' paths: - _msgp\.go - _msgp_test\.go diff --git a/src/vendor/github.com/gofiber/fiber/v3/AGENTS.md b/src/vendor/github.com/gofiber/fiber/v3/AGENTS.md index 82174578..e704b782 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/AGENTS.md +++ b/src/vendor/github.com/gofiber/fiber/v3/AGENTS.md @@ -6,7 +6,7 @@ ### General coding practices -- When adding Go tests, always invoke `t.Parallel()` at the start of each test and subtest to maximize concurrency. +- When adding Go tests, always invoke `t.Parallel()` at the start of each test and subtest to maximize concurrency. The one exception is a test that calls `testing.AllocsPerRun`, which panics with `AllocsPerRun called during parallel test`: leave those sequential and say why in a comment, as `Test_Chain_NoAllocations` and `Test_Combined_DoesNotAllocate` do. - Prefer `github.com/gofiber/utils/v2` helpers (for example, `utils.Trim`) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code. - Keep all protocol behavior RFC-compliant (e.g., HTTP/1.1 requirements) and document any intentional deviations. - Protect hot paths from regressions: profile changes. @@ -72,7 +72,9 @@ Use `make help` to list all available commands. Common targets include: - **longtest**: run the test suite 15 times with shuffling enabled. - **tidy**: clean and tidy dependencies. - **betteralign**: optimize struct field alignment. -- **generate**: run `go generate` after installing msgp and ifacemaker. +- **generate**: run `go generate` after installing msgp and ifacemaker. On a pull request a maintainer + can get the same result without a local toolchain by commenting `/generate`, which runs the target + and pushes the regenerated files onto the branch. These targets can be invoked via `make ` as needed during development and testing. diff --git a/src/vendor/github.com/gofiber/fiber/v3/README.md b/src/vendor/github.com/gofiber/fiber/v3/README.md new file mode 100644 index 00000000..9068ba9e --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/README.md @@ -0,0 +1,879 @@ +

+ + + + Fiber + + +
+ + + + + + + + Codecov + + + + + + + + + + + + + + + + +

+ +

+ Fiber is an Express inspired web framework built on top of Fasthttp, the fastest HTTP engine for Go. Designed to ease things up for fast development with zero memory allocation and performance in mind. +

+ +--- + +

+ + + + Official Sponsors + + +

+

+ + + + CodeRabbit + + +

+

+ + Blacksmith + +

+

+ Tool Sponsors - supporting Fiber with free IDE licenses and AI credits +

+

+ JetBrains +   + OpenAI +   + Anthropic +

+ +--- + +## ⚙️ Installation + +Fiber requires **Go version `1.26` or higher** to run. If you need to install or upgrade Go, visit the [official Go download page](https://go.dev/dl/). To start setting up your project, create a new directory for your project and navigate into it. Then, initialize your project with Go modules by executing the following command in your terminal: + +```bash +go mod init github.com/your/repo +``` + +To learn more about Go modules and how they work, you can check out the [Using Go Modules](https://go.dev/blog/using-go-modules) blog post. + +After setting up your project, you can install Fiber with the `go get` command: + +```bash +go get -u github.com/gofiber/fiber/v3 +``` + +This command fetches the Fiber package and adds it to your project's dependencies, allowing you to start building your web applications with Fiber. + +## ⚡️ Quickstart + +Getting started with Fiber is easy. Here's a basic example to create a simple web server that responds with "Hello, World 👋!" on the root path. This example demonstrates initializing a new Fiber app, setting up a route, and starting the server. + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + // Initialize a new Fiber app + app := fiber.New() + + // Define a route for the GET method on the root path '/' + app.Get("/", func(c fiber.Ctx) error { + // Send a string response to the client + return c.SendString("Hello, World 👋!") + }) + + // Start the server on port 3000 + log.Fatal(app.Listen(":3000")) +} +``` + +This simple server is easy to set up and run. It introduces the core concepts of Fiber: app initialization, route definition, and starting the server. Just run this Go program, and visit `http://localhost:3000` in your browser to see the message. + +## Zero Allocation + +Fiber is optimized for **high-performance**, meaning values returned from **fiber.Ctx** are **not** immutable by default and **will** be reused across requests. As a rule of thumb, you **must** only use context values within the handler and **must not** keep any references. Once you return from the handler, any values obtained from the context will be reused in future requests. Visit our [documentation](https://docs.gofiber.io/#zero-allocation) to learn more. + +## 🤖 Benchmarks + +These tests are performed by [TechEmpower](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=plaintext). If you want to see all the results, please visit our [Wiki](https://docs.gofiber.io/extra/benchmarks). + +

+ + +

+ +## 🎯 Features + +- Robust [Routing](https://docs.gofiber.io/guide/routing) +- Serve [Static Files](https://docs.gofiber.io/api/app#static) +- Extreme [Performance](https://docs.gofiber.io/extra/benchmarks) +- [Low Memory](https://docs.gofiber.io/extra/benchmarks) footprint +- [API Endpoints](https://docs.gofiber.io/api/ctx) +- [Middleware](https://docs.gofiber.io/category/-middleware) & [Next](https://docs.gofiber.io/api/ctx#next) support +- [Rapid](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) server-side programming +- [Template Engines](https://github.com/gofiber/template) +- [WebSocket Support](https://docs.gofiber.io/contrib/websocket) +- [Socket.io Support](https://docs.gofiber.io/contrib/socketio) +- [Server-Sent Events](https://docs.gofiber.io/middleware/sse) +- [Rate Limiter](https://docs.gofiber.io/middleware/limiter) +- And much more, [explore Fiber](https://docs.gofiber.io/) + +## 💡 Philosophy + +New gophers that make the switch from [Node.js](https://nodejs.org/en/about/) to [Go](https://go.dev/doc/) are dealing with a learning curve before they can start building their web applications or microservices. Fiber, as a **web framework**, was created with the idea of **minimalism** and follows the **UNIX way**, so that new gophers can quickly enter the world of Go with a warm and trusted welcome. + +Fiber is **inspired** by Express, the most popular web framework on the Internet. We combined the **ease** of Express and **raw performance** of Go. If you have ever implemented a web application in Node.js (_using Express or similar_), then many methods and principles will seem **very common** to you. + +We **listen** to our users in [issues](https://github.com/gofiber/fiber/issues), Discord [channel](https://gofiber.io/discord) _and all over the Internet_ to create a **fast**, **flexible** and **friendly** Go web framework for **any** task, **deadline** and developer **skill**! Just like Express does in the JavaScript world. + +## ⚠️ Limitations + +- Due to Fiber's usage of unsafe, the library may not always be compatible with the latest Go version. Fiber v3 has been tested with Go version 1.26 or higher. +- Fiber automatically adapts common `net/http` handler shapes when you register them on the router, and you can still use the [adaptor middleware](https://docs.gofiber.io/middleware/adaptor/) when you need to bridge entire apps or `net/http` middleware. + +### net/http compatibility + +Fiber can run side by side with the standard library. The router accepts existing `net/http` handlers directly and even works with native `fasthttp.RequestHandler` callbacks, so you can plug in legacy endpoints without wrapping them manually: + +```go +package main + +import ( + "log" + "net/http" + + "github.com/gofiber/fiber/v3" +) + +func main() { + httpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if _, err := w.Write([]byte("served by net/http")); err != nil { + panic(err) + } + }) + + app := fiber.New() + app.Get("/", httpHandler) + + // Start the server on port 3000 + log.Fatal(app.Listen(":3000")) +} +``` + +When you need to convert entire applications or reuse `net/http` middleware chains, rely on the [adaptor middleware](https://docs.gofiber.io/middleware/adaptor/). It converts handlers and middlewares in both directions and even lets you mount a Fiber app in a `net/http` server. + +### Express-style handlers + +Fiber also adapts Express-style callbacks that operate on the lightweight `fiber.Req` and `fiber.Res` helper interfaces. This lets you port middleware and route handlers from Express-inspired codebases while keeping Fiber's router features: + +```go +// Request/response handlers (2-argument) +app.Get("/", func(req fiber.Req, res fiber.Res) error { + return res.SendString("Hello from Express-style handlers!") +}) + +// Middleware with an error-returning next callback (3-argument) +app.Use(func(req fiber.Req, res fiber.Res, next func() error) error { + if req.IP() == "192.168.1.254" { + return res.SendStatus(fiber.StatusForbidden) + } + return next() +}) + +// Middleware with a no-arg next callback (3-argument) +app.Use(func(req fiber.Req, res fiber.Res, next func()) { + if req.Get("X-Skip") == "true" { + return // stop the chain without calling next + } + next() +}) +``` + +> **Note:** Adapted `net/http` handlers continue to operate with the standard-library semantics. They don't get access to `fiber.Ctx` features and incur the overhead of the compatibility layer, so native `fiber.Handler` callbacks still provide the best performance. + +## 👀 Examples + +Listed below are some of the common examples. If you want to see more code examples, please visit our [Recipes repository](https://github.com/gofiber/recipes) or visit our hosted [API documentation](https://docs.gofiber.io). + +### 📖 [**Basic Routing**](https://docs.gofiber.io/#basic-routing) + +```go title="Example" +package main + +import ( + "fmt" + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + app := fiber.New() + + // GET /api/register + app.Get("/api/*", func(c fiber.Ctx) error { + msg := fmt.Sprintf("✋ %s", c.Params("*")) + return c.SendString(msg) // => ✋ register + }) + + // GET /flights/LAX-SFO + app.Get("/flights/:from-:to", func(c fiber.Ctx) error { + msg := fmt.Sprintf("💸 From: %s, To: %s", c.Params("from"), c.Params("to")) + return c.SendString(msg) // => 💸 From: LAX, To: SFO + }) + + // GET /dictionary.txt + app.Get("/:file.:ext", func(c fiber.Ctx) error { + msg := fmt.Sprintf("📃 %s.%s", c.Params("file"), c.Params("ext")) + return c.SendString(msg) // => 📃 dictionary.txt + }) + + // GET /john/75 + app.Get("/:name/:age/:gender?", func(c fiber.Ctx) error { + msg := fmt.Sprintf("👴 %s is %s years old", c.Params("name"), c.Params("age")) + return c.SendString(msg) // => 👴 john is 75 years old + }) + + // GET /john + app.Get("/:name", func(c fiber.Ctx) error { + msg := fmt.Sprintf("Hello, %s 👋!", c.Params("name")) + return c.SendString(msg) // => Hello john 👋! + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name) + +```go title="Example" +package main + +import ( + "encoding/json" + "fmt" + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + app := fiber.New() + + app.Get("/api/*", func(c fiber.Ctx) error { + msg := fmt.Sprintf("✋ %s", c.Params("*")) + return c.SendString(msg) // => ✋ register + }).Name("api") + + route := app.GetRoute("api") + + data, _ := json.MarshalIndent(route, "", " ") + fmt.Println(string(data)) + // Prints: + // { + // "method": "GET", + // "name": "api", + // "path": "/api/*", + // "params": [ + // "*1" + // ] + // } + + log.Fatal(app.Listen(":3000")) +} +``` + +#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/static" +) + +func main() { + app := fiber.New() + + // Serve static files from the "./public" directory + app.Get("/*", static.New("./public")) + // => http://localhost:3000/js/script.js + // => http://localhost:3000/css/style.css + + app.Get("/prefix*", static.New("./public")) + // => http://localhost:3000/prefix/js/script.js + // => http://localhost:3000/prefix/css/style.css + + // Serve a single file for any unmatched routes + app.Get("*", static.New("./public/index.html")) + // => http://localhost:3000/any/path/shows/index.html + + log.Fatal(app.Listen(":3000")) +} +``` + +#### 📖 [**Middleware & Next**](https://docs.gofiber.io/api/ctx#next) + +```go title="Example" +package main + +import ( + "fmt" + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + app := fiber.New() + + // Middleware that matches any route + app.Use(func(c fiber.Ctx) error { + fmt.Println("🥇 First handler") + return c.Next() + }) + + // Middleware that matches all routes starting with /api + app.Use("/api", func(c fiber.Ctx) error { + fmt.Println("🥈 Second handler") + return c.Next() + }) + + // GET /api/list + app.Get("/api/list", func(c fiber.Ctx) error { + fmt.Println("🥉 Last handler") + return c.SendString("Hello, World 👋!") + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +
+ 📚 Show more code examples + +### Views Engines + +📖 [Config](https://docs.gofiber.io/api/fiber#config) +📖 [Engines](https://github.com/gofiber/template) +📖 [Render](https://docs.gofiber.io/api/ctx#render) + +Fiber defaults to the [html/template](https://pkg.go.dev/html/template/) when no view engine is set. + +If you want to execute partials or use a different engine like [amber](https://github.com/eknkc/amber), [handlebars](https://github.com/aymerick/raymond), [mustache](https://github.com/cbroglie/mustache), or [pug](https://github.com/Joker/jade), etc., check out our [Template](https://github.com/gofiber/template) package that supports multiple view engines. + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/template/pug" +) + +func main() { + // Initialize a new Fiber app with Pug template engine + app := fiber.New(fiber.Config{ + Views: pug.New("./views", ".pug"), + }) + + // Define a route that renders the "home.pug" template + app.Get("/", func(c fiber.Ctx) error { + return c.Render("home", fiber.Map{ + "title": "Homepage", + "year": 1999, + }) + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### Grouping Routes into Chains + +📖 [Group](https://docs.gofiber.io/api/app#group) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" +) + +func middleware(c fiber.Ctx) error { + log.Println("Middleware executed") + return c.Next() +} + +func handler(c fiber.Ctx) error { + return c.SendString("Handler response") +} + +func main() { + app := fiber.New() + + // Root API group with middleware + api := app.Group("/api", middleware) // /api + + // API v1 routes + v1 := api.Group("/v1", middleware) // /api/v1 + v1.Get("/list", handler) // /api/v1/list + v1.Get("/user", handler) // /api/v1/user + + // API v2 routes + v2 := api.Group("/v2", middleware) // /api/v2 + v2.Get("/list", handler) // /api/v2/list + v2.Get("/user", handler) // /api/v2/user + + log.Fatal(app.Listen(":3000")) +} +``` + +### Middleware Logger + +📖 [Logger](https://docs.gofiber.io/middleware/logger) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/logger" +) + +func main() { + app := fiber.New() + + // Use Logger middleware + app.Use(logger.New()) + + // Define routes + app.Get("/", func(c fiber.Ctx) error { + return c.SendString("Hello, Logger!") + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### Cross-Origin Resource Sharing (CORS) + +📖 [CORS](https://docs.gofiber.io/middleware/cors) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/cors" +) + +func main() { + app := fiber.New() + + // Use CORS middleware with default settings + app.Use(cors.New()) + + // Define routes + app.Get("/", func(c fiber.Ctx) error { + return c.SendString("CORS enabled!") + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +Check CORS by passing any domain in `Origin` header: + +```bash +curl -H "Origin: http://example.com" --verbose http://localhost:3000 +``` + +### Custom 404 Response + +📖 [HTTP Methods](https://docs.gofiber.io/api/ctx#status) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + app := fiber.New() + + // Define routes + app.Get("/", static.New("./public")) + + app.Get("/demo", func(c fiber.Ctx) error { + return c.SendString("This is a demo page!") + }) + + app.Post("/register", func(c fiber.Ctx) error { + return c.SendString("Registration successful!") + }) + + // Middleware to handle 404 Not Found + app.Use(func(c fiber.Ctx) error { + return c.SendStatus(fiber.StatusNotFound) // => 404 "Not Found" + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### JSON Response + +📖 [JSON](https://docs.gofiber.io/api/ctx#json) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" +) + +type User struct { + Name string `json:"name"` + Age int `json:"age"` +} + +func main() { + app := fiber.New() + + // Route that returns a JSON object + app.Get("/user", func(c fiber.Ctx) error { + return c.JSON(&User{"John", 20}) + // => {"name":"John", "age":20} + }) + + // Route that returns a JSON map + app.Get("/json", func(c fiber.Ctx) error { + return c.JSON(fiber.Map{ + "success": true, + "message": "Hi John!", + }) + // => {"success":true, "message":"Hi John!"} + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### WebSocket Upgrade + +📖 [Websocket](https://docs.gofiber.io/contrib/websocket) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/websocket" +) + +func main() { + app := fiber.New() + + // WebSocket route + app.Get("/ws", websocket.New(func(c *websocket.Conn) { + defer c.Close() + for { + // Read message from client + mt, msg, err := c.ReadMessage() + if err != nil { + log.Println("read:", err) + break + } + log.Printf("recv: %s", msg) + + // Write message back to client + err = c.WriteMessage(mt, msg) + if err != nil { + log.Println("write:", err) + break + } + } + })) + + log.Fatal(app.Listen(":3000")) + // Connect via WebSocket at ws://localhost:3000/ws +} +``` + +### Server-Sent Events + +📖 [More Info](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) + +```go title="Example" +package main + +import ( + "bufio" + "fmt" + "log" + "time" + + "github.com/gofiber/fiber/v3" + "github.com/valyala/fasthttp" +) + +func main() { + app := fiber.New() + + // Server-Sent Events route + app.Get("/sse", func(c fiber.Ctx) error { + c.Set("Content-Type", "text/event-stream") + c.Set("Cache-Control", "no-cache") + c.Set("Connection", "keep-alive") + c.Set("Transfer-Encoding", "chunked") + + c.Context().SetBodyStreamWriter(func(w *bufio.Writer) { + var i int + for { + i++ + msg := fmt.Sprintf("%d - the time is %v", i, time.Now()) + fmt.Fprintf(w, "data: Message: %s\n\n", msg) + fmt.Println(msg) + + w.Flush() + time.Sleep(5 * time.Second) + } + }) + + return nil + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### Recover Middleware + +📖 [Recover](https://docs.gofiber.io/middleware/recover) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/middleware/recover" +) + +func main() { + app := fiber.New() + + // Use Recover middleware to handle panics gracefully + app.Use(recover.New()) + + // Route that intentionally panics + app.Get("/", func(c fiber.Ctx) error { + panic("normally this would crash your app") + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +### Using Trusted Proxy + +📖 [Config](https://docs.gofiber.io/api/fiber#config) + +```go title="Example" +package main + +import ( + "log" + + "github.com/gofiber/fiber/v3" +) + +func main() { + app := fiber.New(fiber.Config{ + // Configure trusted proxies - WARNING: Only trust proxies you control + // Using TrustProxy: true with unrestricted IPs can lead to IP spoofing + TrustProxy: true, + TrustProxyConfig: fiber.TrustProxyConfig{ + Proxies: []string{"10.0.0.0/8", "172.16.0.0/12"}, // Example: Internal network ranges only + }, + ProxyHeader: fiber.HeaderXForwardedFor, + }) + + // Define routes + app.Get("/", func(c fiber.Ctx) error { + return c.SendString("Trusted Proxy Configured!") + }) + + log.Fatal(app.Listen(":3000")) +} +``` + +
+ +## 🧬 Internal Middleware + +Here is a list of middleware that are included within the Fiber framework. + +| Middleware | Description | +|--------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [adaptor](https://github.com/gofiber/fiber/tree/main/middleware/adaptor) | Converter for net/http handlers to/from Fiber request handlers. | +| [basicauth](https://github.com/gofiber/fiber/tree/main/middleware/basicauth) | Provides HTTP basic authentication. It calls the next handler for valid credentials and 401 Unauthorized for missing or invalid credentials. | +| [cache](https://github.com/gofiber/fiber/tree/main/middleware/cache) | Intercept and cache HTTP responses. | +| [compress](https://github.com/gofiber/fiber/tree/main/middleware/compress) | Compression middleware for Fiber, with support for `deflate`, `gzip`, `brotli` and `zstd`. | +| [cors](https://github.com/gofiber/fiber/tree/main/middleware/cors) | Enable cross-origin resource sharing (CORS) with various options. | +| [csrf](https://github.com/gofiber/fiber/tree/main/middleware/csrf) | Protect from CSRF exploits. | +| [earlydata](https://github.com/gofiber/fiber/tree/main/middleware/earlydata) | Adds support for TLS 1.3's early data ("0-RTT") feature. | +| [encryptcookie](https://github.com/gofiber/fiber/tree/main/middleware/encryptcookie) | Encrypt middleware which encrypts cookie values. | +| [envvar](https://github.com/gofiber/fiber/tree/main/middleware/envvar) | Expose environment variables with providing an optional config. | +| [etag](https://github.com/gofiber/fiber/tree/main/middleware/etag) | Allows for caches to be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed. | +| [expvar](https://github.com/gofiber/fiber/tree/main/middleware/expvar) | Serves via its HTTP server runtime exposed variables in the JSON format. | +| [favicon](https://github.com/gofiber/fiber/tree/main/middleware/favicon) | Ignore favicon from logs or serve from memory if a file path is provided. | +| [healthcheck](https://github.com/gofiber/fiber/tree/main/middleware/healthcheck) | Liveness and Readiness probes for Fiber. | +| [helmet](https://github.com/gofiber/fiber/tree/main/middleware/helmet) | Helps secure your apps by setting various HTTP headers. | +| [hostauthorization](https://github.com/gofiber/fiber/tree/main/middleware/hostauthorization) | Validates the Host header against a configurable allowlist, protecting against DNS rebinding attacks. | +| [idempotency](https://github.com/gofiber/fiber/tree/main/middleware/idempotency) | Allows for fault-tolerant APIs where duplicate requests do not erroneously cause the same action performed multiple times on the server-side. | +| [keyauth](https://github.com/gofiber/fiber/tree/main/middleware/keyauth) | Adds support for key based authentication. | +| [limiter](https://github.com/gofiber/fiber/tree/main/middleware/limiter) | Adds Rate-limiting support to Fiber. Use to limit repeated requests to public APIs and/or endpoints such as password reset. | +| [logger](https://github.com/gofiber/fiber/tree/main/middleware/logger) | HTTP request/response logger. | +| [paginate](https://github.com/gofiber/fiber/tree/main/middleware/paginate) | Extracts pagination parameters from query strings. Supports page-based, offset-based, and cursor-based pagination with multi-field sorting. | +| [pprof](https://github.com/gofiber/fiber/tree/main/middleware/pprof) | Serves runtime profiling data in pprof format. | +| [proxy](https://github.com/gofiber/fiber/tree/main/middleware/proxy) | Allows you to proxy requests to multiple servers. | +| [recover](https://github.com/gofiber/fiber/tree/main/middleware/recover) | Recovers from panics anywhere in the stack chain and handles the control to the centralized ErrorHandler. | +| [redirect](https://github.com/gofiber/fiber/tree/main/middleware/redirect) | Redirect middleware. | +| [requestid](https://github.com/gofiber/fiber/tree/main/middleware/requestid) | Adds a request ID to every request. | +| [responsetime](https://github.com/gofiber/fiber/tree/main/middleware/responsetime) | Measures request handling duration and writes it to a configurable response header. | +| [rewrite](https://github.com/gofiber/fiber/tree/main/middleware/rewrite) | Rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. | +| [session](https://github.com/gofiber/fiber/tree/main/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. | +| [skip](https://github.com/gofiber/fiber/tree/main/middleware/skip) | Skip middleware that skips a wrapped handler if a predicate is true. | +| [static](https://github.com/gofiber/fiber/tree/main/middleware/static) | Static middleware for Fiber that serves static files such as **images**, **CSS**, and **JavaScript**. | +| [timeout](https://github.com/gofiber/fiber/tree/main/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. | + +## 🧬 External Middleware + +List of externally hosted middleware modules and maintained by the [Fiber team](https://github.com/orgs/gofiber/people). + +| Middleware | Description | +| :------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------- | +| [contrib](https://github.com/gofiber/contrib) | Third-party middlewares | +| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. | +| [template](https://github.com/gofiber/template) | This package contains 9 template engines that can be used with Fiber. | + +## 🕶️ Awesome List + +For more articles, middlewares, examples, or tools, check our [awesome list](https://github.com/gofiber/awesome-fiber). + +## 👍 Contribute + +If you want to say **Thank You** and/or support the active development of `Fiber`: + +1. Add a [GitHub Star](https://github.com/gofiber/fiber#%EF%B8%8F-stargazers) to the project. +2. Tweet about the project [on your 𝕏 (Twitter)](https://x.com/intent/tweet?text=Fiber%20is%20an%20Express%20inspired%20%23web%20%23framework%20built%20on%20top%20of%20Fasthttp%2C%20the%20fastest%20HTTP%20engine%20for%20%23Go.%20Designed%20to%20ease%20things%20up%20for%20%23fast%20development%20with%20zero%20memory%20allocation%20and%20%23performance%20in%20mind%20%F0%9F%9A%80%20https%3A%2F%2Fgithub.com%2Fgofiber%2Ffiber). +3. Write a review or tutorial on [Medium](https://medium.com/), [Dev.to](https://dev.to/) or your personal blog. +4. Support the project by becoming a [GitHub Sponsor](https://github.com/sponsors/gofiber). + +## 💻 Development + +To ensure your contributions are ready for a Pull Request, please use the following `Makefile` commands. These tools help maintain code quality and consistency. + +- **make help**: Display available commands. +- **make audit**: Conduct quality checks. +- **make benchmark**: Benchmark code performance. +- **make coverage**: Generate test coverage report. +- **make format**: Automatically format code. +- **make lint**: Run lint checks. +- **make test**: Execute all tests. +- **make tidy**: Tidy dependencies. + +Run these commands to ensure your code adheres to project standards and best practices. + + +## ☕ Supporters + +Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, GitBook, Netlify, and serverless hosting. If you want to support Fiber, please sponsor the organization via ⭐ [**GitHub Sponsors**](https://github.com/sponsors/gofiber). + + + +### 📅 Monthly Sponsors + + + + + +
🔥 Fiber Guardian@coderabbitai
☕ Fiber Supporter@NdoleStudio
🪴 Fiber Friend@simonheisstpeter
+ +### 🎁 One-time Sponsors + + + + +
🚀 Fiber Hero@thnxdev
🪴 Fiber Friend@Gl1tchedPixzl
+ + + +## 💻 Code Contributors + + + Code Contributors + + +## ⭐️ Stargazers + + + + + Stargazers over time + + +## 🧾 License + +Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors](https://github.com/gofiber/fiber/graphs/contributors). `Fiber` is free and open-source software licensed under the [MIT License](https://github.com/gofiber/fiber/blob/main/LICENSE). Official logo was created by [Vic Shóstak](https://github.com/koddr) and distributed under [Creative Commons](https://creativecommons.org/licenses/by-sa/4.0/) license (CC BY-SA 4.0 International). diff --git a/src/vendor/github.com/gofiber/fiber/v3/app.go b/src/vendor/github.com/gofiber/fiber/v3/app.go index 77423ae1..d72c7ab8 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/app.go +++ b/src/vendor/github.com/gofiber/fiber/v3/app.go @@ -20,7 +20,6 @@ import ( "net/http/httputil" "os" "reflect" - "strconv" "strings" "sync" "time" @@ -35,7 +34,7 @@ import ( ) // Version of current fiber package -const Version = "3.4.0" +const Version = "3.6.0" // Handler defines a function to serve HTTP requests. type Handler = func(Ctx) error @@ -82,8 +81,6 @@ type App struct { pool sync.Pool // Fasthttp server server *fasthttp.Server - // Converts string to a byte slice - toBytes func(s string) (b []byte) // Converts byte slice to a string toString func(b []byte) string // Hooks @@ -100,6 +97,9 @@ type App struct { state *State // shared state management (prefork-safe, storage-backed) sharedState *SharedState + // headerHook is the HeaderReceived callback hookHeaderReceived installed, kept + // to tell it from one set since + headerHook func(*fasthttp.RequestHeader) fasthttp.RequestConfig // Route stack divided by HTTP methods stack [][]*Route // customConstraints is a list of external constraints @@ -108,8 +108,20 @@ type App struct { sendfiles []*sendFileStore // custom binders customBinders []CustomBinder - // Route stack divided by HTTP methods and route prefixes + // Route stack divided by HTTP methods and route prefixes. Build-time only: + // requests go through treeIndex. Each build replaces it with freshly + // allocated buckets rather than refilling the previous ones, so a published + // tree stays immutable; it is retained as a field because buildLookahead + // reads it to index the same buckets next() will scan. treeStack []map[int][]*Route + // Request-time view of treeStack: one flat, open-addressed index per HTTP + // method, rebuilt with the tree (see routeTree in router.go). Held by + // pointer so a rebuild publishes each method's tree in one store. + treeIndex []*routeTree + // Precomputed unmatched-route indexes, rebuilt with the tree (router_skip.go) + skip skipRouteIndex + autoHeadRouteID uint64 + autoHeadStackLen int // sendfilesMutex is a mutex used for sendfile operations sendfilesMutex sync.RWMutex mutex sync.Mutex @@ -117,8 +129,12 @@ type App struct { handlersCount uint32 // contains the information if the route stack has been changed to build the optimized tree hasRoutesRefreshed bool + connStateHooked bool // hasCustomCtx tracks whether app uses a custom context implementation hasCustomCtx bool + // hasParamRoutes tracks whether any route consults the per-request slash + // count (rebuilt with the tree); when false the count is skipped entirely + hasParamRoutes bool } type viewsLockKey struct { @@ -171,6 +187,20 @@ func getViewsLock(views Views) *sync.RWMutex { return globalViewsLocks.get(views) } +func isNilViews(views any) bool { + if views == nil { + return true + } + + value := reflect.ValueOf(views) + switch value.Kind() { + case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Chan, reflect.Func, reflect.Interface, reflect.UnsafePointer: + return value.IsNil() + default: + return false + } +} + // Config is a struct holding the server settings. type Config struct { //nolint:govet // Aligning the struct fields is not necessary. betteralign:ignore // Enables the "Server: value" HTTP header. @@ -191,12 +221,40 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa // Default: false CaseSensitive bool `json:"case_sensitive"` + // When set to true, requests whose path and method match no registered route + // are answered with 404 (or 405 when the path exists for other methods) + // before the middleware chain runs, so no work is spent on bots, scanners, + // and bad URLs. + // + // Warning: middleware never runs for skipped requests. This breaks Use-based + // responders on unregistered paths (catch-all 404 pages, static, proxy, + // healthcheck, rewrite and redirect middleware); loggers and metrics will not + // see the skipped requests either, and a rate limiter neither counts nor + // throttles them. CORS preflight requests are exempt, so cors middleware + // keeps working. Customize the 404/405 responses via ErrorHandler. + // + // Note: with more than 64 entries in RequestMethods the fast path is disabled + // and requests fall through to the normal router. + // + // Default: false + SkipUnmatchedRoutes bool `json:"skip_unmatched_routes"` + // When set to true, disables automatic registration of HEAD routes for // every GET route. // // Default: false DisableHeadAutoRegister bool `json:"disable_head_auto_register"` + // When set to true, disables redirect flash messages: Redirect().With and + // WithInput set no cookie, Messages and OldInput report nothing, and the + // scan of every request's headers for an incoming flash cookie is skipped. + // Flash messages travel in the fiber_flash cookie, so only clients that + // keep cookies across a redirect, browsers above all, ever receive them; + // deployments whose clients do not lose nothing by turning them off. + // + // Default: false + DisableFlashMessages bool `json:"disable_flash_messages"` + // When set to true, this relinquishes the 0-allocation promise in certain // cases in order to access the handler values (e.g. request bodies) in an // immutable fashion so that these values are available even if you return @@ -205,10 +263,12 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa // Default: false Immutable bool `json:"immutable"` - // When set to true, converts all encoded characters in the route back - // before setting the path for the context, so that the routing, - // the returning of the current url from the context `ctx.Path()` - // and the parameters `ctx.Params(%key%)` with decoded characters will work + // The router always normalizes the request path before matching (RFC 3986 + // Section 6.2.2): escapes of unreserved characters are decoded, other + // escapes keep their encoding with uppercase hex digits, and "." and ".." + // segments are removed. When set to true, every escape is decoded, so the + // routing, `ctx.Path()` and `ctx.Params(%key%)` see the fully decoded + // path. // // Default: false UnescapePath bool `json:"unescape_path"` @@ -277,12 +337,12 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa // Increase this buffer if your clients send multi-KB RequestURIs // and/or multi-KB headers (for example, BIG cookies). // - // Default: 4096 + // Default: 8192 ReadBufferSize int `json:"read_buffer_size"` // Per-connection buffer size for responses' writing. // - // Default: 4096 + // Default: 8192 WriteBufferSize int `json:"write_buffer_size"` // CompressedFileSuffixes adds suffix to the original file name and @@ -299,10 +359,11 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa // Default: "" ProxyHeader string `json:"proxy_header"` - // GETOnly rejects all non-GET requests if set to true. + // GETOnly rejects every method except GET and HEAD if set to true. // This option is useful as anti-DoS protection for servers // accepting only GET requests. The request size is limited - // by ReadBufferSize if GETOnly is set. + // by ReadBufferSize if GETOnly is set. A rejected request gets 405 with + // "Allow: GET, HEAD". // // Default: false GETOnly bool `json:"get_only"` @@ -467,7 +528,13 @@ type Config struct { //nolint:govet // Aligning the struct fields is not necessa TrustProxyConfig TrustProxyConfig `json:"trust_proxy_config"` // If set to true, c.IP() and c.IPs() will validate IP addresses before returning them. - // Also, c.IP() will return only the first valid IP rather than just the raw header + // Also, c.IP() will return a single validated IP rather than just the raw header value, + // which for X-Forwarded-For may be a comma-separated chain: when TrustProxyConfig names + // proxy IPs or ranges (Proxies, Loopback, Private or LinkLocal) the chain is walked + // right-to-left and those proxies are skipped; otherwise, including when only UnixSocket + // is trusted, the first valid IP from the left is returned. Enable it whenever c.IP() is + // used as a single client identifier and the header can carry a chain; a proxy that + // overwrites the header with one address, or a single-IP header, does not need it. // WARNING: this has a performance cost associated with it. // // Default: false @@ -585,8 +652,8 @@ const ( DefaultBodyLimit = 4 * 1024 * 1024 DefaultMaxRanges = 16 DefaultConcurrency = 256 * 1024 - DefaultReadBufferSize = 4096 - DefaultWriteBufferSize = 4096 + DefaultReadBufferSize = 8192 + DefaultWriteBufferSize = 8192 ) const ( @@ -668,7 +735,6 @@ func New(config ...Config) *App { app := &App{ // Create config config: Config{}, - toBytes: utils.UnsafeBytes, toString: utils.UnsafeString, latestRoute: &Route{}, customBinders: []CustomBinder{}, @@ -730,7 +796,7 @@ func New(config ...Config) *App { } if app.config.Immutable { - app.toBytes, app.toString = toBytesImmutable, toStringImmutable + app.toString = toStringImmutable } if app.config.ErrorHandler == nil { @@ -776,6 +842,11 @@ func New(config ...Config) *App { // Create router stack app.stack = make([][]*Route, len(app.config.RequestMethods)) app.treeStack = make([]map[int][]*Route, len(app.config.RequestMethods)) + app.treeIndex = make([]*routeTree, len(app.config.RequestMethods)) + for i := range app.treeIndex { + // Never nil: next() may run before the tree is first built. + app.treeIndex[i] = &routeTree{} + } // Override colors app.config.ColorScheme = defaultColors(&app.config.ColorScheme) @@ -834,7 +905,12 @@ func (app *App) handleTrustedProxy(ipAddress string) { if ip == nil { log.Warnf("IP address %q could not be parsed", ipAddress) } else { - app.config.TrustProxyConfig.ips[ipAddress] = struct{}{} + // Store the canonical spelling, which lookups compare against. + app.config.TrustProxyConfig.ips[ip.String()] = struct{}{} + if ip4 := ip.To4(); ip4 != nil { + // netip keeps the IPv4-mapped spelling apart from the dotted one. + app.config.TrustProxyConfig.ips["::ffff:"+ip4.String()] = struct{}{} + } } } } @@ -865,21 +941,15 @@ func (app *App) RegisterCustomBinder(customBinder CustomBinder) { // ReloadViews reloads the configured view engine by invoking its Load method. // It returns an error if no view engine is configured or if reloading fails. func (app *App) ReloadViews() error { - app.mutex.Lock() - defer app.mutex.Unlock() - - apps := map[string]*App{"": app} - if app.mountFields != nil { - apps = app.mountFields.appList - } + // Walks the mount metadata rather than the flattened app list: a domain + // mount nested inside a plain one only reaches the root's list once the + // app has started, and ReloadViews may be called before that. The walk + // takes each app's own lock in turn, so this must not hold one itself. + apps := app.mountedApps() var reloaded bool for _, targetApp := range apps { - if targetApp == nil || targetApp.config.Views == nil { - continue - } - - if viewValue := reflect.ValueOf(targetApp.config.Views); viewValue.Kind() == reflect.Pointer && viewValue.IsNil() { + if targetApp == nil || isNilViews(targetApp.config.Views) { continue } @@ -907,6 +977,27 @@ func (app *App) ReloadViews() error { return nil } +// Render writes a template through the configured view engine. +func (app *App) Render(out io.Writer, name string, binding any, layouts ...string) error { + views := app.config.Views + if isNilViews(views) { + return ErrNoViewEngineConfigured + } + if len(layouts) == 0 && app.config.ViewsLayout != "" { + layouts = []string{app.config.ViewsLayout} + } + + viewsLock := getViewsLock(views) + viewsLock.RLock() + defer viewsLock.RUnlock() + + if err := views.Render(out, name, binding, layouts...); err != nil { + return fmt.Errorf("fiber: failed to render views: %w", err) + } + + return nil +} + // SetTLSHandler Can be used to set ClientHelloInfo when using TLS with Listener. func (app *App) SetTLSHandler(tlsHandler *TLSHandler) { // Attach the tlsHandler to the config @@ -922,7 +1013,15 @@ func (app *App) Name(name string) Router { for _, routes := range app.stack { for _, route := range routes { - isMethodValid := route.Method == app.latestRoute.Method || app.latestRoute.use || + // The shared registration id covers every method of a multi-method + // Add, and only those: matching on the method as well would rename + // an older route that merely shares the path, and would do it only + // when the registration happened to finish on that method. It is + // latestID rather than id because a method whose route the + // registration merged into keeps the id of the registration that + // created it. + isMethodValid := route.latestID == app.latestRoute.latestID || + app.latestRoute.use || (app.latestRoute.Method == MethodGet && route.Method == MethodHead) if route.Path == app.latestRoute.Path && isMethodValid { @@ -1022,7 +1121,9 @@ func (app *App) Use(args ...any) Router { for _, prefix := range prefixes { if subApp != nil { - return app.mount(prefix, subApp) + // Every prefix mounts the sub-app, as every prefix registers a handler. + app.mount(prefix, subApp) + continue } app.register([]string{methodUse}, prefix, nil, handlers...) @@ -1221,8 +1322,9 @@ func NewErrorf(code int, message ...any) *Error { if format, ok := message[0].(string); ok { msg = fmt.Sprintf(format, message[1:]...) } else { - // If the first arg isn’t a string, fall back. - msg = fmt.Sprint(message[0]) + // If the first arg isn’t a format string, stringify all of them + // instead of dropping everything after the first. + msg = fmt.Sprint(message...) } } @@ -1275,8 +1377,8 @@ func (app *App) Shutdown() error { return app.ShutdownWithContext(context.Background()) } -// ShutdownWithTimeout gracefully shuts down the server without interrupting any active connections. However, if the timeout is exceeded, -// ShutdownWithTimeout will forcefully close any active connections. +// ShutdownWithTimeout gracefully shuts down the server without interrupting any active connections. If the timeout is exceeded, +// it stops waiting and returns context.DeadlineExceeded; connections still active are not closed. // ShutdownWithTimeout works by first closing all open listeners and then waiting for all connections to return to idle before shutting down. // // Make sure the program doesn't exit and waits instead for ShutdownWithTimeout to return. @@ -1288,26 +1390,31 @@ func (app *App) ShutdownWithTimeout(timeout time.Duration) error { return app.ShutdownWithContext(ctx) } -// ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded. +// ShutdownWithContext shuts down the server and stops waiting once ctx is done; connections still active are not closed. // // Make sure the program doesn't exit and waits instead for ShutdownWithTimeout to return. // // ShutdownWithContext does not close keepalive connections so its recommended to set ReadTimeout to something else than 0. func (app *App) ShutdownWithContext(ctx context.Context) error { app.mutex.Lock() - defer app.mutex.Unlock() - - var err error + server := app.server + app.mutex.Unlock() - if app.server == nil { + if server == nil { return ErrNotRunning } + // The drain waits for in-flight handlers, so the mutex must not be held + // meanwhile: a handler taking it (RebuildTree, Name, ...) would never finish. + var err error + // Execute the Shutdown hook app.hooks.executeOnPreShutdownHooks() - defer app.hooks.executeOnPostShutdownHooks(err) + // Use a closure so the hooks receive the final error; a plain + // `defer ...(err)` would capture the nil value at registration time. + defer func() { app.hooks.executeOnPostShutdownHooks(err) }() - err = app.server.ShutdownWithContext(ctx) + err = server.ShutdownWithContext(ctx) return err } @@ -1366,7 +1473,7 @@ func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, e // Add Content-Length if not provided with body if req.Body != http.NoBody && req.Header.Get(HeaderContentLength) == "" { - req.Header.Add(HeaderContentLength, strconv.FormatInt(req.ContentLength, 10)) + req.Header.Add(HeaderContentLength, utils.FormatInt(req.ContentLength)) } // Ensure Host header is present in the dump (required by fasthttp) @@ -1397,6 +1504,7 @@ func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, e } // prepare the server for the start app.startupProcess() + app.hookHeaderReceived() // Serve conn to server channel := make(chan error, 1) @@ -1492,7 +1600,7 @@ func (app *App) init() *App { app.initServices() // Only load templates if a view engine is specified - if app.config.Views != nil { + if !isNilViews(app.config.Views) { if err := app.config.Views.Load(); err != nil { log.Warnf("failed to load views: %v", err) } @@ -1548,28 +1656,33 @@ func (app *App) init() *App { // error handler. Otherwise, it uses the configured error handler for // the app, which if not set is the DefaultErrorHandler. func (app *App) ErrorHandler(ctx Ctx, err error) error { + // Once fasthttp holds a timeout response, writes are ignored and the + // timed-out handler may still be writing: leave the context alone. + if ctx.RequestCtx().LastTimeoutErrorResponse() != nil { + return nil + } + // Fast path: no mounted sub-apps, so no prefix lookup is needed - if len(app.mountFields.appListKeys) == 0 { + if len(app.mountFields.appListKeys) == 0 && len(app.mountFields.domainAppList) == 0 { return app.config.ErrorHandler(ctx, err) } var ( mountedErrHandler ErrorHandler + mountedErrApp *App mountedPrefixParts int ) - normalizedPath := utils.AddTrailingSlashString(ctx.Path()) - for _, prefix := range app.mountFields.appListKeys { subApp := app.mountFields.appList[prefix] - normalizedPrefix := utils.AddTrailingSlashString(prefix) - if prefix != "" && strings.HasPrefix(normalizedPath, normalizedPrefix) { + if app.mountCoversPath(prefix, ctx.Path()) { // Count slashes instead of splitting - more efficient - parts := strings.Count(prefix, "/") + 1 + parts := mountDepth(prefix) if mountedPrefixParts <= parts { if subApp.configured.ErrorHandler != nil { mountedErrHandler = subApp.config.ErrorHandler + mountedErrApp = subApp } mountedPrefixParts = parts @@ -1577,6 +1690,28 @@ func (app *App) ErrorHandler(ctx Ctx, err error) error { } } + // Sub-apps mounted on a domain answer only for a matching host, so their + // error handler cannot be picked by path alone. The owner is considered + // after the plain mounts, which lets a domain mount win a tie on path + // depth: it matched the host too, so it is the more specific of the two. + if owner := app.domainMountOwner(ctx); owner.outranks(mountedPrefixParts) { + // A plain mount the owner supersedes did not serve the request, so its + // handler is dropped rather than inherited. One enclosing the owner + // still does, and an owner configuring no handler of its own inherits + // it, as a nested mount inherits the handler of the mount it sits in. + // + // Unless the mount is one of the apps the owner sits in: a domain + // mount at the root of a plain one covers exactly the paths that mount + // does, and is as deep as it without being beside it. + if owner.supersedes(mountedPrefixParts, mountedErrApp) { + mountedErrHandler = nil + } + + if handler := domainMountConfig(owner, appHasErrorHandler); handler != nil { + mountedErrHandler = handler.config.ErrorHandler + } + } + if mountedErrHandler != nil { return mountedErrHandler(ctx, err) } @@ -1584,6 +1719,18 @@ func (app *App) ErrorHandler(ctx Ctx, err error) error { return app.config.ErrorHandler(ctx, err) } +const ( + // getOnlyAllow is the Allow value of the 405 that Config.GETOnly produces. + getOnlyAllow = MethodGet + ", " + MethodHead + + // unsupportedTransferCodingMarker precedes the quoted coding in fasthttp's + // error. The ErrUnsupportedTransferEncoding sentinel is not matched: it also + // covers HTTP/1.0 and repeated fields, which are framing errors and stay 400, + // and with Server.SecureErrorLogMessage it stands for every fault, the + // coding included, which then stays 400 as well. + unsupportedTransferCodingMarker = `unsupported transfer-encoding: "` +) + // serverErrorHandler is a wrapper around the application's error handler method // user for the fasthttp server configuration. It maps a set of fasthttp errors to fiber // errors before calling the application's error handler method. @@ -1619,14 +1766,25 @@ func (app *App) serverErrorHandler(fctx *fasthttp.RequestCtx, err error) { err = ErrRequestEntityTooLarge case errors.Is(err, fasthttp.ErrGetOnly): err = ErrMethodNotAllowed + // A 405 must carry Allow (RFC 9110 §15.5.6). + c.Set(HeaderAllow, getOnlyAllow) case strings.Contains(errMessage, "unsupported http request method"): err = ErrNotImplemented + case strings.Contains(errMessage, unsupportedTransferCodingMarker): + // An unknown transfer coding is a 501, not a 400 (RFC 9112 §6.1). + err = ErrNotImplemented case strings.Contains(errMessage, "timeout"): err = ErrRequestTimeout default: err = NewError(StatusBadRequest, errMessage) } + // Seed the mapped status so middleware observes it instead of the default 200. + // The ErrorHandler below still has the last word on what goes out. + if fiberErr, matched := asFiberError(err); matched && fiberErr != nil { + c.Status(fiberErr.Code) + } + if c.getMethodInt() != -1 { c.setSkipNonUseRoutes(true) defer c.setSkipNonUseRoutes(false) @@ -1655,6 +1813,9 @@ func (app *App) startupProcess() { app.mutex.Lock() defer app.mutex.Unlock() + app.hookConnState() + // Collect every mounted app first, nested ones included, so all get their automatic HEAD routes. + app.collectSubApps() app.ensureAutoHeadRoutesLocked() for prefix, subApp := range app.mountFields.appList { if prefix == "" { @@ -1668,6 +1829,67 @@ func (app *App) startupProcess() { app.buildTree() } +// hookConnState makes the server report new and closed connections to the TLS +// handler, keeping a user ConnState callback. A connection is reported new +// while it can still say what it wraps, which is what lets its record be found +// again at close. Idempotent; the caller holds app.mutex. +func (app *App) hookConnState() { + if app.connStateHooked || app.server == nil { + return + } + app.connStateHooked = true + user := app.server.ConnState + app.server.ConnState = func(conn net.Conn, state fasthttp.ConnState) { + // StateHijacked is terminal too: fasthttp never reports StateClosed after + // it, so a hijacked connection (every WebSocket upgrade) would strand its + // record. + if state == fasthttp.StateNew || state == fasthttp.StateClosed || state == fasthttp.StateHijacked { + app.mutex.Lock() + handler := app.tlsHandler + app.mutex.Unlock() + if handler != nil { + if state == fasthttp.StateNew { + handler.track(conn) + } else { + handler.forget(conn) + } + } + } + if user != nil { + user(conn, state) + } + } +} + +// hookHeaderReceived makes the server close the connection after a request that +// carries both Content-Length and Transfer-Encoding (RFC 9112 §6.1), keeping a +// user HeaderReceived callback. It must run before the body is decoded: after that +// fasthttp has replaced the length and dropped the Content-Length value. Call it +// right before the server serves: it wraps the callback set by then, in +// ListenConfig.BeforeServeFunc too, and one replaced since an earlier start. Its +// own hook is left alone: Test and a listener run on one server at the same time, +// and the connections they serve read the callback. +func (app *App) hookHeaderReceived() { + app.mutex.Lock() + defer app.mutex.Unlock() + + if app.server == nil || sameFunc(app.server.HeaderReceived, app.headerHook) { + return + } + user := app.server.HeaderReceived + app.headerHook = func(header *fasthttp.RequestHeader) fasthttp.RequestConfig { + if bothFramingFields(header) { + header.SetConnectionClose() + } + if user != nil { + return user(header) + } + // The zero value keeps the server's own limits and timeouts. + return fasthttp.RequestConfig{} + } + app.server.HeaderReceived = app.headerHook +} + // Run onListen hooks. If they return an error, panic. func (app *App) runOnListenHooks(listenData *ListenData) { if err := app.hooks.executeOnListenHooks(listenData); err != nil { diff --git a/src/vendor/github.com/gofiber/fiber/v3/appconfig.go b/src/vendor/github.com/gofiber/fiber/v3/appconfig.go new file mode 100644 index 00000000..e0fb1bc9 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/appconfig.go @@ -0,0 +1,26 @@ +package fiber + +import ( + "github.com/gofiber/fiber/v3/internal/appconfig" +) + +// The internal packages behind the extractors read a few Config bits per +// request, and Config() copies the whole struct to answer each one. They +// cannot read them directly: config is unexported, and importing those +// packages here would be a cycle. +// +// From init rather than New, so no request can reach them before it is set. +func init() { + appconfig.SetReader(func(a any) appconfig.Hot { + app, ok := a.(*App) + if !ok { + return appconfig.Hot{} + } + // A nil app faults here, as reading Config() off one did before. + return appconfig.Hot{ + Immutable: app.config.Immutable, + DisableHeaderNormalizing: app.config.DisableHeaderNormalizing, + UnescapePath: app.config.UnescapePath, + } + }) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/bind.go b/src/vendor/github.com/gofiber/fiber/v3/bind.go index cacf7c4a..7d2a71be 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/bind.go +++ b/src/vendor/github.com/gofiber/fiber/v3/bind.go @@ -6,13 +6,12 @@ import ( "fmt" "reflect" "slices" + "strings" "sync" "github.com/gofiber/fiber/v3/binder" "github.com/gofiber/fiber/v3/internal/nilerror" "github.com/gofiber/schema" - "github.com/gofiber/utils/v2" - utilsbytes "github.com/gofiber/utils/v2/bytes" ) // CustomBinder An interface to register custom binders. @@ -346,6 +345,9 @@ func (b *Bind) XML(out any) error { // If Content-Type is "application/x-www-form-urlencoded" or "multipart/form-data", it will bind the form values. // Multipart file fields are supported using *multipart.FileHeader, []*multipart.FileHeader, or *[]*multipart.FileHeader. func (b *Bind) Form(out any) error { + // The Content-Type is deliberately not normalized here: FormBinding.Bind opens + // by doing it itself, so a fold here would be a second pass over the same + // header. Body still folds, because it must read the media type to dispatch. bind := binder.GetFromThePool[*binder.FormBinding](&binder.FormBinderPool) bind.EnableSplitting = b.ctx.App().config.EnableSplittingOnParsers bind.MaxBodySize = b.ctx.App().config.BodyLimit @@ -391,13 +393,13 @@ func (b *Bind) MsgPack(out any) error { // Body binds the request body into the struct, map[string]string and map[string][]string. // Returns *BindError on parse failure (manual mode) or *Error with status 400 (auto-handling mode). // It supports decoding the following content types based on the Content-Type header: -// application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data -// If none of the content types above are matched, it'll take a look custom binders by checking the MIMETypes() method of custom binder. -// If there is no custom binder for mime type of body, it will return a ErrUnprocessableEntity error. +// application/json, application/vnd.msgpack, application/xml, text/xml, application/cbor, +// application/x-www-form-urlencoded, multipart/form-data +// Custom binders are checked first, so the first one whose MIMETypes() holds the +// request's content type runs instead of the built-in decoder for that type. +// If neither matches the content type, it will return an ErrUnprocessableEntity error. func (b *Bind) Body(out any) error { - // Get content-type - ctype := utils.UnsafeString(utilsbytes.UnsafeToLower(b.ctx.RequestCtx().Request.Header.ContentType())) - ctype = binder.FilterFlags(utils.ParseVendorSpecificContentType(ctype)) + ctype := bindMediaType(&b.ctx.RequestCtx().Request.Header) // Check custom binders binders := b.ctx.App().customBinders @@ -428,6 +430,75 @@ func (b *Bind) Body(out any) error { return ErrUnprocessableEntity } +type bindSource int + +const ( + sourceURI bindSource = iota + sourceBody + sourceQuery + sourceHeader + sourceCookie +) + +type cachedPrecedence struct { + err error + sources []bindSource +} + +var bindingPrecedenceCache sync.Map // map[reflect.Type]cachedPrecedence + +func getBindingPrecedence(t reflect.Type) ([]bindSource, error) { + if cached, ok := bindingPrecedenceCache.Load(t); ok { + if cp, ok := cached.(cachedPrecedence); ok { + return cp.sources, cp.err + } + } + var precedence []bindSource + var tagFound bool + for i := range t.NumField() { + if tag := t.Field(i).Tag.Get("binding_source"); tag != "" { + if tagFound { + err := fmt.Errorf("multiple binding_source tags found on struct %s", t.Name()) + bindingPrecedenceCache.Store(t, cachedPrecedence{err: err, sources: nil}) + return nil, err + } + tagFound = true + + parts := strings.SplitSeq(tag, ",") + for p := range parts { + sourceName := strings.TrimSpace(p) + if sourceName == "" { + continue + } + var source bindSource + switch sourceName { + case "uri": + source = sourceURI + case "body": + source = sourceBody + case "query": + source = sourceQuery + case "header": + source = sourceHeader + case "cookie": + source = sourceCookie + default: + err := fmt.Errorf("unknown binding_source %q", sourceName) + bindingPrecedenceCache.Store(t, cachedPrecedence{err: err, sources: nil}) + return nil, err + } + + // check for duplicates + if !slices.Contains(precedence, source) { + precedence = append(precedence, source) + } + } + } + } + bindingPrecedenceCache.Store(t, cachedPrecedence{err: nil, sources: precedence}) + return precedence, nil +} + // All binds values from URI params, the request body, the query string, // headers, and cookies into the provided struct in precedence order. // Returns *BindError on parse failure (manual mode) or *Error with status 400 (auto-handling mode). @@ -439,18 +510,46 @@ func (b *Bind) All(out any) error { outElem := outVal.Elem() - // Precedence: URL Params -> Body -> Query -> Headers -> Cookies - sources := []func(any) error{b.URI} + sources := make([]func(any) error, 0, 5) + customPrecedence, err := getBindingPrecedence(outElem.Type()) + if err != nil { + // Note: A malformed binding_source tag is a programmer error, not a client error. + // Returning the raw error here bypasses b.returnErr, intentionally resulting in a 500 + // rather than a 400 even in auto-handling mode. + return err + } - // Check if both Body and Content-Type are set - if len(b.ctx.Request().Body()) > 0 && len(b.ctx.RequestCtx().Request.Header.ContentType()) > 0 { - sources = append(sources, b.Body) + if len(customPrecedence) > 0 { + for _, source := range customPrecedence { + switch source { + case sourceURI: + sources = append(sources, b.URI) + case sourceBody: + if len(b.ctx.Request().Body()) > 0 && len(b.ctx.RequestCtx().Request.Header.ContentType()) > 0 { + sources = append(sources, b.Body) + } + case sourceQuery: + sources = append(sources, b.Query) + case sourceHeader: + sources = append(sources, b.Header) + case sourceCookie: + sources = append(sources, b.Cookie) + } + } + } else { + // Precedence: URL Params -> Body -> Query -> Headers -> Cookies + sources = append(sources, b.URI) + + // Check if both Body and Content-Type are set + if len(b.ctx.Request().Body()) > 0 && len(b.ctx.RequestCtx().Request.Header.ContentType()) > 0 { + sources = append(sources, b.Body) + } + sources = append(sources, b.Query, b.Header, b.Cookie) } - sources = append(sources, b.Query, b.Header, b.Cookie) + prevSkip := b.shouldSkipValidation b.shouldSkipValidation = true - // TODO: Support custom precedence with an optional binding_source tag // TODO: Create WithOverrideEmptyValues // Bind from each source, but only update unset fields for _, bindFunc := range sources { diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/cookie.go b/src/vendor/github.com/gofiber/fiber/v3/binder/cookie.go index b169b714..cdccb7d4 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/cookie.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/cookie.go @@ -17,18 +17,18 @@ func (*CookieBinding) Name() string { // Bind parses the request cookie and returns the result. func (b *CookieBinding) Bind(req *fasthttp.Request, out any) error { - data := acquireDataMap() - defer releaseDataMap(data) + data := acquireBindData(out, 0) + defer releaseBindData(data) for key, val := range req.Header.Cookies() { k := utils.UnsafeString(key) v := utils.UnsafeString(val) - if err := formatBindData(b.Name(), out, data, k, v, b.EnableSplitting, false); err != nil { + if err := data.bind(b.Name(), out, k, v, b.EnableSplitting, false); err != nil { return err } } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // Reset resets the CookieBinding binder. diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/form.go b/src/vendor/github.com/gofiber/fiber/v3/binder/form.go index fb846b66..27419e5d 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/form.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/form.go @@ -4,6 +4,7 @@ import ( "mime/multipart" "sync" + "github.com/gofiber/fiber/v3/internal/mediatype" "github.com/gofiber/utils/v2" "github.com/valyala/fasthttp" ) @@ -11,9 +12,9 @@ import ( const MIMEMultipartForm string = "multipart/form-data" var ( - dataMapPool = sync.Pool{ + bindDataPool = sync.Pool{ New: func() any { - return make(map[string][]string, 8) + return &bindData{values: make(map[string][]string, 8)} }, } formFileMapPool = sync.Pool{ @@ -23,9 +24,12 @@ var ( } ) -// Keep oversized maps out of the pool so a rare large bind doesn't get retained -// and reused across subsequent requests. -const maxPoolableDataMapSize = 256 +// Keep oversized maps and pair slices out of the pool so a rare large bind +// doesn't get retained and reused across subsequent requests. +const ( + maxPoolableDataMapSize = 256 + maxPoolablePairs = 1024 +) // FormBinding is the form binder for form request body. type FormBinding struct { @@ -40,23 +44,32 @@ func (*FormBinding) Name() string { // Bind parses the request body and returns the result. func (b *FormBinding) Bind(req *fasthttp.Request, out any) error { - // Handle multipart form - if FilterFlags(utils.UnsafeString(req.Header.ContentType())) == MIMEMultipartForm { + // Callers reaching the binder directly skip Fiber's normalization, and + // comparing case-insensitively is not enough: PostArgs and MultipartForm match + // the media type and "boundary=" case-sensitively. Guarded — the fold writes. + if mediatype.IsForm(req.Header.ContentType()) { + mediatype.NormalizeRequestContentType(&req.Header) + } + + // Handle multipart form. Media types are case-insensitive + // (RFC 9110 Section 8.3.1), so compare accordingly. + if utils.EqualFold(FilterFlags(utils.UnsafeString(req.Header.ContentType())), MIMEMultipartForm) { return b.bindMultipart(req, out) } - data := acquireDataMap() - defer releaseDataMap(data) + args := req.PostArgs() + data := acquireBindData(out, args.Len()) + defer releaseBindData(data) - for key, val := range req.PostArgs().All() { + for key, val := range args.All() { k := utils.UnsafeString(key) v := utils.UnsafeString(val) - if err := formatBindData(b.Name(), out, data, k, v, b.EnableSplitting, true); err != nil { + if err := data.bind(b.Name(), out, k, v, b.EnableSplitting, true); err != nil { return err } } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // bindMultipart parses the request body and returns the result. @@ -66,11 +79,17 @@ func (b *FormBinding) bindMultipart(req *fasthttp.Request, out any) error { return err } - data := acquireDataMap() - defer releaseDataMap(data) + // The files are merged into the decoder's view of the source map, so a + // multipart form is always filed into one. + mode := bindModeFor(out) + if mode == bindPairs { + mode = bindMap + } + data := acquireBindDataMode(mode) + defer releaseBindData(data) for key, values := range multipartForm.Value { - err = formatBindData(b.Name(), out, data, key, values, b.EnableSplitting, true) + err = data.bindAll(b.Name(), out, key, values, b.EnableSplitting, true) if err != nil { return err } @@ -79,14 +98,17 @@ func (b *FormBinding) bindMultipart(req *fasthttp.Request, out any) error { files := acquireFileHeaderMap() defer releaseFileHeaderMap(files) - for key, values := range multipartForm.File { - err = formatBindData(b.Name(), out, files, key, values, b.EnableSplitting, true) - if err != nil { + for key, headers := range multipartForm.File { + if err := bindFiles(files, key, headers); err != nil { return err } } - return parse(b.Name(), out, data, files) + if data.mode == bindLast { + // A map[string]string keeps no files: parseToMap ignores them too. + return data.parse(b.Name(), out) + } + return parse(b.Name(), out, data.values, files) } // Reset resets the FormBinding binder. @@ -95,21 +117,56 @@ func (b *FormBinding) Reset() { b.MaxBodySize = 0 } -func acquireDataMap() map[string][]string { - m, ok := dataMapPool.Get().(map[string][]string) +// acquireBindData returns a pooled bindData for a bind into out of n pairs, +// 0 when the count is not known up front. A bind into a struct keeps its +// pairs in two slices, which get room for n here, so that a large bind +// allocates them once rather than growing them by appending: splitting can +// file more pairs than n, and append makes room for those. +func acquireBindData(out any, n int) *bindData { + d := acquireBindDataMode(bindModeFor(out)) + if d.mode == bindPairs && n > cap(d.keys) { + d.keys = make([]string, 0, n) + d.pairValues = make([]string, 0, n) + } + return d +} + +// acquireBindDataMode returns a pooled bindData that keeps its values as mode +// says. +func acquireBindDataMode(mode bindMode) *bindData { + d, ok := bindDataPool.Get().(*bindData) if !ok { - m = make(map[string][]string, 8) + d = &bindData{values: make(map[string][]string, 8)} } - return m + if mode == bindLast && d.last == nil { + d.last = make(map[string]string, 8) + } + d.mode = mode + return d } -func releaseDataMap(m map[string][]string) { - if len(m) > maxPoolableDataMapSize { +func releaseBindData(d *bindData) { + if len(d.values) > maxPoolableDataMapSize || len(d.last) > maxPoolableDataMapSize || + cap(d.keys) > maxPoolablePairs { return } - clearDataMap(m) - dataMapPool.Put(m) + d.reset() + bindDataPool.Put(d) +} + +// reset empties d for another bind, dropping the strings it held so they do +// not keep request memory alive while d sits in the pool. +func (d *bindData) reset() { + clearDataMap(d.values) + // A map in use for another mode is empty, and clear would still call + // into the runtime for it. + if len(d.last) > 0 { + clear(d.last) + } + clear(d.keys) + clear(d.pairValues) + d.keys, d.pairValues = d.keys[:0], d.pairValues[:0] } func acquireFileHeaderMap() map[string][]*multipart.FileHeader { diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/header.go b/src/vendor/github.com/gofiber/fiber/v3/binder/header.go index 971b6977..76ea4dbe 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/header.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/header.go @@ -17,18 +17,18 @@ func (*HeaderBinding) Name() string { // Bind parses the request header and returns the result. func (b *HeaderBinding) Bind(req *fasthttp.Request, out any) error { - data := acquireDataMap() - defer releaseDataMap(data) + data := acquireBindData(out, 0) + defer releaseBindData(data) for key, val := range req.Header.All() { k := utils.UnsafeString(key) v := utils.UnsafeString(val) - if err := formatBindData(b.Name(), out, data, k, v, b.EnableSplitting, false); err != nil { + if err := data.bind(b.Name(), out, k, v, b.EnableSplitting, false); err != nil { return err } } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // Reset resets the HeaderBinding binder. diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/mapping.go b/src/vendor/github.com/gofiber/fiber/v3/binder/mapping.go index fdc6f91a..aebaf9cf 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/mapping.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/mapping.go @@ -7,7 +7,10 @@ import ( "reflect" "strings" "sync" + "sync/atomic" + "unsafe" + "github.com/gofiber/utils/v2" utilsstrings "github.com/gofiber/utils/v2/strings" "github.com/valyala/bytebufferpool" @@ -16,6 +19,7 @@ import ( // ParserConfig form decoder config for SetParserDecoder type ParserConfig struct { + // SetAliasTag is ignored: every binder decodes with the tag of its own source. SetAliasTag string ParserType []ParserType IgnoreUnknownKeys bool @@ -29,36 +33,68 @@ type ParserType struct { Converter func(string) reflect.Value } +// tags is used to classify parser's pool; a tag's position is its index in +// decoderPoolSet +var tags = [...]string{bindingHeader, bindingRespHeader, bindingCookie, bindingQuery, bindingForm, bindingURI} + +// decoderPoolSet holds the decoder pool of each tag, at the tag's index in +// tags. A set is never written once published: SetParserDecoder publishes a +// new one, so a bind finds its pool with one atomic load instead of the +// read lock every bind used to take, whose shared reader count every core +// contended on. +type decoderPoolSet [len(tags)]*sync.Pool + var ( - decoderPoolMu sync.RWMutex - // decoderPoolMap helps to improve binders - decoderPoolMap = map[string]*sync.Pool{} - // tags is used to classify parser's pool - tags = []string{bindingHeader, bindingRespHeader, bindingCookie, bindingQuery, bindingForm, bindingURI} + // decoderPools is the published decoderPoolSet + decoderPools atomic.Pointer[decoderPoolSet] + // decoderPoolsMu serializes SetParserDecoder + decoderPoolsMu sync.Mutex ) +// tagIndex returns the index of tag in tags, or -1. +func tagIndex(tag string) int { + switch tag { + case bindingHeader: + return 0 + case bindingRespHeader: + return 1 + case bindingCookie: + return 2 + case bindingQuery: + return 3 + case bindingForm: + return 4 + case bindingURI: + return 5 + } + return -1 +} + func getDecoderPool(tag string) *sync.Pool { - decoderPoolMu.RLock() - pool := decoderPoolMap[tag] - if pool == nil { - decoderPoolMu.RUnlock() - panic(fmt.Sprintf("decoder pool not initialized for tag %q", tag)) + if i := tagIndex(tag); i >= 0 { + return decoderPools.Load()[i] } - decoderPoolMu.RUnlock() + panic(fmt.Sprintf("decoder pool not initialized for tag %q", tag)) +} - return pool +// newDecoderPools returns a decoderPoolSet whose decoders are built with +// parserConfig. +func newDecoderPools(parserConfig ParserConfig) *decoderPoolSet { + var pools decoderPoolSet + for i, tag := range tags { + pools[i] = &sync.Pool{New: func() any { + return decoderBuilder(tag, parserConfig) + }} + } + return &pools } // SetParserDecoder allow globally change the option of form decoder, update decoderPool func SetParserDecoder(parserConfig ParserConfig) { - decoderPoolMu.Lock() - defer decoderPoolMu.Unlock() + decoderPoolsMu.Lock() + defer decoderPoolsMu.Unlock() - for _, tag := range tags { - decoderPoolMap[tag] = &sync.Pool{New: func() any { - return decoderBuilder(tag, parserConfig) - }} - } + decoderPools.Store(newDecoderPools(parserConfig)) } func decoderBuilder(aliasTag string, parserConfig ParserConfig) any { @@ -76,17 +112,10 @@ func decoderBuilder(aliasTag string, parserConfig ParserConfig) any { } func init() { - decoderPoolMu.Lock() - defer decoderPoolMu.Unlock() - - for _, tag := range tags { - decoderPoolMap[tag] = &sync.Pool{New: func() any { - return decoderBuilder(tag, ParserConfig{ - IgnoreUnknownKeys: true, - ZeroEmpty: true, - }) - }} - } + decoderPools.Store(newDecoderPools(ParserConfig{ + IgnoreUnknownKeys: true, + ZeroEmpty: true, + })) } // parse data into the map or struct @@ -123,6 +152,44 @@ func parseToStruct(aliasTag string, out any, data map[string][]string, files ... return nil } +// parseValuesToStruct is parseToStruct for key/value pairs: values[i] is a +// value of keys[i]. +func parseValuesToStruct(aliasTag string, out any, keys, values []string) error { + pool := getDecoderPool(aliasTag) + schemaDecoder := pool.Get().(*schema.Decoder) //nolint:errcheck,forcetypeassert // not needed + defer pool.Put(schemaDecoder) + + if err := schemaDecoder.DecodeValues(out, keys, values); err != nil { + return fmt.Errorf("%w", err) + } + + return nil +} + +// parseLast is parse for a map[string]string destination, from the last value +// filed under each key, which is all parseToMap keeps of a key's values. It +// handles the two types bindModeFor gives bindLast as parseToMap would, and a +// nil pointer to one as parse does, by handing it to the struct decoder. +func parseLast(aliasTag string, out any, last map[string]string) error { + switch m := out.(type) { + case *map[string]string: + if m != nil { + if *m == nil { + *m = make(map[string]string, len(last)) + } + maps.Copy(*m, last) + return nil + } + case map[string]string: + if m == nil { + return ErrMapNilDestination + } + maps.Copy(m, last) + return nil + } + return parse(aliasTag, out, nil) +} + // Parse data into the map // thanks to https://github.com/gin-gonic/gin/blob/master/binding/binding.go func parseToMap(target reflect.Value, data map[string][]string) error { @@ -152,6 +219,9 @@ func parseToMap(target reflect.Value, data map[string][]string) error { return ErrMapNotConvertible } + // The value slices are the caller's to keep: the binders append them + // as any slice is appended, and drop them from their pooled map on + // release (see bindData). maps.Copy(newMap, data) case reflect.String: newMap, ok := target.Interface().(map[string]string) @@ -215,10 +285,6 @@ func parseParamSquareBrackets(k string) (string, error) { return bb.String(), nil } -func isStringKeyMap(t reflect.Type) bool { - return t.Kind() == reflect.Map && t.Key().Kind() == reflect.String -} - func isExported(f *reflect.StructField) bool { if f == nil { return false @@ -226,26 +292,39 @@ func isExported(f *reflect.StructField) bool { return f.PkgPath == "" } +// fieldName returns the lowercased name a field is matched by: the alias from +// its tag, or the Go field name when the tag carries none. func fieldName(f *reflect.StructField, aliasTag string) string { if f == nil { return "" } name := f.Tag.Get(aliasTag) + if first, _, found := utils.CutByte(name, ','); found { + name = first + } if name == "" { name = f.Name - } else if first, _, found := strings.Cut(name, ","); found { - name = first } return utilsstrings.ToLower(name) } +// fieldInfo describes how the keys of one struct type resolve to fields, so a +// slice field can be told from a scalar sharing a struct with one. Cached per type. type fieldInfo struct { - names map[string]reflect.Kind + fields map[string]reflect.Type + embedded map[string]reflect.Type + promoted map[string]promotedField + kinds map[string]reflect.Kind nestedKinds map[reflect.Kind]struct{} } +type promotedField struct { + typ reflect.Type + depth int +} + func unwrapType(t reflect.Type) reflect.Type { for t.Kind() == reflect.Pointer { t = t.Elem() @@ -254,16 +333,35 @@ func unwrapType(t reflect.Type) reflect.Type { return t } +// fieldCache holds the field information of the struct types bound through +// one alias tag. It is consulted for every key of every bound request, and the +// interface-keyed hash of a sync.Map lookup was most of what that cost, so a +// small direct-mapped cache in front answers a type seen before in a few +// loads. A collision only falls through to the map; nothing is ever wrong, +// just slower. +type fieldCache struct { + slots [fieldCacheSlots]atomic.Pointer[fieldCacheEntry] + types sync.Map // reflect.Type -> *fieldInfo +} + +type fieldCacheEntry struct { + info *fieldInfo + id uintptr +} + +// fieldCacheSlots is a power of two, so a slot is a mask rather than a division. +const fieldCacheSlots = 64 + var ( - headerFieldCache sync.Map - respHeaderFieldCache sync.Map - cookieFieldCache sync.Map - queryFieldCache sync.Map - formFieldCache sync.Map - uriFieldCache sync.Map + headerFieldCache fieldCache + respHeaderFieldCache fieldCache + cookieFieldCache fieldCache + queryFieldCache fieldCache + formFieldCache fieldCache + uriFieldCache fieldCache ) -func getFieldCache(aliasTag string) *sync.Map { +func getFieldCache(aliasTag string) *fieldCache { switch aliasTag { case bindingHeader: return &headerFieldCache @@ -284,7 +382,9 @@ func getFieldCache(aliasTag string) *sync.Map { func buildFieldInfo(t reflect.Type, aliasTag string) fieldInfo { info := fieldInfo{ - names: make(map[string]reflect.Kind), + fields: make(map[string]reflect.Type), + embedded: make(map[string]reflect.Type), + promoted: make(map[string]promotedField), nestedKinds: make(map[reflect.Kind]struct{}), } @@ -294,112 +394,440 @@ func buildFieldInfo(t reflect.Type, aliasTag string) fieldInfo { continue } fieldType := unwrapType(f.Type) - info.names[fieldName(&f, aliasTag)] = fieldType.Kind() + name := fieldName(&f, aliasTag) + + if f.Anonymous && fieldType.Kind() == reflect.Struct { + info.embedded[name] = fieldType + info.collectPromoted(fieldType, aliasTag, 1, map[reflect.Type]struct{}{t: {}}) + continue + } + info.fields[name] = fieldType if fieldType.Kind() == reflect.Struct { for j := 0; j < fieldType.NumField(); j++ { sf := fieldType.Field(j) if !isExported(&sf) { continue } - nestedType := unwrapType(sf.Type) - info.nestedKinds[nestedType.Kind()] = struct{}{} + info.nestedKinds[unwrapType(sf.Type).Kind()] = struct{}{} } } } + for _, p := range info.promoted { + if p.typ != nil { + info.nestedKinds[p.typ.Kind()] = struct{}{} + } + } + info.resolveKinds() + return info } -func equalFieldType(out any, kind reflect.Kind, key, aliasTag string) bool { - typ := reflect.TypeOf(out).Elem() - key = utilsstrings.ToLower(key) +// resolveKinds records what resolve answers for a key naming a single field, so +// that common lookup costs one map hit rather than a walk down the type. It asks +// resolve rather than reading the maps, keeping the precedence in one place; an +// unresolvable name is kept as reflect.Invalid, which a missing one is not. +func (info *fieldInfo) resolveKinds() { + info.kinds = make(map[string]reflect.Kind, len(info.fields)+len(info.embedded)+len(info.promoted)) + record := func(name string) { + if _, done := info.kinds[name]; done { + return + } + kind := reflect.Invalid + if t, ok := info.resolve(name, false); ok { + kind = t.Kind() + } + info.kinds[name] = kind + } + for name := range info.fields { + record(name) + } + for name := range info.embedded { + record(name) + } + for name := range info.promoted { + record(name) + } +} - if isStringKeyMap(typ) { - return true +// collectPromoted records the fields of an embedded struct, and of the structs +// it embeds, as promoted fields of the outer type. visited stops cycles, and is +// scoped to the path being walked: a type two sibling branches both embed has +// to be seen through each of them for the alias to come out ambiguous. +func (info *fieldInfo) collectPromoted(t reflect.Type, aliasTag string, depth int, visited map[reflect.Type]struct{}) { + if _, seen := visited[t]; seen { + return } + visited[t] = struct{}{} + defer delete(visited, t) - if typ.Kind() != reflect.Struct { - return false + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if !isExported(&f) { + continue + } + fieldType := unwrapType(f.Type) + name := fieldName(&f, aliasTag) + + if f.Anonymous && fieldType.Kind() == reflect.Struct { + info.collectPromoted(fieldType, aliasTag, depth+1, visited) + continue + } + + switch existing, ok := info.promoted[name]; { + case !ok || existing.depth > depth: + info.promoted[name] = promotedField{typ: fieldType, depth: depth} + case existing.depth == depth: + // Declared at the same depth by two embedded structs: ambiguous. + info.promoted[name] = promotedField{depth: depth} + } + } +} + +// typeID identifies a type by the address of its descriptor, which is stable +// and unique for the life of the program. It is the data word of the +// interface, read directly: reflect.ValueOf(t).Pointer() yields the same +// word at several times the cost, and this runs for every key of every +// bound request. +func typeID(t reflect.Type) uintptr { + return (*[2]uintptr)(unsafe.Pointer(&t))[1] //nolint:gosec // G103: reading the interface's data word, see above +} + +// slot returns the direct-mapped slot a type hashes to. +func (c *fieldCache) slot(t reflect.Type) *atomic.Pointer[fieldCacheEntry] { + return &c.slots[(typeID(t)>>4)&(fieldCacheSlots-1)] +} + +// get returns the field information of a struct type, building it on first use. +func (c *fieldCache) get(t reflect.Type, aliasTag string) (*fieldInfo, bool) { + id := typeID(t) + slot := &c.slots[(id>>4)&(fieldCacheSlots-1)] + if e := slot.Load(); e != nil && e.id == id { + return e.info, true } - cache := getFieldCache(aliasTag) - val, ok := cache.Load(typ) + val, ok := c.types.Load(t) if !ok { - info := buildFieldInfo(typ, aliasTag) - val, _ = cache.LoadOrStore(typ, info) + info := buildFieldInfo(t, aliasTag) + val, _ = c.types.LoadOrStore(t, &info) + } + + info, ok := val.(*fieldInfo) + if ok { + slot.Store(&fieldCacheEntry{id: id, info: info}) } + return info, ok +} + +// nextKeySegment returns the next segment of a key in dot, bracket or mixed +// notation ("a.b", "a[b]", "a[b].c") and the remainder; empty segments are skipped. +func nextKeySegment(key string) (segment, rest string, ok bool) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the three results for clarity + for key != "" { + i := 0 + for i < len(key) && key[i] != '.' && key[i] != '[' && key[i] != ']' { + i++ + } + segment, rest := key[:i], key[i:] + if rest != "" { + rest = rest[1:] + } + if segment != "" { + return segment, rest, true + } + key = rest + } + + return "", "", false +} - info, ok := val.(fieldInfo) +func isDigits(s string) bool { + if s == "" { + return false + } + for i := 0; i < len(s); i++ { + if s[i] < '0' || s[i] > '9' { + return false + } + } + return true +} + +// structKeyKind reports whether the field a key names in a struct type has the +// given kind. An unknown first segment falls back to the coarse nested-kind +// check. t is a struct type; equalFieldType has established that. +func structKeyKind(cache *fieldCache, t reflect.Type, kind reflect.Kind, key, aliasTag string) bool { + segment, rest, ok := nextKeySegment(key) if !ok { + return kind == reflect.Struct + } + // A key naming a field of this struct directly is the common case, and + // resolveKinds already answered it: no walk down the type, and no second + // pass over the key to find out there is nothing after this segment. + if rest == "" { + info, found := cache.get(t, aliasTag) + if !found { + return false + } + if k, resolved := info.kinds[segment]; resolved && k != reflect.Invalid { + return k == kind + } + _, ok := info.nestedKinds[kind] + return ok + } + // One segment of lookahead: whether a segment has more after it decides how + // an embedded struct's own alias resolves, and it ends the walk. The kind + // travels with the type, so each level asks it once. + cur, curKind := t, reflect.Struct + first := true + for { + nextSegment, nextRest, hasMore := nextKeySegment(rest) + + switch curKind { + case reflect.Struct: + info, found := cache.get(cur, aliasTag) + if !found { + return false + } + next, resolved := info.resolve(segment, hasMore) + if !resolved { + if first { + _, ok := info.nestedKinds[kind] + return ok + } + return false + } + cur = next + case reflect.Slice, reflect.Array: + // Elements are addressed by index before their fields. + if !isDigits(segment) { + return false + } + cur = unwrapType(cur.Elem()) + case reflect.Map: + cur = unwrapType(cur.Elem()) + default: + // A scalar has nothing below it. + return false + } + curKind = cur.Kind() + + if !hasMore { + break + } + segment, rest = nextSegment, nextRest + first = false + } + + return curKind == kind +} + +// resolve returns the type a key segment names within this struct: its own +// fields first, then an embedded struct's alias or a promoted field. +func (info *fieldInfo) resolve(segment string, hasMore bool) (reflect.Type, bool) { //nolint:revive // flag-parameter: hasMore is the position of the segment in the key, not a mode switch + if t, ok := info.fields[segment]; ok { + return t, true + } + if hasMore { + if t, ok := info.embedded[segment]; ok { + return t, true + } + } + if p, ok := info.promoted[segment]; ok { + if p.typ == nil { + // Ambiguous alias: treated as unresolved. + return nil, false + } + return p.typ, true + } + if t, ok := info.embedded[segment]; ok { + return t, true + } + + return nil, false +} + +// equalFieldType reports whether the value bound under key can hold the pieces +// of a split value: a slice field of a struct, or a slice-valued map. +func equalFieldType(out any, kind reflect.Kind, key, aliasTag string) bool { + if out == nil { return false } - if k, ok := info.names[key]; ok && k == kind { - return true + // The type answers everything here; a reflect.Value is only taken to tell + // a nil map from one the decoder can fill. + typ := reflect.TypeOf(out) + typKind := typ.Kind() + isPointer := typKind == reflect.Pointer + for typKind == reflect.Pointer { + typ = typ.Elem() + typKind = typ.Kind() } - if _, ok := info.nestedKinds[kind]; ok { - return true + + switch typKind { + case reflect.Map: + // Only a slice-valued map can hold more than one value per key. A nil + // map counts when a pointer to it was passed, since the decoder + // allocates it before filling it; a nil one by value stays unfillable. + if !isPointer && reflect.ValueOf(out).IsNil() { + return false + } + return typ.Key().Kind() == reflect.String && + typ.Elem().Kind() == reflect.Slice && kind == reflect.Slice + case reflect.Struct: + // A struct is decoded through a pointer; a plain value cannot be set. + if !isPointer { + return false + } + default: + return false } - return false + // Lower the key only once a struct lookup is needed. + return structKeyKind(getFieldCache(aliasTag), typ, kind, utilsstrings.ToLower(key), aliasTag) } // FilterFlags returns the media type value by trimming any parameters from a Content-Type header. func FilterFlags(content string) string { - if i := strings.IndexAny(content, " ;"); i >= 0 { + if i := utils.IndexAny2(content, ' ', ';'); i >= 0 { return content[:i] } return content } -func formatBindData[T, K any](aliasTag string, out any, data map[string][]T, key string, value K, enableSplitting, supportBracketNotation bool) error { //nolint:revive // it's okay - var err error +// bindKey returns key as the binders file it: rewritten from bracket notation +// to dots when the source supports that notation and key uses it. +func bindKey(key string, supportBracketNotation bool) (string, error) { //nolint:revive // the flag is the source's setting if supportBracketNotation && strings.IndexByte(key, '[') >= 0 { - key, err = parseParamSquareBrackets(key) - if err != nil { - return err - } + return parseParamSquareBrackets(key) } + return key, nil +} - switch v := any(value).(type) { - case string: - dataMap, ok := any(data).(map[string][]string) - if !ok { - return fmt.Errorf("unsupported value type: %T", value) - } +// bindFiles files a multipart form's headers under key, which is rewritten +// from bracket notation as a form's value keys are. +func bindFiles(files map[string][]*multipart.FileHeader, key string, headers []*multipart.FileHeader) error { + key, err := bindKey(key, true) + if err != nil { + return err + } + files[key] = append(files[key], headers...) + return nil +} - assignBindData(aliasTag, out, dataMap, key, v, enableSplitting) - case []string: - dataMap, ok := any(data).(map[string][]string) - if !ok { - return fmt.Errorf("unsupported value type: %T", value) - } +// bindData is what a string binder files the values it reads under, pooled +// so that filing a value costs no allocation of its own. What it keeps +// depends on the destination, see bindMode: a struct is decoded straight from +// the key/value pairs in the order read, a map[string]string gets the last +// value of each key, and any other map gets the source map parseToMap copies. +type bindData struct { + // values is the source map, for a map destination other than a + // map[string]string, and for a multipart form + values map[string][]string + // last is the last value filed under each key, for a map[string]string + // destination + last map[string]string + // keys and pairValues are the pairs, for a struct destination + keys, pairValues []string + mode bindMode +} - for _, val := range v { - assignBindData(aliasTag, out, dataMap, key, val, enableSplitting) - } - case []*multipart.FileHeader: - for _, val := range v { - valT, ok := any(val).(T) - if !ok { - return fmt.Errorf("unsupported value type: %T", value) - } - data[key] = append(data[key], valT) - } +// bindMode is how a bindData keeps what is filed in it. +type bindMode uint8 + +const ( + // bindPairs keeps key/value pairs for schema.Decoder.DecodeValues, which + // groups them itself: nothing has to build or hash a map. + bindPairs bindMode = iota + // bindMap keeps a map of the values filed under each key, appended as + // any slice is: a map of slices keeps those slices (see parseToMap). + bindMap + // bindLast keeps the last value filed under each key, which is all + // parseToMap puts in a map[string]string: its other values need no + // slice to be kept in. + bindLast +) + +// bindModeFor returns how a bind into out keeps its values. It dispatches as +// parse does: a map with string keys, or a pointer to one, gets a map, and +// everything else is decoded as a struct. +func bindModeFor(out any) bindMode { + switch out.(type) { + case *map[string][]string, map[string][]string: + return bindMap + case *map[string]string, map[string]string: + return bindLast + } + t := reflect.TypeOf(out) + if t == nil { + return bindPairs + } + if t.Kind() == reflect.Pointer { + t = t.Elem() + } + if t.Kind() != reflect.Map || t.Key().Kind() != reflect.String { + return bindPairs + } + return bindMap +} + +// parse decodes what was filed into out. +func (d *bindData) parse(aliasTag string, out any) error { + switch d.mode { + case bindPairs: + return parseValuesToStruct(aliasTag, out, d.keys, d.pairValues) + case bindLast: + return parseLast(aliasTag, out, d.last) default: - return fmt.Errorf("unsupported value type: %T", value) + return parse(aliasTag, out, d.values) + } +} + +// bind files value under key: a key in bracket notation is rewritten to dots +// first when supportBracketNotation is set, and a comma-separated value is +// split when splitting is on and the key names a slice. +func (d *bindData) bind(aliasTag string, out any, key, value string, enableSplitting, supportBracketNotation bool) error { //nolint:revive // the flags are the binder's settings + key, err := bindKey(key, supportBracketNotation) + if err != nil { + return err } + d.split(aliasTag, out, key, value, enableSplitting) + return nil +} - return err +// bindAll is bind for several values of one key, rewriting the key once. +func (d *bindData) bindAll(aliasTag string, out any, key string, values []string, enableSplitting, supportBracketNotation bool) error { //nolint:revive // the flags are the binder's settings + key, err := bindKey(key, supportBracketNotation) + if err != nil { + return err + } + for _, value := range values { + d.split(aliasTag, out, key, value, enableSplitting) + } + return nil } -func assignBindData(aliasTag string, out any, data map[string][]string, key, value string, enableSplitting bool) { //nolint:revive // it's okay +// split files value under key, split at its commas when splitting is on and +// the key names a slice of out's. +func (d *bindData) split(aliasTag string, out any, key, value string, enableSplitting bool) { //nolint:revive // the flag is the binder's setting if enableSplitting && strings.IndexByte(value, ',') >= 0 && equalFieldType(out, reflect.Slice, key, aliasTag) { for v := range strings.SplitSeq(value, ",") { - data[key] = append(data[key], v) + d.add(key, v) } - } else { - data[key] = append(data[key], value) + return + } + d.add(key, value) +} + +// add appends value to the values of key. +func (d *bindData) add(key, value string) { + switch d.mode { + case bindPairs: + d.keys = append(d.keys, key) + d.pairValues = append(d.pairValues, value) + case bindLast: + d.last[key] = value + default: + d.values[key] = append(d.values[key], value) } } diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/query.go b/src/vendor/github.com/gofiber/fiber/v3/binder/query.go index 2c30bb3b..71d69ece 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/query.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/query.go @@ -18,18 +18,18 @@ func (*QueryBinding) Name() string { // Bind parses the request query and returns the result. func (b *QueryBinding) Bind(reqCtx *fasthttp.Request, out any) error { args := reqCtx.URI().QueryArgs() - data := acquireDataMap() - defer releaseDataMap(data) + data := acquireBindData(out, args.Len()) + defer releaseBindData(data) for key, val := range args.All() { k := utils.UnsafeString(key) v := utils.UnsafeString(val) - if err := formatBindData(b.Name(), out, data, k, v, b.EnableSplitting, true); err != nil { + if err := data.bind(b.Name(), out, k, v, b.EnableSplitting, true); err != nil { return err } } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // Reset resets the QueryBinding binder. diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/resp_header.go b/src/vendor/github.com/gofiber/fiber/v3/binder/resp_header.go index ea9154e0..00f8f3af 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/resp_header.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/resp_header.go @@ -17,18 +17,18 @@ func (*RespHeaderBinding) Name() string { // Bind parses the response header and returns the result. func (b *RespHeaderBinding) Bind(resp *fasthttp.Response, out any) error { - data := acquireDataMap() - defer releaseDataMap(data) + data := acquireBindData(out, 0) + defer releaseBindData(data) for key, val := range resp.Header.All() { k := utils.UnsafeString(key) v := utils.UnsafeString(val) - if err := formatBindData(b.Name(), out, data, k, v, b.EnableSplitting, false); err != nil { + if err := data.bind(b.Name(), out, k, v, b.EnableSplitting, false); err != nil { return err } } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // Reset resets the RespHeaderBinding binder. diff --git a/src/vendor/github.com/gofiber/fiber/v3/binder/uri.go b/src/vendor/github.com/gofiber/fiber/v3/binder/uri.go index c986076e..324454f9 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/binder/uri.go +++ b/src/vendor/github.com/gofiber/fiber/v3/binder/uri.go @@ -10,12 +10,14 @@ func (*URIBinding) Name() string { // Bind parses the URI parameters and returns the result. func (b *URIBinding) Bind(params []string, paramsFunc func(key string, defaultValue ...string) string, out any) error { - data := make(map[string][]string, len(params)) + data := acquireBindData(out, len(params)) + defer releaseBindData(data) + for _, param := range params { - data[param] = append(data[param], paramsFunc(param)) + data.add(param, paramsFunc(param)) } - return parse(b.Name(), out, data) + return data.parse(b.Name(), out) } // Reset resets URIBinding binder. diff --git a/src/vendor/github.com/gofiber/fiber/v3/constants.go b/src/vendor/github.com/gofiber/fiber/v3/constants.go index bf0f512b..c3eb0fde 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/constants.go +++ b/src/vendor/github.com/gofiber/fiber/v3/constants.go @@ -1,5 +1,9 @@ package fiber +import ( + internalcookie "github.com/gofiber/fiber/v3/internal/cookie" +) + // HTTP methods were copied from net/http. const ( MethodGet = "GET" // RFC 7231, 4.3.1 @@ -312,10 +316,10 @@ const ( // Cookie SameSite // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7 const ( - CookieSameSiteDisabled = "disabled" // not in RFC, just control "SameSite" attribute will not be set. - CookieSameSiteLaxMode = "Lax" - CookieSameSiteStrictMode = "Strict" - CookieSameSiteNoneMode = "None" + CookieSameSiteDisabled = internalcookie.SameSiteDisabled // not in RFC, just control "SameSite" attribute will not be set. + CookieSameSiteLaxMode = internalcookie.SameSiteLax + CookieSameSiteStrictMode = internalcookie.SameSiteStrict + CookieSameSiteNoneMode = internalcookie.SameSiteNone ) // Route Constraints diff --git a/src/vendor/github.com/gofiber/fiber/v3/constraint.go b/src/vendor/github.com/gofiber/fiber/v3/constraint.go index bd326a6c..7cf69d63 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/constraint.go +++ b/src/vendor/github.com/gofiber/fiber/v3/constraint.go @@ -5,11 +5,14 @@ import ( "fmt" "reflect" "regexp" + "slices" "strconv" "strings" "time" "unicode" + "github.com/gofiber/utils/v2" + "github.com/gofiber/utils/v2/swar" "github.com/google/uuid" ) @@ -161,17 +164,42 @@ func findConstraintHandler(name string, regexHandler any, customs []CustomConstr return &customConstraintWrapper{CustomConstraint: cc} } } - if name == ConstraintRegex { + // A built-in name matches however the pattern spells it: the pattern is now + // adopted as written, where it used to arrive lowercased. Custom constraints + // keep the exact match above, so two customs differing only in case stay + // distinct and a custom cannot capture a built-in name in another case. + if utils.EqualFold(name, ConstraintRegex) { return regexConstraintType{regexHandler: regexHandler} } for _, bc := range builtinConstraints { - if bc.Name() == name { + if utils.EqualFold(bc.Name(), name) { return bc } } return nil } +// mergeCustomConstraints adds the constraints of a mounted app to the app its +// routes are being expanded into. +// +// Expanding a mount re-parses the sub-app's routes against the expanding app, +// so without this a constraint the sub-app registered stops resolving the +// moment its routes move up a level — findConstraintHandler returns nil and +// analyseParameterPart drops the constraint, leaving a route that silently +// validates nothing. A name the expanding app already defines keeps its own +// constraint, which is what its own routes were parsed with. +func mergeCustomConstraints(dst, src []CustomConstraint) []CustomConstraint { + for _, constraint := range src { + if slices.ContainsFunc(dst, func(existing CustomConstraint) bool { return existing.Name() == constraint.Name() }) { + continue + } + + dst = append(dst, constraint) + } + + return dst +} + // newConstraint creates a Constraint with the given handler and data, // calling Analyze() if the handler implements ConstraintAnalyzer. // rawName is the constraint name as it appeared in the route pattern (e.g. "minlen"). @@ -227,6 +255,10 @@ func (c *Constraint) matchConstraint(param string) bool { type intConstraintType struct{} func (intConstraintType) Name() string { return ConstraintInt } + +// The int-family constraints (int, min, max, range) deliberately stay on +// strconv.Atoi: utils.ParseNativeInt benchmarked slower for the short +// (1-14 digit) params routes actually see, winning only near 19 digits. func (intConstraintType) Execute(param string, _ []any) bool { _, err := strconv.Atoi(param) return err == nil @@ -244,7 +276,7 @@ type floatConstraintType struct{} func (floatConstraintType) Name() string { return ConstraintFloat } func (floatConstraintType) Execute(param string, _ []any) bool { - _, err := strconv.ParseFloat(param, 32) + _, err := strconv.ParseFloat(param, 64) return err == nil } @@ -252,8 +284,40 @@ type alphaConstraintType struct{} func (alphaConstraintType) Name() string { return ConstraintAlpha } func (alphaConstraintType) Execute(param string, _ []any) bool { - for _, c := range param { - if !unicode.IsLetter(c) { + // SWAR fast path for the ASCII-common case; the first word containing a + // non-ASCII byte defers the rest to the Unicode rune loop, and so does + // the sub-word tail. The handoff happens only where every preceding + // byte is ASCII, i.e. on a rune boundary. + n := len(param) + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + w := swar.Load8(param, i) + if w&swar.HighBits != 0 { + return isUnicodeAlpha(param[i:]) + } + if swar.MatchRangeMask(w, 'A', 'Z')|swar.MatchRangeMask(w, 'a', 'z') != swar.HighBits { + return false + } + } + // Scalar tail rather than isUnicodeAlpha(param[i:]): short params are + // the common case and skipping the rune decoding measures ~12% faster + // on Benchmark_ConstraintExecution/alpha. + for ; i < n; i++ { + c := param[i] + if c >= 0x80 { + return isUnicodeAlpha(param[i:]) + } + if lc := c | 0x20; lc < 'a' || lc > 'z' { + return false + } + } + return true +} + +// isUnicodeAlpha reports whether s consists only of Unicode letters. +func isUnicodeAlpha(s string) bool { + for _, r := range s { + if !unicode.IsLetter(r) { return false } } @@ -526,6 +590,8 @@ func (regexConstraintType) Execute(param string, data []any) bool { // resolveConstraintName handles case-insensitive and alias matching for constraint names. func resolveConstraintName(name string) string { + // strings.ToLower (not the ASCII-only utils variant) so aliases keep + // Unicode simple case folding, e.g. Turkish-locale "MİNLEN" -> "minlen". switch strings.ToLower(name) { case "minlen": return ConstraintMinLen diff --git a/src/vendor/github.com/gofiber/fiber/v3/ctx.go b/src/vendor/github.com/gofiber/fiber/v3/ctx.go index 551a9d40..2e3df4fd 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/ctx.go +++ b/src/vendor/github.com/gofiber/fiber/v3/ctx.go @@ -5,19 +5,19 @@ package fiber import ( + "bytes" "context" "crypto/tls" "fmt" "io" "maps" "mime/multipart" - "strings" + "net" "sync" "sync/atomic" "time" "github.com/gofiber/utils/v2" - utilsbytes "github.com/gofiber/utils/v2/bytes" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) @@ -72,29 +72,121 @@ type DefaultCtx struct { path []byte // HTTP path with the modifications by the configuration detectionPath []byte // Route detection path treePathHash int // Hash of the path for the search in the tree + pathSlashes int // Number of '/' in the detection path, used to quick-reject routes + pathPrint uint64 // Fingerprint of the detection path; 0 until the route scan hashes it indexRoute int // Index of the current route indexHandler int // Index of the current handler + firstMatchIndex int // Pre-resolved endpoint index from the SkipUnmatchedRoutes lookahead; -1 when unused methodInt int // HTTP method INT equivalent isAbandoned atomic.Bool // If true, ctx won't be pooled until ForceRelease is called isMatched bool // Non use route matched shouldSkipNonUseRoutes bool // Skip non-use routes while iterating middleware isUserContextSet bool // User context was stored in fasthttp user values + pathNeedsNorm bool // pathOriginal holds an escape or a dot segment; set wherever pathOriginal is } // TLSHandler hosts the callback hooks Fiber invokes while negotiating TLS // connections, including optional client certificate lookups. +// +// It records the ClientHelloInfo of every connection, keyed by the connection, +// and releases it when the server reports the connection closed. type TLSHandler struct { - clientHelloInfo *tls.ClientHelloInfo + connless atomic.Pointer[tls.ClientHelloInfo] + clientHelloInfos sync.Map // underlying net.Conn -> *tls.ClientHelloInfo + serverConns sync.Map // server-visible net.Conn -> underlying net.Conn } // GetClientInfo Callback function to set ClientHelloInfo // Must comply with the method structure of https://cs.opensource.google/go/go/+/refs/tags/go1.20:src/crypto/tls/common.go;l=554-563 // Since we overlay the method of the TLS config in the listener method func (t *TLSHandler) GetClientInfo(info *tls.ClientHelloInfo) (*tls.Certificate, error) { - t.clientHelloInfo = info + switch { + case info == nil: + case info.Conn != nil: + t.clientHelloInfos.Store(info.Conn, info) + default: + t.connless.Store(info) + } return nil, nil //nolint:nilnil // Not returning anything useful here is probably fine } +// clientHelloInfo returns the ClientHelloInfo recorded for a connection, or nil. +func (t *TLSHandler) clientHelloInfo(conn net.Conn) *tls.ClientHelloInfo { + if key := underlyingConn(conn); key != nil { + if v, ok := t.clientHelloInfos.Load(key); ok { + if info, ok := v.(*tls.ClientHelloInfo); ok { + return info + } + } + } + return t.connless.Load() +} + +// track notes what a server-visible connection wraps while that connection is +// still open, so its record can be found again once it is not. A *tls.Conn +// needs no note: it answers for what it wraps at any time. The wrapper fasthttp +// installs for Server.MaxConnsPerIP does not — it is closed and returned to a +// pool before the close is reported, and clears the connection it embeds on the +// way, so asking it then dereferences a nil *tls.Conn. +func (t *TLSHandler) track(conn net.Conn) { + if conn == nil { + return + } + if _, ok := conn.(*tls.Conn); ok { + return + } + key := underlyingConn(conn) + if key == nil || key == conn { + return + } + + // Reaching a wrapper that still holds a note means it was recycled before + // the close of the connection it carried was reported. That connection is + // closed — only Close returns a wrapper to the pool — so drop the record it + // would otherwise strand. + if prev, loaded := t.serverConns.Swap(conn, key); loaded { + if stale, ok := prev.(net.Conn); ok && stale != key { + t.clientHelloInfos.Delete(stale) + } + } +} + +// forget drops the record kept for a closed connection, resolving it through +// the note track left when the connection could still be asked what it wrapped. +func (t *TLSHandler) forget(conn net.Conn) { + if conn == nil { + return + } + + if noted, ok := t.serverConns.LoadAndDelete(conn); ok { + if key, ok := noted.(net.Conn); ok { + t.clientHelloInfos.Delete(key) + } + return + } + + key := conn + if tc, ok := conn.(*tls.Conn); ok { + key = tc.NetConn() + } + if key != nil { + t.clientHelloInfos.Delete(key) + } +} + +// underlyingConn returns the net.Conn a TLS handshake ran on; crypto/tls hands +// GetCertificate the raw connection, while the server sees the *tls.Conn — or a +// wrapper around one, as fasthttp installs for Server.MaxConnsPerIP accounting. +// Matching the method rather than the concrete type unwraps both, so the two +// sides key on the same connection. Only call this for a connection still in +// use; see track for why a closed one cannot be unwrapped this way. +func underlyingConn(conn net.Conn) net.Conn { + if tc, ok := conn.(interface{ NetConn() net.Conn }); ok { + return tc.NetConn() + } + return conn +} + // Views is the interface that wraps the Render function. type Views interface { Load() error @@ -153,31 +245,25 @@ func (c *DefaultCtx) SetContext(ctx context.Context) { } // Deadline returns the time when work done on behalf of this context -// should be canceled. Deadline returns ok==false when no deadline is -// set. Successive calls to Deadline return the same results. +// should be canceled. Ctx carries no deadline, so ok is always false. // -// Due to current limitations in how fasthttp works, Deadline operates as a nop. -// See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 +// Ctx satisfies context.Context as a context that can never be canceled: it is +// pooled and reused, so it cannot honor the stability and concurrency the +// interface requires. Pass Context() to anything that is cancellation-aware or +// that outlives the handler. func (*DefaultCtx) Deadline() (time.Time, bool) { return time.Time{}, false } // Done returns a channel that's closed when work done on behalf of this -// context should be canceled. Done may return nil if this context can -// never be canceled. Successive calls to Done return the same value. -// The close of the Done channel may happen asynchronously, -// after the cancel function returns. -// -// Due to current limitations in how fasthttp works, Done operates as a nop. -// See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 +// context should be canceled. Ctx can never be canceled, so Done always +// returns nil, which context.Context explicitly permits. See Deadline. func (*DefaultCtx) Done() <-chan struct{} { return nil } -// Err mirrors context.Err, returning nil until cancellation and then the terminal error value. -// -// Due to current limitations in how fasthttp works, Err operates as a nop. -// See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 +// Err returns nil until the Done channel is closed. Done is always nil here, +// so Err always returns nil. See Deadline. func (*DefaultCtx) Err() error { return nil } @@ -204,6 +290,34 @@ func (c *DefaultCtx) Response() *fasthttp.Response { return &c.fasthttp.Response } +// Body returns the request body, decompressing it when the request declares a +// Content-Encoding the app accepts. Req and Res both carry a Body, so on Ctx +// the request wins, as it does for Get; use Res().Body() for the response. +func (c *DefaultCtx) Body() []byte { + return c.DefaultReq.Body() +} + +// ContentLength returns the value of the Content-Length request header. Req and +// Res both carry one, so on Ctx the request wins, as it does for Get; use +// Res().ContentLength() for the response. +func (c *DefaultCtx) ContentLength() int { + return c.DefaultReq.ContentLength() +} + +// ContentType returns the Content-Type request header, parameters included. Req +// and Res both carry one, so on Ctx the request wins, as it does for Get; use +// Res().ContentType() for the response. +func (c *DefaultCtx) ContentType() string { + return c.DefaultReq.ContentType() +} + +// Cookies returns the request cookie with the given key, or defaultValue. Only +// valid within the handler unless Immutable is set. For the cookies the response +// is set to send, use Res().GetCookies(). +func (c *DefaultCtx) Cookies(key string, defaultValue ...string) string { + return c.DefaultReq.Cookies(key, defaultValue...) +} + // Get returns the HTTP request header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. @@ -241,10 +355,10 @@ func (c *DefaultCtx) GetRespHeaders() map[string][]string { return c.DefaultRes.GetHeaders() } -// ClientHelloInfo return CHI from context +// ClientHelloInfo returns the TLS ClientHelloInfo of the connection this request arrived on, or nil. func (c *DefaultCtx) ClientHelloInfo() *tls.ClientHelloInfo { - if c.app.tlsHandler != nil { - return c.app.tlsHandler.clientHelloInfo + if c.app.tlsHandler != nil && c.fasthttp != nil { + return c.app.tlsHandler.clientHelloInfo(c.fasthttp.Conn()) } return nil @@ -275,6 +389,8 @@ func (c *DefaultCtx) Next() error { // changing the request path. Note that handlers might be executed again. func (c *DefaultCtx) RestartRouting() error { c.indexRoute = -1 + // Path may have changed; invalidate the lookahead index + c.firstMatchIndex = -1 if c.handlerCtx != nil { _, err := c.app.nextCustom(c.handlerCtx) return err @@ -283,6 +399,15 @@ func (c *DefaultCtx) RestartRouting() error { return err } +// ctxForHandlers returns the context user code is handed: the custom context +// when the app uses one, otherwise the DefaultCtx itself, as Next does. +func (c *DefaultCtx) ctxForHandlers() Ctx { + if c.handlerCtx != nil { + return c.handlerCtx + } + return c +} + func (c *DefaultCtx) setHandlerCtx(ctx CustomCtx) { if ctx == nil { c.handlerCtx = nil @@ -302,22 +427,6 @@ func (c *DefaultCtx) OriginalURL() string { return c.app.toString(c.fasthttp.Request.Header.RequestURI()) } -// Path returns the path part of the request URL. -// Optionally, you could override the path. -// Make copies or use the Immutable setting to use the value outside the Handler. -func (c *DefaultCtx) Path(override ...string) string { - if len(override) != 0 && string(c.path) != override[0] { - // Set new path to context - c.pathOriginal = override[0] - - // Set new path to request context - c.fasthttp.Request.URI().SetPath(c.pathOriginal) - // Prettify path - c.configDependentPaths() - } - return c.app.toString(c.path) -} - // RequestID returns the request identifier from the response header or request header. func (c *DefaultCtx) RequestID() string { if requestID := c.GetRespHeader(HeaderXRequestID); requestID != "" { @@ -365,24 +474,125 @@ func (c *DefaultCtx) ViewBind(vars Map) error { // Route returns the matched Route struct. func (c *DefaultCtx) Route() *Route { if c.route == nil { - // Fallback for fasthttp error handler; equals c.Method() without - // the variadic call so Route stays within the inlining budget - return &Route{ - path: c.pathOriginal, - Path: c.pathOriginal, - Method: c.app.method(c.methodInt), - Handlers: emptyRouteHandlers[:], - Params: emptyRouteParams[:], - } + // Cold path kept out of line so Route stays within the inlining budget. + return c.routeFallback() } return c.route } +// routeFallback builds the synthetic route for the fasthttp error handler. +// Its Method field is resolved like c.Method() (including the raw-header +// fallback for unregistered methods) so Route and Method always agree. +// Never inlined: inlining it would push Route over the inlining budget. +// +//go:noinline +func (c *DefaultCtx) routeFallback() *Route { + return &Route{ + path: c.pathOriginal, + Path: c.pathOriginal, + Method: currentMethod(c), + Handlers: emptyRouteHandlers[:], + Params: emptyRouteParams[:], + } +} + +// Endpoint returns the route that will handle this request, without advancing the +// handler chain, so global middleware can read its Path or Name before calling +// Next. Returns nil when no endpoint will run: 404, 405, and while the error +// handler replays the chain for a request rejected at the protocol level. +// +// It looks ahead, where the neighboring accessors look back: Route reports the +// route currently executing, which inside middleware is the middleware itself, +// and Matched reports whether an endpoint has been selected yet. +// +// It scans the remaining routes in the request's tree bucket, so calling it from +// global middleware costs a second router scan per request. +func (c *DefaultCtx) Endpoint() *Route { + // Already on a non-middleware endpoint. + if c.route != nil && !c.route.use && !c.route.mount { + return c.route + } + if c.methodInt == -1 || c.app == nil { + return nil + } + // serverErrorHandler replays the chain with this set, and next() then lets no + // endpoint run, so naming one here would promise a handler that cannot run. + if c.shouldSkipNonUseRoutes { + return nil + } + + tree, _ := c.app.treeIndex[c.methodInt].lookup(c.treePathHash) + detectionPath := utils.UnsafeString(c.detectionPath) + path := utils.UnsafeString(c.path) + head := pathHeadWord(detectionPath) + pathSlashes := c.pathSlashCount(c.app) + + // SkipUnmatchedRoutes already resolved the endpoint, but the index only answers + // while routing has not walked past it, and a route registered mid-request can + // shift the bucket under it, so it still has to clear the prefix filter. + if c.firstMatchIndex > c.indexRoute && c.firstMatchIndex < len(tree) { + if route := tree[c.firstMatchIndex]; route != nil && !route.use && !route.mount && + !route.prefixRejects(head) { + return route + } + } + + // Use a scratch params buffer so look-ahead does not clobber c.values. + var scratch [maxParams]string + + // Starting past indexRoute follows the chain, which is why the result needs no + // cache: every mutation that would invalidate one already moves a field read here. + for i := c.indexRoute + 1; i < len(tree); i++ { + route := tree[i] + if route.mount || route.use { + continue + } + if route.prefixRejects(head) { + continue + } + if route.match(detectionPath, path, &scratch, pathSlashes) { + return route + } + } + + return nil +} + // FullPath returns the matched route path, including any group prefixes. func (c *DefaultCtx) FullPath() string { return c.Route().Path } +// RouteName returns the name of the route currently executing, or "" when it is +// unnamed. Inside middleware that is the middleware's own route; use +// Endpoint().Name to look ahead to the one that will handle the request. +func (c *DefaultCtx) RouteName() string { + // Route() builds a synthetic Route when none matched, and that one never + // carries a Name — so the allocation could only ever produce "". + if c.route == nil { + return "" + } + return c.route.Name +} + +// MountPath returns the prefix the sub-app owning the current route was mounted +// under, or "" for a top-level route. Path is not relative to it. One *App +// mounted twice reports its last prefix, as App.MountPath does. +func (c *DefaultCtx) MountPath() string { + if c.app == nil { + return "" + } + // A route with no recorded owner is this app's own, so it is not under a + // mount at all — reading the app's own prefix here would answer with a + // mount the request never went through. + owner := c.app.routeOwner(c.route) + if owner == nil { + return "" + } + + return owner.MountPath() +} + // Matched returns true if the current request path was matched by the router. func (c *DefaultCtx) Matched() bool { return c.getMatched() @@ -400,23 +610,11 @@ func (c *DefaultCtx) IsMiddleware() bool { return c.indexHandler+1 < len(c.route.Handlers) } -// HasBody returns true if the request declares a body via Content-Length, Transfer-Encoding, or already buffered payload data. -func (c *DefaultCtx) HasBody() bool { - hdr := &c.fasthttp.Request.Header - - switch cl := hdr.ContentLength(); { - case cl > 0: - return true - case cl == -1: - // fasthttp reports -1 for Transfer-Encoding: chunked bodies. - return true - case cl == 0: - if hasTransferEncodingBody(hdr) { - return true - } - } - - return len(c.fasthttp.Request.Body()) > 0 +// IsFinal reports whether this is the last handler of a matched non-middleware +// route, so nothing further on that route runs. It describes the route, not the +// request: another route can still match, and a Use route is never final. +func (c *DefaultCtx) IsFinal() bool { + return c.route != nil && !c.IsMiddleware() } // OverrideParam overwrites a route parameter value by name. @@ -452,75 +650,6 @@ func (c *DefaultCtx) OverrideParam(name, value string) { } } -func hasTransferEncodingBody(hdr *fasthttp.RequestHeader) bool { - teBytes := hdr.Peek(HeaderTransferEncoding) - var te string - - if len(teBytes) > 0 { - te = utils.UnsafeString(teBytes) - } else { - for key, value := range hdr.All() { - if !utils.EqualFold(utils.UnsafeString(key), HeaderTransferEncoding) { - continue - } - te = utils.UnsafeString(value) - break - } - } - - if te == "" { - return false - } - - hasEncoding := false - for raw := range strings.SplitSeq(te, ",") { - token := utils.TrimSpace(raw) - if token == "" { - continue - } - if idx := strings.IndexByte(token, ';'); idx >= 0 { - token = utils.TrimSpace(token[:idx]) - } - if token == "" { - continue - } - if utils.EqualFold(token, "identity") { - continue - } - hasEncoding = true - } - - return hasEncoding -} - -// IsWebSocket returns true if the request includes a WebSocket upgrade handshake. -func (c *DefaultCtx) IsWebSocket() bool { - conn := c.fasthttp.Request.Header.Peek(HeaderConnection) - var isUpgrade bool - for v := range strings.SplitSeq(utils.UnsafeString(conn), ",") { - if utils.EqualFold(utils.TrimSpace(v), "upgrade") { - isUpgrade = true - break - } - } - if !isUpgrade { - return false - } - return utils.EqualFold(c.fasthttp.Request.Header.Peek(HeaderUpgrade), websocketBytes) -} - -// IsPreflight returns true if the request is a CORS preflight. -func (c *DefaultCtx) IsPreflight() bool { - if c.Method() != MethodOptions { - return false - } - hdr := &c.fasthttp.Request.Header - if len(hdr.Peek(HeaderAccessControlRequestMethod)) == 0 { - return false - } - return len(hdr.Peek(HeaderOrigin)) > 0 -} - // SaveFile saves any multipart file to disk. func (*DefaultCtx) SaveFile(fileheader *multipart.FileHeader, path string) error { if fileheader == nil { @@ -571,18 +700,69 @@ func (c *DefaultCtx) SaveFileToStorage(fileheader *multipart.FileHeader, path st return nil } -// Secure returns whether a secure connection was established. -func (c *DefaultCtx) Secure() bool { - return c.Scheme() == schemeHTTPS +// Error returns an *Error carrying the given status code, defaulting the message +// to the status text. Returning it hands it to the app's ErrorHandler, which +// writes the response; Error itself sets nothing. +func (*DefaultCtx) Error(status int, message ...string) error { + return NewError(status, message...) } // Status sets the HTTP status for the response. // This method is chainable. +// +// A status outside 100 to 999 is logged and replaced by 500. func (c *DefaultCtx) Status(status int) Ctx { - c.fasthttp.Response.SetStatusCode(status) + c.fasthttp.Response.SetStatusCode(validStatus(status)) return c } +// ID returns the connection-unique identifier fasthttp assigned to this request, +// unlike RequestID, which reads a header. It is not unique across processes or +// restarts, so use it to correlate log lines within one server run. +func (c *DefaultCtx) ID() uint64 { + return c.fasthttp.ID() +} + +// StartTime returns the time the server began handling this request. It is the +// reference point Elapsed measures from. +func (c *DefaultCtx) StartTime() time.Time { + return c.fasthttp.Time() +} + +// Elapsed returns how long this request has been handled so far, measured from +// StartTime. Called after the handler chain has run, it is the request latency. +func (c *DefaultCtx) Elapsed() time.Duration { + return time.Since(c.fasthttp.Time()) +} + +// LocalAddr returns the server-side address of the connection this request +// arrived on. IP returns the client address as a string; this is the full +// net.Addr, so the port, network, and unix socket path survive. +func (c *DefaultCtx) LocalAddr() net.Addr { + return c.fasthttp.LocalAddr() +} + +// RemoteAddr returns the address of the immediate peer, which is the proxy +// rather than the client when the app sits behind one. Use IP or IPs for the +// client address a trusted proxy forwarded. +func (c *DefaultCtx) RemoteAddr() net.Addr { + return c.fasthttp.RemoteAddr() +} + +// Hijack registers a handler that takes over the connection once the response is +// sent, for protocols Fiber does not speak. The connection then closes unless +// KeepHijackedConns is set, and the handler must not touch the pooled Ctx. +func (c *DefaultCtx) Hijack(handler fasthttp.HijackHandler) { + c.fasthttp.Hijack(handler) +} + +// Hijacked returns true if Hijack has been called on this request, so a later +// handler can tell that the connection is already spoken for and leave the +// response alone. +func (c *DefaultCtx) Hijacked() bool { + return c.fasthttp.Hijacked() +} + // String returns unique string representation of the ctx. // // The returned value may be useful for logging. @@ -633,38 +813,44 @@ func (c *DefaultCtx) Value(key any) any { return c.fasthttp.UserValue(key) } -var ( - // xmlHTTPRequestBytes is precomputed for XHR detection - xmlHTTPRequestBytes = []byte("xmlhttprequest") - // websocketBytes is precomputed for WebSocket upgrade detection - websocketBytes = []byte("websocket") -) - -// XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, -// indicating that the request was issued by a client library (such as jQuery). -func (c *DefaultCtx) XHR() bool { - return utils.EqualFold(c.fasthttp.Request.Header.Peek(HeaderXRequestedWith), xmlHTTPRequestBytes) -} - // configDependentPaths set paths for route recognition and prepared paths for the user, // here the features for caseSensitive, decoded paths, strict paths are evaluated func (c *DefaultCtx) configDependentPaths() { - c.path = append(c.path[:0], c.pathOriginal...) - // If UnescapePath enabled, we decode the path and save it for the framework user - if c.app.config.UnescapePath { - c.path = fasthttp.AppendUnquotedArg(c.path[:0], c.path) - } - - // another path is specified which is for routing recognition only - // use the path that was changed by the previous configuration flags - // If CaseSensitive is disabled, we lowercase the original path - c.detectionPath = append(c.detectionPath[:0], c.path...) - if !c.app.config.CaseSensitive { - utilsbytes.UnsafeToLower(c.detectionPath) + // Routing starts from fasthttp's PathOriginal, not its decoded, normalized + // Path. normalizeRequestPath owns request-path decoding according to + // UnescapePath; route-pattern preprocessing must not decode it again. + // The path is normalized as RFC 3986 Section 6.2.2 describes before any + // route sees it (see normalizeRequestPath). The detection path is what a + // route is matched against: the case fold of the path unless CaseSensitive + // is set. Most requests need no normalization, and under the default + // configuration both are then written in a single pass over the original, + // which counts the detection path's slashes on the way. Elsewhere the + // count stays 0, which pathSlashCount takes as not computed yet. + slashes, counted := 0, false + switch { + case c.pathNeedsNorm: + c.path = append(c.path[:0], c.pathOriginal...) + c.path = normalizeRequestPath(c.path, c.app.config.UnescapePath) + if c.app.config.CaseSensitive { + c.detectionPath = append(c.detectionPath[:0], c.path...) + } else { + c.detectionPath = appendLowerASCII(c.detectionPath[:0], c.path) + } + case !c.app.config.CaseSensitive: + c.path, c.detectionPath, slashes = appendCopyLowerASCII(c.path, c.detectionPath, c.pathOriginal) + counted = true + default: + c.path = append(c.path[:0], c.pathOriginal...) + c.detectionPath = append(c.detectionPath[:0], c.path...) } // If StrictRouting is disabled, we strip all trailing slashes if !c.app.config.StrictRouting && len(c.detectionPath) > 1 && c.detectionPath[len(c.detectionPath)-1] == '/' { + n := len(c.detectionPath) c.detectionPath = utils.TrimRight(c.detectionPath, '/') + if counted { + // every byte trimmed was a '/' the count included + slashes -= n - len(c.detectionPath) + } } // Define the path for dividing routes into areas for fast tree detection, so that fewer routes need to be traversed, @@ -675,6 +861,37 @@ func (c *DefaultCtx) configDependentPaths() { int(c.detectionPath[1])<<8 | int(c.detectionPath[2]) } + + // The slash count of the detection path, or 0 when it was not counted + // above, in which case pathSlashCount counts it when route matching first + // needs it. + c.pathSlashes = slashes + c.pathPrint = 0 +} + +// pathNeedsNormalization reports whether normalizeRequestPath could change +// path, given the length of the path fasthttp normalized when it parsed the +// request. Parsing decoded the escapes and removed the dot and empty segments, +// and each of those shortens the path, so one that kept its length holds no +// escape and no dot segment, apart from a trailing "/." that fasthttp leaves +// in place. A stray "%" that begins no escape keeps the length too, since +// fasthttp copies it as sent, and such a path is matched as sent, which is +// also what normalizeRequestPath makes of it: that writes a stray "%" as "%25" +// only where an escape decoded after it would complete a new escape with it, +// and a decoded escape changes the length. +// +// A path without a leading slash, the authority form fasthttp admits for +// CONNECT, is normalized whatever its length: the slash fasthttp adds in +// front of its copy is canceled by the one it takes out of a doubled slash, +// so "admin//secret" keeps its length while holding both. +// +// It takes that length rather than the URI so that it stays inlinable in the +// request hot path. A caller that switched DisablePathNormalizing on has asked +// for the path to be treated as sent, so it does not trust the parsed copy and +// scans the original with needsPathNormalization instead. +func pathNeedsNormalization(normalizedLen int, path string) bool { + n := len(path) + return normalizedLen != n || n == 0 || path[0] != '/' || (n >= 2 && path[n-2] == '/' && path[n-1] == '.') } // Reset is a method to reset context fields by given request when to use server handlers. @@ -685,8 +902,16 @@ func (c *DefaultCtx) Reset(fctx *fasthttp.RequestCtx) { // Reset matched flag c.isMatched = false c.shouldSkipNonUseRoutes = false + c.firstMatchIndex = -1 + c.route = nil // Set paths - c.pathOriginal = c.app.toString(fctx.URI().PathOriginal()) + uri := fctx.URI() + c.pathOriginal = c.app.toString(uri.PathOriginal()) + if uri.DisablePathNormalizing { + c.pathNeedsNorm = needsPathNormalization(c.pathOriginal) + } else { + c.pathNeedsNorm = pathNeedsNormalization(len(uri.Path()), c.pathOriginal) + } // Set method c.methodInt = c.app.methodInt(utils.UnsafeString(fctx.Request.Header.Method())) // Attach *fasthttp.RequestCtx to ctx @@ -714,6 +939,10 @@ func (c *DefaultCtx) release() { ReleaseBind(c.bind) c.bind = nil } + // Zero the whole backing array before pooling: what lives here is the previous + // request's flash data, which for WithInput is its entire form. + // parseAndClearFlashMessages clears too, since UnmarshalMsg re-slices this. + clear(c.flashMessages[:cap(c.flashMessages)]) c.flashMessages = c.flashMessages[:0] // Clear viewBindMap by deleting all keys (reuse underlying map if possible) if c.viewBindMap != nil { @@ -842,7 +1071,7 @@ func (c *DefaultCtx) Bind() *Bind { if c.bind == nil { c.bind = AcquireBind() } - c.bind.ctx = c + c.bind.ctx = c.ctxForHandlers() return c.bind } @@ -859,6 +1088,20 @@ func (c *DefaultCtx) getTreePathHash() int { return c.treePathHash } +// pathSlashCount lazily counts the '/' bytes of the detection path and caches +// the result for the request; matching uses it to reject route candidates +// without walking their segments. app is the serving App, which can differ +// from c.app when an App value was copied. When it registers no route that +// consults the count, counting is skipped and 0 is returned — a real detection +// path always contains a '/', so 0 doubles as the "unknown" state that makes +// Route.match skip the quick-reject entirely. +func (c *DefaultCtx) pathSlashCount(app *App) int { + if c.pathSlashes == 0 && app.hasParamRoutes { + c.pathSlashes = bytes.Count(c.detectionPath, slashDelimiterBytes) + } + return c.pathSlashes +} + func (c *DefaultCtx) getDetectionPath() string { return c.app.toString(c.detectionPath) } @@ -875,6 +1118,10 @@ func (c *DefaultCtx) getSkipNonUseRoutes() bool { return c.shouldSkipNonUseRoutes } +func (c *DefaultCtx) getFirstMatchIndex() int { + return c.firstMatchIndex +} + func (c *DefaultCtx) setIndexHandler(handler int) { c.indexHandler = handler } @@ -891,6 +1138,10 @@ func (c *DefaultCtx) setSkipNonUseRoutes(skip bool) { c.shouldSkipNonUseRoutes = skip } +func (c *DefaultCtx) setFirstMatchIndex(index int) { + c.firstMatchIndex = index +} + func (c *DefaultCtx) setRoute(route *Route) { c.route = route } diff --git a/src/vendor/github.com/gofiber/fiber/v3/ctx_interface.go b/src/vendor/github.com/gofiber/fiber/v3/ctx_interface.go index 5f2f4e65..b812c8fc 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/ctx_interface.go +++ b/src/vendor/github.com/gofiber/fiber/v3/ctx_interface.go @@ -36,15 +36,18 @@ type CustomCtx interface { getMethodInt() int getIndexRoute() int getTreePathHash() int + pathSlashCount(app *App) int getDetectionPath() string getPathOriginal() string getValues() *[maxParams]string getMatched() bool getSkipNonUseRoutes() bool + getFirstMatchIndex() int setIndexHandler(handler int) setIndexRoute(route int) setMatched(matched bool) setSkipNonUseRoutes(skip bool) + setFirstMatchIndex(index int) setRoute(route *Route) } diff --git a/src/vendor/github.com/gofiber/fiber/v3/ctx_interface_gen.go b/src/vendor/github.com/gofiber/fiber/v3/ctx_interface_gen.go index 694a0efd..b9f45c4e 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/ctx_interface_gen.go +++ b/src/vendor/github.com/gofiber/fiber/v3/ctx_interface_gen.go @@ -8,6 +8,7 @@ import ( "crypto/tls" "io" "mime/multipart" + "net" "time" "github.com/valyala/fasthttp" @@ -29,25 +30,19 @@ type Ctx interface { // SetContext sets a context implementation by user. SetContext(ctx context.Context) // Deadline returns the time when work done on behalf of this context - // should be canceled. Deadline returns ok==false when no deadline is - // set. Successive calls to Deadline return the same results. + // should be canceled. Ctx carries no deadline, so ok is always false. // - // Due to current limitations in how fasthttp works, Deadline operates as a nop. - // See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 + // Ctx satisfies context.Context as a context that can never be canceled: it is + // pooled and reused, so it cannot honor the stability and concurrency the + // interface requires. Pass Context() to anything that is cancellation-aware or + // that outlives the handler. Deadline() (time.Time, bool) // Done returns a channel that's closed when work done on behalf of this - // context should be canceled. Done may return nil if this context can - // never be canceled. Successive calls to Done return the same value. - // The close of the Done channel may happen asynchronously, - // after the cancel function returns. - // - // Due to current limitations in how fasthttp works, Done operates as a nop. - // See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 + // context should be canceled. Ctx can never be canceled, so Done always + // returns nil, which context.Context explicitly permits. See Deadline. Done() <-chan struct{} - // Err mirrors context.Err, returning nil until cancellation and then the terminal error value. - // - // Due to current limitations in how fasthttp works, Err operates as a nop. - // See: https://github.com/valyala/fasthttp/issues/965#issuecomment-777268945 + // Err returns nil until the Done channel is closed. Done is always nil here, + // so Err always returns nil. See Deadline. Err() error // Request return the *fasthttp.Request object // This allows you to use all fasthttp request methods @@ -59,6 +54,22 @@ type Ctx interface { // https://godoc.org/github.com/valyala/fasthttp#Response // Returns nil if the context has been released. Response() *fasthttp.Response + // Body returns the request body, decompressing it when the request declares a + // Content-Encoding the app accepts. Req and Res both carry a Body, so on Ctx + // the request wins, as it does for Get; use Res().Body() for the response. + Body() []byte + // ContentLength returns the value of the Content-Length request header. Req and + // Res both carry one, so on Ctx the request wins, as it does for Get; use + // Res().ContentLength() for the response. + ContentLength() int + // ContentType returns the Content-Type request header, parameters included. Req + // and Res both carry one, so on Ctx the request wins, as it does for Get; use + // Res().ContentType() for the response. + ContentType() string + // Cookies returns the request cookie with the given key, or defaultValue. Only + // valid within the handler unless Immutable is set. For the cookies the response + // is set to send, use Res().GetCookies(). + Cookies(key string, defaultValue ...string) string // Get returns the HTTP request header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. @@ -81,22 +92,21 @@ type Ctx interface { // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting instead. GetRespHeaders() map[string][]string - // ClientHelloInfo return CHI from context + // ClientHelloInfo returns the TLS ClientHelloInfo of the connection this request arrived on, or nil. ClientHelloInfo() *tls.ClientHelloInfo // Next executes the next method in the stack that matches the current route. Next() error // RestartRouting instead of going to the next handler. This may be useful after // changing the request path. Note that handlers might be executed again. RestartRouting() error + // ctxForHandlers returns the context user code is handed: the custom context + // when the app uses one, otherwise the DefaultCtx itself, as Next does. + ctxForHandlers() Ctx setHandlerCtx(ctx CustomCtx) // OriginalURL contains the original request URL. // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting to use the value outside the Handler. OriginalURL() string - // Path returns the path part of the request URL. - // Optionally, you could override the path. - // Make copies or use the Immutable setting to use the value outside the Handler. - Path(override ...string) string // RequestID returns the request identifier from the response header or request header. RequestID() string // Req returns a convenience type whose API is limited to operations @@ -115,30 +125,83 @@ type Ctx interface { ViewBind(vars Map) error // Route returns the matched Route struct. Route() *Route + // routeFallback builds the synthetic route for the fasthttp error handler. + // Its Method field is resolved like c.Method() (including the raw-header + // fallback for unregistered methods) so Route and Method always agree. + // Never inlined: inlining it would push Route over the inlining budget. + routeFallback() *Route + // Endpoint returns the route that will handle this request, without advancing the + // handler chain, so global middleware can read its Path or Name before calling + // Next. Returns nil when no endpoint will run: 404, 405, and while the error + // handler replays the chain for a request rejected at the protocol level. + // + // It looks ahead, where the neighboring accessors look back: Route reports the + // route currently executing, which inside middleware is the middleware itself, + // and Matched reports whether an endpoint has been selected yet. + // + // It scans the remaining routes in the request's tree bucket, so calling it from + // global middleware costs a second router scan per request. + Endpoint() *Route // FullPath returns the matched route path, including any group prefixes. FullPath() string + // RouteName returns the name of the route currently executing, or "" when it is + // unnamed. Inside middleware that is the middleware's own route; use + // Endpoint().Name to look ahead to the one that will handle the request. + RouteName() string + // MountPath returns the prefix the sub-app owning the current route was mounted + // under, or "" for a top-level route. Path is not relative to it. One *App + // mounted twice reports its last prefix, as App.MountPath does. + MountPath() string // Matched returns true if the current request path was matched by the router. Matched() bool // IsMiddleware returns true if the current request handler was registered as middleware. IsMiddleware() bool - // HasBody returns true if the request declares a body via Content-Length, Transfer-Encoding, or already buffered payload data. - HasBody() bool + // IsFinal reports whether this is the last handler of a matched non-middleware + // route, so nothing further on that route runs. It describes the route, not the + // request: another route can still match, and a Use route is never final. + IsFinal() bool // OverrideParam overwrites a route parameter value by name. // If the parameter name does not exist in the route, this method does nothing. OverrideParam(name, value string) - // IsWebSocket returns true if the request includes a WebSocket upgrade handshake. - IsWebSocket() bool - // IsPreflight returns true if the request is a CORS preflight. - IsPreflight() bool // SaveFile saves any multipart file to disk. SaveFile(fileheader *multipart.FileHeader, path string) error // SaveFileToStorage saves any multipart file to an external storage system. SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error - // Secure returns whether a secure connection was established. - Secure() bool + // Error returns an *Error carrying the given status code, defaulting the message + // to the status text. Returning it hands it to the app's ErrorHandler, which + // writes the response; Error itself sets nothing. + Error(status int, message ...string) error // Status sets the HTTP status for the response. // This method is chainable. + // + // A status outside 100 to 999 is logged and replaced by 500. Status(status int) Ctx + // ID returns the connection-unique identifier fasthttp assigned to this request, + // unlike RequestID, which reads a header. It is not unique across processes or + // restarts, so use it to correlate log lines within one server run. + ID() uint64 + // StartTime returns the time the server began handling this request. It is the + // reference point Elapsed measures from. + StartTime() time.Time + // Elapsed returns how long this request has been handled so far, measured from + // StartTime. Called after the handler chain has run, it is the request latency. + Elapsed() time.Duration + // LocalAddr returns the server-side address of the connection this request + // arrived on. IP returns the client address as a string; this is the full + // net.Addr, so the port, network, and unix socket path survive. + LocalAddr() net.Addr + // RemoteAddr returns the address of the immediate peer, which is the proxy + // rather than the client when the app sits behind one. Use IP or IPs for the + // client address a trusted proxy forwarded. + RemoteAddr() net.Addr + // Hijack registers a handler that takes over the connection once the response is + // sent, for protocols Fiber does not speak. The connection then closes unless + // KeepHijackedConns is set, and the handler must not touch the pooled Ctx. + Hijack(handler fasthttp.HijackHandler) + // Hijacked returns true if Hijack has been called on this request, so a later + // handler can tell that the connection is already spoken for and leave the + // response alone. + Hijacked() bool // String returns unique string representation of the ctx. // // The returned value may be useful for logging. @@ -147,9 +210,6 @@ type Ctx interface { // and therefore available to all following routes that match the request. If the context // has been released and c.fasthttp is nil (for example, after ReleaseCtx), Value returns nil. Value(key any) any - // XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, - // indicating that the request was issued by a client library (such as jQuery). - XHR() bool // configDependentPaths set paths for route recognition and prepared paths for the user, // here the features for caseSensitive, decoded paths, strict paths are evaluated configDependentPaths() @@ -206,28 +266,90 @@ type Ctx interface { getMethodInt() int getIndexRoute() int getTreePathHash() int + // pathSlashCount lazily counts the '/' bytes of the detection path and caches + // the result for the request; matching uses it to reject route candidates + // without walking their segments. app is the serving App, which can differ + // from c.app when an App value was copied. When it registers no route that + // consults the count, counting is skipped and 0 is returned — a real detection + // path always contains a '/', so 0 doubles as the "unknown" state that makes + // Route.match skip the quick-reject entirely. + pathSlashCount(app *App) int getDetectionPath() string getValues() *[maxParams]string getMatched() bool getSkipNonUseRoutes() bool + getFirstMatchIndex() int setIndexHandler(handler int) setIndexRoute(route int) setMatched(matched bool) setSkipNonUseRoutes(skip bool) + setFirstMatchIndex(index int) setRoute(route *Route) getPathOriginal() string + // Accepts checks if the specified extensions or content types are acceptable. + Accepts(offers ...string) string + // AcceptsCharsets checks if the specified charset is acceptable. + AcceptsCharsets(offers ...string) string + // AcceptsEncodings checks if the specified encoding is acceptable. + // + // Per RFC 9110 §12.5.3, a missing Accept-Encoding accepts any coding (the first + // offer wins), an empty one only "identity", and "identity" is acceptable unless + // the field excludes it with q=0. + AcceptsEncodings(offers ...string) string + // AcceptsLanguages checks if the specified language is acceptable using + // RFC 4647 Basic Filtering. + AcceptsLanguages(offers ...string) string + // AcceptsLanguagesExtended checks if the specified language is acceptable using + // RFC 4647 Extended Filtering. + AcceptsLanguagesExtended(offers ...string) string + // BodyRaw contains the raw body submitted in a POST request. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting instead. + BodyRaw() []byte + //nolint:nonamedreturns // gocritic unnamedResult prefers naming decoded body, decode count, and error + tryDecodeBodyInOrder(originalBody *[]byte, encodings []string) (body []byte, decodesRealized uint8, err error) + // BodyStream returns the request body as a stream, non-nil only when + // Config.StreamRequestBody is enabled and the body is not already buffered. + // Reading it consumes the body, so a later Body call will not see it. + BodyStream() io.Reader // FullURL returns the full request URL (protocol + host + original URL). FullURL() string // UserAgent returns the User-Agent request header. UserAgent() string // Referer returns the Referer request header. Referer() string + // Origin returns the Origin request header. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + Origin() string + // headerField returns a request header's first non-empty field value, matching + // the field name case-insensitively (RFC 9110 Section 5.1). fieldname.First + // also steps over a present-but-empty first line, so a value on a later line + // is found and this agrees with GetAll on whether the field is there. + headerField(name string) []byte // AcceptLanguage returns the Accept-Language request header. + // Repeated field lines are combined into one comma-joined list (RFC 9110 + // Section 5.2) and the field name matches case-insensitively (Section 5.1), + // matching what AcceptsLanguages negotiates on. AcceptLanguage() string // AcceptEncoding returns the Accept-Encoding request header. + // Repeated field lines are combined into one comma-joined list (RFC 9110 + // Section 5.2) and the field name matches case-insensitively (Section 5.1), + // matching what AcceptsEncodings negotiates on. AcceptEncoding() string // HasHeader reports whether the request includes a header with the given key. + // The field name matches case-insensitively (RFC 9110 Section 5.1), so this + // agrees with GetAll on whether the field is there. HasHeader(key string) bool + // HasHeaderValue reports whether the request header key lists value as one of + // its comma-separated members, on any of its field lines. Repeated field lines + // are one list (RFC 9110 Section 5.3) and the member matches under ASCII case + // folding, so it fits directive-style headers such as Cache-Control or + // Connection. A comma inside a quoted argument does not end a member, so + // `ext="a,no-transform,b"` is one member and does not list no-transform + // (RFC 9111 permits quoted directive arguments, escaped quotes included). An + // empty value is never present. Only valid within the handler. + HasHeaderValue(key, value string) bool // MediaType returns the MIME type from the Content-Type header without parameters. MediaType() string // Charset returns the charset parameter from the Content-Type header. @@ -246,36 +368,14 @@ type Ctx interface { AcceptsXML() bool // AcceptsEventStream reports whether the Accept header allows text/event-stream. AcceptsEventStream() bool - // Accepts checks if the specified extensions or content types are acceptable. - Accepts(offers ...string) string - // AcceptsCharsets checks if the specified charset is acceptable. - AcceptsCharsets(offers ...string) string - // AcceptsEncodings checks if the specified encoding is acceptable. - AcceptsEncodings(offers ...string) string - // AcceptsLanguages checks if the specified language is acceptable using - // RFC 4647 Basic Filtering. - AcceptsLanguages(offers ...string) string - // AcceptsLanguagesExtended checks if the specified language is acceptable using - // RFC 4647 Extended Filtering. - AcceptsLanguagesExtended(offers ...string) string - // BodyRaw contains the raw body submitted in a POST request. - // Returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting instead. - BodyRaw() []byte - //nolint:nonamedreturns // gocritic unnamedResult prefers naming decoded body, decode count, and error - tryDecodeBodyInOrder(originalBody *[]byte, encodings []string) (body []byte, decodesRealized uint8, err error) - // Body contains the raw body submitted in a POST request. - // This method will decompress the body if the 'Content-Encoding' header is provided. - // It returns the original (or decompressed) body data which is valid only within the handler. - // Don't store direct references to the returned data. - // If you need to keep the body's data later, make a copy or use the Immutable option. - Body() []byte - // Cookies are used for getting a cookie value by key. - // Defaults to the empty string "" if the cookie doesn't exist. - // If a default value is given, it will return that value if the cookie doesn't exist. - // The returned value is only valid within the handler. Do not store any references. - // Make copies or use the Immutable setting to use the value outside the Handler. - Cookies(key string, defaultValue ...string) string + // CookieNames returns the request cookie names in header order, or nil when + // there are none. A repeated name appears once per occurrence, which is how the + // shadowing AllCookies collapses is detected. The strings are copies. + CookieNames() []string + // AllCookies returns the request cookies as a name/value map, or nil when there + // are none. A repeated name resolves to its first occurrence, as Cookies does, + // so a shadowed cookie cannot be validated in one and consumed in the other. + AllCookies() map[string]string // FormFile returns the first file by key from a MultipartForm. // The multipart form is parsed using the application's BodyLimit to prevent // unbounded memory usage. @@ -288,14 +388,46 @@ type Ctx interface { // Make copies or use the Immutable setting instead. // When the request is a multipart form, it is parsed using the application's // BodyLimit so the configured limit is consistently enforced. + // + // On a form request this lowercases the case-insensitive parts of the request's + // own Content-Type, so a value obtained earlier from Get(HeaderContentType) — + // which aliases those bytes unless Immutable is set — can change during the + // call. Copy it first if you need it to outlive one. FormValue(key string, defaultValue ...string) string // Fresh returns true when the response is still “fresh” in the client's cache, // otherwise false is returned to indicate that the client cache is now stale // and the full response should be sent. + // Freshness only applies to GET and HEAD requests; for any other method false is + // returned, as RFC 9110 defines 304 Not Modified only for those methods and + // requires If-Modified-Since to be ignored otherwise. // When a client sends the Cache-Control: no-cache request header to indicate an end-to-end // reload request, this module will return false to make handling these requests transparent. // https://github.com/jshttp/fresh/blob/master/index.js#L33 Fresh() bool + // IfNoneMatch returns the entity tags in the If-None-Match request header, + // verbatim and unvalidated; a comma inside a quoted opaque-tag does not split + // one. Fresh already compares them. Only valid within the handler. + IfNoneMatch() []string + // IfModifiedSince returns the time carried by the If-Modified-Since request + // header, ErrHeaderNotFound when it is absent or empty, and a parse error when + // it is none of the HTTP-date formats RFC 9110 Section 5.6.7 requires. + IfModifiedSince() (time.Time, error) + // GetAll returns every field line stored under key, where Get returns only the + // first, or nil when the header is absent. Empty lines are skipped, so its + // presence answers as HasHeader does. Only valid within the handler. + GetAll(key string) []string + // Authorization splits the Authorization header into auth-scheme and credentials + // (RFC 9110 Section 11.6.2), neither decoded nor validated. They view the request + // buffer: a credential kept past the handler becomes another request's. + Authorization() (scheme, credentials string) + // authorizationParts splits the Authorization header at the first space or tab + // (RFC 9110 Section 11.4), on raw bytes so each caller materializes only the + // strings it needs. A lone token is a scheme without credentials. + authorizationParts() (scheme, credentials []byte) + // Bearer returns the credentials of a Bearer Authorization header (RFC 6750 + // Section 2.1), unverified, or "" for another scheme. It views the request + // buffer: a token kept past the handler becomes another request's. + Bearer() string // Host contains the host derived from the X-Forwarded-Host or Host HTTP header. // Returned value is only valid within the handler. Do not store any references. // In a network context, `Host` refers to the combination of a hostname and potentially a port number used for connecting, @@ -313,10 +445,17 @@ type Ctx interface { // Port returns the remote port of the request. Port() string // IP returns the client's IP address. When the request comes from a trusted proxy (see - // [TrustProxyConfig]), the value is extracted from the configured ProxyHeader by walking the - // X-Forwarded-For chain right-to-left and skipping all trusted proxy IPs; the first - // non-trusted IP in the chain is returned. Please use Config.TrustProxy to prevent header - // spoofing if your app is behind a proxy. + // [TrustProxyConfig]) and Config.ProxyHeader is set, the value is taken from that header. + // With Config.EnableIPValidation enabled and proxy IPs or ranges configured (Proxies, + // Loopback, Private or LinkLocal), the X-Forwarded-For chain is walked right-to-left, every + // trusted proxy IP is skipped and the first non-trusted IP is returned; with validation + // enabled but only UnixSocket trusted, the first valid IP from the left is returned. With + // validation disabled (the default), the raw header value is returned as-is, which for + // X-Forwarded-For may be the whole comma-separated chain. Enable validation whenever the + // result is used as a single client identifier and the header can carry a chain, for example + // by the limiter middleware or an allowlist; a proxy that overwrites the header with one + // address, or a single-IP header, does not need it. Please use Config.TrustProxy to prevent + // header spoofing if your app is behind a proxy. IP() string // extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. // When IP validation is enabled, any invalid IPs will be omitted. @@ -337,20 +476,69 @@ type Ctx interface { // Is returns the matching content type, // if the incoming request's Content-Type HTTP header field matches the MIME type specified by the type parameter Is(extension string) bool + // HasBody returns true if the request declares a body via Content-Length, Transfer-Encoding, or already buffered payload data. + HasBody() bool + // IsWebSocket returns true if the request includes a WebSocket upgrade handshake. + IsWebSocket() bool + // IsPreflight returns true if the request is a CORS preflight. + IsPreflight() bool + // Secure returns whether a secure connection was established. + Secure() bool + // XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, + // indicating that the request was issued by a client library (such as jQuery). + XHR() bool // Locals makes it possible to pass any values under keys scoped to the request // and therefore available to all following routes that match the request. // // All the values are removed from ctx after returning from the top // RequestHandler. Additionally, Close method is called on each value // implementing io.Closer before removing the value from ctx. + // + // Storing through the Ctx interface heap-allocates the one-element slice the + // variadic value is packed into; SetLocal stores the same value without it. Locals(key any, value ...any) any + // SetLocal stores value under key scoped to the request, exactly as + // Locals(key, value) does: the value is available to all following routes that + // match the request, removed after the top RequestHandler returns, and its + // Close method is called first if it implements io.Closer. Like Locals, it + // stores nothing while the context is released. A Ctx must not be used past + // its handler either way, because the pool hands the same one to the next + // request. + // + // Locals takes its value variadically, and reached through the Ctx interface + // the compiler cannot see that the callee only reads that argument, so the + // one-element "..." slice is heap-allocated on every call. SetLocal takes the + // value directly, so that slice is never built. Boxing a value that is not + // already an interface still allocates, exactly as it does for Locals. + SetLocal(key, value any) // Method returns the HTTP request method for the context, optionally overridden by the provided argument. // If no override is given or if the provided override is not a valid HTTP method, it returns the current method from the context. // Otherwise, it updates the context's method and returns the overridden method as a string. Method(override ...string) string + // IsSafe reports whether the request method is safe, meaning it is not expected + // to change server state (RFC 9110 Section 9.2.1). + IsSafe() bool + // IsIdempotent reports whether the request method is idempotent, meaning + // repeating it has the same intended effect as making it once (RFC 9110 + // Section 9.2.2). Every safe method is also idempotent. + IsIdempotent() bool // MultipartForm parse form entries from binary. // This returns a map[string][]string, so given a key, the value will be a string slice. + // + // On a form request this lowercases the case-insensitive parts of the request's + // own Content-Type, so a value obtained earlier from Get(HeaderContentType) — + // which aliases those bytes unless Immutable is set — can change during the + // call. Copy it first if you need it to outlive one. MultipartForm() (*multipart.Form, error) + // URI returns the parsed *fasthttp.URI of the request, giving access to all + // fasthttp URI methods. It is owned by the request and rewritten by a Path + // override, so it is only valid within the handler. + URI() *fasthttp.URI + // Path returns the path part of the request URL, normalized before routing + // (see Config.UnescapePath); OriginalURL returns the request target as sent. + // Optionally, you could override the path. + // Make copies or use the Immutable setting to use the value outside the Handler. + Path(override ...string) string // Params is used to get the route parameters. // Defaults to empty string "" if the param doesn't exist. // If a default value is given, it will return that value if the param doesn't exist. @@ -409,14 +597,40 @@ type Ctx interface { getBody() []byte // Append the specified value to the HTTP response header field. // If the header is not already set, it creates the header with the specified value. + // Empty values are skipped: a sender must not generate empty list elements + // (RFC 9110 Section 5.6.1.2). + // Members are compared byte-exactly, because some lists (Link, Cache-Control) + // are not all field names. For Vary field names, use Vary, which folds case. Append(field string, values ...string) + // Add appends the value as a new field line, where Append folds values into one + // comma-separated line. The headers fasthttp keeps in a slot of their own are + // the exception: Content-Type, Server and the rest are replaced and Date and TE + // ignored, though Set-Cookie is slotted and does append. Use Cookie for that. + Add(key, val string) // Attachment sets the HTTP response Content-Disposition header field to attachment. Attachment(filename ...string) // ClearCookie expires a specific cookie by key on the client side. // If no key is provided it expires all cookies that came with the request. ClearCookie(key ...string) // Cookie sets a cookie by passing a cookie struct. + // + // The argument is treated as read-only: the normalization this method applies + // (default Path, SessionOnly, and the Secure implied by SameSite=None or + // Partitioned) happens on a local copy, so a caller may reuse the same *Cookie + // template across requests. Cookie(cookie *Cookie) + // GetCookie reads back a cookie this response is set to send, false when the + // name is unset or its value does not parse. Names are case-sensitive and a + // repeat resolves to the first. Writing the copy back through Cookie stamps + // Path=/ on a cookie that carried none, widening its scope — set Path first. + GetCookie(name string) (*Cookie, bool) + // GetCookies returns a copy of every cookie this response is set to send, in + // order, or nil when there are none. Repeated names are kept apart, and an + // unparsable one is skipped. For what the client sent, use Req.Cookies. + // + // Named for GetCookie beside it rather than Cookies, which would collide with + // Req.Cookies under a different signature and stop Ctx satisfying Res. + GetCookies() []*Cookie // Download transfers the file from path as an attachment. // Typically, browsers will prompt the user for download. // By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog). @@ -436,6 +650,10 @@ type Ctx interface { // For more flexible content negotiation, use Format. // If the header is not specified or there is no proper format, text/plain is used. AutoFormat(body any) error + // Del removes every field line stored under key, whatever case it is spelled in, + // and is a no-op for a header that was never set. Del(HeaderSetCookie) withdraws + // the pending cookies, where ClearCookie expires one in the client's jar. + Del(key string) // JSON converts any interface or string to JSON. // Array and slice values encode as JSON arrays, // except that []byte encodes as a base64-encoded string, @@ -457,6 +675,12 @@ type Ctx interface { // JSONP sends a JSON response with JSONP support. // This method is identical to JSON, except that it opts-in to JSONP callback support. // By default, the callback name is simply callback. + // + // The callback name is reduced to a JavaScript member expression: everything + // outside [A-Za-z0-9_$.[]] is dropped. Callers routinely take the name straight + // from the query string, which is what JSONP is for, and the name lands + // verbatim in a same-origin text/javascript body — so an unfiltered one would + // let a request supply arbitrary script for the app's own origin. JSONP(data any, callback ...string) error // XML converts any interface or string to XML. // This method also sets the content header to application/xml; charset=utf-8. @@ -473,6 +697,14 @@ type Ctx interface { // Render a template with data and sends a text/html response. // We support the following engines: https://github.com/gofiber/template Render(name string, bind any, layouts ...string) error + // ResetBody discards the response body, keeping the status and headers. + // Use it before replacing a partially written body — an error page over a + // half-rendered view, a cached body over a fresh one. + ResetBody() + // Written reports whether anything has been written to the response body, so a + // handler that produced one can be told from a handler that did not. A stream + // counts without being drained; a status or header alone does not. + Written() bool // Send sets the HTTP response body without copying it. // From this point onward the body argument must not be changed. Send(body []byte) error @@ -492,6 +724,10 @@ type Ctx interface { // The Content-Type response HTTP header field is set based on the file's extension. // If the file extension is missing or invalid, the Content-Type is detected from the file's format. SendFile(file string, config ...SendFile) error + // NoContent replies 204 No Content. SendStatus already discards the body; this + // drops the Content-Type too, since RFC 9110 Section 6.4.1 gives a 204 no + // content to describe. SendStatus(204) keeps it, so the two differ. + NoContent() error // SendStatus sets the HTTP status code and if the response body is empty, // it sets the correct status message in the body. SendStatus(status int) error @@ -505,10 +741,17 @@ type Ctx interface { // Set sets the response's HTTP header field to the specified key, value. Set(key, val string) setCanonical(key, val string) + // StatusCode returns the status code set on the response, the read side of + // Status, and reports 200 until something sets another. After Next it is the + // status the chain settled on. + StatusCode() int // Type sets the Content-Type HTTP header to the MIME type specified by the file extension. Type(extension string, charset ...string) Ctx // Vary adds the given header field to the Vary response header. // This will append the header, if not already listed; otherwise, leaves it listed in the current location. + // Field names are compared case-insensitively (RFC 9110 Section 5.1); the first spelling is kept. + // Per RFC 9110 Section 12.5.5 the wildcard "*" only has meaning as the sole member of the field: + // once "*" is added (or already present), the header is collapsed to a single "*". Vary(fields ...string) // Write appends p into response body. Write(p []byte) (int, error) diff --git a/src/vendor/github.com/gofiber/fiber/v3/domain.go b/src/vendor/github.com/gofiber/fiber/v3/domain.go index 71af1934..0c0da47c 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/domain.go +++ b/src/vendor/github.com/gofiber/fiber/v3/domain.go @@ -7,6 +7,7 @@ package fiber import ( "fmt" "reflect" + "slices" "strings" "github.com/gofiber/utils/v2" @@ -305,7 +306,7 @@ func (d *domainRouter) wrapHandlers(handlers []Handler) []Handler { values: values, } } - c.Locals(cacheKey, check) + setLocal(c, cacheKey, check) } if !check.isMatched { @@ -314,7 +315,7 @@ func (d *domainRouter) wrapHandlers(handlers []Handler) []Handler { // Reuse the cached domainParams (or nil to clear stale values) // instead of allocating a new struct per handler invocation. - c.Locals(domainLocalsKey, check.params) + setLocal(c, domainLocalsKey, check.params) return origHandler(c) } @@ -376,7 +377,8 @@ func (d *domainRouter) Use(args ...any) Router { for _, prefix := range prefixes { if subApp != nil { - return d.mount(prefix, subApp) + d.mount(prefix, subApp) + continue } wrapped := d.wrapHandlers(handlers) @@ -418,35 +420,76 @@ func (d *domainRouter) mount(prefix string, subApp *App) Router { // Create a wrapper app so that the original sub-app is not mutated. // This allows the same sub-app to be reused (e.g., mounted on multiple // domains) without double-wrapping handlers. + // + // The method table comes from the app being mounted on, not from the + // sub-app: processSubAppsRoutes reads the wrapper's stack at the parent's + // method indexes, so a wrapper with a shorter stack would put that read out + // of range. wrapperApp := New(Config{ - CaseSensitive: subApp.config.CaseSensitive, - StrictRouting: subApp.config.StrictRouting, - RegexHandler: subApp.config.RegexHandler, + CaseSensitive: subApp.config.CaseSensitive, + StrictRouting: subApp.config.StrictRouting, + RegexHandler: subApp.config.RegexHandler, + RequestMethods: d.app.config.RequestMethods, + DisableHeadAutoRegister: subApp.config.DisableHeadAutoRegister, }) - wrapperApp.customConstraints = subApp.customConstraints - - // Clone routes from the sub-app with domain-wrapped handlers. - // Lock the sub-app while reading to prevent data races with concurrent - // route registration. - subApp.mutex.Lock() - defer subApp.mutex.Unlock() - for m := range subApp.stack { - for _, route := range subApp.stack[m] { - clonedRoute := subApp.copyRoute(route) - if len(clonedRoute.Handlers) > 0 { - clonedRoute.Handlers = d.wrapHandlers(clonedRoute.Handlers) - } - wrapperApp.stack[m] = append(wrapperApp.stack[m], clonedRoute) - } + // Every route the wrapper carries is filtered by the pattern of the mount + // it came from, which is what the automatic HEAD routes have to respect: + // the apps behind one wrapper do not all answer for the same hostnames. + wrapperApp.mountFields.hostScopedRoutes = true + + // Clone routes from the sub-app with domain-wrapped handlers. The clone + // also collects the constraints of every app it walks, since the wrapper is + // what the routes are re-parsed against when the mount is expanded, and + // marks the routes of the apps that register no automatic HEAD routes. + d.cloneRoutesForDomain(wrapperApp, subApp) + + // Give the clones their automatic HEAD routes. A mounted app normally gets + // them from startupProcess, which walks the parent's app list — and the + // wrapper is deliberately not in it, so without this a domain-mounted GET + // route answers HEAD with 405 where a plain mount answers 200. + // + // The routes marked while cloning are passed over, and the marks travel on + // to the app this one is mounted on, so it withholds them there as well. + wrapperApp.ensureAutoHeadRoutes() + + // Register the sub-app, and every app it has mounted, as domain mounts of + // the parent. They are kept out of appList so that their ErrorHandler and + // view engine only answer for hosts this domain matches, and so that two + // sub-apps mounted at the same path on different domains do not displace + // each other. + // + // Collect the mounts before taking the parent's lock, and hold only one + // app's lock at a time while doing it. App.mount writes these lists under + // the lock of the app they belong to, so reading them unguarded would race + // — but holding two at once would hang outright when an app is mounted on + // itself, and could deadlock two goroutines mounting each other's apps. + // + // The walk goes through the sub-app's own mount metadata rather than its + // flattened list, which is filled in as apps are mounted and so misses one + // mounted on a descendant afterwards; it also picks up the apps each + // descendant domain-mounted itself, since those records live only on the + // app they were registered on. The routes reach all of them either way. + pending := subApp.mountTree() + + // Each app's mount path is written under its own lock, and before the + // parent's is taken: an app registering a route reads it there, and it may + // be the parent itself when an app is mounted on itself. + for i := range pending { + mount := &pending[i] + mount.path = getGroupPath(mountPath, mount.path) + + mount.app.mutex.Lock() + mount.app.mountFields.mountPath = mount.path + mount.app.mutex.Unlock() } d.app.mutex.Lock() // Support for configs of mounted-apps and sub-mounted-apps - for mountedPrefixes, subAppInstance := range subApp.mountFields.appList { - path := getGroupPath(mountPath, mountedPrefixes) + for i := range pending { + mount := &pending[i] + recorded := d.app.newDomainMount(mount.app, mount.path, append(slices.Clone(mount.matchers), d.matcher), mount.ancestors, mount.declared) - subAppInstance.mountFields.mountPath = path - d.app.mountFields.appList[path] = subAppInstance + d.app.mountFields.domainAppList = addDomainMount(d.app.mountFields.domainAppList, &recorded) } d.app.mutex.Unlock() @@ -473,6 +516,164 @@ func (d *domainRouter) mount(prefix string, subApp *App) Router { return d } +// cloneRoutesForDomain fills dst with domain-filtered clones of src's routes, +// expanding any app src itself has mounted. +// +// The expansion is what keeps a nested mount working. A mount is registered as +// a placeholder route that carries its target app in the unexported group +// field, and copyRoute does not carry that field over, so a cloned placeholder +// would reach startup with mount set and group nil and crash the expansion in +// processSubAppsRoutes. Flattening the descendants here also runs their +// handlers through wrapHandlers, so they stay bound to the domain instead of +// being served on every host. +// Routes cloned from an app that registers no automatic HEAD routes are marked +// as such on the wrapper, so synthesizing them stays off for those and stays on +// for the rest. +func (d *domainRouter) cloneRoutesForDomain(dst, src *App) { + for m, routes := range d.domainRoutes(dst, src, domainClone{}) { + dst.stack[m] = routes + } +} + +// domainClone is what a walk down a mounted app's tree carries with it. +type domainClone struct { + // prefix is the path the app being walked is mounted at, relative to the + // app the domain mount was registered with + prefix string + // chain holds the apps between the mounted sub-app and this one, so a mount + // cycle terminates. It is a slice rather than a set because it is only ever + // a few entries deep and each branch needs its own: an app mounted twice on + // sibling branches is cloned for both. + chain []*App + // skipAutoHead marks that an app above this one registers no automatic HEAD + // routes, and stands in front of these + skipAutoHead bool +} + +// domainRoutes returns src's routes, cloned with domain-filtered handlers and +// with the walk's prefix applied, as one slice per method index of dst. Routes +// of an app src has mounted take the placeholder's position, so the order the +// sub-app registered its routes in is preserved. +func (d *domainRouter) domainRoutes(dst, src *App, walk domainClone) [][]*Route { + routes := make([][]*Route, len(dst.stack)) + if slices.Contains(walk.chain, src) { + return routes + } + + // An app that does not serve HEAD, or that turned the automatic routes off, + // contributes neither HEAD routes nor HEAD middleware to the clone — so a + // HEAD route synthesized from one of its GET routes would run the handler + // with nothing in front of it. That holds for the apps it has mounted too, + // whose routes it stands in front of, and for no one else: the mount is a + // tree, and an app opting out says nothing about its siblings or the apps + // it is mounted inside. + skipAutoHead := walk.skipAutoHead || src.config.DisableHeadAutoRegister || src.methodInt(MethodHead) < 0 + + // Take a snapshot rather than holding the lock for the whole walk: it keeps + // this from ever holding two apps' locks at once. The routes are copied by + // value, not by pointer, because registering a route on a path src already + // serves appends to that route's handlers in place, and renaming one writes + // its name — a clone taken after the lock was released would race both. + // + // A mount placeholder is kept as it is: its target app is read from the + // group it carries, and the walk into it has to happen unlocked. + // + // The snapshot is indexed by dst's methods, not src's: an app is free to + // configure its own RequestMethods, and the two tables then neither line up + // nor have to be the same length. + type sourceRoute struct { + route *Route + owner *App + constraints []CustomConstraint + } + + src.mutex.Lock() + stack := make([][]sourceRoute, len(routes)) + for m := range stack { + srcRoutes := src.routesForMethod(dst.method(m)) + stack[m] = make([]sourceRoute, len(srcRoutes)) + + for i, route := range srcRoutes { + if route.mount { + stack[m][i] = sourceRoute{route: route} + continue + } + + // src is itself a wrapper when the sub-app had domain mounts of its + // own, and already knows the real app behind each of its routes. + owner := src.routeOwner(route) + if owner == nil { + owner = src + } + + stack[m][i] = sourceRoute{ + route: src.copyRoute(route), + owner: owner, + constraints: src.routeConstraintsFor(route), + } + } + } + dst.customConstraints = mergeCustomConstraints(dst.customConstraints, src.customConstraints) + src.mutex.Unlock() + + // Mounted apps are flattened once and reused across the method indexes: + // register files a copy of the placeholder in every method's stack, and + // all of them share the one group it was registered with. + var mounted map[*Group][][]*Route + + for m := range routes { + for _, source := range stack[m] { + if source.route.mount { + // register only sets mount for a route whose group carries the + // mounted app, so group and group.app are both set here — the + // same invariant processSubAppsRoutes relies on. + group := source.route.group + if mounted[group] == nil { + if mounted == nil { + mounted = make(map[*Group][][]*Route) + } + mounted[group] = d.domainRoutes(dst, group.app, domainClone{ + prefix: getGroupPath(walk.prefix, source.route.path), + chain: append(walk.chain, src), + skipAutoHead: skipAutoHead, + }) + } + + routes[m] = append(routes[m], mounted[group][m]...) + continue + } + + clonedRoute := source.route + // An empty prefix cannot change the path, and re-parsing the route + // to reach the same result is the most expensive thing here. + // The route brings the constraints of the apps that composed its + // path, and those win over the ones collected from the rest of the + // tree: two apps mounted side by side can name one constraint + // differently, and neither binds the other. + constraints := mergeCustomConstraints(slices.Clone(source.constraints), dst.customConstraints) + dst.markRouteConstraints(clonedRoute, constraints) + + if walk.prefix != "" { + dst.addPrefixToRoute(walk.prefix, clonedRoute, src.config.RegexHandler, constraints...) + } + clonedRoute.Handlers = d.wrapHandlers(clonedRoute.Handlers) + + // Record the app the route came from, so a request that runs it + // resolves that app's config rather than one inferred from the host + // and the path. + dst.markRouteOwner(clonedRoute, source.owner) + + if skipAutoHead { + dst.markSkipAutoHead(clonedRoute) + } + + routes[m] = append(routes[m], clonedRoute) + } + } + + return routes +} + // Get registers a route for GET methods. // The handler only executes when the request hostname matches the domain pattern. func (d *domainRouter) Get(path string, handler any, handlers ...any) Router { diff --git a/src/vendor/github.com/gofiber/fiber/v3/error.go b/src/vendor/github.com/gofiber/fiber/v3/error.go index 327771cd..b19824c4 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/error.go +++ b/src/vendor/github.com/gofiber/fiber/v3/error.go @@ -22,6 +22,11 @@ var ( ErrNoViewEngineConfigured = errors.New("fiber: no view engine configured") // ErrAutoCertWithCertFile indicates AutoCertManager cannot be used with CertFile/CertKeyFile. ErrAutoCertWithCertFile = errors.New("tls: AutoCertManager cannot be combined with CertFile/CertKeyFile") + // ErrRouteNotRepresentable indicates a route whose path no relative URL can + // name, so Route.URL, GetRouteURL and Redirect().Route cannot compose one. + // A path starting with two or more slashes is such a route: the URL that + // would reach it opens an authority instead. + ErrRouteNotRepresentable = errors.New("router: route path cannot be expressed as a relative URL") ) // Fiber redirection errors @@ -31,11 +36,20 @@ var ( // Range errors var ( - ErrRangeMalformed = errors.New("range: malformed range header string") + // ErrRangeMalformed is returned for a syntactically invalid Range header, + // which RFC 9110 Section 14.2 allows a server to reject; it carries a + // 400 Bad Request status so propagating it does not surface as a 500. + ErrRangeMalformed = NewError(StatusBadRequest, "range: malformed range header string") + // ErrRangeUnsupported is returned for a Range header whose range unit is + // not "bytes". RFC 9110 Section 14.2 requires an origin server to IGNORE + // a Range header field with a range unit it does not understand, so + // callers receiving this error should serve the full representation + // instead of returning an error response. It still carries a + // 400 Bad Request status as a safety net, so blind propagation does not + // surface as a 500. + ErrRangeUnsupported = NewError(StatusBadRequest, "range: unsupported range unit") ErrRangeTooLarge = NewError(StatusRequestedRangeNotSatisfiable, "range: too many ranges") ErrRangeUnsatisfiable = errors.New("range: unsatisfiable range") - // errRangeBound: empty/non-numeric range bound; control-flow only, never surfaced. - errRangeBound = errors.New("range: bound not parsable") ) // Binder errors @@ -90,3 +104,10 @@ var ( ErrFileRead = errors.New("file: failed to read file") ErrFileStore = errors.New("file: failed to store file") ) + +// Header errors +var ( + // ErrHeaderNotFound is returned by request header accessors that parse a + // value, to tell an absent header apart from one that failed to parse. + ErrHeaderNotFound = errors.New("header: field not present in the request") +) diff --git a/src/vendor/github.com/gofiber/fiber/v3/group.go b/src/vendor/github.com/gofiber/fiber/v3/group.go index 34cc324b..a9ef6e1c 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/group.go +++ b/src/vendor/github.com/gofiber/fiber/v3/group.go @@ -96,7 +96,8 @@ func (grp *Group) Use(args ...any) Router { for _, prefix := range prefixes { if subApp != nil { - return grp.mount(prefix, subApp) + grp.mount(prefix, subApp) + continue } grp.app.register([]string{methodUse}, getGroupPath(grp.Prefix, prefix), grp, handlers...) diff --git a/src/vendor/github.com/gofiber/fiber/v3/helpers.go b/src/vendor/github.com/gofiber/fiber/v3/helpers.go index d8a1b76e..56903fea 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/helpers.go +++ b/src/vendor/github.com/gofiber/fiber/v3/helpers.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "math/bits" "net" "os" "path/filepath" @@ -24,11 +25,16 @@ import ( "github.com/gofiber/utils/v2" utilsbytes "github.com/gofiber/utils/v2/bytes" + utilsstrings "github.com/gofiber/utils/v2/strings" + "github.com/gofiber/utils/v2/swar" + "github.com/gofiber/fiber/v3/binder" "github.com/gofiber/fiber/v3/internal/contextvalue" + etagpkg "github.com/gofiber/fiber/v3/internal/etag" + "github.com/gofiber/fiber/v3/internal/headerlist" + "github.com/gofiber/fiber/v3/internal/mediatype" "github.com/gofiber/fiber/v3/log" - "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) @@ -70,13 +76,33 @@ func ValueFromContext[T any](ctx, key any) (T, bool) { // This is useful when values need to be available via both c.Locals() and // context.Context lookups throughout middleware and handlers. func StoreInContext(c Ctx, key, value any) { - c.Locals(key, value) + setLocal(c, key, value) if c.App().config.PassLocalsToContext { c.SetContext(context.WithValue(c.Context(), key, value)) } } +// setLocal stores key/value on c, preferring the concrete context, and +// returns what Locals returned so callers keep its result. +// +// Locals takes its value variadically, and reached through the Ctx interface +// the compiler cannot see that it only reads that argument, so the +// one-element "..." slice is heap-allocated on every call. Calling the +// concrete method lets it inline and keeps the slice in the frame: 50ns with +// an allocation becomes 11ns without, on every request that stores a request +// ID, a session, a CSRF token or an authenticated user. +// +// A custom Ctx fails the assertion and keeps the interface call, so an +// overridden Locals is still the one that runs. internal/ctxlocal.Set is the +// same function for the packages that cannot reach this one. +func setLocal(c Ctx, key, value any) any { + if dc, ok := c.(*DefaultCtx); ok { + return dc.Locals(key, value) + } + return c.Locals(key, value) +} + // getTLSConfig returns a net listener's tls config func getTLSConfig(ln net.Listener) *tls.Config { if ln == nil { @@ -165,58 +191,93 @@ func readContent(rf io.ReaderFrom, name string) (int64, error) { return n, nil } -// quoteString escapes special characters using percent-encoding. -// Non-ASCII bytes are encoded as well so the result is always ASCII. -func (app *App) quoteString(raw string) string { - bb := bytebufferpool.Get() - quoted := string(fasthttp.AppendQuotedArg(bb.B, app.toBytes(raw))) - bytebufferpool.Put(bb) - return quoted -} - -// quoteRawString escapes only characters that need quoting according to -// https://www.rfc-editor.org/rfc/rfc9110#section-5.6.4 so the result may -// contain non-ASCII bytes. -func (*App) quoteRawString(raw string) string { - const hex = "0123456789ABCDEF" - bb := bytebufferpool.Get() - defer bytebufferpool.Put(bb) - - for i := 0; i < len(raw); i++ { - c := raw[i] - switch { - case c == '\\' || c == '"': - // escape backslash and quote - bb.B = append(bb.B, '\\', c) - case c == '\n': - bb.B = append(bb.B, '\\', 'n') - case c == '\r': - bb.B = append(bb.B, '\\', 'r') - case c < 0x20 || c == 0x7f: - // percent-encode control and DEL - bb.B = append( - bb.B, - '%', - hex[c>>4], - hex[c&0x0f], - ) - default: - bb.B = append(bb.B, c) +// appendLowerASCII writes the ASCII-lowercased bytes of src into dst[:0], +// growing dst as needed, in a single pass over src (instead of a copy +// followed by an in-place case fold). Bytes outside 'A'..'Z', including +// non-ASCII, are copied unchanged. src and dst must not overlap. +func appendLowerASCII(dst, src []byte) []byte { + n := len(src) + // Amortized growth like append: every byte of dst[:n] is overwritten + // below, so the grown slice's contents don't matter. + dst = slices.Grow(dst[:0], n)[:n] + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + swar.Store8(dst, i, swar.ToLowerWord(swar.Load8(src, i))) + } + if i == n { + return dst + } + if n >= swar.WordLen { + // Finish with one overlapping word; the overlapped bytes are + // rewritten with the same values. + swar.Store8(dst, n-swar.WordLen, swar.ToLowerWord(swar.Load8(src, n-swar.WordLen))) + return dst + } + for ; i < n; i++ { + c := src[i] + if c-'A' <= 'Z'-'A' { + c |= 0x20 } + dst[i] = c } - - return string(bb.B) + return dst } -// isASCII reports whether the provided string contains only ASCII characters. -// See: https://www.rfc-editor.org/rfc/rfc0020 -func (*App) isASCII(s string) bool { - for i := 0; i < len(s); i++ { - if s[i] > 127 { - return false +// appendCopyLowerASCII writes src into dst and its ASCII lower-case form into +// low, reading src once and returning both, together with the number of '/' +// bytes in src. It backs the default configuration of configDependentPaths, +// where the detection path is exactly the case fold of the path: doing it as a +// copy followed by appendLowerASCII reads every byte twice and pays two +// capacity checks and two loop set-ups, which for the path lengths routers see +// is most of the cost. Fusing them measured 19-46% faster across 5- to 70-byte +// paths. The slash count rides along for the same reason: the router needs it +// for nearly every request, and a separate bytes.Count call cost more than the +// few instructions it takes per word here. +// +// lowerBuf must not alias src. src may alias dstBuf at a higher offset, as it +// does when Path is overridden with a substring of its current value. +func appendCopyLowerASCII(dstBuf, lowerBuf []byte, src string) (dst, lower []byte, slashes int) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the two same-typed slices + n := len(src) + // Amortized growth like append: every byte of both slices is overwritten + // below, so the grown slices' contents don't matter. + dst = slices.Grow(dstBuf[:0], n)[:n] + lower = slices.Grow(lowerBuf[:0], n)[:n] + // Load the overlapping tail before writing dst. If src is a substring of + // dstBuf, an earlier store may otherwise overwrite bytes in this word. + var tail uint64 + if n >= swar.WordLen && n%swar.WordLen != 0 { + tail = swar.Load8(src, n-swar.WordLen) + } + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + w := swar.Load8(src, i) + swar.Store8(dst, i, w) + swar.Store8(lower, i, swar.ToLowerWord(w)) + slashes += bits.OnesCount64(swar.MatchByteMask(w, '/')) + } + if i == n { + return dst, lower, slashes + } + if n >= swar.WordLen { + // Finish with one overlapping word; the overlapped bytes are + // rewritten with the same values, and shifted out of the count. + swar.Store8(dst, n-swar.WordLen, tail) + swar.Store8(lower, n-swar.WordLen, swar.ToLowerWord(tail)) + slashes += bits.OnesCount64(swar.MatchByteMask(tail, '/') >> (8 * (i - (n - swar.WordLen)))) + return dst, lower, slashes + } + for ; i < n; i++ { + c := src[i] + dst[i] = c + if c == '/' { + slashes++ + } + if c-'A' <= 'Z'-'A' { + c |= 0x20 } + lower[i] = c } - return true + return dst, lower, slashes } // defaultString returns the value or a default value if it is set @@ -239,19 +300,43 @@ func getGroupPath(prefix, path string) string { return utils.TrimRight(prefix, '/') + path } +// Match specificity levels returned by the acceptsX helpers. A higher value +// means the range matched the offer more specifically. They only need to be +// ordered consistently within a single helper (each getOffer call uses one +// helper), so an explicit q=0 rejection can override a positive match of the +// same or lower specificity per RFC 9110 §12.5.1. +const ( + matchWildcard = 1 // "*" / trailing-"*" prefix / language "*" + matchPrefix = 2 // language subtag prefix, e.g. "en" matching "en-US" + matchExact = 3 // exact, case-insensitive match + + // Media ranges rank by their coarse class first and by the number of + // matched media-type parameters second, so "text/html;level=1" outranks + // "text/html", which outranks "text/*", which outranks "*/*". + matchMediaAny = 1 // "*/*" + matchMediaTypeAny = 2 // "type/*" + matchMediaTypeSubtype = 3 // "type/subtype" + mediaSpecificityScale = 100 +) + // acceptsOffer determines if an offer matches a given specification. // It supports a trailing '*' wildcard and performs case-insensitive exact matching. -// Returns true if the offer matches the specification, false otherwise. -func acceptsOffer(spec, offer string, _ headerParams) bool { +// It returns the match specificity (0 = no match, higher = more specific): a +// wildcard/prefix match is less specific than an exact match. The specificity is +// used to let an explicit q=0 rejection override a less specific positive match +// of the same coarse class (RFC 9110 §12.5.1). +func acceptsOffer(spec, offer string, _ headerParams) int { if len(spec) >= 1 && spec[len(spec)-1] == '*' { - prefix := spec[:len(spec)-1] - if len(offer) < len(prefix) { - return false + if utils.HasPrefixFold(offer, spec[:len(spec)-1]) { + return matchWildcard } - return utils.EqualFold(prefix, offer[:len(prefix)]) + return 0 } - return utils.EqualFold(spec, offer) + if utils.EqualFold(spec, offer) { + return matchExact + } + return 0 } // acceptsLanguageOfferBasic determines if a language tag offer matches a range @@ -260,19 +345,25 @@ func acceptsOffer(spec, offer string, _ headerParams) bool { // followed by a hyphen. The comparison is case-insensitive. Only a single "*" // as the entire range is allowed. Any "*" appearing after a hyphen renders the // range invalid and will not match. -func acceptsLanguageOfferBasic(spec, offer string, _ headerParams) bool { +// It returns the match specificity (0 = no match): "*" is least specific, a +// prefix match ("en" for "en-US") is more specific, and an exact match is most +// specific — so an explicit "en-US;q=0" can override a positive "en". +func acceptsLanguageOfferBasic(spec, offer string, _ headerParams) int { if spec == "*" { - return true + return matchWildcard } if strings.IndexByte(spec, '*') >= 0 { - return false + return 0 } if utils.EqualFold(spec, offer) { - return true + return matchExact + } + if len(offer) > len(spec) && + utils.HasPrefixFold(offer, spec) && + offer[len(spec)] == '-' { + return matchPrefix } - return len(offer) > len(spec) && - utils.EqualFold(offer[:len(spec)], spec) && - offer[len(spec)] == '-' + return 0 } // acceptsLanguageOfferExtended determines if a language tag offer matches a @@ -281,12 +372,16 @@ func acceptsLanguageOfferBasic(spec, offer string, _ headerParams) bool { // - '*' matches zero or more subtags (can "slide") // - Unspecified subtags are treated like '*' (so trailing/extraneous tag subtags are fine) // - Matching fails if sliding encounters a singleton (incl. 'x') -func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) bool { +// It returns the match specificity (0 = no match): a bare "*" is least specific, +// and otherwise the specificity grows with the number of concrete range subtags +// that had to match, so a deeper range (e.g. "en-US") outranks a shorter one +// ("en") and an explicit "en-US;q=0" can override a positive "en". +func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) int { if spec == "*" { - return true + return matchWildcard } if spec == "" || offer == "" { - return false + return 0 } // Use stack-allocated arrays to avoid heap allocations for typical language tags @@ -305,7 +400,7 @@ func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) bool { // Step 2: first subtag must match (or be '*') if rs[0] != "*" && !utils.EqualFold(rs[0], ts[0]) { - return false + return 0 } i, j := 1, 1 // i = range index, j = tag index @@ -315,7 +410,7 @@ func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) bool { continue } if j >= len(ts) { // 3.B: ran out of tag subtags - return false + return 0 } if utils.EqualFold(rs[i], ts[j]) { // 3.C: exact subtag match i++ @@ -324,13 +419,21 @@ func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) bool { } // 3.D: singleton barrier (one letter or digit, incl. 'x') if len(ts[j]) == 1 { - return false + return 0 } // 3.E: slide forward in the tag and try again j++ } - // 4: matched all range subtags - return true + + // 4: matched all range subtags. Rank by the number of concrete (non-"*") + // range subtags so a more specific range wins the specificity comparison. + specificity := matchWildcard + for _, sub := range rs { + if sub != "*" { + specificity++ + } + } + return specificity } // acceptsOfferType This function determines if an offer type matches a given specification. @@ -338,8 +441,11 @@ func acceptsLanguageOfferExtended(spec, offer string, _ headerParams) bool { // It gets the MIME type of the offer (either from the offer itself or by its file extension). // It checks if the offer MIME type matches the specification MIME type or if the specification is of the form /* and the offer MIME type has the same MIME type. // It checks if the offer contains every parameter present in the specification. -// Returns true if the offer type matches the specification, false otherwise. -func acceptsOfferType(spec, offerType string, specParams headerParams) bool { +// It returns the match specificity (0 = no match): "*/*" is least specific, +// then "type/*", then "type/subtype", and matched media-type parameters break +// ties so "text/html;level=1" outranks "text/html" (letting "text/html;level=1;q=0" +// override a positive "text/html"). +func acceptsOfferType(spec, offerType string, specParams headerParams) int { var offerMime, offerParams string if i := strings.IndexByte(offerType, ';'); i == -1 { @@ -351,7 +457,7 @@ func acceptsOfferType(spec, offerType string, specParams headerParams) bool { // Accept: */* if spec == "*/*" { - return paramsMatch(specParams, offerParams) + return mediaMatchSpecificity(matchMediaAny, specParams, offerParams) } var mimetype string @@ -361,9 +467,9 @@ func acceptsOfferType(spec, offerType string, specParams headerParams) bool { mimetype = utils.GetMIME(offerMime) // extension } - if spec == mimetype { + if utils.EqualFold(spec, mimetype) { // Accept: / - return paramsMatch(specParams, offerParams) + return mediaMatchSpecificity(matchMediaTypeSubtype, specParams, offerParams) } s := strings.IndexByte(mimetype, '/') @@ -371,11 +477,21 @@ func acceptsOfferType(spec, offerType string, specParams headerParams) bool { // Accept: /* if s != -1 && specSlash != -1 { if utils.EqualFold(spec[:specSlash], mimetype[:s]) && (spec[specSlash:] == "/*" || mimetype[s:] == "/*") { - return paramsMatch(specParams, offerParams) + return mediaMatchSpecificity(matchMediaTypeAny, specParams, offerParams) } } - return false + return 0 +} + +// mediaMatchSpecificity returns the specificity of a media range that matched an +// offer's type/subtype, or 0 when the media-type parameters don't match. The +// coarse class dominates; the count of matched parameters breaks ties. +func mediaMatchSpecificity(base int, specParams headerParams, offerParams string) int { + if !paramsMatch(specParams, offerParams) { + return 0 + } + return base*mediaSpecificityScale + len(specParams) } // paramsMatch returns whether offerParams contains all parameters present in specParams. @@ -417,38 +533,58 @@ func paramsMatch(specParamStr headerParams, offerParams string) bool { return allSpecParamsMatch } -// getSplicedStrList function takes a string and a string slice as an argument, divides the string into different -// elements divided by ',' and stores these elements in the string slice. -// It returns the populated string slice as an output. -// -// If the given slice hasn't enough space, it will allocate more and return. -func getSplicedStrList(headerValue string, dst []string) []string { - if headerValue == "" { - return nil - } +// joinedHeaderValue accumulates the combined value of a header's field lines +// (RFC 9110 Section 5.2). It allocates only in the rare multi-line case; the +// single-line result aliases the header storage. +type joinedHeaderValue struct { + key string + combined []byte + multi bool + seen bool +} - dst = dst[:0] - segmentStart := 0 - for i := 0; i < len(headerValue); i++ { - if headerValue[i] == ',' { - dst = append(dst, utils.TrimSpace(headerValue[segmentStart:i])) - segmentStart = i + 1 - } +func (j *joinedHeaderValue) visit(k, v []byte) { + if len(k) != len(j.key) || !utils.EqualFold(utils.UnsafeString(k), j.key) { + return } - dst = append(dst, utils.TrimSpace(headerValue[segmentStart:])) + j.seen = true + j.combined, j.multi = headerlist.JoinNext(j.combined, v, j.multi) +} - return dst +// peekJoinedRequestHeader returns the combined value of every field line for +// key in a single pass over the request headers. Unlike PeekAll it performs no +// per-call key normalization. Concrete (non-generic) so the visitor stays on +// the stack. +func peekJoinedRequestHeader(h *fasthttp.RequestHeader, key string) []byte { + value, _ := lookupJoinedRequestHeader(h, key) + return value } -func joinHeaderValues(headers [][]byte) []byte { - switch len(headers) { - case 0: - return nil - case 1: - return headers[0] - default: - return bytes.Join(headers, []byte{','}) - } +// lookupJoinedRequestHeader is peekJoinedRequestHeader that also reports whether +// the request has a field line for key, which an empty value does not tell. +func lookupJoinedRequestHeader(h *fasthttp.RequestHeader, key string) ([]byte, bool) { + j := joinedHeaderValue{key: key} + // VisitAll (not the replacement All) keeps this zero-alloc: All returns + // an iterator closure that escapes to the heap on every call. The SA1019 + // deprecation is suppressed for helpers.go in .golangci.yml. + // + // VisitAllInOrder is deliberately not used: it reparses rawHeaders, which + // only holds headers read off the wire, so headers set programmatically + // (e.g. by net/http adaptors) would be missed entirely. VisitAll already + // preserves the relative order of repeated field lines sharing a key, + // which is all this helper needs; it only reorders across distinct keys. + h.VisitAll(j.visit) + return j.combined, j.seen +} + +// peekJoinedResponseHeader is peekJoinedRequestHeader for response headers. +func peekJoinedResponseHeader(h *fasthttp.ResponseHeader, key string) ([]byte, bool) { + j := joinedHeaderValue{key: key} + // VisitAll (not the replacement All) keeps this zero-alloc: All returns + // an iterator closure that escapes to the heap on every call. The SA1019 + // deprecation is suppressed for helpers.go in .golangci.yml. + h.VisitAll(j.visit) + return j.combined, j.multi } func unescapeHeaderValue(v []byte) ([]byte, error) { @@ -489,27 +625,33 @@ func forEachMediaRange(header []byte, functor func([]byte)) { n := 0 header = utils.TrimLeft(header, ' ') quotes := 0 - escaping := false if hasDQuote { // Complex case. We need to keep track of quotes and quoted-pairs (i.e., characters escaped with \ ) + // Only ',', '"' and '\\' can change state, so jump between them + // instead of visiting every byte. loop: for n < len(header) { + i := utils.IndexAny3(header[n:], ',', '"', '\\') + if i == -1 { + n = len(header) + break + } + n += i switch header[n] { case ',': if quotes%2 == 0 { break loop } case '"': - if !escaping { - quotes++ + quotes++ + default: // '\\' + if quotes%2 == 1 && n+1 < len(header) { + // A quoted-pair escapes exactly the next byte + // (RFC 9110 §5.6.4); consume it so an escaped + // quote is not mistaken for a closing quote. + n++ } - case '\\': - if quotes%2 == 1 { - escaping = !escaping - } - default: - // all other characters are ignored } n++ } @@ -538,7 +680,7 @@ var headerParamPool = sync.Pool{ } // getOffer return valid offer for header negotiation. -func getOffer(header []byte, isAccepted func(spec, offer string, specParams headerParams) bool, offers ...string) string { +func getOffer(header []byte, isAccepted func(spec, offer string, specParams headerParams) int, offers ...string) string { if len(offers) == 0 { return "" } @@ -548,6 +690,9 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head acceptedTypes := make([]acceptedType, 0, 8) order := 0 + // Whether every range carries the same weight, in which case first-match selection is exact. + uniformQuality := true + var firstQuality float64 // Parse header and get accepted types with their quality and specificity // See: https://www.rfc-editor.org/rfc/rfc9110#name-content-negotiation-fields @@ -562,7 +707,12 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head // Optimized quality parsing qIndex := i + 3 if bytes.HasPrefix(accept[i:], semicolonQEquals) && bytes.IndexByte(accept[qIndex:], ';') == -1 { - if q, err := fasthttp.ParseUfloat(accept[qIndex:]); err == nil { + // A list element may be followed by optional whitespace before + // the comma (RFC 9110 §5.6.1.2), and forEachMediaRange only + // trims the leading side. Trim the trailing side here so the + // weight still parses; otherwise the error below is swallowed + // and an explicit q=0 rejection silently becomes q=1. + if q, err := fasthttp.ParseUfloat(utils.TrimSpace(accept[qIndex:])); err == nil { quality = q } } else { @@ -571,7 +721,9 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head delete(params, k) } fasthttp.VisitHeaderParams(accept[i:], func(key, value []byte) bool { - if len(key) == 1 && key[0] == 'q' { + // The weight parameter name "q" is case-insensitive + // (RFC 9110 §12.4.2). + if len(key) == 1 && (key[0] == 'q' || key[0] == 'Q') { if q, err := fasthttp.ParseUfloat(value); err == nil { quality = q } @@ -586,12 +738,6 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head return true }) } - - // Skip this accept type if quality is 0.0 - // See: https://www.rfc-editor.org/rfc/rfc9110#quality.values - if quality == 0.0 { - return - } } spec = utils.TrimSpace(spec) @@ -613,6 +759,12 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head specificity = 4 } + if order == 1 { + firstQuality = quality + } else if quality != firstQuality { + uniformQuality = false + } + // Add to accepted types acceptedTypes = append(acceptedTypes, acceptedType{ spec: utils.UnsafeString(spec), @@ -628,25 +780,87 @@ func getOffer(header []byte, isAccepted func(spec, offer string, specParams head sortAcceptedTypes(acceptedTypes) } - // Find the first offer that matches the accepted types - for _, acceptedType := range acceptedTypes { + // Find the best offer that matches the accepted types. Per RFC 9110 §12.5.1 + // the most specific matching range determines an offer's weight, and q=0 rejects it. + result := "" + switch { + case uniformQuality && firstQuality == 0: + // Every range rejects: nothing is acceptable. + case uniformQuality: + // Fast path: with equal weights the first matching range in preference order wins. + result, _ = firstMatchingOffer(acceptedTypes, isAccepted, offers) + default: + // The first match stands unless a more specific range later demotes + // that offer; only such a demotion can let another offer win. + offer, rank := firstMatchingOffer(acceptedTypes, isAccepted, offers) + if offer == "" { + break + } + // The ranges before rank matched nothing, so only the rest can demote. + if quality, _, ok := offerQuality(acceptedTypes[rank:], isAccepted, offer); ok && quality == acceptedTypes[rank].quality { + result = offer + break + } + + // Resolve each offer from its most specific matching range and keep the heaviest. + var bestQuality float64 + bestRank := 0 for _, offer := range offers { if offer == "" { continue } - if isAccepted(acceptedType.spec, offer, acceptedType.params) { - if acceptedType.params != nil { - headerParamPool.Put(acceptedType.params) - } - return offer + quality, rank, ok := offerQuality(acceptedTypes, isAccepted, offer) + if !ok { + continue + } + if result == "" || quality > bestQuality || (quality == bestQuality && rank < bestRank) { + result, bestQuality, bestRank = offer, quality, rank } } - if acceptedType.params != nil { - headerParamPool.Put(acceptedType.params) + } + + for i := range acceptedTypes { + if acceptedTypes[i].params != nil { + headerParamPool.Put(acceptedTypes[i].params) } } - return "" + return result +} + +// firstMatchingOffer returns the first offer matched by the first range that +// matches any offer, with that range's index; "" when nothing matches. +func firstMatchingOffer(types []acceptedType, isAccepted func(spec, offer string, specParams headerParams) int, offers []string) (offer string, rank int) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the pair for clarity + for i := range types { + for _, candidate := range offers { + if candidate != "" && isAccepted(types[i].spec, candidate, types[i].params) > 0 { + return candidate, i + } + } + } + return "", 0 +} + +// offerQuality resolves an offer against the ranges, in preference order: the +// weight of the most specific matching range (RFC 9110 §12.5.1), an explicit +// q=0 winning among equally specific ones. rank is the first matching range's +// position; ok is false when nothing matches or the weight is 0. +func offerQuality(types []acceptedType, isAccepted func(spec, offer string, specParams headerParams) int, offer string) (quality float64, rank int, ok bool) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the results for clarity + bestSpecificity := 0 + for i := range types { + specificity := isAccepted(types[i].spec, offer, types[i].params) + if specificity == 0 { + continue + } + if bestSpecificity == 0 { + rank = i + } + if specificity > bestSpecificity || (specificity == bestSpecificity && types[i].quality == 0) { + bestSpecificity = specificity + quality = types[i].quality + } + } + return quality, rank, bestSpecificity > 0 && quality > 0 } // sortAcceptedTypes sorts accepted types by quality and specificity, preserving order of equal elements @@ -673,79 +887,48 @@ func sortAcceptedTypes(at []acceptedType) { } } -// normalizeEtag validates an entity tag and returns the -// value without quotes. weak is true if the tag has the "W/" prefix. -func normalizeEtag(t string) (value string, weak, ok bool) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the parsed ETag components - weak = strings.HasPrefix(t, "W/") - if weak { - t = t[2:] +// getEncodingOffer is getOffer for Accept-Encoding, where "identity" is also +// acceptable unless the field excludes it (RFC 9110 §12.5.3). An unlisted +// identity ranks below every coding the field lists. +func getEncodingOffer(header []byte, offers []string) string { + if offer := getOffer(header, acceptsOffer, offers...); offer != "" { + return offer } - - if len(t) < 2 || t[0] != '"' || t[len(t)-1] != '"' { - return "", weak, false + // getOffer has already weighed an identity the field mentions. + if identity := identityOffer(offers); identity != "" && !identityListed(header) { + return identity } - return t[1 : len(t)-1], weak, true + return "" } -// matchEtag performs a weak comparison of entity tags according to -// RFC 9110 §8.8.3.2. The weak indicator ("W/") is ignored, but both tags must -// be properly quoted. Invalid tags result in a mismatch. -func matchEtag(s, etag string) bool { - n1, _, ok1 := normalizeEtag(s) - n2, _, ok2 := normalizeEtag(etag) - if !ok1 || !ok2 { - return false +// identityOffer returns the offer naming no content coding, or "". +func identityOffer(offers []string) string { + for _, offer := range offers { + // The length check first: EqualFold is a call, and most offers are not identity. + if len(offer) == len(StrIdentity) && utils.EqualFold(offer, StrIdentity) { + return offer + } } - - return n1 == n2 + return "" } -// matchEtagStrong performs a strong entity-tag comparison following -// RFC 9110 §8.8.3.1. A weak tag never matches a strong one, even if the quoted -// values are identical. -func matchEtagStrong(s, etag string) bool { - n1, w1, ok1 := normalizeEtag(s) - n2, w2, ok2 := normalizeEtag(etag) - if !ok1 || !ok2 || w1 || w2 { - return false +// identityListed reports whether the field mentions identity or the "*" wildcard. +func identityListed(header []byte) bool { + for element := range headerlist.All(utils.UnsafeString(header)) { + coding, _, _ := utils.CutByte(element, ';') + coding = utils.TrimSpace(coding) + if coding == "*" || utils.EqualFold(coding, StrIdentity) { + return true + } } - - return n1 == n2 + return false } // isEtagStale reports whether a response with the given ETag would be considered // stale when presented with the raw If-None-Match header value. Comparison is // weak as defined by RFC 9110 §8.8.3.2. func (app *App) isEtagStale(etag string, noneMatchBytes []byte) bool { - var start, end int - header := utils.TrimSpace(app.toString(noneMatchBytes)) - - // Short-circuit the wildcard case: "*" never counts as stale. - if header == "*" { - return false - } - - // Adapted from: - // https://github.com/jshttp/fresh/blob/master/index.js#L110 - for i := range noneMatchBytes { - switch noneMatchBytes[i] { - case 0x20: - if start == end { - start = i + 1 - end = i + 1 - } - case 0x2c: - if matchEtag(app.toString(noneMatchBytes[start:end]), etag) { - return false - } - start = i + 1 - end = i + 1 - default: - end = i + 1 - } - } - - return !matchEtag(app.toString(noneMatchBytes[start:end]), etag) + return !etagpkg.AnyMatch(app.toString(noneMatchBytes), etag) } func parseAddr(raw string) (host, port string) { //nolint:nonamedreturns // gocritic unnamedResult requires naming host and port parts for clarity @@ -838,6 +1021,46 @@ func matchNoCacheToken(s string, i int) bool { (b[7]|asciiCaseFold) == 'e' } +// sameFunc reports whether a is the non-nil callback b, which == cannot say for +// funcs: it compares the closure each value points to. +func sameFunc(a, b func(*fasthttp.RequestHeader) fasthttp.RequestConfig) bool { + return a != nil && *(*unsafe.Pointer)(unsafe.Pointer(&a)) == *(*unsafe.Pointer)(unsafe.Pointer(&b)) //nolint:gosec // funcs are only comparable to nil +} + +// bothFramingFields reports whether a request carries Content-Length and +// Transfer-Encoding (RFC 9112 §6.1). fasthttp keeps no trace of the second one in +// the length it reports: chunked wins and the Content-Length value is dropped, and +// "identity" is ignored, leaving the Content-Length framing. +func bothFramingFields(h *fasthttp.RequestHeader) bool { + switch length := h.ContentLength(); { + case length == -1: // chunked + return hasHeaderField(h.RawHeaders(), HeaderContentLength) + case length >= 0: // framed by Content-Length + return hasHeaderField(h.RawHeaders(), HeaderTransferEncoding) + } + return false // -2: neither field +} + +// hasHeaderField reports whether raw, a request's header block, has a line for the +// field name, which is the only place left to look for what fasthttp drops or +// ignores. Whitespace before the colon is not matched: fasthttp rejects that +// request. +func hasHeaderField(raw []byte, name string) bool { + for len(raw) > 0 { + line := raw + if i := bytes.IndexByte(raw, '\n'); i >= 0 { + line, raw = raw[:i], raw[i+1:] + } else { + raw = nil + } + if len(line) > len(name) && line[len(name)] == ':' && + utils.EqualFold(utils.UnsafeString(line[:len(name)]), name) { + return true + } + } + return false +} + var errTestConnClosed = errors.New("testConn is closed") type testConn struct { @@ -894,10 +1117,6 @@ func toStringImmutable(b []byte) string { return string(b) } -func toBytesImmutable(s string) []byte { - return []byte(s) -} - // HTTP methods and their unique INTs func (app *App) methodInt(s string) int { // For better performance @@ -931,10 +1150,54 @@ func (app *App) methodInt(s string) int { return slices.Index(app.config.RequestMethods, s) } +// routesForMethod returns the routes registered for an HTTP method, or nil if +// the app does not serve it. Use this instead of indexing another app's stack +// with your own method index: RequestMethods is configurable, so two apps' +// tables can differ in both order and length. +func (app *App) routesForMethod(method string) []*Route { + m := app.methodInt(method) + if m < 0 || m >= len(app.stack) { + return nil + } + + return app.stack[m] +} + func (app *App) method(methodInt int) string { + // methodInt is -1 for methods not registered in RequestMethods (the + // router responds 501 before dispatch, but contexts acquired directly + // via AcquireCtx can still carry one); never index with it. + if methodInt < 0 || methodInt >= len(app.config.RequestMethods) { + return "" + } return app.config.RequestMethods[methodInt] } +// The status line carries three digits (RFC 9112 §4). RFC 9110 §15 only defines +// 100..599, but 600..999 is still well-formed, so it is let through. +const ( + minStatusCode = 100 + maxStatusCode = 999 +) + +// validStatus returns status if it fits a status line, else 500. fasthttp would +// write 99 or 1000 as a malformed line and 0 as a 200. +func validStatus(status int) int { + if status < minStatusCode || status > maxStatusCode { + return invalidStatus(status) + } + return status +} + +// invalidStatus logs the status and returns the one sent instead. It stays out of +// line so that validStatus, and Status with it, can be inlined. +// +//go:noinline +func invalidStatus(status int) int { + log.Errorf("fiber: status code %d is not a three-digit HTTP status, sending %d instead", status, StatusInternalServerError) + return StatusInternalServerError +} + // IsMethodSafe reports whether the HTTP method is considered safe. // See https://datatracker.ietf.org/doc/html/rfc9110#section-9.2.1 func IsMethodSafe(m string) bool { @@ -1111,3 +1374,40 @@ type GenericTypeIntegerUnsigned interface { type GenericTypeFloat interface { float32 | float64 } + +// hasMediaType reports whether ct names mime in its canonical spelling, alone +// or followed by parameters, which is what the folding below would produce. +func hasMediaType(ct []byte, mime string) bool { + if len(ct) < len(mime) || string(ct[:len(mime)]) != mime { + return false + } + return len(ct) == len(mime) || ct[len(mime)] == ';' || ct[len(mime)] == ' ' +} + +// bindMediaType returns the request's media type, lowered for comparison against +// the MIME constants. The request's own bytes are folded only for a form, the +// one case needing it in place; anything else is compared on a copy. +func bindMediaType(h *fasthttp.RequestHeader) string { + ct := h.ContentType() + + // The canonical spellings need no folding or parsing, so they answer before + // the case-insensitive walk below; every other spelling still takes it. The + // form type is matched bare because its parameters are folded in place for + // fasthttp's own parser, which the walk keeps doing. + if hasMediaType(ct, MIMEApplicationJSON) { + return MIMEApplicationJSON + } + if string(ct) == MIMEApplicationForm { + return MIMEApplicationForm + } + + if mediatype.IsForm(ct) { + raw := utils.UnsafeString(mediatype.NormalizeRequestContentType(h)) + return binder.FilterFlags(utils.ParseVendorSpecificContentType(raw)) + } + + // ToLower returns its input unchanged when there is nothing to fold, so the + // common path costs no allocation. + lowered := utilsstrings.ToLower(utils.UnsafeString(ct)) + return binder.FilterFlags(utils.ParseVendorSpecificContentType(lowered)) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/hooks.go b/src/vendor/github.com/gofiber/fiber/v3/hooks.go index 13a5e317..e1ee77f5 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/hooks.go +++ b/src/vendor/github.com/gofiber/fiber/v3/hooks.go @@ -427,8 +427,34 @@ func (h *Hooks) executeOnPostStartupMessageHooks(data *PostStartupMessageData) e return nil } +// snapshotOnPreShutdown copies the registered pre-shutdown hooks under the app +// mutex, so a hook may register others without deadlocking on the iteration. +func (h *Hooks) snapshotOnPreShutdown() []OnPreShutdownHandler { + if h.app == nil { + return h.onPreShutdown + } + h.app.mutex.Lock() + defer h.app.mutex.Unlock() + + return append([]OnPreShutdownHandler(nil), h.onPreShutdown...) +} + +// snapshotOnPostShutdown copies the registered post-shutdown hooks under the +// app mutex, for the same reason as snapshotOnPreShutdown. +func (h *Hooks) snapshotOnPostShutdown() []OnPostShutdownHandler { + if h.app == nil { + return h.onPostShutdown + } + h.app.mutex.Lock() + defer h.app.mutex.Unlock() + + return append([]OnPostShutdownHandler(nil), h.onPostShutdown...) +} + func (h *Hooks) executeOnPreShutdownHooks() { - for _, v := range h.onPreShutdown { + // Snapshot under the app mutex the registration appends under: shutdown no + // longer holds it while draining, so iterating the slice directly races. + for _, v := range h.snapshotOnPreShutdown() { if err := v(); err != nil { log.Errorf("failed to call pre shutdown hook: %v", err) } @@ -436,7 +462,7 @@ func (h *Hooks) executeOnPreShutdownHooks() { } func (h *Hooks) executeOnPostShutdownHooks(err error) { - for _, v := range h.onPostShutdown { + for _, v := range h.snapshotOnPostShutdown() { if hookErr := v(err); hookErr != nil { log.Errorf("failed to call post shutdown hook: %v", hookErr) } diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/appconfig/appconfig.go b/src/vendor/github.com/gofiber/fiber/v3/internal/appconfig/appconfig.go new file mode 100644 index 00000000..668d23a0 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/appconfig/appconfig.go @@ -0,0 +1,46 @@ +// Package appconfig hands request hot paths the few Config bits they read on +// every call, without the copy App.Config returns by value. +// +// Config is over 600 bytes, so reading one boolean out of it cost 25ns against +// 2ns for the App call itself. Package fiber installs a reader that takes the +// bits off the app directly; it cannot be done from here, because config is +// unexported and importing fiber would be a cycle. +package appconfig + +import ( + "sync" +) + +// Hot is the subset of fiber.Config that request hot paths read. +type Hot struct { + Immutable bool + DisableHeaderNormalizing bool + UnescapePath bool +} + +var ( + // read answers Of. Every caller holds a fiber.Ctx and so has imported + // fiber, whose init is ordered before them, and none can see this one. + read = func(any) Hot { return Hot{} } + + // readOnce makes "installed once, before main" true of the code rather + // than of a comment: without it any package could retarget what Immutable + // means, and could do it while requests are being served. + readOnce sync.Once +) + +// SetReader installs the function Of answers with. The first call wins, later +// calls and a nil reader are ignored. +// +// Package fiber calls this from its init. Nothing else should call it. +func SetReader(fn func(any) Hot) { + if fn == nil { + return + } + readOnce.Do(func() { read = fn }) +} + +// Of returns the Hot bits of app, which must be a *fiber.App. +func Of(app any) Hot { + return read(app) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/byterange/byterange.go b/src/vendor/github.com/gofiber/fiber/v3/internal/byterange/byterange.go new file mode 100644 index 00000000..f650cc16 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/byterange/byterange.go @@ -0,0 +1,204 @@ +// Package byterange adds the Range and If-Range rules (RFC 9110 §13.1.5, §14.2) +// that fasthttp's file server lacks: it refuses several ranges with 416, takes +// only a lower-case "bytes" unit, applies Range to HEAD and ignores If-Range. +// It is shared by Ctx.SendFile and the static middleware. +package byterange + +import ( + "bytes" + "strings" + "time" + + "github.com/gofiber/utils/v2" + "github.com/valyala/fasthttp" +) + +const ( + // unitBytes is the only unit the file server knows. Units are + // case-insensitive (RFC 9110 §14.1), its parser is not. + unitBytes = "bytes" + + weakPrefix = "W/" + + // A Last-Modified time is implicitly weak unless the server knows the file did + // not change twice within that second (§8.8.2.2), which it cannot. Two seconds + // of age only rules out a file still being written; one rewritten within the + // second a client fetched it in still matches that client's date. + strongAfter = 2 * time.Second +) + +// verdict is what to do with a Range field before the file server sees it. +type verdict int + +const ( + pass verdict = iota // as is; the file server rejects what it cannot parse + rewrite // spelled the way the file server parses it + ignore // without the field, so the whole file is sent +) + +// plan is what to do with a Range field; for rewrite, canonical is the field to use. +type plan struct { + canonical []byte + verdict verdict +} + +// classify decides what to do with a Range field, building a rewrite in dst. +func classify(dst, field []byte) plan { + unit, set, found := utils.CutByte(field, '=') + unit = utils.TrimSpace(unit) + if !found || len(unit) == 0 { + return plan{verdict: pass} + } + // A Range with an unknown unit must be ignored (§14.2). + if !utils.EqualFold(utils.UnsafeString(unit), unitBytes) { + return plan{verdict: ignore} + } + + // The file server answers one range. Several are ignored, which §14.2 allows, + // rather than refused with a 416. + var spec []byte + for set != nil { + var element []byte + element, set, found = utils.CutByte(set, ',') + if !found { + set = nil + } + // Empty list elements are ignored (§5.6.1.2). + element = utils.TrimSpace(element) + if len(element) == 0 { + continue + } + if spec != nil { + return plan{verdict: ignore} + } + spec = element + } + if spec == nil { + return plan{verdict: pass} + } + + canonical := append(append(dst[:0], unitBytes...), '=') + canonical = append(canonical, spec...) + if bytes.Equal(canonical, field) { + return plan{verdict: pass} + } + return plan{canonical: canonical, verdict: rewrite} +} + +// Wrap returns handler, a fasthttp file server with byte ranges enabled, with the +// Range field handled as RFC 9110 asks. The field is ignored, and the whole file +// sent, for a non-GET request, a unit other than "bytes", several ranges, or an +// If-Range that does not match the Last-Modified the file server sent. +func Wrap(handler fasthttp.RequestHandler) fasthttp.RequestHandler { + return func(ctx *fasthttp.RequestCtx) { + serveAt(ctx, handler, time.Now) + } +} + +// serveAt is the handler Wrap returns, with the clock that ages a Last-Modified given. +func serveAt(ctx *fasthttp.RequestCtx, handler fasthttp.RequestHandler, now func() time.Time) { + header := &ctx.Request.Header + field := header.Peek(fasthttp.HeaderRange) + if len(field) == 0 { + handler(ctx) + return + } + + // Only GET has range semantics (§14.2). + var buf [64]byte + p := plan{verdict: ignore} + if ctx.IsGet() { + p = classify(buf[:0], field) + } + + ifRange := header.Peek(fasthttp.HeaderIfRange) + if len(ifRange) == 0 || p.verdict == ignore { + p.serve(ctx, handler) + return + } + // The value is copied because serving rearranges the request header's storage. + serveConditional(ctx, handler, p, utils.CopyBytes(ifRange), now) +} + +// serve runs handler for the Range field as the plan has it. +func (p plan) serve(ctx *fasthttp.RequestCtx, handler fasthttp.RequestHandler) { + switch p.verdict { + case pass: + handler(ctx) + case rewrite: + serveWithField(ctx, handler, p.canonical) + default: + serveWithField(ctx, handler, nil) + } +} + +// serveWithField runs handler with the Range field set to value, or removed when +// value is nil, and puts the original back for the rest of the chain. +func serveWithField(ctx *fasthttp.RequestCtx, handler fasthttp.RequestHandler, value []byte) { + header := &ctx.Request.Header + original := utils.CopyBytes(header.Peek(fasthttp.HeaderRange)) + defer header.SetBytesV(fasthttp.HeaderRange, original) + + if value == nil { + header.Del(fasthttp.HeaderRange) + } else { + header.SetBytesV(fasthttp.HeaderRange, value) + } + handler(ctx) +} + +// serveConditional serves a Range that comes with an If-Range. Only the response +// has the validators to judge it by, so when they do not match, the whole file is +// served in its place. +func serveConditional(ctx *fasthttp.RequestCtx, handler fasthttp.RequestHandler, p plan, ifRange []byte, now func() time.Time) { + // A refusal wipes the response, so the headers the caller had set are kept to + // start the second attempt from. + callerHeader := &fasthttp.ResponseHeader{} + ctx.Response.Header.CopyTo(callerHeader) + + p.serve(ctx, handler) + + switch ctx.Response.StatusCode() { + case fasthttp.StatusPartialContent: + if !ifRangeMatches(ifRange, &ctx.Response, now()) { + serveWhole(ctx, handler, callerHeader) + } + case fasthttp.StatusRequestedRangeNotSatisfiable: + // The 416 has no validators. The whole file has, and is the answer when + // If-Range does not match. + serveWhole(ctx, handler, callerHeader) + if ctx.Response.StatusCode() == fasthttp.StatusOK && ifRangeMatches(ifRange, &ctx.Response, now()) { + ctx.Error("Range Not Satisfiable", fasthttp.StatusRequestedRangeNotSatisfiable) + } + } +} + +// serveWhole discards the response and has handler send the whole file, from the +// headers the caller had set. +func serveWhole(ctx *fasthttp.RequestCtx, handler fasthttp.RequestHandler, callerHeader *fasthttp.ResponseHeader) { + ctx.Response.ResetBody() + callerHeader.CopyTo(&ctx.Response.Header) + serveWithField(ctx, handler, nil) +} + +// ifRangeMatches evaluates If-Range against the file server's response (§13.1.5): +// an entity-tag must equal a strong ETag, a date the exact, strong Last-Modified, +// judged at now. The file server sends no ETag of its own, and a weak tag never matches. +func ifRangeMatches(ifRange []byte, resp *fasthttp.Response, now time.Time) bool { + ifRange = utils.TrimSpace(ifRange) + if len(ifRange) == 0 { + return false + } + + if ifRange[0] == '"' || strings.HasPrefix(utils.UnsafeString(ifRange), weakPrefix) { + etag := resp.Header.Peek(fasthttp.HeaderETag) + return ifRange[0] == '"' && len(etag) > 0 && etag[0] == '"' && bytes.Equal(etag, ifRange) + } + + lastModified := resp.Header.Peek(fasthttp.HeaderLastModified) + if !bytes.Equal(lastModified, ifRange) { + return false + } + modified, err := fasthttp.ParseHTTPDate(lastModified) + return err == nil && now.Sub(modified) >= strongAfter +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/cookie/samesite.go b/src/vendor/github.com/gofiber/fiber/v3/internal/cookie/samesite.go new file mode 100644 index 00000000..edf2ad10 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/cookie/samesite.go @@ -0,0 +1,78 @@ +// Package cookie centralizes cookie policy shared by Fiber core and middleware. +package cookie + +import ( + "net/http" + + "github.com/gofiber/utils/v2" + "github.com/valyala/fasthttp" +) + +// SameSite mode names accepted by Fiber's cookie APIs. +const ( + SameSiteDisabled = "disabled" + SameSiteLax = "Lax" + SameSiteStrict = "Strict" + SameSiteNone = "None" +) + +// SameSite maps one Fiber SameSite mode to the cookie implementations Fiber +// validates with and writes through. +type SameSite struct { + HTTPMode http.SameSite + FastHTTPMode fasthttp.CookieSameSite + RequiresSecure bool +} + +// ParseSameSite parses value case-insensitively. Unsupported values return the +// Lax mapping and false, allowing callers to choose fallback or rejection. +func ParseSameSite(value string) (SameSite, bool) { + switch { + case utils.EqualFold(value, SameSiteDisabled): + return SameSite{ + HTTPMode: 0, + FastHTTPMode: fasthttp.CookieSameSiteDisabled, + }, true + case utils.EqualFold(value, SameSiteLax): + return SameSite{ + HTTPMode: http.SameSiteLaxMode, + FastHTTPMode: fasthttp.CookieSameSiteLaxMode, + }, true + case utils.EqualFold(value, SameSiteStrict): + return SameSite{ + HTTPMode: http.SameSiteStrictMode, + FastHTTPMode: fasthttp.CookieSameSiteStrictMode, + }, true + case utils.EqualFold(value, SameSiteNone): + return SameSite{ + HTTPMode: http.SameSiteNoneMode, + FastHTTPMode: fasthttp.CookieSameSiteNoneMode, + RequiresSecure: true, + }, true + default: + return SameSite{ + HTTPMode: http.SameSiteLaxMode, + FastHTTPMode: fasthttp.CookieSameSiteLaxMode, + }, false + } +} + +// FormatSameSite names the Fiber SameSite mode a fasthttp cookie carries, +// inverting ParseSameSite for every mode Fiber writes. fasthttp's default mode +// has no Fiber name and returns an empty string. +func FormatSameSite(mode fasthttp.CookieSameSite) string { + switch mode { + case fasthttp.CookieSameSiteDisabled: + return SameSiteDisabled + case fasthttp.CookieSameSiteLaxMode: + return SameSiteLax + case fasthttp.CookieSameSiteStrictMode: + return SameSiteStrict + case fasthttp.CookieSameSiteNoneMode: + return SameSiteNone + default: + // fasthttp's default mode lands here: it emits the attribute with no + // value, which is not one of the modes Fiber names. + return "" + } +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/etag/etag.go b/src/vendor/github.com/gofiber/fiber/v3/internal/etag/etag.go new file mode 100644 index 00000000..f4f3827b --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/etag/etag.go @@ -0,0 +1,102 @@ +// Package etag parses and compares HTTP entity tags (RFC 9110 Section 8.8.3). +// It is shared by the core conditional-request path (Ctx.Fresh) and the ETag +// middleware, which previously carried divergent parsers: the middleware split +// If-None-Match on every comma, mis-parsing an opaque-tag that contains one. +package etag + +import ( + "slices" + "strings" + + "github.com/gofiber/fiber/v3/internal/headerlist" + "github.com/gofiber/utils/v2" +) + +// weakPrefix marks a weak entity tag (RFC 9110 Section 8.8.3). +const weakPrefix = "W/" + +// Parse validates an entity tag and returns the value without quotes. +// weak is true if the tag has the "W/" prefix. +func Parse(t string) (value string, weak, ok bool) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the parsed ETag components + weak = strings.HasPrefix(t, weakPrefix) + if weak { + t = t[len(weakPrefix):] + } + + if len(t) < 2 || t[0] != '"' || t[len(t)-1] != '"' { + return "", weak, false + } + return t[1 : len(t)-1], weak, true +} + +// Match performs a weak comparison of entity tags according to +// RFC 9110 Section 8.8.3.2. The weak indicator ("W/") is ignored, but both tags +// must be properly quoted. Invalid tags result in a mismatch. +func Match(s, etag string) bool { + n1, _, ok1 := Parse(s) + n2, _, ok2 := Parse(etag) + if !ok1 || !ok2 { + return false + } + + return n1 == n2 +} + +// MatchStrong performs a strong entity-tag comparison following +// RFC 9110 Section 8.8.3.1. A weak tag never matches a strong one, even if the +// quoted values are identical. +func MatchStrong(s, etag string) bool { + n1, w1, ok1 := Parse(s) + n2, w2, ok2 := Parse(etag) + if !ok1 || !ok2 || w1 || w2 { + return false + } + + return n1 == n2 +} + +// Split returns the entity tags in a raw If-None-Match or If-Match field value. +// A comma inside a quoted opaque-tag does not separate it (RFC 9110 +// Section 8.8.3), and empty list elements are skipped. Returns nil for no tags. +func Split(header string) []string { + if header == "" { + return nil + } + + // One more than the commas is an upper bound: a comma inside a quoted + // opaque-tag only over-estimates, never under. + tags := slices.AppendSeq(make([]string, 0, strings.Count(header, ",")+1), headerlist.AllQuoted(header)) + if len(tags) == 0 { + return nil + } + return tags +} + +// AnyMatch reports whether any entity tag in the raw If-None-Match field value +// matches etag. Comparison is weak as defined by RFC 9110 Section 8.8.3.2, and +// "*" matches every entity tag. An empty field value matches nothing. +func AnyMatch(header, etag string) bool { + rest := utils.TrimSpace(header) + + // Short-circuit the wildcard case: "*" matches any entity tag. + if rest == "*" { + return true + } + + // etag is the same for every element, so parse it once rather than through + // Match on each. An unparseable one matches nothing (RFC 9110 8.8.3.2). + want, _, ok := Parse(etag) + if !ok { + return false + } + + // Commas inside the opaque-tag do not separate: etagc permits "," within the + // quoted tag (RFC 9110 Section 8.8.3), so `"v1,v2"` is one entity tag. + for tag := range headerlist.AllQuoted(header) { + if got, _, ok := Parse(tag); ok && got == want { + return true + } + } + + return false +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/fieldname/fieldname.go b/src/vendor/github.com/gofiber/fiber/v3/internal/fieldname/fieldname.go new file mode 100644 index 00000000..eb72c64b --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/fieldname/fieldname.go @@ -0,0 +1,314 @@ +// Package fieldname reads and removes HTTP header fields by name +// case-insensitively (RFC 9110 §5.1). +// +// fasthttp's Peek, PeekAll and Del are byte-exact, which finds every line only +// while it canonicalizes the key; under DisableHeaderNormalizing the store keeps +// the spelling the peer sent, which for HTTP/2 and 3 is lower case. +// +// canonical says whether the caller knows the keys to be canonical — fasthttp +// keeps that private, so it is passed in; see headerlookup.Canonical. +package fieldname + +import ( + "iter" + + "github.com/gofiber/utils/v2" + "github.com/valyala/fasthttp" +) + +// Peeker is the part of fasthttp's headers needed to read field lines by name. +type Peeker interface { + Peek(key string) []byte + PeekAll(key string) [][]byte + All() iter.Seq2[[]byte, []byte] + // VisitAll is deprecated in fasthttp in favor of All, but All builds an + // iterator per call while this walks the store directly. Kept for the reads + // that run per request and do not need to stop early. + VisitAll(f func(key, value []byte)) +} + +// Deleter is the part of fasthttp's headers needed to remove a field by name. +type Deleter interface { + Del(key string) + PeekAll(key string) [][]byte + All() iter.Seq2[[]byte, []byte] +} + +// Lines returns every field line stored under name. The walk replaces the +// byte-exact lookup rather than backing it up: a message can carry both +// spellings, and an empty canonical line would hide the value beside it. +// +//nolint:revive // flag-parameter: canonical is a property of the header store, not a mode of operation +func Lines(h Peeker, name string, canonical bool) [][]byte { + if canonical { + // PeekAll hands back the header's own slice without allocating. + return h.PeekAll(name) + } + + // Walked rather than ranged: this runs per key header on every cacheable + // request, and All's iterator costs more than the match itself does. + var values [][]byte + h.VisitAll(func(k, v []byte) { + if utils.EqualFold(utils.UnsafeString(k), name) { + values = append(values, v) + } + }) + return values +} + +// First returns the first field line stored under name that holds anything, or +// nil if there is none. The names fasthttp keeps in a slot of their own are +// unaffected either way: every spelling is routed into the slot on the way in. +// +// Empty lines are stepped over rather than answered with, because a message can +// carry the name more than once and Peek reports the first line whether or not +// it holds a value: an empty "Cache-Control:" ahead of "Cache-Control: private" +// read as a response saying nothing about caching. A field line that is present +// and empty says nothing a caller can act on, so nothing is lost by looking past +// it for one that does. +// +// Repetition itself is left to the caller to judge, because what it means +// depends on the field: a response may carry Cache-Control twice and mean the +// list, while a second Origin or Authorization line is malformed and cannot be +// resolved by picking one. headerlookup.Value refuses that case for the request +// fields where it arises. +// +//nolint:revive // flag-parameter: canonical is a property of the header store +func First(h Peeker, name string, canonical bool) []byte { + if canonical { + v := Peek(h, name) + if len(v) > 0 { + return v + } + if v == nil { + // Nothing is stored under the name, so there is nothing beside it + // to find and the walk below is skipped: a nil answer means absent, + // a non-nil empty one means a line that is present and empty. That + // distinction is fasthttp's to keep, so Test_First_EmptyLineIsNotNil + // pins it — if it ever stops holding, that test says so rather than + // this quietly reverting to reading only the first line. + return nil + } + + // Reached only for a field that is present and empty, which is the shape + // being guarded against rather than one anything sends by accident. + // PeekAll costs no allocation and resolves the slotted names. + for _, v := range h.PeekAll(name) { + if len(v) > 0 { + return v + } + } + return nil + } + + // Split out rather than written below: All's iterator is heap-allocated + // where the compiler cannot see the branch is dead, so holding it in this + // function cost the canonical path an allocation it never used. + return firstFold(h, name) +} + +// firstFold answers First for a store whose field names are spelled however the +// peer sent them. +func firstFold(h Peeker, name string) []byte { + // Walked rather than ranged, for the reason Lines gives: All builds a + // heap-allocated iterator per call. Scanning past the match costs less than + // the early exit ranging would buy. + var found []byte + h.VisitAll(func(k, v []byte) { + if found == nil && len(v) > 0 && utils.EqualFold(utils.UnsafeString(k), name) { + found = v + } + }) + return found +} + +// Canonical reports whether every field name in h is spelled the way fasthttp +// normalizes it, so the byte-exact Peek and Del find them all. +// +// Ask this of a response rather than reading the app config: a proxied response +// is parsed by an outbound fasthttp.Client carrying its own normalizing setting, +// so a default-normalizing app can hold a response of lower-case names. It is +// one walk, against one per field for the case-insensitive reads it saves. +func Canonical(h *fasthttp.ResponseHeader) bool { + canonical := true + // Walked rather than ranged, for the reason Lines gives: All allocates an + // iterator per call, and this runs per response. The deprecation is excluded + // in .golangci.yml rather than by an inline directive, which the lint cache + // leaves reported as unused on some runs. + h.VisitAll(func(k, _ []byte) { + if canonical && !isCanonicalName(k) { + canonical = false + } + }) + return canonical +} + +// isCanonicalName reports whether name is upper case at the start of each +// "-"-separated token and lower case everywhere else, which is what fasthttp's +// normalization produces. +func isCanonicalName(name []byte) bool { + upper := true + for _, c := range name { + if upper { + if c >= 'a' && c <= 'z' { + return false + } + } else if c >= 'A' && c <= 'Z' { + return false + } + upper = c == '-' + } + return true +} + +// Del removes every field line named name, whatever case it is stored under. +// +//nolint:revive // flag-parameter: canonical is a property of the header store +func Del(h Deleter, name string, canonical bool) { + h.Del(name) + if canonical { + // The scan below would only confirm Del found everything, at the cost + // of an iterator allocation per name on an otherwise alloc-free path. + return + } + + // Collected before deleting, like DelOthers, rather than rescanning after + // each removal: ResponseHeader.All reports a default Content-Type whenever + // the slot is empty, so a rescan would keep finding the name it just + // deleted. A name stored non-canonically in a normalizing store is the same + // shape, since Del normalizes the key before matching and so cannot remove + // it at all. + var others []string + for k := range h.All() { + if utils.EqualFold(utils.UnsafeString(k), name) { + others = append(others, string(k)) + } + } + + for _, k := range others { + h.Del(k) + } +} + +// DelOthers removes every stored spelling of name except name itself, which the +// caller is about to write or delete under that key. Every other one, not just +// the first: stopping early leaves the rest beside the value the caller writes. +func DelOthers(h Deleter, name string) { + // Collected before deleting: removing while ranging over the store is not safe. + var others []string + for k := range h.All() { + if ks := utils.UnsafeString(k); ks != name && utils.EqualFold(ks, name) { + others = append(others, string(k)) + } + } + + for _, k := range others { + h.Del(k) + } +} + +// DelSet removes every field line matching any of names in a single pass, which +// beats Del's per-name scan when the whole set is known up front. +func DelSet(h Deleter, names []string) { + var removed []string + for k := range h.All() { + if ContainsFold(names, utils.UnsafeString(k)) { + removed = append(removed, string(k)) + } + } + + // A repeated name is deleted twice; Del removes every line at once, so + // scanning to avoid that costs more than making the call. + for _, name := range removed { + h.Del(name) + } +} + +// ContainsFold reports whether needle equals any of haystack, case-insensitively. +func ContainsFold(haystack []string, needle string) bool { + for _, h := range haystack { + if utils.EqualFold(h, needle) { + return true + } + } + return false +} + +// Byte classes of a field name, for IsCanonical. +const ( + keyOther byte = iota // a token byte that is not a letter + keyLower // a-z + keyUpper // A-Z + keyInvalid // not a token byte (RFC 9110 Section 5.6.2) +) + +// keyClass classifies every byte a field name can hold. The token set is the +// one fasthttp normalizes; any other byte makes it store the name as sent. +var keyClass = func() [256]byte { + var t [256]byte + for i := range t { + t[i] = keyInvalid + } + for _, c := range []byte("!#$%&'*+-.^_`|~0123456789") { + t[c] = keyOther + } + for c := byte('a'); c <= 'z'; c++ { + t[c] = keyLower + t[c-'a'+'A'] = keyUpper + } + return t +}() + +// IsCanonical reports whether name is already in fasthttp's canonical form: a +// token with an upper-case letter first and after each '-' and lower case +// elsewhere. fasthttp derives that form again on every keyed call, three +// passes and a copy, only to arrive at the same bytes; a name that already has +// it can take the *Canonical methods instead, which store and find exactly what +// the normalizing ones would whether or not the store normalizes. +// Test_IsCanonical_MatchesFasthttp keeps the form in step. +func IsCanonical(name string) bool { + n := len(name) + if n == 0 { + return false + } + // Names such as X-Request-ID fail only at their last byte, so the tail is + // checked first: an upper-case letter not following a '-' cannot end a + // canonical name. + if n > 1 && name[n-1] >= 'A' && name[n-1] <= 'Z' && name[n-2] != '-' { + return false + } + upper := true + for i := range n { + c := name[i] + switch keyClass[c] { + case keyInvalid: + return false + case keyLower: + if upper { + return false + } + case keyUpper: + if !upper { + return false + } + } + upper = c == '-' + } + return true +} + +// Peek is fasthttp's byte-exact Peek, minus the key normalization when name is +// already canonical; Test_Peek_MatchesFasthttp keeps the two answering alike in +// both store modes. +func Peek(h Peeker, name string) []byte { + if IsCanonical(name) { + // Concrete calls only: through the interface the key would escape. + switch h := h.(type) { + case *fasthttp.RequestHeader: + return h.PeekCanonical(utils.UnsafeBytes(name)) + case *fasthttp.ResponseHeader: + return h.PeekCanonical(utils.UnsafeBytes(name)) + } + } + return h.Peek(name) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/headerlist/headerlist.go b/src/vendor/github.com/gofiber/fiber/v3/internal/headerlist/headerlist.go new file mode 100644 index 00000000..2ca8e8f8 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/headerlist/headerlist.go @@ -0,0 +1,331 @@ +// Package headerlist walks the comma-separated list values that RFC 9110 +// Section 5.6.1 defines, and joins the field lines that Section 5.3 says are +// equivalent to one. +// +// Seven scanners used to spell this out separately: three in the core +// (helpers.go, ctx.go, res.go) and four in middleware (adaptor, proxy, compress, +// cache). They agreed on splitting at commas and trimming OWS, and disagreed on +// everything after that, so the divergences are named here rather than left to +// be rediscovered per call site: +// +// - Case. [Contains] compares exactly, [ContainsFold] under ASCII case +// folding. [AppendUnique] and [AppendUniqueFold] follow the same split. +// [Append] echoes list members as written. Vary members are HTTP field +// names and must match however they arrive (RFC 9110 Section 5.1). +// - Quoting. [All] treats every comma as a separator, which is what a list of +// bare tokens wants. [AllQuoted] keeps commas that sit inside a quoted +// string, which is what a list of entity tags or media-type parameters +// needs, since those may contain one. +// - Whitespace. [All] and its siblings trim with utils.TrimSpace, which also +// takes CR, LF, VT and FF. [TrimOWS] takes only SP and HTAB, the OWS of +// RFC 9110 Section 5.6.3, for a caller that validates what is left. +// +// Empty elements are skipped throughout: "a,,b" yields "a" and "b". A list is +// permitted to carry them (RFC 9110 Section 5.6.1 allows the empty element for +// legacy reasons) and no caller here has ever wanted one. +package headerlist + +import ( + "iter" + + "github.com/gofiber/utils/v2" +) + +// All yields each non-empty element of a comma-separated list value, with +// leading and trailing whitespace removed. +// +// Every comma separates. Use [AllQuoted] for a list whose elements may contain +// a quoted comma. +func All(list string) iter.Seq[string] { + return func(yield func(string) bool) { + start := 0 + for i := range len(list) { + if list[i] != ',' { + continue + } + if element := utils.TrimSpace(list[start:i]); element != "" { + if !yield(element) { + return + } + } + start = i + 1 + } + if element := utils.TrimSpace(list[start:]); element != "" { + yield(element) + } + } +} + +// AllQuoted is [All] for lists whose elements may contain a comma inside a +// quoted string, such as If-None-Match, where the opaque-tag `"v1,v2"` is one +// entity tag and not two elements (RFC 9110 Section 8.8.3). +// +// Only '"' and ',' can affect where an element ends, so the walk jumps between +// them instead of visiting every byte. A quoted string left open by a malformed +// value swallows the rest of the list, which keeps a truncated field from +// splitting into elements the sender did not write. +func AllQuoted(list string) iter.Seq[string] { + return func(yield func(string) bool) { + start, pos := 0, 0 + inQuotes := false + for { + i := utils.IndexAny2(list[pos:], '"', ',') + if i == -1 { + break + } + i += pos + pos = i + 1 + + if list[i] == '"' { + inQuotes = !inQuotes + continue + } + if inQuotes { + continue + } + if element := utils.TrimSpace(list[start:i]); element != "" { + if !yield(element) { + return + } + } + start = i + 1 + } + if element := utils.TrimSpace(list[start:]); element != "" { + yield(element) + } + } +} + +// AllQuotedPairs is [AllQuoted] for quoted strings that may carry a quoted-pair +// (RFC 9110 Section 5.6.4), such as Cache-Control directive arguments: inside +// quotes a backslash escapes the next byte, so `ext="a\"", no-transform` has two +// elements. Entity tags have no quoted-pair and keep using [AllQuoted]. +func AllQuotedPairs(list string) iter.Seq[string] { + return func(yield func(string) bool) { + start, pos := 0, 0 + inQuotes := false + for { + i := utils.IndexAny3(list[pos:], '"', ',', '\\') + if i == -1 { + break + } + i += pos + pos = i + 1 + + switch { + case list[i] == '\\': + if inQuotes && pos < len(list) { + pos++ // the escaped byte ends neither the string nor the element + } + continue + case list[i] == '"': + inQuotes = !inQuotes + continue + case inQuotes: + continue + } + if element := utils.TrimSpace(list[start:i]); element != "" { + if !yield(element) { + return + } + } + start = i + 1 + } + if element := utils.TrimSpace(list[start:]); element != "" { + yield(element) + } + } +} + +// AllLines yields the elements of every field line in order, so that a header +// sent as one line and the same header sent as several read alike (RFC 9110 +// Section 5.3). +// +// The lines are read as-is; the caller keeps whatever storage they alias. +func AllLines(lines [][]byte) iter.Seq[string] { + return func(yield func(string) bool) { + for _, line := range lines { + for element := range All(utils.UnsafeString(line)) { + if !yield(element) { + return + } + } + } + } +} + +// TrimOWS removes the optional whitespace around a list element or a field +// value: SP and HTAB, which is all RFC 9110 Section 5.6.3 allows. CR, LF, VT +// and FF are not OWS, so they stay for a validating caller to reject, as does +// a tab inside the value. +// +// The result aliases s. +func TrimOWS[S ~string | ~[]byte](s S) S { + start, end := 0, len(s) + for start < end && (s[start] == ' ' || s[start] == '\t') { + start++ + } + for end > start && (s[end-1] == ' ' || s[end-1] == '\t') { + end-- + } + return s[start:end] +} + +// Contains reports whether list has an element equal to value, compared byte +// for byte. An empty value is never present. +// +// value is matched against the elements [All] yields, so it is expected to be +// one element and to carry no OWS of its own: " gzip " is not an element of +// " gzip ", though "gzip" is. +// +// Use [ContainsFold] to match a token whose case the sender chose. +func Contains(list, value string) bool { + if value == "" { + return false + } + + for element := range All(list) { + if element == value { + return true + } + } + return false +} + +// ContainsFold reports whether list has an element equal to value under ASCII +// case folding. An empty value is never present. +func ContainsFold(list, value string) bool { + if value == "" { + return false + } + + for element := range All(list) { + if utils.EqualFold(element, value) { + return true + } + } + return false +} + +// Append appends the elements of list to dst and returns it, reusing dst's +// storage. It returns nil for an empty list, leaving dst untouched. +// +// This is the allocation-free counterpart to [All], for the callers that need +// the elements to outlive the walk. It is written as a loop rather than over +// [All] because it sits on the per-request Accept-Encoding path. +func Append(dst []string, list string) []string { + if list == "" { + return nil + } + + dst = dst[:0] + start := 0 + for i := range len(list) { + if list[i] != ',' { + continue + } + if element := utils.TrimSpace(list[start:i]); element != "" { + dst = append(dst, element) + } + start = i + 1 + } + if element := utils.TrimSpace(list[start:]); element != "" { + dst = append(dst, element) + } + + return dst +} + +// Join renders the field lines of one header as the single combined value that +// RFC 9110 Section 5.3 says they are equivalent to, separated by a bare comma. +// +// A lone line is returned as it stands, so the result aliases the caller's +// storage and must not be retained past it. Only the multi-line case allocates, +// and that case is rare. +func Join(lines [][]byte) []byte { + switch len(lines) { + case 0: + return nil + case 1: + return lines[0] + } + + n := len(lines) - 1 + for _, line := range lines { + n += len(line) + } + + joined := make([]byte, 0, n) + for i, line := range lines { + if i > 0 { + joined = appendJoinedLine(joined, line) + continue + } + joined = append(joined, line...) + } + return joined +} + +func appendJoinedLine(dst, line []byte) []byte { + dst = append(dst, ',') + return append(dst, line...) +} + +// JoinNext adds a field line to a value built during a streaming header walk. +// The first line aliases the caller's storage. On the second line the result +// takes ownership of a new buffer; later lines reuse it when capacity permits. +// Use [Join] when all lines are already available so it can size that buffer +// once. The bool reports whether at least two lines have been joined. +// +//nolint:revive // multiple tracks ownership of combined, not a caller-selected mode. +func JoinNext(combined, line []byte, multiple bool) ([]byte, bool) { + if combined == nil { + return line, false + } + if !multiple { + joined := make([]byte, 0, len(combined)+1+len(line)) + joined = append(joined, combined...) + return appendJoinedLine(joined, line), true + } + return appendJoinedLine(combined, line), true +} + +// AppendUnique adds each value that list does not already carry, separated by +// ", ", and returns the result. It returns "" when nothing was added, so a +// caller can tell "unchanged" from "changed" without comparing the strings. +// +// Presence is decided by [Contains], byte for byte: a value already listed in +// another case is added again rather than silently dropped, since the field +// this serves is echoed to the client as written. +// +// Use [AppendUniqueFold] when the members are HTTP field names. +func AppendUnique(list string, values []string) string { + return appendIfAbsent(list, values, Contains) +} + +// AppendUniqueFold is [AppendUnique] with presence decided by [ContainsFold]. +// Use it when the list members are HTTP field names, which RFC 9110 Section 5.1 +// treats as case-insensitive. The first spelling is kept. +func AppendUniqueFold(list string, values []string) string { + return appendIfAbsent(list, values, ContainsFold) +} + +func appendIfAbsent(list string, values []string, present func(list, value string) bool) string { + original := list + for _, value := range values { + if value == "" { + continue + } + switch { + case list == "": + list = value + case !present(list, value): + list += ", " + value + } + } + + if list == original { + return "" + } + return list +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/headerlookup/headerlookup.go b/src/vendor/github.com/gofiber/fiber/v3/internal/headerlookup/headerlookup.go new file mode 100644 index 00000000..2a2cc1a5 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/headerlookup/headerlookup.go @@ -0,0 +1,214 @@ +// Package headerlookup answers, for a caller holding a fiber.Ctx, the two +// questions the byte-exact header API cannot: whether the stored field names are +// canonical, and what a named request header holds if they are not. +package headerlookup + +import ( + "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/appconfig" + "github.com/gofiber/fiber/v3/internal/fieldname" + "github.com/gofiber/utils/v2" + "github.com/valyala/fasthttp" +) + +// Canonical reports whether fasthttp normalized this request's header names. +// +// fasthttp keeps the answer private, so take it from the app config that set +// it. This answers for the request store only: a proxied response is parsed by +// an outbound fasthttp.Client carrying its own setting. +func Canonical(c fiber.Ctx) bool { + return !appconfig.Of(c.App()).DisableHeaderNormalizing +} + +// singleLine returns one field line as a string, copied only where Immutable +// promises the caller a value that outlives the request's buffer. +// +//nolint:revive // flag-parameter: immutable is a property of the app's config, not a mode of operation +func singleLine(line []byte, immutable bool) string { + if len(line) == 0 { + return "" + } + if immutable { + return string(line) + } + return utils.UnsafeString(line) +} + +// Value returns the named request header, matching the field name +// case-insensitively (RFC 9110 §5.1). Ctx.Get is byte-exact, so a lower-case +// "origin:" read as absent and the CSRF check found nothing to verify. +// +// ok is false where the message carries the field more than once, whatever the +// lines are spelled like or hold. Every caller here reads a field defined as a +// single value — Origin, Referer, Sec-Fetch-Site, Authorization — for which +// RFC 9110 §5.2 says a sender must not generate a second line at all, so such a +// message is malformed and what it means is not a question with an answer. +// Answering with any one of the lines lets whoever wrote the other one decide: +// picking the first hides a value behind an empty line, and picking the first +// non-empty defeats a middleware that cleared the field while a differently +// spelled line from the client remained. +// +// ok is true for a single line that is present and empty, which is not +// ambiguous — it says the field holds nothing, and "" is that answer. +// +// A caller must not read a false ok as an absent header: absent is a state +// these fields are allowed to be in and some checks skip themselves for it, +// which is the opposite of what a malformed message should get. Refuse instead. +// The value is empty whenever ok is false, so a caller that only refuses empty +// values still fails closed. +func Value(c fiber.Ctx, name string) (string, bool) { + cfg := appconfig.Of(c.App()) + h := &c.Request().Header + + var ( + found []byte + ok bool + ) + if cfg.DisableHeaderNormalizing { + found, ok = foldValue(h, name) + } else { + found, ok = canonicalValue(h, name) + } + if !ok { + return "", false + } + return singleLine(found, cfg.Immutable), true +} + +// Combined returns the named request header as the one value RFC 9110 §5.3 +// gives a field carried on several lines: their values in the order received, +// separated by ", ". +// +// This is for a caller naming a field it does not choose — extractors take the +// name from the application's config, and Accept, Forwarded and the rest are +// list fields a peer may legally send twice. Value's refusal is wrong for them, +// because two lines there are one value, not two answers. Where the field is a +// single value the combination is still not one: a credential joined with +// another does not match the one that was issued, so a caller comparing it +// refuses, which is the outcome Value reaches directly. +func Combined(c fiber.Ctx, name string) string { + cfg := appconfig.Of(c.App()) + h := &c.Request().Header + + if utils.EqualFold(name, fiber.HeaderCookie) { + // Cookie is not a comma-separated list — RFC 6265 §5.4 joins its + // crumbs with "; " — and fasthttp keeps them in a store of their own, + // which PeekAll enumerates one cookie at a time. Joining those would + // hand the caller "a=1, b=2" for a request that said "a=1; b=2". + // Collecting first makes fasthttp reassemble the field, so what is read + // below is the one line it actually holds. The lookup is expected to + // miss; collecting is the point of the call, as it is in the cache's + // keyFieldLines. + h.Cookie("") + } + + if cfg.DisableHeaderNormalizing { + return foldCombined(h, name, cfg.Immutable) + } + + lines := fieldname.Lines(h, name, true) + + switch len(lines) { + case 0: + return "" + case 1: + return singleLine(lines[0], cfg.Immutable) + } + + n := 2 * (len(lines) - 1) + for _, line := range lines { + n += len(line) + } + joined := make([]byte, 0, n) + for i, line := range lines { + if i > 0 { + joined = append(joined, ',', ' ') + } + joined = append(joined, line...) + } + // The buffer is this function's own, so no copy is owed to Immutable. + return utils.UnsafeString(joined) +} + +// foldCombined answers Combined for a store keeping whatever spelling the peer +// sent, which is what HTTP/2 and 3 put on the wire. +// +// Its own walk rather than fieldname.Lines, whose callback and result slice +// both escape, costing three allocations per header read. The single-line case +// allocates nothing; repeated lines walk twice, which is rare and already pays +// for the join. +// +//nolint:revive // flag-parameter: immutable is a property of the app's config, not a mode of operation +func foldCombined(h *fasthttp.RequestHeader, name string, immutable bool) string { + var first []byte + lines, size := 0, 0 + for k, v := range h.All() { + if !utils.EqualFold(utils.UnsafeString(k), name) { + continue + } + if lines == 0 { + first = v + } + lines++ + size += len(v) + } + + switch lines { + case 0: + return "" + case 1: + return singleLine(first, immutable) + } + + joined := make([]byte, 0, size+2*(lines-1)) + // Counted, not read off the buffer: a first line that is present and empty + // writes nothing, and the next still needs its separator. + written := 0 + for k, v := range h.All() { + if !utils.EqualFold(utils.UnsafeString(k), name) { + continue + } + if written > 0 { + joined = append(joined, ',', ' ') + } + joined = append(joined, v...) + written++ + } + // The buffer is this function's own, so no copy is owed to Immutable. + return utils.UnsafeString(joined) +} + +// canonicalValue answers Value for a store whose field names fasthttp folded on +// the way in, so one PeekAll — which costs no allocation and resolves the names +// kept in a slot of their own — sees every spelling at once. +func canonicalValue(h *fasthttp.RequestHeader, name string) ([]byte, bool) { + lines := h.PeekAll(name) + if len(lines) > 1 { + return nil, false + } + if len(lines) == 0 { + return nil, true + } + return lines[0], true +} + +// foldValue answers Value for a store keeping whatever spelling the peer sent. +// +// Split out rather than written beside canonicalValue: All's iterator is +// heap-allocated where the compiler cannot see the branch is dead, so holding it +// in Value would cost the normalized path an allocation it never uses. +func foldValue(h *fasthttp.RequestHeader, name string) ([]byte, bool) { + var found []byte + seen := 0 + for k, v := range h.All() { + if !utils.EqualFold(utils.UnsafeString(k), name) { + continue + } + seen++ + if seen > 1 { + return nil, false + } + found = v + } + return found, true +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/logtemplate/sanitize.go b/src/vendor/github.com/gofiber/fiber/v3/internal/logtemplate/sanitize.go new file mode 100644 index 00000000..39861cf8 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/logtemplate/sanitize.go @@ -0,0 +1,73 @@ +package logtemplate + +import ( + "github.com/gofiber/utils/v2" +) + +// WriteSanitized writes p to output with ASCII control bytes replaced by +// spaces. Tabs are preserved. Clean inputs (the common case) forward +// directly to output.Write with no allocation; dirty inputs are scrubbed +// into a copy starting at the first control byte. +func WriteSanitized(output Buffer, p []byte) (int, error) { + idx := IndexControlByte(p) + if idx == -1 { + return output.Write(p) + } + return output.Write(ScrubControls(p, idx)) +} + +// WriteSanitizedString is WriteSanitized for strings, keeping the clean +// fast path on output.WriteString. +func WriteSanitizedString(output Buffer, s string) (int, error) { + idx := IndexControlByte(s) + if idx == -1 { + return output.WriteString(s) + } + return output.Write(ScrubControls(s, idx)) +} + +// ScrubControls returns a copy of s with every byte IsControlByte matches +// replaced by a space. idx is the index of the first such byte, so the scan +// starts there and the clean prefix is copied untouched. +// +// A negative idx — what IndexControlByte returns for clean input — is clamped +// to 0 rather than panicking, so ScrubControls(s, IndexControlByte(s)) is +// safe even though the callers here take the clean fast path instead. +func ScrubControls[S ~string | ~[]byte](s S, idx int) []byte { + if idx < 0 { + idx = 0 + } + scrubbed := make([]byte, len(s)) + copy(scrubbed, s) + for i := idx; i < len(scrubbed); i++ { + if IsControlByte(scrubbed[i]) { + scrubbed[i] = ' ' + } + } + return scrubbed +} + +// IndexControlByte returns the index of the first byte IsControlByte matches, +// or -1 if none is present. +// +// The set it looks for — C0 controls except HTAB, plus DEL, with bytes >= 0x80 +// never matching — is exactly the one utils.IndexControlExceptTab scans for, so +// this is a thin alias over that helper rather than a second SWAR loop to keep +// in step. utils unrolls two words per branch and folds the whole test into one +// arithmetic mask, which measures ~28% faster on a 12-byte path and ~45% faster +// on a 120-byte user agent than the single-word loop this replaced. +func IndexControlByte[S ~string | ~[]byte](s S) int { + return utils.IndexControlExceptTab(s) +} + +// IsControlByte reports whether b is an ASCII control byte that must not pass +// through to a log line. Tab is preserved because operators frequently use it +// for delimiting structured fields. CR, LF, NUL, and the other C0/DEL bytes +// are replaced — they are the bytes attackers use to forge log lines or +// corrupt terminal output via ANSI escape sequences. +func IsControlByte(b byte) bool { + if b == '\t' { + return false + } + return b < 0x20 || b == 0x7f +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/mediatype/mediatype.go b/src/vendor/github.com/gofiber/fiber/v3/internal/mediatype/mediatype.go new file mode 100644 index 00000000..268d0be0 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/mediatype/mediatype.go @@ -0,0 +1,104 @@ +// Package mediatype canonicalizes the case-insensitive parts of a request's +// Content-Type, so the case-sensitive parsers downstream — fasthttp's form and +// multipart readers above all — see the value they expect. +package mediatype + +import ( + "bytes" + + "github.com/gofiber/utils/v2" + utilsbytes "github.com/gofiber/utils/v2/bytes" + "github.com/valyala/fasthttp" +) + +// NormalizeRequestContentType lowercases the case-insensitive parts of a +// request's Content-Type in place. The fold must land on the request's own +// bytes: fasthttp locates the boundary and the urlencoded body case-sensitively. +func NormalizeRequestContentType(h *fasthttp.RequestHeader) []byte { + ct := h.ContentType() + + // Nothing to fold is both the common and the repeat case: after the first + // FormValue the header is already lowercase. Uppercase confined to a parameter + // value still takes the full walk, which leaves it alone. + if !hasUpper(ct) { + return ct + } + + i := bytes.IndexByte(ct, ';') + if i == -1 { + utilsbytes.UnsafeToLower(ct) + return ct + } + utilsbytes.UnsafeToLower(ct[:i]) + + for i < len(ct) { + i++ // step over the ';' + for i < len(ct) && (ct[i] == ' ' || ct[i] == '\t') { + i++ + } + + nameStart := i + for i < len(ct) && ct[i] != '=' && ct[i] != ';' { + i++ + } + utilsbytes.UnsafeToLower(ct[nameStart:i]) + if i >= len(ct) || ct[i] == ';' { + continue + } + + // Step over the value untouched: a quoted-string may contain ';' (RFC 9110 + // §5.6.6), and a quoted-pair may contain '"'. Ending the string at an + // escaped quote would fold the rest as parameters, and fasthttp matches + // "boundary" case-sensitively, so lowercasing a decoy inside a value is + // what makes it the one fasthttp picks: on + // `X="\"; BOUNDARY=bogus"; BOUNDARY=Real` it took bogus over Real. + i++ // step over the '=' + if i < len(ct) && ct[i] == '"' { + i++ + for i < len(ct) && ct[i] != '"' { + if ct[i] == '\\' && i+1 < len(ct) { + i++ // the escaped byte cannot close the string + } + i++ + } + if i < len(ct) { + i++ // closing quote + } + } + for i < len(ct) && ct[i] != ';' { + i++ + } + } + + return ct +} + +// Form media types, duplicated from package fiber because that package imports +// this one. +const ( + applicationForm = "application/x-www-form-urlencoded" + multipartForm = "multipart/form-data" +) + +// IsForm reports whether ct names one of the two media types fasthttp's form +// parsers handle. Callers gate NormalizeRequestContentType on it, since the fold +// lands on the request's own bytes. Compared folded, parameters ignored. +func IsForm(ct []byte) bool { + if i := bytes.IndexByte(ct, ';'); i >= 0 { + ct = ct[:i] + } + ct = bytes.TrimRight(ct, " \t") + + name := utils.UnsafeString(ct) + return utils.EqualFold(name, applicationForm) || utils.EqualFold(name, multipartForm) +} + +// hasUpper reports whether b holds an ASCII uppercase byte. +func hasUpper(b []byte) bool { + for _, c := range b { + if c >= 'A' && c <= 'Z' { + return true + } + } + return false +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/memory/memory.go b/src/vendor/github.com/gofiber/fiber/v3/internal/memory/memory.go index d4e14279..1fe476db 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/internal/memory/memory.go +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/memory/memory.go @@ -17,6 +17,7 @@ package memory import ( + "math" "sync" "time" @@ -76,7 +77,7 @@ func (s *Storage) Get(key string) any { func (s *Storage) Set(key string, val any, ttl time.Duration) { var exp uint32 if ttl > 0 { - exp = uint32(ttl.Seconds()) + utils.Timestamp() + exp = absoluteExpiry(ttl) } // Defensive copies to prevent unsafe reuse from sync.Pool @@ -100,6 +101,21 @@ func (s *Storage) Delete(key string) { s.mu.Unlock() } +// DeleteIf removes key only when matches accepts its current value. The +// predicate runs under the storage lock and must not call back into Storage. +func (s *Storage) DeleteIf(key string, matches func(any) bool) bool { + s.mu.Lock() + defer s.mu.Unlock() + + entry, ok := s.data[key] + if !ok || !matches(entry.v) { + return false + } + + delete(s.data, key) + return true +} + // Reset clears the storage by dropping every stored key. func (s *Storage) Reset() { nd := make(map[string]item) @@ -141,3 +157,29 @@ func (s *Storage) gc(sleep time.Duration) { s.mu.Unlock() } } + +// absoluteExpiry turns a positive TTL into the whole-second timestamp an entry +// expires at, saturating instead of wrapping: a near-maximum TTL added to the +// current timestamp would otherwise land in the past and expire at once. +func absoluteExpiry(ttl time.Duration) uint32 { + now := utils.Timestamp() + secs := ceilSeconds(ttl) + if secs > math.MaxUint32-now { + return math.MaxUint32 + } + return secs + now +} + +// ceilSeconds converts a positive duration to whole seconds, rounding up. +func ceilSeconds(d time.Duration) uint32 { + // Divide before rounding up: adding a second first overflows for a duration + // near the top of the range and wraps into a tiny, immediately expired value. + secs := d / time.Second + if d%time.Second != 0 { + secs++ + } + if secs > math.MaxUint32 { + return math.MaxUint32 + } + return uint32(secs) //nolint:gosec // G115: bounded by the MaxUint32 check above +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/origin/origin.go b/src/vendor/github.com/gofiber/fiber/v3/internal/origin/origin.go new file mode 100644 index 00000000..3ce99482 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/origin/origin.go @@ -0,0 +1,179 @@ +// Package origin validates and matches the serialized origins that the CORS and +// CSRF middleware compare against their configured allow lists. +// +// Both middleware carried their own copy of this. `normalizeOrigin` differed by +// one scheme check, and the subdomain type, its matcher and the wildcard walk +// were character for character the same in `middleware/cors/utils.go` and +// `middleware/csrf/helpers.go`. The one real difference is named here as +// [SchemePolicy] rather than left to be inferred from which copy you are +// reading: +// +// - CORS accepts any scheme, because Access-Control-Allow-Origin is echoed +// for schemes beyond http(s) and the browser is the one enforcing. +// - CSRF accepts only http and https, because it decides whether a request +// may mutate state and a non-web scheme has no business doing so. +// +// This package decides only whether two serialized origins are the same string +// after normalization. It does not fold default ports, so "https://a.com" and +// "https://a.com:443" are different origins here. That is what an Origin header +// carries (RFC 6454 Section 6.1 serializes without the default port), and it is +// deliberately stricter than internal/schemehost, which folds ports because it +// compares URLs rather than origins. +package origin + +import ( + "net/url" + "strings" + + utilsstrings "github.com/gofiber/utils/v2/strings" +) + +// SchemePolicy says which URL schemes a caller is willing to treat as an origin. +type SchemePolicy uint8 + +const ( + // AnyScheme accepts whatever scheme url.Parse accepts. Used by CORS. + AnyScheme SchemePolicy = iota + // WebSchemesOnly accepts only http and https. Used by CSRF. + WebSchemesOnly +) + +const ( + schemeHTTP = "http" + schemeHTTPS = "https" + schemeSep = "://" + // wildcardSep introduces a subdomain wildcard, as in "https://*.example.com". + wildcardSep = schemeSep + "*." +) + +// Normalize reports whether raw is a well formed origin and returns it as +// lowercase "scheme://host". +// +// An origin is scheme and host and nothing else, so userinfo, a query, a +// fragment, or a path beyond a bare "/" all make it invalid rather than being +// stripped. A "*" anywhere in the host is rejected outright: a wildcard is only +// meaningful as a whole configured pattern, never inside a value, so +// "https://*" is not an origin (see the note on Access-Control-Allow-Origin in +// RFC 6454 Section 7.1). +func Normalize(raw string, policy SchemePolicy) (string, bool) { + parsed, err := url.Parse(raw) + if err != nil { + return "", false + } + + if policy == WebSchemesOnly && parsed.Scheme != schemeHTTP && parsed.Scheme != schemeHTTPS { + return "", false + } + + if strings.IndexByte(parsed.Host, '*') >= 0 { + return "", false + } + + if parsed.User != nil || + parsed.Host == "" || + (parsed.Path != "" && parsed.Path != "/") || + parsed.RawQuery != "" || + parsed.Fragment != "" { + return "", false + } + + return utilsstrings.ToLower(parsed.Scheme) + schemeSep + utilsstrings.ToLower(parsed.Host), true +} + +// Subdomain is a configured wildcard pattern such as "https://*.example.com", +// split around the "*" into the part before it and the part after. +type Subdomain struct { + Prefix string + Suffix string +} + +// Pattern is one parsed entry of an allow list, which is either a plain origin +// or a subdomain wildcard. +type Pattern struct { + // Subdomain is set when Wildcard, and zero otherwise. + Subdomain Subdomain + // Origin is the normalized value when not Wildcard, and empty otherwise. + Origin string + // Wildcard reports which of the two fields above carries the entry. + Wildcard bool +} + +// ParsePattern reads one allow-list entry and reports whether it is usable. +// +// An entry that does not normalize is rejected, so callers get one place to +// fail rather than one per shape. +func ParsePattern(pattern string, policy SchemePolicy) (Pattern, bool) { + before, after, found := strings.Cut(pattern, wildcardSep) + if !found { + normalized, valid := Normalize(pattern, policy) + if !valid { + return Pattern{}, false + } + return Pattern{Origin: normalized}, true + } + + // Validate the pattern with the wildcard label removed, so that everything + // Normalize rejects is rejected here too. + normalized, valid := Normalize(before+schemeSep+after, policy) + if !valid { + return Pattern{Wildcard: true}, false + } + + scheme, host, split := strings.Cut(normalized, schemeSep) + if !split { + return Pattern{Wildcard: true}, false + } + return Pattern{Subdomain: Subdomain{Prefix: scheme + schemeSep, Suffix: host}, Wildcard: true}, true +} + +// MatchNormalized reports whether an already normalized origin sits under this +// wildcard. The caller is trusted to have normalized it; use [MatchAny] to +// match a raw header value. +func (s Subdomain) MatchNormalized(o string) bool { + // Not a subdomain if not long enough for a dot separator. + if len(o) < len(s.Prefix)+len(s.Suffix)+1 { + return false + } + + if !strings.HasPrefix(o, s.Prefix) || !strings.HasSuffix(o, s.Suffix) { + return false + } + + // Require the dot separator and at least one non-empty label between the + // prefix and the suffix, so "https://.example.com" does not match. + suffixStart := len(o) - len(s.Suffix) + if suffixStart <= len(s.Prefix) || o[suffixStart-1] != '.' { + return false + } + + // The labels between the two must themselves be non-empty. + sub := o[len(s.Prefix) : suffixStart-1] + if sub == "" || strings.HasPrefix(sub, ".") || strings.HasSuffix(sub, ".") || strings.Contains(sub, "..") { + return false + } + + return true +} + +// MatchAny reports whether raw sits under any of the wildcards. +// +// raw must already be in normalized form: it is normalized again and rejected +// if that changes it, so a request carrying "https://EXAMPLE.com" or a trailing +// slash cannot match a pattern that the same value in canonical form would not. +func MatchAny(subs []Subdomain, raw string, policy SchemePolicy) bool { + if len(subs) == 0 { + return false + } + + normalized, ok := Normalize(raw, policy) + if !ok || normalized != raw { + return false + } + + for _, sub := range subs { + if sub.MatchNormalized(raw) { + return true + } + } + return false +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/paramdelim/paramdelim.go b/src/vendor/github.com/gofiber/fiber/v3/internal/paramdelim/paramdelim.go new file mode 100644 index 00000000..ead0beb0 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/paramdelim/paramdelim.go @@ -0,0 +1,17 @@ +// Package paramdelim holds the byte set that ends a ":name" placeholder in a +// path. The route parser and the HTTP client both need the same grammar; keep +// it here so they cannot drift (#4635). +package paramdelim + +// PathEndChars are the bytes that terminate a :name placeholder in a URL path +// or route pattern: '/', '-', '.', ':', '\\', and '?'. +func PathEndChars() [256]bool { + var s [256]bool + s['/'] = true + s['-'] = true + s['.'] = true + s[':'] = true + s['\\'] = true + s['?'] = true + return s +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/quotedstring/quotedstring.go b/src/vendor/github.com/gofiber/fiber/v3/internal/quotedstring/quotedstring.go new file mode 100644 index 00000000..1b42b886 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/quotedstring/quotedstring.go @@ -0,0 +1,80 @@ +// Package quotedstring encodes values placed inside HTTP quoted strings. +package quotedstring + +import ( + "github.com/gofiber/utils/v2/swar" + "github.com/valyala/bytebufferpool" +) + +// escapeMask marks the lanes of w holding bytes Escape must encode: '\\', +// '"', any C0 control (including HTAB), or DEL. Lanes >= 0x80 are never +// marked; non-ASCII bytes pass through verbatim. +func escapeMask(w uint64) uint64 { + return swar.MatchByteMask(w, '\\') | swar.MatchByteMask(w, '"') | + swar.MatchRangeMask(w, 0x00, 0x1f) | swar.MatchByteMask(w, 0x7f) +} + +// indexEscape returns the index of the first byte escapeMask matches, or -1 +// when raw needs no escaping. It scans eight bytes at a time, finishing inputs +// of 8+ bytes with one overlapping word; shorter inputs are checked byte-wise. +func indexEscape(raw string) int { + n := len(raw) + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m := escapeMask(swar.Load8(raw, i)); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + if n >= swar.WordLen { + if m := escapeMask(swar.Load8(raw, n-swar.WordLen)); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 + } + for ; i < n; i++ { + if c := raw[i]; c == '\\' || c == '"' || c < 0x20 || c == 0x7f { + return i + } + } + return -1 +} + +// Escape encodes raw for placement inside an RFC 9110 quoted-string. Quotes +// and backslashes use quoted-pair escaping, LF and CR use their conventional +// backslash forms, and other C0 controls plus DEL are percent-encoded. HTAB is +// encoded even though RFC 9110 permits it as qdtext. Non-ASCII bytes pass +// through verbatim. The returned value excludes the surrounding quotes. +// Escape is a serializer, not input validation; callers apply their own +// rejection or sanitization policy before calling it. +func Escape(raw string) string { + end := indexEscape(raw) + if end == -1 { + return raw + } + + const hex = "0123456789ABCDEF" + bb := bytebufferpool.Get() + defer bytebufferpool.Put(bb) + + bb.B = append(bb.B, raw[:end]...) + for i := end; i < len(raw); i++ { + c := raw[i] + switch { + case c == '\\' || c == '"': + bb.B = append(bb.B, '\\', c) + case c == '\n': + bb.B = append(bb.B, '\\', 'n') + case c == '\r': + bb.B = append(bb.B, '\\', 'r') + case c < 0x20 || c == 0x7f: + bb.B = append(bb.B, '%', hex[c>>4], hex[c&0x0f]) + default: + bb.B = append(bb.B, c) + } + } + + return string(bb.B) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/schemehost/schemehost.go b/src/vendor/github.com/gofiber/fiber/v3/internal/schemehost/schemehost.go index 512bdbbf..be3074fa 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/internal/schemehost/schemehost.go +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/schemehost/schemehost.go @@ -7,6 +7,7 @@ import ( "net/url" "strings" + "github.com/gofiber/utils/v2" utilsstrings "github.com/gofiber/utils/v2/strings" ) @@ -15,76 +16,120 @@ const ( schemeHTTPS = "https" ) +// schemePorts is the single source of truth for the schemes whose default +// port is normalized away during origin comparison. +var schemePorts = [...]struct { + scheme string + port string +}{ + {schemeHTTP, "80"}, + {schemeHTTPS, "443"}, +} + +// foldSchemePort resolves scheme against schemePorts, ASCII +// case-insensitively, returning the canonical lowercase scheme and its +// default port. +func foldSchemePort(scheme string) (canonical, port string, known bool) { //nolint:nonamedreturns // names document the three results + for _, e := range schemePorts { + if utils.EqualFold(scheme, e.scheme) { + return e.scheme, e.port, true + } + } + return "", "", false +} + // Match reports whether (schemeA, hostA) and (schemeB, hostB) denote the same // origin. Scheme comparison is case-insensitive and default ports (http:80, // https:443) are normalized so "example.com" and "example.com:443" match. func Match(schemeA, hostA, schemeB, hostB string) bool { - normalizedSchemeA := utilsstrings.ToLower(schemeA) - normalizedSchemeB := utilsstrings.ToLower(schemeB) + if !utils.EqualFold(schemeA, schemeB) { + return false + } + + // Identical host strings always normalize identically, so they denote the + // same origin once the schemes match. This is the dominant same-origin + // input (e.g. Origin-vs-Host on non-CORS requests). + if hostA == hostB { + return true + } - normalizedHostA := normalizeSchemeHost(normalizedSchemeA, hostA) - normalizedHostB := normalizeSchemeHost(normalizedSchemeB, hostB) + scheme, defaultPort, known := foldSchemePort(schemeA) + if !known { + // Unknown schemes get no port normalization: the hosts must simply be + // equal, ASCII case-insensitively. + return utils.EqualFold(hostA, hostB) + } + + // Fast path for two clean "host" or "host:port" values (the common case): + // compare the host parts case-insensitively and the effective ports + // exactly, without allocating lowered or port-normalized copies. + if hostOnlyA, portA, cleanA := splitCleanHostPort(hostA); cleanA { + if hostOnlyB, portB, cleanB := splitCleanHostPort(hostB); cleanB { + if portA == "" { + portA = defaultPort + } + if portB == "" { + portB = defaultPort + } + return portA == portB && utils.EqualFold(hostOnlyA, hostOnlyB) + } + } - return normalizedSchemeA == normalizedSchemeB && normalizedHostA == normalizedHostB + // Anything unusual (userinfo, percent-encoding, bracketed IPv6, control + // chars, invalid port, ...) takes the legacy normalize-and-compare path. + return normalizeHostPort(scheme, hostA, defaultPort) == normalizeHostPort(scheme, hostB, defaultPort) } -func normalizeSchemeHost(scheme, host string) string { +// normalizeHostPort lowercases host and appends defaultPort when no explicit +// port is present. scheme is only used by the url.Parse fallback. +func normalizeHostPort(scheme, host, defaultPort string) string { host = utilsstrings.ToLower(host) - var defaultPort string - switch scheme { - case schemeHTTP: - defaultPort = "80" - case schemeHTTPS: - defaultPort = "443" - default: - return host - } - - // Fast path for a clean "host" or "host:port" value (the common case), - // avoiding the url.Parse allocation. Anything unusual (userinfo, path, - // percent-encoding, bracketed IPv6, control chars, empty/invalid port, ...) - // falls back to the url.Parse path, which preserves the exact legacy behavior. - if hasPort, clean := classifyHostPort(host); clean { - if hasPort { + // Clean "host" or "host:port" values (e.g. the clean side of a mixed + // clean/unclean pair; Match handles the clean/clean case itself) avoid the + // url.Parse allocation. Anything unusual (userinfo, path, percent-encoding, + // bracketed IPv6, control chars, empty/invalid port, ...) falls back to the + // url.Parse path, which preserves the exact legacy behavior. + if _, port, clean := splitCleanHostPort(host); clean { + if port != "" { return host } return host + ":" + defaultPort } - return normalizeSchemeHostViaParse(scheme, host, defaultPort) + return normalizeHostPortViaParse(scheme, host, defaultPort) } -// classifyHostPort reports whether host is a plain "" or -// ":" value (clean) and, if so, whether it carries an -// explicit numeric port. The accepted character set is deliberately narrow -// (lowercase ASCII letters, digits, '.', '-', and a single ':'); anything else, -// including bracketed IPv6 literals, returns clean=false and is handled by the +// splitCleanHostPort splits a plain "" or +// ":" value (clean) into its host and port parts. The +// accepted character set is deliberately narrow (ASCII letters, digits, '.', +// '-', and a single ':' followed by digits); anything else, including +// bracketed IPv6 literals, returns clean=false and is handled by the // url.Parse fallback so behavior stays identical to the legacy implementation. -func classifyHostPort(host string) (hasPort, clean bool) { //nolint:nonamedreturns // names document the two booleans +func splitCleanHostPort(s string) (host, port string, clean bool) { //nolint:nonamedreturns // names document the three results colon := -1 - for i := 0; i < len(host); i++ { - c := host[i] + for i := 0; i < len(s); i++ { + c := s[i] switch { - case c >= 'a' && c <= 'z', c >= '0' && c <= '9', c == '.', c == '-': + case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9', c == '.', c == '-': // safe reg-name / IPv4 character case c == ':': if colon >= 0 { - return false, false // more than one colon -> not a clean host:port + return "", "", false // more than one colon -> not a clean host:port } colon = i default: - return false, false // brackets, control chars, anything else + return "", "", false // brackets, control chars, anything else } } if colon < 0 { - return false, host != "" // no port; empty host falls back to url.Parse + return s, "", s != "" // no port; empty host falls back to url.Parse } - if !allDigits(host[colon+1:]) { - return false, false // "host:" or "host:abc" -> let url.Parse decide + if !allDigits(s[colon+1:]) { + return "", "", false // "host:" or "host:abc" -> let url.Parse decide } - return true, true + return s[:colon], s[colon+1:], true } // allDigits reports whether s is non-empty and all ASCII digits. @@ -100,9 +145,9 @@ func allDigits(s string) bool { return true } -// normalizeSchemeHostViaParse is the url.Parse-based fallback. host is already +// normalizeHostPortViaParse is the url.Parse-based fallback. host is already // lowercased and scheme is known to be http or https. -func normalizeSchemeHostViaParse(scheme, host, defaultPort string) string { +func normalizeHostPortViaParse(scheme, host, defaultPort string) string { parsedHost, err := url.Parse(scheme + "://" + host) if err != nil { return host diff --git a/src/vendor/github.com/gofiber/fiber/v3/internal/urlnorm/urlnorm.go b/src/vendor/github.com/gofiber/fiber/v3/internal/urlnorm/urlnorm.go new file mode 100644 index 00000000..d4fd9c23 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/internal/urlnorm/urlnorm.go @@ -0,0 +1,68 @@ +// Package urlnorm applies the parts of the WHATWG URL parser's input handling a +// guard must apply before judging a URL Fiber is about to emit. Nothing +// normalizes an outbound URL; the parser deciding it runs in the client after. +package urlnorm + +import ( + "strings" +) + +// StripTabCRLF removes every ASCII tab, LF and CR, as the WHATWG URL parser does +// before parsing. Leaving them in lets "\t/evil.com" hide behind a leading slash. +// Returns the input unchanged, without copying, when it holds none of them. +func StripTabCRLF(s string) string { + var b []byte + for i := 0; i < len(s); i++ { + switch c := s[i]; c { + case '\t', '\n', '\r': + if b == nil { + b = append(make([]byte, 0, len(s)), s[:i]...) + } + default: + if b != nil { + b = append(b, c) + } + } + } + if b == nil { + return s + } + return string(b) +} + +// RootedPath returns location as what a URL composed from a named route can only +// be: a path on the origin now being served. Parameter values are escaped before +// this check, except slashes inside greedy parameters; normalization still +// protects route author text and direct callers. +// +// Exactly one leading slash, never two: "//evil.com" is a network-path reference +// whose host is whatever follows, so it resolves against "https://good.example" +// as "https://evil.com". That is true of author text as much as of a value, +// which is why NamesAuthority refuses such a route rather than composing it. +func RootedPath(location string) string { + location = StripTabCRLF(location) + + n := LeadingSlashes(location) + if n == 1 && location[0] == '/' { + return location + } + // Backslashes count as slashes here because the parser folds them. + return "/" + location[n:] +} + +// LeadingSlashes returns the length of the run of slashes starting s, counting +// backslashes among them because the parser folds the two. +func LeadingSlashes(s string) int { + n := 0 + for n < len(s) && (s[n] == '/' || s[n] == '\\') { + n++ + } + return n +} + +// AsBrowserReads returns location with the handling a client applies before +// parsing: tab, LF and CR removed, then surrounding C0 controls and spaces +// trimmed (RFC 9110 §5.5). Interior spaces are percent-encoded, not removed. +func AsBrowserReads(location string) string { + return strings.TrimFunc(StripTabCRLF(location), func(r rune) bool { return r <= ' ' }) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/listen.go b/src/vendor/github.com/gofiber/fiber/v3/listen.go index dbe71938..4e3705c0 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/listen.go +++ b/src/vendor/github.com/gofiber/fiber/v3/listen.go @@ -8,6 +8,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" "io" "net" @@ -40,10 +41,16 @@ const ( globalIpv4Addr = "0.0.0.0" ) +// ErrCertFileAndKeyRequired indicates that only one of CertFile and CertKeyFile was set. +var ErrCertFileAndKeyRequired = errors.New("tls: CertFile and CertKeyFile must both be set to serve TLS") + // ListenConfig is a struct to customize startup of Fiber. type ListenConfig struct { // GracefulContext is a field to shutdown Fiber by given context gracefully. // + // With EnablePrefork the context stops only the process it is canceled in; + // deliver the signal to every process so each child drains its own connections. + // // Default: nil GracefulContext context.Context `json:"graceful_context"` //nolint:containedctx // It's needed to set context inside Listen. @@ -55,11 +62,14 @@ type ListenConfig struct { // TLSConfigFunc allows customizing tls.Config as you want. // + // Ignored when TLSConfig is set: configure that tls.Config directly instead. + // // Default: nil TLSConfigFunc func(tlsConfig *tls.Config) `json:"tls_config_func"` - // TLSConfig allows providing a tls.Config used as the base for TLS settings. - // This enables external certificate providers via GetCertificate. + // TLSConfig is cloned and served as supplied, enabling external certificate + // providers via GetCertificate. It replaces the other TLS settings rather than + // seeding them, so there is no mutual TLS unless its ClientAuth requires it. // // Default: nil TLSConfig *tls.Config `json:"tls_config"` @@ -98,15 +108,17 @@ type ListenConfig struct { // Default : "" CertKeyFile string `json:"cert_key_file"` - // CertClientFile is a path of client certificate. - // If you want to use mTLS, you have to enter this field. + // CertClientFile is a path of the CA bundle used to verify client + // certificates, which is how ListenConfig asks for mTLS. Ignored when + // TLSConfig is set: its ClientAuth decides instead, against its ClientCAs. // // Default : "" CertClientFile string `json:"cert_client_file"` // When the graceful shutdown begins, use this field to set the timeout // duration. If the timeout is reached, OnPostShutdown will be called with the error. - // Set to 0 to disable the timeout and wait indefinitely. + // It bounds the wait for connections only; Listen also waits for the shutdown hooks. + // Negative disables the timeout and waits indefinitely; zero applies the default. // // Default: 10 * time.Second ShutdownTimeout time.Duration `json:"shutdown_timeout"` @@ -132,6 +144,8 @@ type ListenConfig struct { // TLSMinVersion allows to set TLS minimum version. // + // Ignored when TLSConfig is set: set MinVersion on that tls.Config instead. + // // Default: tls.VersionTLS12 // WARNING: TLS1.0 and TLS1.1 versions are not supported. TLSMinVersion uint16 `json:"tls_min_version"` @@ -183,13 +197,24 @@ func listenConfigDefault(config ...ListenConfig) ListenConfig { cfg.TLSMinVersion = tls.VersionTLS12 } - if cfg.TLSMinVersion != tls.VersionTLS12 && cfg.TLSMinVersion != tls.VersionTLS13 { - panic("unsupported TLS version, please use tls.VersionTLS12 or tls.VersionTLS13") + if cfg.ShutdownTimeout == 0 { + cfg.ShutdownTimeout = 10 * time.Second } return cfg } +// validateTLSMinVersion rejects a version this package will not build a +// tls.Config from. Asked only where the field is read: rejecting it in the +// defaults panicked before warnSupersededTLSFields or +// warnIgnoredTLSFieldsOnListener could say the value was being ignored anyway, +// which is the diagnostic a stale TLS 1.1 most needs. +func validateTLSMinVersion(cfg *ListenConfig) { + if cfg.TLSMinVersion != tls.VersionTLS12 && cfg.TLSMinVersion != tls.VersionTLS13 { + panic("unsupported TLS version, please use tls.VersionTLS12 or tls.VersionTLS13") + } +} + // Listen serves HTTP requests from the given addr. // You should enter custom ListenConfig to customize startup. (TLS, mTLS, prefork...) // @@ -204,7 +229,10 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { var tlsHandler *TLSHandler if cfg.TLSConfig != nil { tlsConfig = cfg.TLSConfig.Clone() + warnSupersededTLSFields(&cfg) } else { + validateTLSMinVersion(&cfg) + switch { case cfg.AutoCertManager != nil && (cfg.CertFile != "" || cfg.CertKeyFile != ""): return ErrAutoCertWithCertFile @@ -223,6 +251,10 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { GetCertificate: tlsHandler.GetClientInfo, } + case cfg.CertFile != "" || cfg.CertKeyFile != "": + // Half a key pair is a misconfiguration: refuse rather than serve plaintext. + return ErrCertFileAndKeyRequired + case cfg.AutoCertManager != nil: tlsConfig = &tls.Config{ MinVersion: cfg.TLSMinVersion, @@ -249,12 +281,8 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { } // Graceful shutdown - if cfg.GracefulContext != nil { - ctx, cancel := context.WithCancel(cfg.GracefulContext) - defer cancel() - - go app.gracefulShutdown(ctx, &cfg) - } + waitForShutdown := app.startGracefulShutdown(&cfg) + defer waitForShutdown() // Start prefork if cfg.EnablePrefork { @@ -267,6 +295,16 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { return fmt.Errorf("failed to listen: %w", err) } + // Close the listener on any path that doesn't reach Serve (which otherwise + // takes ownership of it) — an early error return or a panicking hook — so + // the bound socket isn't leaked. + served := false + defer func() { + if !served { + _ = ln.Close() //nolint:errcheck // best-effort cleanup on the error path + } + }() + // prepare the server for the start app.startupProcess() @@ -284,10 +322,86 @@ func (app *App) Listen(addr string, config ...ListenConfig) error { return err } } + app.hookHeaderReceived() + served = true return app.server.Serve(ln) } +// warnSupersededTLSFields logs the ListenConfig TLS fields a supplied TLSConfig +// supersedes. CertClientFile is where silence is dangerous: it is the only way +// ListenConfig asks for mTLS, and a TLSConfig says nothing about it by default. +func warnSupersededTLSFields(cfg *ListenConfig) { + if cfg.CertClientFile != "" { + log.Warn("[Listen] TLSConfig supersedes CertClientFile: a client certificate is required only if " + + "TLSConfig sets ClientAuth to a Require mode, with ClientCAs as the roots it verifies against.") + } + + var ignored []string + if cfg.CertFile != "" || cfg.CertKeyFile != "" { + ignored = append(ignored, "CertFile/CertKeyFile") + } + // Zero is unset and listenConfigDefault fills in TLS 1.2, so only a caller who + // asked for something else is losing anything here. + if cfg.TLSMinVersion != 0 && cfg.TLSMinVersion != tls.VersionTLS12 { + ignored = append(ignored, "TLSMinVersion") + } + if cfg.AutoCertManager != nil { + ignored = append(ignored, "AutoCertManager") + } + if cfg.TLSConfigFunc != nil { + ignored = append(ignored, "TLSConfigFunc") + } + if len(ignored) > 0 { + log.Warnf("[Listen] TLSConfig supersedes %s.", strings.Join(ignored, ", ")) + } +} + +// warnIgnoredTLSFieldsOnListener reports TLS settings App.Listener cannot honor. +// It serves the listener it is handed, so CertClientFile buys no client- +// certificate verification — and unless the caller wrapped it, no TLS either. +func warnIgnoredTLSFieldsOnListener(cfg *ListenConfig, ln net.Listener) { + if cfg.CertClientFile != "" { + log.Warn("[Listener] CertClientFile is ignored: a client certificate is required only if the supplied " + + "listener already asks for one. Wrap it with tls.NewListener using a tls.Config whose ClientAuth " + + "is a Require mode.") + } + + var ignored []string + if cfg.TLSConfig != nil { + ignored = append(ignored, "TLSConfig") + } + if cfg.CertFile != "" || cfg.CertKeyFile != "" { + ignored = append(ignored, "CertFile/CertKeyFile") + } + if cfg.TLSMinVersion != 0 && cfg.TLSMinVersion != tls.VersionTLS12 { + ignored = append(ignored, "TLSMinVersion") + } + if cfg.AutoCertManager != nil { + ignored = append(ignored, "AutoCertManager") + } + if cfg.TLSConfigFunc != nil { + ignored = append(ignored, "TLSConfigFunc") + } + if len(ignored) == 0 { + return + } + + suffix := "." + if getTLSConfig(ln) == nil { + suffix = "; this listener is not serving TLS." + } + log.Warnf("[Listener] serves the supplied listener as-is, so %s %s ignored%s", + strings.Join(ignored, ", "), pluralIsAre(len(ignored)), suffix) +} + +func pluralIsAre(n int) string { + if n == 1 { + return "is" + } + return "are" +} + func applyClientCert(tlsConfig *tls.Config, certClientFile string) error { if certClientFile == "" { return nil @@ -311,16 +425,17 @@ func applyClientCert(tlsConfig *tls.Config, certClientFile string) error { // Listener serves HTTP requests from the given listener. // You should enter custom ListenConfig to customize startup. (prefork, startup message, graceful shutdown...) +// +// The listener is served exactly as supplied, so every TLS field of the config +// is ignored — including CertClientFile. Wrap it with tls.NewListener yourself +// to serve TLS or require a client certificate. func (app *App) Listener(ln net.Listener, config ...ListenConfig) error { cfg := listenConfigDefault(config...) + warnIgnoredTLSFieldsOnListener(&cfg, ln) // Graceful shutdown - if cfg.GracefulContext != nil { - ctx, cancel := context.WithCancel(cfg.GracefulContext) - defer cancel() - - go app.gracefulShutdown(ctx, &cfg) - } + waitForShutdown := app.startGracefulShutdown(&cfg) + defer waitForShutdown() // prepare the server for the start app.startupProcess() @@ -344,6 +459,7 @@ func (app *App) Listener(ln net.Listener, config ...ListenConfig) error { if cfg.EnablePrefork { log.Warn("Prefork isn't supported for custom listeners.") } + app.hookHeaderReceived() return app.server.Serve(ln) } @@ -377,6 +493,7 @@ func (*App) createListener(addr string, tlsConfig *tls.Config, cfg *ListenConfig if cfg.ListenerNetwork == NetworkUnix { if err = os.Chmod(addr, cfg.UnixSocketFileMode); err != nil { + _ = listener.Close() //nolint:errcheck // best-effort cleanup on the error path return nil, fmt.Errorf("cannot chmod %#o for %q: %w", cfg.UnixSocketFileMode, addr, err) } } @@ -602,22 +719,34 @@ func (app *App) printRoutesMessage() { _ = w.Flush() //nolint:errcheck // It is fine to ignore the error here } -// shutdown goroutine -func (app *App) gracefulShutdown(ctx context.Context, cfg *ListenConfig) { - <-ctx.Done() +// startGracefulShutdown watches cfg.GracefulContext and returns the cleanup Listen +// defers. Serve returns once the listener closes, so the cleanup waits out the drain. +func (app *App) startGracefulShutdown(cfg *ListenConfig) func() { + if cfg.GracefulContext == nil { + return func() {} + } - var err error + done := make(chan struct{}) + stop := context.AfterFunc(cfg.GracefulContext, func() { + defer close(done) + app.gracefulShutdown(cfg) + }) - if cfg != nil && cfg.ShutdownTimeout != 0 { - err = app.ShutdownWithTimeout(cfg.ShutdownTimeout) //nolint:contextcheck // TODO: Implement it - } else { - err = app.Shutdown() //nolint:contextcheck // TODO: Implement it + return func() { + if !stop() { + <-done + } } +} - if err != nil { - app.hooks.executeOnPostShutdownHooks(err) - return +func (app *App) gracefulShutdown(cfg *ListenConfig) { + // The OnPostShutdown hooks are fired by ShutdownWithContext (via + // Shutdown/ShutdownWithTimeout) with the real error, so we must not fire + // them again here or they would run twice. That error is already delivered + // to those hooks, so it is intentionally ignored here. + if cfg != nil && cfg.ShutdownTimeout > 0 { + _ = app.ShutdownWithTimeout(cfg.ShutdownTimeout) //nolint:errcheck // error is delivered to OnPostShutdown hooks + } else { + _ = app.Shutdown() //nolint:errcheck // error is delivered to OnPostShutdown hooks } - - app.hooks.executeOnPostShutdownHooks(nil) } diff --git a/src/vendor/github.com/gofiber/fiber/v3/log/context.go b/src/vendor/github.com/gofiber/fiber/v3/log/context.go index 46dd6ca7..339eda37 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/log/context.go +++ b/src/vendor/github.com/gofiber/fiber/v3/log/context.go @@ -4,8 +4,6 @@ import ( "errors" "fmt" "maps" - "slices" - "strings" "sync" "sync/atomic" @@ -208,60 +206,14 @@ func defaultContextValueTag(output Buffer, ctx any, _ *ContextData, extraParam s } // writeSanitized writes p to output with ASCII control bytes replaced by -// spaces. Tabs are preserved. The replacement is done in-place on a single -// pass so the hot path stays alloc-free for inputs that are already clean -// (the common case): clean inputs forward directly to output.Write. +// spaces. Tabs are preserved. See logtemplate.WriteSanitized. func writeSanitized(output Buffer, p []byte) (int, error) { - if !needsControlSanitize(p) { - return output.Write(p) - } - scrubbed := make([]byte, len(p)) - for i, b := range p { - if isControlByte(b) { - scrubbed[i] = ' ' - } else { - scrubbed[i] = b - } - } - return output.Write(scrubbed) + return logtemplate.WriteSanitized(output, p) } +// writeSanitizedString is writeSanitized for strings. func writeSanitizedString(output Buffer, s string) (int, error) { - if !needsControlSanitizeString(s) { - return output.WriteString(s) - } - scrubbed := make([]byte, len(s)) - for i := 0; i < len(s); i++ { - b := s[i] - if isControlByte(b) { - scrubbed[i] = ' ' - } else { - scrubbed[i] = b - } - } - return output.Write(scrubbed) -} - -func needsControlSanitize(p []byte) bool { - return slices.ContainsFunc(p, isControlByte) -} - -func needsControlSanitizeString(s string) bool { - return strings.IndexFunc(s, func(r rune) bool { - return r < 0x80 && isControlByte(byte(r)) //nolint:gosec // G115: integer overflow conversion rune -> byte - }) >= 0 -} - -// isControlByte reports whether b is an ASCII control byte that must not pass -// through to a log line. Tab is preserved because operators frequently use it -// for delimiting structured fields. CR, LF, NUL, and the other C0/DEL bytes -// are replaced — they are the bytes attackers use to forge log lines or -// corrupt terminal output via ANSI escape sequences. -func isControlByte(b byte) bool { - if b == '\t' { - return false - } - return b < 0x20 || b == 0x7f + return logtemplate.WriteSanitizedString(output, s) } func emptyContextTag(_ Buffer, _ any, _ *ContextData, _ string) (int, error) { diff --git a/src/vendor/github.com/gofiber/fiber/v3/log/default.go b/src/vendor/github.com/gofiber/fiber/v3/log/default.go index 81b05bd3..fd7086a0 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/log/default.go +++ b/src/vendor/github.com/gofiber/fiber/v3/log/default.go @@ -15,6 +15,7 @@ var _ AllLogger[*log.Logger] = (*defaultLogger)(nil) type defaultLogger struct { stdlog *log.Logger + exit func(int) ctx retainedContext level Level depth int @@ -53,10 +54,25 @@ func newRetainedContext(value any) retainedContext { return retainedContext{value: value, isOk: true} } +// exitFatal ends the program the way Fatal must. A logger may carry a hook of +// its own, so a test can intercept the exit without reaching for global state; +// nil, the zero value a directly constructed logger has, means os.Exit. +func (l *defaultLogger) exitFatal() { + if l.exit != nil { + l.exit(1) + return + } + os.Exit(1) //nolint:revive // exiting is what Fatal is for +} + // privateLog logs a message at a given level log the default logger. // when the level is fatal, it will exit the program. func (l *defaultLogger) privateLog(lv Level, fmtArgs []any) { if l.level > lv { + if lv == LevelFatal { + // Fatal exits even when its line is not written. + l.exitFatal() + } return } level := lv.toString() @@ -73,7 +89,7 @@ func (l *defaultLogger) privateLog(lv Level, fmtArgs []any) { buf.Reset() bytebufferpool.Put(buf) if lv == LevelFatal { - os.Exit(1) //nolint:revive // we want to exit the program when Fatal is called + l.exitFatal() } } @@ -81,6 +97,10 @@ func (l *defaultLogger) privateLog(lv Level, fmtArgs []any) { // when the level is fatal, it will exit the program. func (l *defaultLogger) privateLogf(lv Level, format string, fmtArgs []any) { if l.level > lv { + if lv == LevelFatal { + // Fatal exits even when its line is not written. + l.exitFatal() + } return } level := lv.toString() @@ -101,7 +121,7 @@ func (l *defaultLogger) privateLogf(lv Level, format string, fmtArgs []any) { buf.Reset() bytebufferpool.Put(buf) if lv == LevelFatal { - os.Exit(1) //nolint:revive // we want to exit the program when Fatal is called + l.exitFatal() } } @@ -109,6 +129,10 @@ func (l *defaultLogger) privateLogf(lv Level, format string, fmtArgs []any) { // when the level is fatal, it will exit the program. func (l *defaultLogger) privateLogw(lv Level, format string, keysAndValues []any) { if l.level > lv { + if lv == LevelFatal { + // Fatal exits even when its line is not written. + l.exitFatal() + } return } level := lv.toString() @@ -148,7 +172,7 @@ func (l *defaultLogger) privateLogw(lv Level, format string, keysAndValues []any buf.Reset() bytebufferpool.Put(buf) if lv == LevelFatal { - os.Exit(1) //nolint:revive // we want to exit the program when Fatal is called + l.exitFatal() } } @@ -294,6 +318,7 @@ func (l *defaultLogger) writeContext(buf Buffer) { func (l *defaultLogger) WithContext(ctx any) CommonLogger { return &defaultLogger{ stdlog: l.stdlog, + exit: l.exit, ctx: newRetainedContext(ctx), level: l.level, depth: l.depth - 1, diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/compress/compress.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/compress/compress.go index 9f23a9aa..2e8f3f81 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/compress/compress.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/compress/compress.go @@ -4,39 +4,32 @@ import ( "strings" "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/headerlist" "github.com/gofiber/fiber/v3/middleware/etag" "github.com/gofiber/utils/v2" "github.com/valyala/fasthttp" ) -func hasToken(header, token string) bool { - for part := range strings.SplitSeq(header, ",") { - if utils.EqualFold(utils.TrimSpace(part), token) { - return true - } - } - return false -} - func shouldSkip(c fiber.Ctx) bool { if c.Method() == fiber.MethodHead { return true } - status := c.Response().StatusCode() + status := c.Res().StatusCode() if status < 200 || status == fiber.StatusNoContent || status == fiber.StatusResetContent || status == fiber.StatusNotModified || status == fiber.StatusPartialContent || c.Get(fiber.HeaderRange) != "" || - hasToken(c.Get(fiber.HeaderCacheControl), "no-transform") || - hasToken(c.GetRespHeader(fiber.HeaderCacheControl), "no-transform") { + c.HasHeaderValue(fiber.HeaderCacheControl, "no-transform") || + headerlist.ContainsFold(c.GetRespHeader(fiber.HeaderCacheControl), "no-transform") { return true } - // Skip body length check for streaming responses to avoid materializing the stream - if !c.Response().IsBodyStream() && len(c.Response().Body()) == 0 { + // Written counts a stream without draining it, so a streaming response is + // never mistaken for an empty one. + if !c.Res().Written() { return true } @@ -49,7 +42,7 @@ func appendVaryAcceptEncoding(c fiber.Ctx) { c.Set(fiber.HeaderVary, fiber.HeaderAcceptEncoding) return } - if hasToken(vary, "*") || hasToken(vary, fiber.HeaderAcceptEncoding) { + if headerlist.ContainsFold(vary, "*") || headerlist.ContainsFold(vary, fiber.HeaderAcceptEncoding) { return } c.Set(fiber.HeaderVary, vary+", "+fiber.HeaderAcceptEncoding) @@ -118,11 +111,25 @@ func New(config ...Config) fiber.Handler { return nil } - compressor(c.RequestCtx()) + // Negotiate with weights, wildcards and lists honored (RFC 9110 §12.5.3). + // A request may carry several Accept-Encoding field lines; RFC 9110 §5.3 + // treats them as one comma-separated list, which AcceptEncoding joins. + encoding := negotiateEncoding(c.AcceptEncoding()) + if encoding == "" { + appendVaryAcceptEncoding(c) + return nil + } + + compressWith(c, compressor, encoding) if tag := c.GetRespHeader(fiber.HeaderETag); tag != "" && !strings.HasPrefix(tag, "W/") { if c.GetRespHeader(fiber.HeaderContentEncoding) != "" { - c.Set(fiber.HeaderETag, string(etag.Generate(c.Response().Body()))) + if c.Response().IsBodyStream() { + // The encoded bytes are not in memory to hash; a weak validator still names the representation. + c.Set(fiber.HeaderETag, "W/"+tag) + } else { + c.Set(fiber.HeaderETag, string(etag.Generate(c.Response().Body()))) + } } } @@ -131,3 +138,74 @@ func New(config ...Config) fiber.Handler { return nil } } + +// supportedEncodings lists the content codings the middleware can produce, in preference order. +var supportedEncodings = [...]string{"br", "zstd", "gzip", "deflate"} + +// negotiateEncoding picks the supported coding the client weighs highest in +// Accept-Encoding (RFC 9110 §12.5.3); "" when none is acceptable or the header is absent. +func negotiateEncoding(accept string) string { + best := "" + bestQuality := 0.0 + for _, offer := range supportedEncodings { + if quality := encodingQuality(accept, offer); quality > bestQuality { + best, bestQuality = offer, quality + } + } + return best +} + +// encodingQuality returns the weight Accept-Encoding gives a coding: its own entry, else the wildcard's, else 0. +func encodingQuality(accept, offer string) float64 { + wildcard := 0.0 + for element := range headerlist.All(accept) { + token, params := element, "" + if i := strings.IndexByte(element, ';'); i >= 0 { + // VisitHeaderParams expects the parameters with their leading ';'. + token, params = element[:i], element[i:] + } + token = utils.TrimSpace(token) + if token != "*" && !utils.EqualFold(token, offer) { + continue + } + // An element carries other parameters than the weight, and an absent or + // malformed q leaves the default weight of 1 (RFC 9110 §12.4.2). + quality := 1.0 + if params != "" { + fasthttp.VisitHeaderParams(utils.UnsafeBytes(params), func(key, value []byte) bool { + if len(key) == 1 && (key[0] == 'q' || key[0] == 'Q') { + if parsed, err := fasthttp.ParseUfloat(value); err == nil { + quality = parsed + } + return false + } + return true + }) + } + if token == "*" { + wildcard = quality + continue + } + return quality + } + return wildcard +} + +// compressWith runs fasthttp's compressor for the negotiated encoding, handing +// it the bare token, and restores the client's Accept-Encoding afterwards. +func compressWith(c fiber.Ctx, compressor fasthttp.RequestHandler, encoding string) { + header := &c.Request().Header + lines := header.PeekAll(fiber.HeaderAcceptEncoding) + saved := make([][]byte, len(lines)) + for i, line := range lines { + saved[i] = utils.CopyBytes(line) + } + + header.Set(fiber.HeaderAcceptEncoding, encoding) + compressor(c.RequestCtx()) + + header.Del(fiber.HeaderAcceptEncoding) + for _, line := range saved { + header.AddBytesV(fiber.HeaderAcceptEncoding, line) + } +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/cors.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/cors.go index 6baf146c..bc866dc4 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/cors.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/cors.go @@ -1,17 +1,79 @@ package cors import ( + "slices" "strconv" "strings" "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/headerlookup" + originpkg "github.com/gofiber/fiber/v3/internal/origin" "github.com/gofiber/fiber/v3/log" "github.com/gofiber/utils/v2" utilsstrings "github.com/gofiber/utils/v2/strings" ) +// corsSchemes is the scheme policy for Access-Control-Allow-Origin: any +// scheme, since the browser is the party enforcing the check and CORS is +// used beyond http(s). +const corsSchemes = originpkg.AnyScheme + const redactedValue = "[redacted]" +// headerLists holds the comma-joined forms of the list-valued CORS response +// headers. Their sources are fixed when New returns, so each is built once +// there instead of being re-joined on every request that emits it. +type headerLists struct { + allowMethods string + allowHeaders string + exposeHeaders string + + // Whether each list was configured at all, which is not the same question + // as whether its joined form is empty: AllowHeaders: []string{""} is a + // configured list that joins to "". For Access-Control-Allow-Headers the + // difference decides the response — an empty value authorizes no headers, + // while an absent list falls back to echoing whatever the request asked + // for in Access-Control-Request-Headers. + hasAllowMethods bool + hasAllowHeaders bool + hasExposeHeaders bool +} + +// Vary takes its field names variadically, and a fresh "..." argument list is +// a slice the compiler has to heap-allocate: Vary's result reaches the header +// store, so escape analysis marks the elements as leaking even though fasthttp +// copies the bytes. Passing a package-level slice with "..." hands the callee +// the existing backing array instead, which removed the only allocation on the +// simple-request path and three of the four on preflight. They are only ever +// passed through vary below, which keeps the shared arrays away from a Ctx +// that might write to them. +var ( + varyOrigin = []string{fiber.HeaderOrigin} + varyPreflight = []string{fiber.HeaderAccessControlRequestMethod, fiber.HeaderAccessControlRequestHeaders, fiber.HeaderOrigin} + varyPreflightPrivate = []string{ + fiber.HeaderAccessControlRequestMethod, + fiber.HeaderAccessControlRequestHeaders, + fiber.HeaderAccessControlRequestPrivateNetwork, + fiber.HeaderOrigin, + } +) + +// vary adds fields to the Vary response header. +// +// The lists above are shared by every request this middleware serves, so they +// must not reach an implementation that could write to them: a custom Ctx is +// free to sort or otherwise rewrite its variadic argument, and doing that to a +// package-level array would corrupt the field names of later responses and +// race with the requests running alongside. DefaultCtx only reads what Vary is +// given, so it gets the shared slice; anything else gets a copy of its own. +func vary(c fiber.Ctx, fields []string) { + if dc, ok := c.(*fiber.DefaultCtx); ok { + dc.Vary(fields...) + return + } + c.Vary(slices.Clone(fields)...) +} + // isOriginSerializedOrNull checks if the origin is a serialized origin or the literal "null". // It returns two booleans: (isSerialized, isNull). func isOriginSerializedOrNull(originHeaderRaw string) (isSerialized, isNull bool) { //nolint:nonamedreturns // gocritic unnamedResult prefers naming serialization and null status results @@ -19,7 +81,7 @@ func isOriginSerializedOrNull(originHeaderRaw string) (isSerialized, isNull bool return false, true } - originIsSerialized, _ := normalizeOrigin(originHeaderRaw) + _, originIsSerialized := originpkg.Normalize(originHeaderRaw, corsSchemes) return originIsSerialized, false } @@ -55,7 +117,7 @@ func New(config ...Config) fiber.Handler { // allowOrigins is a set of strings that contains the allowed origins // defined in the 'AllowOrigins' configuration. allowOrigins := make(map[string]struct{}, len(cfg.AllowOrigins)) - allowSubOrigins := []subdomain{} + allowSubOrigins := []originpkg.Subdomain{} // Validate and normalize static AllowOrigins allowAllOrigins := len(cfg.AllowOrigins) == 0 && cfg.AllowOriginsFunc == nil @@ -66,24 +128,14 @@ func New(config ...Config) fiber.Handler { } trimmedOrigin := utils.TrimSpace(origin) - if before, after, found := strings.Cut(trimmedOrigin, "://*."); found { - withoutWildcard := before + "://" + after - isValid, normalizedOrigin := normalizeOrigin(withoutWildcard) - if !isValid { - panic("[CORS] Invalid origin format in configuration: " + maskValue(trimmedOrigin)) - } - scheme, host, ok := strings.Cut(normalizedOrigin, "://") - if !ok { - panic("[CORS] Invalid origin format after normalization:" + maskValue(trimmedOrigin)) - } - sd := subdomain{prefix: scheme + "://", suffix: host} - allowSubOrigins = append(allowSubOrigins, sd) + pattern, ok := originpkg.ParsePattern(trimmedOrigin, corsSchemes) + if !ok { + panic("[CORS] Invalid origin format in configuration: " + maskValue(trimmedOrigin)) + } + if pattern.Wildcard { + allowSubOrigins = append(allowSubOrigins, pattern.Subdomain) } else { - isValid, normalizedOrigin := normalizeOrigin(trimmedOrigin) - if !isValid { - panic("[CORS] Invalid origin format in configuration: " + maskValue(trimmedOrigin)) - } - allowOrigins[normalizedOrigin] = struct{}{} + allowOrigins[pattern.Origin] = struct{}{} } } @@ -100,6 +152,25 @@ func New(config ...Config) fiber.Handler { // Convert int to string maxAge := strconv.Itoa(cfg.MaxAge) + // The list-valued response headers are built from configuration that + // cannot change once New returns, so they are joined here rather than on + // every request. strings.Join was the only remaining allocation on the + // preflight path. + lists := headerLists{ + hasAllowMethods: len(cfg.AllowMethods) > 0, + hasAllowHeaders: len(cfg.AllowHeaders) > 0, + hasExposeHeaders: len(cfg.ExposeHeaders) > 0, + } + if lists.hasAllowMethods { + lists.allowMethods = strings.Join(cfg.AllowMethods, ", ") + } + if lists.hasAllowHeaders { + lists.allowHeaders = strings.Join(cfg.AllowHeaders, ", ") + } + if lists.hasExposeHeaders { + lists.exposeHeaders = strings.Join(cfg.ExposeHeaders, ", ") + } + // Return new handler return func(c fiber.Ctx) error { // Don't execute middleware if Next returns true @@ -107,8 +178,11 @@ func New(config ...Config) fiber.Handler { return c.Next() } - // Get origin header preserving the original case for the response - originHeaderRaw := c.Get(fiber.HeaderOrigin) + // Every request header here is read case-insensitively, as csrf already + // does: Ctx.Get is byte-exact, so under DisableHeaderNormalizing the + // lower-case names HTTP/2 sends read as absent and CORS never applied. + // Origin, with the original case kept for the response. + originHeaderRaw, _ := headerlookup.Value(c, fiber.HeaderOrigin) originHeader := utilsstrings.ToLower(originHeaderRaw) // If the request does not have Origin header, the request is outside the scope of CORS @@ -116,19 +190,24 @@ func New(config ...Config) fiber.Handler { // See https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches // Unless all origins are allowed, we include the Vary header to cache the response correctly if !allowAllOrigins { - c.Vary(fiber.HeaderOrigin) + vary(c, varyOrigin) } return c.Next() } - // If it's a preflight request and doesn't have Access-Control-Request-Method header, it's outside the scope of CORS - if c.Method() == fiber.MethodOptions && c.Get(fiber.HeaderAccessControlRequestMethod) == "" { + // If it's a preflight request and doesn't have Access-Control-Request-Method header, it's outside the scope of CORS. + // The header is read only for OPTIONS, so plain cross-origin requests skip the lookup. + requestMethod := "" + if c.Method() == fiber.MethodOptions { + requestMethod, _ = headerlookup.Value(c, fiber.HeaderAccessControlRequestMethod) + } + if c.Method() == fiber.MethodOptions && requestMethod == "" { // Response to OPTIONS request should not be cached but, // some caching can be configured to cache such responses. // To Avoid poisoning the cache, we include the Vary header // for non-CORS OPTIONS requests: - c.Vary(fiber.HeaderOrigin) + vary(c, varyOrigin) return c.Next() } @@ -145,7 +224,7 @@ func New(config ...Config) fiber.Handler { } // Check if the origin is in the list of allowed subdomains - if allowOrigin == "" && matchSubdomainOrigin(allowSubOrigins, originHeader) { + if allowOrigin == "" && originpkg.MatchAny(allowSubOrigins, originHeader, corsSchemes) { allowOrigin = originHeaderRaw } } @@ -165,9 +244,9 @@ func New(config ...Config) fiber.Handler { if c.Method() != fiber.MethodOptions { if !allowAllOrigins { // See https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches - c.Vary(fiber.HeaderOrigin) + vary(c, varyOrigin) } - setSimpleHeaders(c, allowOrigin, &cfg) + setSimpleHeaders(c, allowOrigin, &cfg, &lists) return c.Next() } @@ -175,26 +254,35 @@ func New(config ...Config) fiber.Handler { // Response to OPTIONS request should not be cached but, // some caching can be configured to cache such responses. - // To Avoid poisoning the cache, we include the Vary header - // of preflight responses: - c.Vary(fiber.HeaderAccessControlRequestMethod) - c.Vary(fiber.HeaderAccessControlRequestHeaders) - if cfg.AllowPrivateNetwork && c.Get(fiber.HeaderAccessControlRequestPrivateNetwork) == "true" { - c.Vary(fiber.HeaderAccessControlRequestPrivateNetwork) + // To avoid poisoning the cache, we include the Vary header + // of preflight responses, set in a single variadic Vary call + // per branch since every Vary call scans all response headers. + privateNetworkRequested := false + if cfg.AllowPrivateNetwork { + // Read only when the feature is on: with the default config the + // header's value is discarded, so the lookup would be pure cost. + privateNetwork, _ := headerlookup.Value(c, fiber.HeaderAccessControlRequestPrivateNetwork) + privateNetworkRequested = privateNetwork == "true" + } + if privateNetworkRequested { + vary(c, varyPreflightPrivate) c.Set(fiber.HeaderAccessControlAllowPrivateNetwork, "true") + } else { + vary(c, varyPreflight) } - c.Vary(fiber.HeaderOrigin) - setPreflightHeaders(c, allowOrigin, maxAge, &cfg) + setPreflightHeaders(c, allowOrigin, maxAge, &cfg, &lists) // Set Preflight headers - if len(cfg.AllowMethods) > 0 { - c.Set(fiber.HeaderAccessControlAllowMethods, strings.Join(cfg.AllowMethods, ", ")) + if lists.hasAllowMethods { + c.Set(fiber.HeaderAccessControlAllowMethods, lists.allowMethods) } - if len(cfg.AllowHeaders) > 0 { - c.Set(fiber.HeaderAccessControlAllowHeaders, strings.Join(cfg.AllowHeaders, ", ")) + if lists.hasAllowHeaders { + c.Set(fiber.HeaderAccessControlAllowHeaders, lists.allowHeaders) } else { - h := c.Get(fiber.HeaderAccessControlRequestHeaders) + // Combined, not Value: this one is a list field, so a peer may + // legally split it over two lines and both name headers to allow. + h := headerlookup.Combined(c, fiber.HeaderAccessControlRequestHeaders) if h != "" { c.Set(fiber.HeaderAccessControlAllowHeaders, h) } @@ -206,7 +294,7 @@ func New(config ...Config) fiber.Handler { } // Function to set Simple CORS headers -func setSimpleHeaders(c fiber.Ctx, allowOrigin string, cfg *Config) { +func setSimpleHeaders(c fiber.Ctx, allowOrigin string, cfg *Config, lists *headerLists) { if cfg == nil { return } @@ -225,15 +313,16 @@ func setSimpleHeaders(c fiber.Ctx, allowOrigin string, cfg *Config) { c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin) } - // Set Expose-Headers if not empty - if len(cfg.ExposeHeaders) > 0 { - c.Set(fiber.HeaderAccessControlExposeHeaders, strings.Join(cfg.ExposeHeaders, ", ")) + // Set Expose-Headers if not empty. lists is nil-tolerant for the same + // reason cfg is: the helper is called directly by tests. + if lists != nil && lists.hasExposeHeaders { + c.Set(fiber.HeaderAccessControlExposeHeaders, lists.exposeHeaders) } } // Function to set Preflight CORS headers -func setPreflightHeaders(c fiber.Ctx, allowOrigin, maxAge string, cfg *Config) { - setSimpleHeaders(c, allowOrigin, cfg) +func setPreflightHeaders(c fiber.Ctx, allowOrigin, maxAge string, cfg *Config, lists *headerLists) { + setSimpleHeaders(c, allowOrigin, cfg, lists) // Set MaxAge if set if cfg != nil && cfg.MaxAge > 0 { diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/utils.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/utils.go deleted file mode 100644 index 0a9548b6..00000000 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/cors/utils.go +++ /dev/null @@ -1,96 +0,0 @@ -package cors - -import ( - "net/url" - "strings" - - utilsstrings "github.com/gofiber/utils/v2/strings" -) - -// normalizeOrigin checks if the provided origin is in a correct format -// and normalizes it by removing any path or trailing slash. -// It returns a boolean indicating whether the origin is valid -// and the normalized origin. -func normalizeOrigin(origin string) (valid bool, normalized string) { //nolint:nonamedreturns // gocritic unnamedResult prefers naming validity and normalized origin results - parsedOrigin, err := url.Parse(origin) - if err != nil { - return false, "" - } - - // Don't allow a wildcard with a protocol - // wildcards cannot be used within any other value. For example, the following header is not valid: - // Access-Control-Allow-Origin: https://* - if strings.IndexByte(parsedOrigin.Host, '*') >= 0 { - return false, "" - } - - // Validate there is a host present. The presence of a path, query, or fragment components - // is checked, but a trailing "/" (indicative of the root) is allowed for the path and will be normalized - if parsedOrigin.User != nil || - parsedOrigin.Host == "" || - (parsedOrigin.Path != "" && parsedOrigin.Path != "/") || - parsedOrigin.RawQuery != "" || - parsedOrigin.Fragment != "" { - return false, "" - } - - // Normalize the origin by constructing it from the scheme and host. - // The path or trailing slash is not included in the normalized origin. - return true, utilsstrings.ToLower(parsedOrigin.Scheme) + "://" + utilsstrings.ToLower(parsedOrigin.Host) -} - -type subdomain struct { - // The wildcard pattern - prefix string - suffix string -} - -func matchSubdomainOrigin(subdomains []subdomain, origin string) bool { - if len(subdomains) == 0 { - return false - } - - isValid, normalizedOrigin := normalizeOrigin(origin) - if !isValid || normalizedOrigin != origin { - return false - } - - for _, sub := range subdomains { - if sub.matchNormalized(origin) { - return true - } - } - - return false -} - -func (s subdomain) matchNormalized(o string) bool { - // Not a subdomain if not long enough for a dot separator. - if len(o) < len(s.prefix)+len(s.suffix)+1 { - return false - } - - if !strings.HasPrefix(o, s.prefix) || !strings.HasSuffix(o, s.suffix) { - return false - } - - // Check for the dot separator and validate that there is at least one - // non-empty label between prefix and suffix. Empty labels like - // "https://.example.com" or "https://..example.com" should not match. - suffixStartIndex := len(o) - len(s.suffix) - if suffixStartIndex <= len(s.prefix) { - return false - } - if o[suffixStartIndex-1] != '.' { - return false - } - - // Extract the subdomain part (without the trailing dot) and ensure it - // doesn't contain empty labels. - sub := o[len(s.prefix) : suffixStartIndex-1] - if sub == "" || strings.HasPrefix(sub, ".") || strings.HasSuffix(sub, ".") || strings.Contains(sub, "..") { - return false - } - - return true -} diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/etag/etag.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/etag/etag.go index 9a6b6364..e804c3d8 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/etag/etag.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/etag/etag.go @@ -1,13 +1,16 @@ package etag import ( - "bytes" "hash/crc32" "math" "slices" "strings" "github.com/gofiber/fiber/v3" + internaletag "github.com/gofiber/fiber/v3/internal/etag" + "github.com/gofiber/fiber/v3/internal/fieldname" + "github.com/gofiber/fiber/v3/internal/headerlist" + "github.com/gofiber/fiber/v3/internal/headerlookup" "github.com/gofiber/utils/v2" "github.com/valyala/bytebufferpool" ) @@ -68,7 +71,7 @@ func New(config ...Config) fiber.Handler { } // Don't generate ETags for invalid responses - if c.Response().StatusCode() != fiber.StatusOK { + if c.Res().StatusCode() != fiber.StatusOK { return nil } body := c.Response().Body() @@ -76,8 +79,15 @@ func New(config ...Config) fiber.Handler { if len(body) == 0 { return nil } - // Skip ETag if header is already present - if c.Response().Header.PeekBytes(normalizedHeaderETag) != nil { + // Skip ETag if any field line is already present, whatever case the + // handler spelled the name in — a second line would be a conflicting + // validator (RFC 9110 Section 8.8.3). + // + // Both halves of the guard are needed: fasthttp canonicalizes ETag to + // "Etag", so a store of canonical names still holds a spelling the + // byte-exact PeekAll(fiber.HeaderETag) misses while normalizing is off. + respHeader := &c.Response().Header + if len(fieldname.Lines(respHeader, fiber.HeaderETag, headerlookup.Canonical(c) && fieldname.Canonical(respHeader))) > 0 { return nil } @@ -96,58 +106,26 @@ func New(config ...Config) fiber.Handler { // The ETag header is sent on both 200 and 304 responses (RFC 9110 §15.4.5). c.Response().Header.SetCanonical(normalizedHeaderETag, etag) - // Get ETag header from request - clientEtag := c.Request().Header.Peek(fiber.HeaderIfNoneMatch) - - if isNoneMatch(clientEtag, etag) { - c.RequestCtx().ResetBody() - - return c.SendStatus(fiber.StatusNotModified) + // 304 is defined for GET and HEAD only (RFC 9110 §13.1.2); other methods pass through. + if method := c.Method(); method != fiber.MethodGet && method != fiber.MethodHead { + return nil } - return nil - } -} + // Get ETag header from request. If-None-Match is a list field: repeated + // lines are one combined list (RFC 9110 Section 5.2) and the name + // matches case-insensitively, agreeing with the core Fresh path. + clientEtag := headerlist.Join(fieldname.Lines(&c.Request().Header, fiber.HeaderIfNoneMatch, headerlookup.Canonical(c))) -// isNoneMatch reports whether any entity tag in the If-None-Match header value -// matches the response ETag, using the weak comparison required for -// If-None-Match by RFC 9110 §8.8.3.2. -func isNoneMatch(header, etag []byte) bool { - header = utils.TrimSpace(header) - if len(header) == 0 { - return false - } - if len(header) == 1 && header[0] == '*' { - return true - } + // Both slices are only read for the duration of the comparison and + // neither is retained, so the unsafe views cannot outlive them. + if internaletag.AnyMatch(utils.UnsafeString(clientEtag), utils.UnsafeString(etag)) { + c.Res().ResetBody() - for len(header) > 0 { - // RFC 9110 allows a comma inside an opaque-tag, so this split can - // mis-parse such tags. It fails open and Fiber's ETags never contain - // commas, so it is acceptable here. - entry, rest, _ := bytes.Cut(header, []byte(",")) - header = rest - if etagWeakMatch(utils.TrimSpace(entry), etag) { - return true + return c.SendStatus(fiber.StatusNotModified) } - } - - return false -} -// etagWeakMatch compares two entity tags, ignoring weak indicators -// (RFC 9110 §8.8.3.2). Both tags must be quoted to match. -func etagWeakMatch(a, b []byte) bool { - a = bytes.TrimPrefix(a, weakPrefix) - b = bytes.TrimPrefix(b, weakPrefix) - if len(a) < 2 || a[0] != '"' || a[len(a)-1] != '"' { - return false - } - if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { - return false + return nil } - - return bytes.Equal(a, b) } // isEventStream reports whether the response is a Server-Sent Events stream. diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/favicon/favicon.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/favicon/favicon.go index f71c6f65..57bb15dd 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/favicon/favicon.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/favicon/favicon.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "io/fs" + "math" "os" "strconv" @@ -101,7 +102,11 @@ func New(config ...Config) fiber.Handler { } func readLimited(reader io.Reader, maxBytes int64) ([]byte, error) { - limit := maxBytes + 1 + // One byte past the limit tells a too-large file apart, without overflowing. + limit := maxBytes + if limit < math.MaxInt64 { + limit++ + } data, err := io.ReadAll(io.LimitReader(reader, limit)) if err != nil { return nil, fmt.Errorf("favicon: read limited: %w", err) diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/config.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/config.go index e2f53707..9fd9e50b 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/config.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/config.go @@ -32,7 +32,9 @@ type Config struct { // } MaxFunc func(c fiber.Ctx) int - // A function to dynamically calculate the expiration time for rate limiter entries + // A function to dynamically calculate the expiration time for rate limiter entries. + // Window accounting is whole-second, so a positive value below one second is floored to + // one second. A zero or negative value falls back to the default expiration. // // Default: A function that returns the static `Expiration` value from the config. ExpirationFunc func(c fiber.Ctx) time.Duration @@ -43,7 +45,11 @@ type Config struct { // utils.Timestamp() is used on the hot path. clock func() time.Time - // KeyGenerator allows you to generate custom keys, by default c.IP() is used + // KeyGenerator allows you to generate custom keys, by default c.IP() is used. + // Behind a reverse proxy, c.IP() only identifies a client when TrustProxy, + // TrustProxyConfig and ProxyHeader are configured, plus EnableIPValidation when + // the header is a chain the proxy appends to (X-Forwarded-For); otherwise it is + // the proxy's address or the raw, client-influenced forwarded header. // // Default: func(c fiber.Ctx) string { // return c.IP() @@ -127,7 +133,7 @@ func configDefault(config ...Config) Config { if cfg.Max <= 0 { cfg.Max = ConfigDefault.Max } - if int(cfg.Expiration.Seconds()) <= 0 { + if cfg.Expiration <= 0 { cfg.Expiration = ConfigDefault.Expiration } if cfg.KeyGenerator == nil { @@ -152,6 +158,19 @@ func configDefault(config ...Config) Config { return cfg } +// windowSeconds turns a per-request expiration into the whole-second window used +// for accounting. A positive sub-second value floors to 1s instead of truncating +// to a 0-second window (NaN rate in sliding, no limiting at all in fixed). +func windowSeconds(d time.Duration) uint64 { + if d <= 0 { + d = ConfigDefault.Expiration + } + if sec := uint64(d.Seconds()); sec > 0 { + return sec + } + return 1 +} + // currentSecond returns the current Unix time in whole seconds used for window // accounting. Production reads the cached utils.Timestamp() (refreshed by a 1s // ticker) to keep the hot path allocation- and syscall-free; tests can inject a diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter.go index 63e39c1e..3f32c567 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter.go @@ -2,6 +2,8 @@ package limiter import ( "errors" + "hash/maphash" + "sync" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/internal/nilerror" @@ -14,6 +16,25 @@ const ( xRateLimitReset = "X-RateLimit-Reset" ) +// lockShards is a power of two so the shard index is a mask. A fixed array stays +// allocation-free and, unlike a per-key map, cannot be grown with fresh keys. +const lockShards = 64 + +// keySeed randomizes the shard mapping per process, so a client cannot pick +// keys (by default its IP) that all land on one shard. +var keySeed = maphash.MakeSeed() + +// keyedMutex serializes the read-modify-write per key, so one client's storage +// round-trip no longer blocks every other client. +type keyedMutex [lockShards]sync.Mutex + +// lock acquires the shard owning key and returns it for unlocking. +func (k *keyedMutex) lock(key string) *sync.Mutex { + mu := &k[maphash.String(keySeed, key)&(lockShards-1)] + mu.Lock() + return mu +} + // Handler defines a rate-limiting strategy that can produce a middleware // handler using the provided configuration. type Handler interface { @@ -32,7 +53,7 @@ func New(config ...Config) fiber.Handler { // getEffectiveStatusCode returns the actual status code, considering both the error and response status func getEffectiveStatusCode(c fiber.Ctx, err error) int { if nilerror.IsNil(err) { - return c.Response().StatusCode() + return c.Res().StatusCode() } // If there's an error and it's a *fiber.Error, use its status code @@ -42,5 +63,5 @@ func getEffectiveStatusCode(c fiber.Ctx, err error) int { } // Otherwise, use the response status code - return c.Response().StatusCode() + return c.Res().StatusCode() } diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_fixed.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_fixed.go index 36ccf446..31f75480 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_fixed.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_fixed.go @@ -2,8 +2,6 @@ package limiter import ( "fmt" - "strconv" - "sync" "github.com/gofiber/fiber/v3" "github.com/gofiber/utils/v2" @@ -20,7 +18,7 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { } // Limiter variables - mux := &sync.RWMutex{} + locks := new(keyedMutex) // Create manager to simplify storage operations ( see manager.go ) manager := newManager(cfg.Storage, !cfg.DisableValueRedaction) @@ -38,25 +36,23 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { return c.Next() } - // Generate expiration from generator - expirationDuration := cfg.ExpirationFunc(c) - if expirationDuration <= 0 { - expirationDuration = ConfigDefault.Expiration - } - expiration := uint64(expirationDuration.Seconds()) + // Generate expiration from generator. The storage TTL is derived from the + // window so a sub-second value cannot expire the entry mid-window. + expiration := windowSeconds(cfg.ExpirationFunc(c)) + expirationDuration, _ := secondsToDuration(expiration) // Get key from request key := cfg.KeyGenerator(c) // Lock entry - mux.Lock() + mu := locks.lock(key) reqCtx := c.Context() // Get entry from pool and release when finished e, err := manager.get(reqCtx, key) if err != nil { - mux.Unlock() + mu.Unlock() return err } @@ -84,26 +80,26 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { // Update storage if setErr := manager.set(reqCtx, key, e, expirationDuration); setErr != nil { - mux.Unlock() + mu.Unlock() return fmt.Errorf("limiter: failed to persist state: %w", setErr) } // Unlock entry - mux.Unlock() + mu.Unlock() // Check if hits exceed the max if remaining < 0 { // Return response with Retry-After header // https://tools.ietf.org/html/rfc6584 if !cfg.DisableHeaders { - c.Set(fiber.HeaderRetryAfter, strconv.FormatUint(resetInSec, 10)) + c.Set(fiber.HeaderRetryAfter, utils.FormatUint(resetInSec)) } // Call LimitReached handler return cfg.LimitReached(c) } - // Continue stack for reaching c.Response().StatusCode() + // Continue stack for reaching c.Res().StatusCode() // Store err for returning err = c.Next() @@ -114,10 +110,10 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { if (cfg.SkipSuccessfulRequests && statusCode < fiber.StatusBadRequest) || (cfg.SkipFailedRequests && statusCode >= fiber.StatusBadRequest) { // Lock entry - mux.Lock() + mu = locks.lock(key) // rehash: c.Next() may have rewritten an unsafe key entry, getErr := manager.get(reqCtx, key) if getErr != nil { - mux.Unlock() + mu.Unlock() return getErr } e = entry @@ -128,11 +124,11 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { } remaining = maxRequests - e.currHits if setErr := manager.set(reqCtx, key, e, expirationDuration); setErr != nil { - mux.Unlock() + mu.Unlock() return fmt.Errorf("limiter: failed to persist state: %w", setErr) } // Unlock entry - mux.Unlock() + mu.Unlock() } // On the skip path currHits can exceed maxRequests (blocked requests @@ -143,9 +139,9 @@ func (FixedWindow) New(cfg *Config) fiber.Handler { // We can continue, update RateLimit headers if !cfg.DisableHeaders { - c.Set(xRateLimitLimit, strconv.Itoa(maxRequests)) - c.Set(xRateLimitRemaining, strconv.Itoa(remaining)) - c.Set(xRateLimitReset, strconv.FormatUint(resetInSec, 10)) + c.Set(xRateLimitLimit, utils.FormatInt(int64(maxRequests))) + c.Set(xRateLimitRemaining, utils.FormatInt(int64(remaining))) + c.Set(xRateLimitReset, utils.FormatUint(resetInSec)) } return err diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_sliding.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_sliding.go index dbe514b7..021bc56e 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_sliding.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/limiter_sliding.go @@ -3,8 +3,6 @@ package limiter import ( "fmt" "math" - "strconv" - "sync" "time" "github.com/gofiber/fiber/v3" @@ -22,7 +20,7 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { } // Limiter variables - mux := &sync.RWMutex{} + locks := new(keyedMutex) // Create manager to simplify storage operations ( see manager.go ) manager := newManager(cfg.Storage, !cfg.DisableValueRedaction) @@ -41,24 +39,20 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { } // Generate expiration from generator - expirationDuration := cfg.ExpirationFunc(c) - if expirationDuration <= 0 { - expirationDuration = ConfigDefault.Expiration - } - expiration := uint64(expirationDuration.Seconds()) + expiration := windowSeconds(cfg.ExpirationFunc(c)) // Get key from request key := cfg.KeyGenerator(c) // Lock entry - mux.Lock() + mu := locks.lock(key) reqCtx := c.Context() // Get entry from pool and release when finished e, err := manager.get(reqCtx, key) if err != nil { - mux.Unlock() + mu.Unlock() return err } @@ -94,26 +88,26 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { // Otherwise, after the end of "sample window", attackers could launch // a new request with the full window length. if setErr := manager.set(reqCtx, key, e, ttlDuration(resetInSec, expiration)); setErr != nil { - mux.Unlock() + mu.Unlock() return fmt.Errorf("limiter: failed to persist state: %w", setErr) } // Unlock entry - mux.Unlock() + mu.Unlock() // Check if hits exceed the allowed maximum for this request if remaining < 0 { // Return response with Retry-After header // https://tools.ietf.org/html/rfc6584 if !cfg.DisableHeaders { - c.Set(fiber.HeaderRetryAfter, strconv.FormatUint(resetInSec, 10)) + c.Set(fiber.HeaderRetryAfter, utils.FormatUint(resetInSec)) } // Call LimitReached handler return cfg.LimitReached(c) } - // Continue stack for reaching c.Response().StatusCode() + // Continue stack for reaching c.Res().StatusCode() // Store err for returning err = c.Next() @@ -125,10 +119,10 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { if skipHit || !cfg.DisableHeaders { // Lock entry - mux.Lock() + mu = locks.lock(key) // rehash: c.Next() may have rewritten an unsafe key entry, getErr := manager.get(reqCtx, key) if getErr != nil { - mux.Unlock() + mu.Unlock() return getErr } e = entry @@ -146,11 +140,11 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { rate = int(math.Ceil(float64(e.prevHits)*weight)) + e.currHits remaining = maxRequests - rate if setErr := manager.set(reqCtx, key, e, ttlDuration(resetInSec, expiration)); setErr != nil { - mux.Unlock() + mu.Unlock() return fmt.Errorf("limiter: failed to persist state: %w", setErr) } // Unlock entry - mux.Unlock() + mu.Unlock() // rate can exceed maxRequests (blocked requests persist their // increment), so clamp remaining to keep the header >= 0. @@ -160,9 +154,9 @@ func (SlidingWindow) New(cfg *Config) fiber.Handler { // We can continue, update RateLimit headers if !cfg.DisableHeaders { - c.Set(xRateLimitLimit, strconv.Itoa(maxRequests)) - c.Set(xRateLimitRemaining, strconv.Itoa(remaining)) - c.Set(xRateLimitReset, strconv.FormatUint(resetInSec, 10)) + c.Set(xRateLimitLimit, utils.FormatInt(int64(maxRequests))) + c.Set(xRateLimitRemaining, utils.FormatInt(int64(remaining))) + c.Set(xRateLimitReset, utils.FormatUint(resetInSec)) } } diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/manager.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/manager.go index 7a8b4fad..51d9adef 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/manager.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/limiter/manager.go @@ -2,12 +2,16 @@ package limiter import ( "context" + "crypto/sha256" + "encoding/hex" "fmt" + "strings" "sync" "time" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/internal/memory" + "github.com/gofiber/utils/v2" ) // msgp -file="manager.go" -o="manager_msgp.go" -tests=false -unexported @@ -29,6 +33,47 @@ type manager struct { const redactedKey = "[redacted]" +// maxKeyLength bounds a rate-limit key before it ever reaches storage or the +// in-memory map. +// +// KeyGenerator's default returns c.IP(), which — with app.Config.TrustProxy +// and ProxyHeader set and the (default) EnableIPValidation left off — is the +// raw ProxyHeader value verbatim: an attacker-controlled string with no +// length limit (see the ProxyHeader "Behavior note" in docs/api/fiber.md). A +// custom KeyGenerator can return any other request-derived value just as +// easily. Left unbounded, a client can grow the backing store, or the +// unbounded in-memory map on the default path, by an amount of its own +// choosing on every request with a fresh value. +// +// Bounded here, at the one seam both window strategies call through, so +// neither strategy nor the in-memory fallback nor a future one needs to +// remember to do it. 192 matches middleware/cache's own per-segment bound +// (maxKeyDimensionSegmentLength) for the same reason cache picked it: real +// keys are far shorter, so this only ever engages against abuse. +const maxKeyLength = 192 + +// hashPrefix namespaces a bounded key that was too long to keep verbatim. +// Same literal cache/keygen.go uses, so an operator inspecting either +// middleware's storage sees the same shape; the two are not unified into a +// shared helper because cache's bound also escapes delimiters between +// multiple concatenated segments, a concern this single-segment key has none +// of. +const hashPrefix = "sha256:" + +// boundKey caps key at maxKeyLength, replacing it with a deterministic digest +// when it is too long or already claims the reserved hashPrefix namespace — +// otherwise a short adversarial key could collide with a genuinely-hashed +// long one. Hashing rather than truncating or rejecting keeps distinct +// oversized inputs mapped to distinct buckets and keeps the request rate +// limited rather than either exempted or itself denied. +func boundKey(key string) string { + if len(key) <= maxKeyLength && !strings.HasPrefix(key, hashPrefix) { + return key + } + hash := sha256.Sum256(utils.UnsafeBytes(key)) + return hashPrefix + hex.EncodeToString(hash[:]) +} + func newManager(storage fiber.Storage, shouldRedactKeys bool) *manager { // Create new storage handler manager := &manager{ @@ -64,6 +109,7 @@ func (m *manager) release(e *item) { // get data from storage or memory func (m *manager) get(ctx context.Context, key string) (*item, error) { + key = boundKey(key) if m.storage != nil { raw, err := m.storage.GetWithContext(ctx, key) if err != nil { @@ -95,6 +141,7 @@ func (m *manager) get(ctx context.Context, key string) (*item, error) { // set data to storage or memory func (m *manager) set(ctx context.Context, key string, it *item, exp time.Duration) error { + key = boundKey(key) if m.storage != nil { raw, err := it.MarshalMsg(nil) if err != nil { diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/context_tag.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/context_tag.go index 87017ecd..86a50007 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/context_tag.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/context_tag.go @@ -2,6 +2,7 @@ package logger import ( "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/logtemplate" fiberlog "github.com/gofiber/fiber/v3/log" ) @@ -49,12 +50,15 @@ func RegisterContextTag(name string, extract func(ctx any) string) { panic("logger: RegisterContextTag requires a non-empty name and extractor") } + // Sanitized like every built-in tag: what extract returns is whatever the + // application pulled out of the context, in practice request data, so writing + // it raw lets a CR or LF close the line and start another. fiberlog.MustRegisterContextTag(name, func(output fiberlog.Buffer, ctx any, _ *fiberlog.ContextData, _ string) (int, error) { v := extract(ctx) if v == "" { return 0, nil } - return output.WriteString(v) + return logtemplate.WriteSanitizedString(output, v) }) MustRegisterTag(name, func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { @@ -62,6 +66,6 @@ func RegisterContextTag(name string, extract func(ctx any) string) { if v == "" { return 0, nil } - return output.WriteString(v) + return writeSanitizedString(output, v) }) } diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/default_logger.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/default_logger.go index 4e3882b2..b392ed76 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/default_logger.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/default_logger.go @@ -5,9 +5,12 @@ import ( "io" "os" "strconv" + "time" + "unicode/utf8" "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/internal/logtemplate" + "github.com/gofiber/utils/v2" "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" "github.com/valyala/bytebufferpool" @@ -37,25 +40,61 @@ func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg *Config) error { // Default output when no custom Format or io.Writer is given if cfg.Format == DefaultFormat { // Format error if exist + // The request-derived values below (IP, path, and the chain error, + // which routinely embeds decoded request data) are scrubbed of control + // bytes for the same reason the template tags are: raw CR/LF lets a + // client forge additional access-log lines. See #4341. The method is + // not scrubbed — fasthttp rejects a request line whose method token + // holds one — which keeps this path consistent with ${method}. formatErr := "" if cfg.areColorsEnabled { if data.ChainErr != nil { - formatErr = colors.Red + " | " + data.ChainErr.Error() + colors.Reset + formatErr = colors.Red + " | " + sanitizeLogValue(data.ChainErr.Error()) + colors.Reset } - fmt.Fprintf( - buf, - "%s |%s %3d %s| %13v | %15s |%s %-7s %s| %-"+data.ErrPaddingStr+"s %s\n", - data.Timestamp, - statusColor(c.Response().StatusCode(), &colors), c.Response().StatusCode(), colors.Reset, - data.Stop.Sub(data.Start), - c.IP(), - methodColor(c.Method(), &colors), c.Method(), colors.Reset, - c.Path(), - formatErr, - ) + + // The same line the uncolored branch below writes, with the + // status and method wrapped in their colors. It was one Fprintf + // with the format + // + // "%s |%s %3d %s| %13v | %15s |%s %-7s %s| %-s %s\n" + // + // which reflects over eleven arguments and boxes each: eleven + // allocations and ~2.5x the time of the uncolored branch, on the + // path every terminal user sees. Written in place instead. Two + // details of fmt's output are kept deliberately: it pads by + // runes, so the latency and path columns here count runes where + // the uncolored branch has always counted bytes, and the + // concatenated format string's error padding is parsed the same + // way the uncolored branch parses it. + status := c.Res().StatusCode() + method := c.Method() + errPadding, _ := strconv.Atoi(data.ErrPaddingStr) //nolint:errcheck // It is fine to ignore the error + + buf.WriteString(data.Timestamp) + buf.WriteString(" |") + buf.WriteString(statusColor(status, &colors)) + buf.WriteByte(' ') + appendIntPadded(buf, status, 3) + buf.WriteByte(' ') + buf.WriteString(colors.Reset) + buf.WriteString("| ") + appendDurationColumns(buf, data.Stop.Sub(data.Start), 13) + buf.WriteString(" | ") + writeColumnRight(buf, sanitizeLogValue(c.IP()), 15) + buf.WriteString(" |") + buf.WriteString(methodColor(method, &colors)) + buf.WriteByte(' ') + writeColumnLeft(buf, method, 7) + buf.WriteByte(' ') + buf.WriteString(colors.Reset) + buf.WriteString("| ") + writeColumnLeft(buf, sanitizeLogValue(c.Path()), errPadding) + buf.WriteByte(' ') + buf.WriteString(formatErr) + buf.WriteByte('\n') } else { if data.ChainErr != nil { - formatErr = " | " + data.ChainErr.Error() + formatErr = " | " + sanitizeLogValue(data.ChainErr.Error()) } // Helper function to append fixed-width string with padding @@ -77,16 +116,18 @@ func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg *Config) error { buf.WriteString(data.Timestamp) buf.WriteString(" | ") - // Status Code with 3 fixed width, right aligned - fixedWidth(strconv.Itoa(c.Response().StatusCode()), 3, true) + // Status Code with 3 fixed width, right aligned; appended digit-wise + // to avoid the per-request Itoa string. + appendIntPadded(buf, c.Res().StatusCode(), 3) buf.WriteString(" | ") - // Duration with 13 fixed width, right aligned - fixedWidth(data.Stop.Sub(data.Start).String(), 13, true) + // Duration with 13 fixed width, right aligned; rendered straight + // into the buffer instead of via Duration.String. + appendDurationPadded(buf, data.Stop.Sub(data.Start), 13) buf.WriteString(" | ") // Client IP with 15 fixed width, right aligned - fixedWidth(c.IP(), 15, true) + fixedWidth(sanitizeLogValue(c.IP()), 15, true) buf.WriteString(" | ") // HTTP Method with 7 fixed width, left aligned @@ -95,7 +136,7 @@ func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg *Config) error { // Path with dynamic padding for error message, left aligned errPadding, _ := strconv.Atoi(data.ErrPaddingStr) //nolint:errcheck // It is fine to ignore the error - fixedWidth(c.Path(), errPadding, false) + fixedWidth(sanitizeLogValue(c.Path()), errPadding, false) // Error message buf.WriteString(" ") @@ -150,13 +191,137 @@ func beforeHandlerFunc(cfg *Config) { } } +// maxIntLen is the widest decimal an int64 can render ("-9223372036854775808"), +// so a scratch array of that size lets utils.AppendInt format any of them +// without growing the slice. +const maxIntLen = 20 + +// writeScratch writes s to output one byte at a time. +// +// Handing the slice to output.Write instead would push the caller's scratch +// array onto the heap: Buffer is an interface, so the compiler has to assume +// Write keeps the pointer. That allocation costs more than the extra calls — +// a status code measured 47ns with one 24-byte allocation through Write +// against 21ns and none this way. +func writeScratch(output Buffer, s []byte) (int, error) { + for i, c := range s { + if err := output.WriteByte(c); err != nil { + return i, err + } + } + return len(s), nil +} + +// writePadding writes the spaces that right-align a used-column value in a +// field of the given width, and returns how many it wrote. +func writePadding(output Buffer, width, used int) (int, error) { + written := 0 + for i := used; i < width; i++ { + if err := output.WriteByte(' '); err != nil { + return written, err + } + written++ + } + return written, nil +} + // appendInt writes the decimal form of v into output without going through -// fmt boxing. The 20-byte stack scratch fits any int64; strconv.AppendInt -// only grows the slice when the formatted value exceeds that capacity, which -// cannot happen for a fixed-width int. +// fmt boxing. func appendInt(output Buffer, v int) (int, error) { - var scratch [20]byte - return output.Write(strconv.AppendInt(scratch[:0], int64(v), 10)) + var scratch [maxIntLen]byte + return writeScratch(output, utils.AppendInt(scratch[:0], int64(v))) +} + +// appendIntTag is appendInt right-aligned to width with spaces, the shape +// fmt's "%*d" verbs produced for the colored status column. +func appendIntTag(output Buffer, v, width int) (int, error) { + var scratch [maxIntLen]byte + s := utils.AppendInt(scratch[:0], int64(v)) + + written, err := writePadding(output, width, len(s)) + if err != nil { + return written, err + } + n, err := writeScratch(output, s) + return written + n, err +} + +// appendIntPadded appends the decimal form of v to buf, right-aligned to +// width with spaces, without allocating an intermediate string. +func appendIntPadded(buf *bytebufferpool.ByteBuffer, v, width int) { + var scratch [maxIntLen]byte + s := utils.AppendInt(scratch[:0], int64(v)) + for i := len(s); i < width; i++ { + buf.WriteByte(' ') + } + buf.Write(s) +} + +// maxDurationLen is the widest output time.Duration.String can produce +// ("-2562047h47m16.854775808s"), so a scratch array of that size lets +// utils.AppendDuration render any latency without touching the heap. +const maxDurationLen = 25 + +// appendDurationPadded appends d in time.Duration.String form to buf, +// right-aligned to width with spaces. utils.AppendDuration renders the same +// bytes straight into a stack scratch instead of building the intermediate +// string Duration.String returns, which measured ~17% faster on this column. +// Padding counts bytes, as the string form this replaced did. +func appendDurationPadded(buf *bytebufferpool.ByteBuffer, d time.Duration, width int) { + var scratch [maxDurationLen]byte + s := utils.AppendDuration(scratch[:0], d) + for i := len(s); i < width; i++ { + buf.WriteByte(' ') + } + buf.Write(s) +} + +// appendDurationColumns is appendDurationPadded with the padding counted in +// columns rather than bytes, the width "%13v" produced for the colored default +// format: a sub-millisecond latency renders "µs", whose 'µ' is two bytes but +// one column. +func appendDurationColumns(buf *bytebufferpool.ByteBuffer, d time.Duration, width int) { + var scratch [maxDurationLen]byte + s := utils.AppendDuration(scratch[:0], d) + for i := utf8.RuneCount(s); i < width; i++ { + buf.WriteByte(' ') + } + buf.Write(s) +} + +// writeColumnRight appends s to buf right-aligned in width columns, the shape +// fmt's "%15s" produced for the colored default format. Columns are runes, as +// fmt counted them, so a multi-byte rune takes the one column it displays as. +func writeColumnRight(buf *bytebufferpool.ByteBuffer, s string, width int) { + for pad := width - utf8.RuneCountInString(s); pad > 0; pad-- { + buf.WriteByte(' ') + } + buf.WriteString(s) +} + +// writeColumnLeft is writeColumnRight with the padding after s, the shape +// fmt's "%-7s" produced. +func writeColumnLeft(buf *bytebufferpool.ByteBuffer, s string, width int) { + buf.WriteString(s) + for pad := width - utf8.RuneCountInString(s); pad > 0; pad-- { + buf.WriteByte(' ') + } +} + +// appendDurationTag is appendDurationPadded for the Buffer interface the +// ${latency} tag writes through. Its padding counts runes rather than bytes so +// the column keeps the width fmt's "%13v" produced: a sub-millisecond latency +// renders "µs", whose 'µ' is two bytes but one column. +func appendDurationTag(output Buffer, d time.Duration, width int) (int, error) { + var scratch [maxDurationLen]byte + s := utils.AppendDuration(scratch[:0], d) + + written, err := writePadding(output, width, utf8.RuneCount(s)) + if err != nil { + return written, err + } + n, err := writeScratch(output, s) + return written + n, err } // writeLog writes a msg to w, printing a warning to stderr if the log fails. diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/logger.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/logger.go index bcaa76c7..3a3bc881 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/logger.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/logger.go @@ -120,9 +120,11 @@ func New(config ...Config) fiber.Handler { } else { data.Timestamp = "" } - // These compiled chains are shared across requests. The default logger and - // custom LoggerFunc implementations must only read them, for example via - // logtemplate.ExecuteChains. + // These compiled chains are shared across requests, so a custom + // LoggerFunc must only read them — never append to or reorder them. + // Walk Data.TemplateChain and Data.LogFuncChain in step; the helper the + // default logger uses for this lives in internal/ and is not importable + // from outside the module. data.TemplateChain = templateChain data.LogFuncChain = logFuncChain // put data back in the pool diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/tags.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/tags.go index 199dd312..fa344d68 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/tags.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/tags.go @@ -2,7 +2,6 @@ package logger import ( "errors" - "fmt" "maps" "strings" "sync" @@ -91,49 +90,76 @@ func createTagMap(cfg *Config) map[string]LogFunc { // Set default tags tagFunctions := map[string]LogFunc{ TagReferer: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Get(fiber.HeaderReferer)) + return writeSanitizedString(output, c.Get(fiber.HeaderReferer)) }, TagProtocol: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { return output.WriteString(c.Protocol()) }, TagScheme: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Scheme()) + // Scheme echoes X-Forwarded-Proto / X-Url-Scheme once the proxy is + // trusted, so it is request-derived like ${ips} and ${ua}. + return writeSanitizedString(output, c.Scheme()) }, TagPort: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { return output.WriteString(c.Port()) }, TagIP: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.IP()) + return writeSanitizedString(output, c.IP()) }, TagIPs: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Get(fiber.HeaderXForwardedFor)) + // Ask the framework for the chain rather than read the header a second way: + // a lower-case "x-forwarded-for:" logged an empty chain while the trust + // decisions used it. c.IPs() splits and trims, so both wire forms match. + ips := c.IPs() + n := 0 + for i, ip := range ips { + if i > 0 { + m, err := output.WriteString(",") + n += m + if err != nil { + return n, err + } + } + m, err := writeSanitizedString(output, ip) + n += m + if err != nil { + return n, err + } + } + return n, nil }, TagHost: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Hostname()) + return writeSanitizedString(output, c.Hostname()) }, TagPath: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Path()) + return writeSanitizedString(output, c.Path()) }, TagURL: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.OriginalURL()) + return writeSanitizedString(output, c.OriginalURL()) }, TagUA: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Get(fiber.HeaderUserAgent)) + return writeSanitizedString(output, c.Get(fiber.HeaderUserAgent)) }, TagBody: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.Write(c.Body()) + return writeSanitized(output, c.Body()) }, TagBytesReceived: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return appendInt(output, c.Request().Header.ContentLength()) + return appendInt(output, c.Req().ContentLength()) }, TagBytesSent: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return appendInt(output, c.Response().Header.ContentLength()) + return appendInt(output, c.Res().ContentLength()) }, TagRoute: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Route().Path) + // Normally the registered pattern, but Ctx.Route falls back to a + // synthetic route carrying the raw request path when no route + // matched, so this can be request-derived too. + return writeSanitizedString(output, c.Route().Path) }, TagResBody: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.Write(c.Response().Body()) + // Res.Body answers nil for a streamed response rather than draining + // it, so logging cannot buffer an SSE or SendFile body it was only + // meant to observe. + return writeSanitized(output, c.Res().Body()) }, TagReqHeaders: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { out := make(map[string][]string) @@ -145,10 +171,10 @@ func createTagMap(cfg *Config) map[string]LogFunc { for k, v := range out { reqHeaders = append(reqHeaders, k+"="+strings.Join(v, ",")) } - return output.WriteString(strings.Join(reqHeaders, "&")) + return writeSanitizedString(output, strings.Join(reqHeaders, "&")) }, TagQueryStringParams: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { - return output.WriteString(c.Request().URI().QueryArgs().String()) + return writeSanitizedString(output, c.Req().URI().QueryArgs().String()) }, TagBlack: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { @@ -182,59 +208,68 @@ func createTagMap(cfg *Config) map[string]LogFunc { if data.ChainErr != nil { if cfg.areColorsEnabled { colors := c.App().Config().ColorScheme - return fmt.Fprintf(output, "%s%s%s", colors.Red, data.ChainErr.Error(), colors.Reset) + return writeSanitizedColored(output, colors.Red, data.ChainErr.Error(), colors.Reset) } - return output.WriteString(data.ChainErr.Error()) + return writeSanitizedString(output, data.ChainErr.Error()) } return output.WriteString("-") }, TagReqHeader: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { - return output.WriteString(c.Get(extraParam)) + return writeSanitizedString(output, c.Get(extraParam)) }, TagRespHeader: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { - return output.WriteString(c.GetRespHeader(extraParam)) + return writeSanitizedString(output, c.GetRespHeader(extraParam)) }, TagQuery: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { - return output.WriteString(fiber.Query[string](c, extraParam)) + return writeSanitizedString(output, fiber.Query[string](c, extraParam)) }, TagForm: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { - return output.WriteString(c.FormValue(extraParam)) + return writeSanitizedString(output, c.FormValue(extraParam)) }, TagCookie: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { - return output.WriteString(c.Cookies(extraParam)) + return writeSanitizedString(output, c.Cookies(extraParam)) }, TagLocals: func(output Buffer, c fiber.Ctx, _ *Data, extraParam string) (int, error) { switch v := c.Locals(extraParam).(type) { case []byte: - return output.Write(v) + return writeSanitized(output, v) case string: - return output.WriteString(v) + return writeSanitizedString(output, v) case nil: return 0, nil default: - return fmt.Fprintf(output, "%v", v) + // %v can render arbitrary text (e.g. a struct holding request + // data), so it goes through the same scrubbing. + return writeSanitizedValue(output, v) } }, TagStatus: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { + status := c.Res().StatusCode() if cfg.areColorsEnabled { + // Written in place rather than with fmt: "%s%3d%s" reflects + // over three arguments and boxes the status, which measured + // well over twice the cost of the same three writes. colors := c.App().Config().ColorScheme - return fmt.Fprintf(output, "%s%3d%s", statusColor(c.Response().StatusCode(), &colors), c.Response().StatusCode(), colors.Reset) + return writeColoredInt(output, statusColor(status, &colors), status, 3, colors.Reset) } - return appendInt(output, c.Response().StatusCode()) + return appendInt(output, status) }, TagMethod: func(output Buffer, c fiber.Ctx, _ *Data, _ string) (int, error) { + method := c.Method() if cfg.areColorsEnabled { colors := c.App().Config().ColorScheme - return fmt.Fprintf(output, "%s%s%s", methodColor(c.Method(), &colors), c.Method(), colors.Reset) + return writeColored(output, methodColor(method, &colors), method, colors.Reset) } - return output.WriteString(c.Method()) + return output.WriteString(method) }, TagPid: func(output Buffer, _ fiber.Ctx, data *Data, _ string) (int, error) { return output.WriteString(data.Pid) }, TagLatency: func(output Buffer, _ fiber.Ctx, data *Data, _ string) (int, error) { - latency := data.Stop.Sub(data.Start) - return fmt.Fprintf(output, "%13v", latency) + // Rendered digit-wise rather than with fmt: "%13v" reflects over + // the Duration, allocates its String, and boxes it, which measured + // ~5x the cost of appending the same 13 columns in place. + return appendDurationTag(output, data.Stop.Sub(data.Start), 13) }, TagTime: func(output Buffer, _ fiber.Ctx, data *Data, _ string) (int, error) { return output.WriteString(data.Timestamp) diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/utils.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/utils.go index cd8e6eac..37d7b024 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/utils.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/logger/utils.go @@ -1,11 +1,14 @@ package logger import ( + "fmt" "io" "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/logtemplate" fiberlog "github.com/gofiber/fiber/v3/log" "github.com/gofiber/utils/v2" + "github.com/valyala/bytebufferpool" ) func methodColor(method string, colors *fiber.Colors) string { @@ -93,3 +96,120 @@ func LoggerToWriter[T any](logger fiberlog.AllLogger[T], level fiberlog.Level) i loggerInstance: logger, } } + +// writeSanitized writes p to output with ASCII control bytes replaced by +// spaces (tabs are preserved), so user-controlled values such as a request +// body or a decoded query parameter cannot inject CR/LF and forge log lines. +func writeSanitized(output Buffer, p []byte) (int, error) { + return logtemplate.WriteSanitized(output, p) +} + +// writeSanitizedString is writeSanitized for strings. +func writeSanitizedString(output Buffer, s string) (int, error) { + return logtemplate.WriteSanitizedString(output, s) +} + +// writeColored writes value between the two color escapes. Both the sequences +// and value are written verbatim: it backs the tags whose uncolored branch +// also writes value unscrubbed, so wrapping it in color must not change what +// reaches the log. +func writeColored(output Buffer, color, value, reset string) (int, error) { + n, err := output.WriteString(color) + if err != nil { + return n, err + } + m, err := output.WriteString(value) + n += m + if err != nil { + return n, err + } + m, err = output.WriteString(reset) + return n + m, err +} + +// writeColoredInt is writeColored for a decimal right-aligned to width. +func writeColoredInt(output Buffer, color string, v, width int, reset string) (int, error) { + n, err := output.WriteString(color) + if err != nil { + return n, err + } + m, err := appendIntTag(output, v, width) + n += m + if err != nil { + return n, err + } + m, err = output.WriteString(reset) + return n + m, err +} + +// writeSanitizedColored writes value between the two color escapes, scrubbing +// only value. The color sequences are library-controlled and must reach the +// output verbatim. +func writeSanitizedColored(output Buffer, color, value, reset string) (int, error) { + n, err := output.WriteString(color) + if err != nil { + return n, err + } + m, err := writeSanitizedString(output, value) + n += m + if err != nil { + return n, err + } + m, err = output.WriteString(reset) + return n + m, err +} + +// SanitizeValue returns s with ASCII control bytes replaced by spaces, +// preserving horizontal tab. It is the same scrubbing the built-in tags apply +// to request-derived values, exported so that code taking one of the paths +// that bypasses those tags can apply it too: +// +// - a tag registered with RegisterTag, MustRegisterTag or RegisterContextTag +// - an entry in Config.CustomTags +// - a Config.LoggerFunc, which replaces the whole rendering pipeline +// +// Any of those can write a value that reached the handler percent-decoded — a +// query parameter, a form field, a header — and an unscrubbed CR/LF there +// forges an extra access-log line. +// +// Clean input, the overwhelmingly common case, is returned unchanged with no +// allocation. Only ASCII controls are replaced; bytes at or above 0x80 pass +// through, so a value that may carry C1 controls (U+0080–U+009F, including +// NEL U+0085) needs its own handling. +func SanitizeValue(s string) string { + return sanitizeLogValue(s) +} + +// sanitizeLogValue returns s with ASCII control bytes replaced by spaces +// (tabs preserved). It is the string-returning counterpart of +// writeSanitizedString, for the default-format writer, which composes its line +// with fmt.Fprintf and fixed-width padding rather than by writing tags into +// the buffer. Clean input — the overwhelmingly common case — is returned +// unchanged with no allocation. +func sanitizeLogValue(s string) string { + idx := logtemplate.IndexControlByte(s) + if idx == -1 { + return s + } + return string(logtemplate.ScrubControls(s, idx)) +} + +// writeSanitizedValue renders v with %v and writes the scrubbed result. +// +// The rendering goes through a pooled scratch buffer because the bytes have to +// be scrubbed before they reach output, and scrubbing in place afterwards is +// not an option: Buffer is an interface, and an implementation whose Bytes() +// returns a copy would silently skip the scrub. The pool keeps that +// indirection allocation-free; it costs roughly 30ns over writing straight to +// output, paid only by ${locals:} values that are neither string nor []byte. +func writeSanitizedValue(output Buffer, v any) (int, error) { + b := bytebufferpool.Get() + defer bytebufferpool.Put(b) + + // Called without assignment deliberately: the only error Fprintf can report + // is one from the writer, and bytebufferpool.ByteBuffer.Write always returns + // a nil error. The error that matters — a failed write to output — is the + // one returned below. + fmt.Fprintf(b, "%v", v) + return writeSanitized(output, b.B) +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/recover/recover.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/recover/recover.go index 8be5df10..5c0db9d7 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/recover/recover.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/recover/recover.go @@ -8,8 +8,10 @@ import ( "github.com/gofiber/fiber/v3" ) +// Must not start with "panic: ": the panic was recovered, and that exact prefix +// makes gotestsum treat the whole run as crashed and skip --rerun-fails. func defaultStackTraceHandler(_ fiber.Ctx, e any) { - fmt.Fprintf(os.Stderr, "panic: %v\n\n%s\n", e, debug.Stack()) + fmt.Fprintf(os.Stderr, "recovered panic: %v\n\n%s\n", e, debug.Stack()) } // DefaultPanicHandler returns r directly if it's an error, and creates a new one with the %v verb otherwise. diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/requestid/requestid.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/requestid/requestid.go index 5b6d86fa..fc1b287f 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/requestid/requestid.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/requestid/requestid.go @@ -6,6 +6,7 @@ import ( "github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3/middleware/logger" "github.com/gofiber/utils/v2" + "github.com/gofiber/utils/v2/swar" ) // The contextKey type is unexported to prevent collisions with context keys defined in @@ -68,6 +69,13 @@ func sanitizeRequestID(rid string, generator func() string) string { return utils.SecureToken() } +// visibleASCIIMask marks the lanes of w inside [0x20, 0x7E]; bytes >= 0x80 +// are never marked. A word is all visible ASCII iff the mask equals +// swar.HighBits. +func visibleASCIIMask(w uint64) uint64 { + return swar.MatchRangeMask(w, 0x20, 0x7e) +} + // isValidRequestID reports whether the request ID contains only visible ASCII // characters (0x20–0x7E) and is non-empty. func isValidRequestID(rid string) bool { @@ -75,9 +83,23 @@ func isValidRequestID(rid string) bool { return false } - for i := 0; i < len(rid); i++ { - c := rid[i] - if c < 0x20 || c > 0x7e { + // Check eight bytes per iteration, finishing inputs of 8+ bytes with + // one overlapping word; shorter ones are checked byte-wise. + n := len(rid) + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + if visibleASCIIMask(swar.Load8(rid, i)) != swar.HighBits { + return false + } + } + if i == n { + return true + } + if n >= swar.WordLen { + return visibleASCIIMask(swar.Load8(rid, n-swar.WordLen)) == swar.HighBits + } + for ; i < n; i++ { + if c := rid[i]; c < 0x20 || c > 0x7e { return false } } diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/static/config.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/static/config.go index 7a6489ed..e471ea40 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/static/config.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/static/config.go @@ -53,7 +53,8 @@ type Config struct { // Optional. Default: false Compress bool `json:"compress"` - // When set to true, enables byte range requests. + // When set to true, enables byte range requests. A request for several + // ranges, or whose If-Range does not match, gets the whole file. // // Optional. Default: false ByteRange bool `json:"byte_range"` diff --git a/src/vendor/github.com/gofiber/fiber/v3/middleware/static/static.go b/src/vendor/github.com/gofiber/fiber/v3/middleware/static/static.go index c8236471..4261b948 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/middleware/static/static.go +++ b/src/vendor/github.com/gofiber/fiber/v3/middleware/static/static.go @@ -5,11 +5,9 @@ import ( "errors" "fmt" "io/fs" - "net/url" "os" - pathpkg "path" "path/filepath" - "slices" + "runtime" "strconv" "strings" "sync" @@ -18,131 +16,236 @@ import ( "github.com/valyala/fasthttp" "github.com/gofiber/fiber/v3" + "github.com/gofiber/fiber/v3/internal/byterange" ) var ErrInvalidPath = errors.New("invalid path") const invalidPathSentinel = "/__fiber_invalid__" -func bytesToPathString(p []byte) string { - if bytes.IndexByte(p, '\\') >= 0 { - b := make([]byte, len(p)) - copy(b, p) - for i := range b { - if b[i] == '\\' { - b[i] = '/' - } - } - return utils.UnsafeString(b) - } +// windowsOS is runtime.GOOS on Windows, where a path component loses its +// trailing dots and spaces when a file is opened. +const windowsOS = "windows" - return utils.UnsafeString(p) +// rewrite carries the path the file server opens for one request. The handler +// builds it before it calls fasthttp, so PathRewrite only has to read it. +type rewrite struct { + path []byte } -func unescapePathString(s string) (string, error) { - for strings.IndexByte(s, '%') >= 0 { - us, err := url.PathUnescape(s) - if err != nil { - return "", ErrInvalidPath - } - if us == s { - break - } - s = us - } +// rewriteKey is the fasthttp user-value key under which PathRewrite finds the rewrite. +type rewriteKey struct{} - return s, nil +var rewritePool = sync.Pool{ + New: func() any { return &rewrite{path: make([]byte, 0, 128)} }, } -func hasParentDirSegment(p []byte) (bool, error) { - s, err := unescapePathString(bytesToPathString(p)) - if err != nil { - return false, err - } +// fileServer is the fasthttp file server of one route of one app, with what +// it needs to turn a routed path into the path it opens. +type fileServer struct { + fsys fs.FS + handler fasthttp.RequestHandler + root string + fsRootPrefix []byte // the fs.FS subdirectory served, put before every path + prefixLen int // length of the route prefix stripped from the path + decodeEscapes bool // off under UnescapePath, which already decoded everything + rootIsFile bool + segmentBound bool // the route is a /prefix* mount, so the rest of the path starts at a / + invalid bool // the fs.FS root cannot be opened, so no path names a file +} - trimmed := utils.TrimLeft(filepath.ToSlash(s), '/') - for trimmed != "" { - segment, rest, found := strings.Cut(trimmed, "/") - if segment == ".." { - return true, nil +// fileServerKey identifies a file server: the decoding mode and the compressed +// file suffixes are the app's, and the prefix to strip is the route's. +type fileServerKey struct { + app *fiber.App + route string +} + +// requestPath appends to dst the path the file server opens for the routed +// path p, or invalidPathSentinel when p names nothing inside the root. +func (s *fileServer) requestPath(dst []byte, p string) []byte { + addTrailingSlash := false + if len(p) >= s.prefixLen { + // a partial wildcard such as /static* also matches /staticx; the rest of + // the path must start at a segment boundary + if s.segmentBound && len(p) > s.prefixLen && p[s.prefixLen] != '/' { + return append(dst, invalidPathSentinel...) + } + if s.invalid { + return append(dst, invalidPathSentinel...) } - if !found { - return false, nil + // If the root is a file, we need to reset the path to "/" always. + switch { + case s.rootIsFile && s.fsys == nil: + p = "/" + case s.rootIsFile && s.fsys != nil: + p = s.root + default: + p = p[s.prefixLen:] + // a trailing slash lets fasthttp serve a directory index without a redirect + addTrailingSlash = true } - trimmed = rest } - return false, nil -} - -// sanitizePath validates and cleans the requested path. -// It returns an error if the path attempts to traverse directories. -func sanitizePath(p []byte, filesystem fs.FS) ([]byte, error) { - hasTrailingSlash := len(p) > 0 && p[len(p)-1] == '/' - - s, err := unescapePathString(bytesToPathString(p)) - if err != nil { - return nil, err + dst = append(dst, s.fsRootPrefix...) + start := len(dst) + if p == "" || p[0] != '/' { + dst = append(dst, '/') } - - if strings.IndexByte(s, '\\') >= 0 { - return nil, ErrInvalidPath + dst = append(dst, p...) + if addTrailingSlash && dst[len(dst)-1] != '/' { + dst = append(dst, '/') } - // reject any null bytes - if strings.IndexByte(s, '\x00') >= 0 { - return nil, ErrInvalidPath + sanitized, err := sanitizePath(dst[start:], s.fsys, s.decodeEscapes) + if err != nil { + // return a guaranteed-missing path so fs responds with 404 + return append(dst[:0], invalidPathSentinel...) } + return dst[:start+len(sanitized)] +} - normalized := filepath.ToSlash(s) - if filesystem == nil && strings.HasPrefix(normalized, "//") { +// decodeFileName validates the escapes the router left in p and returns p +// unchanged. The router already produced the canonical resource name (it decoded +// every escape of an unreserved character and kept the rest encoded; see +// unescapeSafePath), so file lookup opens exactly the bytes the route and any +// path-scoped middleware matched. It refuses what cannot name such a file: a +// backslash or control character, a malformed or truncated escape, an escape of +// a separator or control character, and an escape of an unreserved character. +// That last one cannot survive the router's own decoding, so its only source is +// a stray '%' the router kept literally that lines up with the following bytes +// into a fresh escape ("%%370rivate" and "%7%30rivate" both normalize to +// "%70rivate"); decoding it a second time here would reach a name ("private") +// the router never matched and the middleware never guarded, so it is rejected. +// When decodeEscapes is off, UnescapePath already decoded everything and no +// escape remains to validate. +func decodeFileName(p []byte, decodeEscapes bool) ([]byte, error) { //nolint:revive // the flag mirrors UnescapePath; see sanitizePath + if utils.IndexControl(p) >= 0 || bytes.IndexByte(p, '\\') >= 0 { return nil, ErrInvalidPath } - - s = pathpkg.Clean("/" + normalized) - - trimmed := utils.TrimLeft(s, '/') - if trimmed != "" { - if slices.Contains(strings.Split(trimmed, "/"), "..") { + i := bytes.IndexByte(p, '%') + if !decodeEscapes || i < 0 { + return p, nil + } + for ; i < len(p); i++ { + if p[i] != '%' { + continue + } + if i+2 >= len(p) { return nil, ErrInvalidPath } - } - - if filesystem == nil { - normalizedClean := filepath.ToSlash(trimmed) - if strings.HasPrefix(normalizedClean, "//") { + hi, lo := unhex(p[i+1]), unhex(p[i+2]) + if hi < 0 || lo < 0 { return nil, ErrInvalidPath } - if volume := filepath.VolumeName(normalizedClean); volume != "" { + c := byte(hi<<4 | lo) //nolint:gosec // G115: both nibbles are 0-15 + if c == '/' || c == '\\' || c < 0x20 || c == 0x7f || isUnreserved(c) { return nil, ErrInvalidPath } - if len(normalizedClean) >= 2 && normalizedClean[1] == ':' { - drive := normalizedClean[0] - if (drive >= 'a' && drive <= 'z') || (drive >= 'A' && drive <= 'Z') { - return nil, ErrInvalidPath + i += 2 + } + return p, nil +} + +func isUnreserved(c byte) bool { + return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || + c == '-' || c == '.' || c == '_' || c == '~' +} + +// unhex returns the value of a hexadecimal digit, or -1 for any other byte. +func unhex(c byte) int { + switch { + case c >= '0' && c <= '9': + return int(c - '0') + case c >= 'a' && c <= 'f': + return int(c-'a') + 10 + case c >= 'A' && c <= 'F': + return int(c-'A') + 10 + default: + return -1 + } +} + +// hasUnsafeSegment reports whether p holds a "." or ".." segment, or an empty +// one other than the root's leading and a directory's trailing slash. The +// router removes dot segments and keeps empty ones as sent, so none of them +// is part of a path it matched to a file. +func hasUnsafeSegment(p []byte) bool { + start := 0 + for i := 0; i <= len(p); i++ { + if i < len(p) && p[i] != '/' { + continue + } + switch n := i - start; { + case n == 0: + if start > 0 && i < len(p) { + return true } + case n == 1 && p[start] == '.', n == 2 && p[start] == '.' && p[start+1] == '.': + return true } - if strings.HasPrefix(filepath.ToSlash(s), "//") { - return nil, ErrInvalidPath + start = i + 1 + } + return false +} + +// hasDriveLetter reports whether name starts with a Windows drive letter and a colon. +func hasDriveLetter(name string) bool { + if len(name) < 2 || name[1] != ':' { + return false + } + drive := name[0] + return (drive >= 'a' && drive <= 'z') || (drive >= 'A' && drive <= 'Z') +} + +// hasTrailingDotOrSpaceSegment reports whether a segment of p ends in a dot or +// a space. Windows drops both from a path component when it opens a file, so +// "private./secret.txt" and "private /secret.txt" would open +// "private/secret.txt": a path the router kept apart from "private", and one +// that middleware guarding "private" never saw. Elsewhere such a name is an +// ordinary file, so sanitizePath applies this only on Windows, and there to +// every root: an fs.FS may be OS-backed (os.DirFS) and cannot be told apart +// from a virtual one such as embed.FS, so a virtual name ending in a dot or a +// space is refused on Windows rather than leave the alias open for the rest. +func hasTrailingDotOrSpaceSegment(p []byte) bool { + for i, c := range p { + if (c == '.' || c == ' ') && (i+1 == len(p) || p[i+1] == '/') { + return true } } + return false +} +// sanitizePath validates the routed path p, with the route's prefix stripped, +// and returns the path the file server opens, which is p unchanged. It fails +// with ErrInvalidPath when p cannot name a file inside the root: an escape of a +// slash ("private%2Fsecret.txt" never reaches the "private/secret.txt" the +// router did not match), an escape of an unreserved character (a stray '%' the +// router kept that would otherwise double-decode past the route and middleware), +// a malformed escape, a backslash, a control character, a ".", ".." or empty +// segment, a drive letter and, on Windows, a segment ending in a dot or a space +// that the OS would strip. Escapes the router kept remain encoded, keeping file +// lookup aligned with route and middleware matching. +func sanitizePath(p []byte, filesystem fs.FS, decodeEscapes bool) ([]byte, error) { //nolint:revive // the flag mirrors UnescapePath + p, err := decodeFileName(p, decodeEscapes) + if err != nil { + return nil, err + } + if hasUnsafeSegment(p) || (runtime.GOOS == windowsOS && hasTrailingDotOrSpaceSegment(p)) { + return nil, ErrInvalidPath + } + + name := strings.TrimPrefix(utils.UnsafeString(p), "/") if filesystem != nil { - s = trimmed - if s == "" { - return []byte("/"), nil - } - if !fs.ValidPath(s) { + if name = strings.TrimSuffix(name, "/"); name != "" && !fs.ValidPath(name) { return nil, ErrInvalidPath } - s = "/" + s + return p, nil } - - if hasTrailingSlash && len(s) > 1 && s[len(s)-1] != '/' { - s += "/" + if filepath.VolumeName(name) != "" || hasDriveLetter(name) { + return nil, ErrInvalidPath } - - return utils.UnsafeBytes(s), nil + return p, nil } // New creates a new middleware handler. @@ -152,155 +255,185 @@ func sanitizePath(p []byte, filesystem fs.FS) ([]byte, error) { func New(root string, cfg ...Config) fiber.Handler { config := configDefault(cfg...) - var createFS sync.Once - var fileHandler fasthttp.RequestHandler - var cacheControlValue string - var rootCheckErr error - var rootIsFile bool + var ( + rootCheck sync.Once + rootCheckErr error + rootIsFile bool + // servers holds one file server per app and route, since the stripped prefix is the route's. + servers sync.Map + serversMu sync.Mutex + ) + cacheControlValue := "" + if config.MaxAge > 0 { + cacheControlValue = "public, max-age=" + strconv.Itoa(config.MaxAge) + } - // adjustments for io/fs compatibility - if config.FS != nil && root == "" { - root = "." + // adjustments for io/fs compatibility: io/fs paths are always relative and + // slash-separated, so a leading slash (e.g. "/" or "/dist") is never a valid + // fs path and makes isFile's fs.FS.Open fail, which sends every request to + // the PathNotFound handler. Strip it and treat an empty result as the fs root ".". + if config.FS != nil { + root = strings.TrimLeft(root, "/") + if root == "" { + root = "." + } } - return func(c fiber.Ctx) error { - // Don't execute middleware if Next returns true - if config.Next != nil && config.Next(c) { - return c.Next() + // newFileServer builds the fasthttp file server for one route prefix; + // decodeEscapes is off under UnescapePath, which already decoded everything. + newFileServer := func(prefix string, compressedFileSuffixes map[string]string, decodeEscapes bool) *fileServer { + // Is prefix a partial wildcard? + segmentBound := false + if before, _, found := utils.CutByte(prefix, '*'); found { + // /john* -> /john + prefix = before + // only /john* must not match /johnx; /john/* and /* end in a slash + segmentBound = before != "" && before[len(before)-1] != '/' } - // We only serve static assets on GET or HEAD methods - method := c.Method() - if method != fiber.MethodGet && method != fiber.MethodHead { - return c.Next() + prefixLen := len(prefix) + if prefixLen > 1 && prefix[prefixLen-1:] == "/" { + // /john/ -> /john + prefixLen-- } - // Initialize FS - createFS.Do(func() { - prefix := c.Route().Path + // For io/fs.FS, Root must be empty so fasthttp's pathToFilePath + // returns clean relative paths without prefixing the root. + // requestPath already handles file-root and subdirectory cases. + fsRoot := root + if config.FS != nil { + fsRoot = "" + } - rootIsFile, rootCheckErr = isFile(root, config.FS) + var fsRootPrefix []byte + if config.FS != nil && root != "" && root != "." && !rootIsFile { + // fasthttp.FS.Root is forced to "" for io/fs.FS so pathToFilePath + // returns clean relative paths. requestPath puts the caller's + // configured subdirectory before the sanitized request path. + fsRootPrefix = append([]byte{'/'}, root...) + } - // Is prefix a partial wildcard? - if before, _, found := strings.Cut(prefix, "*"); found { - // /john* -> /john - prefix = before - } + files := &fasthttp.FS{ + Root: fsRoot, + FS: config.FS, + AllowEmptyRoot: true, + GenerateIndexPages: config.Browse, + AcceptByteRange: config.ByteRange, + Compress: config.Compress, + CompressBrotli: config.Compress, // Brotli compression won't work without this + CompressZstd: config.Compress, // Zstd compression won't work without this + CompressedFileSuffixes: compressedFileSuffixes, + CacheDuration: config.CacheDuration, + SkipCache: config.CacheDuration < 0, + IndexNames: config.IndexNames, + PathNotFound: func(fctx *fasthttp.RequestCtx) { + fctx.Response.SetStatusCode(fiber.StatusNotFound) + }, + } - prefixLen := len(prefix) - if prefixLen > 1 && prefix[prefixLen-1:] == "/" { - // /john/ -> /john - prefixLen-- + // serve the path the handler built from the one the router matched, + // not fasthttp's own decoding of the request + files.PathRewrite = func(fctx *fasthttp.RequestCtx) []byte { + if rw, ok := fctx.UserValue(rewriteKey{}).(*rewrite); ok { + return rw.path } + return []byte(invalidPathSentinel) + } - // For io/fs.FS, Root must be empty so fasthttp's pathToFilePath - // returns clean relative paths without prefixing the root. - // PathRewrite already handles file-root and subdirectory cases. - fsRoot := root - if config.FS != nil { - fsRoot = "" - } + handler := files.NewRequestHandler() + if config.ByteRange { + handler = byterange.Wrap(handler) + } - var fsRootPrefix []byte - if config.FS != nil && root != "" && root != "." && !rootIsFile { - // fasthttp.FS.Root is forced to "" for io/fs.FS so pathToFilePath - // returns clean relative paths. PathRewrite prepends the caller's - // configured subdirectory after sanitizing the request path. - fsRootPrefix = make([]byte, len(root)+1) - fsRootPrefix[0] = '/' - copy(fsRootPrefix[1:], root) - } + return &fileServer{ + handler: handler, + fsys: config.FS, + root: root, + fsRootPrefix: fsRootPrefix, + prefixLen: prefixLen, + segmentBound: segmentBound, + decodeEscapes: decodeEscapes, + rootIsFile: rootIsFile, + invalid: rootCheckErr != nil && config.FS != nil, + } + } - fileServer := &fasthttp.FS{ - Root: fsRoot, - FS: config.FS, - AllowEmptyRoot: true, - GenerateIndexPages: config.Browse, - AcceptByteRange: config.ByteRange, - Compress: config.Compress, - CompressBrotli: config.Compress, // Brotli compression won't work without this - CompressZstd: config.Compress, // Zstd compression won't work without this - CompressedFileSuffixes: c.App().Config().CompressedFileSuffixes, - CacheDuration: config.CacheDuration, - SkipCache: config.CacheDuration < 0, - IndexNames: config.IndexNames, - PathNotFound: func(fctx *fasthttp.RequestCtx) { - fctx.Response.SetStatusCode(fiber.StatusNotFound) - }, + // serverFor returns the file server for the app and route serving c, built on first use. + serverFor := func(c fiber.Ctx) *fileServer { + key := fileServerKey{app: c.App(), route: c.Route().Path} + if s, ok := servers.Load(key); ok { + if server, ok := s.(*fileServer); ok { + return server } + } - fileServer.PathRewrite = func(fctx *fasthttp.RequestCtx) []byte { - path := fctx.Path() - - if len(path) >= prefixLen { - if rootCheckErr != nil && fileServer.FS != nil { - return []byte(invalidPathSentinel) - } - - // If the root is a file, we need to reset the path to "/" always. - switch { - case rootIsFile && fileServer.FS == nil: - path = []byte("/") - case rootIsFile && fileServer.FS != nil: - path = utils.UnsafeBytes(root) - default: - path = path[prefixLen:] - if len(fsRootPrefix) > 0 { - hasTraversal, err := hasParentDirSegment(path) - if err != nil || hasTraversal { - return []byte(invalidPathSentinel) - } - } - if len(path) == 0 || path[len(path)-1] != '/' { - path = append(path, '/') - } - } - } + serversMu.Lock() + defer serversMu.Unlock() + if s, ok := servers.Load(key); ok { + if server, ok := s.(*fileServer); ok { + return server + } + } + rootCheck.Do(func() { + rootIsFile, rootCheckErr = isFile(root, config.FS) + }) + cfg := c.App().Config() + server := newFileServer(key.route, cfg.CompressedFileSuffixes, !cfg.UnescapePath) + servers.Store(key, server) + return server + } - if len(path) > 0 && path[0] != '/' { - path = append([]byte("/"), path...) - } + return func(c fiber.Ctx) error { + // Don't execute middleware if Next returns true + if config.Next != nil && config.Next(c) { + return c.Next() + } - sanitized, err := sanitizePath(path, fileServer.FS) - if err != nil { - // return a guaranteed-missing path so fs responds with 404 - return []byte(invalidPathSentinel) - } - if len(fsRootPrefix) > 0 { - rewrittenPath := make([]byte, len(fsRootPrefix)+len(sanitized)) - copy(rewrittenPath, fsRootPrefix) - copy(rewrittenPath[len(fsRootPrefix):], sanitized) - return rewrittenPath - } - return sanitized - } + // We only serve static assets on GET or HEAD methods + method := c.Method() + if method != fiber.MethodGet && method != fiber.MethodHead { + return c.Next() + } - maxAge := config.MaxAge - if maxAge > 0 { - cacheControlValue = "public, max-age=" + strconv.Itoa(maxAge) - } + server := serverFor(c) - fileHandler = fileServer.NewRequestHandler() - }) + // PathRewrite only receives the fasthttp context; hand it the path to open. + rw, ok := rewritePool.Get().(*rewrite) + if !ok { + rw = &rewrite{} + } + rw.path = server.requestPath(rw.path[:0], c.Path()) + fctx := c.RequestCtx() + fctx.SetUserValue(rewriteKey{}, rw) // Serve file - fileHandler(c.RequestCtx()) + server.handler(fctx) - // Sets the response Content-Disposition header to attachment if the Download option is true - if config.Download { - name := filepath.Base(c.Path()) - if rootIsFile { - name = filepath.Base(root) - } - c.Attachment(name) - } + fctx.RemoveUserValue(rewriteKey{}) + rewritePool.Put(rw) // Return request if found and not forbidden - status := c.RequestCtx().Response.StatusCode() + status := fctx.Response.StatusCode() if status != fiber.StatusNotFound && status != fiber.StatusForbidden { - if cacheControlValue != "" { - c.RequestCtx().Response.Header.Set(fiber.HeaderCacheControl, cacheControlValue) + // Only a served file is an attachment; the header must not leak onto a + // miss, a redirect, or an error such as 416. + if config.Download && status >= fiber.StatusOK && status < fiber.StatusMultipleChoices { + name := filepath.Base(c.Path()) + if rootIsFile { + name = filepath.Base(root) + } + // Attachment derives a Content-Type from the extension; keep the detected one. + contentType := utils.CopyString(c.GetRespHeader(fiber.HeaderContentType)) + c.Attachment(name) + if contentType != "" { + c.Set(fiber.HeaderContentType, contentType) + } + } + + // An error response such as 416 must not be cached under the file's MaxAge. + if cacheControlValue != "" && status >= fiber.StatusOK && status < fiber.StatusBadRequest { + fctx.Response.Header.Set(fiber.HeaderCacheControl, cacheControlValue) } if config.ModifyResponse != nil { @@ -316,9 +449,9 @@ func New(root string, cfg ...Config) fiber.Handler { } // Reset response to default - c.RequestCtx().SetContentType("") // Issue #420 - c.RequestCtx().Response.SetStatusCode(fiber.StatusOK) - c.RequestCtx().Response.SetBodyString("") + fctx.SetContentType("") // Issue #420 + fctx.Response.SetStatusCode(fiber.StatusOK) + fctx.Response.SetBodyString("") // Next middleware return c.Next() diff --git a/src/vendor/github.com/gofiber/fiber/v3/mount.go b/src/vendor/github.com/gofiber/fiber/v3/mount.go index 588cd872..76ed8758 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/mount.go +++ b/src/vendor/github.com/gofiber/fiber/v3/mount.go @@ -5,7 +5,10 @@ package fiber import ( + "maps" + "slices" "sort" + "strings" "sync" "sync/atomic" @@ -18,6 +21,23 @@ type mountFields struct { appList map[string]*App // Prefix of app if it was mounted mountPath string + // Apps mounted through a domain router. They are kept out of appList + // because that map is keyed by path alone: two apps mounted at the same + // path for different hosts would displace each other, and a lookup would + // answer for hosts the domain pattern rejects. + domainAppList []domainMountedApp + // Routes that arrived from a mount which registers no automatic HEAD + // routes, kept by route because a path can belong to a mount and to this + // app at once + noAutoHeadRoutes map[*Route]struct{} + // Mounted app each cloned route came from, so the request that ran one + // resolves its config directly instead of inferring an owner from the host + // and the path + routeOwners map[*Route]*App + // Constraints each cloned route was parsed with, which are the ones of the + // apps its path was composed by. Two sibling mounts can name one constraint + // differently, and a route is only ever bound by the one its own app has. + routeConstraints map[*Route][]CustomConstraint // Ordered keys of apps (sorted by key length for Render) appListKeys []string // guards one-time generation of appListKeys @@ -26,6 +46,114 @@ type mountFields struct { subAppsRoutesAdded sync.Once // check mounted sub-apps subAppsProcessed sync.Once + // Whether this app's routes only answer for the hostnames the mount they + // came from matches, which is true of the wrapper a domain mount builds + hostScopedRoutes bool +} + +// domainMountedApp is a sub-app mounted through a domain router. Its config — +// the ErrorHandler and the view engine — applies only to requests whose +// hostname matches every domain pattern the app was mounted behind. +type domainMountedApp struct { + app *App + // parser matches path when it carries parameters, and is nil otherwise: a + // mount can be registered at "/:tenant" the same way a route can + parser *routeParser + // path is the full mount path, normalized by the app it is mounted on + path string + // matchers are the patterns of the domain routers this app was mounted + // behind, outermost last. A request has to satisfy all of them. + matchers []domainMatcher + // ancestors are the apps this one is mounted inside, outermost first. They + // are what its configuration is inherited from: a mount that merely covers + // the same path encloses nothing. + ancestors []*App + // declared are the constraints of the apps whose mount prefixes the path is + // composed of, which is where a constraint named in one of them is defined + declared []CustomConstraint +} + +// newDomainMount records a mount of mounted at path, normalized and parsed +// with the routing rules of the app it is being mounted on, so the lookups +// recognize it the same way the router recognizes its routes. +func (app *App) newDomainMount(mounted *App, path string, matchers []domainMatcher, ancestors []*App, declared []CustomConstraint) domainMountedApp { + normalized := app.normalizePath(path) + + mount := domainMountedApp{ + app: mounted, + path: normalized, + matchers: matchers, + ancestors: ancestors, + declared: declared, + } + + // A mount prefix is written in the terms of the app it was registered on, + // and may name a constraint only that app knows. Those win where both + // define a name, as they do when a mount's routes are re-parsed. + constraints := mergeCustomConstraints(slices.Clone(declared), app.customConstraints) + + if parser := parseRoute(normalized, app.config.RegexHandler, constraints...); len(parser.params) > 0 { + mount.parser = &parser + } + + return mount +} + +// covers reports whether this mount covers path, which is matched as a pattern +// when the mount path carries parameters. +func (m *domainMountedApp) covers(path string) bool { + if m.parser != nil { + var params [maxParams]string + + return m.parser.getMatch(path, path, ¶ms, true) + } + + return strings.HasPrefix(utils.AddTrailingSlashString(path), utils.AddTrailingSlashString(m.path)) +} + +// matchesHost reports whether hostname satisfies every domain pattern the app +// was mounted behind. +func (m *domainMountedApp) matchesHost(hostname string) bool { + for i := range m.matchers { + if matched, _ := m.matchers[i].match(hostname); !matched { + return false + } + } + + return true +} + +// equals reports whether two records describe the same mount: the same app, +// at the same path, behind the same domain patterns. +func (m *domainMountedApp) equals(other *domainMountedApp) bool { + if m.app != other.app || m.path != other.path || len(m.matchers) != len(other.matchers) { + return false + } + + for i := range m.matchers { + // parts carries the pattern the rest of the matcher is derived from. + if !slices.Equal(m.matchers[i].parts, other.matchers[i].parts) { + return false + } + } + + return true +} + +// depth counts the path segments a mount path covers, so the deepest mount +// covering a request can be picked. The root mount covers none of its own, +// which leaves any named mount more specific than it. +func mountDepth(path string) int { + if path == "" || path == "/" { + return 0 + } + + return strings.Count(path, "/") +} + +// depth counts the path segments this mount covers. +func (m *domainMountedApp) depth() int { + return mountDepth(m.path) } // Create empty mountFields instance @@ -42,6 +170,10 @@ func newMountFields(app *App) *mountFields { // any of the fiber's sub apps are added to the application's error handlers // to be invoked on errors that happen within the prefix route. func (app *App) mount(prefix string, subApp *App) Router { + if subApp == app { + panic("fiber: an app cannot be mounted onto itself") + } + prefix = utils.TrimRight(prefix, '/') if prefix == "" { prefix = "/" @@ -101,6 +233,460 @@ func (grp *Group) mount(prefix string, subApp *App) Router { return grp } +// domainOwner is the domain-mounted app a request belongs to, and how deep the +// mount it was reached through is. +type domainOwner struct { + app *App + // ancestors are the apps the owner is mounted inside, outermost first, and + // are what it inherits configuration from. + ancestors []*App + // depth is how many path segments the mount covers, which ranks the owner + // against the plain mounts covering the same request. + depth int + // exact marks an owner taken from the route that ran rather than inferred + // from the host and the path + exact bool +} + +// outranks reports whether this owner should answer for the request instead of +// a plain mount whose path is plainDepth segments deep. +// +// An owner taken from the route that ran always does: that route was served by +// it, and a plain mount is only ever ranked by depth because path is all there +// is to go on. An inferred one wins a tie, having matched the host as well, and +// gives way to a deeper plain mount as a mounted app gives way to one below it. +func (o domainOwner) outranks(plainDepth int) bool { + return o.app != nil && (o.exact || plainDepth <= o.depth) +} + +// supersedes reports whether this owner replaces a plain mount rather than +// inheriting from it. One at or below the owner's own depth did not serve the +// request; only the apps the owner is mounted inside enclose it, and those it +// inherits from however deep they are. +func (o domainOwner) supersedes(plainDepth int, plain *App) bool { + return o.app != nil && plainDepth >= o.depth && !slices.Contains(o.ancestors, plain) +} + +// appHasErrorHandler is the setting a request inherits from the domain mounts +// it was reached through. +func appHasErrorHandler(app *App) bool { return app.configured.ErrorHandler != nil } + +// domainMountRender resolves what a domain mount contributes to a render: the +// nearest app configuring a view engine, and the layout of the nearest app at +// or below that one which configures a layout. +// +// The layout search stops where rendering does. An app with an engine of its +// own renders through it and takes no layout from further out, exactly as the +// scan over the ordinary mounts stops at the first engine it covers; only when +// nothing below configures an engine does the layout travel outward with the +// search for one. +func domainMountRender(owner domainOwner) (*App, string) { //nolint:gocritic // unnamedResult: named returns conflict with nonamedreturns linter + if owner.app == nil { + return nil, "" + } + + layout := owner.app.config.ViewsLayout + if !isNilViews(owner.app.config.Views) { + return owner.app, layout + } + + for _, ancestor := range slices.Backward(owner.ancestors) { + if layout == "" { + layout = ancestor.config.ViewsLayout + } + + if !isNilViews(ancestor.config.Views) { + return ancestor, layout + } + } + + return nil, layout +} + +// domainMountConfig returns the app a setting is taken from: the owner when it +// configures one, and otherwise the deepest domain mount enclosing it that +// does — the inheritance an ordinarily nested mount gets from the app it sits +// in. Mounts at the owner's own depth are siblings that did not serve the +// request, and configure nothing on its behalf. +// +// There has to be an owner: nothing outranks a plain mount without one, so a +// caller reaches this having established it. +func domainMountConfig(owner domainOwner, want func(*App) bool) *App { + if want(owner.app) { + return owner.app + } + + // Innermost first, so the nearest app configuring the setting answers. Only + // the apps the owner is mounted inside are consulted: a mount that reaches + // the same paths on the same hosts is a sibling, and configures nothing on + // the owner's behalf. + for _, ancestor := range slices.Backward(owner.ancestors) { + if want(ancestor) { + return ancestor + } + } + + return nil +} + +// domainMountOwner returns the domain mount that owns this request: the app the +// route that ran was mounted from, or — for an error raised before any of them +// matched — the deepest mount covering the path whose patterns match the host, +// and among equally deep ones the first registered, matching the order their +// routes are matched in. +func (app *App) domainMountOwner(c Ctx) domainOwner { + // The app the route that ran was mounted from, if it was mounted at all. + // Its mount still has to match the request: a domain-wrapped handler that + // declined the host left the route it belongs to as the one that ran, and + // that app served nothing. + routeApp := app.routeOwner(c.Route()) + + var owner, byRoute domainOwner + + path := app.normalizePath(c.Path()) + + for i := range app.mountFields.domainAppList { + mount := &app.mountFields.domainAppList[i] + if !mount.covers(path) || !mount.matchesHost(c.Hostname()) { + continue + } + + depth := mount.depth() + + // Two sub-apps mounted at one path behind overlapping patterns both + // cover the request and both match the host. Only one of them ran. + if mount.app == routeApp && (byRoute.app == nil || depth > byRoute.depth) { + byRoute = domainOwner{app: mount.app, ancestors: mount.ancestors, depth: depth, exact: true} + } + + if owner.app == nil || depth > owner.depth { + owner.app, owner.depth, owner.ancestors = mount.app, depth, mount.ancestors + } + } + + if byRoute.app != nil { + return byRoute + } + + // A route that names an app none of these mounts describe was served by an + // ordinary mount, or by one whose host these patterns reject. Either way + // this request is not a domain mount's to answer for, and only one that ran + // no mounted route at all — a 404, or an error raised above them — is left + // to the mount covering its path. + if routeApp != nil { + return domainOwner{} + } + + return owner +} + +// mountedApps returns this app and every app mounted below it, plain or on a +// domain, for the operations that touch each mounted app's config. +// +// It walks the mount metadata itself rather than reading the flattened lists, +// which are only complete once the app has been through its startup process. +func (app *App) mountedApps() []*App { + apps := []*App{app} + + for i := 0; i < len(apps); i++ { + for _, mounted := range apps[i].mountedAppsSnapshot() { + if !slices.Contains(apps, mounted) { + apps = append(apps, mounted) + } + } + } + + return apps +} + +// mountedAppRef is an app reachable from another one: the path it is reachable +// at, and the domain patterns a request has to satisfy to get there. +type mountedAppRef struct { + app *App + path string + matchers []domainMatcher + ancestors []*App + declared []CustomConstraint +} + +// mountTree returns this app and every app mounted below it, plain or on a +// domain, with the paths and the domain patterns composed along the way. +// +// It walks the mount metadata of each app in turn rather than reading the +// flattened list of one: that list is filled in when an app is mounted, so an +// app mounted on a descendant afterwards is missing from it until startup +// repairs it — and a domain mount records its apps when it is registered. +func (app *App) mountTree() []mountedAppRef { + walk := mountWalk{seen: make(map[mountWalkKey]int)} + walk.add(app, "", nil, nil, nil) + + return walk.refs +} + +// mountWalk carries the state of one walk over an app's mounts. +type mountWalk struct { + // seen holds the longest chain each app has already been reached at, per + // path. An app list holds the descendants of the apps it lists, so a + // descendant is reachable through every combination of the lists leading to + // it — walking one again pays for itself only when the chain is longer than + // one it was reached with before, since only the longest is kept. + seen map[mountWalkKey]int + refs []mountedAppRef +} + +// mountWalkKey identifies an app at the path it was reached at, behind the +// patterns it was reached through: the same app can be mounted at one path for +// two hostnames, and each of those is a mount of its own. +type mountWalkKey struct { + app *App + path string + matchers string +} + +// matchersKey identifies a set of domain patterns. Labels carry neither +// separator, so the parts of one pattern and the patterns of one mount cannot +// run together. +func matchersKey(matchers []domainMatcher) string { + patterns := make([]string, len(matchers)) + for i := range matchers { + patterns[i] = strings.Join(matchers[i].parts, ".") + } + + return strings.Join(patterns, "\n") +} + +// add records this app and its descendants, reached at prefix +// behind matchers. chain holds the apps above this one so a mount cycle +// terminates; it is a slice because it is only ever a few entries deep, and an +// app mounted on two branches is still reached through both. +func (w *mountWalk) add(app *App, prefix string, matchers []domainMatcher, declared []CustomConstraint, chain []*App) { + if slices.Contains(chain, app) { + return + } + + key := mountWalkKey{app: app, path: prefix, matchers: matchersKey(matchers)} + if reached, ok := w.seen[key]; ok && reached >= len(chain) { + return + } + w.seen[key] = len(chain) + + w.refs = append(w.refs, mountedAppRef{ + app: app, + path: prefix, + matchers: matchers, + ancestors: slices.Clone(chain), + declared: declared, + }) + chain = append(chain, app) + + // The prefixes below are written in this app's terms, so a constraint only + // it knows travels with them. Its own win where a name is defined twice, + // the way a mounted app's do when its routes are re-parsed. + declared = mergeCustomConstraints(slices.Clone(app.customConstraints), declared) + + // Patterns compose innermost first, the order a mount records them in: a + // request has to satisfy every one of them. + for _, mount := range app.domainMountsSnapshot() { + w.add( + mount.app, + getGroupPath(prefix, mount.path), + append(slices.Clone(mount.matchers), matchers...), + declared, + chain, + ) + } + + for mountPrefix, mounted := range app.plainMountsSnapshot() { + if mounted == app { + continue + } + + w.add(mounted, getGroupPath(prefix, mountPrefix), matchers, declared, chain) + } +} + +// mountedAppsSnapshot returns the apps mounted directly on this one, plain or +// on a domain. +func (app *App) mountedAppsSnapshot() []*App { + plain := app.plainMountsSnapshot() + domain := app.domainMountsSnapshot() + + mounted := make([]*App, 0, len(plain)+len(domain)) + for _, sub := range plain { + mounted = append(mounted, sub) + } + + for i := range domain { + mounted = append(mounted, domain[i].app) + } + + return mounted +} + +// plainMountsSnapshot copies this app's list of ordinarily mounted apps, read +// under its own lock: App.mount writes it under that lock, and a read left +// unguarded would race a concurrent mount. Only this app is locked, and only +// for the copy, so a caller may hold no other app's lock — mounting an app on +// itself would otherwise take one lock twice. +func (app *App) plainMountsSnapshot() map[string]*App { + if app.mountFields == nil { + return nil + } + + app.mutex.Lock() + defer app.mutex.Unlock() + + return maps.Clone(app.mountFields.appList) +} + +// domainMountsSnapshot copies this app's domain mount records, under the same +// lock and with the same restriction as plainMountsSnapshot. +func (app *App) domainMountsSnapshot() []domainMountedApp { + if app.mountFields == nil { + return nil + } + + app.mutex.Lock() + defer app.mutex.Unlock() + + return slices.Clone(app.mountFields.domainAppList) +} + +// mountCoversPath reports whether a mount registered at mountPath covers path. +// +// Both sides are put through this app's routing rules first: an app list is +// keyed by the path the caller spelled, so on a case-insensitive app a mount +// registered as "/API" has to cover a request for "/api/x" the same way its +// routes do. A parametric mount path is matched literally here — the app list +// keeps no parsed form of its keys. +func (app *App) mountCoversPath(mountPath, path string) bool { + if mountPath == "" { + return false + } + + return strings.HasPrefix( + utils.AddTrailingSlashString(app.normalizePath(path)), + utils.AddTrailingSlashString(app.normalizePath(mountPath)), + ) +} + +// markSkipAutoHead records that a route must not be given an automatic HEAD +// companion. Provenance is kept by route rather than by path: once a mount is +// expanded, its routes sit in this app's stack next to the app's own, and a +// path can belong to both. +func (app *App) markSkipAutoHead(route *Route) { + if app.mountFields.noAutoHeadRoutes == nil { + app.mountFields.noAutoHeadRoutes = make(map[*Route]struct{}) + } + + app.mountFields.noAutoHeadRoutes[route] = struct{}{} +} + +// skipsAutoHeadFor reports whether route came from a mount that registers no +// automatic HEAD routes of its own. +func (app *App) skipsAutoHeadFor(route *Route) bool { + _, ok := app.mountFields.noAutoHeadRoutes[route] + + return ok +} + +// markRouteOwner records that route was cloned out of owner, the app it was +// mounted from. Ownership is kept by route for the same reason the automatic +// HEAD provenance is: host and path do not identify the app on their own, since +// two sub-apps can be mounted at one path behind patterns that both match. +// +// Ordinary mounts are recorded as well as domain ones. A sub-app that has +// already expanded its own mounts carries its children's routes in its stack, +// and the domain mount that clones them next would otherwise take them all for +// its own. +func (app *App) markRouteOwner(route *Route, owner *App) { + if app.mountFields.routeOwners == nil { + app.mountFields.routeOwners = make(map[*Route]*App) + } + + app.mountFields.routeOwners[route] = owner +} + +// markRouteConstraints records the constraints route was parsed with, so the +// next app to re-parse it uses those rather than a registry merged from every +// app it happens to have mounted. +func (app *App) markRouteConstraints(route *Route, constraints []CustomConstraint) { + if len(constraints) == 0 { + return + } + + if app.mountFields.routeConstraints == nil { + app.mountFields.routeConstraints = make(map[*Route][]CustomConstraint) + } + + app.mountFields.routeConstraints[route] = constraints +} + +// routeConstraintsFor returns the constraints route was parsed with, falling +// back to those of the app holding it — which is where its own routes get +// theirs from. +func (app *App) routeConstraintsFor(route *Route) []CustomConstraint { + if recorded, ok := app.mountFields.routeConstraints[route]; ok { + return recorded + } + + return app.customConstraints +} + +// routeOwner returns the mounted app route was cloned out of, or nil when the +// route did not come from a mount. +func (app *App) routeOwner(route *Route) *App { + if route == nil || len(app.mountFields.routeOwners) == 0 { + return nil + } + + return app.mountFields.routeOwners[route] +} + +// appendDomainMounts re-registers the domain mounts of a mounted app on the app +// above it, moving their paths under prefix. Their domain patterns travel with +// them: the host still has to match for their config to apply. +func (app *App) appendDomainMounts(dst, mounts []domainMountedApp, prefix string, owner *App) []domainMountedApp { + for i := range mounts { + mount := &mounts[i] + + // The app they were registered on encloses them from here: their own + // ancestors are the apps between it and them, and it is the outermost. + ancestors := append([]*App{owner}, mount.ancestors...) + + moved := app.newDomainMount(mount.app, getGroupPath(prefix, mount.path), mount.matchers, ancestors, mount.declared) + dst = addDomainMount(dst, &moved) + } + + return dst +} + +// addDomainMount appends a domain mount unless the same one is already +// recorded. An app list holds the descendants of the apps it lists, so the +// startup walk reaches the same mount once per path that leads to it. +func addDomainMount(dst []domainMountedApp, mount *domainMountedApp) []domainMountedApp { + for i := range dst { + if !dst[i].equals(mount) { + continue + } + + // An app list holds the descendants of the apps it lists, so a mount is + // reached both through the app it was registered on and as an entry of + // the app above that one. Only the first walk passes through its real + // parent; the other arrives with a prefix of that chain, and with the + // constraints of the apps it skipped missing from its path — and which + // one is seen first is up to map iteration order. The complete record + // replaces the partial one whichever way round they arrive. + if len(mount.ancestors) > len(dst[i].ancestors) { + dst[i] = *mount + } + + return dst + } + + return append(dst, *mount) +} + // MountPath returns the route pattern where the current app instance was mounted as a sub-application. func (app *App) MountPath() string { return app.mountFields.mountPath @@ -108,17 +694,13 @@ func (app *App) MountPath() string { // hasMountedApps Checks if there are any mounted apps in the current application. func (app *App) hasMountedApps() bool { - return len(app.mountFields.appList) > 1 + return len(app.mountFields.appList) > 1 || len(app.mountFields.domainAppList) > 0 } // mountStartupProcess Handles the startup process of mounted apps by appending sub-app routes, generating app list keys, and processing sub-app routes. func (app *App) mountStartupProcess() { if app.hasMountedApps() { - // add routes of sub-apps - app.mountFields.subAppsProcessed.Do(func() { - app.appendSubAppLists(app.mountFields.appList) - app.mountFields.appListKeysOnce.Do(app.generateAppListKeys) - }) + app.collectSubApps() // adds the routes of the sub-apps to the current application. app.mountFields.subAppsRoutesAdded.Do(func() { app.processSubAppsRoutes() @@ -126,6 +708,17 @@ func (app *App) mountStartupProcess() { } } +// collectSubApps gathers the sub-apps mounted at any depth into appList. It runs once. +func (app *App) collectSubApps() { + if !app.hasMountedApps() { + return + } + app.mountFields.subAppsProcessed.Do(func() { + app.appendSubAppLists(app.mountFields.appList) + app.mountFields.appListKeysOnce.Do(app.generateAppListKeys) + }) +} + // generateAppListKeys generates app list keys for Render, should work after appendSubAppLists func (app *App) generateAppListKeys() { for key := range app.mountFields.appList { @@ -159,8 +752,13 @@ func (app *App) appendSubAppLists(appList map[string]*App, parent ...string) { app.mountFields.appList[prefix] = subApp } + // Domain mounts are kept out of appList, so collect them here instead. + // Doing it at startup rather than when the sub-app was mounted also + // picks up the ones registered in between. + app.mountFields.domainAppList = app.appendDomainMounts(app.mountFields.domainAppList, subApp.mountFields.domainAppList, prefix, subApp) + // The first element of appList is always the app itself. If there are no other sub apps, we should skip appending nested apps. - if len(subApp.mountFields.appList) > 1 { + if subApp.hasMountedApps() { app.appendSubAppLists(subApp.mountFields.appList, prefix) } } @@ -195,16 +793,59 @@ func (app *App) processSubAppsRoutes() { continue } + // Read the sub-app's routes by method rather than by stack index: + // an app is free to configure its own RequestMethods, and the two + // tables then neither line up nor have to be the same length. + subAppRoutes := route.group.app.routesForMethod(app.method(m)) + + // The sub-app's routes are about to be re-parsed against this app, + // so its constraints have to be resolvable here too. + app.customConstraints = mergeCustomConstraints(app.customConstraints, route.group.app.customConstraints) + + // A sub-app that registers no automatic HEAD routes of its own + // must not be given them here either: its middleware is + // registered for the methods it serves, and a HEAD route + // synthesized from the GET one would run without it. + skipsAutoHead := route.group.app.config.DisableHeadAutoRegister || route.group.app.methodInt(MethodHead) < 0 + // Create a slice to hold the sub-app's routes - subRoutes := make([]*Route, len(route.group.app.stack[m])) + subRoutes := make([]*Route, len(subAppRoutes)) // Iterate over the sub-app's routes - for j, subAppRoute := range route.group.app.stack[m] { + for j, subAppRoute := range subAppRoutes { // Clone the sub-app's route subAppRouteClone := app.copyRoute(subAppRoute) + // The prefix is this app's, and may name a constraint only this + // app knows; the route brings the constraints of the apps that + // composed its path, and those win where a name is defined + // twice. Kept per route: two apps mounted side by side can name + // one constraint differently, and neither binds the other. + constraints := mergeCustomConstraints( + slices.Clone(route.group.app.routeConstraintsFor(subAppRoute)), + app.customConstraints, + ) + // Add the parent route's path as a prefix to the sub-app's route - app.addPrefixToRoute(route.path, subAppRouteClone, route.group.app.config.RegexHandler, route.group.app.customConstraints...) + app.addPrefixToRoute(route.path, subAppRouteClone, route.group.app.config.RegexHandler, constraints...) + app.markRouteConstraints(subAppRouteClone, constraints) + + // Carry the sub-app's stance on automatic HEAD routes over to + // the clone, so this app's own routes at the same path keep + // theirs and the sub-app's descendants keep skipping. + if skipsAutoHead || route.group.app.skipsAutoHeadFor(subAppRoute) { + app.markSkipAutoHead(subAppRouteClone) + } + + // Carry the app each route came from over as well. The sub-app + // here is the wrapper the domain router built when the mount is + // a domain one, and the apps behind it are the ones whose config + // has to answer; an ordinary mount is its own routes' owner. + owner := route.group.app.routeOwner(subAppRoute) + if owner == nil { + owner = route.group.app + } + app.markRouteOwner(subAppRouteClone, owner) // Add the cloned sub-app's route to the slice of sub-app routes subRoutes[j] = subAppRouteClone diff --git a/src/vendor/github.com/gofiber/fiber/v3/path.go b/src/vendor/github.com/gofiber/fiber/v3/path.go index e5a9d6fd..b831f29d 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/path.go +++ b/src/vendor/github.com/gofiber/fiber/v3/path.go @@ -14,13 +14,27 @@ import ( "strings" "sync" + "github.com/gofiber/fiber/v3/internal/paramdelim" "github.com/gofiber/utils/v2" - utilsbytes "github.com/gofiber/utils/v2/bytes" utilsstrings "github.com/gofiber/utils/v2/strings" + "github.com/gofiber/utils/v2/swar" ) -// routeParser holds the path segments and param names -type routeParser struct { +// routeParser holds the path segments and param names. +// +// The slash bounds lead the struct on purpose: Route.match consults them for +// every parametric candidate it rejects, and Route embeds routeParser so that +// they share a cache line with the other fields the router reads while +// scanning. Keep them first when adding fields. +// +//nolint:govet // fieldalignment: the slash bounds lead deliberately, see above +type routeParser struct { // betteralign:ignore - see above + minSlashes int32 // minimum number of '/' a matching detection path can contain + maxSlashes int32 // maximum number of '/' a matching detection path can contain; only valid when maxBounded is true + maxBounded bool // false when a parameter can swallow '/', making the maximum unknowable; false also disables the max check + constParam bool // route is exactly one const segment + one plain trailing param; see matchConstParam + yields bool // an optional parameter sits directly before another parameter; see matchBacktrack + probe constProbe // first constant after a parameter, checked before getMatch; see computeProbe segs []*routeSegment // the parsed segments of the route params []string // that parameter names the parsed route wildCardCount int // number of wildcard parameters, used internally to give the wildcard parameter its number @@ -47,6 +61,7 @@ type routeSegment struct { IsParam bool // Truth value that indicates whether it is a parameter or a constant part IsGreedy bool // indicates whether the parameter is greedy or not, is used with wildcard and plus IsOptional bool // indicates whether the parameter is optional or not + CanYield bool // optional parameter directly before another parameter; only there can an empty retry help // common information IsLast bool // shows if the segment is the last one for the route HasOptionalSlash bool // segment has the possibility of an optional slash @@ -145,6 +160,8 @@ var constraintNameToID = map[string]TypeConstraint{ var ( // slash has a special role, unlike the other parameters it must not be interpreted as a parameter routeDelimiter = []byte{slashDelimiter, '-', '.'} + // slashDelimiterBytes is the byte-slice form of slashDelimiter for bytes.Count + slashDelimiterBytes = []byte{slashDelimiter} // list of chars for the parameter recognizing parameterStartChars = [256]bool{ wildcardParam: true, @@ -154,14 +171,7 @@ var ( // list of chars of delimiters and the starting parameter name char parameterDelimiterChars = append([]byte{paramStarterChar, escapeChar}, routeDelimiter...) // list of chars to find the end of a parameter - parameterEndChars = [256]bool{ - optionalParam: true, - paramStarterChar: true, - escapeChar: true, - slashDelimiter: true, - '-': true, - '.': true, - } + parameterEndChars = paramdelim.PathEndChars() ) // RoutePatternMatch reports whether path matches the provided Fiber route pattern. @@ -171,6 +181,12 @@ var ( // The optional Config argument can be used to control case sensitivity and // strict routing behavior. This helper allows checking potential matches // without registering a route. +// +// path is a rooted path, as c.Path() returns one. The empty string is read as +// "/", so RoutePatternMatch("", "/") is true; any other string without a +// leading slash matches no pattern. Request routing differs in one respect: it +// roots the request target it is handed before matching, so "OPTIONS *" is +// routed as "/*", whereas RoutePatternMatch("*", "/*") is false. func RoutePatternMatch(path, pattern string, cfg ...Config) bool { // See logic in (*Route).match and (*App).register var ctxParams [maxParams]string @@ -184,49 +200,472 @@ func RoutePatternMatch(path, pattern string, cfg ...Config) bool { if path == "" { path = "/" } - - // Cannot have an empty pattern - if pattern == "" { - pattern = "/" - } - // Pattern always start with a '/' - if pattern[0] != '/' { - pattern = "/" + pattern + // Every pattern starts with a slash, so a path without one matches none. + // (A request path is rooted before routing, see normalizeRequestPath.) + if path[0] != '/' { + return false } - patternPretty := []byte(pattern) + pattern, patternPretty, patternClean := normalizeRoutePattern(pattern, &config) + + // Mirror DefaultCtx.configDependentPaths: normalize the path, then derive + // the detection path (lowercased when CaseSensitive is off, trailing slash + // stripped when StrictRouting is off). getMatch takes both, so constraints + // see the same bytes here as in the router. + if needsPathNormalization(path) { + path = utils.UnsafeString(normalizeRequestPath([]byte(path), config.UnescapePath)) + } - // Case-sensitive routing, all to lowercase + detectionPath := path if !config.CaseSensitive { - patternPretty = utilsbytes.UnsafeToLower(patternPretty) - path = utilsstrings.ToLower(path) + detectionPath = utilsstrings.ToLower(detectionPath) } - // Strict routing, remove trailing slashes - if !config.StrictRouting && len(patternPretty) > 1 { - patternPretty = utils.TrimRight(patternPretty, '/') + if !config.StrictRouting && len(detectionPath) > 1 { + detectionPath = utils.TrimRight(detectionPath, '/') } parser, _ := routerParserPool.Get().(*routeParser) //nolint:errcheck // only contains routeParser parser.reset() - patternStr := string(patternPretty) - parser.parseRoute(patternStr, config.RegexHandler) + parser.parseRoute(patternPretty, config.RegexHandler) defer routerParserPool.Put(parser) + if !config.CaseSensitive && strings.IndexByte(pattern, paramConstraintStart) >= 0 { + // The constraints come from the pattern as written; see adoptConstraints. + var raw routeParser + raw.parseRoute(pattern, config.RegexHandler) + parser.adoptConstraints(&raw) + } + if config.StrictRouting { + parser.applyStrictRouting() + } - // '*' wildcard matches any path - if (patternStr == "/" && path == "/") || patternStr == "/*" { + // '*' wildcard matches any path; the star flag keeps an escaped "/\*" literal. + if (patternClean == "/" && detectionPath == "/") || patternPretty == "/*" { return true } // Does this route have parameters if len(parser.params) > 0 { - if match := parser.getMatch(path, path, &ctxParams, false); match { + if match := parser.getMatch(detectionPath, path, &ctxParams, false); match { return true } } // Check for a simple match - patternPretty = RemoveEscapeCharBytes(patternPretty) + return patternClean == detectionPath +} + +// normalizeRoutePattern keeps the three forms needed by the router together: +// raw preserves parameter names and constraint arguments, pretty applies the +// routing configuration but retains escapes for parsing, and clean is the +// literal comparison key. It does not decode or normalize request paths. +// +//nolint:nonamedreturns // names distinguish the three string representations +func normalizeRoutePattern(pattern string, config *Config) (raw, pretty, clean string) { + if pattern == "" { + pattern = "/" + } + if pattern[0] != '/' { + pattern = "/" + pattern + } + raw = pattern + pretty = raw + if !config.CaseSensitive { + pretty = utilsstrings.ToLower(pretty) + } + if !config.StrictRouting && len(pretty) > 1 { + pretty = utils.TrimRight(pretty, '/') + } + clean = RemoveEscapeChar(pretty) + return raw, pretty, clean +} + +// adoptConstraints takes the constraints of raw's parameters for this parser's. +// The parser is built from the prettified, possibly lowercased pattern, which +// would corrupt constraint names and arguments; raw is the pattern as written. +func (parser *routeParser) adoptConstraints(raw *routeParser) { + if len(parser.params) != len(raw.params) { + return + } + j := 0 + for _, seg := range parser.segs { + if !seg.IsParam { + continue + } + for j < len(raw.segs) && !raw.segs[j].IsParam { + j++ + } + if j >= len(raw.segs) { + return + } + seg.Constraints = raw.segs[j].Constraints + j++ + } + parser.constParam = isConstParamShape(parser.segs) +} + +// applyStrictRouting makes a trailing slash on the last constant segment +// mandatory under StrictRouting, so "/a/:id/" does not match "/a/x". +func (parser *routeParser) applyStrictRouting() { + if n := len(parser.segs); n > 0 { + if last := parser.segs[n-1]; !last.IsParam && last.HasOptionalSlash { + last.HasOptionalSlash = false + } + } + parser.computeSlashBounds() +} + +// unescapePath decodes the percent-encoded bytes of a path in place. Unlike the +// form-argument decoder it leaves '+' alone and keeps a malformed escape as is. +func unescapePath(b []byte) []byte { + i := bytes.IndexByte(b, '%') + if i == -1 { + return b + } + n := len(b) + dst := i + for i < n { + if b[i] == '%' && i+2 < n { + if hi, lo := unhex(b[i+1]), unhex(b[i+2]); hi >= 0 && lo >= 0 { + b[dst] = byte(hi<<4 | lo) //nolint:gosec // G115: both nibbles are 0-15 + dst++ + i += 3 + continue + } + } + b[dst] = b[i] + dst++ + i++ + } + return b[:dst] +} + +// unhex returns the value of a hexadecimal digit, or -1 for any other byte. +func unhex(c byte) int { + switch { + case c >= '0' && c <= '9': + return int(c - '0') + case c >= 'a' && c <= 'f': + return int(c-'a') + 10 + case c >= 'A' && c <= 'F': + return int(c-'A') + 10 + default: + return -1 + } +} + +// pathUnreserved marks the unreserved characters of RFC 3986 Section 2.3. +// Only their percent-encoded forms name the same resource as the characters +// themselves (Section 6.2.2.2), so they are the escapes the router decodes. +var pathUnreserved = newPathUnreserved() + +func newPathUnreserved() [256]bool { + var unreserved [256]bool + for c := byte('a'); c <= 'z'; c++ { + unreserved[c] = true + unreserved[c-'a'+'A'] = true + } + for c := byte('0'); c <= '9'; c++ { + unreserved[c] = true + } + for _, c := range []byte("-._~") { + unreserved[c] = true + } + return unreserved +} + +// unescapeSafePath normalizes the percent escapes of b in place (RFC 3986 +// Section 6.2.2): an escape of an unreserved character is decoded, and any +// other escape is kept with uppercase hex digits. A stray "%" that begins no +// escape is kept as sent, unless the two bytes written after it are hex +// digits, which only a decoded escape can produce: kept, it would read as an +// escape no one sent, "%%370rivate" becoming "%70rivate", which decodes to +// "private", a path the router never matched. Such a "%" is written as "%25". +// The result is a valid path that normalizes to itself and holds no escape of +// an unreserved character. The escapes the router keeps, such as "%2F", are +// still meant to stay encoded: the result is not a path to percent-decode. +// Since a stray "%" changes only next to a decoded escape, it comes out the +// same in a path matched as sent (see pathNeedsNormalization) as in one +// normalized for another reason, so "/files/100%" and "/files/./100%" both +// end in "100%". +func unescapeSafePath(b []byte) []byte { + const upperhex = "0123456789ABCDEF" + i := bytes.IndexByte(b, '%') + if i == -1 { + return b + } + n := len(b) + dst := i + for i < n { + if b[i] != '%' { + b[dst] = b[i] + dst++ + i++ + continue + } + if i+2 < n { + if hi, lo := unhex(b[i+1]), unhex(b[i+2]); hi >= 0 && lo >= 0 { + if v := byte(hi<<4 | lo); pathUnreserved[v] { //nolint:gosec // G115: both nibbles are 0-15 + b[dst] = v + dst++ + } else { + b[dst], b[dst+1], b[dst+2] = '%', upperhex[hi], upperhex[lo] + dst += 3 + } + i += 3 + continue + } + } + if strayPercentNeedsEscape(b, i+1) { + return escapeStrayPercent(b, dst, i) + } + b[dst] = '%' + dst++ + i++ + } + return b[:dst] +} + +// escapeStrayPercent finishes unescapeSafePath from the stray "%" at b[i] that +// has to be written as "%25", once the in-place pass has written its result so +// far to b[:dst]. Writing "%25" there would overwrite the escape after it before +// the pass has read it, so the rest is written to a new slice. Only a malformed +// request path pays for the copy, and it is made once: every "%25" is paired +// with the escape decoded within the two bytes after it, which is three bytes +// shorter than it was, and no decoded escape completes two of them, so the +// result is never longer than b. +func escapeStrayPercent(b []byte, dst, i int) []byte { + const upperhex = "0123456789ABCDEF" + n := len(b) + out := make([]byte, dst, n) + copy(out, b[:dst]) + for i < n { + if b[i] != '%' { + out = append(out, b[i]) + i++ + continue + } + if i+2 < n { + if hi, lo := unhex(b[i+1]), unhex(b[i+2]); hi >= 0 && lo >= 0 { + if v := byte(hi<<4 | lo); pathUnreserved[v] { //nolint:gosec // G115: both nibbles are 0-15 + out = append(out, v) + } else { + out = append(out, '%', upperhex[hi], upperhex[lo]) + } + i += 3 + continue + } + } + if strayPercentNeedsEscape(b, i+1) { + out = append(out, '%', '2', '5') + } else { + out = append(out, '%') + } + i++ + } + return out +} + +// strayPercentNeedsEscape reports whether the stray "%" before b[j] has to be +// written as "%25", that is whether the next two bytes unescapeSafePath writes +// after it are hex digits. +func strayPercentNeedsEscape(b []byte, j int) bool { + if first := nextNormalizedByte(b, &j); unhex(first) < 0 { + return false + } + second := nextNormalizedByte(b, &j) + return unhex(second) >= 0 +} + +// nextNormalizedByte returns the first byte unescapeSafePath writes for b[*j:] +// and moves *j past the input that byte takes. An escape it keeps and a stray +// "%" both write a '%' first, and past the end it returns 0; neither is a hex +// digit. +func nextNormalizedByte(b []byte, j *int) byte { + i := *j + if i >= len(b) { + return 0 + } + if b[i] == '%' && i+2 < len(b) { + if hi, lo := unhex(b[i+1]), unhex(b[i+2]); hi >= 0 && lo >= 0 { + if v := byte(hi<<4 | lo); pathUnreserved[v] { //nolint:gosec // G115: both nibbles are 0-15 + *j = i + 3 + return v + } + } + } + *j = i + 1 + return b[i] +} + +// cleanPathSegments removes the "." and ".." segments of b in place, as +// RFC 3986 Section 5.2.4 describes. ".." never climbs above the root, a path +// ending in a removed segment keeps its trailing slash ("/a/b/.." is "/a/"), +// and empty segments stay: "/a//b" and "/a/b" are different paths. +func cleanPathSegments(b []byte) []byte { + if !hasDotSegment(b) { + return b + } + n := len(b) + rooted := b[0] == '/' + i := 0 + if rooted { + i = 1 + } + w := 0 + trailingSlash := false + for i <= n { + j := i + for j < n && b[j] != '/' { + j++ + } + seg := b[i:j] + last := j == n + switch { + case len(seg) == 1 && seg[0] == '.': + trailingSlash = last + case len(seg) == 2 && seg[0] == '.' && seg[1] == '.': + if k := bytes.LastIndexByte(b[:w], '/'); k >= 0 { + w = k + } else { + w = 0 + } + trailingSlash = last + default: + if rooted || w > 0 { + b[w] = '/' + w++ + } + w += copy(b[w:], seg) + trailingSlash = false + } + i = j + 1 + } + if trailingSlash && (w == 0 || b[w-1] != '/') { + b[w] = '/' + w++ + } + return b[:w] +} + +// pairWindow is the span two words that overlap by one byte cover. +const pairWindow = 2*swar.WordLen - 1 + +// slashDotLanes flags the lanes of w holding a '/' followed within w by a +// '.'. Load8 puts byte k in lane k, so a shift by one lane compares each byte +// with its successor; callers overlap words by one byte for the pair that +// straddles two words. +func slashDotLanes(w uint64) uint64 { + return swar.MatchByteMask(w, '/') & (swar.MatchByteMask(w, '.') >> 8) +} + +// needsPathNormalization reports whether normalizeRequestPath could change s: +// it is unrooted, or holds a percent escape or a segment starting with a dot. +// It scans a word at a time and serves where fasthttp's own normalization +// cannot answer the question (see DefaultCtx.pathNeedsNormalization). +func needsPathNormalization(s string) bool { + n := len(s) + if n == 0 || s[0] != '/' { + return true + } + if n >= swar.WordLen { + // Words overlap by one byte so every adjacent pair shares a word; a + // pinned two-word window keeps the loads at constant offsets. + percent := swar.Broadcast('%') + i := 0 + for ; i+pairWindow <= n; i += pairWindow - 1 { + win := s[i : i+pairWindow] + w0, w1 := swar.Load8(win, 0), swar.Load8(win, swar.WordLen-1) + if swar.ZeroLanes(w0^percent)|swar.ZeroLanes(w1^percent)|slashDotLanes(w0)|slashDotLanes(w1) != 0 { + return true + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen - 1 { + w := swar.Load8(s, i) + if swar.ZeroLanes(w^percent)|slashDotLanes(w) != 0 { + return true + } + } + // the loops covered the bytes up to i; a word aligned to the end takes the rest + if i >= n-1 { + return false + } + w := swar.Load8(s, n-swar.WordLen) + return swar.ZeroLanes(w^percent)|slashDotLanes(w) != 0 + } + for i := range n { + switch s[i] { + case '%': + return true + case '/': + if i+1 < n && s[i+1] == '.' { + return true + } + } + } + return false +} + +// hasDotSegment reports whether cleanPathSegments could change b: it holds a +// segment starting with a dot. +func hasDotSegment(b []byte) bool { + n := len(b) + if n == 0 { + return false + } + if b[0] == '.' { + return true + } + if n >= swar.WordLen { + i := 0 + for ; i+pairWindow <= n; i += pairWindow - 1 { + win := b[i : i+pairWindow : i+pairWindow] + if slashDotLanes(swar.Load8(win, 0))|slashDotLanes(swar.Load8(win, swar.WordLen-1)) != 0 { + return true + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen - 1 { + if slashDotLanes(swar.Load8(b, i)) != 0 { + return true + } + } + if i >= n-1 { + return false + } + return slashDotLanes(swar.Load8(b, n-swar.WordLen)) != 0 + } + for i := range n - 1 { + if b[i] == '/' && b[i+1] == '.' { + return true + } + } + return false +} - return string(patternPretty) == path +// normalizeRequestPath normalizes a request path in place as RFC 3986 +// Section 6.2.2 describes: an unrooted path is rooted, percent escapes are +// normalized, all of them decoded when unescapeAll (UnescapePath) is set and +// otherwise only those of unreserved characters, and then "." and ".." +// segments are removed. Decoding runs exactly once, so "%2570rivate" stays a +// literal name, while "/%70rivate", "/./private" and "/x/../private" all +// match a route or guard on "/private". +// +// The rooting covers the absolute-form target with an empty path +// ("GET http://host?q") and the asterisk-form "OPTIONS *", which carry no +// leading slash. fasthttp roots its own copy, which is how such a path gets +// here, and routes and Use prefixes assume a rooted path: unrooted, it slipped +// past every root-level middleware while a "/*" route still matched it. +// RFC 9112 Section 3.2 reads the empty path as "/". +func normalizeRequestPath(b []byte, unescapeAll bool) []byte { //nolint:revive // the flag mirrors Config.UnescapePath + if len(b) == 0 || b[0] != '/' { + b = append(b, 0) + copy(b[1:], b) + b[0] = '/' + } + if unescapeAll { + b = unescapePath(b) + } else { + b = unescapeSafePath(b) + } + return cleanPathSegments(b) } func (parser *routeParser) reset() { @@ -234,6 +673,11 @@ func (parser *routeParser) reset() { parser.params = parser.params[:0] parser.wildCardCount = 0 parser.plusCount = 0 + parser.minSlashes = 0 + parser.maxSlashes = 0 + parser.maxBounded = false + parser.constParam = false + parser.probe = constProbe{} } // parseRoute analyzes the route and divides it into segments for constant areas and parameters, @@ -258,6 +702,229 @@ func (parser *routeParser) parseRoute(pattern string, regexHandler any, customCo parser.segs[len(parser.segs)-1].IsLast = true } parser.segs = addParameterMetaInfo(parser.segs) + for _, s := range parser.segs { + parser.yields = parser.yields || s.CanYield + } + parser.constParam = isConstParamShape(parser.segs) +} + +// isConstParamShape reports whether segs is the "/const/:param" shape that +// matchConstParam specializes: exactly one constant segment followed by one +// plain trailing parameter. Every condition here is one the specialized body +// assumes rather than re-checks, so keep the two in step. +func isConstParamShape(segs []*routeSegment) bool { + if len(segs) != 2 { + return false + } + c, p := segs[0], segs[1] + return !c.IsParam && !c.HasOptionalSlash && + p.IsParam && p.IsLast && !p.IsGreedy && !p.IsOptional && len(p.Constraints) == 0 +} + +// computeSlashBounds precomputes the minimum and maximum number of '/' bytes a +// detection path can contain and still match this pattern, so the router can +// reject candidates with an integer compare before walking their segments. +// The unbounded cases mirror the findParamLen branches that let a parameter +// swallow '/'; Test_Route_Match_SlashBoundsDifferential guards the pairing. +func (parser *routeParser) computeSlashBounds() { + minSlashes := 0 + maxSlashes := 0 + bounded := true + for _, seg := range parser.segs { + if seg.IsParam { + switch { + case seg.IsGreedy: + // '*' and '+' match across '/' + bounded = false + case !seg.IsLast && seg.Length == 1: + // adjacent parameters consume one byte each, possibly a '/' + bounded = false + case !seg.IsLast && len(seg.ComparePart) == 1 && seg.ComparePart[0] != slashDelimiter: + // findParamLen's single-byte IndexByte search has no slash guard + bounded = false + } + // otherwise a non-greedy parameter never contains '/': the last + // segment stops at the next '/', and the multi-byte ComparePart + // branch rejects parameters that would span one + continue + } + n := strings.Count(seg.Const, string(slashDelimiter)) + minSlashes += n + maxSlashes += n + if seg.HasOptionalSlash { + // getMatch may drop the trailing '/' of this const part + minSlashes-- + } + } + parser.minSlashes = int32(minSlashes) + if bounded { + parser.maxSlashes = int32(maxSlashes) + parser.maxBounded = true + } +} + +// constProbe is the first constant after a parameter, packed like +// pathHeadWord, which Route.match tests at the slash it must start at before +// walking the segments: "/repos/:owner/:repo/issues/:number" and +// "/repos/:owner/:repo/pulls/:number" pass the prefix filter and the slash +// bounds alike and differ here. The slash is found per request: the first +// parameter starts at from and ends at the next '/', and skip more slashes +// separate it from the constant. A zero mask means no probe. +type constProbe struct { + word uint64 // the constant's leading bytes, packed little-endian + mask uint64 // covers the packed bytes; 0 means no probe + from int32 // length of the leading constant, where the first parameter starts + skip int32 // slashes to pass over after from before the constant's own +} + +// computeProbe picks the first constant after a parameter that is longer than +// a lone '/'. Every segment before it must keep that constant's slash +// predictable: parameters end at the next '/' (not greedy, optional or +// fixed-length, and a compare part led by '/'), and no constant drops an +// optional trailing '/'. Otherwise the route gets no probe. +// Test_RouteParser_Probe pins the gate. +func (parser *routeParser) computeProbe() { + parser.probe = constProbe{} + segs := parser.segs + if len(segs) == 0 || segs[0].IsParam || segs[0].HasOptionalSlash { + return + } + from := len(segs[0].Const) + skip := 0 + for _, seg := range segs[1:] { + if seg.IsParam { + if seg.IsGreedy || seg.IsOptional || seg.Length != 0 || + seg.ComparePart == "" || seg.ComparePart[0] != slashDelimiter { + return + } + continue + } + c := seg.Const + if seg.HasOptionalSlash { + // getMatch may match this constant without its trailing '/' + c = c[:len(c)-1] + } + // The parameter before this constant passed the gate above, and its + // compare part is derived from this constant, so c starts with '/'. + if len(c) > 1 { + parser.probe = newConstProbe(c, from, skip) + return + } + if seg.HasOptionalSlash { + return + } + // A constant this short is exactly "/": one more slash to pass over. + skip++ + } +} + +// newConstProbe packs the first word of c into a probe located by from and skip. +func newConstProbe(c string, from, skip int) constProbe { + word, mask := packConst(c) + return constProbe{word: word, mask: mask, from: int32(from), skip: int32(skip)} //nolint:gosec // G115 - offsets into a route pattern +} + +// packConst packs up to a word of s like pathHeadWord and returns it with the +// mask covering its lanes; an empty s yields a zero mask. +// +//nolint:nonamedreturns // the pair is easier to read named than by position +func packConst(s string) (word, mask uint64) { + if len(s) > swar.WordLen { + s = s[:swar.WordLen] + } + if s == "" { + return 0, 0 + } + mask = ^uint64(0) + if n := len(s); n < swar.WordLen { + mask = uint64(1)<<(8*n) - 1 + } + return pathHeadWord(s), mask +} + +// rejects reports whether the probe's constant is not at its slash in +// detectionPath, or the path is too short to reach it. +func (p *constProbe) rejects(detectionPath string) bool { + w, ok := p.locate(detectionPath) + return !ok || w&p.mask != p.word +} + +// locate returns the word of detectionPath at the probe's slash, packed like +// pathHeadWord, or false when the path is too short to reach that slash. It +// depends on from and skip alone, which is what lets probeMemo share one +// search among the routes of a bucket that probe the same slash. The slashes +// are found with an inline swar.MatchByteMask scan rather than +// strings.IndexByte: a parameter spans a few bytes, so the slash is nearly +// always in the first word and the call was most of the check. +func (p *constProbe) locate(detectionPath string) (uint64, bool) { + n := len(detectionPath) + i := int(p.from) + if i > n { + return 0, false + } + for skip := p.skip; ; skip-- { + var m uint64 + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m = swar.MatchByteMask(swar.Load8(detectionPath, i), slashDelimiter); m != 0 { + break + } + } + switch { + case m != 0: + i += swar.FirstLane(m) + case i < n && n >= swar.WordLen: + from := n - swar.WordLen + m = swar.MatchByteMask(swar.Load8(detectionPath, from), slashDelimiter) & (^uint64(0) << (8 * (i - from))) + if m == 0 { + return 0, false + } + i = from + swar.FirstLane(m) + default: + for i < n && detectionPath[i] != slashDelimiter { + i++ + } + if i == n { + return 0, false + } + } + if skip == 0 { + break + } + i++ + } + // common case inline; wordAt handles the end of the path + if i+swar.WordLen <= n { + return swar.Load8(detectionPath, i), true + } + return wordAt(detectionPath, i), true +} + +// probeMemo shares constProbe.locate among the candidates of one route scan. +// Routes that differ only after a parameter, as a REST resource's endpoints +// do, probe the same slash, so the scan finds it once and each such candidate +// costs a masked compare. The zero value is an empty memo. +type probeMemo struct { + // key is the from and skip of the probe locate last ran for, packed by + // probeMemo.headRejects: two probes with equal keys locate the same word + // of any detection path. It is 0 when none has, since a probe's from is + // never 0 (see scanHead.setProbe). + key uint64 + word uint64 // what locate returned for that probe + ok bool // what locate returned for that probe +} + +// wordAt packs s[i:i+8] little-endian without reading past s: lanes past the +// end are zero, and when s holds a word the tail is an overlapping load +// shifted so that lane 0 is s[i]. Requires 0 <= i <= len(s). +func wordAt(s string, i int) uint64 { + rest := len(s) - i + if rest >= swar.WordLen { + return swar.Load8(s, i) + } + if len(s) >= swar.WordLen { + return swar.Load8(s, len(s)-swar.WordLen) >> (8 * (swar.WordLen - rest)) + } + return pathHeadWord(s[i:]) } // parseRoute analyzes the route and divides it into segments for constant areas and parameters, @@ -265,6 +932,10 @@ func (parser *routeParser) parseRoute(pattern string, regexHandler any, customCo func parseRoute(pattern string, regexHandler any, customConstraints ...CustomConstraint) routeParser { parser := routeParser{} parser.parseRoute(pattern, regexHandler, customConstraints...) + // The slash bounds and the probe only speed up the router's scan, so they + // are computed here rather than on RoutePatternMatch's per-call path. + parser.computeSlashBounds() + parser.computeProbe() // Check if the route has too many parameters if len(parser.params) > maxParams { @@ -298,6 +969,7 @@ func addParameterMetaInfo(segs []*routeSegment) []*routeSegment { for i := range segLen { // check how often the compare part is in the following const parts if segs[i].IsParam { + segs[i].CanYield = segs[i].IsOptional && !segs[i].IsGreedy && segLen > i+1 && segs[i+1].IsParam // check if parameter segments are directly after each other; // when neither this parameter nor the next parameter are greedy, we only want one character if segLen > i+1 && !segs[i].IsGreedy && segs[i+1].IsParam && !segs[i+1].IsGreedy { @@ -313,7 +985,7 @@ func addParameterMetaInfo(segs []*routeSegment) []*routeSegment { } } // check if the end of the segment is an optional slash and then if the segment is optional or the last one - } else if segs[i].Const[len(segs[i].Const)-1] == slashDelimiter && (segs[i].IsLast || (segLen > i+1 && segs[i+1].IsOptional)) { + } else if segs[i].Const != "" && segs[i].Const[len(segs[i].Const)-1] == slashDelimiter && (segs[i].IsLast || (segLen > i+1 && segs[i+1].IsOptional)) { segs[i].HasOptionalSlash = true } } @@ -511,8 +1183,17 @@ func hasPartialMatchBoundary(path string, matchedLength int) bool { // getMatch parses the passed url and tries to match it against the route segments and determine the parameter positions func (parser *routeParser) getMatch(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint:revive // Accepting a bool param is fine here + if parser.constParam { + return parser.matchConstParam(detectionPath, path, params, partialCheck) + } + if parser.yields { + return parser.matchBacktrack(detectionPath, path, params, partialCheck) + } + originalDetectionPath := detectionPath - var i, paramsIterator, partLen int + // offset indexes into the never-resliced path; it only advances by bytes consumed + // from detectionPath (never longer than path), so offset+i stays in bounds. + var i, paramsIterator, partLen, offset int for _, segment := range parser.segs { partLen = len(detectionPath) // check const segment @@ -521,6 +1202,7 @@ func (parser *routeParser) getMatch(detectionPath, path string, params *[maxPara // is optional part or the const part must match with the given string // check if the end of the segment is an optional slash // the unsigned compare proves 0 <= i <= len(detectionPath), keeping detectionPath[:i] bounds-check free + // NOTE: computeSlashBounds' minSlashes accounts for this optional-slash drop if segment.HasOptionalSlash && partLen == i-1 && detectionPath == segment.Const[:i-1] { i-- } else if uint(i) > uint(len(detectionPath)) || detectionPath[:i] != segment.Const { @@ -533,7 +1215,7 @@ func (parser *routeParser) getMatch(detectionPath, path string, params *[maxPara return false } // take over the params positions - params[paramsIterator] = path[:i] + params[paramsIterator] = path[offset : offset+i] if !segment.IsOptional || i != 0 { // check constraint @@ -549,7 +1231,8 @@ func (parser *routeParser) getMatch(detectionPath, path string, params *[maxPara // reduce founded part from the string if partLen > 0 { - detectionPath, path = detectionPath[i:], path[i:] + detectionPath = detectionPath[i:] + offset += i } } if detectionPath != "" { @@ -565,8 +1248,178 @@ func (parser *routeParser) getMatch(detectionPath, path string, params *[maxPara return true } +type backtrackPoint struct { + detectionPath string + segIdx int + offset int + paramsIterator int +} + +// maxBacktrackRetries bounds optional-parameter retry attempts to prevent +// exponential execution times on routes with many adjacent optional parameters. +const maxBacktrackRetries = 16 + +// matchBacktrack is getMatch for routes with an optional parameter directly before another +// parameter: it retries that parameter as empty (/:a:b?:c on /ac), up to maxBacktrackRetries. +func (parser *routeParser) matchBacktrack(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint:revive // mirrors getMatch's signature + originalDetectionPath := detectionPath + var i, paramsIterator, partLen, offset, retries, segIdx int + var backtrackStack [maxParams]backtrackPoint + backtrackLen := 0 + + restore := func() bool { + if backtrackLen > 0 && retries < maxBacktrackRetries { + retries++ + backtrackLen-- + if backtrackLen >= 0 && backtrackLen < len(backtrackStack) { + bp := backtrackStack[backtrackLen] + segIdx = bp.segIdx + 1 + detectionPath = bp.detectionPath + offset = bp.offset + paramsIterator = bp.paramsIterator + params[paramsIterator-1] = "" + return true + } + } + return false + } + +segments: + for { + if segIdx >= len(parser.segs) { + if detectionPath != "" { + if !partialCheck { + if restore() { + continue + } + return false + } + consumedLength := len(originalDetectionPath) - len(detectionPath) + if !hasPartialMatchBoundary(originalDetectionPath, consumedLength) { + if restore() { + continue + } + return false + } + } + return true + } + + segment := parser.segs[segIdx] + partLen = len(detectionPath) + + if !segment.IsParam { + i = segment.Length + // is optional part or the const part must match with the given string + // check if the end of the segment is an optional slash + // the unsigned compare proves 0 <= i <= len(detectionPath), keeping detectionPath[:i] bounds-check free + // NOTE: computeSlashBounds' minSlashes accounts for this optional-slash drop + if segment.HasOptionalSlash && partLen == i-1 && detectionPath == segment.Const[:i-1] { + i-- + } else if uint(i) > uint(len(detectionPath)) || detectionPath[:i] != segment.Const { + if restore() { + continue + } + return false + } + } else { + i = findParamLen(detectionPath, segment) + if !segment.IsOptional && i == 0 { + if restore() { + continue + } + return false + } + + if !segment.IsOptional || i != 0 { + paramValue := path[offset : offset+i] + for _, c := range segment.Constraints { + if matched := c.matchConstraint(paramValue); !matched { + // an earlier optional may yield; this value itself is never retried as empty + if restore() { + continue segments + } + return false + } + } + } + + // retry point: this parameter as empty + if segment.CanYield && i > 0 && backtrackLen < len(backtrackStack) { + backtrackStack[backtrackLen] = backtrackPoint{ + segIdx: segIdx, + offset: offset, + paramsIterator: paramsIterator + 1, + detectionPath: detectionPath, + } + backtrackLen++ + } + + params[paramsIterator] = path[offset : offset+i] + paramsIterator++ + } + + if partLen > 0 { + detectionPath = detectionPath[i:] + offset += i + } + segIdx++ + } +} + +// matchConstParam is getMatch specialized to the "/const/:param" shape, which +// is what most REST endpoints look like ("/user/keys/:key_id"). It is a +// straight-line rewrite of the generic segment walk for that shape, not a +// different matcher: isConstParamShape gates on exactly the properties that +// let each step below collapse. +// +// Walking the generic loop for two segments costs a pointer chase per segment, +// the IsParam/IsOptional/IsLast branches, the constraint loop and the reslice +// bookkeeping, all to reach the same three operations this does directly. +func (parser *routeParser) matchConstParam(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint:revive // mirrors getMatch's signature + constSeg := parser.segs[0] + + // Same guard as the generic const branch; HasOptionalSlash is excluded by + // the gate, so the trailing-slash-drop case cannot arise here. + n := constSeg.Length + if uint(n) > uint(len(detectionPath)) || detectionPath[:n] != constSeg.Const { + return false + } + + // The parameter is last and non-greedy, so findParamLenForLastSegment would + // stop it at the next '/', or take the remainder when there is none. + rest := detectionPath[n:] + i := len(rest) + if idx := strings.IndexByte(rest, slashDelimiter); idx != -1 { + i = idx + } + // The gate excludes optional parameters, so an empty one is no match. + if i == 0 { + return false + } + + // offset into path, never resliced, exactly as the generic loop tracks it + params[0] = path[n : n+i] + + if i == len(rest) { + return true + } + // Leftover detection path: only prefix (use) routes may stop short, and + // only on a segment boundary. + if !partialCheck { + return false + } + return hasPartialMatchBoundary(detectionPath, n+i) +} + // findParamLen for the expressjs wildcard behavior (right to left greedy) // look at the other segments and take what is left for the wildcard from right to left +// +// NOTE: computeSlashBounds mirrors which branches here let a parameter consume +// '/' (greedy, adjacent Length==1, single-byte ComparePart). When changing how +// parameters consume '/', update computeSlashBounds or the router's slash-count +// quick-reject will wrongly filter routes. +// CanYield relies on a parameter ending at the first occurrence of its ComparePart. func findParamLen(s string, segment *routeSegment) int { if segment.IsLast { return findParamLenForLastSegment(s, segment) @@ -587,6 +1440,19 @@ func findParamLen(s string, segment *routeSegment) int { if constPosition := strings.IndexByte(s, segment.ComparePart[0]); constPosition != -1 { return constPosition } + } else if len(segment.ComparePart) > 1 && !segment.IsGreedy && segment.ComparePart[0] == slashDelimiter { + // A non-greedy parameter cannot span a '/', so it ends at the first + // '/' of s, and only if the compare part sits there. Otherwise the + // answer is 0 whether the compare part occurs later or not at all: + // the constant after the parameter fails either way. + slash := strings.IndexByte(s, slashDelimiter) + if slash == -1 { + return len(s) + } + if strings.HasPrefix(s[slash:], segment.ComparePart) { + return slash + } + return 0 } else if constPosition := strings.Index(s, segment.ComparePart); constPosition != -1 { // if the compare part was found, but contains a slash although this part is not greedy, then it must not match // example: /api/:param/fixedEnd -> path: /api/123/456/fixedEnd = no match , /api/123/fixedEnd = match @@ -652,14 +1518,8 @@ func RemoveEscapeChar(word string) string { // Slow path: copy and remove escape characters b := []byte(word) - dst := escapeIdx - for src := escapeIdx + 1; src < len(b); src++ { - if b[src] != '\\' { - b[dst] = b[src] - dst++ - } - } - return string(b[:dst]) + tail := RemoveEscapeCharBytes(b[escapeIdx:]) + return string(b[:escapeIdx+len(tail)]) } // RemoveEscapeCharBytes removes escape characters diff --git a/src/vendor/github.com/gofiber/fiber/v3/prefork.go b/src/vendor/github.com/gofiber/fiber/v3/prefork.go index 83133f9a..52424369 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/prefork.go +++ b/src/vendor/github.com/gofiber/fiber/v3/prefork.go @@ -78,6 +78,7 @@ func (app *App) prefork(addr string, tlsConfig *tls.Config, cfg *ListenConfig) e // prepare the server for the start app.startupProcess() + app.hookHeaderReceived() if cfg.ListenerAddrFunc != nil { cfg.ListenerAddrFunc(ln.Addr()) diff --git a/src/vendor/github.com/gofiber/fiber/v3/redirect.go b/src/vendor/github.com/gofiber/fiber/v3/redirect.go index eb4dbf0b..28a9fd18 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/redirect.go +++ b/src/vendor/github.com/gofiber/fiber/v3/redirect.go @@ -12,11 +12,10 @@ import ( "sync" "github.com/gofiber/utils/v2" - utilsbytes "github.com/gofiber/utils/v2/bytes" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" - "github.com/gofiber/fiber/v3/binder" + "github.com/gofiber/fiber/v3/internal/fieldname" "github.com/gofiber/fiber/v3/internal/schemehost" ) @@ -51,12 +50,8 @@ var flashCookieNeedle = []byte(FlashCookieName + "=") // 1) a fast raw-header prefilter to avoid unnecessary cookie parsing, // 2) an exact cookie lookup to avoid prefix false positives (e.g. fiber_flashX). func hasFlashCookie(header *fasthttp.RequestHeader) bool { - rawHeaders := header.RawHeaders() - if len(rawHeaders) == 0 { - return false - } - - if !bytes.Contains(rawHeaders, flashCookieNeedle) { + // A request built programmatically has no raw headers, so the prefilter cannot answer for it. + if rawHeaders := header.RawHeaders(); len(rawHeaders) > 0 && !bytes.Contains(rawHeaders, flashCookieNeedle) { return false } @@ -127,6 +122,10 @@ func ReleaseRedirect(r *Redirect) { func (r *Redirect) release() { r.status = StatusSeeOther + // Zero before truncating: WithInput copies the whole request body into these + // entries, and a bare [:0] leaves those strings reachable from the backing + // array for as long as the pooled *Redirect lives. + clear(r.messages[:cap(r.messages)]) r.messages = r.messages[:0] r.c = nil } @@ -161,6 +160,7 @@ func (r *Redirect) Status(code int) *Redirect { // They will be sent as a cookie. // You can get them by using: Redirect().Messages(), Redirect().Message() // Note: You must use escape char before using ',' and ':' chars to avoid wrong parsing. +// No cookie is set when Config.DisableFlashMessages is on. func (r *Redirect) With(key, value string, level ...uint8) *Redirect { // Get level var msgLevel uint8 @@ -191,10 +191,13 @@ func (r *Redirect) With(key, value string, level ...uint8) *Redirect { // They will be sent as a cookie. // This method can send form, multipart form, query data to redirected route. // You can get them by using: Redirect().OldInputs(), Redirect().OldInput() +// It does nothing when Config.DisableFlashMessages is on. func (r *Redirect) WithInput() *Redirect { - // Get content-type - ctype := utils.UnsafeString(utilsbytes.UnsafeToLower(r.c.RequestCtx().Request.Header.ContentType())) - ctype = binder.FilterFlags(utils.ParseVendorSpecificContentType(ctype)) + if r.c.app.config.DisableFlashMessages { + return r + } + + ctype := bindMediaType(&r.c.RequestCtx().Request.Header) oldInput := acquireOldInput() defer releaseOldInput(oldInput) @@ -346,7 +349,8 @@ func (r *Redirect) Route(name string, config ...RedirectConfig) error { cfg = config[0] } - // Get location from route name + // Get location from route name. buildRouteURL already holds the composed + // path to this origin, so only the query is left to place. route := r.c.App().GetRoute(name) location, err := r.c.getLocationFromRoute(&route, cfg.Params) if err != nil { @@ -366,27 +370,55 @@ func (r *Redirect) Route(name string, config ...RedirectConfig) error { first = false queryText.WriteString(k) queryText.WriteByte('=') - queryText.WriteString(v) + // Escape the value so characters like &, =, # or + don't break the + // query string. Keys are left as-is to preserve the nested-key + // convention (e.g. `data[0][name]`) used elsewhere. + queryText.B = utils.AppendQueryEscape(queryText.B, v) } - return r.To(location + "?" + r.c.app.toString(queryText.Bytes())) + // Concatenated here rather than in a helper: the result goes straight to + // To, so escape analysis can build it on the stack. Returning it from a + // function cost an allocation per redirect. + query := r.c.app.toString(queryText.Bytes()) + separator, fragment := queryMergePoint(location) + if fragment < 0 { + return r.To(location + separator + query) + } + return r.To(location[:fragment] + separator + query + location[fragment:]) } return r.To(location) } +// queryMergePoint says where a query belongs in location: the separator that +// introduces it, and where the fragment starts, or -1. +func queryMergePoint(location string) (separator string, fragment int) { //nolint:nonamedreturns // the two results are easy to swap without names + fragment = strings.IndexByte(location, '#') + + query := location + if fragment >= 0 { + query = location[:fragment] + } + if strings.IndexByte(query, '?') >= 0 { + return "&", fragment + } + return "?", fragment +} + // Back redirect to the URL to referer. // It validates that the Referer is same-origin to prevent open redirect attacks. // If the Referer is missing, invalid, or cross-origin, the fallback URL is used. func (r *Redirect) Back(fallback ...string) error { - location := r.c.Get(HeaderReferer) + location := r.refererHeader() if location != "" { - if !strings.HasPrefix(location, "/") || strings.HasPrefix(location, "//") { - parsed, err := url.Parse(location) - if err != nil || (parsed.Scheme != "" && parsed.Host == "") || (parsed.Host != "" && !schemehost.Match(parsed.Scheme, parsed.Host, r.c.Scheme(), r.c.Host())) { - location = "" // Reject invalid or cross-origin referrers - } + // Reject invalid or cross-origin referrers, and redirect to the + // normalized form so every client resolves it the same way the + // same-origin check did. + normalized, ok := r.sameOriginReferer(location) + if !ok { + normalized = "" } + location = normalized } if location == "" { @@ -403,31 +435,138 @@ func (r *Redirect) Back(fallback ...string) error { return r.To(location) } -// parseAndClearFlashMessages is a method to get flash messages before they are getting removed -func (r *Redirect) parseAndClearFlashMessages() { - // parse flash messages - cookieValue, err := hex.DecodeString(r.c.Cookies(FlashCookieName)) - if err != nil { - return +// refererHeader returns the Referer, matching the field name the way a recipient +// must (RFC 9110 §5.1). Ctx.Get is byte-exact, so under DisableHeaderNormalizing +// a lower-case "referer:" read as absent and Back always took the fallback. +func (r *Redirect) refererHeader() string { + if v := r.c.Get(HeaderReferer); v != "" { + return v } + if !r.c.app.config.DisableHeaderNormalizing { + return "" + } + + return r.c.app.toString(fieldname.First(&r.c.fasthttp.Request.Header, HeaderReferer, false)) +} - _, err = r.c.flashMessages.UnmarshalMsg(cookieValue) +// sameOriginReferer reports whether the Referer resolves back to the origin now +// being served, returning the normalized form safe to echo. A browser's +// normalization decides that, not net/url: " //evil.com", "/\evil.com", "///x". +func (r *Redirect) sameOriginReferer(location string) (string, bool) { + // The normalized value is what gets redirected to, so a client that does + // not apply these rules itself cannot resolve a different origin than the + // one validated here. + location = normalizeRefererURL(location) + if location == "" { + return "", false + } + + // An absolute path stays on the current origin, but "//host" is a + // network-path reference that switches to another one. + if location[0] == '/' && !strings.HasPrefix(location, "//") { + return location, true + } + + parsed, err := url.Parse(location) if err != nil { - return + return "", false + } + if parsed.Host == "" { + // A scheme with no authority ("javascript:", "mailto:") is no same-origin + // reference; anything else is a relative path — except an empty authority + // ("//?x", "//#f", "//@"), which names no origin and resolves nowhere. + return location, parsed.Scheme == "" && !strings.HasPrefix(location, "//") + } + + return location, schemehost.Match(parsed.Scheme, parsed.Host, r.c.Scheme(), r.c.Host()) +} + +// normalizeRefererURL applies the parts of the WHATWG parser that decide which +// origin a Referer resolves to: strip surrounding C0 controls, drop tab and +// newline, fold backslashes, collapse a leading slash run to two. +func normalizeRefererURL(location string) string { + location = strings.TrimFunc(location, func(c rune) bool { return c <= ' ' }) + + var b []byte + inPath := true + for i := 0; i < len(location); i++ { + c := location[i] + switch { + case c == '\t' || c == '\n' || c == '\r': + if b == nil { + b = append(make([]byte, 0, len(location)), location[:i]...) + } + continue + case c == '?' || c == '#': + inPath = false + case c == '\\' && inPath: + if b == nil { + b = append(make([]byte, 0, len(location)), location[:i]...) + } + b = append(b, '/') + continue + } + if b != nil { + b = append(b, c) + } + } + if b != nil { + location = string(b) + } + + // "///evil.com" reaches the same authority state as "//evil.com", so keep + // at most the two slashes that introduce it. + if strings.HasPrefix(location, "//") { + n := 0 + for n < len(location) && location[n] == '/' { + n++ + } + if n == len(location) { + return "/" + } + location = location[n-2:] } + return location +} + +// parseAndClearFlashMessages is a method to get flash messages before they are getting removed +func (r *Redirect) parseAndClearFlashMessages() { + // UnmarshalMsg re-slices this capacity rather than allocating, and the + // generated decoder assigns only the fields the message carries — so an empty + // map keeps whatever the slot held, and the destination must arrive zeroed. + clear(r.c.flashMessages[:cap(r.c.flashMessages)]) + r.c.flashMessages = r.c.flashMessages[:0] + + // parse flash messages + if cookieValue, err := hex.DecodeString(r.c.Cookies(FlashCookieName)); err == nil { + if _, err := r.c.flashMessages.UnmarshalMsg(cookieValue); err != nil { + // UnmarshalMsg re-slices to the length the payload declared before + // it decodes any element, so a failure partway leaves the slice + // holding zero-valued entries. Drop them. + r.c.flashMessages = r.c.flashMessages[:0] + } + } + + // Expire the cookie whatever the payload turned out to be, including the + // hex-decode failure above. A value this application cannot decode it never + // will, so leaving it means re-running hex and msgp on every later request. r.c.Cookie(&Cookie{ - Name: FlashCookieName, - Value: "", - Path: "/", - MaxAge: -1, + Name: FlashCookieName, + Value: "", + Path: "/", + MaxAge: -1, + HTTPOnly: true, + Secure: r.c.Secure(), }) } -// processFlashMessages is a helper function to process flash messages and old input data -// and set them as cookies +// processFlashMessages sets the flash messages and old input data as cookies. +// +// The payload is hex-encoded, not signed, and WithInput copies the whole form +// into it — so the cookie is HTTPOnly, and Secure whenever the request was TLS. func (r *Redirect) processFlashMessages() { - if len(r.messages) == 0 { + if len(r.messages) == 0 || r.c.app.config.DisableFlashMessages { return } @@ -443,5 +582,7 @@ func (r *Redirect) processFlashMessages() { Name: FlashCookieName, Value: r.c.app.toString(dst), SessionOnly: true, + HTTPOnly: true, + Secure: r.c.Secure(), }) } diff --git a/src/vendor/github.com/gofiber/fiber/v3/req.go b/src/vendor/github.com/gofiber/fiber/v3/req.go index 870b1886..dceabbf0 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/req.go +++ b/src/vendor/github.com/gofiber/fiber/v3/req.go @@ -3,19 +3,23 @@ package fiber import ( "bytes" "errors" + "io" "math" "mime/multipart" "net" - "net/netip" - "strconv" "strings" + "time" "github.com/gofiber/utils/v2" - utilsbytes "github.com/gofiber/utils/v2/bytes" utilsstrings "github.com/gofiber/utils/v2/strings" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" "golang.org/x/net/idna" + + etagpkg "github.com/gofiber/fiber/v3/internal/etag" + "github.com/gofiber/fiber/v3/internal/fieldname" + "github.com/gofiber/fiber/v3/internal/headerlist" + "github.com/gofiber/fiber/v3/internal/mediatype" ) // Pre-allocated byte slices for common header comparisons to avoid allocations @@ -49,33 +53,44 @@ type DefaultReq struct { // Accepts checks if the specified extensions or content types are acceptable. func (r *DefaultReq) Accepts(offers ...string) string { - header := joinHeaderValues(r.c.fasthttp.Request.Header.PeekAll(HeaderAccept)) + header := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAccept) return getOffer(header, acceptsOfferType, offers...) } // AcceptsCharsets checks if the specified charset is acceptable. func (r *DefaultReq) AcceptsCharsets(offers ...string) string { - header := joinHeaderValues(r.c.fasthttp.Request.Header.PeekAll(HeaderAcceptCharset)) + header := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptCharset) return getOffer(header, acceptsOffer, offers...) } // AcceptsEncodings checks if the specified encoding is acceptable. +// +// Per RFC 9110 §12.5.3, a missing Accept-Encoding accepts any coding (the first +// offer wins), an empty one only "identity", and "identity" is acceptable unless +// the field excludes it with q=0. func (r *DefaultReq) AcceptsEncodings(offers ...string) string { - header := joinHeaderValues(r.c.fasthttp.Request.Header.PeekAll(HeaderAcceptEncoding)) - return getOffer(header, acceptsOffer, offers...) + header, present := lookupJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptEncoding) + if len(header) == 0 && len(offers) > 0 { + // Nothing to weigh, but an absent field and a present, empty one differ. + if !present { + return offers[0] + } + return identityOffer(offers) + } + return getEncodingOffer(header, offers) } // AcceptsLanguages checks if the specified language is acceptable using // RFC 4647 Basic Filtering. func (r *DefaultReq) AcceptsLanguages(offers ...string) string { - header := joinHeaderValues(r.c.fasthttp.Request.Header.PeekAll(HeaderAcceptLanguage)) + header := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptLanguage) return getOffer(header, acceptsLanguageOfferBasic, offers...) } // AcceptsLanguagesExtended checks if the specified language is acceptable using // RFC 4647 Extended Filtering. func (r *DefaultReq) AcceptsLanguagesExtended(offers ...string) string { - header := joinHeaderValues(r.c.fasthttp.Request.Header.PeekAll(HeaderAcceptLanguage)) + header := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptLanguage) return getOffer(header, acceptsLanguageOfferExtended, offers...) } @@ -135,7 +150,11 @@ func (r *DefaultReq) tryDecodeBodyInOrder( *originalBody = make([]byte, len(tempBody)) copy(*originalBody, tempBody) } - request.SetBodyRaw(body) + // identity leaves the body as it is; re-setting an aliasing slice would + // release its buffer under ReduceMemoryUsage. + if encoding != StrIdentity { + request.SetBodyRaw(body) + } } } @@ -157,20 +176,27 @@ func (r *DefaultReq) Body() []byte { request := &r.c.fasthttp.Request - // Get Content-Encoding header - headerEncoding = utils.UnsafeString(utilsbytes.UnsafeToLower(request.Header.ContentEncoding())) - - // If no encoding is provided, return the original body - if headerEncoding == "" { + // Fast path: no Content-Encoding header at all. ContentEncoding peeks the + // stored key byte-exactly, which is decisive only while fasthttp normalized + // the names on the way in — under DisableHeaderNormalizing a lower-case + // spelling would read as absent here and skip decompression entirely. + // An empty value is still a present field line and must be joined with + // duplicates below before RFC 9110 empty-list elements are ignored. + if !r.c.app.config.DisableHeaderNormalizing && request.Header.ContentEncoding() == nil { return r.getBody() } + // Multiple field lines form one list (RFC 9110 §5.2), so join before splitting. + // The result aliases the header storage, so fold into a new string; ToLower + // returns its input unchanged without an uppercase byte, so this stays free. + encodedBytes := peekJoinedRequestHeader(&request.Header, HeaderContentEncoding) + headerEncoding = utilsstrings.ToLower(utils.UnsafeString(encodedBytes)) + // Split and get the encodings list, in order to attend the // rule defined at: https://www.rfc-editor.org/rfc/rfc9110#section-8.4-5 - encodingOrder = getSplicedStrList(headerEncoding, encodingOrder) - for i := range encodingOrder { - encodingOrder[i] = utilsstrings.UnsafeToLower(encodingOrder[i]) - } + // The splitter drops empty list elements (RFC 9110 Section 5.6.1.2), and + // headerEncoding was already lowercased wholesale above. + encodingOrder = headerlist.Append(encodingOrder, headerEncoding) if len(encodingOrder) == 0 { return r.getBody() } @@ -199,6 +225,20 @@ func (r *DefaultReq) Body() []byte { return r.c.app.GetBytes(body) } +// BodyStream returns the request body as a stream, non-nil only when +// Config.StreamRequestBody is enabled and the body is not already buffered. +// Reading it consumes the body, so a later Body call will not see it. +func (r *DefaultReq) BodyStream() io.Reader { + return r.c.fasthttp.Request.BodyStream() +} + +// ContentLength returns the value of the Content-Length request header. A +// negative result is not a length: -1 is chunked and -2 is identity, which is +// what a bodyless GET reports. Use HasBody to test for a body at all. +func (r *DefaultReq) ContentLength() int { + return r.c.fasthttp.Request.Header.ContentLength() +} + // RequestCtx returns *fasthttp.RequestCtx that carries a deadline // a cancellation signal, and other values across API boundaries. func (r *DefaultReq) RequestCtx() *fasthttp.RequestCtx { @@ -206,46 +246,100 @@ func (r *DefaultReq) RequestCtx() *fasthttp.RequestCtx { } // FullURL returns the full request URL (protocol + host + original URL). -func (c *DefaultCtx) FullURL() string { +func (r *DefaultReq) FullURL() string { buf := bytebufferpool.Get() defer bytebufferpool.Put(buf) - buf.WriteString(c.Scheme()) + buf.WriteString(r.Scheme()) buf.WriteString("://") - buf.WriteString(c.Host()) - buf.WriteString(c.OriginalURL()) + buf.WriteString(r.Host()) + buf.WriteString(r.OriginalURL()) return buf.String() } // UserAgent returns the User-Agent request header. -func (c *DefaultCtx) UserAgent() string { - return c.app.toString(c.fasthttp.Request.Header.UserAgent()) +func (r *DefaultReq) UserAgent() string { + return r.c.app.toString(r.c.fasthttp.Request.Header.UserAgent()) } // Referer returns the Referer request header. -func (c *DefaultCtx) Referer() string { - return c.app.toString(c.fasthttp.Request.Header.Referer()) +func (r *DefaultReq) Referer() string { + return r.c.app.toString(r.c.fasthttp.Request.Header.Referer()) +} + +// Origin returns the Origin request header. +// Returned value is only valid within the handler. Do not store any references. +// Make copies or use the Immutable setting to use the value outside the Handler. +func (r *DefaultReq) Origin() string { + return r.c.app.toString(r.headerField(HeaderOrigin)) +} + +// headerField returns a request header's first non-empty field value, matching +// the field name case-insensitively (RFC 9110 Section 5.1). fieldname.First +// also steps over a present-but-empty first line, so a value on a later line +// is found and this agrees with GetAll on whether the field is there. +func (r *DefaultReq) headerField(name string) []byte { + return fieldname.First(&r.c.fasthttp.Request.Header, name, !r.c.app.config.DisableHeaderNormalizing) } // AcceptLanguage returns the Accept-Language request header. -func (c *DefaultCtx) AcceptLanguage() string { - return c.app.toString(c.fasthttp.Request.Header.Peek(HeaderAcceptLanguage)) +// Repeated field lines are combined into one comma-joined list (RFC 9110 +// Section 5.2) and the field name matches case-insensitively (Section 5.1), +// matching what AcceptsLanguages negotiates on. +func (r *DefaultReq) AcceptLanguage() string { + return r.c.app.toString(peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptLanguage)) } // AcceptEncoding returns the Accept-Encoding request header. -func (c *DefaultCtx) AcceptEncoding() string { - return c.app.toString(c.fasthttp.Request.Header.Peek(HeaderAcceptEncoding)) +// Repeated field lines are combined into one comma-joined list (RFC 9110 +// Section 5.2) and the field name matches case-insensitively (Section 5.1), +// matching what AcceptsEncodings negotiates on. +func (r *DefaultReq) AcceptEncoding() string { + return r.c.app.toString(peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAcceptEncoding)) } // HasHeader reports whether the request includes a header with the given key. -func (c *DefaultCtx) HasHeader(key string) bool { - return len(c.fasthttp.Request.Header.Peek(key)) > 0 +// The field name matches case-insensitively (RFC 9110 Section 5.1), so this +// agrees with GetAll on whether the field is there. +func (r *DefaultReq) HasHeader(key string) bool { + return len(r.headerField(key)) > 0 +} + +// HasHeaderValue reports whether the request header key lists value as one of +// its comma-separated members, on any of its field lines. Repeated field lines +// are one list (RFC 9110 Section 5.3) and the member matches under ASCII case +// folding, so it fits directive-style headers such as Cache-Control or +// Connection. A comma inside a quoted argument does not end a member, so +// `ext="a,no-transform,b"` is one member and does not list no-transform +// (RFC 9111 permits quoted directive arguments, escaped quotes included). An +// empty value is never present. Only valid within the handler. +func (r *DefaultReq) HasHeaderValue(key, value string) bool { + // One lookup settles the common case of a header that is not there at all. + if value == "" || len(r.headerField(key)) == 0 { + return false + } + app := r.c.app + for _, line := range fieldname.Lines(&r.c.fasthttp.Request.Header, key, !app.config.DisableHeaderNormalizing) { + for member := range headerlist.AllQuotedPairs(app.toString(line)) { + if utils.EqualFold(member, value) { + return true + } + } + } + return false +} + +// ContentType returns the Content-Type request header, parameters included; +// MediaType strips them and Charset returns just the charset. On Ctx the request +// wins over Res. Only valid within the handler unless Immutable is set. +func (r *DefaultReq) ContentType() string { + return r.c.app.toString(r.c.fasthttp.Request.Header.ContentType()) } // MediaType returns the MIME type from the Content-Type header without parameters. -func (c *DefaultCtx) MediaType() string { - contentType := utils.TrimSpace(c.fasthttp.Request.Header.ContentType()) +func (r *DefaultReq) MediaType() string { + contentType := utils.TrimSpace(r.c.fasthttp.Request.Header.ContentType()) if len(contentType) == 0 { return "" } @@ -253,87 +347,121 @@ func (c *DefaultCtx) MediaType() string { contentType = contentType[:idx] } contentType = utils.TrimSpace(contentType) - return c.app.toString(contentType) + return r.c.app.toString(contentType) } // Charset returns the charset parameter from the Content-Type header. -func (c *DefaultCtx) Charset() string { - contentType := c.fasthttp.Request.Header.ContentType() - if len(contentType) == 0 { - return "" - } - _, after, ok := bytes.Cut(contentType, []byte{';'}) +func (r *DefaultReq) Charset() string { + contentType := r.c.fasthttp.Request.Header.ContentType() + _, params, ok := utils.CutByte(contentType, ';') if !ok { return "" } - params := after for len(params) > 0 { - params = utils.TrimSpace(params) - if len(params) == 0 { - return "" - } + // Slice off the next parameter at the next ";" that sits outside a + // quoted-string: parameter values may be quoted and contain ";" + // (RFC 9110 Section 5.6.6). A DQUOTE only opens a quoted-string at + // the start of a value (after an "=" plus optional whitespace), so a + // stray quote later in an unquoted value cannot swallow the rest of + // the header. param := params - if idx := bytes.IndexByte(params, ';'); idx != -1 { - param = params[:idx] - params = params[idx+1:] + end := -1 + inQuotes := false + escaped := false + expectValue := false + scan: + for i := 0; i < len(params); i++ { + ch := params[i] + switch { + case escaped: + escaped = false + case inQuotes: + switch ch { + case '\\': + escaped = true + case '"': + inQuotes = false + } + case ch == '=': + expectValue = true + case ch == '"' && expectValue: + inQuotes = true + expectValue = false + case ch == ';': + end = i + break scan + case ch != ' ' && ch != '\t': + expectValue = false + } + } + if end >= 0 { + param = params[:end] + params = params[end+1:] } else { params = nil } - param = utils.TrimSpace(param) - if len(param) == 0 { + name, value, ok := utils.CutByte(param, '=') + if !ok || !utils.EqualFold(utils.TrimSpace(name), []byte("charset")) { continue } - before, after, ok := bytes.Cut(param, []byte{'='}) - if !ok { - continue - } - name := utils.TrimSpace(before) - if !bytes.EqualFold(name, []byte("charset")) { + v := utils.TrimSpace(value) + if len(v) > 0 && v[0] == '"' { + // A quoted value must be a complete quoted-string, and its + // quoted-pairs must be replaced with the escaped octet + // (RFC 9110 Section 5.6.4). + if len(v) < 2 || v[len(v)-1] != '"' { + return "" + } + unescaped, err := unescapeHeaderValue(v[1 : len(v)-1]) + if err != nil { + return "" + } + v = unescaped + } else if bytes.IndexByte(v, '"') >= 0 { + // A bare token must not contain DQUOTE; skip the invalid + // parameter instead of surfacing garbage, so a well-formed + // charset parameter later in the header can still be found. continue } - value := utils.TrimSpace(after) - if len(value) >= 2 && value[0] == '"' && value[len(value)-1] == '"' { - value = value[1 : len(value)-1] - } - return c.app.toString(value) + return r.c.app.toString(v) } return "" } // IsJSON reports whether the Content-Type header is JSON. -func (c *DefaultCtx) IsJSON() bool { - return utils.EqualFold(c.MediaType(), MIMEApplicationJSON) +func (r *DefaultReq) IsJSON() bool { + return utils.EqualFold(r.MediaType(), MIMEApplicationJSON) } // IsForm reports whether the Content-Type header is form-encoded. -func (c *DefaultCtx) IsForm() bool { - return utils.EqualFold(c.MediaType(), MIMEApplicationForm) +func (r *DefaultReq) IsForm() bool { + return utils.EqualFold(r.MediaType(), MIMEApplicationForm) } // IsMultipart reports whether the Content-Type header is multipart form data. -func (c *DefaultCtx) IsMultipart() bool { - return utils.EqualFold(c.MediaType(), MIMEMultipartForm) +func (r *DefaultReq) IsMultipart() bool { + return utils.EqualFold(r.MediaType(), MIMEMultipartForm) } // AcceptsJSON reports whether the Accept header allows JSON. -func (c *DefaultCtx) AcceptsJSON() bool { - return c.Accepts(MIMEApplicationJSON) != "" +func (r *DefaultReq) AcceptsJSON() bool { + return r.Accepts(MIMEApplicationJSON) != "" } // AcceptsHTML reports whether the Accept header allows HTML. -func (c *DefaultCtx) AcceptsHTML() bool { - return c.Accepts(MIMETextHTML) != "" +func (r *DefaultReq) AcceptsHTML() bool { + return r.Accepts(MIMETextHTML) != "" } // AcceptsXML reports whether the Accept header allows XML. -func (c *DefaultCtx) AcceptsXML() bool { - return c.Accepts(MIMEApplicationXML, MIMETextXML) != "" +func (r *DefaultReq) AcceptsXML() bool { + return r.Accepts(MIMEApplicationXML, MIMETextXML) != "" } // AcceptsEventStream reports whether the Accept header allows text/event-stream. -func (c *DefaultCtx) AcceptsEventStream() bool { - return c.Accepts(MIMETextEventStream) != "" +func (r *DefaultReq) AcceptsEventStream() bool { + return r.Accepts(MIMETextEventStream) != "" } // Cookies are used for getting a cookie value by key. @@ -345,6 +473,35 @@ func (r *DefaultReq) Cookies(key string, defaultValue ...string) string { return defaultString(r.c.app.toString(r.c.fasthttp.Request.Header.Cookie(key)), defaultValue) } +// CookieNames returns the request cookie names in header order, or nil when +// there are none. A repeated name appears once per occurrence, which is how the +// shadowing AllCookies collapses is detected. The strings are copies. +func (r *DefaultReq) CookieNames() []string { + var names []string + for key := range r.c.fasthttp.Request.Header.Cookies() { + names = append(names, string(key)) + } + return names +} + +// AllCookies returns the request cookies as a name/value map, or nil when there +// are none. A repeated name resolves to its first occurrence, as Cookies does, +// so a shadowed cookie cannot be validated in one and consumed in the other. +func (r *DefaultReq) AllCookies() map[string]string { + var cookies map[string]string + for key, value := range r.c.fasthttp.Request.Header.Cookies() { + name := string(key) + if _, seen := cookies[name]; seen { + continue + } + if cookies == nil { + cookies = make(map[string]string) + } + cookies[name] = string(value) + } + return cookies +} + // Request return the *fasthttp.Request object // This allows you to use all fasthttp request methods // https://godoc.org/github.com/valyala/fasthttp#Request @@ -370,7 +527,19 @@ func (r *DefaultReq) FormFile(key string) (*multipart.FileHeader, error) { // Make copies or use the Immutable setting instead. // When the request is a multipart form, it is parsed using the application's // BodyLimit so the configured limit is consistently enforced. +// +// On a form request this lowercases the case-insensitive parts of the request's +// own Content-Type, so a value obtained earlier from Get(HeaderContentType) — +// which aliases those bytes unless Immutable is set — can change during the +// call. Copy it first if you need it to outlive one. func (r *DefaultReq) FormValue(key string, defaultValue ...string) string { + // fasthttp locates the urlencoded body and multipart boundary + // case-sensitively, so a legal "Multipart/Form-Data" yielded nothing here. + // Guarded, because the fold rewrites the request's own bytes. + if mediatype.IsForm(r.c.fasthttp.Request.Header.ContentType()) { + mediatype.NormalizeRequestContentType(&r.c.fasthttp.Request.Header) + } + if r.c.IsMultipart() { // For multipart requests, parse the form using the application's BodyLimit. // fasthttp's FormValue would otherwise re-parse with its default 8 MiB limit, @@ -398,15 +567,34 @@ func (r *DefaultReq) FormValue(key string, defaultValue ...string) string { // Fresh returns true when the response is still “fresh” in the client's cache, // otherwise false is returned to indicate that the client cache is now stale // and the full response should be sent. +// Freshness only applies to GET and HEAD requests; for any other method false is +// returned, as RFC 9110 defines 304 Not Modified only for those methods and +// requires If-Modified-Since to be ignored otherwise. // When a client sends the Cache-Control: no-cache request header to indicate an end-to-end // reload request, this module will return false to make handling these requests transparent. // https://github.com/jshttp/fresh/blob/master/index.js#L33 func (r *DefaultReq) Fresh() bool { + // Freshness only applies to GET and HEAD requests: a 304 Not Modified + // response is defined for those methods only, and RFC 9110 Section 13.1.3 + // requires If-Modified-Since to be ignored for any other method. + // A negative methodInt means the method is not registered at all, so it + // cannot be GET or HEAD (and must not be used to index RequestMethods). + if r.c.methodInt < 0 { + return false + } + if method := r.c.app.method(r.c.methodInt); method != MethodGet && method != MethodHead { + return false + } + header := &r.c.fasthttp.Request.Header // fields - modifiedSince := header.Peek(HeaderIfModifiedSince) - noneMatch := header.Peek(HeaderIfNoneMatch) + // List-based fields may be split across multiple field lines, which are + // semantically one comma-joined list (RFC 9110 Section 5.2). Field names + // match case-insensitively, so the lower-case spellings HTTP/2 and 3 send + // are not read as an unconditional request. + modifiedSince := r.headerField(HeaderIfModifiedSince) + noneMatch := peekJoinedRequestHeader(header, HeaderIfNoneMatch) // unconditional request if len(modifiedSince) == 0 && len(noneMatch) == 0 { @@ -416,7 +604,7 @@ func (r *DefaultReq) Fresh() bool { // Always return stale when Cache-Control: no-cache // to support end-to-end reload requests // https://www.rfc-editor.org/rfc/rfc9111#section-5.2.1.4 - cacheControl := header.Peek(HeaderCacheControl) + cacheControl := peekJoinedRequestHeader(header, HeaderCacheControl) if len(cacheControl) > 0 && isNoCache(utils.UnsafeString(cacheControl)) { return false } @@ -445,7 +633,7 @@ func (r *DefaultReq) Fresh() bool { if len(lastModified) == 0 { return false } - lastModifiedTime, err := fasthttp.ParseHTTPDate(lastModified) + lastModifiedTime, err := parseHTTPDate(lastModified) if err != nil { return false } @@ -453,7 +641,7 @@ func (r *DefaultReq) Fresh() bool { // Last-Modified it was given. Identical, already-validated dates are // equal, so skip the second parse and comparison. if !bytes.Equal(lastModified, modifiedSince) { - modifiedSinceTime, err := fasthttp.ParseHTTPDate(modifiedSince) + modifiedSinceTime, err := parseHTTPDate(modifiedSince) if err != nil { return false } @@ -465,6 +653,46 @@ func (r *DefaultReq) Fresh() bool { return true } +// parseHTTPDate parses an HTTP-date field value. RFC 9110 Section 5.6.7 +// requires recipients to accept the obsolete RFC 850 and ANSI C asctime() +// formats in addition to the preferred IMF-fixdate; utils.ParseHTTPDate +// covers all three with net/http.ParseTime semantics, taking an +// allocation-free fast path for canonical IMF-fixdate input. Unlike +// net/http.ParseTime it also tolerates surrounding ASCII whitespace — +// deliberate here, matching RFC 9110 §5.5's exclusion of leading and +// trailing OWS from field values. +func parseHTTPDate(date []byte) (time.Time, error) { + t, err := utils.ParseHTTPDate(date) + if err != nil { + // Callers only nil-check the error; skip wrapping to avoid an + // allocation for every malformed client-supplied date. + return time.Time{}, err //nolint:wrapcheck // see above + } + return t, nil +} + +// IfNoneMatch returns the entity tags in the If-None-Match request header, +// verbatim and unvalidated; a comma inside a quoted opaque-tag does not split +// one. Fresh already compares them. Only valid within the handler. +func (r *DefaultReq) IfNoneMatch() []string { + header := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderIfNoneMatch) + if len(header) == 0 { + return nil + } + return etagpkg.Split(r.c.app.toString(header)) +} + +// IfModifiedSince returns the time carried by the If-Modified-Since request +// header, ErrHeaderNotFound when it is absent or empty, and a parse error when +// it is none of the HTTP-date formats RFC 9110 Section 5.6.7 requires. +func (r *DefaultReq) IfModifiedSince() (time.Time, error) { + value := r.headerField(HeaderIfModifiedSince) + if len(value) == 0 { + return time.Time{}, ErrHeaderNotFound + } + return parseHTTPDate(value) +} + // Get returns the HTTP request header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. @@ -478,13 +706,68 @@ func (r *DefaultReq) Get(key string, defaultValue ...string) string { // If the generic type cannot be matched to a supported type, the function // returns the default value (if provided) or the zero value of type V. func GetReqHeader[V GenericType](c Ctx, key string, defaultValue ...V) V { - v, err := genericParseType[V](c.App().toString(c.Request().Header.Peek(key))) + v, err := genericParseType[V](c.App().toString(c.Req().headerField(key))) if err != nil && len(defaultValue) > 0 { return defaultValue[0] } return v } +// GetAll returns every field line stored under key, where Get returns only the +// first, or nil when the header is absent. Empty lines are skipped, so its +// presence answers as HasHeader does. Only valid within the handler. +func (r *DefaultReq) GetAll(key string) []string { + app := r.c.app + lines := fieldname.Lines(&r.c.fasthttp.Request.Header, key, !app.config.DisableHeaderNormalizing) + + var values []string + for _, line := range lines { + if len(line) == 0 { + continue + } + values = append(values, app.toString(line)) + } + return values +} + +// Authorization splits the Authorization header into auth-scheme and credentials +// (RFC 9110 Section 11.6.2), neither decoded nor validated. They view the request +// buffer: a credential kept past the handler becomes another request's. +func (r *DefaultReq) Authorization() (scheme, credentials string) { //nolint:nonamedreturns // gocritic unnamedResult requires naming the two halves for clarity + rawScheme, rawCredentials := r.authorizationParts() + app := r.c.app + return app.toString(rawScheme), app.toString(rawCredentials) +} + +// authorizationParts splits the Authorization header at the first space or tab +// (RFC 9110 Section 11.4), on raw bytes so each caller materializes only the +// strings it needs. A lone token is a scheme without credentials. +func (r *DefaultReq) authorizationParts() (scheme, credentials []byte) { //nolint:nonamedreturns // the two halves need naming for clarity + raw := utils.TrimSpace(r.headerField(HeaderAuthorization)) + if len(raw) == 0 { + return nil, nil + } + i := utils.IndexAny2(raw, ' ', '\t') + if i < 0 { + return raw, nil + } + return raw[:i], utils.TrimSpace(raw[i+1:]) +} + +// Bearer returns the credentials of a Bearer Authorization header (RFC 6750 +// Section 2.1), unverified, or "" for another scheme. It views the request +// buffer: a token kept past the handler becomes another request's. +func (r *DefaultReq) Bearer() string { + // The scheme is compared on the raw bytes rather than through Authorization, + // so a header naming another scheme costs no string at all and a Bearer one + // materializes only the token. + scheme, credentials := r.authorizationParts() + if len(credentials) == 0 || !utils.EqualFold(utils.UnsafeString(scheme), "Bearer") { + return "" + } + return r.c.app.toString(credentials) +} + // GetHeaders (a.k.a GetReqHeaders) returns the HTTP request headers. // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting instead. @@ -510,7 +793,7 @@ func (r *DefaultReq) GetHeaders() map[string][]string { func (r *DefaultReq) Host() string { if r.IsProxyTrusted() { if host := r.Get(HeaderXForwardedHost); host != "" { - if before, _, found := strings.Cut(host, ","); found { + if before, _, found := utils.CutByte(host, ','); found { return utils.TrimSpace(before) } return utils.TrimSpace(host) @@ -538,13 +821,15 @@ func (r *DefaultReq) Port() string { } switch typedAddr := addr.(type) { case *net.TCPAddr: - return strconv.Itoa(typedAddr.Port) + return utils.FormatInt(int64(typedAddr.Port)) case *net.UnixAddr: return "" } - _, port, err := net.SplitHostPort(addr.String()) - if err != nil { + // utils.SplitHostPort applies net.SplitHostPort's rules but reports a + // miss as ok == false, so an address without a port costs no *net.AddrError. + _, port, ok := utils.SplitHostPort(addr.String()) + if !ok { return "" } @@ -552,10 +837,17 @@ func (r *DefaultReq) Port() string { } // IP returns the client's IP address. When the request comes from a trusted proxy (see -// [TrustProxyConfig]), the value is extracted from the configured ProxyHeader by walking the -// X-Forwarded-For chain right-to-left and skipping all trusted proxy IPs; the first -// non-trusted IP in the chain is returned. Please use Config.TrustProxy to prevent header -// spoofing if your app is behind a proxy. +// [TrustProxyConfig]) and Config.ProxyHeader is set, the value is taken from that header. +// With Config.EnableIPValidation enabled and proxy IPs or ranges configured (Proxies, +// Loopback, Private or LinkLocal), the X-Forwarded-For chain is walked right-to-left, every +// trusted proxy IP is skipped and the first non-trusted IP is returned; with validation +// enabled but only UnixSocket trusted, the first valid IP from the left is returned. With +// validation disabled (the default), the raw header value is returned as-is, which for +// X-Forwarded-For may be the whole comma-separated chain. Enable validation whenever the +// result is used as a single client identifier and the header can carry a chain, for example +// by the limiter middleware or an allowlist; a proxy that overwrites the header with one +// address, or a single-IP header, does not need it. Please use Config.TrustProxy to prevent +// header spoofing if your app is behind a proxy. func (r *DefaultReq) IP() string { app := r.c.app if r.IsProxyTrusted() && app.config.ProxyHeader != "" { @@ -573,7 +865,7 @@ func (r *DefaultReq) IP() string { func (r *DefaultReq) extractIPsFromHeader(header string) []string { // TODO: Reuse the c.extractIPFromHeader func somehow in here - headerValue := r.Get(header) + headerValue := proxyHeaderValue(r, header) // We can't know how many IPs we will return, but we will try to guess with this constant division. // Counting ',' makes function slower for about 50ns in general case. @@ -609,15 +901,16 @@ func (r *DefaultReq) extractIPsFromHeader(header string) []string { j++ } - for i < j && (headerValue[i] == ' ' || headerValue[i] == ',') { + for i < j && headerValue[i] == ',' { i++ } - s := utils.TrimRight(headerValue[i:j], ' ') + s := headerlist.TrimOWS(headerValue[i:j]) if r.c.app.config.EnableIPValidation { - // Skip validation if IP is clearly not IPv4/IPv6; otherwise, validate without allocations - if (!v6 && !v4) || (v6 && !utils.IsIPv6(s)) || (v4 && !utils.IsIPv4(s)) { + // Skip validation if IP is clearly not IPv4/IPv6; otherwise, validate without allocations. + // A colon decides: an IPv4-mapped IPv6 address carries both separators. + if (!v6 && !v4) || (v6 && !utils.IsIPv6(s)) || (!v6 && v4 && !utils.IsIPv4(s)) { continue } } @@ -637,10 +930,10 @@ func (r *DefaultReq) extractIPFromHeader(header string) string { app := r.c.app if !app.config.EnableIPValidation { - return r.Get(header) + return proxyHeaderValue(r, header) } - headerValue := r.Get(header) + headerValue := proxyHeaderValue(r, header) hasTrustedProxyConfig := r.hasTrustedProxyConfig() if !hasTrustedProxyConfig { start := 0 @@ -650,7 +943,7 @@ func (r *DefaultReq) extractIPFromHeader(header string) string { end++ } - ipStr := utils.Trim(headerValue[start:end], ' ') + ipStr := headerlist.TrimOWS(headerValue[start:end]) if isValidProxyIP(ipStr) { return ipStr } @@ -669,7 +962,7 @@ func (r *DefaultReq) extractIPFromHeader(header string) string { start-- } - ipStr := utils.Trim(headerValue[start:end], ' ') + ipStr := headerlist.TrimOWS(headerValue[start:end]) if isValidProxyIP(ipStr) { leftmostIP = ipStr if !r.isTrustedProxyIP(ipStr) { @@ -692,12 +985,20 @@ func (r *DefaultReq) extractIPFromHeader(header string) string { return "" } +// proxyHeaderValue combines repeated proxy header field lines as required by +// RFC 9110 Section 5.2. This ensures security-sensitive IP extraction sees the +// complete chain when an adapter or proxy preserves separate field lines. +func proxyHeaderValue(r *DefaultReq, header string) string { + value := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, header) + return r.c.app.toString(value) +} + func isValidProxyIP(ipStr string) bool { - hasIPv4Separator := strings.IndexByte(ipStr, '.') >= 0 - hasIPv6Separator := strings.IndexByte(ipStr, ':') >= 0 - return (hasIPv4Separator || hasIPv6Separator) && - (!hasIPv4Separator || utils.IsIPv4(ipStr)) && - (!hasIPv6Separator || utils.IsIPv6(ipStr)) + if strings.IndexByte(ipStr, ':') >= 0 { + // A colon makes it IPv6, including the IPv4-mapped form ::ffff:a.b.c.d (RFC 4291 §2.2). + return utils.IsIPv6(ipStr) + } + return strings.IndexByte(ipStr, '.') >= 0 && utils.IsIPv4(ipStr) } // hasTrustedProxyConfig returns true if any trusted proxy configuration is set. @@ -710,9 +1011,15 @@ func (r *DefaultReq) hasTrustedProxyConfig() bool { func (r *DefaultReq) isTrustedProxyIP(ipStr string) bool { cfg := r.c.app.config.TrustProxyConfig - ip, err := netip.ParseAddr(ipStr) - if err != nil { - return false + // utils.ParseIPv4/ParseIPv6 together accept exactly the strings + // netip.ParseAddr does, without allocating an error for invalid input. + ip, ok := utils.ParseIPv4(ipStr) + if !ok { + if ip, ok = utils.ParseIPv6(ipStr); !ok { + return false + } + // An IPv4-mapped address names an IPv4 proxy: look it up as that, as net.IP does for the peer. + ip = ip.Unmap() } if cfg.Loopback && ip.IsLoopback() { @@ -774,12 +1081,135 @@ func (r *DefaultReq) Is(extension string) bool { return utils.EqualFold(ct, extensionHeader) } +// HasBody returns true if the request declares a body via Content-Length, Transfer-Encoding, or already buffered payload data. +func (r *DefaultReq) HasBody() bool { + hdr := &r.c.fasthttp.Request.Header + + switch cl := hdr.ContentLength(); { + case cl > 0: + return true + case cl == -1: + // fasthttp reports -1 for Transfer-Encoding: chunked bodies. + return true + case cl == 0: + if hasTransferEncodingBody(hdr) { + return true + } + } + + return len(r.c.fasthttp.Request.Body()) > 0 +} + +func hasTransferEncodingBody(hdr *fasthttp.RequestHeader) bool { + // Repeated field lines form one combined list (RFC 9110 Section 5.2), + // so every Transfer-Encoding line must be inspected, not just the first. + if lines := hdr.PeekAll(HeaderTransferEncoding); len(lines) > 0 { + for _, line := range lines { + if transferEncodingLineHasBody(utils.UnsafeString(line)) { + return true + } + } + return false + } + + // Fallback scan for non-normalized header keys. + for key, value := range hdr.All() { + if !utils.EqualFold(utils.UnsafeString(key), HeaderTransferEncoding) { + continue + } + if transferEncodingLineHasBody(utils.UnsafeString(value)) { + return true + } + } + + return false +} + +// transferEncodingLineHasBody reports whether a single Transfer-Encoding +// field line contains a transfer coding other than "identity". +func transferEncodingLineHasBody(te string) bool { + for token := range headerlist.All(te) { + // A transfer coding may carry parameters ("chunked;q=1"), which name the + // coding no more than the bare token does (RFC 9110 Section 10.1.4). + if idx := strings.IndexByte(token, ';'); idx >= 0 { + token = utils.TrimSpace(token[:idx]) + } + if token == "" || utils.EqualFold(token, "identity") { + continue + } + return true + } + return false +} + +// IsWebSocket returns true if the request includes a WebSocket upgrade handshake. +func (r *DefaultReq) IsWebSocket() bool { + // Repeated field lines are equivalent to one combined comma-separated + // list (RFC 9110 Section 5.2), so inspect every Connection and Upgrade + // field line, not just the first. + hdr := &r.c.fasthttp.Request.Header + canonical := !r.c.app.config.DisableHeaderNormalizing + if !headerListContainsToken(fieldname.Lines(hdr, HeaderConnection, canonical), "upgrade") { + return false + } + // Upgrade is a list of protocols, each optionally carrying a "/version" + // suffix (RFC 9110 Section 7.8), e.g. "Upgrade: websocket, h2c". + return headerListContainsToken(fieldname.Lines(hdr, HeaderUpgrade, canonical), "websocket") +} + +// headerListContainsToken reports whether any comma-separated element across +// the given field lines equals token case-insensitively. An optional +// "/version" suffix (Upgrade protocol syntax, RFC 9110 Section 7.8) is +// ignored when comparing; valid Connection members never contain "/", so +// this is safe for both headers. +func headerListContainsToken(lines [][]byte, token string) bool { + for element := range headerlist.AllLines(lines) { + // Connection and Upgrade carry protocol names, which may name a version + // after a slash ("HTTP/2.0"). Match on the name alone. + if i := strings.IndexByte(element, '/'); i >= 0 { + element = element[:i] + } + if utils.EqualFold(element, token) { + return true + } + } + return false +} + +// IsPreflight returns true if the request is a CORS preflight. +func (r *DefaultReq) IsPreflight() bool { + if r.Method() != MethodOptions { + return false + } + if len(r.headerField(HeaderAccessControlRequestMethod)) == 0 { + return false + } + return len(r.headerField(HeaderOrigin)) > 0 +} + +// Secure returns whether a secure connection was established. +func (r *DefaultReq) Secure() bool { + return r.Scheme() == schemeHTTPS +} + +// xmlHTTPRequestBytes is precomputed for XHR detection +var xmlHTTPRequestBytes = []byte("xmlhttprequest") + +// XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, +// indicating that the request was issued by a client library (such as jQuery). +func (r *DefaultReq) XHR() bool { + return utils.EqualFold(r.headerField(HeaderXRequestedWith), xmlHTTPRequestBytes) +} + // Locals makes it possible to pass any values under keys scoped to the request // and therefore available to all following routes that match the request. // // All the values are removed from ctx after returning from the top // RequestHandler. Additionally, Close method is called on each value // implementing io.Closer before removing the value from ctx. +// +// Storing through the Ctx interface heap-allocates the one-element slice the +// variadic value is packed into; SetLocal stores the same value without it. func (r *DefaultReq) Locals(key any, value ...any) any { if r.c.fasthttp == nil { if len(value) > 0 { @@ -794,6 +1224,34 @@ func (r *DefaultReq) Locals(key any, value ...any) any { return value[0] } +// SetLocal stores value under key scoped to the request, exactly as +// Locals(key, value) does: the value is available to all following routes that +// match the request, removed after the top RequestHandler returns, and its +// Close method is called first if it implements io.Closer. Like Locals, it +// stores nothing while the context is released. A Ctx must not be used past +// its handler either way, because the pool hands the same one to the next +// request. +// +// Locals takes its value variadically, and reached through the Ctx interface +// the compiler cannot see that the callee only reads that argument, so the +// one-element "..." slice is heap-allocated on every call. SetLocal takes the +// value directly, so that slice is never built. Boxing a value that is not +// already an interface still allocates, exactly as it does for Locals. +func (r *DefaultReq) SetLocal(key, value any) { + c := r.c + if c.fasthttp == nil { + return + } + // A custom Ctx is entitled to override Locals, and this stores what + // Locals(key, value) stores, so the override is the one that must run. + // It pays the slice the default path exists to avoid, as setLocal does. + if handlerCtx := c.handlerCtx; handlerCtx != nil { + handlerCtx.Locals(key, value) + return + } + c.fasthttp.SetUserValue(key, value) +} + // Locals function utilizing Go's generics feature. // This function allows for manipulating and retrieving local values within a // request context with a more specific data type. @@ -807,7 +1265,9 @@ func Locals[V any](c Ctx, key any, value ...V) V { if len(value) == 0 { v, ok = c.Locals(key).(V) } else { - v, ok = c.Locals(key, value[0]).(V) + // Set through setLocal so the store does not pay for the + // heap-allocated one-element slice an interface Locals call costs. + v, ok = setLocal(c, key, value[0]).(V) } if !ok { return v // return zero of type V @@ -822,22 +1282,83 @@ func (r *DefaultReq) Method(override ...string) string { app := r.c.app if len(override) == 0 { // Nothing to override, just return current method from context - return app.method(r.c.methodInt) + return currentMethod(r.c) } - method := utilsstrings.ToUpper(override[0]) + // Method tokens are case-sensitive (RFC 9110 Section 9.1), so try the + // override exactly as given first — this is what keeps mixed-case custom + // methods registered via Config.RequestMethods working. + method := override[0] methodInt := app.methodInt(method) if methodInt == -1 { - // Provided override does not valid HTTP method, no override, return current method - return app.method(r.c.methodInt) + // Fall back to the conventional uppercase form as a convenience for + // the standard methods (e.g. "get" -> "GET"). + method = utilsstrings.ToUpper(method) + methodInt = app.methodInt(method) } + if methodInt == -1 { + // Provided override is not a registered HTTP method; no override, + // return current method + return currentMethod(r.c) + } + if methodInt == r.c.methodInt { + return method + } + // A middleware sits at a position of its own in every method's tree, so + // carry the index over or Next would skip the routes before it. + r.c.indexRoute = app.routeIndexInTree(methodInt, r.c.treePathHash, r.c.route, r.c.indexRoute) r.c.methodInt = methodInt + // Method changed; invalidate the lookahead index + r.c.firstMatchIndex = -1 return method } +// currentMethod resolves the context's method, falling back to the raw +// request header value when the method is not registered in RequestMethods, +// so unregistered methods are reported instead of panicking. +// It is a package-level function (not a method) to stay off the generated +// Req/Ctx interfaces. +func currentMethod(c *DefaultCtx) string { + // app.method owns the definition of "unregistered" (it bounds-checks + // methodInt and returns "" for anything out of range). + if m := c.app.method(c.methodInt); m != "" { + return m + } + // Copy the raw header bytes: every other return path yields a stable + // string from RequestMethods, so callers may retain the result beyond + // the handler; an unsafe alias into the request buffer would be + // silently corrupted on connection reuse. + return string(c.fasthttp.Request.Header.Method()) +} + +// IsSafe reports whether the request method is safe, meaning it is not expected +// to change server state (RFC 9110 Section 9.2.1). +func (r *DefaultReq) IsSafe() bool { + return IsMethodSafe(r.Method()) +} + +// IsIdempotent reports whether the request method is idempotent, meaning +// repeating it has the same intended effect as making it once (RFC 9110 +// Section 9.2.2). Every safe method is also idempotent. +func (r *DefaultReq) IsIdempotent() bool { + return IsMethodIdempotent(r.Method()) +} + // MultipartForm parse form entries from binary. // This returns a map[string][]string, so given a key, the value will be a string slice. +// +// On a form request this lowercases the case-insensitive parts of the request's +// own Content-Type, so a value obtained earlier from Get(HeaderContentType) — +// which aliases those bytes unless Immutable is set — can change during the +// call. Copy it first if you need it to outlive one. func (r *DefaultReq) MultipartForm() (*multipart.Form, error) { + // fasthttp matches both "multipart/form-data" and the "boundary=" parameter + // name case-sensitively, so fold first. FormFile and SaveFile come through + // here too. Guarded like FormValue: the fold writes. + if mediatype.IsForm(r.c.fasthttp.Request.Header.ContentType()) { + mediatype.NormalizeRequestContentType(&r.c.fasthttp.Request.Header) + } + return r.c.fasthttp.MultipartFormWithLimit(r.c.app.config.BodyLimit) } @@ -848,6 +1369,38 @@ func (r *DefaultReq) OriginalURL() string { return r.c.app.toString(r.c.fasthttp.Request.Header.RequestURI()) } +// URI returns the parsed *fasthttp.URI of the request, giving access to all +// fasthttp URI methods. It is owned by the request and rewritten by a Path +// override, so it is only valid within the handler. +func (r *DefaultReq) URI() *fasthttp.URI { + return r.c.fasthttp.Request.URI() +} + +// Path returns the path part of the request URL, normalized before routing +// (see Config.UnescapePath); OriginalURL returns the request target as sent. +// Optionally, you could override the path. +// Make copies or use the Immutable setting to use the value outside the Handler. +func (r *DefaultReq) Path(override ...string) string { + if len(override) != 0 && string(r.c.path) != override[0] { + // Set new path to context + r.c.pathOriginal = override[0] + + // Set new path to request context + r.c.fasthttp.Request.URI().SetPath(r.c.pathOriginal) + // An override is off the request hot path, so scan the new path rather + // than repeat the length comparison Reset makes. + r.c.pathNeedsNorm = needsPathNormalization(r.c.pathOriginal) + // Prettify path + r.c.configDependentPaths() + // The detection path/tree hash changed; invalidate the lookahead index. + r.c.firstMatchIndex = -1 + // The new path may live in another bucket, so carry the index over for + // Next to resume after this route. + r.c.indexRoute = r.c.app.routeIndexInTree(r.c.methodInt, r.c.treePathHash, r.c.route, r.c.indexRoute) + } + return r.c.app.toString(r.c.path) +} + // Params is used to get the route parameters. // Defaults to empty string "" if the param doesn't exist. // If a default value is given, it will return that value if the param doesn't exist. @@ -923,22 +1476,40 @@ func (r *DefaultReq) Scheme() string { if utils.EqualFold(key, xForwardedProtoBytes) || utils.EqualFold(key, xForwardedProtocolBytes) { v := app.toString(val) - if before, _, found := strings.Cut(v, ","); found { - scheme = utils.TrimSpace(before) - } else { - scheme = utils.TrimSpace(v) + if before, _, found := utils.CutByte(v, ','); found { + v = before + } + if forwarded, ok := forwardedScheme(v); ok { + scheme = forwarded } } else if utils.EqualFold(key, xForwardedSslBytes) && utils.EqualFold(val, onBytes) { scheme = schemeHTTPS } case utils.EqualFold(key, xURLSchemeBytes): - scheme = utils.TrimSpace(app.toString(val)) + if forwarded, ok := forwardedScheme(app.toString(val)); ok { + scheme = forwarded + } default: continue } } - return utilsstrings.ToLower(utils.TrimSpace(scheme)) + return scheme +} + +// forwardedScheme canonicalizes a scheme announced by a proxy header. Only +// "http" and "https": the value is spliced into a URL (BaseURL) and compared for +// origin equality (CSRF, Redirect.Back). Rejecting leaves the prior scheme. +func forwardedScheme(value string) (string, bool) { + value = utils.TrimSpace(value) + switch { + case utils.EqualFold(value, schemeHTTPS): + return schemeHTTPS, true + case utils.EqualFold(value, schemeHTTP): + return schemeHTTP, true + default: + return "", false + } } // Protocol returns the HTTP protocol of request: HTTP/1.1 and HTTP/2. @@ -1031,13 +1602,13 @@ func (r *DefaultReq) Range(size int64) (Range, error) { rangeData.Ranges = make([]RangeSet, 0, prealloc) } + // parseBound parses a present (non-empty) range bound. A bound that is + // not a valid integer makes the range-spec, and therefore the whole + // ranges-specifier, invalid (RFC 9110 Section 14.1.1). parseBound := func(value string) (int64, error) { - if value == "" { // empty bound (suffix/prefix range); skip the parser's error alloc - return 0, errRangeBound - } parsed, err := utils.ParseUint(value) if err != nil { - return 0, errRangeBound // sentinel: never surfaced, avoids per-request alloc + return 0, ErrRangeMalformed } if parsed > (math.MaxUint64 >> 1) { return 0, ErrRangeMalformed @@ -1045,28 +1616,40 @@ func (r *DefaultReq) Range(size int64) (Range, error) { return int64(parsed), nil } - before, after, found := strings.Cut(rangeStr, "=") - if !found || strings.IndexByte(after, '=') >= 0 { - return rangeData, ErrRangeMalformed + before, after, found := utils.CutByte(rangeStr, '=') + if !found { + return Range{}, ErrRangeMalformed } - rangeData.Type = utilsstrings.ToLower(utils.TrimSpace(before)) - if rangeData.Type != "bytes" { - return rangeData, ErrRangeMalformed + if !utils.EqualFold(utils.TrimSpace(before), "bytes") { + // A range unit the server does not understand is not malformed: it + // must be ignored (RFC 9110 Section 14.2), which only the caller can + // do, so signal it distinctly. This check runs before any syntax + // checks on the range-set, since the other-range grammar permits + // characters (such as "=") that byte ranges do not. + return Range{}, ErrRangeUnsupported + } + rangeData.Type = "bytes" + if strings.IndexByte(after, '=') >= 0 { + return Range{}, ErrRangeMalformed } ranges = utils.TrimSpace(after) var ( - singleRange string - moreRanges = ranges - rangeCount int + singleRange string + moreRanges = ranges + elementCount int // every list element, including empty ones (MaxRanges bound) + sawRangeSpec bool // at least one non-empty range-spec was present ) for moreRanges != "" { - rangeCount++ - if rangeCount > maxRanges { + // Empty elements count toward MaxRanges too, so the cap bounds the + // total parsing work per header, not just the accepted range-specs. + elementCount++ + if elementCount > maxRanges { r.c.DefaultRes.Status(StatusRequestedRangeNotSatisfiable) r.c.DefaultRes.Set(HeaderContentRange, "bytes */"+utils.FormatInt(size)) //nolint:staticcheck // It is fine to ignore the static check - return rangeData, ErrRangeTooLarge + return Range{}, ErrRangeTooLarge } + singleRange = moreRanges if i := strings.IndexByte(moreRanges, ','); i >= 0 { singleRange = moreRanges[:i] @@ -1077,31 +1660,62 @@ func (r *DefaultReq) Range(size int64) (Range, error) { singleRange = utils.TrimSpace(singleRange) + // RFC 9110 Section 5.6.1.2: recipients must parse and ignore a + // reasonable number of empty list elements, e.g. "bytes=,0-5" is + // equivalent to "bytes=0-5". + if singleRange == "" { + continue + } + sawRangeSpec = true + var ( startStr, endStr string i int ) if i = strings.IndexByte(singleRange, '-'); i == -1 { - return rangeData, ErrRangeMalformed + return Range{}, ErrRangeMalformed } startStr = utils.TrimSpace(singleRange[:i]) endStr = utils.TrimSpace(singleRange[i+1:]) - start, startErr := parseBound(startStr) - end, endErr := parseBound(endStr) - if errors.Is(startErr, ErrRangeMalformed) || errors.Is(endErr, ErrRangeMalformed) { - return rangeData, ErrRangeMalformed + var ( + start, end int64 + err error + ) + if startStr != "" { + if start, err = parseBound(startStr); err != nil { + return Range{}, err + } } - if startErr != nil { // -nnn + if endStr != "" { + if end, err = parseBound(endStr); err != nil { + return Range{}, err + } + } + switch { + case startStr == "" && endStr == "": + // "-" carries neither a first-byte-pos nor a suffix-length and is + // not a valid range-spec (RFC 9110 Section 14.1.1). + return Range{}, ErrRangeMalformed + case startStr == "": // -nnn (suffix range) start = max(size-end, 0) end = size - 1 - } else if endErr != nil { // nnn- - end = size - 1 - } - if end > size-1 { // limit last-byte-pos to current length + case endStr == "": // nnn- (open-ended range) end = size - 1 + default: // nnn-mmm + // An int-range with a last-byte-pos less than its first-byte-pos + // invalidates the whole ranges-specifier (RFC 9110 Section 14.1.1). + if end < start { + return Range{}, ErrRangeMalformed + } + if end > size-1 { // limit last-byte-pos to current length + end = size - 1 + } } - if start > end || start < 0 { + if start > end { + // Syntactically valid but does not overlap the representation + // (e.g. first-byte-pos beyond EOF or a zero-length suffix); skip + // it and let the satisfiability check below decide. continue } rangeData.Ranges = append(rangeData.Ranges, RangeSet{ @@ -1110,6 +1724,11 @@ func (r *DefaultReq) Range(size int64) (Range, error) { }) } if len(rangeData.Ranges) < 1 { + if !sawRangeSpec { + // Only empty list elements: there was no range-spec at all, so + // the ranges-specifier is invalid rather than unsatisfiable. + return Range{}, ErrRangeMalformed + } r.c.DefaultRes.Status(StatusRequestedRangeNotSatisfiable) r.c.DefaultRes.Set(HeaderContentRange, "bytes */"+utils.FormatInt(size)) //nolint:staticcheck // It is fine to ignore the static check return rangeData, ErrRequestedRangeNotSatisfiable @@ -1118,6 +1737,11 @@ func (r *DefaultReq) Range(size int64) (Range, error) { return rangeData, nil } +// Endpoint returns the route that will handle this request. See Ctx.Endpoint. +func (r *DefaultReq) Endpoint() *Route { + return r.c.Endpoint() +} + // Route returns the matched Route struct. func (r *DefaultReq) Route() *Route { return r.c.Route() @@ -1198,7 +1822,9 @@ func (r *DefaultReq) Stale() bool { // If Config.TrustProxy false, it returns false. // IsProxyTrusted can check remote ip by proxy ranges and ip map. func (r *DefaultReq) IsProxyTrusted() bool { - config := r.c.app.config + // By pointer: Config is over 600 bytes, and copying it to read one bool cost + // more than the rest of this function on every IP, Scheme, Host and BaseURL. + config := &r.c.app.config if !config.TrustProxy { return false } @@ -1225,8 +1851,12 @@ func (r *DefaultReq) IsProxyTrusted() bool { return true } - if _, trusted := config.TrustProxyConfig.ips[ip.String()]; trusted { - return true + // Only stringify the IP when there is an exact-match map to look it up in; + // ip.String() heap-allocates and is wasted work for CIDR-only configs. + if len(config.TrustProxyConfig.ips) > 0 { + if _, trusted := config.TrustProxyConfig.ips[ip.String()]; trusted { + return true + } } for _, ipNet := range config.TrustProxyConfig.ranges { diff --git a/src/vendor/github.com/gofiber/fiber/v3/req_interface_gen.go b/src/vendor/github.com/gofiber/fiber/v3/req_interface_gen.go index fba9b6df..a5b5f354 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/req_interface_gen.go +++ b/src/vendor/github.com/gofiber/fiber/v3/req_interface_gen.go @@ -3,7 +3,9 @@ package fiber import ( + "io" "mime/multipart" + "time" "github.com/valyala/fasthttp" ) @@ -15,6 +17,10 @@ type Req interface { // AcceptsCharsets checks if the specified charset is acceptable. AcceptsCharsets(offers ...string) string // AcceptsEncodings checks if the specified encoding is acceptable. + // + // Per RFC 9110 §12.5.3, a missing Accept-Encoding accepts any coding (the first + // offer wins), an empty one only "identity", and "identity" is acceptable unless + // the field excludes it with q=0. AcceptsEncodings(offers ...string) string // AcceptsLanguages checks if the specified language is acceptable using // RFC 4647 Basic Filtering. @@ -38,15 +44,91 @@ type Req interface { // Don't store direct references to the returned data. // If you need to keep the body's data later, make a copy or use the Immutable option. Body() []byte + // BodyStream returns the request body as a stream, non-nil only when + // Config.StreamRequestBody is enabled and the body is not already buffered. + // Reading it consumes the body, so a later Body call will not see it. + BodyStream() io.Reader + // ContentLength returns the value of the Content-Length request header. A + // negative result is not a length: -1 is chunked and -2 is identity, which is + // what a bodyless GET reports. Use HasBody to test for a body at all. + ContentLength() int // RequestCtx returns *fasthttp.RequestCtx that carries a deadline // a cancellation signal, and other values across API boundaries. RequestCtx() *fasthttp.RequestCtx + // FullURL returns the full request URL (protocol + host + original URL). + FullURL() string + // UserAgent returns the User-Agent request header. + UserAgent() string + // Referer returns the Referer request header. + Referer() string + // Origin returns the Origin request header. + // Returned value is only valid within the handler. Do not store any references. + // Make copies or use the Immutable setting to use the value outside the Handler. + Origin() string + // headerField returns a request header's first non-empty field value, matching + // the field name case-insensitively (RFC 9110 Section 5.1). fieldname.First + // also steps over a present-but-empty first line, so a value on a later line + // is found and this agrees with GetAll on whether the field is there. + headerField(name string) []byte + // AcceptLanguage returns the Accept-Language request header. + // Repeated field lines are combined into one comma-joined list (RFC 9110 + // Section 5.2) and the field name matches case-insensitively (Section 5.1), + // matching what AcceptsLanguages negotiates on. + AcceptLanguage() string + // AcceptEncoding returns the Accept-Encoding request header. + // Repeated field lines are combined into one comma-joined list (RFC 9110 + // Section 5.2) and the field name matches case-insensitively (Section 5.1), + // matching what AcceptsEncodings negotiates on. + AcceptEncoding() string + // HasHeader reports whether the request includes a header with the given key. + // The field name matches case-insensitively (RFC 9110 Section 5.1), so this + // agrees with GetAll on whether the field is there. + HasHeader(key string) bool + // HasHeaderValue reports whether the request header key lists value as one of + // its comma-separated members, on any of its field lines. Repeated field lines + // are one list (RFC 9110 Section 5.3) and the member matches under ASCII case + // folding, so it fits directive-style headers such as Cache-Control or + // Connection. A comma inside a quoted argument does not end a member, so + // `ext="a,no-transform,b"` is one member and does not list no-transform + // (RFC 9111 permits quoted directive arguments, escaped quotes included). An + // empty value is never present. Only valid within the handler. + HasHeaderValue(key, value string) bool + // ContentType returns the Content-Type request header, parameters included; + // MediaType strips them and Charset returns just the charset. On Ctx the request + // wins over Res. Only valid within the handler unless Immutable is set. + ContentType() string + // MediaType returns the MIME type from the Content-Type header without parameters. + MediaType() string + // Charset returns the charset parameter from the Content-Type header. + Charset() string + // IsJSON reports whether the Content-Type header is JSON. + IsJSON() bool + // IsForm reports whether the Content-Type header is form-encoded. + IsForm() bool + // IsMultipart reports whether the Content-Type header is multipart form data. + IsMultipart() bool + // AcceptsJSON reports whether the Accept header allows JSON. + AcceptsJSON() bool + // AcceptsHTML reports whether the Accept header allows HTML. + AcceptsHTML() bool + // AcceptsXML reports whether the Accept header allows XML. + AcceptsXML() bool + // AcceptsEventStream reports whether the Accept header allows text/event-stream. + AcceptsEventStream() bool // Cookies are used for getting a cookie value by key. // Defaults to the empty string "" if the cookie doesn't exist. // If a default value is given, it will return that value if the cookie doesn't exist. // The returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting to use the value outside the Handler. Cookies(key string, defaultValue ...string) string + // CookieNames returns the request cookie names in header order, or nil when + // there are none. A repeated name appears once per occurrence, which is how the + // shadowing AllCookies collapses is detected. The strings are copies. + CookieNames() []string + // AllCookies returns the request cookies as a name/value map, or nil when there + // are none. A repeated name resolves to its first occurrence, as Cookies does, + // so a shadowed cookie cannot be validated in one and consumed in the other. + AllCookies() map[string]string // Request return the *fasthttp.Request object // This allows you to use all fasthttp request methods // https://godoc.org/github.com/valyala/fasthttp#Request @@ -63,19 +145,51 @@ type Req interface { // Make copies or use the Immutable setting instead. // When the request is a multipart form, it is parsed using the application's // BodyLimit so the configured limit is consistently enforced. + // + // On a form request this lowercases the case-insensitive parts of the request's + // own Content-Type, so a value obtained earlier from Get(HeaderContentType) — + // which aliases those bytes unless Immutable is set — can change during the + // call. Copy it first if you need it to outlive one. FormValue(key string, defaultValue ...string) string // Fresh returns true when the response is still “fresh” in the client's cache, // otherwise false is returned to indicate that the client cache is now stale // and the full response should be sent. + // Freshness only applies to GET and HEAD requests; for any other method false is + // returned, as RFC 9110 defines 304 Not Modified only for those methods and + // requires If-Modified-Since to be ignored otherwise. // When a client sends the Cache-Control: no-cache request header to indicate an end-to-end // reload request, this module will return false to make handling these requests transparent. // https://github.com/jshttp/fresh/blob/master/index.js#L33 Fresh() bool + // IfNoneMatch returns the entity tags in the If-None-Match request header, + // verbatim and unvalidated; a comma inside a quoted opaque-tag does not split + // one. Fresh already compares them. Only valid within the handler. + IfNoneMatch() []string + // IfModifiedSince returns the time carried by the If-Modified-Since request + // header, ErrHeaderNotFound when it is absent or empty, and a parse error when + // it is none of the HTTP-date formats RFC 9110 Section 5.6.7 requires. + IfModifiedSince() (time.Time, error) // Get returns the HTTP request header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting instead. Get(key string, defaultValue ...string) string + // GetAll returns every field line stored under key, where Get returns only the + // first, or nil when the header is absent. Empty lines are skipped, so its + // presence answers as HasHeader does. Only valid within the handler. + GetAll(key string) []string + // Authorization splits the Authorization header into auth-scheme and credentials + // (RFC 9110 Section 11.6.2), neither decoded nor validated. They view the request + // buffer: a credential kept past the handler becomes another request's. + Authorization() (scheme, credentials string) + // authorizationParts splits the Authorization header at the first space or tab + // (RFC 9110 Section 11.4), on raw bytes so each caller materializes only the + // strings it needs. A lone token is a scheme without credentials. + authorizationParts() (scheme, credentials []byte) + // Bearer returns the credentials of a Bearer Authorization header (RFC 6750 + // Section 2.1), unverified, or "" for another scheme. It views the request + // buffer: a token kept past the handler becomes another request's. + Bearer() string // GetHeaders (a.k.a GetReqHeaders) returns the HTTP request headers. // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting instead. @@ -97,10 +211,17 @@ type Req interface { // Port returns the remote port of the request. Port() string // IP returns the client's IP address. When the request comes from a trusted proxy (see - // [TrustProxyConfig]), the value is extracted from the configured ProxyHeader by walking the - // X-Forwarded-For chain right-to-left and skipping all trusted proxy IPs; the first - // non-trusted IP in the chain is returned. Please use Config.TrustProxy to prevent header - // spoofing if your app is behind a proxy. + // [TrustProxyConfig]) and Config.ProxyHeader is set, the value is taken from that header. + // With Config.EnableIPValidation enabled and proxy IPs or ranges configured (Proxies, + // Loopback, Private or LinkLocal), the X-Forwarded-For chain is walked right-to-left, every + // trusted proxy IP is skipped and the first non-trusted IP is returned; with validation + // enabled but only UnixSocket trusted, the first valid IP from the left is returned. With + // validation disabled (the default), the raw header value is returned as-is, which for + // X-Forwarded-For may be the whole comma-separated chain. Enable validation whenever the + // result is used as a single client identifier and the header can carry a chain, for example + // by the limiter middleware or an allowlist; a proxy that overwrites the header with one + // address, or a single-IP header, does not need it. Please use Config.TrustProxy to prevent + // header spoofing if your app is behind a proxy. IP() string // extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. // When IP validation is enabled, any invalid IPs will be omitted. @@ -121,24 +242,73 @@ type Req interface { // Is returns the matching content type, // if the incoming request's Content-Type HTTP header field matches the MIME type specified by the type parameter Is(extension string) bool + // HasBody returns true if the request declares a body via Content-Length, Transfer-Encoding, or already buffered payload data. + HasBody() bool + // IsWebSocket returns true if the request includes a WebSocket upgrade handshake. + IsWebSocket() bool + // IsPreflight returns true if the request is a CORS preflight. + IsPreflight() bool + // Secure returns whether a secure connection was established. + Secure() bool + // XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest, + // indicating that the request was issued by a client library (such as jQuery). + XHR() bool // Locals makes it possible to pass any values under keys scoped to the request // and therefore available to all following routes that match the request. // // All the values are removed from ctx after returning from the top // RequestHandler. Additionally, Close method is called on each value // implementing io.Closer before removing the value from ctx. + // + // Storing through the Ctx interface heap-allocates the one-element slice the + // variadic value is packed into; SetLocal stores the same value without it. Locals(key any, value ...any) any + // SetLocal stores value under key scoped to the request, exactly as + // Locals(key, value) does: the value is available to all following routes that + // match the request, removed after the top RequestHandler returns, and its + // Close method is called first if it implements io.Closer. Like Locals, it + // stores nothing while the context is released. A Ctx must not be used past + // its handler either way, because the pool hands the same one to the next + // request. + // + // Locals takes its value variadically, and reached through the Ctx interface + // the compiler cannot see that the callee only reads that argument, so the + // one-element "..." slice is heap-allocated on every call. SetLocal takes the + // value directly, so that slice is never built. Boxing a value that is not + // already an interface still allocates, exactly as it does for Locals. + SetLocal(key, value any) // Method returns the HTTP request method for the context, optionally overridden by the provided argument. // If no override is given or if the provided override is not a valid HTTP method, it returns the current method from the context. // Otherwise, it updates the context's method and returns the overridden method as a string. Method(override ...string) string + // IsSafe reports whether the request method is safe, meaning it is not expected + // to change server state (RFC 9110 Section 9.2.1). + IsSafe() bool + // IsIdempotent reports whether the request method is idempotent, meaning + // repeating it has the same intended effect as making it once (RFC 9110 + // Section 9.2.2). Every safe method is also idempotent. + IsIdempotent() bool // MultipartForm parse form entries from binary. // This returns a map[string][]string, so given a key, the value will be a string slice. + // + // On a form request this lowercases the case-insensitive parts of the request's + // own Content-Type, so a value obtained earlier from Get(HeaderContentType) — + // which aliases those bytes unless Immutable is set — can change during the + // call. Copy it first if you need it to outlive one. MultipartForm() (*multipart.Form, error) // OriginalURL contains the original request URL. // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting to use the value outside the Handler. OriginalURL() string + // URI returns the parsed *fasthttp.URI of the request, giving access to all + // fasthttp URI methods. It is owned by the request and rewritten by a Path + // override, so it is only valid within the handler. + URI() *fasthttp.URI + // Path returns the path part of the request URL, normalized before routing + // (see Config.UnescapePath); OriginalURL returns the request target as sent. + // Optionally, you could override the path. + // Make copies or use the Immutable setting to use the value outside the Handler. + Path(override ...string) string // Params is used to get the route parameters. // Defaults to empty string "" if the param doesn't exist. // If a default value is given, it will return that value if the param doesn't exist. @@ -180,6 +350,8 @@ type Req interface { Queries() map[string]string // Range returns a struct containing the type and a slice of ranges. Range(size int64) (Range, error) + // Endpoint returns the route that will handle this request. See Ctx.Endpoint. + Endpoint() *Route // Route returns the matched Route struct. Route() *Route // Subdomains returns a slice of subdomains from the host, excluding the last `offset` components. diff --git a/src/vendor/github.com/gofiber/fiber/v3/res.go b/src/vendor/github.com/gofiber/fiber/v3/res.go index 7f14505c..64f52864 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/res.go +++ b/src/vendor/github.com/gofiber/fiber/v3/res.go @@ -2,22 +2,27 @@ package fiber import ( "bufio" + "bytes" "fmt" "html/template" "io" "io/fs" "net/http" - "net/url" "os" pathpkg "path" "path/filepath" + "reflect" "slices" - "strconv" "strings" "time" "unicode" "unicode/utf8" + "github.com/gofiber/fiber/v3/internal/byterange" + internalcookie "github.com/gofiber/fiber/v3/internal/cookie" + "github.com/gofiber/fiber/v3/internal/fieldname" + "github.com/gofiber/fiber/v3/internal/headerlist" + "github.com/gofiber/fiber/v3/internal/quotedstring" "github.com/gofiber/utils/v2" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" @@ -39,7 +44,8 @@ type SendFile struct { // Optional. Default: false Compress bool `json:"compress"` - // When set to true, enables byte range requests. + // When set to true, enables byte range requests. A request for several + // ranges, or whose If-Range does not match, gets the whole file. // // Optional. Default: false ByteRange bool `json:"byte_range"` @@ -74,7 +80,7 @@ type sendFileStore struct { // // Here we don't use reflect.DeepEqual because it is quite slow compared to manual comparison. func (sf *sendFileStore) configEqual(cfg SendFile) bool { - if sf.config.FS != cfg.FS { + if !sameFS(sf.config.FS, cfg.FS) { return false } @@ -101,6 +107,36 @@ func (sf *sendFileStore) configEqual(cfg SendFile) bool { return true } +// sameFS reports whether two file systems are the same one. Values of an +// uncomparable dynamic type (fstest.MapFS) are compared by what they reference. +func sameFS(a, b fs.FS) bool { + if a == nil || b == nil { + return a == nil && b == nil + } + + va, vb := reflect.ValueOf(a), reflect.ValueOf(b) + if va.Type() != vb.Type() { + return false + } + if va.Type().Comparable() { + return a == b + } + + switch va.Kind() { + case reflect.Slice: + // Pointer() is &elem[0] and ignores the length, so two prefixes of one + // backing array would otherwise look like the same file system. + return va.Pointer() == vb.Pointer() && va.Len() == vb.Len() + case reflect.Map, reflect.Chan, reflect.Pointer, reflect.UnsafePointer: + return va.Pointer() == vb.Pointer() + default: + // A func's pointer is its code entry, shared by every closure over the + // same body, so two file systems capturing different roots would look + // like one. Treat them as distinct rather than serve the wrong root. + return false + } +} + // Cookie defines the values used when configuring cookies emitted by // DefaultRes.Cookie. type Cookie struct { @@ -137,49 +173,49 @@ func (r *DefaultRes) App() *App { // Append the specified value to the HTTP response header field. // If the header is not already set, it creates the header with the specified value. +// Empty values are skipped: a sender must not generate empty list elements +// (RFC 9110 Section 5.6.1.2). +// Members are compared byte-exactly, because some lists (Link, Cache-Control) +// are not all field names. For Vary field names, use Vary, which folds case. func (r *DefaultRes) Append(field string, values ...string) { if len(values) == 0 { return } - h := r.c.app.toString(r.c.fasthttp.Response.Header.Peek(field)) - originalH := h - for _, value := range values { - if h == "" { - h = value - } else if !headerContainsValue(h, value) { - h += ", " + value - } + // Consider all existing field lines combined (RFC 9110 Section 5.2) so + // the dedup check sees members added on later lines via Header.Add. + existing, multiLine := peekJoinedResponseHeader(&r.c.fasthttp.Response.Header, field) + updated := headerlist.AppendUnique(utils.UnsafeString(existing), values) + if updated == "" { + return } - if originalH != h { - r.Set(field, h) + if multiLine { + // Set only rewrites the first field line; drop the extras that are + // now folded into the combined value. + r.c.fasthttp.Response.Header.Del(field) } + r.Set(field, updated) } -// headerContainsValue checks if a header value already contains the given value -// as a comma-separated element. Per RFC 9110, list elements are separated by commas -// with optional whitespace (OWS) around them. -func headerContainsValue(header, value string) bool { - // Empty value should never match - if value == "" { - return false - } +// varyAccept is the field list Format and AutoFormat add to Vary. It is +// hoisted because a fresh "..." argument list is a slice the compiler has to +// heap-allocate — Vary's result reaches the header store, so escape analysis +// marks the elements as leaking even though fasthttp copies the bytes — while +// passing an existing slice hands over its backing array. Both callers are +// methods on *DefaultRes, so the Vary they reach is the one below and not +// something a custom Res could substitute; it only reads the field list, which +// makes sharing one array across every request safe. +var varyAccept = []string{HeaderAccept} - // Exact match (single value header) - if header == value { - return true - } - - // Check each comma-separated element, handling optional whitespace (OWS) - for part := range strings.SplitSeq(header, ",") { - if utils.TrimSpace(part) == value { - return true - } +func sanitizeFilename(filename string) string { + // unicode.IsControl matches C0, DEL and the C1 range. The first two are + // single bytes utils.IndexControl finds word-at-a-time, and C1 can only + // appear in non-ASCII input, so an all-ASCII name that clears both scans + // is clean without decoding a rune. That pair measures 24-58% faster than + // the rune loop across 13- to 90-byte names. + if utils.IndexControl(filename) == -1 && utils.IsASCII(filename) { + return utils.TrimSpace(filename) } - return false -} - -func sanitizeFilename(filename string) string { for _, r := range filename { if unicode.IsControl(r) { b := make([]byte, 0, len(filename)) @@ -203,6 +239,59 @@ func fallbackFilenameIfInvalid(filename string) string { return filename } +// isExtValueAttrChar reports whether c is an attr-char per RFC 8187 §3.2: +// ALPHA / DIGIT / "!" / "#" / "$" / "&" / "+" / "-" / "." / "^" / "_" / +// "`" / "|" / "~". Every other byte of an ext-value must be pct-encoded. +func isExtValueAttrChar(c byte) bool { + switch { + case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9': + return true + } + switch c { + case '!', '#', '$', '&', '+', '-', '.', '^', '_', '`', '|', '~': + return true + default: + return false + } +} + +// encodeExtValue percent-encodes s as the value-chars of an RFC 8187 +// ext-value. URL path/query escaping is not sufficient here: it leaves +// bytes such as ':', '=', and '@' bare, which the ext-value grammar forbids. +func encodeExtValue(s string) string { + const hex = "0123456789ABCDEF" + b := make([]byte, 0, len(s)) + for i := 0; i < len(s); i++ { + c := s[i] + if isExtValueAttrChar(c) { + b = append(b, c) + } else { + b = append(b, '%', hex[c>>4], hex[c&0x0F]) + } + } + return string(b) +} + +// contentDispositionAttachment builds an RFC 6266 Content-Disposition value +// for a sanitized filename: the filename parameter is a quoted-string with +// RFC 9110 §5.6.4 escaping, and non-ASCII names additionally carry an +// RFC 8187 filename* ext-value for interoperability. +func contentDispositionAttachment(fname string) string { + disp := `attachment; filename="` + quotedstring.Escape(fname) + `"` + if !utils.IsASCII(fname) { + disp += `; filename*=UTF-8''` + encodeExtValue(fname) + } + return disp +} + +// Add appends the value as a new field line, where Append folds values into one +// comma-separated line. The headers fasthttp keeps in a slot of their own are +// the exception: Content-Type, Server and the rest are replaced and Date and TE +// ignored, though Set-Cookie is slotted and does append. Use Cookie for that. +func (r *DefaultRes) Add(key, val string) { + r.c.fasthttp.Response.Header.Add(key, val) +} + // Attachment sets the HTTP response Content-Disposition header field to attachment. func (r *DefaultRes) Attachment(filename ...string) { if len(filename) > 0 { @@ -210,18 +299,7 @@ func (r *DefaultRes) Attachment(filename ...string) { fname = sanitizeFilename(fname) fname = fallbackFilenameIfInvalid(fname) r.Type(filepath.Ext(fname)) - app := r.c.app - var quoted string - if app.isASCII(fname) { - quoted = app.quoteString(fname) - } else { - quoted = app.quoteRawString(fname) - } - disp := `attachment; filename="` + quoted + `"` - if !app.isASCII(fname) { - disp += `; filename*=UTF-8''` + url.PathEscape(fname) - } - r.setCanonical(HeaderContentDisposition, disp) + r.setCanonical(HeaderContentDisposition, contentDispositionAttachment(fname)) return } r.setCanonical(HeaderContentDisposition, "attachment") @@ -250,50 +328,50 @@ func (r *DefaultRes) RequestCtx() *fasthttp.RequestCtx { } // Cookie sets a cookie by passing a cookie struct. +// +// The argument is treated as read-only: the normalization this method applies +// (default Path, SessionOnly, and the Secure implied by SameSite=None or +// Partitioned) happens on a local copy, so a caller may reuse the same *Cookie +// template across requests. func (r *DefaultRes) Cookie(cookie *Cookie) { - if cookie.Path == "" { - cookie.Path = "/" - } + c := *cookie - if cookie.SessionOnly { - cookie.MaxAge = 0 - cookie.Expires = time.Time{} + if c.Path == "" { + c.Path = "/" } - var sameSite http.SameSite + if c.SessionOnly { + c.MaxAge = 0 + c.Expires = time.Time{} + } - switch { - case utils.EqualFold(cookie.SameSite, CookieSameSiteStrictMode): - sameSite = http.SameSiteStrictMode - case utils.EqualFold(cookie.SameSite, CookieSameSiteNoneMode): - sameSite = http.SameSiteNoneMode + sameSite, _ := internalcookie.ParseSameSite(c.SameSite) + if sameSite.RequiresSecure { // SameSite=None requires Secure=true per RFC and browser requirements - cookie.Secure = true - case utils.EqualFold(cookie.SameSite, CookieSameSiteDisabled): - sameSite = 0 - case utils.EqualFold(cookie.SameSite, CookieSameSiteLaxMode): - sameSite = http.SameSiteLaxMode - default: - sameSite = http.SameSiteLaxMode + c.Secure = true } // Partitioned requires Secure=true per CHIPS spec - if cookie.Partitioned { - cookie.Secure = true + if c.Partitioned { + c.Secure = true } - // create/validate cookie using net/http + // Surrounding double quotes frame the value (RFC 6265 §4.1.1); they are not part of it. + value, quoted := unquoteCookieValue(c.Value) + + // Validate before fasthttp's setters can silently replace CR/LF or semicolons; + // rejection, rather than mutation, is this API's existing contract. hc := &http.Cookie{ //nolint:gosec // G124: http.Cookie missing or has insecure Secure, HttpOnly, or SameSite attribute - Name: cookie.Name, - Value: cookie.Value, - Path: cookie.Path, - Domain: cookie.Domain, - Expires: cookie.Expires, - MaxAge: cookie.MaxAge, - Secure: cookie.Secure, - HttpOnly: cookie.HTTPOnly, - SameSite: sameSite, - Partitioned: cookie.Partitioned, + Name: c.Name, + Value: value, + Path: c.Path, + Domain: c.Domain, + Expires: c.Expires, + MaxAge: c.MaxAge, + Secure: c.Secure, + HttpOnly: c.HTTPOnly, + SameSite: sameSite.HTTPMode, + Partitioned: c.Partitioned, } if err := hc.Valid(); err != nil { @@ -304,11 +382,17 @@ func (r *DefaultRes) Cookie(cookie *Cookie) { // create fasthttp cookie fcookie := fasthttp.AcquireCookie() fcookie.SetKey(hc.Name) - fcookie.SetValue(hc.Value) + // net/http quotes a value with a space or comma, and so does this, although + // RFC 6265 §4.1.1 allows neither even in quotes. fasthttp drops the quotes on read. + wireValue := hc.Value + if quoted || utils.IndexAny2(wireValue, ' ', ',') >= 0 { + wireValue = `"` + wireValue + `"` + } + fcookie.SetValue(wireValue) fcookie.SetPath(hc.Path) fcookie.SetDomain(hc.Domain) - if !cookie.SessionOnly { + if !c.SessionOnly { fcookie.SetMaxAge(hc.MaxAge) fcookie.SetExpire(hc.Expires) } @@ -316,16 +400,7 @@ func (r *DefaultRes) Cookie(cookie *Cookie) { fcookie.SetSecure(hc.Secure) fcookie.SetHTTPOnly(hc.HttpOnly) - switch sameSite { - case http.SameSiteLaxMode: - fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode) - case http.SameSiteStrictMode: - fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode) - case http.SameSiteNoneMode: - fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode) - default: - fcookie.SetSameSite(fasthttp.CookieSameSiteDisabled) - } + fcookie.SetSameSite(sameSite.FastHTTPMode) fcookie.SetPartitioned(hc.Partitioned) @@ -334,6 +409,116 @@ func (r *DefaultRes) Cookie(cookie *Cookie) { fasthttp.ReleaseCookie(fcookie) } +// unquoteCookieValue strips one pair of surrounding double quotes. A lone quote +// is left for validation to reject. +func unquoteCookieValue(value string) (string, bool) { + if len(value) >= 2 && value[0] == '"' && value[len(value)-1] == '"' { + return value[1 : len(value)-1], true + } + return value, false +} + +// GetCookie reads back a cookie this response is set to send, false when the +// name is unset or its value does not parse. Names are case-sensitive and a +// repeat resolves to the first. Writing the copy back through Cookie stamps +// Path=/ on a cookie that carried none, widening its scope — set Path first. +func (r *DefaultRes) GetCookie(name string) (*Cookie, bool) { + header := &r.c.fasthttp.Response.Header + + fcookie := fasthttp.AcquireCookie() + defer fasthttp.ReleaseCookie(fcookie) + + for key, value := range header.Cookies() { + if string(key) != name { + continue + } + // Parsed from the yielded value rather than looked up again by name: the + // lookup discards the parse error, turning a Set-Cookie whose attributes + // fail to parse into one that silently lost its Path and flags. + if fcookie.ParseBytes(value) != nil { + return nil, false + } + return responseCookie(fcookie, value), true + } + + return nil, false +} + +// GetCookies returns a copy of every cookie this response is set to send, in +// order, or nil when there are none. Repeated names are kept apart, and an +// unparsable one is skipped. For what the client sent, use Req.Cookies. +// +// Named for GetCookie beside it rather than Cookies, which would collide with +// Req.Cookies under a different signature and stop Ctx satisfying Res. +func (r *DefaultRes) GetCookies() []*Cookie { + header := &r.c.fasthttp.Response.Header + + fcookie := fasthttp.AcquireCookie() + defer fasthttp.ReleaseCookie(fcookie) + + var cookies []*Cookie + // Each entry is parsed where it is found: resolving the name against the + // header again answers with the first cookie of that name once per entry, + // hiding every later one behind a duplicate of the first. + for _, value := range header.Cookies() { + if fcookie.ParseBytes(value) != nil { + continue + } + cookies = append(cookies, responseCookie(fcookie, value)) + } + + return cookies +} + +// cookieAttrPresent reports whether a Set-Cookie value carries the named +// attribute. RFC 6265 Section 4.1.1 excludes ";" from cookie-value, so splitting +// on it is safe; the first element is the name=value pair and is skipped. +func cookieAttrPresent(value []byte, attr string) bool { + _, rest, found := utils.CutByte(value, ';') + if !found { + return false + } + + for len(rest) > 0 { + part := rest + if i := bytes.IndexByte(rest, ';'); i >= 0 { + part, rest = rest[:i], rest[i+1:] + } else { + rest = nil + } + name, _, _ := utils.CutByte(part, '=') + if utils.EqualFold(utils.UnsafeString(utils.TrimSpace(name)), attr) { + return true + } + } + + return false +} + +// responseCookie converts a parsed Set-Cookie back into the Cookie Res.Cookie +// accepts. fasthttp writes a deletion as "max-age=0" and parses it back as 0, +// so raw is consulted to tell that from an absent attribute. +func responseCookie(fcookie *fasthttp.Cookie, raw []byte) *Cookie { + cookie := &Cookie{ + Name: string(fcookie.Key()), + Value: string(fcookie.Value()), + Path: string(fcookie.Path()), + Domain: string(fcookie.Domain()), + Expires: fcookie.Expire(), + MaxAge: fcookie.MaxAge(), + Secure: fcookie.Secure(), + HTTPOnly: fcookie.HTTPOnly(), + SameSite: internalcookie.FormatSameSite(fcookie.SameSite()), + Partitioned: fcookie.Partitioned(), + } + if cookie.MaxAge == 0 && cookieAttrPresent(raw, "max-age") { + cookie.MaxAge = -1 + } + cookie.SessionOnly = cookie.MaxAge == 0 && cookie.Expires.IsZero() + + return cookie +} + // Download transfers the file from path as an attachment. // Typically, browsers will prompt the user for download. // By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog). @@ -347,18 +532,7 @@ func (r *DefaultRes) Download(file string, filename ...string) error { } fname = sanitizeFilename(fname) fname = fallbackFilenameIfInvalid(fname) - app := r.c.app - var quoted string - if app.isASCII(fname) { - quoted = app.quoteString(fname) - } else { - quoted = app.quoteRawString(fname) - } - disp := `attachment; filename="` + quoted + `"` - if !app.isASCII(fname) { - disp += `; filename*=UTF-8''` + url.PathEscape(fname) - } - r.setCanonical(HeaderContentDisposition, disp) + r.setCanonical(HeaderContentDisposition, contentDispositionAttachment(fname)) return r.SendFile(file) } @@ -369,6 +543,10 @@ func (r *DefaultRes) Response() *fasthttp.Response { return &r.c.fasthttp.Response } +// formatDefaultMediaType is the sentinel MediaType marking a Format handler as +// the fallback. It is not a media type and is never emitted as a Content-Type. +const formatDefaultMediaType = "default" + // Format performs content-negotiation on the Accept HTTP header. // It uses Accepts to select a proper format and calls the matching // user-provided handler function. @@ -386,11 +564,28 @@ func (r *DefaultRes) Format(handlers ...ResFmt) error { } } - r.Vary(HeaderAccept) - - if r.c.DefaultReq.Get(HeaderAccept) == "" { - r.c.fasthttp.Response.Header.SetContentType(handlers[0].MediaType) - return handlers[0].Handler(r.c) + // Handlers must see the custom context when the app uses one, as Next does. + handlerCtx := r.c.ctxForHandlers() + + r.Vary(varyAccept...) + + // Absent means the combined Accept view (RFC 9110 Section 5.2) is empty: + // no field line, or only empty ones. The joined read matches the field name + // case-insensitively, the same way Accepts negotiates, so the two entry + // points agree on whether the client stated a preference. + acceptRaw := peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAccept) + if len(acceptRaw) == 0 { + // Without an Accept header the client accepts any media type + // (RFC 9110 Section 12.5.1), so pick the first non-default handler and + // use its media type. The literal "default" is not a media type and + // must not be emitted as a Content-Type value. + for _, h := range handlers { + if h.MediaType != formatDefaultMediaType { + r.c.fasthttp.Response.Header.SetContentType(h.MediaType) + return h.Handler(handlerCtx) + } + } + return handlers[0].Handler(handlerCtx) } // Using an int literal as the slice capacity allows for the slice to be @@ -400,7 +595,7 @@ func (r *DefaultRes) Format(handlers ...ResFmt) error { types := make([]string, 0, 8) var defaultHandler Handler for _, h := range handlers { - if h.MediaType == "default" { + if h.MediaType == formatDefaultMediaType { defaultHandler = h.Handler continue } @@ -412,13 +607,13 @@ func (r *DefaultRes) Format(handlers ...ResFmt) error { if defaultHandler == nil { return r.SendStatus(StatusNotAcceptable) } - return defaultHandler(r.c) + return defaultHandler(handlerCtx) } for _, h := range handlers { if h.MediaType == accept { r.c.fasthttp.Response.Header.SetContentType(h.MediaType) - return h.Handler(r.c) + return h.Handler(handlerCtx) } } @@ -432,8 +627,17 @@ func (r *DefaultRes) Format(handlers ...ResFmt) error { // For more flexible content negotiation, use Format. // If the header is not specified or there is no proper format, text/plain is used. func (r *DefaultRes) AutoFormat(body any) error { - // Get accepted content type - accept := r.c.DefaultReq.Accepts("html", "json", "txt", "xml", "msgpack", "cbor") //nolint:staticcheck // It is fine to ignore the static check + // The response is selected based on the Accept header, so let caches know + // (RFC 9110 Section 12.5.5). + r.Vary(varyAccept...) + + // Get accepted content type; text/plain when nothing matches. + accept := "txt" + if len(peekJoinedRequestHeader(&r.c.fasthttp.Request.Header, HeaderAccept)) > 0 { + if negotiated := r.c.DefaultReq.Accepts("html", "json", "txt", "xml", "msgpack", "cbor"); negotiated != "" { //nolint:staticcheck // It is fine to ignore the static check + accept = negotiated + } + } // Set accepted content type r.Type(accept) @@ -468,12 +672,38 @@ func (r *DefaultRes) AutoFormat(body any) error { return r.SendString(b) } +// ContentLength returns what the Content-Length response header declares: a +// length a handler or upstream set, -1 for an unknown-length stream, 0 when +// none is declared. fasthttp fills it in on serialization; see also Res.Body. +func (r *DefaultRes) ContentLength() int { + return r.c.fasthttp.Response.Header.ContentLength() +} + +// ContentType returns the Content-Type response header, the read side of Type. +// With none set it reports what would be sent: fasthttp's default, or "" under +// Config.DisableDefaultContentType. Only valid within the handler. +func (r *DefaultRes) ContentType() string { + return r.c.app.toString(r.c.fasthttp.Response.Header.ContentType()) +} + +// Del removes every field line stored under key, whatever case it is spelled in, +// and is a no-op for a header that was never set. Del(HeaderSetCookie) withdraws +// the pending cookies, where ClearCookie expires one in the client's jar. +func (r *DefaultRes) Del(key string) { + header := &r.c.fasthttp.Response.Header + // The byte-exact fast path needs both sides canonical: the stored names (a + // proxied response can hold lower-case ones) and the caller's key, which + // fasthttp only normalizes while DisableHeaderNormalizing is off. + canonical := !r.c.app.config.DisableHeaderNormalizing && fieldname.Canonical(header) + fieldname.Del(header, key, canonical) +} + // Get (a.k.a. GetRespHeader) returns the HTTP response header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. // Make copies or use the Immutable setting instead. func (r *DefaultRes) Get(key string, defaultValue ...string) string { - return defaultString(r.c.app.toString(r.c.fasthttp.Response.Header.Peek(key)), defaultValue) + return defaultString(r.c.app.toString(fieldname.Peek(&r.c.fasthttp.Response.Header, key)), defaultValue) } // GetHeaders (a.k.a GetRespHeaders) returns the HTTP response headers. @@ -557,15 +787,23 @@ func (r *DefaultRes) CBOR(data any, ctype ...string) error { // JSONP sends a JSON response with JSONP support. // This method is identical to JSON, except that it opts-in to JSONP callback support. // By default, the callback name is simply callback. +// +// The callback name is reduced to a JavaScript member expression: everything +// outside [A-Za-z0-9_$.[]] is dropped. Callers routinely take the name straight +// from the query string, which is what JSONP is for, and the name lands +// verbatim in a same-origin text/javascript body — so an unfiltered one would +// let a request supply arbitrary script for the app's own origin. func (r *DefaultRes) JSONP(data any, callback ...string) error { raw, err := r.c.app.config.JSONEncoder(data) if err != nil { return err } - cb := "callback" + cb := defaultJSONPCallback if len(callback) > 0 { - cb = callback[0] + if sanitized := sanitizeJSONPCallback(callback[0]); sanitized != "" { + cb = sanitized + } } // Build JSONP response: callback(data); @@ -584,6 +822,146 @@ func (r *DefaultRes) JSONP(data any, callback ...string) error { return nil } +const defaultJSONPCallback = "callback" + +// isJSONPCallbackByte reports whether b may appear in a JSONP callback name. The +// set spells a JavaScript member expression and admits nothing that could open a +// string, comment or statement. +func isJSONPCallbackByte(b byte) bool { + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || + (b >= '0' && b <= '9') || + b == '_' || b == '$' || b == '.' || b == '[' || b == ']' +} + +// sanitizeJSONPCallback drops every byte isJSONPCallbackByte rejects, as Express +// and Django do, then requires a member expression, returning "" otherwise. +// Filtering is enough for safety, not correctness: "1.2.3" and "a[" only throw. +func sanitizeJSONPCallback(cb string) string { + i := 0 + for ; i < len(cb); i++ { + if !isJSONPCallbackByte(cb[i]) { + break + } + } + + if i != len(cb) { + out := make([]byte, i, len(cb)) + copy(out, cb[:i]) + for ; i < len(cb); i++ { + if isJSONPCallbackByte(cb[i]) { + out = append(out, cb[i]) + } + } + cb = utils.UnsafeString(out) + } + + if !isJSONPMemberExpression(cb) { + return "" + } + return cb +} + +// isJSONPMemberExpression reports whether cb is a dotted chain of identifiers +// with optional bracket indexing — the shape a JSONP body may legally call. +func isJSONPMemberExpression(cb string) bool { + if cb == "" { + return false + } + // "let" is a keyword only where a "[" follows it, and only at the head: an + // expression statement may not begin "let [", so the body "let[a](…);" is + // read as a destructuring declaration and is a syntax error. "let(…)", + // "let.a(…)" and an inner "cb[let[a]]" are all calls and stay allowed. + if strings.HasPrefix(cb, "let[") { + return false + } + + depth := 0 + atStart := true // expecting the first byte of an identifier + inIndex := false // that first byte follows '[', so a number may stand there + afterClose := false // a ']' just closed an index + numeric := false // the open index began with a digit, so it is a number + isRef := true // the open token is read as a name, not written as a property + start := 0 // first byte of the open token + for i := 0; i < len(cb); i++ { + switch c := cb[i]; c { + case '.': + if atStart || numeric || (isRef && isJSReservedWord(cb[start:i])) { + return false + } + atStart, inIndex, afterClose, isRef = true, false, false, false + case '[': + if atStart || numeric || (isRef && isJSReservedWord(cb[start:i])) { + return false + } + depth++ + atStart, inIndex, afterClose, isRef = true, true, false, true + start = i + 1 + case ']': + if atStart || depth == 0 { + return false + } + if isRef && !numeric && isJSReservedWord(cb[start:i]) { + return false + } + depth-- + afterClose, numeric, isRef = true, false, false + default: + // Only '.', '[' or another ']' may follow a closing bracket, so "cb[0]x" + // is no member expression. Without this the machine would accept it and + // emit a body that does not parse. + if afterClose { + return false + } + if atStart { + // An identifier may not start with a digit. A bracket index may, and + // then it is that number alone: "cb[0]" parses, "cb[0x]" does not. + // Only a token opened by '[' counts — "cb[a.0]" is a property named + // after a dot, where a digit is as illegal as it is at the top level. + if c >= '0' && c <= '9' { + if !inIndex { + return false + } + numeric = true + } + atStart, inIndex = false, false + } else if numeric && (c < '0' || c > '9') { + return false + } + } + } + if isRef && !numeric && isJSReservedWord(cb[start:]) { + return false + } + return depth == 0 && !atStart +} + +// isJSReservedWord reports whether tok is a word JavaScript will not read as a +// name. Only the positions that are read matter — the head of the expression and +// the head inside each index — since "a.for" and "a[b.class]" name properties, +// which any word may do. Emitting "for({…})" instead just ships a syntax error to +// the browser, so those spellings fall back to the default callback. +func isJSReservedWord(tok string) bool { + // Only the words a classic script rejects wherever they stand. A JSONP body + // is loaded by a script tag, so it is parsed under the script goal in sloppy + // mode, and several words that look reserved are ordinary identifiers there. + // + // Absent on purpose: "this", "true", "false" and "null" are keywords, but + // each is a complete expression, so "this.cb" and "cb[true]" parse. "await" + // is reserved only in a module or an async function, and "yield" only in + // strict mode or a generator, so both name a callback here. "let" is + // contextual in a third way and handled where it is read. + switch tok { + case "break", "case", "catch", "class", "const", "continue", + "debugger", "default", "delete", "do", "else", "enum", "export", + "extends", "finally", "for", "function", "if", "import", "in", + "instanceof", "new", "return", "super", "switch", + "throw", "try", "typeof", "var", "void", "while", "with": + return true + default: + return false + } +} + // XML converts any interface or string to XML. // This method also sets the content header to application/xml; charset=utf-8. func (r *DefaultRes) XML(data any) error { @@ -611,7 +989,9 @@ func (r *DefaultRes) Links(link ...string) { bb.WriteByte('>') } else { bb.WriteString(`; rel="`) - bb.WriteString(link[i]) + // The rel value sits inside a quoted-string, so quotes and + // backslashes must be escaped (RFC 9110 Section 5.6.4). + bb.WriteString(quotedstring.Escape(link[i])) bb.WriteString(`",`) } } @@ -678,9 +1058,37 @@ func (r *DefaultRes) Render(name string, bind any, layouts ...string) error { rootApp := r.c.app var rendered bool + + // A sub-app mounted on a domain only applies to a matching host, so the + // path scan below cannot find it. Rank it against the plain mounts by how + // deep its mount path is, so neither borrows the other's engine; a tie + // goes to the domain mount, which matched the host as well. + domain := rootApp.domainMountOwner(r.c) + domainViews, domainLayout := domainMountRender(domain) + for _, prefix := range slices.Backward(rootApp.mountFields.appListKeys) { app := rootApp.mountFields.appList[prefix] - if prefix == "" || strings.Contains(r.c.OriginalURL(), prefix) { + if domain.outranks(mountDepth(prefix)) { + // The layout applies whether or not the owner brought an engine: + // a mount configuring only a layout renders through the engine + // above it, exactly as an ordinary one does. + if len(layouts) == 0 && domainLayout != "" { + layouts = []string{domainLayout} + } + + if domainViews != nil { + break + } + + // With no engine of its own the search goes on above the owner, as + // it does for an ordinary mount — but not through a mount the + // owner supersedes, which did not serve the request and whose + // engine is not the owner's to borrow. + if domain.supersedes(mountDepth(prefix), app) { + continue + } + } + if prefix == "" || rootApp.mountCoversPath(prefix, r.c.Path()) { if len(layouts) == 0 && app.config.ViewsLayout != "" { layouts = []string{ app.config.ViewsLayout, @@ -688,7 +1096,7 @@ func (r *DefaultRes) Render(name string, bind any, layouts ...string) error { } // Render template from Views - if app.config.Views != nil { + if !isNilViews(app.config.Views) { if err := func() error { viewsLock := getViewsLock(app.config.Views) viewsLock.RLock() @@ -709,6 +1117,26 @@ func (r *DefaultRes) Render(name string, bind any, layouts ...string) error { } } + // The layout is already settled: the scan above visits the root mount at + // worst, which every owner outranks, and applies the owner's layout there. + if !rendered && domainViews != nil { + if err := func() error { + viewsLock := getViewsLock(domainViews.config.Views) + viewsLock.RLock() + defer viewsLock.RUnlock() + + if err := domainViews.config.Views.Render(buf, name, bind, layouts...); err != nil { + return fmt.Errorf("failed to render: %w", err) + } + + return nil + }(); err != nil { + return err + } + + rendered = true + } + if !rendered { // Render raw template using 'name' as filepath if no engine is set var tmpl *template.Template @@ -741,6 +1169,32 @@ func (r *DefaultRes) renderExtensions(bind any) { r.c.renderExtensions(bind) } +// Body returns the response body buffered so far, or nil for a streamed one, +// which draining would de-stream; Written tells those apart. The buffer is live, +// so writing to it writes to the response, and the next write voids it. +func (r *DefaultRes) Body() []byte { + resp := &r.c.fasthttp.Response + if resp.IsBodyStream() { + return nil + } + return resp.Body() +} + +// ResetBody discards the response body, keeping the status and headers. +// Use it before replacing a partially written body — an error page over a +// half-rendered view, a cached body over a fresh one. +func (r *DefaultRes) ResetBody() { + r.c.fasthttp.Response.ResetBody() +} + +// Written reports whether anything has been written to the response body, so a +// handler that produced one can be told from a handler that did not. A stream +// counts without being drained; a status or header alone does not. +func (r *DefaultRes) Written() bool { + resp := &r.c.fasthttp.Response + return resp.IsBodyStream() || len(resp.Body()) > 0 +} + // Send sets the HTTP response body without copying it. // From this point onward the body argument must not be changed. func (r *DefaultRes) Send(body []byte) error { @@ -766,6 +1220,14 @@ func (r *DefaultRes) SendEarlyHints(hints []string) error { for _, h := range hints { r.c.fasthttp.Response.Header.Add("Link", h) } + // A server MUST NOT send a 1xx response to an HTTP/1.0 (or earlier) + // client (RFC 9110 Section 15.2), and fasthttp can only write interim + // responses on real HTTP/1.1 connections, so send the 103 exclusively + // for HTTP/1.1 requests. The Link headers above still go out on the + // final response; only the interim 103 is skipped. + if !r.c.fasthttp.Request.Header.IsHTTP11() { + return nil + } return r.c.fasthttp.EarlyHints() } @@ -777,6 +1239,13 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { // Save the filename, we will need it in the error message if the file isn't found filename := file + // A control byte is no part of a name a client can ask for. One that + // reached fasthttp's URI parser failed it silently, which left the root + // path and served the root's index.html instead. + if utils.IndexControl(utils.UnsafeBytes(file)) >= 0 { + return NewError(StatusNotFound, fmt.Sprintf("sendfile: file %s not found", filename)) + } + var cfg SendFile if len(config) > 0 { cfg = config[0] @@ -788,17 +1257,24 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { var fsHandler fasthttp.RequestHandler var cacheControlValue string + // Function values have no safe identity in Go: reflect.Value.Pointer only + // identifies their shared code, not captured closure data. Do not retain + // handlers for function-backed file systems, since they can never be safely + // matched and would otherwise grow the application cache on every request. + cacheHandler := cfg.FS == nil || reflect.ValueOf(cfg.FS).Kind() != reflect.Func app := r.c.app - app.sendfilesMutex.RLock() - for _, sf := range app.sendfiles { - if sf.configEqual(cfg) { - fsHandler = sf.handler - cacheControlValue = sf.cacheControlValue - break + if cacheHandler { + app.sendfilesMutex.RLock() + for _, sf := range app.sendfiles { + if sf.configEqual(cfg) { + fsHandler = sf.handler + cacheControlValue = sf.cacheControlValue + break + } } + app.sendfilesMutex.RUnlock() } - app.sendfilesMutex.RUnlock() if fsHandler == nil { fasthttpFS := &fasthttp.FS{ @@ -812,30 +1288,36 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { CompressZstd: cfg.Compress, CompressedFileSuffixes: app.config.CompressedFileSuffixes, CacheDuration: cfg.CacheDuration, - SkipCache: cfg.CacheDuration < 0, + SkipCache: cfg.CacheDuration < 0 || !cacheHandler, IndexNames: []string{"index.html"}, PathNotFound: func(ctx *fasthttp.RequestCtx) { ctx.Response.SetStatusCode(StatusNotFound) }, } + handler := fasthttpFS.NewRequestHandler() + if cfg.ByteRange { + handler = byterange.Wrap(handler) + } sf := &sendFileStore{ config: cfg, - handler: fasthttpFS.NewRequestHandler(), + handler: handler, } maxAge := cfg.MaxAge if maxAge > 0 { - sf.cacheControlValue = "public, max-age=" + strconv.Itoa(maxAge) + sf.cacheControlValue = "public, max-age=" + utils.FormatInt(int64(maxAge)) } // set vars fsHandler = sf.handler cacheControlValue = sf.cacheControlValue - app.sendfilesMutex.Lock() - app.sendfiles = append(app.sendfiles, sf) - app.sendfilesMutex.Unlock() + if cacheHandler { + app.sendfilesMutex.Lock() + app.sendfiles = append(app.sendfiles, sf) + app.sendfilesMutex.Unlock() + } } // Keep original path for mutable params @@ -843,11 +1325,7 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { request := &r.c.fasthttp.Request - // Delete the Accept-Encoding header if compression is disabled - if !cfg.Compress { - // https://github.com/valyala/fasthttp/blob/7cc6f4c513f9e0d3686142e0a1a5aa2f76b3194a/fs.go#L55 - request.Header.Del(HeaderAcceptEncoding) - } + // Keep the request's Accept-Encoding: middleware running after this call still needs it. // copy of https://github.com/valyala/fasthttp/blob/7cc6f4c513f9e0d3686142e0a1a5aa2f76b3194a/fs.go#L103-L121 with small adjustments if file == "" || (!filepath.IsAbs(file) && cfg.FS == nil) { @@ -872,8 +1350,18 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { originalURL := utils.CopyString(r.c.OriginalURL()) defer request.SetRequestURI(originalURL) - // Set new URI for fileHandler - request.SetRequestURI(file) + // The file server reads the request URI, which fasthttp percent-decodes and + // splits at "?" and "#" as it parses it, so the name goes in escaped and + // comes out of that decode exactly as given: "100%25.txt" is the file of + // that name and not "100%.txt", "a?b" is not "a" with a query, and a + // "..%2Fsecret.txt" that a route parameter carried into filepath.Join stays + // one segment instead of decoding, after the join was cleaned, into a step + // out of the caller's directory. SetRequestURIBytes copies the escaped + // name, so a pooled buffer holds it only for the call. + uriBuf := bytebufferpool.Get() + uriBuf.B = utils.AppendPathSegmentsEscape(uriBuf.B[:0], file) + request.SetRequestURIBytes(uriBuf.B) + bytebufferpool.Put(uriBuf) var ( sendFileSize int64 @@ -907,6 +1395,23 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { // Get the status code which is set by fasthttp fsStatus := response.StatusCode() + // fasthttp answers a directory named without a trailing slash with a + // redirect to the name with one, the only redirect its file handler + // issues. Here that name is a filesystem path, not a route, so the + // redirect could only disclose it: the directory is not found. The + // Location carries the name escaped, so it is not compared with the + // name. A name with the trailing slash serves the directory's index.html. + // The error carries no name either, since the default error handler writes + // its message to the client. + if fsStatus == StatusFound { + response.Header.Del(HeaderLocation) + response.SetStatusCode(StatusNotFound) + if status != StatusNotFound { + return ErrNotFound + } + fsStatus = StatusNotFound + } + // Check for error if status != StatusNotFound && fsStatus == StatusNotFound { return NewError(StatusNotFound, fmt.Sprintf("sendfile: file %s not found", filename)) @@ -920,7 +1425,7 @@ func (r *DefaultRes) SendFile(file string, config ...SendFile) error { // Apply cache control header if status != StatusNotFound && status != StatusForbidden { if cfg.ByteRange && hasSendFileSize && response.StatusCode() == StatusRequestedRangeNotSatisfiable && len(response.Header.Peek(HeaderContentRange)) == 0 { - response.Header.Set(HeaderContentRange, "bytes */"+strconv.FormatInt(sendFileSize, 10)) + response.Header.Set(HeaderContentRange, "bytes */"+utils.FormatInt(sendFileSize)) } if cacheControlValue != "" { @@ -954,13 +1459,29 @@ func sendFileContentLength(path string, cfg SendFile) (int64, error) { return info.Size(), nil } +// NoContent replies 204 No Content. SendStatus already discards the body; this +// drops the Content-Type too, since RFC 9110 Section 6.4.1 gives a 204 no +// content to describe. SendStatus(204) keeps it, so the two differ. +func (r *DefaultRes) NoContent() error { + r.Del(HeaderContentType) + + return r.SendStatus(StatusNoContent) +} + // SendStatus sets the HTTP status code and if the response body is empty, // it sets the correct status message in the body. func (r *DefaultRes) SendStatus(status int) error { - r.Status(status) + // Settle the status first so the checks below use the one that is sent. + status = validStatus(status) + r.c.fasthttp.Response.SetStatusCode(status) if statusDisallowsBody(status) { - r.c.fasthttp.Response.ResetBody() + resp := &r.c.fasthttp.Response + resp.ResetBody() + // ResetBody drops the body but keeps a Content-Length the handler + // declared, which RFC 9110 Section 8.6 forbids here and which leaves a + // keep-alive peer waiting for bytes that never come. + resp.Header.Del(HeaderContentLength) return nil } @@ -1000,6 +1521,14 @@ func (r *DefaultRes) SendStreamWriter(streamWriter func(*bufio.Writer)) error { // Set sets the response's HTTP header field to the specified key, value. func (r *DefaultRes) Set(key, val string) { + // A key already in canonical form skips the normalization fasthttp's Set + // runs only to arrive at the same bytes, and the second copy of the value + // it makes on the way; the line stored is the same in either store mode. + // Test_Res_Set_MatchesHeaderSet keeps the two paths storing it alike. + if fieldname.IsCanonical(key) { + r.setCanonical(key, val) + return + } r.c.fasthttp.Response.Header.Set(key, val) } @@ -1009,11 +1538,20 @@ func (r *DefaultRes) setCanonical(key, val string) { // Status sets the HTTP status for the response. // This method is chainable. +// +// A status outside 100 to 999 is logged and replaced by 500. func (r *DefaultRes) Status(status int) Ctx { - r.c.fasthttp.Response.SetStatusCode(status) + r.c.fasthttp.Response.SetStatusCode(validStatus(status)) return r.c } +// StatusCode returns the status code set on the response, the read side of +// Status, and reports 200 until something sets another. After Next it is the +// status the chain settled on. +func (r *DefaultRes) StatusCode() int { + return r.c.fasthttp.Response.StatusCode() +} + func statusDisallowsBody(status int) bool { // As per RFC 9110, 1xx (Informational) responses cannot have a body. if status >= 100 && status < 200 { @@ -1070,8 +1608,35 @@ func shouldIncludeCharset(mimeType string) bool { // Vary adds the given header field to the Vary response header. // This will append the header, if not already listed; otherwise, leaves it listed in the current location. +// Field names are compared case-insensitively (RFC 9110 Section 5.1); the first spelling is kept. +// Per RFC 9110 Section 12.5.5 the wildcard "*" only has meaning as the sole member of the field: +// once "*" is added (or already present), the header is collapsed to a single "*". func (r *DefaultRes) Vary(fields ...string) { - r.Append(HeaderVary, fields...) + if len(fields) == 0 { + return + } + // Peek without copying: the value is only inspected before any write. + // All field lines are combined (RFC 9110 Section 5.2) so a wildcard on a + // later line added via Header.Add is still honored. + existing, multiLine := peekJoinedResponseHeader(&r.c.fasthttp.Response.Header, HeaderVary) + existingStr := utils.UnsafeString(existing) + if slices.Contains(fields, "*") || headerlist.Contains(existingStr, "*") { + if multiLine { + // setCanonical only rewrites the first field line. + r.c.fasthttp.Response.Header.Del(HeaderVary) + } + r.setCanonical(HeaderVary, "*") + return + } + updated := headerlist.AppendUniqueFold(existingStr, fields) + if updated == "" { + return + } + if multiLine { + // Set only rewrites the first field line; fold the extras into one. + r.c.fasthttp.Response.Header.Del(HeaderVary) + } + r.Set(HeaderVary, updated) } // Write appends p into response body. diff --git a/src/vendor/github.com/gofiber/fiber/v3/res_interface_gen.go b/src/vendor/github.com/gofiber/fiber/v3/res_interface_gen.go index 63947e8e..a4ee1298 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/res_interface_gen.go +++ b/src/vendor/github.com/gofiber/fiber/v3/res_interface_gen.go @@ -15,7 +15,16 @@ type Res interface { App() *App // Append the specified value to the HTTP response header field. // If the header is not already set, it creates the header with the specified value. + // Empty values are skipped: a sender must not generate empty list elements + // (RFC 9110 Section 5.6.1.2). + // Members are compared byte-exactly, because some lists (Link, Cache-Control) + // are not all field names. For Vary field names, use Vary, which folds case. Append(field string, values ...string) + // Add appends the value as a new field line, where Append folds values into one + // comma-separated line. The headers fasthttp keeps in a slot of their own are + // the exception: Content-Type, Server and the rest are replaced and Date and TE + // ignored, though Set-Cookie is slotted and does append. Use Cookie for that. + Add(key, val string) // Attachment sets the HTTP response Content-Disposition header field to attachment. Attachment(filename ...string) // ClearCookie expires a specific cookie by key on the client side. @@ -25,7 +34,24 @@ type Res interface { // a cancellation signal, and other values across API boundaries. RequestCtx() *fasthttp.RequestCtx // Cookie sets a cookie by passing a cookie struct. + // + // The argument is treated as read-only: the normalization this method applies + // (default Path, SessionOnly, and the Secure implied by SameSite=None or + // Partitioned) happens on a local copy, so a caller may reuse the same *Cookie + // template across requests. Cookie(cookie *Cookie) + // GetCookie reads back a cookie this response is set to send, false when the + // name is unset or its value does not parse. Names are case-sensitive and a + // repeat resolves to the first. Writing the copy back through Cookie stamps + // Path=/ on a cookie that carried none, widening its scope — set Path first. + GetCookie(name string) (*Cookie, bool) + // GetCookies returns a copy of every cookie this response is set to send, in + // order, or nil when there are none. Repeated names are kept apart, and an + // unparsable one is skipped. For what the client sent, use Req.Cookies. + // + // Named for GetCookie beside it rather than Cookies, which would collide with + // Req.Cookies under a different signature and stop Ctx satisfying Res. + GetCookies() []*Cookie // Download transfers the file from path as an attachment. // Typically, browsers will prompt the user for download. // By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog). @@ -49,6 +75,18 @@ type Res interface { // For more flexible content negotiation, use Format. // If the header is not specified or there is no proper format, text/plain is used. AutoFormat(body any) error + // ContentLength returns what the Content-Length response header declares: a + // length a handler or upstream set, -1 for an unknown-length stream, 0 when + // none is declared. fasthttp fills it in on serialization; see also Res.Body. + ContentLength() int + // ContentType returns the Content-Type response header, the read side of Type. + // With none set it reports what would be sent: fasthttp's default, or "" under + // Config.DisableDefaultContentType. Only valid within the handler. + ContentType() string + // Del removes every field line stored under key, whatever case it is spelled in, + // and is a no-op for a header that was never set. Del(HeaderSetCookie) withdraws + // the pending cookies, where ClearCookie expires one in the client's jar. + Del(key string) // Get (a.k.a. GetRespHeader) returns the HTTP response header specified by field. // Field names are case-insensitive // Returned value is only valid within the handler. Do not store any references. @@ -79,6 +117,12 @@ type Res interface { // JSONP sends a JSON response with JSONP support. // This method is identical to JSON, except that it opts-in to JSONP callback support. // By default, the callback name is simply callback. + // + // The callback name is reduced to a JavaScript member expression: everything + // outside [A-Za-z0-9_$.[]] is dropped. Callers routinely take the name straight + // from the query string, which is what JSONP is for, and the name lands + // verbatim in a same-origin text/javascript body — so an unfiltered one would + // let a request supply arbitrary script for the app's own origin. JSONP(data any, callback ...string) error // XML converts any interface or string to XML. // This method also sets the content header to application/xml; charset=utf-8. @@ -108,6 +152,18 @@ type Res interface { // We support the following engines: https://github.com/gofiber/template Render(name string, bind any, layouts ...string) error renderExtensions(bind any) + // Body returns the response body buffered so far, or nil for a streamed one, + // which draining would de-stream; Written tells those apart. The buffer is live, + // so writing to it writes to the response, and the next write voids it. + Body() []byte + // ResetBody discards the response body, keeping the status and headers. + // Use it before replacing a partially written body — an error page over a + // half-rendered view, a cached body over a fresh one. + ResetBody() + // Written reports whether anything has been written to the response body, so a + // handler that produced one can be told from a handler that did not. A stream + // counts without being drained; a status or header alone does not. + Written() bool // Send sets the HTTP response body without copying it. // From this point onward the body argument must not be changed. Send(body []byte) error @@ -127,6 +183,10 @@ type Res interface { // The Content-Type response HTTP header field is set based on the file's extension. // If the file extension is missing or invalid, the Content-Type is detected from the file's format. SendFile(file string, config ...SendFile) error + // NoContent replies 204 No Content. SendStatus already discards the body; this + // drops the Content-Type too, since RFC 9110 Section 6.4.1 gives a 204 no + // content to describe. SendStatus(204) keeps it, so the two differ. + NoContent() error // SendStatus sets the HTTP status code and if the response body is empty, // it sets the correct status message in the body. SendStatus(status int) error @@ -142,11 +202,20 @@ type Res interface { setCanonical(key, val string) // Status sets the HTTP status for the response. // This method is chainable. + // + // A status outside 100 to 999 is logged and replaced by 500. Status(status int) Ctx + // StatusCode returns the status code set on the response, the read side of + // Status, and reports 200 until something sets another. After Next it is the + // status the chain settled on. + StatusCode() int // Type sets the Content-Type HTTP header to the MIME type specified by the file extension. Type(extension string, charset ...string) Ctx // Vary adds the given header field to the Vary response header. // This will append the header, if not already listed; otherwise, leaves it listed in the current location. + // Field names are compared case-insensitively (RFC 9110 Section 5.1); the first spelling is kept. + // Per RFC 9110 Section 12.5.5 the wildcard "*" only has meaning as the sole member of the field: + // once "*" is added (or already present), the header is collapsed to a single "*". Vary(fields ...string) // Write appends p into response body. Write(p []byte) (int, error) diff --git a/src/vendor/github.com/gofiber/fiber/v3/router.go b/src/vendor/github.com/gofiber/fiber/v3/router.go index c18a7bef..314451ec 100644 --- a/src/vendor/github.com/gofiber/fiber/v3/router.go +++ b/src/vendor/github.com/gofiber/fiber/v3/router.go @@ -5,16 +5,49 @@ package fiber import ( + "bytes" "fmt" + "math/bits" "slices" + "strings" "sync/atomic" + "github.com/gofiber/fiber/v3/internal/urlnorm" "github.com/gofiber/utils/v2" utilsstrings "github.com/gofiber/utils/v2/strings" + "github.com/gofiber/utils/v2/swar" "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) +const ( + // filterMinBucket is the number of routes from which a bucket carries a + // bucketFilter. The scan reaches the routes of a smaller bucket directly + // sooner than it sets up the filter and calls out to it. + filterMinBucket = 8 + + // inlineCandidates is how many candidates a scan of a filtered bucket + // tests as an unfiltered bucket's are before it sets up the filter. A hop + // that its next route takes, as each hop of a middleware chain does, or + // that steps over one route to it, as a chain registered between a + // bucket's routes does, is over sooner than the filter is set up. + inlineCandidates = 2 + + // fingerprintMinBucket is the number of static routes from which a bucket + // filter carries fingerprints; below it the leading-byte filter is cheaper + // than a hash. + fingerprintMinBucket = 8 + + // fingerprintNone is even, so no route fingerprint equals it: the scan uses + // it as the request fingerprint when no static route in the bucket is as + // long as the path, which rejects them all without hashing. + fingerprintNone = 2 + + // 64-bit FNV-1a offset basis and prime, used by pathFingerprint. + fingerprintBasis = 0xcbf29ce484222325 + fingerprintPrime = 0x100000001b3 +) + // Router defines all router handle interface, including app and group router. type Router interface { Use(args ...any) Router @@ -44,20 +77,27 @@ type Router interface { } // Route is a struct that holds all metadata for each registered handler. -type Route struct { +// +//nolint:govet // fieldalignment: the router's scan dictates this order, see below +type Route struct { // betteralign:ignore - see below // ### important: always keep in sync with the copy method "app.copyRoute" and all creations of Route struct ### - group *Group // Group instance. used for routes in groups + // + // Field order is load-bearing. App.next scans a bucket of routes and + // discards most of them, so the fields it needs to do that lead the struct + // and a rejected candidate costs one cache line instead of touching the + // whole thing. prefix/prefixMask come first because they alone reject the + // common case; path, Params' length, the routing flags and routeParser's + // slash bounds follow for the candidates that survive. Keep new routing + // state up here and everything else below routeParser. (A bucket of + // filterMinBucket routes or more is filtered on its scanHeads instead, and + // only the candidates they let through are loaded.) + + prefix uint64 // leading path bytes packed little-endian, see buildPrefixFilter + prefixMask uint64 // covers the bytes of prefix that are known constants; 0 disables the filter path string // Prettified path - // Public fields - Method string `json:"method"` // HTTP method - Name string `json:"name"` // Route's name - //nolint:revive // Having both a Path (uppercase) and a path (lowercase) is fine - Path string `json:"path"` // Original registered route path - Params []string `json:"params"` // Case-sensitive param keys - Handlers []Handler `json:"-"` // Ctx handlers - routeParser routeParser // Parameter parser + Params []string `json:"params"` // Case-sensitive param keys // Data for routing use bool // USE matches path prefixes @@ -66,6 +106,30 @@ type Route struct { root bool // Path equals '/' autoHead bool // Automatically generated HEAD route caseSensitive bool // Whether parameter matching is case-sensitive + unescapePath bool // Whether request routing decodes escaped slashes + + routeParser routeParser // Parameter parser + + // id identifies the registration this route was created by and is shared + // by its per-method copies, so one of them can be found again in another + // method's tree (see routeIndexInTree). It never changes once assigned. + id uint64 + // latestID is the id of the most recent registration whose handlers this + // route carries: its own, until a later Add merges into it. Name matches on + // it to reach every method of that registration, which id cannot do — a + // merge only appends handlers, leaving each method's route with the id of + // the registration that first created it. + latestID uint64 + + Handlers []Handler `json:"-"` // Ctx handlers + + group *Group // Group instance. used for routes in groups + + // Public fields + Method string `json:"method"` // HTTP method + Name string `json:"name"` // Route's name + //nolint:revive // Having both a Path (uppercase) and a path (lowercase) is fine + Path string `json:"path"` // Original registered route path } var ( @@ -73,10 +137,134 @@ var ( preferredPlusGreedyParameters = []string{"+", "*"} ) +// routeTree is a flat, open-addressed index from a tree-path hash to the route +// bucket of a single HTTP method. It serves the request-time lookup that used +// to go through treeStack's map[int][]*Route, where hashing the key and walking +// the bucket group accounted for ~14% of a routed request in CPU profiles. +// Here the lookup is a multiply-shift plus a short linear probe, and a miss +// resolves to the globals bucket inline instead of costing a second lookup. +type routeTree struct { + // hashes is a power-of-two sized probe table holding the tree-path hash of + // each slot, 0 meaning free. It is kept apart from the buckets so a probe + // walks 4 bytes per slot (16 per cache line) instead of a slice header. + // nil when the method has no prefixed bucket and every request hits globals. + hashes []int32 + // buckets is parallel to hashes and holds the routes of each occupied slot + buckets [][]*Route + // filters is parallel to buckets: each slot's filter, nil for a bucket + // below filterMinBucket routes + filters []*bucketFilter + // globalFilter is the filter of globals + globalFilter *bucketFilter + // globals is the bucket for tree hash 0, which is also where misses go + globals []*Route + // mask is len(hashes)-1, used to wrap the probe + mask uint32 + // shift is 32-log2(len(hashes)), so slot keeps the high bits of the + // multiply. A fixed shift would cap the index at whatever it exposes and + // leave larger tables with an unreachable upper half. + shift uint32 +} + +// routeTreeHashMul is the golden-ratio constant used to spread tree hashes, +// whose low bits are just the third path byte, across the probe table. +const routeTreeHashMul = 0x9E3779B1 + +// buildRouteTree converts one method's tree-path buckets into a routeTree. +// +// It returns a pointer, and allocates rather than recycling the previous +// tables, so that publishing a rebuilt tree is a single pointer store. Holding +// the tree by value instead cost a five-word store, which let a reader pair the +// new hash table with the old buckets; recycling the tables let a reader see a +// cleared one and fall through to globals. Both were measurable — 24 wrong +// answers in 20k requests served across a RebuildTree loop, against 0 before +// the index existed — so this restores the parity that assigning treeStack's +// map pointer used to provide. +// +// The buckets are freshly allocated for each build so a published tree remains +// immutable while a request scans it. Publishing is still an unsynchronized +// store, however, so this does not make RebuildTree safe for concurrent use; +// RebuildTree's own doc states the contract. +func buildRouteTree(buckets map[int][]*Route) *routeTree { + tree := &routeTree{globals: buckets[0]} + tree.globalFilter = newBucketFilter(tree.globals) + + prefixed := len(buckets) + if _, ok := buckets[0]; ok { + prefixed-- + } + if prefixed == 0 { + return tree + } + + // Keep the table at most half full: probes stay short, and a free slot is + // always reachable, which is what terminates the loop in lookup. + size := 8 + for size < prefixed*2 { + size *= 2 + } + + tree.hashes = make([]int32, size) + tree.buckets = make([][]*Route, size) + tree.filters = make([]*bucketFilter, size) + tree.mask = uint32(size - 1) //nolint:gosec // G115 - size is a small power of two + // size is a power of two, so its trailing-zero count is log2(size). + tree.shift = uint32(32 - bits.TrailingZeros32(uint32(size))) //nolint:gosec // G115 - size is a small power of two + + for hash, routes := range buckets { + if hash == 0 { + continue + } + i := tree.slot(hash) + for tree.hashes[i] != 0 { + i = (i + 1) & tree.mask + } + tree.hashes[i] = int32(hash) //nolint:gosec // G115 - tree hashes are 24-bit, built from three path bytes + tree.buckets[i] = routes + tree.filters[i] = newBucketFilter(routes) + } + + return tree +} + +// slot returns the probe start index for a tree-path hash. +// +// Fibonacci hashing: the multiply pushes the entropy of the low bytes up into +// the high bits, so the index has to be taken from the top. Shifting by a fixed +// amount and masking cannot do that -- it bounds the index by whatever the +// shift leaves, which for a table bigger than that bound makes the upper half +// unreachable as a probe start and collapses the lower half into a linear scan. +func (t *routeTree) slot(hash int) uint32 { + return uint32(hash) * routeTreeHashMul >> t.shift //nolint:gosec // G115 - tree hashes are 24-bit, built from three path bytes +} + +// lookup returns the route bucket for a tree-path hash, falling back to the +// globals bucket when that hash has no bucket of its own. +// +//nolint:nonamedreturns // the pair reads better named than by position +func (t *routeTree) lookup(hash int) (routes []*Route, filter *bucketFilter) { + if hash == 0 || t.hashes == nil { + return t.globals, t.globalFilter + } + + want := int32(hash) //nolint:gosec // G115 - tree hashes are 24-bit, built from three path bytes + for i := t.slot(hash); ; i = (i + 1) & t.mask { + switch t.hashes[i] { + case want: + return t.buckets[i], t.filters[i] + case 0: + return t.globals, t.globalFilter + } + } +} + // URL generates a URL from the route path and parameters. // This method fills in the route parameters with the provided values. // Parameter matching respects the app's CaseSensitive configuration: // case-insensitive by default, case-sensitive when CaseSensitive is true. +// Parameter values are percent-encoded using URL path-segment rules. +// Dot-containing values that form a dot-only path segment, and slashes that +// UnescapePath would decode outside a parameter's match, return ErrRouteNotRepresentable. // // Example: // @@ -95,19 +283,39 @@ func (r Route) URL(params Map) (string, error) { // buildRouteURL generates a URL from route segments and parameters. // This shared helper is used by both Route.URL() and DefaultRes.getLocationFromRoute() -// to ensure consistent URL generation behavior across APIs. +// to ensure consistent URL generation behavior across APIs. Substituted values +// are encoded as path segments before they enter the composed URL. Greedy +// parameters keep literal slashes because they match path tails rather than one +// segment. // // Parameter resolution uses a deterministic three-step lookup: // 1. Exact key match on segment.ParamName // 2. Case-insensitive fallback picking the lexicographically-smallest matching key (when !caseSensitive) // 3. Greedy parameter fallback for wildcard (*) and plus (+) parameters func buildRouteURL(route *Route, params Map) (string, error) { + // No relative URL names such a route. Two leading slashes open an authority, + // so "//internal" resolves to the host "internal" rather than a path here, + // and one leading slash reaches a different route. Say so instead of + // composing either. + // + // Judged after the parser's own input handling, since that is what a client + // applies to whatever is composed: a tab, CR or LF is deleted anywhere in the + // URL, and a run of controls or spaces is stripped from either end. So a + // route registered at "/\t/internal" reads as "//internal", and one at + // "/internal " — reachable through "/internal%20" under UnescapePath — reads + // as "/internal", a different route. No URL names either. + normalized := urlnorm.AsBrowserReads(route.Path) + if normalized != route.Path || urlnorm.LeadingSlashes(normalized) > 1 { + return "", ErrRouteNotRepresentable + } + if len(route.routeParser.segs) == 0 { - return route.Path, nil + return urlnorm.RootedPath(route.Path), nil } buf := bytebufferpool.Get() defer bytebufferpool.Put(buf) + checkDotSegments := false for _, segment := range route.routeParser.segs { if !segment.IsParam { @@ -150,14 +358,76 @@ func buildRouteURL(route *Route, params Map) (string, error) { } if found { - _, err := buf.WriteString(utils.ToString(val)) - if err != nil { - return "", fmt.Errorf("failed to write string: %w", err) + value := utils.ToString(val) + if !checkDotSegments { + if segment.IsGreedy { + checkDotSegments = strings.IndexByte(value, '.') >= 0 + } else { + // Its slashes get escaped, so it stays inside one segment and only + // "." or ".." can be or complete a dot segment. + checkDotSegments = value == "." || value == ".." + } } + if route.unescapePath && strings.IndexByte(value, '/') >= 0 { + if route.slashLeavesParam(segment, value) { + return "", ErrRouteNotRepresentable + } + // A slash in the value can split a constant dot into its own segment. + checkDotSegments = true + } + if segment.IsGreedy { + buf.B = utils.AppendPathSegmentsEscape(buf.B, value) + continue + } + buf.B = utils.AppendPathEscape(buf.B, value) } } - return buf.String(), nil + if checkDotSegments && route.urlHasDotSegment(buf.B) { + return "", ErrRouteNotRepresentable + } + return urlnorm.RootedPath(buf.String()), nil +} + +// slashLeavesParam reports whether a decoded slash in value ends up outside the parameter. +// It mirrors the slash-consuming branches of findParamLen, including adjacent parameters +// (which consume exactly one byte) and single-byte non-slash terminators. +func (*Route) slashLeavesParam(segment *routeSegment, value string) bool { + return !segment.IsGreedy && + (segment.IsLast || (segment.Length == 1 && len(value) > 1) || + (segment.Length != 1 && (len(segment.ComparePart) != 1 || segment.ComparePart[0] == slashDelimiter))) +} + +// urlHasDotSegment checks the composed path, since constants can complete or +// disambiguate a parameter's dots. Decode once, just as request routing does; +// an escaped slash is a boundary only with UnescapePath enabled. +func (r *Route) urlHasDotSegment(path []byte) bool { + if bytes.IndexByte(path, '%') != -1 { + path = slices.Clone(path) + if r.unescapePath { + path = unescapePath(path) + } else { + path = unescapeSafePath(path) + } + } + // Jump from dot to dot: a dot segment starts after a '/' and ends at a '/' or the end. + for i := bytes.IndexByte(path, '.'); i >= 0; { + if i == 0 || path[i-1] == '/' { + j := i + 1 + if j < len(path) && path[j] == '.' { + j++ + } + if j == len(path) || path[j] == '/' { + return true + } + } + next := bytes.IndexByte(path[i+1:], '.') + if next < 0 { + break + } + i += next + 1 + } + return false } // preferredGreedyParameters returns the generic greedy fallback lookup order @@ -177,7 +447,129 @@ func preferredGreedyParameters(paramName string) []string { return defaultGreedyParameterKeys } -func (r *Route) match(detectionPath, path string, params *[maxParams]string) bool { +// pathHeadWord packs the first swar.WordLen bytes of a detection path into a +// little-endian word, zero-padded when the path is shorter, so a route's +// precomputed prefix can be tested with a single masked compare. +func pathHeadWord(s string) uint64 { + if len(s) >= swar.WordLen { + return swar.Load8(s, 0) + } + + var word uint64 + for i := range len(s) { + word |= uint64(s[i]) << (8 * i) + } + return word +} + +// buildPrefixFilter precomputes the leading-byte filter that App.next uses to +// discard routes before paying for Route.match. +// +// The filter mirrors the first comparison each branch of match would make, so +// it can only reject what match would reject: +// - a route without parameters is compared against r.path in full (exact for +// an endpoint, as a prefix for middleware), so r.path leads it +// - a parametric route enters getMatch, which requires the constant part of +// the first segment; an optional trailing slash may be dropped there, so +// that byte is left out +// - '*' matches every path, and a first segment that is itself a parameter +// constrains nothing, so both disable the filter +// +// The star check comes first: match accepts a star route before looking at parameters. +// +// Anything that changes a route's path, params or parser must run this again. +// The three places that can are register, which builds the route, copyRoute, +// which carries the fields over, and addPrefixToRoute, which rewrites them. +// Test_Route_PrefixFilter_NotStale pins that the set is complete. +// +// It is deliberately not recomputed in buildTree. buildTree runs from +// RebuildTree, whose whole purpose is registering routes on a live app, and the +// routes it would write to are the ones in-flight requests are reading: a +// reader that caught this function between setting prefix and narrowing +// prefixMask compared a short prefix under an all-ones mask and rejected a +// route it matches. That measured 178 spurious misses in 22.8M requests served +// across a rebuild loop, against 0 before the filter existed. +func (r *Route) buildPrefixFilter() { + r.prefix, r.prefixMask = computePrefixFilter(r) +} + +// computePrefixFilter derives a route's leading-byte filter without publishing +// it, so the two words can be installed in one assignment and the result can be +// recomputed and compared in tests. It returns the packed prefix word and the +// mask covering its known bytes. +// +//nolint:nonamedreturns // the pair is easier to read named than by position +func computePrefixFilter(r *Route) (word, mask uint64) { + return packConst(knownPrefix(r)) +} + +// knownPrefix returns the leading bytes every detection path the route +// matches begins with, as far as the first comparison match makes can tell: +// all of r.path for a route without parameters, the constant of the first +// segment otherwise, less a trailing '/' getMatch may drop, and nothing for a +// star route or a first segment that is itself a parameter. See +// buildPrefixFilter for why each case is what it is. +func knownPrefix(r *Route) string { + if r.star { + return "" + } + + prefix := r.path + if len(r.Params) > 0 { + segs := r.routeParser.segs + if len(segs) == 0 || segs[0].IsParam { + return "" + } + prefix = segs[0].Const + if segs[0].HasOptionalSlash { + prefix = prefix[:len(prefix)-1] + } + } + return prefix +} + +// prefixRejects reports whether the leading bytes of a detection path, packed +// by pathHeadWord, already rule this route out. +// +// This is the whole of the leading-byte filter, and it lives here rather than +// inline at the scan sites so there is one copy to change and one copy for the +// differential tests to guard. Six hand-written copies could drift from each +// other, and a test asserting against a seventh would not notice. +func (r *Route) prefixRejects(head uint64) bool { + return (head^r.prefix)&r.prefixMask != 0 +} + +// pathFingerprint hashes a path for the static-route filter. Equal strings +// hash equal, which is all a reject-only filter needs; length seeds the hash +// and the body is consumed a word at a time. The low bit is forced on because +// 0 marks a route the filter cannot speak for. +func pathFingerprint[S ~string | ~[]byte](s S) uint64 { + h := fingerprintBasis ^ uint64(len(s)) + i := 0 + for ; i+swar.WordLen <= len(s); i += swar.WordLen { + h = (h ^ swar.Load8(s, i)) * fingerprintPrime + h ^= h >> 31 + } + var tail uint64 + for ; i < len(s); i++ { + tail = tail<<8 | uint64(s[i]) + } + h = (h ^ tail) * fingerprintPrime + h ^= h >> 31 + return h | 1 +} + +// staticFingerprint returns a route's filter fingerprint, or 0 when its match +// is not the exact compare against r.path (root, star, parametric, use and +// mount routes). Test_Route_Fingerprint_MatchesMatch keeps it in step with match. +func staticFingerprint(r *Route) uint64 { + if r.use || r.mount || r.star || r.root || len(r.Params) > 0 { + return 0 + } + return pathFingerprint(r.path) +} + +func (r *Route) match(detectionPath, path string, params *[maxParams]string, pathSlashes int) bool { // root detectionPath check if r.root && len(detectionPath) == 1 && detectionPath[0] == '/' { return true @@ -195,8 +587,7 @@ func (r *Route) match(detectionPath, path string, params *[maxParams]string) boo // Does this route have parameters? if len(r.Params) > 0 { - // Match params using precomputed routeParser - return r.routeParser.getMatch(detectionPath, path, params, r.use) + return r.matchParams(detectionPath, path, params, pathSlashes) } // Middleware route? @@ -222,21 +613,79 @@ func (r *Route) match(detectionPath, path string, params *[maxParams]string) boo return false } +// skipSlashFilters is the slash count to pass match for it to skip its quick +// rejects on the route's slash bounds and probe, which is what 0 means to it: +// a real detection path holds at least one '/'. pathSlashCount returns it when +// no route consults the count, and a filtered bucket's scan passes it for a +// route whose scan head already applied both filters. +const skipSlashFilters = 0 + +// matchParams is the parametric branch of match, kept out of line so match +// stays small on the middleware and static-endpoint paths every request takes. +func (r *Route) matchParams(detectionPath, path string, params *[maxParams]string, pathSlashes int) bool { + // Quick-reject on the precomputed slash-count bounds before walking segments, + // unless pathSlashes is skipSlashFilters; prefix (use) routes may extend + // past the pattern, so only the lower bound applies to them. + p := &r.routeParser + if pathSlashes > 0 { + if pathSlashes < int(p.minSlashes) || (!r.use && p.maxBounded && pathSlashes > int(p.maxSlashes)) { + return false + } + // Then the probe constant, one masked compare; see constProbe. + if p.probe.mask != 0 && p.probe.rejects(detectionPath) { + return false + } + } + // Match params using precomputed routeParser + return p.getMatch(detectionPath, path, params, r.use) +} + func (app *App) next(c *DefaultCtx) (bool, error) { methodInt := c.methodInt treeHash := c.treePathHash detectionPath := utils.UnsafeString(c.detectionPath) path := utils.UnsafeString(c.path) - // Get stack length - tree, ok := app.treeStack[methodInt][treeHash] - if !ok { - tree = app.treeStack[methodInt][0] - } + // Get the route bucket for this method and tree path + tree, filter := app.treeIndex[methodInt].lookup(treeHash) + head := pathHeadWord(detectionPath) indexRoute := max(c.indexRoute+1, 0) + start := indexRoute + // Hoist loop invariants: route.match takes &c.values, so these would reload each iteration. + pathSlashes := c.pathSlashCount(app) + firstMatchIndex := c.firstMatchIndex + skipNonUse := c.shouldSkipNonUseRoutes + skipHasParamUse := app.skip.hasParamUse + // A filtered bucket is walked by scan.skip, which applies the slash count + // and the probe before the route is loaded, so match is then passed + // skipSlashFilters, which stands its own copies of those filters down. + // The scan is only set up for one: a small app routes a few ns faster + // without it on the stack. Its first inlineCandidates candidates are + // tested as an unfiltered bucket's are, and the scan is initialized only + // once the loop moves past them. + var scan *routeScan + scanReady := false + if filter != nil { + scan = &routeScan{} + } - // Loop over the route stack starting from previous index; - // the clamp above plus the len(tree) guard keep tree[indexRoute] bounds-check free + // Loop over the route stack starting from previous index for ; indexRoute < len(tree); indexRoute++ { + // Rule routes out before loading them where the bucket has a filter, + // else on the leading path bytes before touching the rest of the route + matchSlashes := pathSlashes + if scan != nil && indexRoute >= start+inlineCandidates { + if !scanReady { + scan.init(detectionPath, head, pathSlashes) + scanReady = true + } + if indexRoute = scan.skip(filter, indexRoute, start, &c.pathPrint); indexRoute >= len(tree) { + break + } + matchSlashes = skipSlashFilters + } else if tree[indexRoute].prefixRejects(head) { + continue + } + // Get *Route route := tree[indexRoute] @@ -244,12 +693,30 @@ func (app *App) next(c *DefaultCtx) (bool, error) { continue } + // Lookahead pre-resolved the endpoint: skip endpoints already ruled out; middleware still runs. + if firstMatchIndex >= 0 && !route.use { + if indexRoute < firstMatchIndex { + continue + } + // Reuse the lookahead's params unless param/wildcard middleware may have clobbered them. + if indexRoute == firstMatchIndex && !skipHasParamUse && !skipNonUse { + c.route = route + c.isMatched = true + if len(route.Handlers) > 0 { + c.indexHandler = 0 + c.indexRoute = indexRoute + return true, route.Handlers[0](c) + } + return true, nil + } + } + // Check if it matches the request path - if !route.match(detectionPath, path, &c.values) { + if !route.match(detectionPath, path, &c.values, matchSlashes) { continue } - if c.shouldSkipNonUseRoutes && !route.use { + if skipNonUse && !route.use { continue } @@ -282,17 +749,40 @@ func (app *App) next(c *DefaultCtx) (bool, error) { exists := false methods := app.config.RequestMethods + prune := app.skip.methodMaskValid + routeMethods := app.skip.routeMethods + // Where the scan meets its first filtered bucket here, it is set up in + // this, which is declared outside the loop so that it stays on the stack. + var lateScan routeScan for i := range methods { // Skip original method if methodInt == i { continue } + // Methods with no non-use route can never add an Allow entry. + if prune && routeMethods&(uint64(1)<= start+inlineCandidates { + if !scanReady { + scan.init(detectionPath, head, pathSlashes) + scanReady = true + } + if indexRoute = scan.skip(filter, indexRoute, start, &pathPrint); indexRoute >= len(tree) { + break + } + matchSlashes = skipSlashFilters + } else if tree[indexRoute].prefixRejects(head) { + continue + } + // Get *Route route := tree[indexRoute] @@ -345,11 +865,29 @@ func (app *App) nextCustom(c CustomCtx) (bool, error) { continue } + // Lookahead pre-resolved the endpoint: skip endpoints already ruled out; middleware still runs. + if firstMatchIndex >= 0 && !route.use { + if indexRoute < firstMatchIndex { + continue + } + // Reuse the lookahead's params unless param/wildcard middleware may have clobbered them. + if indexRoute == firstMatchIndex && !skipHasParamUse && !skipNonUse { + c.setRoute(route) + c.setMatched(true) + if len(route.Handlers) > 0 { + c.setIndexHandler(0) + c.setIndexRoute(indexRoute) + return true, route.Handlers[0](c) + } + return true, nil + } + } + // Check if it matches the request path - if !route.match(c.getDetectionPath(), c.Path(), c.getValues()) { + if !route.match(detectionPath, path, values, matchSlashes) { continue } - if c.getSkipNonUseRoutes() && !route.use { + if skipNonUse && !route.use { continue } @@ -381,17 +919,39 @@ func (app *App) nextCustom(c CustomCtx) (bool, error) { exists := false methods := app.config.RequestMethods + prune := app.skip.methodMaskValid + routeMethods := app.skip.routeMethods + // See next for lateScan. + var lateScan routeScan for i := range methods { // Skip original method if methodInt == i { continue } + // Methods with no non-use route can never add an Allow entry. + if prune && routeMethods&(uint64(1)< 1 { - prettyPath = utils.TrimRight(prettyPath, '/') - } +func (app *App) addPrefixToRoute(prefix string, route *Route, regexHandler any, customConstraints ...CustomConstraint) { + prefixedPath, prettyPath, cleanPath := normalizeRoutePattern(getGroupPath(prefix, route.Path), &app.config) route.Path = prefixedPath - route.path = RemoveEscapeChar(prettyPath) + route.path = cleanPath route.routeParser = parseRoute(prettyPath, regexHandler, customConstraints...) + // As in register: the constraints come from the pattern as written. + rawParser := parseRoute(prefixedPath, regexHandler, customConstraints...) + route.routeParser.adoptConstraints(&rawParser) + if app.config.StrictRouting { + route.routeParser.applyStrictRouting() + } + // A prefix can introduce parameters of its own — a sub-app mounted at + // "/v1/:version" is prefixing every one of its routes with one. Params + // decides whether the router matches a route by pattern or by string + // equality, so it has to be rebuilt along with the parser or the route + // stops matching entirely. Read from the unprettified path, as register + // does, so parameter names keep the case they were registered with. + if prettyPath == prefixedPath { + route.Params = route.routeParser.params + } else { + route.Params = parseRoute(prefixedPath, regexHandler, customConstraints...).params + } route.root = false route.star = false route.caseSensitive = app.config.CaseSensitive - - return route + route.unescapePath = app.config.UnescapePath + // buildTree recomputes this for every route, but this function rewrites the + // path and parser a filter is derived from, so refresh it here too rather + // than depend on a caller marking the routes refreshed. + route.buildPrefixFilter() } +// copyRoute clones a route, deliberately leaving group behind: a clone belongs +// to whichever app it is being placed in, and Name() would otherwise prefix it +// with the group name of the app it came from. Callers that do want the group — +// ensureAutoHeadRoutesLocked, which copies a route in place — assign it back. +// +// The omission is load-bearing for a mount placeholder, whose target app lives +// in group.app: carrying it over would let a clone of the placeholder expand +// the mounted app's handlers verbatim, which for a domain mount means serving +// them on every host. domainRouter.cloneRoutesForDomain expands the mount +// instead, so no placeholder is ever cloned. func (*App) copyRoute(route *Route) *Route { return &Route{ + // Shared with the registration this route came from, so a copy can + // still be found in another method's tree (see routeIndexInTree). + id: route.id, + latestID: route.latestID, + + // Leading-byte filter + prefix: route.prefix, + prefixMask: route.prefixMask, + // Router booleans use: route.use, mount: route.mount, @@ -505,6 +1133,7 @@ func (*App) copyRoute(route *Route) *Route { root: route.root, autoHead: route.autoHead, caseSensitive: route.caseSensitive, + unescapePath: route.unescapePath, // Path data path: route.path, @@ -520,19 +1149,8 @@ func (*App) copyRoute(route *Route) *Route { } func (app *App) normalizePath(path string) string { - if path == "" { - path = "/" - } - if path[0] != '/' { - path = "/" + path - } - if !app.config.CaseSensitive { - path = utilsstrings.ToLower(path) - } - if !app.config.StrictRouting && len(path) > 1 { - path = utils.TrimRight(path, '/') - } - return RemoveEscapeChar(path) + _, _, clean := normalizeRoutePattern(path, &app.config) + return clean } // RemoveRoute is used to remove a route from the stack by path. @@ -633,6 +1251,9 @@ func (app *App) pruneAutoHeadRouteLocked(path string) { } } +// routeIDs hands out the ids shared by the per-method copies of a registration. +var routeIDs atomic.Uint64 + func (app *App) register(methods []string, pathRaw string, group *Group, handlers ...Handler) { // A regular route requires at least one ctx handler if len(handlers) == 0 && group == nil { @@ -646,25 +1267,19 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler } // Precompute path normalization ONCE - if pathRaw == "" { - pathRaw = "/" - } - if pathRaw[0] != '/' { - pathRaw = "/" + pathRaw - } - pathPretty := pathRaw - if !app.config.CaseSensitive { - pathPretty = utilsstrings.ToLower(pathPretty) - } - if !app.config.StrictRouting && len(pathPretty) > 1 { - pathPretty = utils.TrimRight(pathPretty, '/') - } - pathClean := RemoveEscapeChar(pathPretty) + pathRaw, pathPretty, pathClean := normalizeRoutePattern(pathRaw, &app.config) parsedRaw := parseRoute(pathRaw, app.config.RegexHandler, app.customConstraints...) parsedPretty := parseRoute(pathPretty, app.config.RegexHandler, app.customConstraints...) + // The pretty pattern is matched against, but its constraints must come + // from the raw one (see routeParser.adoptConstraints). + parsedPretty.adoptConstraints(&parsedRaw) + if app.config.StrictRouting { + parsedPretty.applyStrictRouting() + } isMount := group != nil && group.app != app + routeID := routeIDs.Add(1) for _, method := range methods { method = utilsstrings.ToUpper(method) @@ -673,8 +1288,9 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler } isUse := method == methodUse - isStar := pathClean == "/*" - isRoot := pathClean == "/" + // Derived from the pattern with its escapes intact: "/\*" is a literal path. + isStar := pathPretty == "/*" + isRoot := pathPretty == "/" route := Route{ use: isUse, @@ -682,6 +1298,9 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler star: isStar, root: isRoot, caseSensitive: app.config.CaseSensitive, + unescapePath: app.config.UnescapePath, + id: routeID, + latestID: routeID, path: pathClean, routeParser: parsedPretty, @@ -692,6 +1311,7 @@ func (app *App) register(methods []string, pathRaw string, group *Group, handler Method: method, Handlers: handlers, } + route.buildPrefixFilter() // Increment global handler count atomic.AddUint32(&app.handlersCount, uint32(len(handlers))) //nolint:gosec // G115 - handler count is always small @@ -727,6 +1347,17 @@ func (app *App) addRoute(method string, route *Route) { if l > 0 && app.stack[m][l-1].Path == route.Path && route.use == app.stack[m][l-1].use && !route.mount && !app.stack[m][l-1].mount { preRoute := app.stack[m][l-1] preRoute.Handlers = append(preRoute.Handlers, route.Handlers...) + // The merged route now carries this registration's handlers, so Name has + // to reach it — and the routes the same Add merged into under the other + // methods — through the id they now share. id itself stays put: the + // per-method copies of the registration that created this route still + // hold it, and routeIndexInTree pairs them by it when a handler switches + // method mid-request. + preRoute.latestID = route.id + // Name prefixes with the group of the route it renames, which for this + // name is the group the merging registration was made through. + preRoute.group = route.group + route = preRoute } else { route.Method = method // Add route to the stack @@ -750,6 +1381,28 @@ func (app *App) ensureAutoHeadRoutes() { app.ensureAutoHeadRoutesLocked() } +// autoHeadKey identifies the route an automatic HEAD companion would collide +// with. +type autoHeadKey struct { + // owner is set only where routes are host-scoped, and is what keeps the + // HEAD route of one mounted app from standing in for another app's GET + owner *App + path string +} + +// autoHeadKey returns the key route is deduplicated under. Where an app's +// routes are host-scoped — the wrapper a domain mount builds — a HEAD route +// only covers the GET routes of the same mounted app: on a hostname that app's +// pattern rejects it declines, leaving a GET route of another one there without +// a companion to answer for it. +func (app *App) autoHeadKey(route *Route) autoHeadKey { + if !app.mountFields.hostScopedRoutes { + return autoHeadKey{path: route.path} + } + + return autoHeadKey{owner: app.routeOwner(route), path: route.path} +} + func (app *App) ensureAutoHeadRoutesLocked() { if app.config.DisableHeadAutoRegister { return @@ -761,16 +1414,32 @@ func (app *App) ensureAutoHeadRoutesLocked() { return } + // Nothing can need a new companion while no route has been registered since + // the last pass and the HEAD stack still holds the ones it produced, so the + // scan below is skipped rather than rebuilt on every RebuildTree call. + currentRouteID := routeIDs.Load() + if app.autoHeadRouteID == currentRouteID && app.autoHeadStackLen == len(app.stack[headIndex]) { + return + } + // Recorded on the normal exits only: a panicking OnRoute hook must not leave + // an aborted scan marked complete, which would keep every HEAD request that + // needed a companion at 405 for the lifetime of the process. + recordScan := func() { + app.autoHeadRouteID = routeIDs.Load() + app.autoHeadStackLen = len(app.stack[headIndex]) + } + headStack := app.stack[headIndex] - existing := make(map[string]struct{}, len(headStack)) + existing := make(map[autoHeadKey]struct{}, len(headStack)) for _, route := range headStack { if route.mount || route.use { continue } - existing[route.path] = struct{}{} + existing[app.autoHeadKey(route)] = struct{}{} } if len(app.stack[getIndex]) == 0 { + recordScan() return } @@ -780,7 +1449,10 @@ func (app *App) ensureAutoHeadRoutesLocked() { if route.mount || route.use { continue } - if _, ok := existing[route.path]; ok { + if _, ok := existing[app.autoHeadKey(route)]; ok { + continue + } + if app.skipsAutoHeadFor(route) { continue } @@ -788,12 +1460,19 @@ func (app *App) ensureAutoHeadRoutesLocked() { headRoute.group = route.group headRoute.Method = MethodHead headRoute.autoHead = true + // The synthesized route belongs to whichever app the GET route came + // from, so a HEAD request resolves the same config a GET one does, and + // an app re-parsing it later holds it to the same constraints. + if owner := app.routeOwner(route); owner != nil { + app.markRouteOwner(headRoute, owner) + } + app.markRouteConstraints(headRoute, app.mountFields.routeConstraints[route]) // Fasthttp automatically omits response bodies when transmitting // HEAD responses, so the copied GET handler stack can execute // unchanged while still producing an empty body on the wire. headStack = append(headStack, headRoute) - existing[route.path] = struct{}{} + existing[app.autoHeadKey(route)] = struct{}{} app.hasRoutesRefreshed = true added = true @@ -808,6 +1487,7 @@ func (app *App) ensureAutoHeadRoutesLocked() { if added { app.stack[headIndex] = headStack } + recordScan() } // RebuildTree rebuilds the prefix tree from the previously registered routes. @@ -822,9 +1502,27 @@ func (app *App) RebuildTree() *App { app.mutex.Lock() defer app.mutex.Unlock() + // Routes registered since startup get their automatic HEAD companions here. + app.ensureAutoHeadRoutesLocked() + return app.buildTree() } +// routeIndexInTree returns the position of route in another method's tree +// bucket, or current when it is not there; copies are told apart by their shared id. +func (app *App) routeIndexInTree(methodInt, treeHash int, route *Route, current int) int { + if route == nil || methodInt < 0 || methodInt >= len(app.treeIndex) { + return current + } + candidates, _ := app.treeIndex[methodInt].lookup(treeHash) + for i, candidate := range candidates { + if candidate.id == route.id { + return i + } + } + return current +} + // buildTree build the prefix tree from the previously registered routes func (app *App) buildTree() *App { // If routes haven't been refreshed, nothing to do @@ -832,16 +1530,33 @@ func (app *App) buildTree() *App { return app } - // 1) First loop: determine all possible 3-char prefixes ("treePaths") for each method + // 1) First loop: determine all possible 3-char prefixes ("treePaths") for each method. + // The scratch below is shared by the methods, cleared between them: a + // method's routes share a few prefixes between them, so a map sized for + // the routes rather than the prefixes was most of what a rebuild allocated. + hasParamRoutes := false + var treePaths []int + prefixCounts := make(map[int]int) for method := range app.config.RequestMethods { routes := app.stack[method] - treePaths := make([]int, len(routes)) + treePaths = slices.Grow(treePaths[:0], len(routes))[:len(routes)] + clear(treePaths) + clear(prefixCounts) globalCount := 0 - prefixCounts := make(map[int]int, len(routes)) for i, route := range routes { - if len(route.routeParser.segs) > 0 && len(route.routeParser.segs[0].Const) >= maxDetectionPaths { + // The leading-byte filter is deliberately not rebuilt here; see + // buildPrefixFilter. These routes are live for in-flight requests. + + // Star routes resolve before the slash-count quick-reject in + // Route.match, so only non-star parametric routes consult it. + if len(route.Params) > 0 && !route.star { + hasParamRoutes = true + } + + if len(route.routeParser.segs) > 0 && len(route.routeParser.segs[0].Const) >= maxDetectionPaths && + !dropsOptionalSlashBelowTreeHash(route.routeParser.segs[0]) { treePaths[i] = int(route.routeParser.segs[0].Const[0])<<16 | int(route.routeParser.segs[0].Const[1])<<8 | int(route.routeParser.segs[0].Const[2]) @@ -855,11 +1570,28 @@ func (app *App) buildTree() *App { prefixCounts[treePaths[i]]++ } - prevBuckets := app.treeStack[method] + // Carve this build's buckets out of one allocation. The arena is fresh + // per build, so a published bucket is never written through; a bucket + // per make() would give the same guarantee, but one allocation keeps a + // rebuild's alloc count flat as routes are added. + // + // Each bucket is a three-index slice whose cap is exactly what the + // append loop below puts in it, so a bucket cannot reach its + // neighbor: appending past that cap reallocates instead of writing + // into the next window. + total := globalCount + for _, count := range prefixCounts { + total += count + globalCount + } + arena := make([]*Route, total) + tsMap := make(map[int][]*Route, len(prefixCounts)+1) - tsMap[0] = reuseRouteBucket(prevBuckets, 0, globalCount) + tsMap[0] = arena[0:0:globalCount] + off := globalCount for treePath, count := range prefixCounts { - tsMap[treePath] = reuseRouteBucket(prevBuckets, treePath, count+globalCount) + end := off + count + globalCount + tsMap[treePath] = arena[off:off:end] + off = end } for i, route := range routes { @@ -876,16 +1608,27 @@ func (app *App) buildTree() *App { } app.treeStack[method] = tsMap + app.treeIndex[method] = buildRouteTree(tsMap) } + app.hasParamRoutes = hasParamRoutes + + app.buildSkipIndexes() // reset the flag and return app.hasRoutesRefreshed = false return app } -func reuseRouteBucket(prev map[int][]*Route, key, capHint int) []*Route { - if bucket, ok := prev[key]; ok && cap(bucket) >= capHint { - return bucket[:0] - } - return make([]*Route, 0, capHint) +// dropsOptionalSlashBelowTreeHash reports whether a route's leading constant +// segment can match a detection path too short to carry a tree hash. +// +// getMatch lets a segment with HasOptionalSlash match one byte less than its +// Const (the trailing '/' is optional), so "/a/" also matches "/a". A +// detection path shorter than maxDetectionPaths always hashes to 0, so a route +// bucketed under the hash of its full Const would be invisible to that +// request: next() would scan bucket 0 and never see it. Consts longer than +// maxDetectionPaths are unaffected — dropping the final '/' leaves the first +// three bytes, and therefore the hash, unchanged. +func dropsOptionalSlashBelowTreeHash(seg *routeSegment) bool { + return seg.HasOptionalSlash && len(seg.Const) == maxDetectionPaths } diff --git a/src/vendor/github.com/gofiber/fiber/v3/router_filter.go b/src/vendor/github.com/gofiber/fiber/v3/router_filter.go new file mode 100644 index 00000000..c010291b --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/router_filter.go @@ -0,0 +1,303 @@ +// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️ +// 🤖 GitHub Repository: https://github.com/gofiber/fiber +// 📌 API Documentation: https://docs.gofiber.io + +package fiber + +import ( + "math" + "math/bits" + "strings" + + "github.com/gofiber/utils/v2/swar" +) + +// bucketFilter lets the scan rule out a bucket's routes before loading them. +// Only a bucket of filterMinBucket routes or more carries one. +type bucketFilter struct { + // heads is parallel to the bucket: each route's scanHead + heads []scanHead + // prints is parallel to the bucket: each static route's fingerprint, 0 for + // a route the fingerprint cannot speak for. nil below fingerprintMinBucket + // static routes. + prints []uint64 + // maxLen is the longest static path in the bucket; a longer request + // matches none of them, so the scan need not hash it + maxLen int +} + +// newBucketFilter builds a bucket's filter, or returns nil when the bucket has +// fewer than filterMinBucket routes. Built from the finished bucket so the +// tree's pointer swap publishes routes and filter together. +func newBucketFilter(routes []*Route) *bucketFilter { + if len(routes) < filterMinBucket { + return nil + } + f := &bucketFilter{heads: make([]scanHead, len(routes))} + static := 0 + for i, route := range routes { + f.heads[i].init(route) + if staticFingerprint(route) != 0 { + static++ + } + } + if static < fingerprintMinBucket { + return f + } + + f.prints = make([]uint64, len(routes)) + for i, route := range routes { + f.prints[i] = staticFingerprint(route) + if f.prints[i] != 0 { + f.maxLen = max(f.maxLen, len(route.path)) + } + } + return f +} + +// scanHead is what a route scan needs to rule a candidate out without loading +// its Route: a leading-byte filter, a slash-count filter and the constant +// probe. A filtered bucket holds one per route at the route's index, so a +// candidate they reject costs a sequential read of its head instead of a +// pointer chase into a Route, which a large route set keeps out of L1: the +// chase was most of what a rejected candidate cost. Like every filter here it +// can only reject what Route.match would. +// +// The leading-byte filter here reads two words where Route's reads one, since +// the routes sharing a bucket tend to share their first word too: every route +// of an "/api/v1/" API does. A head costs a call to skip to get past, which a +// route that got by one word paid for in full before match turned it down. +// +// Heads are derived from their routes when the tree is built. A route's +// filters are final by then (see buildPrefixFilter), and a head is published +// together with its route by the tree's pointer swap, so the two cannot +// disagree. +type scanHead struct { + // prefix and prefixMask filter on the first word of knownPrefix, as the + // route's own prefix and prefixMask do; prefix2 and prefixMask2 on the + // second, when there is one + prefix uint64 + prefixMask uint64 + prefix2 uint64 + prefixMask2 uint64 + // probeWord is what the route's constant probe compares, when match + // would consult one; see probe + probeWord uint64 + // slashMask has bit n set when a detection path holding n '/' bytes can + // match, bit maxSlashBit standing for that many or more; see init + slashMask uint32 + // probeFrom and probeSkip locate the probe as constProbe's from and skip + // do, and probeLen is how many bytes of probeWord it compares, 0 when the + // head has no probe. They are narrow so that a head takes 48 bytes, since + // a filtered bucket holds one per route. A probe they cannot hold, which + // takes a leading constant over 64 KiB or more than 255 parameters before + // the probe, is not checked before the full match: match skips its own + // copy in a filtered bucket (see skipSlashFilters), and getMatch compares + // the same constant, so such a route only loses the quick reject. + probeFrom uint16 + probeSkip uint8 + probeLen uint8 +} + +// maxSlashBit is the highest bit of a scanHead's slashMask, which stands for +// that many '/' bytes or more. +const maxSlashBit = 31 + +// init fills h, a zero scanHead, with the head of r. newBucketFilter fills +// its heads in place with it, since copying each one out of a constructor was +// a third of what building a filter cost. The first prefix word is the route's +// own leading-byte filter, which buildPrefixFilter computed when the route was +// registered. +// +// The slash counts a route can match become a bitmask, so the scan tests them +// with one AND. A route without parameters is compared against r.path, in full +// or as a prefix (use), so it takes that path's count, or any count from it +// up. A route with parameters gets the bounds routeParser.computeSlashBounds +// found and matchParams checks: a prefix (use) route only the lower one. Star +// and root routes are answered before either comparison, so they keep every +// bit, as does every route for bit 0, which a scan uses for a count it did not +// compute. The probe is taken where matchParams would consult it. +func (h *scanHead) init(r *Route) { + h.slashMask = ^uint32(0) + h.prefix, h.prefixMask = r.prefix, r.prefixMask + if prefix := knownPrefix(r); len(prefix) > swar.WordLen { + h.prefix2, h.prefixMask2 = packConst(prefix[swar.WordLen:]) + } + switch { + case r.star || r.root: + return + case len(r.Params) == 0: + n := min(strings.Count(r.path, string(slashDelimiter)), maxSlashBit) + if r.use { + h.slashMask <<= n + } else { + h.slashMask = uint32(1) << n + } + default: + p := &r.routeParser + // Every count from the minimum up, capped at maxSlashBit, which a + // count at or past the minimum always sets. + h.slashMask <<= min(max(p.minSlashes, 0), maxSlashBit) + if !r.use && p.maxBounded && p.maxSlashes < maxSlashBit { + // ...and none past the maximum. A maximum below the minimum + // leaves no count at all, apart from bit 0 below. + h.slashMask &= uint32(1)<<(max(p.maxSlashes, -1)+1) - 1 + } + h.setProbe(p.probe) + } + h.slashMask |= 1 +} + +// setProbe stores p, a route's constant probe, in h, unless it has none or h's +// narrow fields cannot hold it. A probe's mask covers the leading lanes of its +// word (see packConst), so its length stands in for it. +func (h *scanHead) setProbe(p constProbe) { + n := bits.Len64(p.mask) / 8 + // A probe lies past the route's leading constant, so from is positive, + // which also keeps its memo key off the 0 that stands for none. + if n == 0 || p.mask != lanesMask(n) || p.from <= 0 || p.from > math.MaxUint16 || p.skip < 0 || p.skip > math.MaxUint8 { + return + } + h.probeWord = p.word + h.probeFrom = uint16(p.from) + h.probeSkip = uint8(p.skip) + h.probeLen = uint8(n) //nolint:gosec // G115 - at most a word's lanes +} + +// probe returns the constant probe h holds, which h.probeLen says it does. +func (h *scanHead) probe() constProbe { + return constProbe{word: h.probeWord, mask: lanesMask(int(h.probeLen)), from: int32(h.probeFrom), skip: int32(h.probeSkip)} +} + +// headRejects is constProbe.rejects for the constant probe h holds, which +// h.probeLen says it does, searching for the slash only when the probe the +// memo last served read another one: the key is the probe's from and its +// skip, since probes that share a from can still differ in the slash they +// read. The probe is only assembled when the memo has to search. +// detectionPath must be the same on every call. +func (m *probeMemo) headRejects(h *scanHead, detectionPath string) bool { + if k := uint64(h.probeFrom)<<32 | uint64(h.probeSkip); k != m.key { + p := h.probe() + m.word, m.ok = p.locate(detectionPath) + m.key = k + } + return !m.ok || m.word&lanesMask(int(h.probeLen)) != h.probeWord +} + +// lanesMask covers the first n lanes of a word, 0 <= n <= 8. +func lanesMask(n int) uint64 { + return ^uint64(0) >> (64 - 8*uint(n)) +} + +// slashBit is the bit a detection path's slash count selects in a scanHead's +// slashMask: bit n for n '/' bytes, bit maxSlashBit for that many or more, and +// bit 0 for a count of 0, which is how pathSlashCount reports one it did not +// compute and which every head accepts. +func slashBit(pathSlashes int) uint32 { + return uint32(1) << min(pathSlashes, maxSlashBit) +} + +// rejects reports whether the leading-byte filter or the slash-count filter +// rules the head's route out for a detection path whose first two words are +// head and head2, packed by pathHeadWord, and whose slash count selects slash +// (see slashBit). The masked compares are combined without a branch. +func (h *scanHead) rejects(head, head2 uint64, slash uint32) bool { + return (head^h.prefix)&h.prefixMask|(head2^h.prefix2)&h.prefixMask2|uint64(slash&^h.slashMask) != 0 +} + +// routeScan is the request's side of a scan through filtered buckets: what +// their filters compare against. A scan sets it up when it first has to walk +// a filtered bucket past the candidates it tests inline (inlineCandidates), +// and skip then walks such a bucket to the next route the filter lets through. +type routeScan struct { + detectionPath string + // head and head2 are the path's first two words, packed by pathHeadWord + head uint64 + head2 uint64 + // slash is slashBit of the path's slash count + slash uint32 + // probes shares the constant probes' slash search among candidates + probes probeMemo +} + +// init sets up s, a zero routeScan, for detectionPath, whose leading bytes +// pathHeadWord packed into head and which holds pathSlashes '/' bytes (0 when +// the count was not computed). It fills s in place, since copying the struct +// out of a constructor stalled. +func (s *routeScan) init(detectionPath string, head uint64, pathSlashes int) { + s.detectionPath = detectionPath + s.head = head + if n := len(detectionPath); n > swar.WordLen { + // The second word as pathHeadWord packs it: a path under two words + // is loaded from its end, overlapping the first word, and shifted + // down so that its byte 8 lands in lane 0 and the lanes past its end + // are zero: one load in place of a byte loop or a call. + off := min(n, 2*swar.WordLen) - swar.WordLen + s.head2 = swar.Load8(detectionPath, off) >> (8 * (swar.WordLen - off)) + } + s.slash = slashBit(pathSlashes) +} + +// skip returns the index of the first route at or after i that f, the filter +// of the bucket being scanned, does not rule out, or the bucket's length when +// none is left. first is where the scan started: the fingerprints are not +// consulted there, so a hit on the first candidate never hashes the path. +// pathPrint holds the path's fingerprint, 0 until a scan first needs it, when +// skip stores it there; DefaultCtx keeps it across the scans of a request. It +// is a parameter rather than a field so that a caller's local does not escape. +func (s *routeScan) skip(f *bucketFilter, i, first int, pathPrint *uint64) int { + heads := f.heads + // The request fingerprint: fingerprintNone when no static route in the + // bucket is as long as the path, else *pathPrint, hashed the first time a + // scan needs it. + prints := f.prints + want := *pathPrint + if len(s.detectionPath) > f.maxLen { + want = fingerprintNone + } + for ; i < len(heads); i++ { + // Reject static routes by fingerprint first. prints is nil below + // fingerprintMinBucket static routes, and 0 marks a route it cannot + // judge. + if i > first && i < len(prints) { + if want == 0 { + want = pathFingerprint(s.detectionPath) + *pathPrint = want + } + for i < len(prints) && prints[i] != 0 && prints[i] != want { + i++ + } + if i >= len(heads) { + break + } + } + if h := &heads[i]; h.rejects(s.head, s.head2, s.slash) || + h.probeLen != 0 && s.probes.headRejects(h, s.detectionPath) { + continue + } + return i + } + return len(heads) +} + +// endpoint walks tree, a bucket that f filters, for the first endpoint (a +// non-use route) matching the request, as the scans deciding between 404 and +// 405 walk the other methods' buckets. It returns the endpoint's index and +// true, with its parameters written to values, or the bucket's last index and +// false when there is none, which is where those scans leave the context. +// pathPrint is as for skip. +func (s *routeScan) endpoint(tree []*Route, f *bucketFilter, path string, values *[maxParams]string, pathPrint *uint64) (int, bool) { + for i := 0; ; i++ { + if i = s.skip(f, i, 0, pathPrint); i >= len(tree) { + return len(tree) - 1, false + } + route := tree[i] + if route.use { + continue + } + // skip applied the slash count and the probe + if route.match(s.detectionPath, path, values, skipSlashFilters) { + return i, true + } + } +} diff --git a/src/vendor/github.com/gofiber/fiber/v3/router_skip.go b/src/vendor/github.com/gofiber/fiber/v3/router_skip.go new file mode 100644 index 00000000..e86a1578 --- /dev/null +++ b/src/vendor/github.com/gofiber/fiber/v3/router_skip.go @@ -0,0 +1,278 @@ +// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️ +// 🤖 GitHub Repository: https://github.com/gofiber/fiber +// 📌 API Documentation: https://docs.gofiber.io + +package fiber + +import ( + "strings" +) + +// skipRouteIndex holds precomputed unmatched-route indexes, rebuilt by buildSkipIndexes with the route tree. +type skipRouteIndex struct { + // staticMethods maps a static endpoint's path to a method bitmask; nil unless SkipUnmatchedRoutes is on + staticMethods map[string]uint64 + // buckets holds the per-tree-bucket lookahead state, one entry per treeStack bucket key (union across methods) + buckets map[int]*skipBucket + // zeroBucket serves tree hashes with no bucket at all, mirroring next()'s treeStack miss + zeroBucket *skipBucket + // routeMethods is a method bitmask with at least one non-use route; only valid when methodMaskValid + routeMethods uint64 + // staticSlashes has a bit per '/' count present among staticMethods' keys, so + // resolveSkip can skip hashing the path when no static route could match it. + // Counts >= 64 set no bit; requests that long take the unconditional path. + staticSlashes uint64 + // enabled gates the fast path: SkipUnmatchedRoutes is on and middleware is registered + // (without middleware next() already answers 404/405 cheaply) + enabled bool + // hasParamUse is true when any param/wildcard middleware exists; when false next() can reuse the lookahead's params + hasParamUse bool + // methodMaskValid is true when routeMethods is trustworthy (len(RequestMethods) <= 64) + methodMaskValid bool +} + +// skipBucket holds one tree bucket's param/root/star candidates per method, with the +// bucket-0 fallback materialized at build time so a lookup never needs a second map access. +type skipBucket struct { + // cands is indexed by method int + cands [][]indexedRoute + // paramMask has a bit per method with at least one candidate in cands + paramMask uint64 +} + +// indexedRoute pairs a candidate route with its position in its tree bucket. +type indexedRoute struct { + route *Route + idx int +} + +// skipDecision is the outcome kind of the SkipUnmatchedRoutes lookahead. +type skipDecision int + +const ( + skipRunChain skipDecision = iota // run the normal chain + skipNotFound // 404 without running the chain + skipNotAllowed // 405; allowMask holds the methods +) + +// skipResult is the outcome of the SkipUnmatchedRoutes lookahead. +type skipResult struct { + decision skipDecision + allowMask uint64 // methods for the Allow header (skipNotAllowed only) + matchIndex int // pre-resolved endpoint index for next()/nextCustom(), or -1 +} + +// buildSkipIndexes rebuilds app.skip from the route tree; called from buildTree. +func (app *App) buildSkipIndexes() { + idx := skipRouteIndex{} + + // Masks are 64-bit; with more methods leave everything disabled, next() answers as usual. + idx.methodMaskValid = len(app.config.RequestMethods) <= 64 + if !idx.methodMaskValid { + app.skip = idx + return + } + + // 405-fallback prune mask; maintained even when SkipUnmatchedRoutes is off. + for method := range app.config.RequestMethods { + for _, route := range app.stack[method] { + if !route.use { + idx.routeMethods |= uint64(1) << method + break + } + } + } + + if app.config.SkipUnmatchedRoutes { + idx.buildLookahead(app) + } + + app.skip = idx +} + +// buildLookahead fills the SkipUnmatchedRoutes lookahead indexes. +func (idx *skipRouteIndex) buildLookahead(app *App) { + nMethods := len(app.config.RequestMethods) + static := make(map[string]uint64) + buckets := make(map[int]*skipBucket) + hasUse := false + hasParamUse := false + + getBucket := func(treeHash int) *skipBucket { + b := buckets[treeHash] + if b == nil { + b = &skipBucket{cands: make([][]indexedRoute, nMethods)} + buckets[treeHash] = b + } + return b + } + + for method := range app.config.RequestMethods { + bit := uint64(1) << method + + // Static endpoints match by exact compare against route.path, so keying by route.path is exact. + for _, route := range app.stack[method] { + if route.use { + hasUse = true + // param/wildcard middleware clobbers c.values on match + if route.star || len(route.Params) > 0 { + hasParamUse = true + } + continue + } + if route.mount || route.star || route.root || len(route.Params) > 0 { + continue + } + static[route.path] |= bit + // These routes match by exact string compare, so a candidate + // detection path necessarily carries the same number of '/'. + if n := strings.Count(route.path, "/"); n < 64 { + idx.staticSlashes |= uint64(1) << n + } + } + + // Candidates come from the final buckets (post bucket-0 replication) so idx lines up with next()'s scan. + for treeHash, bucket := range app.treeStack[method] { + sb := getBucket(treeHash) + for i, route := range bucket { + if route.use || route.mount { + continue + } + if route.root || route.star || len(route.Params) > 0 { + sb.cands[method] = append(sb.cands[method], indexedRoute{route: route, idx: i}) + sb.paramMask |= bit + } + } + } + } + + zero := buckets[0] + if zero == nil { + zero = &skipBucket{cands: make([][]indexedRoute, nMethods)} + buckets[0] = zero + } + + // Materialize the per-method bucket-0 fallback: a method without a treeStack + // bucket at this hash scans its bucket 0 in next(), so mirror that here. + for treeHash, sb := range buckets { + if treeHash == 0 { + continue + } + for method := range app.config.RequestMethods { + if _, ok := app.treeStack[method][treeHash]; ok { + continue + } + sb.cands[method] = zero.cands[method] + if len(zero.cands[method]) > 0 { + sb.paramMask |= uint64(1) << method + } + } + } + + idx.staticMethods = static + idx.buckets = buckets + idx.zeroBucket = zero + idx.enabled = hasUse + idx.hasParamUse = hasParamUse +} + +// resolveSkip decides 404/405/run-chain. values is scratch: param/wildcard +// middleware may overwrite it before the endpoint runs, so next() re-matches then. +func (app *App) resolveSkip(methodInt, treeHash, pathSlashes int, detectionPath, path string, values *[maxParams]string) skipResult { + skip := &app.skip + methodBit := uint64(1) << methodInt + + // Hashing detectionPath for the static index costs a pass over the whole + // path, and static endpoints match by exact compare, so a differing '/' + // count rules them all out before the map is touched. pathSlashes 0 means + // the count was never computed, which stands the filter down. + var staticMask uint64 + if pathSlashes == 0 || pathSlashes >= 64 || skip.staticSlashes&(uint64(1)< [!NOTE] > Because primitive types like int, float, bool, unint and their variants have their default (or zero) values set by Golang, it is not possible to distinguish them from a provided value when decoding/encoding form values. In this case, the value provided by the `default` option tag will be always applied. For example, let's assume that the value submitted in the form for `balance` is `0.0` then the default of `10.0` will be applied, even if `0.0` is part of the form data for the `balance` field. In such cases, it is highly recommended to use pointers to allow schema to distinguish between when a form field has no provided value and when a form has a value equal to the corresponding default set by Golang for a particular type. If the type of the `Balance` field above is changed to `*float64`, then the zero value would be `nil`. In this case, if the form data value for `balance` is `0.0`, then the default will not be applied. + ## ☕ Supporters Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, hosting, and serverless infrastructure. If you want to support Fiber, please become a [GitHub Sponsor](https://github.com/sponsors/gofiber). +

+ + + + CodeRabbit + + +

+

+ + Blacksmith + +

+

+ Tool Sponsors - supporting Fiber with free IDE licenses and AI credits +

+

+ JetBrains +   + OpenAI +   + Anthropic +

+ ### 📅 Monthly Sponsors - +
🔥 Fiber Guardian@coderabbitai
☕ Fiber Supporter@NdoleStudio @petercool
☕ Fiber Supporter@NdoleStudio
🪴 Fiber Friend@simonheisstpeter
@@ -126,8 +164,10 @@ Fiber is an open-source project that runs on donations to pay the bills, e.g., o +
🚀 Fiber Hero@thnxdev
🪴 Fiber Friend@Gl1tchedPixzl
+ ## License diff --git a/src/vendor/github.com/gofiber/schema/cache.go b/src/vendor/github.com/gofiber/schema/cache.go index 82866999..4ac6a794 100644 --- a/src/vendor/github.com/gofiber/schema/cache.go +++ b/src/vendor/github.com/gofiber/schema/cache.go @@ -11,6 +11,7 @@ import ( "strings" "sync" "sync/atomic" + "unsafe" utils "github.com/gofiber/utils/v2" utilstrings "github.com/gofiber/utils/v2/strings" @@ -19,6 +20,22 @@ import ( const maxParserIndex = 1000 +// maxDirectKeyLen bounds the stack buffers keys are case-folded or assembled +// in for a map probe; longer keys take a path that allocates. +const maxDirectKeyLen = 64 + +// maxDirectPaths caps the nested entries precomputed per struct type: deep +// fan-out nesting multiplies dotted chains, and without a cap build time and +// retained memory grow exponentially. Excess keys use the generic parser. +const maxDirectPaths = 512 + +// maxPathReserve caps the hop and part slices the parser reserves from a +// path's separator count. That count comes from a key nothing has validated +// yet, so an unbounded reservation lets a key of mostly separators claim +// megabytes before its first segment is rejected. Appending past the +// reservation still works, and real paths are a few segments deep. +const maxPathReserve = 16 + var ( errInvalidPath = errors.New("schema: invalid path") errIndexTooLarge = errors.New("schema: index exceeds parser limit") @@ -47,13 +64,31 @@ type cache struct { // returns observes the new configuration even if a racing build stored // a stale entry after the clear. gen atomic.Uint64 + // slots is a direct-mapped cache in front of m, indexed by the address + // of the type's descriptor: a hit costs a few loads and a compare, where + // m's interface-keyed hash was the largest part of what Decode paid to + // find a type's metadata. Entries are m's own, generation included, so + // a collision or a stale entry only falls through to m. + slots [typeCacheSlots]atomic.Pointer[cacheEntry] } -// cacheEntry tags a structInfo with the configuration generation it was -// built under; entries are stored by pointer in c.m (matching the encoder's -// encPlan pattern). +// typeCacheSlots is the size of cache.slots, a power of two so a slot is a +// mask rather than a division. +const typeCacheSlots = 32 + +// typeSlot returns the cache.slots index of t: bits of the address of its +// type descriptor, the data word of the reflect.Type interface, read +// directly since reflect.ValueOf(t).Pointer() costs several times as much. +func typeSlot(t reflect.Type) uintptr { + return (*[2]uintptr)(unsafe.Pointer(&t))[1] >> 4 & (typeCacheSlots - 1) +} + +// cacheEntry tags a structInfo with its type and the configuration +// generation it was built under; entries are stored by pointer in c.m +// (matching the encoder's encPlan pattern) and in c.slots. type cacheEntry struct { info *structInfo + typ reflect.Type gen uint64 } @@ -88,16 +123,36 @@ func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) { // parsed-path cache lives on that structInfo, keyed by the plain path // string, which hashes much cheaper than a composite key. func (c *cache) parsePathInfo(p string, rootInfo *structInfo) ([]pathPart, error) { - if cached, ok := rootInfo.paths.Load(p); ok { - return cached.([]pathPart), nil + // Fast path: probe the precomputed direct paths, whose index matches the + // key case-insensitively in one probe, as the fields do. + if rootInfo.directIndex.len > 0 { + if parts, ok := rootInfo.directIndex.lookup(p); ok { + return parts, nil + } + // Every field a bare alias can reach is in the direct paths + // (buildDirectPaths adds the flat aliases before the cap can + // truncate anything), and the probe matched the key folded, so a + // dotless miss names no field. + if strings.IndexByte(p, '.') < 0 { + return nil, errInvalidPath + } + } + + if cached, ok := rootInfo.paths.load(p); ok { + return cached, nil } struc := rootInfo var t reflect.Type var field *fieldInfo var index64 int64 - var parts []pathPart - var hops []pathHop + // A path yields at most one hop and one part per segment. The hops of + // every part share one backing array, cut into capped slices as the + // parts are emitted. + segments := min(strings.Count(p, ".")+1, maxPathReserve) + parts := make([]pathPart, 0, segments) + hopBuf := make([]pathHop, 0, segments) + hopStart := 0 for keyStart := 0; ; { keyEnd, segment, err := nextPathSegment(p, keyStart) if err != nil { @@ -109,8 +164,8 @@ func (c *cache) parsePathInfo(p string, rootInfo *structInfo) ([]pathPart, error // Valid field. Append the hop; the field's index chain was resolved // when the structInfo was built, so the decoder walks plain indices // instead of repeating FieldByName lookups on every Decode call. - hops = append(hops, pathHop{index: field.index, ensure: struc.anonymousPtrFields}) - if field.isSliceOfStructs && !field.isMultipart && (!field.unmarshalerInfo.IsValid || (field.unmarshalerInfo.IsValid && field.unmarshalerInfo.IsSliceElement)) { + hopBuf = append(hopBuf, pathHop{index: field.index, ensure: struc.anonymousPtrFields}) + if field.takesIndex() { // Parse a special case: slices of structs. // i+1 must be the slice index. // @@ -132,12 +187,14 @@ func (c *cache) parsePathInfo(p string, rootInfo *structInfo) ([]pathPart, error if index64 > maxParserIndex { return nil, errIndexTooLarge } + hops := hopBuf[hopStart:len(hopBuf):len(hopBuf)] + hopStart = len(hopBuf) parts = append(parts, pathPart{ - hops: hops, - field: field, - index: int(index64), + hops: hops, + field: field, + index: int(index64), + soleIndex: soleHopIndex(hops), }) - hops = nil // Get the next struct type, dropping ptrs. if field.typ.Kind() == reflect.Ptr { @@ -171,19 +228,120 @@ func (c *cache) parsePathInfo(p string, rootInfo *structInfo) ([]pathPart, error } // Add the remaining. A part without hops means the path terminated at a // slice index ("a.0"), so the decoder receives a slice element there. + hops := hopBuf[hopStart:len(hopBuf):len(hopBuf)] parts = append(parts, pathPart{ - hops: hops, - field: field, - index: -1, - elem: len(hops) == 0, + hops: hops, + field: field, + index: -1, + soleIndex: soleHopIndex(hops), + elem: len(hops) == 0, }) // Detach the key: callers may pass strings aliasing reused request buffers. - if cached, loaded := rootInfo.paths.LoadOrStore(strings.Clone(p), parts); loaded { - return cached.([]pathPart), nil + cached, _ := rootInfo.paths.loadOrStore(strings.Clone(p), parts) + return cached, nil +} + +// maxFastPaths bounds pathCache's copy-on-write map: each publish copies the +// whole map, so past this many paths further entries spill instead. Real +// structs stay well inside it. +const maxFastPaths = 512 + +// pathCache caches parsed paths for one struct type, keyed by the raw source +// key. Lookups run against a plain string-keyed map published atomically — +// sync.Map's interface keys cost a type hash and a trie walk, and +// parsePathInfo probes once per source key. Writes copy the map under the +// lock, so a reader only ever sees a complete one. +type pathCache struct { + fast atomic.Pointer[map[string][]pathPart] + // spill holds paths seen after fast was sealed, so a key space larger + // than maxFastPaths keeps its cache. + spill sync.Map // map[string][]pathPart + mu sync.Mutex + sealed atomic.Bool +} + +func (c *pathCache) load(key string) ([]pathPart, bool) { + if m := c.fast.Load(); m != nil { + if parts, ok := (*m)[key]; ok { + return parts, true + } + } + // spill only ever receives entries once fast is sealed. + if c.sealed.Load() { + if v, ok := c.spill.Load(key); ok { + return v.([]pathPart), true + } } + return nil, false +} - return parts, nil +// loadOrStore caches parts under key, or returns what a concurrent call +// cached there first. +func (c *pathCache) loadOrStore(key string, parts []pathPart) ([]pathPart, bool) { + if !c.sealed.Load() { + c.mu.Lock() + old := c.fast.Load() + if old != nil { + if existing, ok := (*old)[key]; ok { + c.mu.Unlock() + return existing, true + } + } + if old == nil || len(*old) < maxFastPaths { + var next map[string][]pathPart + if old == nil { + next = make(map[string][]pathPart, 1) + } else { + next = make(map[string][]pathPart, len(*old)+1) + maps.Copy(next, *old) + } + next[key] = parts + c.fast.Store(&next) + c.mu.Unlock() + return parts, false + } + c.sealed.Store(true) + c.mu.Unlock() + } + v, loaded := c.spill.LoadOrStore(key, parts) + return v.([]pathPart), loaded +} + +func (c *pathCache) clear() { + c.mu.Lock() + c.fast.Store(nil) + // Nothing reaches spill before the seal, so an unsealed cache has none. + if c.sealed.Load() { + c.spill.Clear() + c.sealed.Store(false) + } + c.mu.Unlock() +} + +// foldASCIILower writes the ASCII-lowercased form of s into buf and reports +// whether any byte changed. Folding into a caller-owned stack buffer lets the +// case-insensitive map probes below skip the allocation utilstrings.ToLower +// makes for a mixed-case key. The caller guarantees len(buf) >= len(s). +func foldASCIILower(buf []byte, s string) bool { + n := len(s) + changed := false + i := 0 + for ; i+swar.WordLen <= n; i += swar.WordLen { + w := swar.Load8(s, i) + lw := swar.ToLowerWord(w) + changed = changed || lw != w + swar.Store8(buf, i, lw) + } + for ; i < n; i++ { + ch := s[i] + if ch >= 'A' && ch <= 'Z' { + ch += 'a' - 'A' + changed = true + } + buf[i] = ch + } + return changed } // dotBroadcast is the SWAR needle for '.'; hoisted so the word loop in @@ -214,20 +372,28 @@ func nextPathSegment(path string, start int) (int, string, error) { // get returns a cached structInfo, creating it if necessary. func (c *cache) get(t reflect.Type) *structInfo { gen := c.gen.Load() + slot := &c.slots[typeSlot(t)] + // Ignore entries built under an older configuration: a build racing a + // reconfiguration may store one after the clear. Hit-validation + // guarantees that any call starting after the reconfiguration returned + // observes the new configuration (a call already in flight during the + // reconfiguration may still briefly use old metadata, which is inherent + // to concurrent reconfiguration). + cur := slot.Load() + if cur != nil && cur.typ == t && cur.gen == gen { + return cur.info + } if v, ok := c.m.Load(t); ok { - // Ignore entries built under an older configuration: a build racing - // a reconfiguration may store one after the clear. Hit-validation - // guarantees that any call starting after the reconfiguration - // returned observes the new configuration (a call already in flight - // during the reconfiguration may still briefly use old metadata, - // which is inherent to concurrent reconfiguration). if e := v.(*cacheEntry); e.gen == gen { + claimSlot(slot, cur, e) return e.info } } info := c.create(t, "") if c.gen.Load() == gen { - c.m.Store(t, &cacheEntry{info: info, gen: gen}) + e := &cacheEntry{info: info, typ: t, gen: gen} + c.m.Store(t, e) + claimSlot(slot, cur, e) } // If the configuration changed while building, serve the result once // without caching it (or with a stale tag that hit-validation ignores); @@ -235,11 +401,27 @@ func (c *cache) get(t reflect.Type) *structInfo { return info } +// claimSlot stores e in slot, which held cur when get read it, unless cur is +// the live entry of another type: two types sharing a slot would otherwise +// take it from each other on every call, and each store would invalidate the +// slots' cache line on every core reading it. A later type that loses the +// slot finds its metadata in c.m, as every type did before the slots. +func claimSlot(slot *atomic.Pointer[cacheEntry], cur, e *cacheEntry) { + if cur == nil || cur.gen < e.gen { + slot.CompareAndSwap(cur, e) + } +} + // reset clears cached metadata and must be called with c.l held. Parsed // path caches live on the structInfos, so dropping them drops those too. func (c *cache) reset() { c.gen.Add(1) c.m.Clear() + // The generation already turns the slots' entries away; dropping them + // lets their metadata go. + for i := range c.slots { + c.slots[i].Store(nil) + } } // aliasTag returns the configured tag name under the configuration lock, so @@ -297,7 +479,19 @@ func (c *cache) create(t reflect.Type, parentAlias string) *structInfo { info.fieldsByName[field.aliasLower] = field } } - info.requiredFields = c.buildRequiredFields(info) + for _, f := range info.fields { + if f.takesIndex() { + info.hasIndexedSlice = true + } + if k := f.typ.Kind(); f.def != nil || k == reflect.Struct || + (k == reflect.Ptr && f.typ.Elem().Kind() == reflect.Struct) { + info.defaultFields = append(info.defaultFields, f) + } + } + info.requiredGroups = c.buildRequiredFields(info) + info.requiredPrefixes = buildRequiredPrefixes(info.requiredGroups) + info.direct = c.buildDirectPaths(info) + info.directIndex = newFoldIndex(info.direct) // The setDefaults walk also allocates nil anonymous embedded pointers, // so it can only be skipped when neither defaults nor such pointers // exist anywhere in the tree. @@ -305,6 +499,73 @@ func (c *cache) create(t reflect.Type, parentAlias string) *structInfo { return info } +// buildDirectPaths precomputes, keyed by lowercase path, the parsed paths for +// every key resolvable without runtime state: flat aliases plus dotted chains +// through non-pointer nested struct fields. +func (c *cache) buildDirectPaths(info *structInfo) map[string][]pathPart { + direct := make(map[string][]pathPart, len(info.fieldsByName)) + // Flat aliases first (linear in field count) so the cap below can never + // crowd them out; iterate fields in declaration order, honoring + // fieldsByName's first-wins rule. + for _, f := range info.fields { + if !directEligible(info, f) { + continue + } + hops := []pathHop{{index: f.index, ensure: info.anonymousPtrFields}} + direct[f.aliasLower] = []pathPart{{ + hops: hops, + field: f, + index: -1, + soleIndex: soleHopIndex(hops), + }} + } + for _, f := range info.fields { + if len(direct) >= maxDirectPaths { + break + } + if !directEligible(info, f) || f.typ.Kind() != reflect.Struct { + continue + } + // Non-pointer struct nesting cannot recurse (the type would be + // illegal), so the child's info is always buildable here. + hop := pathHop{index: f.index, ensure: info.anonymousPtrFields} + for childKey, childParts := range c.get(f.typ).direct { + if len(direct) >= maxDirectPaths { + break + } + cp := childParts[0] + hops := make([]pathHop, 0, len(cp.hops)+1) + hops = append(hops, hop) + hops = append(hops, cp.hops...) + direct[f.aliasLower+"."+childKey] = []pathPart{{ + hops: hops, + field: cp.field, + index: -1, + soleIndex: soleHopIndex(hops), + }} + } + } + return direct +} + +// directEligible reports whether f can serve as a direct-path terminal: it is +// its alias's first-wins winner, the alias has no dot, and a bare alias is a +// valid path (slice-of-structs fields require a following slice index). +func directEligible(info *structInfo, f *fieldInfo) bool { + if info.fieldsByName[f.aliasLower] != f || strings.IndexByte(f.aliasLower, '.') >= 0 { + return false + } + return !f.takesIndex() +} + +// takesIndex reports whether a path through f must carry a slice element +// index: f is a slice of structs walked element by element, not one handed to +// a multipart binder or a TextUnmarshaler whole. +func (f *fieldInfo) takesIndex() bool { + return f.isSliceOfStructs && !f.isMultipart && + (!f.unmarshalerInfo.IsValid || f.unmarshalerInfo.IsSliceElement) +} + // needsDefaultsWalk reports whether the setDefaults walk can have any effect // on the struct tree rooted at t: it declares a default tag option, or has an // (exported) anonymous pointer field the walk allocates, anywhere in the @@ -390,12 +651,23 @@ func (c *cache) createField(field reflect.StructField, parentAlias, tag string) elemU = isTextUnmarshaler(reflect.Zero(ft)) } - return &fieldInfo{ + // Non-pointer builtin scalars without unmarshalers or custom converters + // can skip decode's dispatch entirely; converter registration resets the + // cache, so this build-time decision stays valid. + fastKind := reflect.Invalid + if k := field.Type.Kind(); k != reflect.Ptr && !m.IsValid && + getBuiltinConverter(k) != nil && c.converter(field.Type) == nil { + fastKind = k + } + + f := &fieldInfo{ typ: field.Type, + fastKind: fastKind, name: field.Name, alias: alias, aliasLower: utilstrings.ToLower(alias), canonicalAlias: canonicalAlias, + canonicalDot: canonicalAlias + ".", unmarshalerInfo: m, derefUnmarshaler: derefU, elemUnmarshaler: elemU, @@ -405,6 +677,8 @@ func (c *cache) createField(field reflect.StructField, parentAlias, tag string) isRequired: options.Contains("required"), defaultValue: options.getDefaultOptionValue(), } + f.resolveDefault() + return f } // converter returns the converter for a type. @@ -422,11 +696,27 @@ type structInfo struct { fields []*fieldInfo fieldsByName map[string]*fieldInfo anonymousPtrFields []int - requiredFields map[string][]fieldWithPrefix - // paths caches parsed paths rooted at this struct type - // (map[string][]pathPart); keys are cloned so they never alias reused - // request buffers. - paths sync.Map + // requiredGroups lists the required keys in a stable order, so each has + // an index the satisfied-group bitset can address; requiredPrefixes maps + // a nested-key prefix to the groups a key under it can satisfy. + requiredGroups []requiredGroup + requiredPrefixes map[string][]requiredPrefix + // direct maps lowercase statically-resolvable keys to their precomputed + // parsed paths; built once and immutable, see buildDirectPaths. + direct map[string][]pathPart + // directIndex is direct, indexed for parsePathInfo's case-insensitive + // lookups + directIndex foldIndex + // paths caches parsed paths rooted at this struct type; keys are cloned + // so they never alias reused request buffers. + paths pathCache + // hasIndexedSlice reports whether any field's paths carry a slice element + // index, and so may grow that slice while decoding. + hasIndexedSlice bool + // defaultFields are the fields the setDefaults walk has to visit: those + // with a default, and the structs and pointers to structs it descends + // into. The rest of the fields can never be affected by it. + defaultFields []*fieldInfo // needsDefaultsWalk reports whether the setDefaults walk can have any // effect on this struct tree: it is set when a default tag option or an // anonymous embedded pointer field (which the walk allocates) exists @@ -435,35 +725,85 @@ type structInfo struct { } func (i *structInfo) get(alias string) *fieldInfo { - aliasKey := utilstrings.ToLower(alias) - if field, ok := i.fieldsByName[aliasKey]; ok { + // fieldsByName is keyed by lowercase alias, so the raw probe settles an + // already-lowercase one without folding. A mixed-case alias is folded + // into a stack buffer and probed from there: the compiler elides the + // string conversion in a map index, so that allocates nothing either. + if field, ok := i.fieldsByName[alias]; ok { return field } - return nil + if n := len(alias); n <= maxDirectKeyLen { + var buf [maxDirectKeyLen]byte + if !foldASCIILower(buf[:], alias) { + return nil // already lowercase: the probe above was conclusive + } + return i.fieldsByName[string(buf[:n])] + } + return i.fieldsByName[utilstrings.ToLower(alias)] } -func (c *cache) buildRequiredFields(info *structInfo) map[string][]fieldWithPrefix { - var requiredFields map[string][]fieldWithPrefix +func (c *cache) buildRequiredFields(info *structInfo) []requiredGroup { + var groups []requiredGroup + var byKey map[string]int + add := func(key string, f fieldWithPrefix) { + if i, ok := byKey[key]; ok { + groups[i].fields = append(groups[i].fields, f) + return + } + if byKey == nil { + byKey = make(map[string]int) + } + byKey[key] = len(groups) + groups = append(groups, requiredGroup{key: key, fields: []fieldWithPrefix{f}}) + } for _, field := range info.fields { if field.typ.Kind() == reflect.Struct { nested := c.get(field.typ) for _, prefix := range field.paths("") { nestedPrefix := prefix + "." - for key, fields := range nested.requiredFields { - requiredKey := field.canonicalAlias + "." + key - for _, nestedField := range fields { - requiredFields = appendRequiredField(requiredFields, requiredKey, - newFieldWithPrefix(nestedField.fieldInfo, nestedPrefix+nestedField.prefix)) + for _, group := range nested.requiredGroups { + requiredKey := field.canonicalAlias + "." + group.key + for _, nestedField := range group.fields { + add(requiredKey, newFieldWithPrefix(nestedField.fieldInfo, nestedPrefix+nestedField.prefix)) } } } } if field.isRequired { - requiredFields = appendRequiredField(requiredFields, field.canonicalAlias, - newFieldWithPrefix(field, "")) + add(field.canonicalAlias, newFieldWithPrefix(field, "")) } } - return requiredFields + return groups +} + +// buildRequiredPrefixes indexes the groups by the nested-key prefix that can +// satisfy them ("d." for required key "d"), so a source key can be resolved +// against all of them at once. +func buildRequiredPrefixes(groups []requiredGroup) map[string][]requiredPrefix { + if len(groups) == 0 { + return nil + } + prefixes := make(map[string][]requiredPrefix) + for gi := range groups { + for _, f := range groups[gi].fields { + for _, dot := range f.searchPathDots { + owners := prefixes[dot] + // One entry per (group, type): several fields of a group + // can reach the same prefix. + dup := false + for _, o := range owners { + if o.group == gi && o.typ == f.typ { + dup = true + break + } + } + if !dup { + prefixes[dot] = append(owners, requiredPrefix{group: gi, typ: f.typ}) + } + } + } + } + return prefixes } func containsAlias(infos []*structInfo, alias string) bool { @@ -478,6 +818,9 @@ func containsAlias(infos []*structInfo, alias string) bool { type fieldInfo struct { typ reflect.Type + // fastKind is the field's builtin scalar kind when decode can set it + // directly (no pointer, unmarshaler, or custom converter); else Invalid. + fastKind reflect.Kind // index is the field index chain relative to the struct type whose // structInfo holds this fieldInfo; promoted fields carry the full chain // through the embedded structs (a copy is made per promotion level). @@ -516,6 +859,24 @@ type fieldInfo struct { isAnonymous bool isRequired bool defaultValue string + // canonicalDot is canonicalAlias with the trailing separator, the prefix + // the fields of a nested struct are looked up under. + canonicalDot string + // def is the default option resolved at build time, nil for the fields + // that have none; see resolveDefault. + def *fieldDefault +} + +// fieldDefault is what setDefaults assigns for a field's default option: +// val for a scalar field (converted to the field type) or a pointer field +// (converted to the pointee type), and slice, a template a slice field's +// default is copied from. An element that failed to convert leaves the +// template short and sets err, which is reported each time the default +// applies. A kind that takes no default leaves all three unset. +type fieldDefault struct { + val reflect.Value + slice reflect.Value + err error } func (f *fieldInfo) paths(prefix string) []string { @@ -529,12 +890,25 @@ type pathPart struct { field *fieldInfo hops []pathHop // path to the field: walks structs using field indices. index int // struct index in slices of structs. + // soleIndex is the single struct field index hops walks, or -1; see + // soleHopIndex. + soleIndex int // elem marks a terminal part whose path ended at a slice index ("a.0"): // the decoder's value is then an element of the slice field rather than // the field itself. elem bool } +// soleHopIndex returns the single struct field index hops walks, or -1 when +// the walk needs decode's general loop: several hops, a promoted field's +// index chain, or embedded pointers to allocate on the way. +func soleHopIndex(hops []pathHop) int { + if len(hops) != 1 || len(hops[0].ensure) != 0 || len(hops[0].index) != 1 { + return -1 + } + return hops[0].index[0] +} + // pathHop describes one named-field lookup along a path. index is the field // index chain relative to the struct at this level (more than one element // when the field is promoted from embedded structs), and ensure lists the @@ -604,3 +978,55 @@ func (o tagOptions) getDefaultOptionValue() string { } return "" } + +// foldIndex is a read-only open-addressing index from lowercase keys to their +// parsed paths that is probed ASCII case-insensitively. A key's slot comes from +// a hash of its case-folded bytes and is confirmed with utils.EqualFold, so a +// mixed-case key, a header name say, costs one probe where a map needed a +// probe with the key as given and another with it folded, and a key naming no +// field is turned away just as fast. +type foldIndex struct { + // slots is a power of two long, at most half full, so every probe + // reaches a free slot + slots []foldSlot + mask uint64 + len int +} + +type foldSlot struct { + key string // lowercase key; "" marks a free slot, since no path is empty + parts []pathPart +} + +// newFoldIndex indexes paths, whose keys are lowercase and non-empty. +func newFoldIndex(paths map[string][]pathPart) foldIndex { + if len(paths) == 0 { + return foldIndex{} + } + size := 8 + for size < 2*len(paths) { + size *= 2 + } + x := foldIndex{slots: make([]foldSlot, size), mask: uint64(size - 1), len: len(paths)} + for key, parts := range paths { + i := utils.HashFold(key) & x.mask + for x.slots[i].key != "" { + i = (i + 1) & x.mask + } + x.slots[i] = foldSlot{key: key, parts: parts} + } + return x +} + +// lookup returns the parts of the key that equals k ASCII case-insensitively. +func (x *foldIndex) lookup(k string) ([]pathPart, bool) { + for i := utils.HashFold(k) & x.mask; ; i = (i + 1) & x.mask { + s := &x.slots[i] + if s.key == "" { + return nil, false + } + if len(s.key) == len(k) && utils.EqualFold(s.key, k) { + return s.parts, true + } + } +} diff --git a/src/vendor/github.com/gofiber/schema/converter.go b/src/vendor/github.com/gofiber/schema/converter.go index 27aa76bb..7190a33a 100644 --- a/src/vendor/github.com/gofiber/schema/converter.go +++ b/src/vendor/github.com/gofiber/schema/converter.go @@ -169,6 +169,44 @@ func convertUint64(value string) reflect.Value { return invalidValue } +// parseNative* adapt the builtin parsers to the (T, bool) shape used by the +// native slice decode path, mirroring setBuiltinKind's per-kind behavior. + +func parseNativeString(s string) (string, bool) { return s, true } + +func parseNativeInt(s string) (int, bool) { + n, err := utils.ParseInt(s) + return int(n), err == nil && int64(int(n)) == n +} + +func parseNativeInt64(s string) (int64, bool) { + n, err := utils.ParseInt(s) + return n, err == nil +} + +func parseNativeUint(s string) (uint, bool) { + n, err := utils.ParseUint(s) + return uint(n), err == nil && uint64(uint(n)) == n +} + +func parseNativeUint64(s string) (uint64, bool) { + n, err := utils.ParseUint(s) + return n, err == nil +} + +func parseNativeFloat64(s string) (float64, bool) { + f, err := utils.ParseFloat64(s) + return f, err == nil +} + +func parseNativeBool(s string) (bool, bool) { + if s == "on" { + return true, true + } + b, err := strconv.ParseBool(s) + return b, err == nil +} + // setBuiltinKind parses val and assigns it directly into v for builtin // convertible kinds, avoiding the reflect.Value boxing of the Converter API. // handled reports whether the kind is builtin-convertible; ok reports whether diff --git a/src/vendor/github.com/gofiber/schema/decoder.go b/src/vendor/github.com/gofiber/schema/decoder.go index 0b8b6bcf..cb11387f 100644 --- a/src/vendor/github.com/gofiber/schema/decoder.go +++ b/src/vendor/github.com/gofiber/schema/decoder.go @@ -11,8 +11,12 @@ import ( "maps" "mime/multipart" "reflect" + "strconv" "strings" "sync" + "unsafe" + + utils "github.com/gofiber/utils/v2" ) const ( @@ -23,6 +27,11 @@ const ( // hoisted so the check does not allocate on every call. var errNotPointerToStruct = errors.New("schema: interface must be a pointer to struct") +// fileKeyValues stands in for the value of a multipart file's key in the +// decode view. Nothing writes through a source map's values and the map it +// goes into is this package's own copy, so one slice serves every file key. +var fileKeyValues = []string{""} + var decodeValueBufferPool = sync.Pool{ New: func() any { buf := make([]reflect.Value, 0, 8) @@ -96,25 +105,7 @@ func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) // Keys are "paths" in dotted notation to the struct fields and nested structs. // // See the package documentation for a full explanation of the mechanics. -func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[string][]*multipart.FileHeader) (err error) { - v := reflect.ValueOf(dst) - if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { - return errNotPointerToStruct - } - - // Catch panics from the decoder and return them as an error. - // This is needed because the decoder calls reflect and reflect panics. - // Installed before any other work so nothing can crash the caller. - defer func() { - if r := recover(); r != nil { - if e, ok := r.(error); ok { - err = e - } else { - err = fmt.Errorf("schema: panic while decoding: %v", r) - } - } - }() - +func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[string][]*multipart.FileHeader) error { var multipartFiles map[string][]*multipart.FileHeader if len(files) > 0 { @@ -129,46 +120,205 @@ func (d *Decoder) Decode(dst interface{}, src map[string][]string, files ...map[ merged := make(map[string][]string, len(src)+len(multipartFiles)) maps.Copy(merged, src) for path := range multipartFiles { - merged[path] = []string{""} + merged[path] = fileKeyValues } src = merged } + s := source{m: src} + return d.decodeSource(dst, &s, multipartFiles) +} + +// DecodeValues decodes key/value pairs to a struct as Decode decodes the map +// they make: values[i] is a value of the key keys[i], and a key given more +// than once has all of its values, in the order given. It saves a caller that +// has the pairs one at a time, as a parsed query string does, building that +// map, and saves the decode iterating it. +// +// Where several keys name the same field, as keys that differ only in case +// do, the keys decode in the order of their first pairs, so the key given +// first the latest wins; Decode lets whichever its map yields last win. +// +// The first parameter must be a pointer to a struct, and keys and values must +// be the same length. The slices are only read, and only during the call. +func (d *Decoder) DecodeValues(dst interface{}, keys, values []string) error { + if len(keys) != len(values) { + return errValuesLength + } + // The index is set up field by field where it lies. Go puts a literal for + // a variable whose address is taken, or a call's result, together + // elsewhere and copies it over, and the copy reads back in wide loads the + // words just stored in narrow ones, which stalls each load. + var p pairIndex + p.keys, p.values = keys, values + if n := len(keys); n <= maxScanPairs { + var next, last [maxScanPairs]int32 + p.next, p.last = next[:n], last[:n] + } else if n <= maxInlinePairs { + var table [2 * maxInlinePairs]int32 + var next, last [maxInlinePairs]int32 + p.table, p.next, p.last = table[:indexSize(n)], next[:n], last[:n] + } else { + p.table, p.next, p.last = make([]int32, indexSize(n)), make([]int32, n), make([]int32, n) + } + p.index() + s := source{pairs: &p} + return d.decodeSource(dst, &s, nil) +} + +// decodeSource decodes src into dst, the pointer to a struct Decode and +// DecodeValues were given, with the files Decode was. +func (d *Decoder) decodeSource(dst interface{}, src *source, multipartFiles map[string][]*multipart.FileHeader) (err error) { + v := reflect.ValueOf(dst) + if v.Kind() != reflect.Pointer || v.Elem().Kind() != reflect.Struct { + return errNotPointerToStruct + } + + // Catch panics from the decoder and return them as an error. + // This is needed because the decoder calls reflect and reflect panics. + // Installed before any other work so nothing can crash the caller. + defer func() { + if r := recover(); r != nil { + if e, ok := r.(error); ok { + err = e + } else { + err = fmt.Errorf("schema: panic while decoding: %v", r) + } + } + }() + v = v.Elem() t := v.Type() rootInfo := d.cache.get(t) - var multiErrors MultiError - for path, values := range src { - if parts, err := d.cache.parsePathInfo(path, rootInfo); err == nil { - var filesSlice []*multipart.FileHeader - if multipartFiles != nil { - filesSlice = multipartFiles[path] - } - if err = d.decode(v, path, parts, values, filesSlice); err != nil { - multiErrors = appendError(multiErrors, path, err) - } - } else { - if errors.Is(err, errIndexTooLarge) { - multiErrors = appendError(multiErrors, path, err) - } else if !d.ignoreUnknownKeys { - multiErrors = appendError(multiErrors, path, UnknownKeyError{Key: path}) + // Required-key bookkeeping rides along with the loop below so src is + // walked once: the direct lookups settle almost every group here, and + // the rest are answered by the nested keys the loop visits anyway. + var satisfied []uint64 + pending := 0 + if len(rootInfo.requiredGroups) > 0 { + // Declared here so a struct with no required keys never pays to + // zero it. + var requiredBits [requiredBitWords]uint64 + satisfied, pending = markProvidedDirectly(rootInfo.requiredGroups, src, requiredBits[:]) + } + // Only a struct whose paths carry an index can grow anything. + var grow *growTracker + if rootInfo.hasIndexedSlice { + var tracker growTracker + grow = &tracker + } + // The state decodeKey carries from key to key is kept in variables of + // its own rather than a struct: the compiler would let the stack values + // above escape along with the errors a struct holding both returns. + var errs MultiError + if p := src.pairs; p != nil { + // A key whose pairs are not adjacent gathers its values here. + var scratch [8]string + for i, path := range p.keys { + if p.first(i) { + errs, pending = d.decodeKey(v, rootInfo, multipartFiles, grow, satisfied, path, p.group(i, scratch[:0]), errs, pending) } } + } else { + for path, values := range src.m { + errs, pending = d.decodeKey(v, rootInfo, multipartFiles, grow, satisfied, path, values, errs, pending) + } } if rootInfo.needsDefaultsWalk { - multiErrors = mergeErrors(multiErrors, d.setDefaults(t, v, src, "")) + errs = mergeErrors(errs, d.setDefaults(t, v, src, "")) } - multiErrors = mergeErrors(multiErrors, d.checkRequired(rootInfo, src)) - if len(multiErrors) > 0 { - return multiErrors + errs = mergeErrors(errs, missingRequired(rootInfo.requiredGroups, satisfied, pending)) + if len(errs) > 0 { + return errs } return nil } +// decodeKey decodes the values of one source key into v, the struct whose +// metadata is rootInfo, and returns errs with any error it met added, and +// pending less the required groups the key settles in satisfied. +func (d *Decoder) decodeKey( + v reflect.Value, rootInfo *structInfo, files map[string][]*multipart.FileHeader, grow *growTracker, + satisfied []uint64, path string, values []string, errs MultiError, pending int, +) (MultiError, int) { + if pending > 0 { + if i := strings.IndexByte(path, '.'); i >= 0 && len(values) > 0 { + pending = markProvidedByNestedKey(rootInfo, path, i+1, values, satisfied, pending) + } + } + if parts, err := d.cache.parsePathInfo(path, rootInfo); err == nil { + var filesSlice []*multipart.FileHeader + if files != nil { + filesSlice = files[path] + } + if err = d.decode(v, path, parts, values, filesSlice, grow); err != nil { + errs = appendError(errs, path, err) + } + // A key that names no field is by far the most common failure, + // and parsePathInfo returns that sentinel unwrapped, so the + // pointer compare keeps errors.Is off the per-key path. + } else if err != errInvalidPath && errors.Is(err, errIndexTooLarge) { //nolint:errorlint // see above + errs = appendError(errs, path, err) + } else if !d.ignoreUnknownKeys { + errs = appendError(errs, path, UnknownKeyError{Key: path}) + } + return errs, pending +} + // setDefaults sets the default values when the `default` tag is specified, // default is supported on basic/primitive types and their pointers, // nested structs can also have default tags -func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][]string, prefix string) MultiError { +var ( + errUnsupportedDefault = errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices") + errRequiredDefault = errors.New("required fields cannot have a default value") +) + +// resolveDefault converts the field's default option once, when the struct +// metadata is built, so setDefaults assigns a resolved value on every call +// instead of converting the string each time. Slice and pointer defaults are +// still instantiated per call, so no two decoded values share one. +func (f *fieldInfo) resolveDefault() { + if f.defaultValue == "" { + return + } + def := &fieldDefault{} + f.def = def + switch f.typ.Kind() { + case reflect.Slice: + elemT := f.typ.Elem() + conv := getBuiltinConverter(elemT.Kind()) + if conv == nil { + return + } + tmpl := reflect.MakeSlice(f.typ, 0, strings.Count(f.defaultValue, "|")+1) + for val := range strings.SplitSeq(f.defaultValue, "|") { + v := conv(val) + if !v.IsValid() { + def.err = fmt.Errorf("failed setting default: %s is not compatible with field %s type", val, f.name) + break + } + // Builtin converters return the underlying kind; convert to the + // (possibly named) element type, else Append panics for []MyInt. + tmpl = reflect.Append(tmpl, v.Convert(elemT)) + } + def.slice = tmpl + case reflect.Ptr: + t1 := f.typ.Elem() + if conv := getBuiltinConverter(t1.Kind()); conv != nil { + if v := conv(f.defaultValue); v.IsValid() { + def.val = v.Convert(t1) + } + } + default: + if conv := getBuiltinConverter(f.typ.Kind()); conv != nil { + if v := conv(f.defaultValue); v.IsValid() { + def.val = v.Convert(f.typ) + } + } + } +} + +func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src *source, prefix string) MultiError { struc := d.cache.get(t) // Skip the walk entirely when it can have no effect (no default tags and // no anonymous embedded pointers to allocate anywhere in the tree) — the @@ -187,79 +337,69 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][] } } - for _, f := range struc.fields { + for _, f := range struc.defaultFields { vCurrent := walkIndexChain(v, f.index) if !vCurrent.IsValid() { // Unreachable behind an unsettable nil embedded pointer. continue } - if vCurrent.Type().Kind() == reflect.Struct && f.defaultValue == "" { - errs = mergeErrors(errs, d.setDefaults(vCurrent.Type(), vCurrent, src, prefix+f.canonicalAlias+".")) - } else if isPointerToStruct(vCurrent) && f.defaultValue == "" { - errs = mergeErrors(errs, d.setDefaults(vCurrent.Elem().Type(), vCurrent.Elem(), src, prefix+f.canonicalAlias+".")) + // vCurrent's type is f.typ; a nested struct is walked under its own + // prefix (an empty prefix concatenates without allocating). + kind := f.typ.Kind() + if kind == reflect.Struct && f.defaultValue == "" { + errs = mergeErrors(errs, d.setDefaults(f.typ, vCurrent, src, prefix+f.canonicalDot)) + } else if kind == reflect.Ptr && f.defaultValue == "" && isPointerToStruct(vCurrent) { + errs = mergeErrors(errs, d.setDefaults(f.typ.Elem(), vCurrent.Elem(), src, prefix+f.canonicalDot)) } - if f.defaultValue != "" && f.isRequired { - errs = appendError(errs, "default-"+f.name, errors.New("required fields cannot have a default value")) - } else if f.defaultValue != "" && vCurrent.IsZero() && !f.isRequired && !fieldProvided(src, prefix, f) { - if f.typ.Kind() == reflect.Struct { - errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices")) - } else if f.typ.Kind() == reflect.Slice { - // check if slice has one of the supported types for defaults - conv := getBuiltinConverter(f.typ.Elem().Kind()) - if conv == nil { - errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices")) - continue - } - - elemT := f.typ.Elem() - defaultSlice := reflect.MakeSlice(f.typ, 0, strings.Count(f.defaultValue, "|")+1) - for val := range strings.SplitSeq(f.defaultValue, "|") { - // this check is to handle if the wrong value is provided - convertedVal := conv(val) - if !convertedVal.IsValid() { - errs = appendError(errs, "default-"+f.name, fmt.Errorf("failed setting default: %s is not compatible with field %s type", val, f.name)) - break - } - // Builtin converters return the underlying kind; convert to - // the (possibly named) element type before appending, else - // reflect.Append panics for e.g. []MyInt. - defaultSlice = reflect.Append(defaultSlice, convertedVal.Convert(elemT)) - } - vCurrent.Set(defaultSlice) - } else if f.typ.Kind() == reflect.Ptr { - t1 := f.typ.Elem() - - if t1.Kind() == reflect.Struct || t1.Kind() == reflect.Slice { - errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices")) - } - - // this check is to handle if the wrong value is provided - if conv := getBuiltinConverter(t1.Kind()); conv != nil { - if convertedVal := conv(f.defaultValue); convertedVal.IsValid() { - // Build a pointer of the field's actual element type: - // the converter yields the underlying kind, which is - // convertible to the (possibly named) element type, - // and *elem is assignable to the field even when the - // field's type is itself a named pointer type (e.g. - // type MyIntPtr *MyInt), where converting a *int - // directly would panic. - p := reflect.New(t1) - p.Elem().Set(convertedVal.Convert(t1)) - vCurrent.Set(p) - } - } - } else { - // this check is to handle if the wrong value is provided - conv := getBuiltinConverter(f.typ.Kind()) - if conv == nil { - errs = appendError(errs, "default-"+f.name, errors.New("default option is supported only on: bool, float variants, string, unit variants types or their corresponding pointers or slices")) - } else if convertedVal := conv(f.defaultValue); convertedVal.IsValid() { - // Builtin converters return the underlying kind; convert to - // the field's (possibly named) type before assigning. - vCurrent.Set(convertedVal.Convert(f.typ)) - } + def := f.def + if def == nil { + continue + } + if f.isRequired { + errs = appendError(errs, "default-"+f.name, errRequiredDefault) + continue + } + if !vCurrent.IsZero() || fieldProvided(src, prefix, f) { + continue + } + // The default itself was resolved when the metadata was built; see + // resolveDefault. Only the per-call parts remain: the errors a kind + // that takes no default reports, and a fresh pointer or slice so no + // two decoded values share one. + switch kind { + case reflect.Struct: + errs = appendError(errs, "default-"+f.name, errUnsupportedDefault) + case reflect.Slice: + if !def.slice.IsValid() { + errs = appendError(errs, "default-"+f.name, errUnsupportedDefault) + continue + } + if def.err != nil { + errs = appendError(errs, "default-"+f.name, def.err) + } + fresh := reflect.MakeSlice(f.typ, def.slice.Len(), def.slice.Cap()) + reflect.Copy(fresh, def.slice) + vCurrent.Set(fresh) + case reflect.Ptr: + t1 := f.typ.Elem() + if t1.Kind() == reflect.Struct || t1.Kind() == reflect.Slice { + errs = appendError(errs, "default-"+f.name, errUnsupportedDefault) + } + if def.val.IsValid() { + // *elem is assignable to the field even when the field's + // type is itself a named pointer type (type MyIntPtr *MyInt), + // where converting a *int directly would panic. + p := reflect.New(t1) + p.Elem().Set(def.val) + vCurrent.Set(p) + } + default: + if getBuiltinConverter(kind) == nil { + errs = appendError(errs, "default-"+f.name, errUnsupportedDefault) + } else if def.val.IsValid() { + vCurrent.Set(def.val) } } } @@ -267,36 +407,159 @@ func (d *Decoder) setDefaults(t reflect.Type, v reflect.Value, src map[string][] return errs } +// growCap is the capacity to give a slice being grown to n elements: room for +// another doubling when the slice is tracked, so later indices mostly land +// inside it, and exactly n when it is not, since the extra would go unused. +func (d *Decoder) growCap(n int, tracked bool) int { + if !tracked { + return n + } + c := 2 * n + if c < n || c > d.maxSize+1 { // overflow, or past what maxSize admits + c = d.maxSize + 1 + } + if c < n { + c = n + } + return c +} + func isPointerToStruct(v reflect.Value) bool { return !v.IsZero() && v.Type().Kind() == reflect.Ptr && v.Elem().Type().Kind() == reflect.Struct } -func fieldProvided(src map[string][]string, prefix string, f *fieldInfo) bool { - for _, p := range f.paths(prefix) { - if _, ok := src[p]; ok { - return true - } +func fieldProvided(src *source, prefix string, f *fieldInfo) bool { + if keyProvided(src, prefix, f.alias) { + return true } - return false + return f.alias != f.canonicalAlias && keyProvided(src, prefix, f.canonicalAlias) +} + +// keyProvided reports whether prefix+name is a key of src, assembling the key +// in a stack buffer when it fits so the probe allocates nothing. +func keyProvided(src *source, prefix, name string) bool { + if prefix == "" { + _, ok := src.lookup(name) + return ok + } + if n := len(prefix) + len(name); n <= maxDirectKeyLen { + var buf [maxDirectKeyLen]byte + copy(buf[copy(buf[:], prefix):], name) + return src.hasBytes(buf[:n]) + } + _, ok := src.lookup(prefix + name) + return ok } -// checkRequired checks whether required fields are empty -// // The set of required fields (including those of nested structs) is -// precomputed once per struct type in structInfo.requiredFields, so this -// only performs the per-request emptiness checks against src. +// precomputed once per struct type in structInfo.requiredGroups, so what +// follows only performs the per-request emptiness checks against src. // -// src is the source map for decoding, we use it here to see if those required fields are included in src -func (d *Decoder) checkRequired(info *structInfo, src map[string][]string) MultiError { +// A group is satisfied by a value under one of its own paths, or by any +// nested key below one of them ("d.e" satisfies required "d"). Direct paths +// are looked up first, since they settle almost every group; what is left is +// answered by walking the dotted prefixes of each source key. Decode runs +// those three steps around its own loop over src; checkRequired composes them +// for a standalone check. + +// requiredBitWords sizes the inline satisfied-group bitset: 256 required +// keys, past which it is allocated. +const requiredBitWords = 4 + +// markProvidedDirectly marks every required group src answers through one of +// its own paths, returning the bitset — backed by inline when the groups fit +// — and how many are still pending. +func markProvidedDirectly(groups []requiredGroup, src *source, inline []uint64) ([]uint64, int) { + if len(groups) == 0 { + return nil, 0 + } + var satisfied []uint64 + if w := (len(groups) + 63) >> 6; w <= len(inline) { + satisfied = inline[:w] + } else { + satisfied = make([]uint64, w) + } + pending := len(groups) + for gi := range groups { + if directlyProvided(groups[gi].fields, src) { + satisfied[gi>>6] |= 1 << uint(gi&63) + pending-- + } + } + return satisfied, pending +} + +// markProvidedByNestedKey walks the dotted prefixes of key from off, marking +// every required group they name that val is non-empty for, and returns the +// new pending count. Callers test for a dotted, non-empty key themselves, so +// the keys that can answer nothing do not pay for a call. +func markProvidedByNestedKey(info *structInfo, key string, off int, val []string, satisfied []uint64, pending int) int { + for { + for _, p := range info.requiredPrefixes[key[:off]] { + if satisfied[p.group>>6]&(1<>6] |= 1 << uint(p.group&63) + pending-- + } + } + i := strings.IndexByte(key[off:], '.') + if i < 0 { + return pending + } + off += i + 1 + } +} + +// missingRequired reports the required keys nothing in src answered. +func missingRequired(groups []requiredGroup, satisfied []uint64, pending int) MultiError { + if pending == 0 { + return nil + } var errs MultiError - for key, fields := range info.requiredFields { - if isEmptyFields(fields, src) { - errs = appendError(errs, key, EmptyFieldError{Key: key}) + for gi := range groups { + if satisfied[gi>>6]&(1< 0 { + for key, val := range src { + i := strings.IndexByte(key, '.') + if i < 0 || len(val) == 0 { + continue + } + if pending = markProvidedByNestedKey(info, key, i+1, val, satisfied, pending); pending == 0 { + break + } + } + } + return missingRequired(info.requiredGroups, satisfied, pending) +} + +// requiredGroup is one required key together with the fields that can +// satisfy it; its position in structInfo.requiredGroups is its bitset index. +type requiredGroup struct { + key string + fields []fieldWithPrefix +} + +// requiredPrefix names a group a nested source key can satisfy, with the +// field type that judges whether the key's value counts as non-empty. +type requiredPrefix struct { + typ reflect.Type + group int +} + type fieldWithPrefix struct { *fieldInfo prefix string @@ -322,30 +585,17 @@ func newFieldWithPrefix(f *fieldInfo, prefix string) fieldWithPrefix { } } -// isEmptyFields returns true if all of specified fields are empty. -func isEmptyFields(fields []fieldWithPrefix, src map[string][]string) bool { +// directlyProvided reports whether any of the group's own paths carries a +// non-empty value in src. +func directlyProvided(fields []fieldWithPrefix, src *source) bool { for _, f := range fields { - for i, path := range f.searchPaths { - v, ok := src[path] - if ok && !isEmpty(f.typ, v) { - return false - } - // Check for nested keys that match this field. - pathDot := f.searchPathDots[i] - for key, val := range src { - if len(val) == 0 { - continue - } - // for nested structs - if strings.HasPrefix(key, pathDot) { - if !isEmpty(f.typ, val) { - return false - } - } + for _, path := range f.searchPaths { + if v, ok := src.lookup(path); ok && !isEmpty(f.typ, v) { + return true } } } - return true + return false } // isEmpty returns true if value is empty for specific type @@ -435,6 +685,36 @@ func isMultipartField(typ reflect.Type) bool { return false } +// walkHops follows a path to the target field, dereferencing pointers and +// allocating the embedded pointers promoted fields need on the way. It +// returns the zero Value when an unsettable nil embedded pointer blocks the +// walk. +func walkHops(v reflect.Value, hops []pathHop) reflect.Value { + for _, hop := range hops { + // A previous hop may have been blocked by an unsettable nil + // embedded pointer; the field is unreachable then. + if !v.IsValid() { + return v + } + if v.Kind() == reflect.Ptr { + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + + // Allocate embedded anonymous pointers required for promoted fields. + for _, idx := range hop.ensure { + if f := v.Field(idx); f.IsNil() { + f.Set(reflect.New(f.Type().Elem())) + } + } + + v = walkIndexChain(v, hop.index) + } + return v +} + // walkIndexChain walks v along a struct field index chain. Chains longer // than one element traverse embedded structs; intermediate nil pointers are // allocated so promoted fields stay reachable. It returns the zero Value @@ -457,30 +737,54 @@ func walkIndexChain(v reflect.Value, chain []int) reflect.Value { return v } -// decode fills a struct field using a parsed path. -func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string, files []*multipart.FileHeader) error { - // Get the field walking the struct fields by index. - for _, hop := range parts[0].hops { - // A previous hop may have been blocked by an unsettable nil - // embedded pointer; the field is unreachable then. - if !v.IsValid() { - return nil - } - if v.Kind() == reflect.Ptr { - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - v = v.Elem() +// growTracker remembers which of the destination struct's slice fields a +// Decode call has already reallocated, and how much room it reserved in each. +// Fields are keyed by their index in that struct, which is what pathPart's +// soleIndex carries: only a slice reached by one hop can be tracked, since a +// deeper path reaches a slice inside some element, which the field alone +// cannot tell apart from the same field in another. Fields past the four +// entries keep growing exactly. +type growTracker struct { + fields [4]int + caps [4]int + n int +} + +// reserved returns the capacity this call gave the slice at struct field +// index i, or 0 if it has not reallocated it. +func (g *growTracker) reserved(i int) int { + for j := 0; j < g.n; j++ { + if g.fields[j] == i { + return g.caps[j] } + } + return 0 +} - // Allocate embedded anonymous pointers required for promoted fields. - for _, idx := range hop.ensure { - if f := v.Field(idx); f.IsNil() { - f.Set(reflect.New(f.Type().Elem())) - } +func (g *growTracker) record(i, c int) { + for j := 0; j < g.n; j++ { + if g.fields[j] == i { + g.caps[j] = c + return } + } + if g.n < len(g.fields) { + g.fields[g.n] = i + g.caps[g.n] = c + g.n++ + } +} - v = walkIndexChain(v, hop.index) +// decode fills a struct field using a parsed path. grow is non-nil only for +// the outermost call, the one place slice growth can be tracked. +func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string, files []*multipart.FileHeader, grow *growTracker) error { + // Get the field walking the struct fields by index. Almost every path is + // one hop into a field of v, which needs none of the loop's bookkeeping. + if idx := parts[0].soleIndex; idx >= 0 && v.Kind() == reflect.Struct { + v = v.Field(idx) + } else if v = walkHops(v, parts[0].hops); !v.IsValid() { + // Unreachable behind an unsettable nil embedded pointer. + return nil } // Don't even bother for unexported fields. @@ -488,6 +792,29 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values return nil } + // Fast path: plain builtin scalar fields skip the converter/unmarshaler + // dispatch below; fastKind was validated at cache-build time. + if k := parts[0].field.fastKind; k != reflect.Invalid && len(parts) == 1 && !parts[0].elem { + val := "" + if len(values) > 0 { + val = values[len(values)-1] + } + if val == "" { + if d.zeroEmpty { + v.SetZero() + } + return nil + } + if _, ok := setBuiltinKind(v, k, val); !ok { + return ConversionError{ + Key: path, + Type: parts[0].field.typ, + Index: -1, + } + } + return nil + } + // Check multipart files if parts[0].field.isMultipart && handleMultipartField(v, files) { return nil @@ -510,18 +837,32 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values if idx > d.maxSize { return fmt.Errorf("%v index %d is larger than the configured maxSize %d", v.Kind(), idx, d.maxSize) } - if v.IsNil() || v.Len() < idx+1 { - // Grow into a fresh backing array: extending within existing - // capacity would write into memory the caller may still share - // through other slices aliasing the original array. - value := reflect.MakeSlice(t, idx+1, idx+1) - if v.Len() > 0 { - // Resize it. - reflect.Copy(value, v) + if n := idx + 1; v.IsNil() || v.Len() < n { + // Indices arrive in map order, so a slice is typically grown + // several times per call. Extending one this call allocated is + // free: the room past its length is ours and freshly zeroed. + owner := -1 + if grow != nil { + owner = parts[0].soleIndex + } + if owner >= 0 && n <= v.Cap() && grow.reserved(owner) >= n { + v.SetLen(n) + } else { + // Otherwise grow into a fresh backing array: extending within + // the existing capacity would write into memory the caller + // may still share through another slice aliasing it. + value := reflect.MakeSlice(t, n, d.growCap(n, owner >= 0)) + if v.Len() > 0 { + // Resize it. + reflect.Copy(value, v) + } + v.Set(value) + if owner >= 0 { + grow.record(owner, value.Cap()) + } } - v.Set(value) } - return d.decode(v.Index(idx), path, parts[1:], values, files) + return d.decode(v.Index(idx), path, parts[1:], values, files, nil) } // Get the converter early in case there is one for a slice type. @@ -560,73 +901,7 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values return d.decodeBuiltinSlice(v, t, path, values) } - itemsBuf := decodeValueBufferPool.Get().(*[]reflect.Value) - items := (*itemsBuf)[:0] - defer func() { - clear(items) - *itemsBuf = items[:0] - decodeValueBufferPool.Put(itemsBuf) - }() - - for key, value := range values { - if value == "" { - if d.zeroEmpty { - items = append(items, reflect.Zero(t.Elem())) - } - } else if m.IsValid { - u := reflect.New(elemT) - if m.IsSliceElementPtr { - u = reflect.New(reflect.PointerTo(elemT).Elem()) - } - um, _ := reflect.TypeAssert[encoding.TextUnmarshaler](u) - if err := um.UnmarshalText([]byte(value)); err != nil { - return ConversionError{ - Key: path, - Type: t, - Index: key, - Err: err, - } - } - if m.IsSliceElementPtr { - items = append(items, u.Elem().Addr()) - } else { - // u is always a pointer from reflect.New; store the - // pointed-to value. - items = append(items, u.Elem()) - } - } else if item := conv(value); item.IsValid() { - items = appendConvertedItem(items, item, elemT, isPtrElem) - } else { - if strings.IndexByte(value, ',') != -1 { - for value := range strings.SplitSeq(value, ",") { - if value == "" { - if d.zeroEmpty { - items = append(items, reflect.Zero(t.Elem())) - } - } else if item := conv(value); item.IsValid() { - items = appendConvertedItem(items, item, elemT, isPtrElem) - } else { - return ConversionError{ - Key: path, - Type: elemT, - Index: key, - } - } - } - } else { - return ConversionError{ - Key: path, - Type: elemT, - Index: key, - } - } - } - } - value := reflect.MakeSlice(t, len(items), len(items)) - for i, item := range items { - value.Index(i).Set(item) - } - v.Set(value) + return d.decodeBoxedSlice(v, t, elemT, path, values, conv, m, isPtrElem) } else { val := "" // Use the last value provided if any values were provided @@ -690,6 +965,81 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values return nil } +// decodeBoxedSlice decodes values into the slice field v whose elements have +// to round-trip through a reflect.Value: a custom converter, a +// TextUnmarshaler, or pointer elements. It is split out so that decode, which +// runs once per source key, carries no defer of its own. +func (d *Decoder) decodeBoxedSlice(v reflect.Value, t, elemT reflect.Type, path string, values []string, conv Converter, m unmarshaler, isPtrElem bool) error { + itemsBuf := decodeValueBufferPool.Get().(*[]reflect.Value) + items := (*itemsBuf)[:0] + defer func() { + clear(items) + *itemsBuf = items[:0] + decodeValueBufferPool.Put(itemsBuf) + }() + + for key, value := range values { + if value == "" { + if d.zeroEmpty { + items = append(items, reflect.Zero(t.Elem())) + } + } else if m.IsValid { + u := reflect.New(elemT) + if m.IsSliceElementPtr { + u = reflect.New(reflect.PointerTo(elemT).Elem()) + } + um, _ := reflect.TypeAssert[encoding.TextUnmarshaler](u) + if err := um.UnmarshalText([]byte(value)); err != nil { + return ConversionError{ + Key: path, + Type: t, + Index: key, + Err: err, + } + } + if m.IsSliceElementPtr { + items = append(items, u.Elem().Addr()) + } else { + // u is always a pointer from reflect.New; store the + // pointed-to value. + items = append(items, u.Elem()) + } + } else if item := conv(value); item.IsValid() { + items = appendConvertedItem(items, item, elemT, isPtrElem) + } else { + if strings.IndexByte(value, ',') != -1 { + for value := range strings.SplitSeq(value, ",") { + if value == "" { + if d.zeroEmpty { + items = append(items, reflect.Zero(t.Elem())) + } + } else if item := conv(value); item.IsValid() { + items = appendConvertedItem(items, item, elemT, isPtrElem) + } else { + return ConversionError{ + Key: path, + Type: elemT, + Index: key, + } + } + } + } else { + return ConversionError{ + Key: path, + Type: elemT, + Index: key, + } + } + } + } + value := reflect.MakeSlice(t, len(items), len(items)) + for i, item := range items { + value.Index(i).Set(item) + } + v.Set(value) + return nil +} + // appendConvertedItem converts a builtin/custom converter result to the slice // element type and appends it, wrapping it in a freshly allocated pointer for // pointer-element slices. The conversion must happen before the pointer wrap: @@ -725,12 +1075,33 @@ func (d *Decoder) decodeBuiltinSlice(v reflect.Value, t reflect.Type, path strin k := elemT.Kind() split := k != reflect.String - n := 0 - for _, value := range values { - if split { + n := len(values) + if split { + for _, value := range values { n += strings.Count(value, ",") } - n++ + // The counts already say whether any value holds a separator, so + // when none does the per-value scans below have nothing to find. + split = n > len(values) + } + + // Exact builtin slice types decode without per-element reflect calls; + // named slice or element types fall through to the generic path. + switch t { + case typSliceString: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeString) + case typSliceInt: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeInt) + case typSliceInt64: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeInt64) + case typSliceUint: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeUint) + case typSliceUint64: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeUint64) + case typSliceFloat64: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeFloat64) + case typSliceBool: + return decodeNativeSlice(d.zeroEmpty, v, path, values, elemT, n, split, parseNativeBool) } sl := reflect.MakeSlice(t, n, n) @@ -776,6 +1147,69 @@ func (d *Decoder) decodeBuiltinSlice(v reflect.Value, t reflect.Type, path strin return nil } +// Exact (unnamed) builtin slice types eligible for the native decode path. +var ( + typSliceString = reflect.TypeOf([]string(nil)) + typSliceInt = reflect.TypeOf([]int(nil)) + typSliceInt64 = reflect.TypeOf([]int64(nil)) + typSliceUint = reflect.TypeOf([]uint(nil)) + typSliceUint64 = reflect.TypeOf([]uint64(nil)) + typSliceFloat64 = reflect.TypeOf([]float64(nil)) + typSliceBool = reflect.TypeOf([]bool(nil)) +) + +// decodeNativeSlice mirrors the generic decodeBuiltinSlice loop for a field +// typed exactly []T, parsing into a native slice assigned only if every value +// parsed (all-or-nothing). n is the precomputed element upper bound. +func decodeNativeSlice[T any](zeroEmpty bool, v reflect.Value, path string, values []string, elemT reflect.Type, n int, split bool, parse func(string) (T, bool)) error { + out := make([]T, 0, n) + var zero T + for key, value := range values { + switch { + case value == "": + if zeroEmpty { + out = append(out, zero) + } + case split && strings.IndexByte(value, ',') != -1: + for item := range strings.SplitSeq(value, ",") { + if item == "" { + if zeroEmpty { + out = append(out, zero) + } + continue + } + ev, ok := parse(item) + if !ok { + return ConversionError{ + Key: path, + Type: elemT, + Index: key, + } + } + out = append(out, ev) + } + default: + ev, ok := parse(value) + if !ok { + return ConversionError{ + Key: path, + Type: elemT, + Index: key, + } + } + out = append(out, ev) + } + } + // v's type is exactly []T here (the dispatch switch guarantees it), and v + // is settable (decode returns before reaching here for a field it cannot + // set), so assign through a typed pointer to it: no reflect.ValueOf + // escape and no Set assignability checks. The pointer comes from + // UnsafeAddr rather than Addr().Interface(), which resolved the pointer + // type on every call and measured a fifth of the whole assignment's cost. + *(*[]T)(unsafe.Pointer(v.UnsafeAddr())) = out + return nil +} + func isTextUnmarshaler(v reflect.Value) unmarshaler { // Create a new unmarshaller instance m := unmarshaler{} @@ -841,18 +1275,21 @@ type ConversionError struct { Err error // low-level error (when it exists) } +// The error strings below are assembled by concatenation instead of +// fmt.Sprintf: %q is strconv.Quote and %d is utils.FormatInt, so the messages +// are byte-identical without the reflection-based formatter. func (e ConversionError) Error() string { var output string if e.Index < 0 { - output = fmt.Sprintf("schema: error converting value for %q", e.Key) + output = "schema: error converting value for " + strconv.Quote(e.Key) } else { - output = fmt.Sprintf("schema: error converting value for index %d of %q", - e.Index, e.Key) + output = "schema: error converting value for index " + + utils.FormatInt(int64(e.Index)) + " of " + strconv.Quote(e.Key) } if e.Err != nil { - output = fmt.Sprintf("%s. Details: %s", output, e.Err) + output += ". Details: " + e.Err.Error() } return output @@ -864,7 +1301,7 @@ type UnknownKeyError struct { } func (e UnknownKeyError) Error() string { - return fmt.Sprintf("schema: invalid path %q", e.Key) + return "schema: invalid path " + strconv.Quote(e.Key) } // EmptyFieldError stores information about an empty required field. @@ -873,7 +1310,7 @@ type EmptyFieldError struct { } func (e EmptyFieldError) Error() string { - return fmt.Sprintf("%v is empty", e.Key) + return e.Key + " is empty" } // MultiError stores multiple decoding errors. @@ -895,15 +1332,7 @@ func (e MultiError) Error() string { case 2: return s + " (and 1 other error)" } - return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1) -} - -func appendRequiredField(m map[string][]fieldWithPrefix, key string, field fieldWithPrefix) map[string][]fieldWithPrefix { - if m == nil { - m = make(map[string][]fieldWithPrefix) - } - m[key] = append(m[key], field) - return m + return s + " (and " + utils.FormatInt(int64(len(e)-1)) + " other errors)" } func appendError(m MultiError, key string, err error) MultiError { diff --git a/src/vendor/github.com/gofiber/schema/encoder.go b/src/vendor/github.com/gofiber/schema/encoder.go index b1d53b36..c85c4c9c 100644 --- a/src/vendor/github.com/gofiber/schema/encoder.go +++ b/src/vendor/github.com/gofiber/schema/encoder.go @@ -21,6 +21,13 @@ var errNotStruct = errors.New("schema: interface must be a struct") // would otherwise panic on the first map assignment. var errNilDst = errors.New("schema: dst map must not be nil") +// maxScratchValueLen bounds values stored in encode's shared scratch array, +// capping how much data a surviving dst entry can keep reachable after the +// caller deletes neighboring keys. Only strings allocated by this package's +// own formatters are eligible at all (see encField.scratchSafe), so the cap +// bounds real bytes, not just headers. +const maxScratchValueLen = 64 + // Encoder encodes values from a struct into url.Values. type Encoder struct { cache *cache @@ -43,6 +50,12 @@ type Encoder struct { type encPlan struct { fields []encField gen uint64 + // freshKeys reports that encoding a value of this type into an empty map + // writes every key exactly once: no two fields share a name, and no field + // is recursed into — a nested struct's keys land in the same map, without + // a prefix, so they could collide with these. encode can then assign each + // key outright instead of reading it back to append. + freshKeys bool } // encField is the precomputed encoding plan for one struct field. @@ -55,7 +68,16 @@ type encField struct { // recurseStructPtr marks pointer-to-struct fields without a custom // encoder: non-nil values are encoded by recursing into the element. recurseStructPtr bool - isStruct bool + // scratchSafe marks fields whose encoder output is allocated by this + // package (numeric/bool/float formatters), so it can never alias a large + // caller-owned buffer and may be batched in encode's shared scratch. + scratchSafe bool + // hasIsZero marks a struct-typed field whose type decides omitempty for + // itself through an IsZero method. Settling that here keeps the check off + // reflect.Value.Interface, which copies the struct to the heap every time + // it is asked — whether or not the method is there. + hasIsZero bool + isStruct bool // nilAsNull marks pointer fields whose element has no immediate // encoder (structs recursed via recurseStructPtr, or unsupported // types): nil values encode as "null", matching the closure behavior @@ -120,18 +142,18 @@ func (e *Encoder) SetAliasTag(tag string) { // on first use. The build reads the tag and registered encoders under the // configuration lock; the generation re-checks around the cache store keep a // build racing a reconfiguration from inserting a stale plan. -func (e *Encoder) structInfo(t reflect.Type) []encField { +func (e *Encoder) structInfo(t reflect.Type) (fields []encField, freshKeys bool) { //nolint:nonamedreturns // the bool is only readable named gen := e.encGen.Load() if cached, ok := e.encCache.Load(t); ok { // Ignore plans built under an older configuration; fall through and // rebuild (the fresh plan overwrites the stale entry). if p := cached.(*encPlan); p.gen == gen { - return p.fields + return p.fields, p.freshKeys } } e.cache.l.RLock() tag := e.cache.tag - fields := make([]encField, 0, t.NumField()) + fields = make([]encField, 0, t.NumField()) for i := 0; i < t.NumField(); i++ { sf := t.Field(i) name, opts := fieldAlias(sf, tag) @@ -146,7 +168,9 @@ func (e *Encoder) structInfo(t reflect.Type) []encField { recurseStructPtr: ft.Kind() == reflect.Ptr && ft.Elem().Kind() == reflect.Struct && !e.hasCustomEncoder(ft), - enc: typeEncoder(ft, e.regenc), + enc: typeEncoder(ft, e.regenc), + scratchSafe: scratchSafeEncoder(ft, e.regenc), + hasIsZero: ft.Kind() == reflect.Struct && ft.Implements(zeroerType), } if f.enc == nil { switch ft.Kind() { @@ -164,14 +188,65 @@ func (e *Encoder) structInfo(t reflect.Type) []encField { fields = append(fields, f) } e.cache.l.RUnlock() + freshKeys = writesEachKeyOnce(fields) // Don't cache a plan whose inputs (tag, registered encoders) changed // while it was being built; the next call rebuilds it fresh. Even if a // stale plan slips in after the clear, its generation tag keeps it from // ever being served. if e.encGen.Load() == gen { - e.encCache.Store(t, &encPlan{fields: fields, gen: gen}) + e.encCache.Store(t, &encPlan{fields: fields, gen: gen, freshKeys: freshKeys}) + } + return fields, freshKeys +} + +// writesEachKeyOnce reports whether the plan's fields write distinct keys and +// none recurses into a nested struct, whose keys land in the same map and +// could repeat one of these. +func writesEachKeyOnce(fields []encField) bool { + names := make(map[string]struct{}, len(fields)) + for i := range fields { + f := &fields[i] + if f.isStruct || f.recurseStructPtr { + return false + } + if _, dup := names[f.name]; dup { + return false + } + names[f.name] = struct{}{} + } + return true +} + +// zeroer is the optional method a type can provide to decide, for omitempty, +// whether a value of it counts as empty. +type zeroer interface{ IsZero() bool } + +var zeroerType = reflect.TypeFor[zeroer]() + +// isZeroValue applies omitempty to one of this field's values: isZero with +// the struct case answered from the plan, so neither outcome goes through +// reflect.Value.Interface. An addressable struct becomes an interface through +// its address, without a copy, and a type known to lack IsZero skips the +// conversion altogether. +func (f *encField) isZeroValue(v reflect.Value) bool { + if v.Kind() != reflect.Struct || !v.CanInterface() { + return isZero(v) + } + if f.hasIsZero { + if v.CanAddr() { + // A value receiver's IsZero is in the pointer's method set too. + iz, _ := reflect.TypeAssert[zeroer](v.Addr()) + return iz.IsZero() + } + iz, _ := reflect.TypeAssert[zeroer](v) + return iz.IsZero() + } + for i := 0; i < v.NumField(); i++ { + if !isZero(v.Field(i)) { + return false + } } - return fields + return true } func isZero(v reflect.Value) bool { @@ -213,7 +288,40 @@ func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error { var errs MultiError - fields := e.structInfo(v.Type()) + fields, freshKeys := e.structInfo(v.Type()) + // When dst starts empty (fresh url.Values), single short package-allocated + // values of distinct keys share one backing array instead of allocating a + // 1-element slice each; the three-index slice caps entries so later + // appends cannot overwrite a neighbor. Caller-derived strings (string + // fields, custom encoders) and long values get their own independently + // collectible slice so a surviving entry cannot keep a deleted neighbor's + // allocation alive; a non-empty dst keeps the single-map-op append pattern. + useScratch := len(dst) == 0 + // An empty dst plus a plan that writes every key once means each key is + // new, so the read append needs — a second hash of the key — is skipped. + fresh := useScratch && freshKeys + var scratch []string + appendValue := func(name, s string, scratchSafe bool) { + if !useScratch || !scratchSafe || len(s) > maxScratchValueLen { + if fresh { + dst[name] = []string{s} + return + } + dst[name] = append(dst[name], s) + return + } + if !fresh { + if old := dst[name]; old != nil { + dst[name] = append(old, s) + return + } + } + if scratch == nil { + scratch = make([]string, 0, len(fields)) + } + scratch = append(scratch, s) + dst[name] = scratch[len(scratch)-1 : len(scratch) : len(scratch)] + } for i := range fields { f := &fields[i] fieldValue := v.Field(f.idx) @@ -228,10 +336,10 @@ func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error { // Encode non-slice types and custom implementations immediately. if f.enc != nil { - if f.omitEmpty && isZero(fieldValue) { + if f.omitEmpty && f.isZeroValue(fieldValue) { continue } - dst[f.name] = append(dst[f.name], f.enc(fieldValue)) + appendValue(f.name, f.enc(fieldValue), f.scratchSafe) continue } @@ -239,7 +347,8 @@ func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error { if f.omitEmpty { continue } - dst[f.name] = append(dst[f.name], "null") + // The "null" literal is static data; always scratch-safe. + appendValue(f.name, "null", true) continue } @@ -312,6 +421,27 @@ func (e *Encoder) hasCustomEncoder(t reflect.Type) bool { return exists } +// scratchSafeEncoder reports whether typeEncoder(t, reg)'s output strings are +// always allocated by this package's own formatters: string fields return the +// caller's string and custom encoders may return anything — either could be a +// small substring aliasing a large buffer, so neither may enter the scratch. +func scratchSafeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) bool { + if _, ok := reg[t]; ok { + return false + } + switch t.Kind() { + case reflect.Bool, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Float32, reflect.Float64: + return true + case reflect.Ptr: + return scratchSafeEncoder(t.Elem(), reg) + default: + return false + } +} + func typeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) encoderFunc { if f, ok := reg[t]; ok { return f @@ -320,9 +450,21 @@ func typeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) encoderFunc { switch t.Kind() { case reflect.Bool: return encodeBool - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + case reflect.Int8: + return encodeInt8 + case reflect.Int16: + return encodeInt16 + case reflect.Int32: + return encodeInt32 + case reflect.Int, reflect.Int64: return encodeInt - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case reflect.Uint8: + return encodeUint8 + case reflect.Uint16: + return encodeUint16 + case reflect.Uint32: + return encodeUint32 + case reflect.Uint, reflect.Uint64: return encodeUint case reflect.Float32: return encodeFloat32 @@ -353,16 +495,44 @@ func encodeBool(v reflect.Value) string { return strconv.FormatBool(v.Bool()) } +// Integers go through the width-specific utils helpers: the 8-bit ones are +// table lookups, allocating nothing, and the 32-bit ones skip a digit group +// the 64-bit formatter has to consider. + func encodeInt(v reflect.Value) string { return utils.FormatInt(v.Int()) } +func encodeInt8(v reflect.Value) string { + return utils.FormatInt8(int8(v.Int())) +} + +func encodeInt16(v reflect.Value) string { + return utils.FormatInt16(int16(v.Int())) +} + +func encodeInt32(v reflect.Value) string { + return utils.FormatInt32(int32(v.Int())) +} + func encodeUint(v reflect.Value) string { return utils.FormatUint(v.Uint()) } +func encodeUint8(v reflect.Value) string { + return utils.FormatUint8(uint8(v.Uint())) +} + +func encodeUint16(v reflect.Value) string { + return utils.FormatUint16(uint16(v.Uint())) +} + +func encodeUint32(v reflect.Value) string { + return utils.FormatUint32(uint32(v.Uint())) +} + func encodeFloat(v reflect.Value, bits int) string { - return strconv.FormatFloat(v.Float(), 'f', 6, bits) + return formatFloatFixed(v.Float(), bits) } func encodeFloat32(v reflect.Value) string { diff --git a/src/vendor/github.com/gofiber/schema/floatfmt.go b/src/vendor/github.com/gofiber/schema/floatfmt.go new file mode 100644 index 00000000..a68fa461 --- /dev/null +++ b/src/vendor/github.com/gofiber/schema/floatfmt.go @@ -0,0 +1,105 @@ +package schema + +import ( + "math" + "math/bits" + "strconv" + + utils "github.com/gofiber/utils/v2" +) + +// encFloatPrec is the number of fractional digits the encoder emits for +// float fields. +const encFloatPrec = 6 + +// scaleFixed is 10^encFloatPrec, the factor that turns a value into the +// integer the formatter prints. +const scaleFixed = 1_000_000 + +// fastFixedLimit bounds the magnitude the exact-integer path accepts: below +// it |value|*10^6 stays under 10^18, so the scaled result and a round-up's +1 +// both fit a uint64. +const fastFixedLimit = 1e12 + +// formatFloatFixed is strconv.FormatFloat(f, 'f', encFloatPrec, bitSize). +// +// strconv has no Ryū fast path for the 'f' verb with a fixed precision (see +// the `fmt != 'f'` guard in its ftoa), so every such call runs the +// multi-precision decimal path. A float's exact value is mant*2^exp, so for +// exponents in range the printed digits are exactly +// round-half-to-even(mant*10^6 * 2^exp), which a 128-bit multiply and a shift +// compute directly; utils.AppendUint then lays down the digits. Inf, NaN and +// magnitudes outside the fast range fall back to strconv. +func formatFloatFixed(f float64, bitSize int) string { + if bitSize == 32 { + // strconv formats the float32 value, which is what the decomposition + // below must see. + f = float64(float32(f)) + } + + u := math.Float64bits(f) + neg := u>>63 != 0 + biasedExp := int(u>>52) & 0x7FF + mant := u & (1<<52 - 1) + if biasedExp == 0x7FF { + // Inf or NaN. + return strconv.FormatFloat(f, 'f', encFloatPrec, bitSize) + } + if biasedExp == 0 { + biasedExp = 1 // subnormal: no implicit leading bit + } else { + mant |= 1 << 52 + } + // f == mant * 2^exp exactly. + exp := biasedExp - 1023 - 52 + // exp >= 0 means |f| >= 2^52, where f*10^6 overflows a uint64; the + // magnitude check bounds the scaled value for everything else. + if exp >= 0 || f > fastFixedLimit || f < -fastFixedLimit { + return strconv.FormatFloat(f, 'f', encFloatPrec, bitSize) + } + + // n = round-half-to-even(mant*10^6 / 2^k), computed on the exact + // 128-bit product so the tie test sees the value's true remainder. + k := uint(-exp) + hi, lo := bits.Mul64(mant, scaleFixed) + var n uint64 + switch { + case k >= 74: + // mant*10^6 < 2^73 <= 2^(k-1), i.e. below half a unit: rounds to 0. + n = 0 + case k < 64: + n = lo>>k | hi<<(64-k) + half := uint64(1) << (k - 1) + if r := lo & (half<<1 - 1); r > half || (r == half && n&1 != 0) { + n++ + } + case k == 64: + n = hi + if lo > 1<<63 || (lo == 1<<63 && n&1 != 0) { + n++ + } + default: + s := k - 64 + n = hi >> s + half := uint64(1) << (s - 1) + // The discarded bits are hi's low s bits followed by all of lo, so + // a tie needs the half bit set and every lower bit clear. + if r := hi & (half<<1 - 1); r > half || (r == half && (lo != 0 || n&1 != 0)) { + n++ + } + } + + // Sign, integer digits (at most 13), '.', then six fractional digits. + var buf [24]byte + dst := buf[:0] + if neg { + dst = append(dst, '-') + } + dst = utils.AppendUint(dst, n/scaleFixed) + dst = append(dst, '.') + // Formatting 10^6+frac and dropping its leading '1' zero-pads the + // fraction without a per-digit loop. + var frac [8]byte + dst = append(dst, utils.AppendUint(frac[:0], scaleFixed+n%scaleFixed)[1:]...) + return string(dst) +} diff --git a/src/vendor/github.com/gofiber/schema/values.go b/src/vendor/github.com/gofiber/schema/values.go new file mode 100644 index 00000000..9000349f --- /dev/null +++ b/src/vendor/github.com/gofiber/schema/values.go @@ -0,0 +1,225 @@ +package schema + +import ( + "errors" + "hash/maphash" +) + +// errValuesLength is returned by DecodeValues for keys and values of +// different lengths. +var errValuesLength = errors.New("schema: keys and values differ in length") + +const ( + // maxInlinePairs is how many pairs DecodeValues groups in arrays on its + // own stack; more are grouped in slices allocated for the call. + maxInlinePairs = 32 + // maxScanPairs is how many pairs are grouped by comparing each key with + // the keys before it rather than through a hash table, which for so few + // costs more to hash than to compare. + maxScanPairs = 8 +) + +// source is what a decode reads the values of a key from: the map Decode was +// given, or the pairs DecodeValues was, grouped by key. It is a struct rather +// than an interface so that a DecodeValues call's index, held on its stack, +// does not escape through a method call the compiler cannot see into. +type source struct { + m map[string][]string + pairs *pairIndex +} + +// lookup returns the values of key as far as the required-key and default +// checks read them, which is whether there are any and what the first one is: +// all of them from a map, and the first alone from pairs, which saves +// gathering them. It reports whether src has the key. +func (src *source) lookup(key string) ([]string, bool) { + if src.pairs != nil { + if i := src.pairs.find(key); i >= 0 { + return src.pairs.values[i : i+1 : i+1], true + } + return nil, false + } + v, ok := src.m[key] + return v, ok +} + +// hasBytes reports whether src has the key held in key. +func (src *source) hasBytes(key []byte) bool { + if src.pairs != nil { + return src.pairs.findBytes(key) >= 0 + } + _, ok := src.m[string(key)] + return ok +} + +// pairIndex groups key/value pairs by key without building a map: keys are +// hashed into an open-addressing table that holds the first pair of each +// key, or for a few pairs compared with the keys before them, and each pair +// links to the next with the same key. A key's values are then the values of +// its pairs, which a single pair or a run of adjacent ones hands out as a +// subslice of values, and any other pattern gathers into a buffer of the +// caller's. +// +// The keys are the request's, so the table hashes them as a Go map would: +// exactly, as they are grouped, and with a seed drawn per process (see +// pairSeed), so no choice of keys can pile them onto one slot. +// +// DecodeValues sets its slices on it where it lies, and its methods store +// integers only, into those slices and mask: a slice stored through a pointer +// to it would count, for the compiler, as a store to the heap, and take the +// arrays DecodeValues keeps the index in on its stack with it. +type pairIndex struct { + keys, values []string + // table holds, for each key, its first pair plus one, so that 0 marks a + // free slot; it is a power of two long and at most half full, and nil + // for maxScanPairs pairs or fewer + table []int32 + // next holds, for each pair, the next pair with the same key plus one, + // or 0 for its key's last pair + next []int32 + // last holds, for a key's first pair, the key's last pair, and -1 for + // every other pair + last []int32 + mask uint64 +} + +// pairSeed seeds the hash of pairIndex. A hash an attacker could predict, +// or one under which distinct keys collide by construction, as keys that +// differ only in case do under a case-folding hash, would let a request +// with enough such keys make every insert probe past all the keys before +// it, quadratic in their number. +var pairSeed = maphash.MakeSeed() + +// pairHash is the hash pairIndex keeps key in, and pairHashBytes the same +// hash of a key held in a byte slice. +func pairHash(key string) uint64 { return maphash.String(pairSeed, key) } + +func pairHashBytes(key []byte) uint64 { return maphash.Bytes(pairSeed, key) } + +// indexSize returns the table length that indexes n pairs. +func indexSize(n int) int { + size := 2 + for size < 2*n { + size *= 2 + } + return size +} + +// index fills in the index of the pairs p.keys[i]=p.values[i], kept in +// p.table, p.next and p.last, which must be zeroed and sized +// indexSize(len(p.keys)) (or nil, for maxScanPairs pairs or fewer), +// len(p.keys) and len(p.keys). +func (p *pairIndex) index() { + if p.table == nil { + p.scan() + return + } + p.mask = uint64(len(p.table) - 1) + p.build() +} + +// scan fills in the index of p's pairs, few enough to compare each key with +// the first pairs before it. +func (p *pairIndex) scan() { + keys := p.keys + for i, key := range keys { + p.last[i] = int32(i) //nolint:gosec // G115 - bounded by the number of pairs + for first := range i { + if p.last[first] >= 0 && keys[first] == key { + p.next[p.last[first]] = int32(i + 1) //nolint:gosec // G115 - bounded by the number of pairs + p.last[first] = int32(i) //nolint:gosec // G115 - bounded by the number of pairs + p.last[i] = -1 + break + } + } + } +} + +// build fills in the index of p's pairs through the hash table. +func (p *pairIndex) build() { + keys := p.keys + for i, key := range keys { + for j := pairHash(key) & p.mask; ; j = (j + 1) & p.mask { + e := p.table[j] + if e == 0 { + p.table[j] = int32(i + 1) //nolint:gosec // G115 - bounded by the number of pairs + p.last[i] = int32(i) //nolint:gosec // G115 - bounded by the number of pairs + break + } + if first := e - 1; keys[first] == key { + p.next[p.last[first]] = int32(i + 1) //nolint:gosec // G115 - bounded by the number of pairs + p.last[first] = int32(i) //nolint:gosec // G115 - bounded by the number of pairs + p.last[i] = -1 + break + } + } + } +} + +// first reports whether pair i is the first pair of its key. +func (p *pairIndex) first(i int) bool { + return p.last[i] >= 0 +} + +// find returns the first pair of key, or -1 when no pair has it. +func (p *pairIndex) find(key string) int { + if p.table == nil { + for first, k := range p.keys { + if p.last[first] >= 0 && k == key { + return first + } + } + return -1 + } + for j := pairHash(key) & p.mask; ; j = (j + 1) & p.mask { + e := p.table[j] + if e == 0 { + return -1 + } + if first := int(e - 1); p.keys[first] == key { + return first + } + } +} + +// findBytes is find for a key held in a byte slice. +func (p *pairIndex) findBytes(key []byte) int { + if p.table == nil { + for first, k := range p.keys { + if p.last[first] >= 0 && k == string(key) { + return first + } + } + return -1 + } + for j := pairHashBytes(key) & p.mask; ; j = (j + 1) & p.mask { + e := p.table[j] + if e == 0 { + return -1 + } + if first := int(e - 1); p.keys[first] == string(key) { + return first + } + } +} + +// group returns the values of the key whose first pair is i, capped at their +// length: a subslice of values when its pairs are adjacent, else the values +// appended to scratch. +func (p *pairIndex) group(i int, scratch []string) []string { + end := i + for n := p.next[end]; n != 0; n = p.next[end] { + if int(n-1) != end+1 { + for { + scratch = append(scratch, p.values[i]) + n := p.next[i] + if n == 0 { + return scratch[:len(scratch):len(scratch)] + } + i = int(n - 1) + } + } + end++ + } + return p.values[i : end+1 : end+1] +} diff --git a/src/vendor/github.com/gofiber/utils/v2/AGENTS.md b/src/vendor/github.com/gofiber/utils/v2/AGENTS.md index dce12257..76cb29f2 100644 --- a/src/vendor/github.com/gofiber/utils/v2/AGENTS.md +++ b/src/vendor/github.com/gofiber/utils/v2/AGENTS.md @@ -15,6 +15,7 @@ gofiber/utils is a helper library for [Fiber](https://github.com/gofiber/fiber) ## Conventions - Performance claims are verified with benchstat (base vs. head on the same machine, at least `-count=10`), never with single runs. -- `make test` runs the suite with race detector and shuffle; `make lint` runs golangci-lint; `make format` applies gofumpt; `make benchfmt` aligns the benchmark tables in README.md. +- `make test` runs the suite with race detector and shuffle; `make lint` runs golangci-lint; `make format` applies gofumpt; `make benchfmt` aligns the benchmark tables in README.md and `make benchupdate` re-measures them. - README.md is a function catalog with benchmark blocks. New exported functions need a README section, and benchmark numbers for touched paths should be regenerated in the same run. +- Each benchmark block starts with the `go test` command that produced it; `make benchupdate` re-runs that command and refreshes the values of the rows it reports, leaving rows it does not measure alone. A maintainer can trigger the same thing on a pull request by commenting `/bench-readme` (arm64) or `/bench-readme-amd64`. - Code, comments, commit messages, and PR text are always written in English. diff --git a/src/vendor/github.com/gofiber/utils/v2/Makefile b/src/vendor/github.com/gofiber/utils/v2/Makefile index 5f0b50fd..41664d0a 100644 --- a/src/vendor/github.com/gofiber/utils/v2/Makefile +++ b/src/vendor/github.com/gofiber/utils/v2/Makefile @@ -31,7 +31,12 @@ format: ## benchfmt: 📝 Format README benchmark lines .PHONY: benchfmt benchfmt: - go run ./scripts/format_benchmarks.go + go run ./scripts + +## benchupdate: 📊 Re-run the README benchmarks and refresh their numbers (ARGS="-block N" for one table) +.PHONY: benchupdate +benchupdate: + go run ./scripts -update $(ARGS) ## lint: 🚨 Run lint checks .PHONY: lint diff --git a/src/vendor/github.com/gofiber/utils/v2/README.md b/src/vendor/github.com/gofiber/utils/v2/README.md index 3e8afccb..374ef68a 100644 --- a/src/vendor/github.com/gofiber/utils/v2/README.md +++ b/src/vendor/github.com/gofiber/utils/v2/README.md @@ -13,6 +13,10 @@ A collection of common functions for [Fiber](https://github.com/gofiber/fiber) w Per-commit benchmark charts: +Each table below starts with the `go test` command that produced it. Maintainers refresh the +numbers with `make benchupdate`, or by commenting `/bench-readme` (arm64) or +`/bench-readme-amd64` on a pull request. + Environment: goos: darwin goarch: arm64 @@ -24,425 +28,442 @@ cpu: Apple M2 Pro // (swar's Benchmark_Load8_Fusion, an advisory codegen guard, is deliberately omitted) # Case Conversion -Benchmark_ToLowerBytes/empty/fiber-12 599341221 1.970 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/empty/fiber/unsafe-12 613673802 1.951 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/empty/default-12 363300402 3.316 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/http-get/fiber-12 350302147 3.434 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/http-get/fiber/unsafe-12 250488015 4.803 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/http-get/default-12 65883986 18.03 ns/op 8 B/op 1 allocs/op -Benchmark_ToLowerBytes/http-get-upper/fiber-12 95234625 12.53 ns/op 3 B/op 1 allocs/op -Benchmark_ToLowerBytes/http-get-upper/fiber/unsafe-12 242418936 4.802 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/http-get-upper/default-12 86405012 13.85 ns/op 8 B/op 1 allocs/op -Benchmark_ToLowerBytes/header-content-type-mixed/fiber-12 52263289 22.74 ns/op 48 B/op 1 allocs/op -Benchmark_ToLowerBytes/header-content-type-mixed/fiber/unsafe-12 131711175 9.101 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/header-content-type-mixed/default-12 25312339 47.13 ns/op 48 B/op 1 allocs/op -Benchmark_ToLowerBytes/large-lower/fiber-12 120148472 10.02 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/large-lower/fiber/unsafe-12 100000000 10.57 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/large-lower/default-12 16746064 71.43 ns/op 64 B/op 1 allocs/op -Benchmark_ToLowerBytes/large-upper/fiber-12 46270634 26.82 ns/op 64 B/op 1 allocs/op -Benchmark_ToLowerBytes/large-upper/fiber/unsafe-12 100000000 10.71 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/large-upper/default-12 15734505 76.92 ns/op 64 B/op 1 allocs/op -Benchmark_ToLowerBytes/large-mixed/fiber-12 46607823 26.06 ns/op 64 B/op 1 allocs/op -Benchmark_ToLowerBytes/large-mixed/fiber/unsafe-12 100000000 10.86 ns/op 0 B/op 0 allocs/op -Benchmark_ToLowerBytes/large-mixed/default-12 16291084 73.76 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpperBytes/empty/fiber-12 607678140 1.976 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/empty/fiber/unsafe-12 611928006 1.981 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/empty/default-12 362632894 3.309 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/http-get/fiber-12 95358867 12.55 ns/op 3 B/op 1 allocs/op -Benchmark_ToUpperBytes/http-get/fiber/unsafe-12 249490471 4.905 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/http-get/default-12 79248020 14.63 ns/op 8 B/op 1 allocs/op -Benchmark_ToUpperBytes/http-get-upper/fiber-12 365516280 3.330 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/http-get-upper/fiber/unsafe-12 249981619 4.803 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/http-get-upper/default-12 64343162 19.01 ns/op 8 B/op 1 allocs/op -Benchmark_ToUpperBytes/header-content-type-mixed/fiber-12 52506741 22.69 ns/op 48 B/op 1 allocs/op -Benchmark_ToUpperBytes/header-content-type-mixed/fiber/unsafe-12 130478352 9.350 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/header-content-type-mixed/default-12 22415607 54.44 ns/op 48 B/op 1 allocs/op -Benchmark_ToUpperBytes/large-lower/fiber-12 44765679 26.92 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpperBytes/large-lower/fiber/unsafe-12 100000000 13.68 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/large-lower/default-12 14464340 110.7 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpperBytes/large-upper/fiber-12 100000000 11.98 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/large-upper/fiber/unsafe-12 83808488 13.94 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/large-upper/default-12 13142096 87.35 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpperBytes/large-mixed/fiber-12 33038661 32.75 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpperBytes/large-mixed/fiber/unsafe-12 100000000 10.93 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpperBytes/large-mixed/default-12 15034422 98.27 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpper/empty/fiber-12 595298628 2.309 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/empty/fiber/unsafe-12 595273404 2.021 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/empty/default-12 636980288 1.883 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/http-get/fiber-12 97025577 12.40 ns/op 3 B/op 1 allocs/op -Benchmark_ToUpper/http-get/fiber/unsafe-12 244711635 4.857 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/http-get/default-12 59790234 19.54 ns/op 8 B/op 1 allocs/op -Benchmark_ToUpper/http-get-upper/fiber-12 383218539 3.056 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/http-get-upper/fiber/unsafe-12 247851331 4.864 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/http-get-upper/default-12 223044249 5.182 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/header-content-type-mixed/fiber-12 52628502 24.13 ns/op 48 B/op 1 allocs/op -Benchmark_ToUpper/header-content-type-mixed/fiber/unsafe-12 127726341 9.233 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/header-content-type-mixed/default-12 11549816 104.0 ns/op 48 B/op 1 allocs/op -Benchmark_ToUpper/large-lower/fiber-12 42409070 26.04 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpper/large-lower/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/large-lower/default-12 7051911 169.0 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpper/large-upper/fiber-12 123837582 9.590 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/large-upper/fiber/unsafe-12 100000000 10.83 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/large-upper/default-12 19115356 61.51 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/large-mixed/fiber-12 45872143 27.77 ns/op 64 B/op 1 allocs/op -Benchmark_ToUpper/large-mixed/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op -Benchmark_ToUpper/large-mixed/default-12 5927710 203.1 ns/op 64 B/op 1 allocs/op -Benchmark_ToLower/empty/fiber-12 613625554 1.952 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/empty/fiber/unsafe-12 572670608 1.989 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/empty/default-12 644769141 1.863 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/http-get/fiber-12 395302272 3.034 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/http-get/fiber/unsafe-12 252231990 4.813 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/http-get/default-12 284202345 4.219 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/http-get-upper/fiber-12 100000000 12.08 ns/op 3 B/op 1 allocs/op -Benchmark_ToLower/http-get-upper/fiber/unsafe-12 252859507 4.816 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/http-get-upper/default-12 60415860 19.54 ns/op 8 B/op 1 allocs/op -Benchmark_ToLower/header-content-type-mixed/fiber-12 53446660 22.49 ns/op 48 B/op 1 allocs/op -Benchmark_ToLower/header-content-type-mixed/fiber/unsafe-12 131152108 9.153 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/header-content-type-mixed/default-12 18039788 66.79 ns/op 48 B/op 1 allocs/op -Benchmark_ToLower/large-lower/fiber-12 120227584 9.982 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/large-lower/fiber/unsafe-12 100000000 10.68 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/large-lower/default-12 24070928 48.79 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/large-upper/fiber-12 44699118 25.92 ns/op 64 B/op 1 allocs/op -Benchmark_ToLower/large-upper/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/large-upper/default-12 7075200 170.0 ns/op 64 B/op 1 allocs/op -Benchmark_ToLower/large-mixed/fiber-12 46426453 26.01 ns/op 64 B/op 1 allocs/op -Benchmark_ToLower/large-mixed/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op -Benchmark_ToLower/large-mixed/default-12 5682778 204.3 ns/op 64 B/op 1 allocs/op +Benchmark_ToLowerBytes/empty/fiber-12 599341221 1.970 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/empty/fiber/unsafe-12 613673802 1.951 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/empty/default-12 363300402 3.316 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/http-get/fiber-12 350302147 3.434 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/http-get/fiber/unsafe-12 250488015 4.803 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/http-get/default-12 65883986 18.03 ns/op 8 B/op 1 allocs/op +Benchmark_ToLowerBytes/http-get-upper/fiber-12 95234625 12.53 ns/op 3 B/op 1 allocs/op +Benchmark_ToLowerBytes/http-get-upper/fiber/unsafe-12 242418936 4.802 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/http-get-upper/default-12 86405012 13.85 ns/op 8 B/op 1 allocs/op +Benchmark_ToLowerBytes/header-content-type-mixed/fiber-12 52263289 22.74 ns/op 48 B/op 1 allocs/op +Benchmark_ToLowerBytes/header-content-type-mixed/fiber/unsafe-12 131711175 9.101 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/header-content-type-mixed/default-12 25312339 47.13 ns/op 48 B/op 1 allocs/op +Benchmark_ToLowerBytes/large-lower/fiber-12 120148472 10.02 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/large-lower/fiber/unsafe-12 100000000 10.57 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/large-lower/default-12 16746064 71.43 ns/op 64 B/op 1 allocs/op +Benchmark_ToLowerBytes/large-upper/fiber-12 46270634 26.82 ns/op 64 B/op 1 allocs/op +Benchmark_ToLowerBytes/large-upper/fiber/unsafe-12 100000000 10.71 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/large-upper/default-12 15734505 76.92 ns/op 64 B/op 1 allocs/op +Benchmark_ToLowerBytes/large-mixed/fiber-12 46607823 26.06 ns/op 64 B/op 1 allocs/op +Benchmark_ToLowerBytes/large-mixed/fiber/unsafe-12 100000000 10.86 ns/op 0 B/op 0 allocs/op +Benchmark_ToLowerBytes/large-mixed/default-12 16291084 73.76 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpperBytes/empty/fiber-12 607678140 1.976 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/empty/fiber/unsafe-12 611928006 1.981 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/empty/default-12 362632894 3.309 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/http-get/fiber-12 95358867 12.55 ns/op 3 B/op 1 allocs/op +Benchmark_ToUpperBytes/http-get/fiber/unsafe-12 249490471 4.905 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/http-get/default-12 79248020 14.63 ns/op 8 B/op 1 allocs/op +Benchmark_ToUpperBytes/http-get-upper/fiber-12 365516280 3.330 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/http-get-upper/fiber/unsafe-12 249981619 4.803 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/http-get-upper/default-12 64343162 19.01 ns/op 8 B/op 1 allocs/op +Benchmark_ToUpperBytes/header-content-type-mixed/fiber-12 52506741 22.69 ns/op 48 B/op 1 allocs/op +Benchmark_ToUpperBytes/header-content-type-mixed/fiber/unsafe-12 130478352 9.350 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/header-content-type-mixed/default-12 22415607 54.44 ns/op 48 B/op 1 allocs/op +Benchmark_ToUpperBytes/large-lower/fiber-12 44765679 26.92 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpperBytes/large-lower/fiber/unsafe-12 100000000 13.68 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/large-lower/default-12 14464340 110.7 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpperBytes/large-upper/fiber-12 100000000 11.98 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/large-upper/fiber/unsafe-12 83808488 13.94 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/large-upper/default-12 13142096 87.35 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpperBytes/large-mixed/fiber-12 33038661 32.75 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpperBytes/large-mixed/fiber/unsafe-12 100000000 10.93 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpperBytes/large-mixed/default-12 15034422 98.27 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpper/empty/fiber-12 595298628 2.309 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/empty/fiber/unsafe-12 595273404 2.021 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/empty/default-12 636980288 1.883 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/http-get/fiber-12 97025577 12.40 ns/op 3 B/op 1 allocs/op +Benchmark_ToUpper/http-get/fiber/unsafe-12 244711635 4.857 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/http-get/default-12 59790234 19.54 ns/op 8 B/op 1 allocs/op +Benchmark_ToUpper/http-get-upper/fiber-12 383218539 3.056 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/http-get-upper/fiber/unsafe-12 247851331 4.864 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/http-get-upper/default-12 223044249 5.182 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/header-content-type-mixed/fiber-12 52628502 24.13 ns/op 48 B/op 1 allocs/op +Benchmark_ToUpper/header-content-type-mixed/fiber/unsafe-12 127726341 9.233 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/header-content-type-mixed/default-12 11549816 104.0 ns/op 48 B/op 1 allocs/op +Benchmark_ToUpper/large-lower/fiber-12 42409070 26.04 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpper/large-lower/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/large-lower/default-12 7051911 169.0 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpper/large-upper/fiber-12 123837582 9.590 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/large-upper/fiber/unsafe-12 100000000 10.83 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/large-upper/default-12 19115356 61.51 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/large-mixed/fiber-12 45872143 27.77 ns/op 64 B/op 1 allocs/op +Benchmark_ToUpper/large-mixed/fiber/unsafe-12 100000000 11.00 ns/op 0 B/op 0 allocs/op +Benchmark_ToUpper/large-mixed/default-12 5927710 203.1 ns/op 64 B/op 1 allocs/op +Benchmark_ToLower/empty/fiber-12 613625554 1.952 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/empty/fiber/unsafe-12 572670608 1.989 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/empty/default-12 644769141 1.863 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/http-get/fiber-12 395302272 3.034 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/http-get/fiber/unsafe-12 252231990 4.813 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/http-get/default-12 284202345 4.219 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/http-get-upper/fiber-12 100000000 12.08 ns/op 3 B/op 1 allocs/op +Benchmark_ToLower/http-get-upper/fiber/unsafe-12 252859507 4.816 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/http-get-upper/default-12 60415860 19.54 ns/op 8 B/op 1 allocs/op +Benchmark_ToLower/header-content-type-mixed/fiber-12 53446660 22.49 ns/op 48 B/op 1 allocs/op +Benchmark_ToLower/header-content-type-mixed/fiber/unsafe-12 131152108 9.153 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/header-content-type-mixed/default-12 18039788 66.79 ns/op 48 B/op 1 allocs/op +Benchmark_ToLower/large-lower/fiber-12 120227584 9.982 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/large-lower/fiber/unsafe-12 100000000 10.68 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/large-lower/default-12 24070928 48.79 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/large-upper/fiber-12 44699118 25.92 ns/op 64 B/op 1 allocs/op +Benchmark_ToLower/large-upper/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/large-upper/default-12 7075200 170.0 ns/op 64 B/op 1 allocs/op +Benchmark_ToLower/large-mixed/fiber-12 46426453 26.01 ns/op 64 B/op 1 allocs/op +Benchmark_ToLower/large-mixed/fiber/unsafe-12 100000000 10.74 ns/op 0 B/op 0 allocs/op +Benchmark_ToLower/large-mixed/default-12 5682778 204.3 ns/op 64 B/op 1 allocs/op # Add Trailing Slash -Benchmark_AddTrailingSlashBytes/empty-12 1000000000 0.5857 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashBytes/slash-only-12 1000000000 0.8694 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashBytes/short-no-slash-12 100000000 11.65 ns/op 4 B/op 1 allocs/op -Benchmark_AddTrailingSlashBytes/short-with-slash-12 1000000000 0.8867 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashBytes/path-no-slash-12 93543546 13.36 ns/op 16 B/op 1 allocs/op -Benchmark_AddTrailingSlashBytes/path-with-slash-12 1000000000 0.9011 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashString/empty-12 1000000000 0.2926 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashString/slash-only-12 1000000000 0.4482 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashString/short-no-slash-12 100000000 11.37 ns/op 4 B/op 1 allocs/op -Benchmark_AddTrailingSlashString/short-with-slash-12 1000000000 0.4502 ns/op 0 B/op 0 allocs/op -Benchmark_AddTrailingSlashString/path-no-slash-12 82427726 14.41 ns/op 16 B/op 1 allocs/op -Benchmark_AddTrailingSlashString/path-with-slash-12 1000000000 0.4529 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashBytes/empty-12 1000000000 0.5857 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashBytes/slash-only-12 1000000000 0.8694 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashBytes/short-no-slash-12 100000000 11.65 ns/op 4 B/op 1 allocs/op +Benchmark_AddTrailingSlashBytes/short-with-slash-12 1000000000 0.8867 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashBytes/path-no-slash-12 93543546 13.36 ns/op 16 B/op 1 allocs/op +Benchmark_AddTrailingSlashBytes/path-with-slash-12 1000000000 0.9011 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashString/empty-12 1000000000 0.2926 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashString/slash-only-12 1000000000 0.4482 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashString/short-no-slash-12 100000000 11.37 ns/op 4 B/op 1 allocs/op +Benchmark_AddTrailingSlashString/short-with-slash-12 1000000000 0.4502 ns/op 0 B/op 0 allocs/op +Benchmark_AddTrailingSlashString/path-no-slash-12 82427726 14.41 ns/op 16 B/op 1 allocs/op +Benchmark_AddTrailingSlashString/path-with-slash-12 1000000000 0.4529 ns/op 0 B/op 0 allocs/op # EqualFold -Benchmark_EqualFoldBytes/fiber-12 67368261 18.48 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFoldBytes/default-12 17774803 65.91 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFold/fiber-12 80501566 14.75 ns/op 0 B/op 0 allocs/op -Benchmark_EqualFold/default-12 18314365 65.96 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFoldBytes/fiber-12 67368261 18.48 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFoldBytes/default-12 17774803 65.91 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold/fiber-12 80501566 14.75 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold/default-12 18314365 65.96 ns/op 0 B/op 0 allocs/op # Search -Benchmark_IndexAny2/7B/swar-12 282163779 4.297 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/7B/scalar-12 314553402 3.826 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/7B/stdlib-indexany-12 50085909 23.97 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/8B/swar-12 522780714 2.289 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/8B/scalar-12 271494799 4.206 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/8B/stdlib-indexany-12 44831599 26.78 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/16B/swar-12 393245086 3.047 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/16B/scalar-12 168476984 7.117 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/16B/stdlib-indexany-12 100000000 10.03 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/32B/swar-12 252199587 4.802 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/32B/scalar-12 84105762 14.27 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/32B/stdlib-indexany-12 70291048 17.37 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/64B/swar-12 144335962 8.290 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/64B/scalar-12 42694686 28.60 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/64B/stdlib-indexany-12 37615540 32.23 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/512B/swar-12 20231538 59.71 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/512B/scalar-12 5071586 233.6 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny2/512B/stdlib-indexany-12 4448119 274.2 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/7B/swar-12 221889592 5.397 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/7B/scalar-12 240859849 4.977 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/8B/swar-12 445742876 2.689 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/8B/scalar-12 211981612 5.620 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/16B/swar-12 326475568 3.739 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/16B/scalar-12 100000000 10.31 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/32B/swar-12 196365920 6.112 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/32B/scalar-12 60021255 19.81 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/64B/swar-12 100000000 10.98 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/64B/scalar-12 31180405 38.97 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/512B/swar-12 15466316 79.22 ns/op 0 B/op 0 allocs/op -Benchmark_IndexAny3/512B/scalar-12 3911382 307.1 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-8B/swar-12 332497509 3.634 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-8B/scalar-12 491493494 2.408 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-32B/swar-12 149769112 7.928 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-32B/scalar-12 44041342 27.13 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/hit-32B/swar-12 138732252 8.758 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/hit-32B/scalar-12 33871633 30.73 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/hit-tail/swar-12 100000000 12.34 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/hit-tail/scalar-12 16138168 75.39 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-64B/swar-12 100000000 11.37 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-64B/scalar-12 17902330 67.78 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-512B/swar-12 17640939 67.65 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/miss-512B/scalar-12 2211582 544.4 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/long-hit-64B/swar-12 100000000 11.58 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/long-hit-64B/scalar-12 23906326 51.33 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/long-miss-64B/swar-12 100000000 11.33 ns/op 0 B/op 0 allocs/op -Benchmark_IndexFold/long-miss-64B/scalar-12 23553600 50.27 ns/op 0 B/op 0 allocs/op +// amd64 note: IndexAny2/IndexAny3 dispatch to package simd for 32+ byte +// inputs; these arm64 rows keep the portable SWAR path. For amd64 numbers +// see the Benchmark_Memchr2/Benchmark_Memchr3 rows in the simd section +// below (the kernels these functions dispatch to). +Benchmark_IndexAny2/7B/swar-12 282163779 4.297 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/7B/scalar-12 314553402 3.826 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/7B/stdlib-indexany-12 50085909 23.97 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/8B/swar-12 522780714 2.289 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/8B/scalar-12 271494799 4.206 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/8B/stdlib-indexany-12 44831599 26.78 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/16B/swar-12 393245086 3.047 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/16B/scalar-12 168476984 7.117 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/16B/stdlib-indexany-12 100000000 10.03 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/32B/swar-12 252199587 4.802 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/32B/scalar-12 84105762 14.27 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/32B/stdlib-indexany-12 70291048 17.37 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/64B/swar-12 144335962 8.290 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/64B/scalar-12 42694686 28.60 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/64B/stdlib-indexany-12 37615540 32.23 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/512B/swar-12 20231538 59.71 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/512B/scalar-12 5071586 233.6 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny2/512B/stdlib-indexany-12 4448119 274.2 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/7B/swar-12 221889592 5.397 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/7B/scalar-12 240859849 4.977 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/8B/swar-12 445742876 2.689 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/8B/scalar-12 211981612 5.620 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/16B/swar-12 326475568 3.739 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/16B/scalar-12 100000000 10.31 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/32B/swar-12 196365920 6.112 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/32B/scalar-12 60021255 19.81 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/64B/swar-12 100000000 10.98 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/64B/scalar-12 31180405 38.97 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/512B/swar-12 15466316 79.22 ns/op 0 B/op 0 allocs/op +Benchmark_IndexAny3/512B/scalar-12 3911382 307.1 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-8B/swar-12 332497509 3.634 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-8B/scalar-12 491493494 2.408 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-32B/swar-12 149769112 7.928 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-32B/scalar-12 44041342 27.13 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/hit-32B/swar-12 138732252 8.758 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/hit-32B/scalar-12 33871633 30.73 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/hit-tail/swar-12 100000000 12.34 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/hit-tail/scalar-12 16138168 75.39 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-64B/swar-12 100000000 11.37 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-64B/scalar-12 17902330 67.78 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-512B/swar-12 17640939 67.65 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/miss-512B/scalar-12 2211582 544.4 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/long-hit-64B/swar-12 100000000 11.58 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/long-hit-64B/scalar-12 23906326 51.33 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/long-miss-64B/swar-12 100000000 11.33 ns/op 0 B/op 0 allocs/op +Benchmark_IndexFold/long-miss-64B/scalar-12 23553600 50.27 ns/op 0 B/op 0 allocs/op # ASCII -Benchmark_IsASCII/7B/swar-12 238699563 5.001 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/7B/scalar-12 292669958 4.064 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/8B/swar-12 439961722 2.687 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/8B/scalar-12 274732192 4.364 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/16B/swar-12 367179319 3.255 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/16B/scalar-12 179331987 6.706 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/32B/swar-12 368345228 3.271 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/32B/scalar-12 100000000 11.62 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/64B/swar-12 265505815 4.486 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/64B/scalar-12 57864440 21.33 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/512B/swar-12 47664915 25.14 ns/op 0 B/op 0 allocs/op -Benchmark_IsASCII/512B/scalar-12 7081790 169.5 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/7B/swar-12 142234436 8.424 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/7B/scalar-12 142394628 8.174 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/8B/swar-12 401721262 3.099 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/8B/scalar-12 138047568 8.654 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/16B/swar-12 244592613 5.059 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/16B/scalar-12 75413396 15.94 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/32B/swar-12 138857455 8.875 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/32B/scalar-12 39539425 30.18 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/64B/swar-12 75193269 16.46 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/64B/scalar-12 20898807 57.81 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/512B/swar-12 9634008 124.9 ns/op 0 B/op 0 allocs/op -Benchmark_IndexNonQuotable/512B/scalar-12 2619062 460.6 ns/op 0 B/op 0 allocs/op +// amd64 note: IsASCII dispatches to package simd for 32+ byte inputs; +// these arm64 rows keep the portable SWAR path. See the simd section +// below for amd64 numbers. +Benchmark_IsASCII/7B/swar-12 238699563 5.001 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/7B/scalar-12 292669958 4.064 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/8B/swar-12 439961722 2.687 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/8B/scalar-12 274732192 4.364 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/16B/swar-12 367179319 3.255 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/16B/scalar-12 179331987 6.706 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/32B/swar-12 368345228 3.271 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/32B/scalar-12 100000000 11.62 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/64B/swar-12 265505815 4.486 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/64B/scalar-12 57864440 21.33 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/512B/swar-12 47664915 25.14 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/512B/scalar-12 7081790 169.5 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/7B/swar-12 142234436 8.424 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/7B/scalar-12 142394628 8.174 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/8B/swar-12 401721262 3.099 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/8B/scalar-12 138047568 8.654 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/16B/swar-12 244592613 5.059 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/16B/scalar-12 75413396 15.94 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/32B/swar-12 138857455 8.875 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/32B/scalar-12 39539425 30.18 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/64B/swar-12 75193269 16.46 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/64B/scalar-12 20898807 57.81 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/512B/swar-12 9634008 124.9 ns/op 0 B/op 0 allocs/op +Benchmark_IndexNonQuotable/512B/scalar-12 2619062 460.6 ns/op 0 B/op 0 allocs/op # Trim -Benchmark_TrimRight/fiber-12 587360972 2.043 ns/op 0 B/op 0 allocs/op -Benchmark_TrimRight/default-12 417142952 2.887 ns/op 0 B/op 0 allocs/op -Benchmark_TrimRightBytes/fiber-12 590828253 2.067 ns/op 0 B/op 0 allocs/op -Benchmark_TrimRightBytes/default-12 374548395 3.236 ns/op 0 B/op 0 allocs/op -Benchmark_TrimLeft/fiber-12 590822072 2.030 ns/op 0 B/op 0 allocs/op -Benchmark_TrimLeft/default-12 408184784 2.967 ns/op 0 B/op 0 allocs/op -Benchmark_TrimLeftBytes/fiber-12 592875732 2.033 ns/op 0 B/op 0 allocs/op -Benchmark_TrimLeftBytes/default-12 405921434 2.967 ns/op 0 B/op 0 allocs/op -Benchmark_Trim/fiber-12 317625432 3.758 ns/op 0 B/op 0 allocs/op -Benchmark_Trim/default-12 250173384 4.735 ns/op 0 B/op 0 allocs/op -Benchmark_Trim/default.trimspace-12 241883282 5.022 ns/op 0 B/op 0 allocs/op -Benchmark_TrimBytes/fiber-12 308885211 3.858 ns/op 0 B/op 0 allocs/op -Benchmark_TrimBytes/default-12 254064188 4.802 ns/op 0 B/op 0 allocs/op -Benchmark_TrimBytes/default.trimspace-12 224231778 5.330 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/empty-12 1000000000 0.3017 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/empty-12 583064172 2.074 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/spaces-12 387354229 3.059 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/spaces-12 320059388 3.651 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/ascii-word-12 345078337 3.535 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/ascii-word-12 270603267 4.465 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/auth-header-bearer-12 291494109 4.141 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/auth-header-bearer-12 224087944 5.329 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/auth-header-basic-12 390765345 3.047 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/auth-header-basic-12 258943531 4.718 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/accept-encoding-12 344369745 3.490 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/accept-encoding-12 277203638 4.347 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/content-type-12 344263705 3.506 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/content-type-12 276213367 4.343 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/x-forwarded-for-12 460119685 2.653 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/x-forwarded-for-12 296468840 4.058 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/query-params-12 330053276 3.520 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/query-params-12 275688495 4.352 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/ascii-long-12 275511898 4.342 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/ascii-long-12 206143018 5.807 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/no-trim-12 1000000000 0.5914 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/no-trim-12 451842741 2.634 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/fiber/mixed-whitespace-12 296083767 4.054 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpace/default/mixed-whitespace-12 224007750 5.294 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/empty-12 1000000000 0.2914 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/empty-12 519488766 2.352 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/spaces-12 410959255 2.966 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/spaces-12 315602949 3.827 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/ascii-word-12 341217429 3.519 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/ascii-word-12 247799318 4.667 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/auth-header-bearer-12 295130076 4.182 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/auth-header-bearer-12 209162235 5.685 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/auth-header-basic-12 393366796 3.053 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/auth-header-basic-12 240882009 4.930 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/accept-encoding-12 343673244 3.512 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/accept-encoding-12 250962042 4.642 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/content-type-12 344382758 3.516 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/content-type-12 250622116 4.693 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/x-forwarded-for-12 459435145 2.621 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/x-forwarded-for-12 276595178 4.359 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/query-params-12 341144192 3.526 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/query-params-12 255843174 4.873 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/ascii-long-12 270183530 4.445 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/ascii-long-12 189740618 6.335 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/no-trim-12 1000000000 0.5969 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/no-trim-12 406072189 2.941 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/fiber/mixed-whitespace-12 289382116 4.057 ns/op 0 B/op 0 allocs/op -Benchmark_TrimSpaceBytes/default/mixed-whitespace-12 218559462 5.493 ns/op 0 B/op 0 allocs/op +Benchmark_TrimRight/fiber-12 587360972 2.043 ns/op 0 B/op 0 allocs/op +Benchmark_TrimRight/default-12 417142952 2.887 ns/op 0 B/op 0 allocs/op +Benchmark_TrimRightBytes/fiber-12 590828253 2.067 ns/op 0 B/op 0 allocs/op +Benchmark_TrimRightBytes/default-12 374548395 3.236 ns/op 0 B/op 0 allocs/op +Benchmark_TrimLeft/fiber-12 590822072 2.030 ns/op 0 B/op 0 allocs/op +Benchmark_TrimLeft/default-12 408184784 2.967 ns/op 0 B/op 0 allocs/op +Benchmark_TrimLeftBytes/fiber-12 592875732 2.033 ns/op 0 B/op 0 allocs/op +Benchmark_TrimLeftBytes/default-12 405921434 2.967 ns/op 0 B/op 0 allocs/op +Benchmark_Trim/fiber-12 317625432 3.758 ns/op 0 B/op 0 allocs/op +Benchmark_Trim/default-12 250173384 4.735 ns/op 0 B/op 0 allocs/op +Benchmark_Trim/default.trimspace-12 241883282 5.022 ns/op 0 B/op 0 allocs/op +Benchmark_TrimBytes/fiber-12 308885211 3.858 ns/op 0 B/op 0 allocs/op +Benchmark_TrimBytes/default-12 254064188 4.802 ns/op 0 B/op 0 allocs/op +Benchmark_TrimBytes/default.trimspace-12 224231778 5.330 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/empty-12 1000000000 0.3017 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/empty-12 583064172 2.074 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/spaces-12 387354229 3.059 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/spaces-12 320059388 3.651 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/ascii-word-12 345078337 3.535 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/ascii-word-12 270603267 4.465 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/auth-header-bearer-12 291494109 4.141 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/auth-header-bearer-12 224087944 5.329 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/auth-header-basic-12 390765345 3.047 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/auth-header-basic-12 258943531 4.718 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/accept-encoding-12 344369745 3.490 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/accept-encoding-12 277203638 4.347 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/content-type-12 344263705 3.506 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/content-type-12 276213367 4.343 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/x-forwarded-for-12 460119685 2.653 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/x-forwarded-for-12 296468840 4.058 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/query-params-12 330053276 3.520 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/query-params-12 275688495 4.352 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/ascii-long-12 275511898 4.342 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/ascii-long-12 206143018 5.807 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/no-trim-12 1000000000 0.5914 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/no-trim-12 451842741 2.634 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/fiber/mixed-whitespace-12 296083767 4.054 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpace/default/mixed-whitespace-12 224007750 5.294 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/empty-12 1000000000 0.2914 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/empty-12 519488766 2.352 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/spaces-12 410959255 2.966 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/spaces-12 315602949 3.827 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/ascii-word-12 341217429 3.519 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/ascii-word-12 247799318 4.667 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/auth-header-bearer-12 295130076 4.182 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/auth-header-bearer-12 209162235 5.685 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/auth-header-basic-12 393366796 3.053 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/auth-header-basic-12 240882009 4.930 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/accept-encoding-12 343673244 3.512 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/accept-encoding-12 250962042 4.642 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/content-type-12 344382758 3.516 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/content-type-12 250622116 4.693 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/x-forwarded-for-12 459435145 2.621 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/x-forwarded-for-12 276595178 4.359 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/query-params-12 341144192 3.526 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/query-params-12 255843174 4.873 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/ascii-long-12 270183530 4.445 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/ascii-long-12 189740618 6.335 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/no-trim-12 1000000000 0.5969 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/no-trim-12 406072189 2.941 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/fiber/mixed-whitespace-12 289382116 4.057 ns/op 0 B/op 0 allocs/op +Benchmark_TrimSpaceBytes/default/mixed-whitespace-12 218559462 5.493 ns/op 0 B/op 0 allocs/op # Convert -Benchmark_ConvertToBytes/fiber-12 320332576 3.787 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/int-12 499429904 2.382 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/int8-12 614406423 1.965 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/int16-12 486644316 2.463 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/int32-12 495227163 2.422 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/int64-12 502362236 2.429 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/uint-12 561693333 2.101 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/uint8-12 611239028 1.965 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/uint16-12 573383422 2.127 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/uint32-12 575723191 2.093 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/uint64-12 575901750 2.089 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/string-12 613909396 1.959 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/[]uint8-12 96832432 12.11 ns/op 16 B/op 1 allocs/op -Benchmark_ToString/bool-12 608058547 1.990 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/float32-12 23195016 47.11 ns/op 4 B/op 1 allocs/op -Benchmark_ToString/float64-12 17204126 70.24 ns/op 4 B/op 1 allocs/op -Benchmark_ToString/time.Time-12 13103935 91.85 ns/op 24 B/op 1 allocs/op -Benchmark_ToString/time.Time#01-12 13198113 91.22 ns/op 24 B/op 1 allocs/op -Benchmark_ToString/[]string-12 65187865 18.35 ns/op 16 B/op 1 allocs/op -Benchmark_ToString/[]int-12 54417859 21.53 ns/op 8 B/op 1 allocs/op -Benchmark_ToString/[2]int-12 32691942 36.57 ns/op 16 B/op 1 allocs/op -Benchmark_ToString/[][]int-12 9382754 128.8 ns/op 112 B/op 6 allocs/op -Benchmark_ToString/[]interface_{}-12 10584483 114.5 ns/op 72 B/op 3 allocs/op -Benchmark_ToString/utils.MyStringer-12 365979882 3.277 ns/op 0 B/op 0 allocs/op -Benchmark_ToString/utils.CustomType-12 11649330 102.5 ns/op 16 B/op 1 allocs/op -Benchmark_ToString_concurrency/int-12 1000000000 0.2619 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/int8-12 1000000000 0.2202 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/int16-12 1000000000 0.2708 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/int32-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/int64-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/uint-12 1000000000 0.2281 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/uint8-12 1000000000 0.2223 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/uint16-12 1000000000 0.2396 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/uint32-12 1000000000 0.2273 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/uint64-12 1000000000 0.2271 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/string-12 1000000000 0.2117 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/[]uint8-12 213842515 5.718 ns/op 16 B/op 1 allocs/op -Benchmark_ToString_concurrency/bool-12 1000000000 0.2118 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/float32-12 201081819 6.011 ns/op 4 B/op 1 allocs/op -Benchmark_ToString_concurrency/float64-12 142000966 8.799 ns/op 4 B/op 1 allocs/op -Benchmark_ToString_concurrency/time.Time-12 71451783 18.04 ns/op 24 B/op 1 allocs/op -Benchmark_ToString_concurrency/time.Time#01-12 69313578 17.74 ns/op 24 B/op 1 allocs/op -Benchmark_ToString_concurrency/[]string-12 187564670 6.455 ns/op 16 B/op 1 allocs/op -Benchmark_ToString_concurrency/[]int-12 262707805 4.498 ns/op 8 B/op 1 allocs/op -Benchmark_ToString_concurrency/[2]int-12 129274200 8.777 ns/op 16 B/op 1 allocs/op -Benchmark_ToString_concurrency/[][]int-12 22638411 52.65 ns/op 112 B/op 6 allocs/op -Benchmark_ToString_concurrency/[]interface_{}-12 34120837 35.36 ns/op 72 B/op 3 allocs/op -Benchmark_ToString_concurrency/utils.MyStringer-12 1000000000 0.4259 ns/op 0 B/op 0 allocs/op -Benchmark_ToString_concurrency/utils.CustomType-12 54806094 25.95 ns/op 16 B/op 1 allocs/op -Benchmark_UnsafeBytes/unsafe-12 1000000000 0.5658 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeBytes/default-12 88407558 13.50 ns/op 16 B/op 1 allocs/op -Benchmark_UnsafeString/unsafe-12 1000000000 0.3545 ns/op 0 B/op 0 allocs/op -Benchmark_UnsafeString/default-12 100000000 12.09 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/0-12 395954607 3.023 ns/op 0 B/op 0 allocs/op -Benchmark_ByteSize/1-12 65295756 18.15 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/500-12 58264801 20.92 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1024-12 60886531 19.80 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1126-12 53409986 22.69 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1048576-12 60969927 19.41 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1153024-12 53647869 22.12 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1073741824-12 63792180 19.05 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1180696576-12 54560540 22.02 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1099511627776-12 64080169 18.85 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1209033293824-12 52957434 22.01 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1125899906842624-12 65629659 18.33 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1238050092875776-12 56535770 21.73 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1152921504606846976-12 64569356 18.56 ns/op 16 B/op 1 allocs/op -Benchmark_ByteSize/1267763295104794624-12 56481996 21.10 ns/op 16 B/op 1 allocs/op +Benchmark_ConvertToBytes/fiber-12 320332576 3.787 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/int-12 499429904 2.382 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/int8-12 614406423 1.965 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/int16-12 486644316 2.463 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/int32-12 495227163 2.422 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/int64-12 502362236 2.429 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/uint-12 561693333 2.101 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/uint8-12 611239028 1.965 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/uint16-12 573383422 2.127 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/uint32-12 575723191 2.093 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/uint64-12 575901750 2.089 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/string-12 613909396 1.959 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/[]uint8-12 96832432 12.11 ns/op 16 B/op 1 allocs/op +Benchmark_ToString/bool-12 608058547 1.990 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/float32-12 23195016 47.11 ns/op 4 B/op 1 allocs/op +Benchmark_ToString/float64-12 17204126 70.24 ns/op 4 B/op 1 allocs/op +Benchmark_ToString/time.Time-12 13103935 91.85 ns/op 24 B/op 1 allocs/op +Benchmark_ToString/time.Time#01-12 13198113 91.22 ns/op 24 B/op 1 allocs/op +Benchmark_ToString/[]string-12 65187865 18.35 ns/op 16 B/op 1 allocs/op +Benchmark_ToString/[]int-12 54417859 21.53 ns/op 8 B/op 1 allocs/op +Benchmark_ToString/[2]int-12 32691942 36.57 ns/op 16 B/op 1 allocs/op +Benchmark_ToString/[][]int-12 9382754 128.8 ns/op 112 B/op 6 allocs/op +Benchmark_ToString/[]interface_{}-12 10584483 114.5 ns/op 72 B/op 3 allocs/op +Benchmark_ToString/utils.MyStringer-12 365979882 3.277 ns/op 0 B/op 0 allocs/op +Benchmark_ToString/utils.CustomType-12 11649330 102.5 ns/op 16 B/op 1 allocs/op +Benchmark_ToString_concurrency/int-12 1000000000 0.2619 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/int8-12 1000000000 0.2202 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/int16-12 1000000000 0.2708 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/int32-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/int64-12 1000000000 0.2658 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/uint-12 1000000000 0.2281 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/uint8-12 1000000000 0.2223 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/uint16-12 1000000000 0.2396 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/uint32-12 1000000000 0.2273 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/uint64-12 1000000000 0.2271 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/string-12 1000000000 0.2117 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/[]uint8-12 213842515 5.718 ns/op 16 B/op 1 allocs/op +Benchmark_ToString_concurrency/bool-12 1000000000 0.2118 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/float32-12 201081819 6.011 ns/op 4 B/op 1 allocs/op +Benchmark_ToString_concurrency/float64-12 142000966 8.799 ns/op 4 B/op 1 allocs/op +Benchmark_ToString_concurrency/time.Time-12 71451783 18.04 ns/op 24 B/op 1 allocs/op +Benchmark_ToString_concurrency/time.Time#01-12 69313578 17.74 ns/op 24 B/op 1 allocs/op +Benchmark_ToString_concurrency/[]string-12 187564670 6.455 ns/op 16 B/op 1 allocs/op +Benchmark_ToString_concurrency/[]int-12 262707805 4.498 ns/op 8 B/op 1 allocs/op +Benchmark_ToString_concurrency/[2]int-12 129274200 8.777 ns/op 16 B/op 1 allocs/op +Benchmark_ToString_concurrency/[][]int-12 22638411 52.65 ns/op 112 B/op 6 allocs/op +Benchmark_ToString_concurrency/[]interface_{}-12 34120837 35.36 ns/op 72 B/op 3 allocs/op +Benchmark_ToString_concurrency/utils.MyStringer-12 1000000000 0.4259 ns/op 0 B/op 0 allocs/op +Benchmark_ToString_concurrency/utils.CustomType-12 54806094 25.95 ns/op 16 B/op 1 allocs/op +Benchmark_UnsafeBytes/unsafe-12 1000000000 0.5658 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeBytes/default-12 88407558 13.50 ns/op 16 B/op 1 allocs/op +Benchmark_UnsafeString/unsafe-12 1000000000 0.3545 ns/op 0 B/op 0 allocs/op +Benchmark_UnsafeString/default-12 100000000 12.09 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/0-12 395954607 3.023 ns/op 0 B/op 0 allocs/op +Benchmark_ByteSize/1-12 65295756 18.15 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/500-12 58264801 20.92 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1024-12 60886531 19.80 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1126-12 53409986 22.69 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1048576-12 60969927 19.41 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1153024-12 53647869 22.12 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1073741824-12 63792180 19.05 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1180696576-12 54560540 22.02 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1099511627776-12 64080169 18.85 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1209033293824-12 52957434 22.01 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1125899906842624-12 65629659 18.33 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1238050092875776-12 56535770 21.73 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1152921504606846976-12 64569356 18.56 ns/op 16 B/op 1 allocs/op +Benchmark_ByteSize/1267763295104794624-12 56481996 21.10 ns/op 16 B/op 1 allocs/op # Format and Append -Benchmark_FormatUint/small/fiber-12 607527520 1.966 ns/op 0 B/op 0 allocs/op -Benchmark_FormatUint/small/strconv-12 607521366 1.973 ns/op 0 B/op 0 allocs/op -Benchmark_FormatUint/medium/fiber-12 64427509 19.04 ns/op 16 B/op 1 allocs/op -Benchmark_FormatUint/medium/strconv-12 59566404 20.42 ns/op 16 B/op 1 allocs/op -Benchmark_FormatUint/large/fiber-12 45395149 26.16 ns/op 24 B/op 1 allocs/op -Benchmark_FormatUint/large/strconv-12 45620366 26.38 ns/op 24 B/op 1 allocs/op -Benchmark_FormatInt/small_pos/fiber-12 608898928 1.963 ns/op 0 B/op 0 allocs/op -Benchmark_FormatInt/small_pos/strconv-12 598721480 1.976 ns/op 0 B/op 0 allocs/op -Benchmark_FormatInt/small_neg/fiber-12 616958124 1.946 ns/op 0 B/op 0 allocs/op -Benchmark_FormatInt/small_neg/strconv-12 87181050 13.77 ns/op 3 B/op 1 allocs/op -Benchmark_FormatInt/medium_pos/fiber-12 63105722 19.12 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt/medium_pos/strconv-12 57454753 20.70 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt/medium_neg/fiber-12 63631222 19.10 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt/medium_neg/strconv-12 61296942 20.17 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt/large_pos/fiber-12 48604558 25.08 ns/op 24 B/op 1 allocs/op -Benchmark_FormatInt/large_pos/strconv-12 45605844 26.25 ns/op 24 B/op 1 allocs/op -Benchmark_FormatInt/large_neg/fiber-12 47388217 25.09 ns/op 24 B/op 1 allocs/op -Benchmark_FormatInt/large_neg/strconv-12 45871998 26.10 ns/op 24 B/op 1 allocs/op -Benchmark_FormatUint32/fiber-12 63452196 18.63 ns/op 16 B/op 1 allocs/op -Benchmark_FormatUint32/strconv-12 59485942 20.08 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt32/fiber-12 63030724 18.98 ns/op 16 B/op 1 allocs/op -Benchmark_FormatInt32/strconv-12 61887302 19.69 ns/op 16 B/op 1 allocs/op -Benchmark_FormatUint16/fiber-12 80149611 14.48 ns/op 5 B/op 1 allocs/op -Benchmark_FormatUint16/strconv-12 77022440 15.43 ns/op 5 B/op 1 allocs/op -Benchmark_FormatInt16/fiber-12 79013646 15.23 ns/op 8 B/op 1 allocs/op -Benchmark_FormatInt16/strconv-12 79695165 15.24 ns/op 8 B/op 1 allocs/op -Benchmark_FormatUint8/fiber-12 599811685 1.947 ns/op 0 B/op 0 allocs/op -Benchmark_FormatUint8/strconv-12 84144096 14.18 ns/op 3 B/op 1 allocs/op -Benchmark_FormatInt8/fiber-12 630717244 1.985 ns/op 0 B/op 0 allocs/op -Benchmark_FormatInt8/strconv-12 83826201 14.24 ns/op 4 B/op 1 allocs/op -Benchmark_AppendUint/fiber-12 130817422 9.139 ns/op 0 B/op 0 allocs/op -Benchmark_AppendUint/strconv-12 100000000 10.08 ns/op 0 B/op 0 allocs/op -Benchmark_AppendInt/small_neg/fiber-12 369512403 3.266 ns/op 0 B/op 0 allocs/op -Benchmark_AppendInt/small_neg/strconv-12 213341739 5.627 ns/op 0 B/op 0 allocs/op -Benchmark_AppendInt/medium_neg/fiber-12 125937435 9.531 ns/op 0 B/op 0 allocs/op -Benchmark_AppendInt/medium_neg/strconv-12 122490632 9.791 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint/small/fiber-12 607527520 1.966 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint/small/strconv-12 607521366 1.973 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint/medium/fiber-12 64427509 19.04 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint/medium/strconv-12 59566404 20.42 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint/large/fiber-12 45395149 26.16 ns/op 24 B/op 1 allocs/op +Benchmark_FormatUint/large/strconv-12 45620366 26.38 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/small_pos/fiber-12 608898928 1.963 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_pos/strconv-12 598721480 1.976 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_neg/fiber-12 616958124 1.946 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_neg/strconv-12 87181050 13.77 ns/op 3 B/op 1 allocs/op +Benchmark_FormatInt/medium_pos/fiber-12 63105722 19.12 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_pos/strconv-12 57454753 20.70 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_neg/fiber-12 63631222 19.10 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_neg/strconv-12 61296942 20.17 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/large_pos/fiber-12 48604558 25.08 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_pos/strconv-12 45605844 26.25 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_neg/fiber-12 47388217 25.09 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_neg/strconv-12 45871998 26.10 ns/op 24 B/op 1 allocs/op +Benchmark_FormatUint32/fiber-12 63452196 18.63 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint32/strconv-12 59485942 20.08 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt32/fiber-12 63030724 18.98 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt32/strconv-12 61887302 19.69 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint16/fiber-12 80149611 14.48 ns/op 5 B/op 1 allocs/op +Benchmark_FormatUint16/strconv-12 77022440 15.43 ns/op 5 B/op 1 allocs/op +Benchmark_FormatInt16/fiber-12 79013646 15.23 ns/op 8 B/op 1 allocs/op +Benchmark_FormatInt16/strconv-12 79695165 15.24 ns/op 8 B/op 1 allocs/op +Benchmark_FormatUint8/fiber-12 599811685 1.947 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint8/strconv-12 84144096 14.18 ns/op 3 B/op 1 allocs/op +Benchmark_FormatInt8/fiber-12 630717244 1.985 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt8/strconv-12 83826201 14.24 ns/op 4 B/op 1 allocs/op +Benchmark_AppendUint/fiber-12 130817422 9.139 ns/op 0 B/op 0 allocs/op +Benchmark_AppendUint/strconv-12 100000000 10.08 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/small_neg/fiber-12 369512403 3.266 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/small_neg/strconv-12 213341739 5.627 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/medium_neg/fiber-12 125937435 9.531 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/medium_neg/strconv-12 122490632 9.791 ns/op 0 B/op 0 allocs/op # Token -Benchmark_GenerateSecureToken/16_bytes-12 4565527 258.6 ns/op 24 B/op 1 allocs/op -Benchmark_GenerateSecureToken/32_bytes-12 4306404 280.8 ns/op 48 B/op 1 allocs/op -Benchmark_TokenGenerators/UUIDv4-12 4019139 288.2 ns/op 64 B/op 2 allocs/op -Benchmark_TokenGenerators/SecureToken-12 4360036 276.9 ns/op 48 B/op 1 allocs/op +Benchmark_GenerateSecureToken/16_bytes-12 4565527 258.6 ns/op 24 B/op 1 allocs/op +Benchmark_GenerateSecureToken/32_bytes-12 4306404 280.8 ns/op 48 B/op 1 allocs/op +Benchmark_TokenGenerators/UUIDv4-12 4019139 288.2 ns/op 64 B/op 2 allocs/op +Benchmark_TokenGenerators/SecureToken-12 4360036 276.9 ns/op 48 B/op 1 allocs/op # HTTP -Benchmark_GetMIME/fiber-12 22321272 53.90 ns/op 0 B/op 0 allocs/op -Benchmark_GetMIME/default-12 17492530 68.46 ns/op 0 B/op 0 allocs/op -Benchmark_ParseVendorSpecificContentType/vendorContentType-12 125467813 9.619 ns/op 0 B/op 0 allocs/op -Benchmark_ParseVendorSpecificContentType/defaultContentType-12 404169172 2.974 ns/op 0 B/op 0 allocs/op -Benchmark_StatusMessage/fiber-12 1000000000 0.3349 ns/op 0 B/op 0 allocs/op -Benchmark_StatusMessage/default-12 460456902 2.610 ns/op 0 B/op 0 allocs/op +Benchmark_GetMIME/fiber-12 22321272 53.90 ns/op 0 B/op 0 allocs/op +Benchmark_GetMIME/default-12 17492530 68.46 ns/op 0 B/op 0 allocs/op +Benchmark_ParseVendorSpecificContentType/vendorContentType-12 125467813 9.619 ns/op 0 B/op 0 allocs/op +Benchmark_ParseVendorSpecificContentType/defaultContentType-12 404169172 2.974 ns/op 0 B/op 0 allocs/op +Benchmark_StatusMessage/fiber-12 1000000000 0.3349 ns/op 0 B/op 0 allocs/op +Benchmark_StatusMessage/default-12 460456902 2.610 ns/op 0 B/op 0 allocs/op # IP -Benchmark_IsIPv4/fiber-12 80408070 14.58 ns/op 0 B/op 0 allocs/op -Benchmark_IsIPv4/default-12 54025154 21.99 ns/op 0 B/op 0 allocs/op -Benchmark_IsIPv6/fiber-12 28283431 42.67 ns/op 0 B/op 0 allocs/op -Benchmark_IsIPv6/default-12 20747964 58.18 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv4/fiber-4 56396187 21.72 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv4/default-4 28357074 40.38 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv6/fiber-4 19461662 62.01 ns/op 0 B/op 0 allocs/op +Benchmark_IsIPv6/default-4 13315670 89.84 ns/op 0 B/op 0 allocs/op # Parse -Benchmark_ParseUint/fiber-12 236748204 5.049 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint/fiber_bytes-12 224650773 5.348 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint/default-12 88588122 13.75 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/6digit-12 207540178 5.769 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/8digit-12 222360716 5.403 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/12digit-12 156132950 7.699 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/19digit-12 135049720 8.880 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/1digit-12 338642533 3.553 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint_DigitRuns/4digit-12 212370570 5.672 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt/fiber-12 299791800 3.981 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt/fiber_bytes-12 288714712 4.165 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt/default-12 76370292 15.48 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt32/fiber-12 200451391 5.988 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt32/fiber_bytes-12 201629558 5.956 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt32/default-12 78384832 15.71 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt16/fiber-12 220670613 5.462 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt16/fiber_bytes-12 220175068 5.430 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt16/default-12 100000000 10.71 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt8/fiber-12 277948545 4.279 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt8/fiber_bytes-12 264784368 4.566 ns/op 0 B/op 0 allocs/op -Benchmark_ParseInt8/default-12 142184748 8.373 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint32/fiber-12 238916116 5.025 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint32/fiber_bytes-12 222286592 5.409 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint32/default-12 90395479 13.33 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint16/fiber-12 251398184 4.828 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint16/fiber_bytes-12 248772012 4.838 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint16/default-12 137015901 8.788 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint8/fiber-12 360430984 3.427 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint8/fiber_bytes-12 327526336 3.659 ns/op 0 B/op 0 allocs/op -Benchmark_ParseUint8/default-12 181904056 6.438 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat64/fiber-12 82912768 14.76 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat64/fiber_bytes-12 95692504 12.68 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat64/default-12 50109265 25.05 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat32/fiber-12 76648135 15.76 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat32/fiber_bytes-12 86422119 13.63 ns/op 0 B/op 0 allocs/op -Benchmark_ParseFloat32/default-12 47198646 25.41 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint/fiber-12 236748204 5.049 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint/fiber_bytes-12 224650773 5.348 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint/default-12 88588122 13.75 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/6digit-12 207540178 5.769 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/8digit-12 222360716 5.403 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/12digit-12 156132950 7.699 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/19digit-12 135049720 8.880 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/1digit-12 338642533 3.553 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint_DigitRuns/4digit-12 212370570 5.672 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt/fiber-12 299791800 3.981 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt/fiber_bytes-12 288714712 4.165 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt/default-12 76370292 15.48 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt32/fiber-12 200451391 5.988 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt32/fiber_bytes-12 201629558 5.956 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt32/default-12 78384832 15.71 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt16/fiber-12 220670613 5.462 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt16/fiber_bytes-12 220175068 5.430 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt16/default-12 100000000 10.71 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt8/fiber-12 277948545 4.279 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt8/fiber_bytes-12 264784368 4.566 ns/op 0 B/op 0 allocs/op +Benchmark_ParseInt8/default-12 142184748 8.373 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint32/fiber-12 238916116 5.025 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint32/fiber_bytes-12 222286592 5.409 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint32/default-12 90395479 13.33 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint16/fiber-12 251398184 4.828 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint16/fiber_bytes-12 248772012 4.838 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint16/default-12 137015901 8.788 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint8/fiber-12 360430984 3.427 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint8/fiber_bytes-12 327526336 3.659 ns/op 0 B/op 0 allocs/op +Benchmark_ParseUint8/default-12 181904056 6.438 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat64/fiber-12 82912768 14.76 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat64/fiber_bytes-12 95692504 12.68 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat64/default-12 50109265 25.05 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat32/fiber-12 76648135 15.76 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat32/fiber_bytes-12 86422119 13.63 ns/op 0 B/op 0 allocs/op +Benchmark_ParseFloat32/default-12 47198646 25.41 ns/op 0 B/op 0 allocs/op # Time -Benchmark_CalculateTimestamp/fiber-12 1000000000 0.3366 ns/op 0 B/op 0 allocs/op -Benchmark_CalculateTimestamp/default-12 36163686 32.69 ns/op 0 B/op 0 allocs/op -Benchmark_CalculateTimestamp/fiber_asserted-12 4471299 267.8 ns/op 12 B/op 2 allocs/op -Benchmark_CalculateTimestamp/default_asserted-12 3991147 298.7 ns/op 8 B/op 2 allocs/op +Benchmark_CalculateTimestamp/fiber-12 1000000000 0.3366 ns/op 0 B/op 0 allocs/op +Benchmark_CalculateTimestamp/default-12 36163686 32.69 ns/op 0 B/op 0 allocs/op +Benchmark_CalculateTimestamp/fiber_asserted-12 4471299 267.8 ns/op 12 B/op 2 allocs/op +Benchmark_CalculateTimestamp/default_asserted-12 3991147 298.7 ns/op 8 B/op 2 allocs/op + +# URL +Benchmark_AppendPathSegmentsEscape/1-segment/fiber-12 84056664 13.99 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/1-segment/split-loop-12 56022625 21.97 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/3-segments/fiber-12 88724314 13.65 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/3-segments/split-loop-12 36393044 32.41 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/6-segments/fiber-12 87622688 13.82 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/6-segments/split-loop-12 23307777 51.23 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/escaping/fiber-12 37647206 31.85 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathSegmentsEscape/escaping/split-loop-12 21136993 58.06 ns/op 0 B/op 0 allocs/op # XML -Benchmark_GolangXMLEncoder-12 574852 2040 ns/op 4864 B/op 12 allocs/op -Benchmark_DefaultXMLEncoder-12 593738 2012 ns/op 4864 B/op 12 allocs/op -Benchmark_DefaultXMLDecoder-12 309031 3876 ns/op 2892 B/op 57 allocs/op +Benchmark_GolangXMLEncoder-12 574852 2040 ns/op 4864 B/op 12 allocs/op +Benchmark_DefaultXMLEncoder-12 593738 2012 ns/op 4864 B/op 12 allocs/op +Benchmark_DefaultXMLDecoder-12 309031 3876 ns/op 2892 B/op 57 allocs/op ``` See all the benchmarks under @@ -462,6 +483,329 @@ as a plain string because call sites pass constant tokens. Their on the [benchmark charts](https://gofiber.github.io/utils/benchmarks/) and join the catalog above on its next regeneration. +`HashFold` is the hashing half of a case-insensitive lookup table whose +other half is `EqualFold`: strings `EqualFold` reports equal hash equal, +so a table of field or header names can be probed with a key in any case +without first lower-casing a copy of it. It folds each word with +`swar.ToLowerWord` as it loads it and mixes with wyhash's widening +multiply: keys under eight bytes, as most are, pack into one word and +cost one multiply, with the length in the multiplier so that keys which +pack alike, such as `a` and `aa`, stay apart; longer keys take one +multiply per sixteen bytes plus a final one. It takes no seed and is no +defense against collisions planned in advance, so it suits keys of the +program's own, such as the fields of a struct, rather than keys an +attacker picks. Against `maphash.String` of a `strings.ToLower` copy, +benchstat over ten runs on an Intel Xeon @ 2.80GHz measured 4.8 ns +against 13.2 ns for a 2-byte key, 4.5 ns against 50.7 ns for a 4-byte +key and 14.7 ns against 184 ns for a 48-byte key, where the copy also +allocates; +`go test -run='^$' -bench='^Benchmark_HashFold$' -benchmem -count=10 . > hashfold.txt` +followed by `benchstat hashfold.txt` reproduces that comparison. The +`HashFold` rows in the amd64 table below, like the table's other rows, +are a single run on the machine its header names. + +## HTTP dates + +`AppendHTTPDate` and `FormatHTTPDate` write a time in the RFC 9110 +preferred HTTP date format (`Mon, 02 Jan 2006 15:04:05 GMT`, +`net/http.TimeFormat`), byte-identical to `time.Format` with that layout +but without walking a layout string: the calendar fields come from one +civil-date conversion of `t.Unix()` (Hinnant's era arithmetic, instead of +the three `abs()` walks behind `Date`, `Clock`, and `Weekday`), and are +written into the fixed-width template with two-digit table lookups. +`ParseHTTPDate` is the reverse: canonical preferred-format input takes a +strict scalar fast path whose validated fields feed `time.Unix` directly +— the same `Time` value `time.Date` builds, minus its normalization pass — +and everything else — the obsolete RFC 850 and asctime forms, unusual +casing, non-GMT zone names, padding — falls back to `time.Parse` with +`net/http.ParseTime` semantics, including its errors. Both directions are +pinned to the `time` package by a day-by-day sweep over the years +0..9999. `Date`, `Last-Modified`, and `If-Modified-Since` handling sit on +every request/response, which makes these the highest-leverage helpers in +this group for Fiber. + +## URL escaping + +`AppendQueryEscape`/`AppendPathEscape` and +`AppendQueryUnescape`/`AppendPathUnescape` produce byte-identical results +(and, for the unescape pair, identical `url.EscapeError` values) to their +`net/url` counterparts, as append-style, allocation-free single passes. +The escape tables are pinned to `net/url.shouldEscape` by exhaustive +per-byte tests. Unescaping jumps between escape sites with the vectorized +scans (`IndexAny2` when `+` needs rewriting, `bytes.IndexByte` otherwise) +and copies clean spans wholesale, so route parameters and query values +without escapes — the common case — cost one scan and one copy. Decoding +never grows the input, so `dst` may be `s[:0]` on a common backing array +to unescape in place; escaping can grow the input, so there `dst` must +not alias `s`. + +`AppendPathSegmentsEscape` covers a whole multi-segment path in one pass: +it escapes every segment as `AppendPathEscape` does and keeps the `/` +between them. The output equals escaping each segment and joining with +`/`, pinned per byte and by fuzzing; `net/url`'s whole-path escaping +differs, as it also leaves `;` and `,` unescaped. The catalog above +measures it against the per-segment loop a caller writes without it; the +other URL benchmarks are still in the amd64 block below. + +## JSON string escaping + +`AppendJSONString` appends a value as a double-quoted JSON string, +byte-identical to `encoding/json.Marshal` of the same string — including +its default HTML escaping (`<`, `>`, `&`), the `\ufffd` replacement of +invalid UTF-8 bytes, and the U+2028/U+2029 escapes — without any of +`Marshal`'s reflection or allocation. Clean spans are located with a SWAR +scan (the same first-match-mask technique as `IndexNonQuotable`) and +copied wholesale. This is the building block for hand-rolled JSON hot +paths such as access-log lines and error bodies. + +## IP address parsing + +`ParseIPv4` and `ParseIPv6` parse addresses into `netip.Addr`, accepting +exactly the strings `netip.ParseAddr` accepts for the respective family +(pinned by fuzzing) while reporting failure with a `bool` instead of a +constructed error. Both take strings or byte slices, so fasthttp-style +callers skip the `string` conversion entirely; remote-address and +trusted-proxy checks parse an IP on every request in Fiber. + +## Header key canonicalization + +`CanonicalHeaderKey` Title-Cases an HTTP header key exactly like +`net/http.CanonicalHeaderKey`, including its return-unchanged guard for +keys containing non-token bytes. Already-canonical keys — the common case +on receive paths — are validated in a single table pass and returned +as-is with zero allocations for strings and byte slices alike. Keys that +do need rewriting cost one allocation; note that for the ~40 header names +in the stdlib's interning table the stdlib returns a cached string +without allocating, so this helper's edge there is time, not allocations. + +## Control-byte scanning + +`IndexControl` returns the index of the first ASCII control byte — a byte +below 0x20 or DEL (0x7F), the RFC 5234 CTL set — and `IndexControlExceptTab` +is the same scan with HTAB permitted, which is the byte set an RFC 9110 +field value may not contain. Both are SWAR first-match scans +(two words per branch, one overlapping word for the tail) over strings or +byte slices; the HTAB exemption is tested only in words that hold a +control byte, so clean input costs the same either way. They never match +bytes >= 0x80, so unlike +`strings.IndexFunc(s, unicode.IsControl)` they neither decode UTF-8 nor +flag the C1 range hidden inside it. Fiber spells this check by hand in +half a dozen places — header values before they are echoed, request IDs, +`Location` values, log fields, Basic auth credentials — and each copy is +one of these two calls. + +## Byte-separator cuts + +`CutByte` and `LastCutByte` are `strings.Cut`/`bytes.Cut` for a single +byte separator, around its first or last occurrence, generic over strings +and byte slices. They return the two parts and a found flag exactly like +the stdlib pair (including the `""`/`nil` after-part of a miss), cost one +`IndexByte`/`LastIndexByte`, and spare `[]byte` callers the `[]byte{sep}` +needle and the length dispatch inside `bytes.Index`. `CutByte` beats +`strings.Cut`; `LastCutByte` has no stdlib counterpart, so its row is +measured against a hand-written `LastIndexByte` split, which it trails by +the cost of the call — its value is the generic `[]byte` support and the +readable spelling. Header parameter splits (`;`), `key=value` pairs, and +host/port and name/extension splits are the intended call sites. + +## Host and port splitting + +`SplitHostPort` splits `host:port`, `host%zone:port`, `[host]:port`, and +`[host%zone]:port` with exactly `net.SplitHostPort`'s acceptance rules +(pinned by fuzzing against it), but reports failure with a `bool` instead +of constructing a `*net.AddrError`, and accepts byte slices. Valid input +costs the same as the stdlib — the scan is the same three `IndexByte` +calls — so the win is on the rejection path, where a malformed `Host` or +`Forwarded` value no longer costs an allocation, and on `[]byte` input, +which no longer needs a string conversion first. + +## List field iteration + +`SplitTrimSeq` returns an iterator over the elements of a list separated +by one byte, with ASCII whitespace trimmed from each element and empty +elements skipped — how HTTP list fields such as `Accept-Encoding`, +`Connection`, `Vary`, and `Cache-Control` are read (RFC 9110 Section +5.6.1: optional whitespace around the commas, empty elements ignored). +It replaces the `strings.SplitSeq` + `TrimSpace` + emptiness-check +triplet, locates each separator with a single `IndexByte`, works on +strings and byte slices alike, and yields subslices without copying. In +an ordinary caller the iterator inlines and allocates nothing, like +`strings.SplitSeq`; the benchmark ranges inside a helper function for +that reason, because calls made directly inside a `b.Loop` body are +never inlined and would show the closure allocations instead. + +## Duration formatting + +`AppendDuration` renders a `time.Duration` exactly as `d.String()` does — +"72h3m0.5s", "1.5ms", "0s" — into the caller's buffer, with the two-digit +table for the field digits; a value with no fraction, the common case, +never touches the fraction digits. `d.String()` allocates its result and +`fmt.Fprintf("%v", d)`, which Fiber's logger uses for the latency column, +costs several times more on top; an append-style form makes per-request +duration rendering (access logs, `Server-Timing`) allocation-free. + +## Decimal formatting + +`FormatUint`/`FormatInt` (and their 32- and 16-bit variants) and +`AppendUint`/`AppendInt` render integers eight digits at a time: a value +below 1e8 becomes eight zero-padded digit lanes through a fixed sequence +of multiplies, shifts, and masks (the SWAR inverse of the 8-digit parse +step in `ParseInt`), so a 64-bit value costs at most three such +conversions and two divisions, all independent of each other, instead of +one dependent divide-and-store per digit; the first significant digit is +found with a trailing-zero count. Values below 100 come from a +precomputed table, and the output is pinned to `strconv` by a dense sweep +plus every decimal and lane-group boundary. `GetMIME` in the same spirit +looks up extensions through a hash table keyed by the extension packed +into one lower-cased word with its length in the top lane, so a hit is a +multiply, a shift, and one slot comparison, with no allocation even for +upper-case input. + +These helpers were added on an amd64 machine, so like the `simd` numbers +their benchmarks are recorded separately from the arm64 catalog above and +join it on its next regeneration. The block also carries the current +numbers for the paths reworked on the same machine (integer formatting, +`GetMIME`, token-sized `EqualFold`), whose arm64 rows above predate that +work: + +Environment: +goos: linux +goarch: amd64 +pkg: github.com/gofiber/utils/v2 +cpu: AMD EPYC + +```text +// go test -benchmem -run=^$ -count=1 . -bench='^Benchmark_(FormatUint|FormatInt|FormatUint32|FormatInt32|FormatUint16|FormatInt16|AppendUint|AppendInt|EqualFold_Short|HashFold|GetMIME|AppendHTTPDate|ParseHTTPDate|AppendDuration|AppendQueryEscape|AppendQueryUnescape|AppendPathUnescape|AppendJSONString|ParseIPv4|ParseIPv6|CanonicalHeaderKey|IndexControl|CutByte|LastCutByte|SplitHostPort|SplitTrimSeq)$' +Benchmark_EqualFold_Short/3B/fiber-4 474570190 2.553 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/3B/default-4 377307522 3.197 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/4B/fiber-4 516945747 2.305 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/4B/default-4 292157928 4.131 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/5B/fiber-4 514813034 2.350 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/5B/default-4 528765130 2.314 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/7B/fiber-4 501824547 2.387 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/7B/default-4 421685026 2.873 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/8B/fiber-4 592805404 2.021 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/8B/default-4 361403394 3.276 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/10B/fiber-4 370927251 3.192 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/10B/default-4 309030364 3.844 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/16B/fiber-4 307347482 3.906 ns/op 0 B/op 0 allocs/op +Benchmark_EqualFold_Short/16B/default-4 207260846 5.811 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/2B/fiber-4 659036155 1.751 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/2B/default-4 261589642 4.678 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/4B/fiber-4 711944869 1.547 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/4B/default-4 68756901 17.48 ns/op 8 B/op 1 allocs/op +Benchmark_HashFold/12B/fiber-4 479447386 2.445 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/12B/default-4 44629953 27.36 ns/op 16 B/op 1 allocs/op +Benchmark_HashFold/17B/fiber-4 312646728 3.786 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/17B/default-4 37432442 31.80 ns/op 24 B/op 1 allocs/op +Benchmark_HashFold/48B/fiber-4 198629916 6.125 ns/op 0 B/op 0 allocs/op +Benchmark_HashFold/48B/default-4 19371859 64.41 ns/op 48 B/op 1 allocs/op +Benchmark_IndexControl/clean-16B/fiber-4 589318218 2.038 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/clean-16B/fiber-except-tab-4 579966133 2.103 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/clean-16B/default-4 155669052 7.793 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/clean-64B/fiber-4 213961107 5.723 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/clean-64B/fiber-except-tab-4 217851234 5.507 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/clean-64B/default-4 33828980 34.88 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/ctl-at-end-64B/fiber-4 173408127 6.696 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/ctl-at-end-64B/fiber-except-tab-4 163767840 7.781 ns/op 0 B/op 0 allocs/op +Benchmark_IndexControl/ctl-at-end-64B/default-4 29708812 39.79 ns/op 0 B/op 0 allocs/op +Benchmark_CutByte/fiber-4 437784441 2.756 ns/op 0 B/op 0 allocs/op +Benchmark_CutByte/default-4 383580765 3.160 ns/op 0 B/op 0 allocs/op +Benchmark_CutByte/fiber-bytes-4 426636248 2.833 ns/op 0 B/op 0 allocs/op +Benchmark_CutByte/default-bytes-4 354200200 3.478 ns/op 0 B/op 0 allocs/op +Benchmark_LastCutByte/fiber-4 749751696 1.676 ns/op 0 B/op 0 allocs/op +Benchmark_LastCutByte/default-4 632607783 1.892 ns/op 0 B/op 0 allocs/op +Benchmark_AppendDuration/micros/fiber-4 230424728 5.212 ns/op 0 B/op 0 allocs/op +Benchmark_AppendDuration/micros/default-4 80879913 13.09 ns/op 8 B/op 1 allocs/op +Benchmark_AppendDuration/micros/fmt-4 23875825 51.86 ns/op 16 B/op 2 allocs/op +Benchmark_AppendDuration/millis-frac/fiber-4 151633136 7.905 ns/op 0 B/op 0 allocs/op +Benchmark_AppendDuration/millis-frac/default-4 69842400 17.53 ns/op 16 B/op 1 allocs/op +Benchmark_AppendDuration/millis-frac/fmt-4 21604033 55.72 ns/op 24 B/op 2 allocs/op +Benchmark_AppendDuration/hours/fiber-4 178755894 6.764 ns/op 0 B/op 0 allocs/op +Benchmark_AppendDuration/hours/default-4 66228235 18.09 ns/op 8 B/op 1 allocs/op +Benchmark_AppendDuration/hours/fmt-4 21582046 55.41 ns/op 16 B/op 2 allocs/op +Benchmark_FormatUint/small/fiber-4 1000000000 1.032 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint/small/strconv-4 1000000000 1.160 ns/op 0 B/op 0 allocs/op +Benchmark_FormatUint/medium/fiber-4 81341080 13.88 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint/medium/strconv-4 91133340 13.66 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint/large/fiber-4 75384313 15.48 ns/op 24 B/op 1 allocs/op +Benchmark_FormatUint/large/strconv-4 63376773 19.89 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/small_pos/fiber-4 1000000000 0.9376 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_pos/strconv-4 1000000000 0.9984 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_neg/fiber-4 1000000000 1.057 ns/op 0 B/op 0 allocs/op +Benchmark_FormatInt/small_neg/strconv-4 142956472 8.399 ns/op 3 B/op 1 allocs/op +Benchmark_FormatInt/medium_pos/fiber-4 87277550 13.60 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_pos/strconv-4 95885060 12.93 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_neg/fiber-4 89401650 13.72 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/medium_neg/strconv-4 91703590 13.05 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt/large_pos/fiber-4 76933171 15.52 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_pos/strconv-4 62900060 19.10 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_neg/fiber-4 80196792 15.17 ns/op 24 B/op 1 allocs/op +Benchmark_FormatInt/large_neg/strconv-4 61880923 19.37 ns/op 24 B/op 1 allocs/op +Benchmark_FormatUint32/fiber-4 100000000 11.86 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint32/strconv-4 93858640 13.21 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt32/fiber-4 91589426 12.22 ns/op 16 B/op 1 allocs/op +Benchmark_FormatInt32/strconv-4 94022053 13.10 ns/op 16 B/op 1 allocs/op +Benchmark_FormatUint16/fiber-4 128578032 9.293 ns/op 5 B/op 1 allocs/op +Benchmark_FormatUint16/strconv-4 121208905 9.864 ns/op 5 B/op 1 allocs/op +Benchmark_FormatInt16/fiber-4 127401009 9.421 ns/op 8 B/op 1 allocs/op +Benchmark_FormatInt16/strconv-4 100000000 10.22 ns/op 8 B/op 1 allocs/op +Benchmark_AppendUint/fiber-4 175413508 6.905 ns/op 0 B/op 0 allocs/op +Benchmark_AppendUint/strconv-4 182603853 6.549 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/small_neg/fiber-4 576874452 2.089 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/small_neg/strconv-4 379915365 3.223 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/medium_neg/fiber-4 167008982 7.141 ns/op 0 B/op 0 allocs/op +Benchmark_AppendInt/medium_neg/strconv-4 168921136 7.105 ns/op 0 B/op 0 allocs/op +Benchmark_CanonicalHeaderKey/canonical/fiber-4 100000000 10.35 ns/op 0 B/op 0 allocs/op +Benchmark_CanonicalHeaderKey/canonical/default-4 96366190 12.84 ns/op 0 B/op 0 allocs/op +Benchmark_CanonicalHeaderKey/common-lower/fiber-4 54264433 22.28 ns/op 16 B/op 1 allocs/op +Benchmark_CanonicalHeaderKey/common-lower/default-4 44659976 26.58 ns/op 0 B/op 0 allocs/op +Benchmark_CanonicalHeaderKey/custom-lower/fiber-4 40730636 29.51 ns/op 24 B/op 1 allocs/op +Benchmark_CanonicalHeaderKey/custom-lower/default-4 30766311 39.13 ns/op 24 B/op 1 allocs/op +Benchmark_SplitHostPort/host-port/fiber-4 196332888 6.120 ns/op 0 B/op 0 allocs/op +Benchmark_SplitHostPort/host-port/default-4 198113818 6.064 ns/op 0 B/op 0 allocs/op +Benchmark_SplitHostPort/ipv6-port/fiber-4 172842418 6.987 ns/op 0 B/op 0 allocs/op +Benchmark_SplitHostPort/ipv6-port/default-4 186879514 6.444 ns/op 0 B/op 0 allocs/op +Benchmark_SplitHostPort/missing-port/fiber-4 290848148 4.164 ns/op 0 B/op 0 allocs/op +Benchmark_SplitHostPort/missing-port/default-4 80586097 14.28 ns/op 32 B/op 1 allocs/op +Benchmark_GetMIME/fiber-4 96395971 13.32 ns/op 0 B/op 0 allocs/op +Benchmark_GetMIME/default-4 26174697 48.25 ns/op 0 B/op 0 allocs/op +Benchmark_AppendHTTPDate/fiber-4 85675015 14.46 ns/op 0 B/op 0 allocs/op +Benchmark_AppendHTTPDate/default-4 21580892 56.33 ns/op 0 B/op 0 allocs/op +Benchmark_ParseHTTPDate/fiber-4 134781268 8.924 ns/op 0 B/op 0 allocs/op +Benchmark_ParseHTTPDate/default-4 16069844 69.36 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv4/fiber-4 145306470 8.264 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv4/default-4 114781018 10.48 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv6/compressed/fiber-4 66615272 17.10 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv6/compressed/default-4 52520895 23.28 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv6/full/fiber-4 47439188 24.95 ns/op 0 B/op 0 allocs/op +Benchmark_ParseIPv6/full/default-4 40544450 32.79 ns/op 0 B/op 0 allocs/op +Benchmark_AppendJSONString/clean-16B/fiber-4 138761914 8.630 ns/op 0 B/op 0 allocs/op +Benchmark_AppendJSONString/clean-16B/default-4 20646793 57.16 ns/op 40 B/op 2 allocs/op +Benchmark_AppendJSONString/clean-64B/fiber-4 46117554 26.39 ns/op 0 B/op 0 allocs/op +Benchmark_AppendJSONString/clean-64B/default-4 13671264 87.64 ns/op 96 B/op 2 allocs/op +Benchmark_AppendJSONString/escaped-64B/fiber-4 16098729 71.69 ns/op 0 B/op 0 allocs/op +Benchmark_AppendJSONString/escaped-64B/default-4 9781168 125.1 ns/op 96 B/op 2 allocs/op +Benchmark_AppendJSONString/unicode-64B/fiber-4 11466999 105.6 ns/op 0 B/op 0 allocs/op +Benchmark_AppendJSONString/unicode-64B/default-4 8753143 137.5 ns/op 112 B/op 2 allocs/op +Benchmark_SplitTrimSeq/accept-encoding/fiber-4 100000000 12.02 ns/op 0 B/op 0 allocs/op +Benchmark_SplitTrimSeq/accept-encoding/default-4 100000000 11.34 ns/op 0 B/op 0 allocs/op +Benchmark_SplitTrimSeq/accept/fiber-4 46949877 25.61 ns/op 0 B/op 0 allocs/op +Benchmark_SplitTrimSeq/accept/default-4 45399441 26.49 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryEscape/clean-64B/fiber-4 56747625 19.26 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryEscape/clean-64B/default-4 84982970 15.04 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryEscape/mixed-64B/fiber-4 13597939 87.92 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryEscape/mixed-64B/default-4 13707001 85.03 ns/op 192 B/op 2 allocs/op +Benchmark_AppendQueryUnescape/plain-64B/fiber-4 171561770 6.994 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryUnescape/plain-64B/default-4 29265138 46.02 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryUnescape/escaped-64B/fiber-4 13128865 90.84 ns/op 0 B/op 0 allocs/op +Benchmark_AppendQueryUnescape/escaped-64B/default-4 13054190 91.49 ns/op 48 B/op 1 allocs/op +Benchmark_AppendPathUnescape/plain-25B/fiber-4 242829855 4.941 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathUnescape/plain-25B/default-4 78070837 15.53 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathUnescape/escaped-31B/fiber-4 52789323 23.36 ns/op 0 B/op 0 allocs/op +Benchmark_AppendPathUnescape/escaped-31B/default-4 27718658 43.70 ns/op 24 B/op 1 allocs/op +``` + ## SWAR primitives The [`swar`](swar/) package exports the SWAR (SIMD within a register) @@ -492,17 +836,375 @@ function for. The package's remaining benchmark, `Benchmark_Load8_Fusion`, is an advisory codegen guard rather than an API performance promise, so it is deliberately not part of the catalog above. +## SIMD-accelerated search (package simd) + +The [`simd`](simd/) package is the vector-width counterpart to `swar`: byte +searching and validation whose scan kernels dispatch to AVX2 assembly (four +32-byte vectors per iteration) on amd64 CPUs for inputs of `simd.MinLen` +(32) bytes or more, and fall back to portable loops built on the `swar` +primitives everywhere else, so it builds and behaves identically on every +platform. +`simd.Accelerated()` reports which mode is active. CPU capability detection +uses [`golang.org/x/sys/cpu`](https://pkg.go.dev/golang.org/x/sys/cpu), +which also verifies OS support for saving the vector register state. + +The AVX2-backed kernels are the multi-needle scans (`Memchr2`, `Memchr3`), +the paired-byte scan (`MemchrPair`), the class scans +(`MemchrDigit`/`MemchrDigitAt`, `MemchrWord`/`MemchrNotWord`), the ASCII +scans (`IsASCII`, `FirstNonASCII`, `CountNonASCII`), and the substring +search (`Memmem`), which +prefilters on the needle's rarest bytes (`SelectRareBytes`, `ByteRank`) +before verifying candidates — 2-6 byte needles containing two distinct +values are scanned for their two rarest bytes at the exact relative +distance, longer or single-valued needles for the single rarest byte. +Each kernel classifies four 32-byte vectors per iteration. Where the +result is a position or a yes/no, the four masks are combined, so a +128-byte block costs a single `VPMOVMSKB` and a single branch, and the +scans that report a position re-extract the four masks in address order on +the (rare) hit path. `CountNonASCII` is the exception — a count cannot be +recovered from a combined mask, so its block loop accumulates per-lane +counts in vector byte lanes (a signed compare against zero and a byte +subtract per vector) and reduces them once at the end, while the +remaining whole vectors are extracted and population-counted; it is the +one kernel gated on `POPCNT` in addition to AVX2. +One tier is documented explicitly as unaccelerated: +`MemchrInTable`/`MemchrNotInTable` are plain +scalar loops, since an arbitrary 256-entry membership test has no cheap +vector form. There is deliberately no single-needle `Memchr`: +`bytes.IndexByte` is already vector-accelerated by the Go runtime. `Memmem` +delegates to `bytes.Index` for haystacks of up to 64 bytes, where the +stdlib's brute-force vector kernel is level with the paired prefilter +(`Benchmark_Memmem_Prefilter` forces the prefilter helpers at every size +to keep that measurable); from 65 bytes `bytes.Index` switches to a loop +anchored on the needle's first byte, and the paired scan takes over. +Needles that take the single rare-byte scan keep a 128-byte routing point, +since that scan is less selective. Both prefilters bail to `bytes.Index` +after a bounded number of failed candidate verifications, so even +adversarial inputs — a rare byte everywhere plus a long almost-matching +needle — stay within a constant of the stdlib's O(n+m) (see +`Benchmark_Memmem_Adversarial`). The +package operates on `[]byte` only; the generic top-level helpers `IsASCII`, +`IndexAny2`, and `IndexAny3` dispatch into it automatically for inputs of +`simd.MinLen`+ bytes on amd64, which is where the AVX2 kernels overtake the +SWAR word loops (-35% to -88% ns/op at 32-512B in `benchstat -count=10` +runs; shorter inputs keep the existing SWAR paths). + +The kernels are adapted from the [coregex](https://github.com/coregx/coregex) +project's `simd` package (MIT License, Copyright (c) 2025 Andrey Kolkov and +contributors; see [`simd/LICENSE`](simd/LICENSE)), with the legacy-SSE +register moves in the kernels replaced by VEX-encoded ones to avoid AVX-SSE +transition stalls, the scalar tail loops replaced by overlapping vector +rescans at the buffer end (a 63-byte scan previously cost ~3.7x a 64-byte +one), the 32-byte main loops replaced by 4x unrolled 128-byte blocks whose +bound is tested once at the bottom against a precomputed limit pointer, the +`\w` classifier rewritten from three `VPMINUB`/`VPMAXUB` clamp-and-compare +range tests into two `VPSHUFB` nibble-table lookups (with the block test +reduced to one compare over the four raw class values), the digit range +test reduced from two signed compares and a `VPANDN` to one biased +`VPADDB` and one compare, `FirstNonASCII` and `CountNonASCII` given +kernels of their own (they were SWAR-only, and the count kernel's block +loop accumulates in vector byte lanes rather than extracting and +population-counting every vector's mask), the 128-byte block loops +placed at fixed offsets inside a 32-byte code window so their throughput +no longer depends on where the linker places each kernel, and the +fallbacks reworked around the stdlib and the `swar` package as described +above. + +Against the pre-unrolling kernels, `benchstat -count=10` on the machine +below reports -26.6%/-49.7% ns/op for `Memchr2` at 512B/4096B, +-17.6%/-34.3% for `Memchr3`, -13.4%/-24.6% for `MemchrPair`, +-39.2%/-50.5% for `MemchrDigit`, -53.5%/-63.7% for `MemchrNotWord`, +-42.2%/-65.7% for `IsASCII`, and -13.7%/-27.1% for `Memmem`, which rides +the paired scan. Those percentages come from `benchstat` over ten runs of +each side; the single-run table below is a catalog, not a base-vs-head +comparison, so subtracting its rows from an older copy of it will not +reproduce them. + +Two bands see no benefit and are worth stating plainly. Inputs below +`simd.MinLen` never reach the kernels at all. Inputs of 32-127 bytes do +reach them but skip the 128-byte block loop, so they pay its setup with +nothing to amortize it against: across that band `benchstat` reports the +class scans clearly ahead (`MemchrNotWord` -8.6% at 32B, -18.4% at 64B; +`IsASCII` -5.0%/-4.3%), most rows statistically unchanged, and two small +regressions — `MemchrDigit` +5.6% at 32B and `Memchr3` +3.8% at 64B. Read +those small-input figures against the run's own noise floor: the `default` +legs call unchanged stdlib code, so their movement bounds what a delta of +that size means. They held within 1% in the run quoted here, but a later +run on the same machine drifted up to 17% on those same rows, so anything +under ~10% at 32-64B should be taken as "no measured change" unless its +control legs are quiet. + +On the portable side, pinning each unrolled group of words with a reslice +before loading at constant offsets inside it removes the per-load bounds +check that `swar.Load8`'s own reslice otherwise repeats. Measured with +`benchstat -count=10` against the same fallbacks, at 32B/512B/4KiB: +`IsASCII` -28%/-60%/-63%, `CountNonASCII` -24%/-44%/-44%, +`FirstNonASCII` -23%/-37%/-43%, `Memchr2` -19%/-23%/-25%, +`MemchrDigit` -7%/-12%/-17%, `Memchr3` -8%/-13%/-18%, +`MemchrWord` -11%/-8%/-11%, `MemchrNotWord` -5%/-7%/-6%. The tier a group +adds costs one compare on inputs too short to use it, which shows up as ++3% to +10% on some of the 8B fallback rows — a few tenths of a +nanosecond, and only below the length where the group pays for itself. +`utils.IsASCII` carries the same rework, so the two copies of that scan +stay in step. + +Making the counting kernel finish its own sub-vector remainder (rather +than splitting the input in Go and calling the SWAR loop for the tail) +also removed a second non-inlinable call from every whole-vector input: +`CountNonASCII` at 32B went from 11.3ns — behind its own fallback — to +6.8ns, level with it, and it leads from 64B up. + +A later audit pass reworked the kernels and fallbacks once more; +`benchstat -count=10` on the machine below, base vs. head, reports: + +- `MemchrDigit` -20% at 512B and -27% at 4KiB from the one-add, + one-compare range test. +- `MemchrWord` -13%/-11% and `MemchrNotWord` -4%/-10% at 512B/4KiB from + comparing the reduced block once instead of every vector, and their + SWAR fallbacks -36%/-41% at 32B, -40%/-43% at 64B and -43%/-45% at + 512B: 15 ALU operations per word instead of 26, from case-folding the + two letter ranges into one test, a one-add underscore test, and a + single shared ASCII gate. +- `CountNonASCII` -15% at 512B and -41% at 4KiB, with 32B and 64B + unchanged: the block loop counts in vector byte lanes (a signed compare + against zero and a byte subtract per vector, flushed through `VPSADBW` + every 127 blocks) instead of four port-0 `VPMOVMSKB` extractions per + block. The remaining whole vectors are still extracted and + population-counted, because the vector reduction is a fixed ten-cycle + chain that one to three vectors cannot amortize — a first version that + used the accumulators for those too was 20% slower at 32-64B. +- `MemchrPair`'s SWAR fallback -33% at 32B, -41% at 64B, -51% at 512B and + -52% at 4KiB, and `MemchrPair` itself -30% at 32B, where the dispatch + routes to that fallback: it now scans two words per branch through + pinned three-index windows (no per-load capacity check or pointer + clamp) and finishes with one overlapping word instead of a scalar + tail. Before, at 32B, it ran no faster than a plain scalar loop. +- `Memmem` -62% at 96B: needles that take the paired prefilter are routed + through it from 65-byte haystacks, where `bytes.Index` leaves its + brute-force vector kernel for a first-byte-anchored loop; 64B and + 128B+ are unchanged. + +The same pinned-window rework applied to the case-conversion loops in +`internal/caseconv`, which the `strings` and `bytes` packages' `ToLower` +and `ToUpper` build on, gives on the same machine -27% to -37% ns/op for +the in-place `UnsafeToLower`/`UnsafeToUpper` at 39-64B, -14% to -19% for +the scan-only path that finds nothing to convert, and -5% to -17% for the +allocating conversions, where the allocation dominates. The arm64 catalog +rows above were not regenerated for that change. + +Comparing the base and head test binaries also showed the untouched +`MemchrPair` kernel ~10% slower at 4KiB, purely because the linker had +moved its entry by 32 bytes: on Skylake-derived cores the JCC erratum +mitigation keeps a macro-fused compare-and-branch that crosses or ends on +a 32-byte boundary out of the decoded-uop cache, so the block loop ran +from the legacy decoder. Every block loop is now placed by a `BLOCKALIGN` +macro at a window offset where all of its fused pairs fit (a few +once-per-call NOPs, visible as +5% on `Memchr2` at 512B and nothing at +4KiB), and an amd64 test reads each kernel's code and fails if a later +edit lets a pair straddle a boundary again. + +Because the AVX2 kernels only engage on amd64, their benchmark numbers are +recorded separately from the arm64 catalog above: + +Environment: +goos: linux +goarch: amd64 +pkg: github.com/gofiber/utils/v2/simd +cpu: AMD EPYC + +```text +// go test ./simd/ -benchmem -run=^$ -bench=Benchmark_ -count=1 +Benchmark_Memchr2/8B/simd-4 453336069 2.623 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/8B/scalar-4 478197765 2.674 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/8B/default-4 72345934 15.47 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/32B/simd-4 543597138 2.243 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/32B/scalar-4 257508678 4.850 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/32B/default-4 74193906 16.23 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/64B/simd-4 472058904 2.590 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/64B/scalar-4 155048143 7.749 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/64B/default-4 43808686 27.32 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/512B/simd-4 285333643 4.214 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/512B/scalar-4 22270338 53.44 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/512B/default-4 5630736 214.0 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/4096B/simd-4 46224841 26.22 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/4096B/scalar-4 2877489 422.0 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr2/4096B/default-4 726162 1572 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/8B/simd-4 339925651 3.321 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/8B/scalar-4 421027478 2.820 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/8B/default-4 77200100 15.70 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/32B/simd-4 519319734 2.359 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/32B/scalar-4 206433102 5.420 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/32B/default-4 72844312 16.53 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/64B/simd-4 449978571 2.630 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/64B/scalar-4 129309135 9.837 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/64B/default-4 42185463 26.81 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/512B/simd-4 225940567 5.312 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/512B/scalar-4 17643322 66.31 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/512B/default-4 6013467 202.0 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/4096B/simd-4 33974170 35.38 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/4096B/scalar-4 2357731 506.4 ns/op 0 B/op 0 allocs/op +Benchmark_Memchr3/4096B/default-4 784706 1620 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/8B/simd-4 233632957 5.209 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/8B/swar-4 362050117 3.056 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/8B/scalar-4 421727352 2.530 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/32B/simd-4 220179676 5.456 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/32B/swar-4 246905683 4.732 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/32B/scalar-4 96293247 11.83 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/64B/simd-4 394496740 3.054 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/64B/swar-4 154056295 7.402 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/64B/scalar-4 48580516 22.82 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/512B/simd-4 214293470 5.584 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/512B/swar-4 24495690 46.56 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/512B/scalar-4 6074738 209.4 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/4096B/simd-4 34414917 33.38 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/4096B/swar-4 3143101 383.6 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrPair/4096B/scalar-4 778839 1533 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/8B/simd-4 483880309 2.464 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/8B/scalar-4 750069652 1.565 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/32B/simd-4 619133365 1.987 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/32B/scalar-4 267233883 4.658 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/64B/simd-4 527087062 2.450 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/64B/scalar-4 237343849 5.062 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/512B/simd-4 332003768 3.635 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/512B/scalar-4 33574414 35.55 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/4096B/simd-4 59304564 20.04 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrDigit/4096B/scalar-4 4241964 285.1 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/8B/simd-4 437997328 2.756 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/8B/scalar-4 567125090 2.095 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/32B/simd-4 490780172 2.595 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/32B/scalar-4 210365462 5.681 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/64B/simd-4 457079554 2.636 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/64B/scalar-4 100000000 10.14 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/512B/simd-4 186813315 6.331 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/512B/scalar-4 15922886 74.89 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/4096B/simd-4 30137052 42.05 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrWord/4096B/scalar-4 1908139 618.5 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/8B/simd-4 394849383 2.875 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/8B/scalar-4 535954507 2.263 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/32B/simd-4 515813132 2.383 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/32B/scalar-4 199687904 5.966 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/64B/simd-4 476874938 2.537 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/64B/scalar-4 100000000 10.77 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/512B/simd-4 209584124 5.633 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/512B/scalar-4 15348631 78.44 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/4096B/simd-4 29995101 40.43 ns/op 0 B/op 0 allocs/op +Benchmark_MemchrNotWord/4096B/scalar-4 1943118 617.6 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/8B/simd-4 270557725 4.450 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/8B/default-4 334460436 3.551 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/32B/simd-4 242523679 4.908 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/32B/default-4 286539350 4.194 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/64B/simd-4 187219377 6.441 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/64B/default-4 211716758 5.631 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/96B/simd-4 144067748 8.323 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/96B/default-4 55789027 20.11 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/128B/simd-4 141711127 8.592 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/128B/default-4 45068487 26.67 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/192B/simd-4 134565835 8.914 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/192B/default-4 30457960 41.10 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/512B/simd-4 100000000 10.22 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/512B/default-4 9940363 119.8 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/4096B/simd-4 31796578 38.44 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem/4096B/default-4 1304142 921.5 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/8B/paired-4 208555989 5.886 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/8B/paired-stdlib-4 314000942 3.663 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/32B/paired-4 148980051 8.022 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/32B/paired-stdlib-4 284449442 4.381 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/32B/single-4 184532997 6.402 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/32B/single-stdlib-4 248867040 4.648 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/64B/paired-4 228923468 5.241 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/64B/paired-stdlib-4 200834196 5.973 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/64B/single-4 87575604 13.70 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/64B/single-stdlib-4 100000000 10.89 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/96B/paired-4 219780091 5.479 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/96B/paired-stdlib-4 56172361 21.41 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/96B/single-4 67754218 17.68 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/96B/single-stdlib-4 74631896 16.07 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/128B/paired-4 210315266 5.479 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/128B/paired-stdlib-4 47404712 25.93 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/128B/single-4 47889631 23.78 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/128B/single-stdlib-4 53643756 21.06 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/192B/paired-4 214270470 5.656 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/192B/paired-stdlib-4 28740783 40.53 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/192B/single-4 31663087 36.76 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/192B/single-stdlib-4 34901227 36.17 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/512B/paired-4 150790410 7.509 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/512B/paired-stdlib-4 9959937 112.9 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/512B/single-4 11452664 104.3 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/512B/single-stdlib-4 10991572 109.4 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/4096B/paired-4 35541574 35.89 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/4096B/paired-stdlib-4 1289738 915.4 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/4096B/single-4 1313083 922.7 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Prefilter/4096B/single-stdlib-4 1300030 863.5 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Adversarial/simd-4 1174 1033022 ns/op 0 B/op 0 allocs/op +Benchmark_Memmem_Adversarial/default-4 1230 1033388 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/8B/simd-4 556102136 2.112 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/8B/swar-4 1000000000 0.9469 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/32B/simd-4 580464447 2.085 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/32B/swar-4 759707629 1.639 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/64B/simd-4 577495986 2.093 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/64B/swar-4 603801266 2.070 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/512B/simd-4 393139882 2.919 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/512B/swar-4 172784758 7.016 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/4096B/simd-4 84996772 14.17 ns/op 0 B/op 0 allocs/op +Benchmark_IsASCII/4096B/swar-4 24236050 46.72 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/8B/simd-4 468366580 2.585 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/8B/swar-4 726652689 1.531 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/32B/simd-4 578755396 2.013 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/32B/swar-4 594718906 2.008 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/64B/simd-4 598390389 2.021 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/64B/swar-4 457455298 2.434 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/512B/simd-4 387713314 2.955 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/512B/swar-4 87003118 13.46 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/4096B/simd-4 85277996 14.19 ns/op 0 B/op 0 allocs/op +Benchmark_FirstNonASCII/4096B/swar-4 10937323 108.7 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/8B/simd-4 454104896 2.798 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/8B/swar-4 708241747 1.701 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/32B/simd-4 558144679 2.226 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/32B/swar-4 545270572 2.260 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/64B/simd-4 520362260 2.183 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/64B/swar-4 374447266 3.232 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/512B/simd-4 353822752 3.432 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/512B/swar-4 68949931 18.16 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/4096B/simd-4 71523846 17.36 ns/op 0 B/op 0 allocs/op +Benchmark_CountNonASCII/4096B/swar-4 8294362 145.3 ns/op 0 B/op 0 allocs/op +``` + + ## ☕ Supporters Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, hosting, and serverless infrastructure. If you want to support Fiber, please become a [GitHub Sponsor](https://github.com/sponsors/gofiber). +

+ + + + CodeRabbit + + +

+

+ + Blacksmith + +

+

+ Tool Sponsors - supporting Fiber with free IDE licenses and AI credits +

+

+ JetBrains +   + OpenAI +   + Anthropic +

+ ### 📅 Monthly Sponsors - +
🔥 Fiber Guardian@coderabbitai
☕ Fiber Supporter@NdoleStudio @petercool
☕ Fiber Supporter@NdoleStudio
🪴 Fiber Friend@simonheisstpeter
@@ -510,5 +1212,7 @@ Fiber is an open-source project that runs on donations to pay the bills, e.g., o +
🚀 Fiber Hero@thnxdev
🪴 Fiber Friend@Gl1tchedPixzl
+ diff --git a/src/vendor/github.com/gofiber/utils/v2/ascii.go b/src/vendor/github.com/gofiber/utils/v2/ascii.go index a16018c7..44ba7e19 100644 --- a/src/vendor/github.com/gofiber/utils/v2/ascii.go +++ b/src/vendor/github.com/gofiber/utils/v2/ascii.go @@ -1,29 +1,61 @@ package utils import ( + "github.com/gofiber/utils/v2/internal/unsafeconv" + "github.com/gofiber/utils/v2/simd" "github.com/gofiber/utils/v2/swar" ) -// quoteLanes and backslashLanes broadcast '"' and '\\' to every lane. +// quoteLanes, backslashLanes, and tabLanes broadcast '"', '\\', and HTAB to every lane. const ( quoteLanes = uint64('"') * swar.Ones backslashLanes = uint64('\\') * swar.Ones + tabLanes = uint64('\t') * swar.Ones ) +// The dispatch prologues below gate on simd.MinLen — the measured length +// from which the AVX2 kernels beat these SWAR word loops — so the crossover +// has a single source of truth in the simd package. The simd.Accelerated() +// gate is a constant false off amd64, so the accelerated branches compile +// away entirely there. + // IsASCII reports whether s contains only ASCII bytes (no byte >= 0x80). // It ORs four words per iteration where possible (no index is needed, so -// detection can be deferred to one test per 32 bytes), then tests word-wise; -// inputs of 8+ bytes finish with one overlapping word at n-8, shorter ones -// byte-wise. +// detection can be deferred to one test per 32 bytes), then two, then +// word-wise; inputs of 8+ bytes finish with one overlapping word at n-8, +// shorter ones byte-wise. +// On amd64 CPUs with AVX2, inputs of 32+ bytes dispatch to package simd +// instead. +// +// The unrolled loops pin their group of words with a reslice and load at +// constant offsets inside it. swar.Load8's own reslice is bounds-checked +// against the backing array, which the length-based loop condition does +// not imply, so a variable index costs a compare and a branch per load; +// pinning the window pays that once per group instead. This mirrors +// simd.isASCIIGeneric — the same scan, kept in step so a retune of either +// is a retune of both. func IsASCII[S byteSeq](s S) bool { n := len(s) + if n >= simd.MinLen && simd.Accelerated() { + return simd.IsASCII(unsafeconv.Bytes(s)) + } + if n >= 8 && n < 16 { + return (swar.Load8(s, 0)|swar.Load8(s, n-8))&swar.HighBits == 0 + } i := 0 for ; i+32 <= n; i += 32 { - acc := swar.Load8(s, i) | swar.Load8(s, i+8) | swar.Load8(s, i+16) | swar.Load8(s, i+24) + w := s[i : i+32] + acc := swar.Load8(w, 0) | swar.Load8(w, 8) | swar.Load8(w, 16) | swar.Load8(w, 24) if acc&swar.HighBits != 0 { return false } } + for ; i+16 <= n; i += 16 { + w := s[i : i+16] + if (swar.Load8(w, 0)|swar.Load8(w, 8))&swar.HighBits != 0 { + return false + } + } for ; i+8 <= n; i += 8 { if swar.Load8(s, i)&swar.HighBits != 0 { return false @@ -57,8 +89,11 @@ func IndexNonQuotable[S byteSeq](s S) int { // Two words per branch: the masks compute independently, and if only the // second word matched, its first set lane is still exact. for ; i+16 <= n; i += 16 { - m0 := nonQuotableMask(swar.Load8(s, i)) - m1 := nonQuotableMask(swar.Load8(s, i+8)) + // Pinned window, as in IsASCII above: the two loads land at + // constant offsets and skip their bounds checks. + w := s[i : i+16] + m0 := nonQuotableMask(swar.Load8(w, 0)) + m1 := nonQuotableMask(swar.Load8(w, 8)) if m0|m1 != 0 { if m0 != 0 { return i + swar.FirstLane(m0) @@ -89,16 +124,9 @@ func IndexNonQuotable[S byteSeq](s S) int { } // nonQuotableMask marks the lanes of w holding bytes that need RFC 9110 -// quoted-string escaping. Like swar.ZeroLanes, the result is exact in and below -// the first marked lane, which is all the first-match scan above consumes. +// quoted-string escaping: controls other than HTAB (quotable qdtext), DEL, +// '"', and '\\'. Like swar.ZeroLanes, the result is exact in and below the +// first marked lane, which is all the first-match scan above consumes. func nonQuotableMask(w uint64) uint64 { - // Controls (< 0x20) and DEL (0x7F) share one biased range test: - // t := ((c & 0x7F) + 1) & 0x7F maps DEL to 0 and controls to 0x01..0x20, - // so t <= 0x20 captures exactly both; lanes with the high bit set - // (obs-text, always quotable) are excluded by the &^ w term. HTAB is - // quotable qdtext, so its lanes are cleared with an exact match mask — - // an approximate one could wrongly clear a control lane above a tab. - t := ((w & swar.LowSeven) + swar.Ones) & swar.LowSeven - ctl := ^(t + (0x80-0x21)*swar.Ones) &^ w & swar.HighBits &^ swar.MatchByteMask(w, '\t') - return ctl | swar.ZeroLanes(w^quoteLanes) | swar.ZeroLanes(w^backslashLanes) + return controlLanes(w)&otherLanes(w, tabLanes) | swar.ZeroLanes(w^quoteLanes) | swar.ZeroLanes(w^backslashLanes) } diff --git a/src/vendor/github.com/gofiber/utils/v2/bytes/case.go b/src/vendor/github.com/gofiber/utils/v2/bytes/case.go index 8ad483e9..2d703d73 100644 --- a/src/vendor/github.com/gofiber/utils/v2/bytes/case.go +++ b/src/vendor/github.com/gofiber/utils/v2/bytes/case.go @@ -4,14 +4,15 @@ import ( "github.com/gofiber/utils/v2/internal/caseconv" ) -// swarMinLen is the smallest input length worth routing through the -// word-at-a-time (SWAR) helpers; shorter inputs are cheaper byte-by-byte. -const swarMinLen = caseconv.WordLen +// Sub-word inputs convert here, not in caseconv: at these lengths the call costs +// more than the table lookups. Delegating them measured +47%/+43% on unchanged +// three-byte input and +65%/+60% for the in-place forms (benchstat n=15, +// interleaved, Go 1.26, linux/amd64; the http-get cases reproduce it). // ToLower converts an ASCII byte slice to lower-case without modifying the input. func ToLower(b []byte) []byte { n := len(b) - if n < swarMinLen { + if n < caseconv.WordLen { table := caseconv.ToLowerTable for i := 0; i < n; i++ { c := b[i] @@ -33,20 +34,13 @@ func ToLower(b []byte) []byte { if i < 0 { return b } - - dst := make([]byte, n) - // Copy the unchanged prefix up to the word containing the first - // uppercase byte, then convert the rest word-at-a-time. - from := i &^ (caseconv.WordLen - 1) - copy(dst, b[:from]) - caseconv.ToLowerCopy(dst, b, from) - return dst + return caseconv.ToLowerFrom(b, i) } // ToUpper converts an ASCII byte slice to upper-case without modifying the input. func ToUpper(b []byte) []byte { n := len(b) - if n < swarMinLen { + if n < caseconv.WordLen { table := caseconv.ToUpperTable for i := 0; i < n; i++ { c := b[i] @@ -68,18 +62,13 @@ func ToUpper(b []byte) []byte { if i < 0 { return b } - - dst := make([]byte, n) - from := i &^ (caseconv.WordLen - 1) - copy(dst, b[:from]) - caseconv.ToUpperCopy(dst, b, from) - return dst + return caseconv.ToUpperFrom(b, i) } // UnsafeToLower converts an ASCII byte slice to lower-case in-place. // The passed slice content is modified and the same slice is returned. func UnsafeToLower(b []byte) []byte { - if len(b) < swarMinLen { + if len(b) < caseconv.WordLen { table := caseconv.ToLowerTable for i := range b { b[i] = table[b[i]] @@ -93,7 +82,7 @@ func UnsafeToLower(b []byte) []byte { // UnsafeToUpper converts an ASCII byte slice to upper-case in-place. // The passed slice content is modified and the same slice is returned. func UnsafeToUpper(b []byte) []byte { - if len(b) < swarMinLen { + if len(b) < caseconv.WordLen { table := caseconv.ToUpperTable for i := range b { b[i] = table[b[i]] diff --git a/src/vendor/github.com/gofiber/utils/v2/byteseq.go b/src/vendor/github.com/gofiber/utils/v2/byteseq.go index 707df64a..a31bac1a 100644 --- a/src/vendor/github.com/gofiber/utils/v2/byteseq.go +++ b/src/vendor/github.com/gofiber/utils/v2/byteseq.go @@ -1,6 +1,8 @@ package utils import ( + "math/bits" + "github.com/gofiber/utils/v2/internal/caseconv" "github.com/gofiber/utils/v2/swar" ) @@ -9,6 +11,12 @@ type byteSeq interface { ~string | ~[]byte } +// load4 assembles s[i:i+4] into a little-endian uint32; the caller guarantees i+4 <= len(s). +func load4[S byteSeq](s S, i int) uint32 { + w := s[i : i+4] + return uint32(w[0]) | uint32(w[1])<<8 | uint32(w[2])<<16 | uint32(w[3])<<24 +} + // EqualFold tests ascii strings or bytes for equality case-insensitively func EqualFold[S byteSeq](b, s S) bool { n := len(b) @@ -36,6 +44,14 @@ func EqualFold[S byteSeq](b, s S) bool { y := swar.Load8(s, n-8) return x == y || swar.ToUpperWord(x) == swar.ToUpperWord(y) } + if n >= 4 { + // 4..7 bytes: two overlapping 4-byte windows packed into one word + // fold with a single ToUpperWord; checked after the word paths so + // longer inputs pay nothing for it. + x := uint64(load4(b, 0)) | uint64(load4(b, n-4))<<32 + y := uint64(load4(s, 0)) | uint64(load4(s, n-4))<<32 + return x == y || swar.ToUpperWord(x) == swar.ToUpperWord(y) + } table := caseconv.ToUpperTable for ; i < n; i++ { @@ -46,6 +62,63 @@ func EqualFold[S byteSeq](b, s S) bool { return true } +// HashFold returns a 64-bit hash of s in which ASCII letters are folded to one +// case: strings that EqualFold reports equal hash equal. It is the hashing +// half of a case-insensitive lookup table whose other half is EqualFold, for +// keys such as header or field names, and reads s a word at a time without +// writing a folded copy of it anywhere. As in EqualFold, only 'A'..'Z' and +// 'a'..'z' fold; every other byte, including those >= 0x80, hashes as is. +// +// It is not a cryptographic hash, and it takes no seed, so it offers no +// protection against collisions planned in advance: use it to index keys of +// the program's own, such as the fields of a struct, and not to store keys an +// attacker picks. Its values may change between releases; do not persist them. +func HashFold[S byteSeq](s S) uint64 { + n := len(s) + if n < 8 { + // A key shorter than a word, as most are, packs into one: from four + // bytes up as two overlapping halves, below that as its first, + // middle and last byte, which cover one to three bytes between them. + // Keys of different lengths can pack alike, "a" and "aa" say, so the + // length goes into the multiplier, where no byte of the key reaches. + var w uint64 + switch { + case n >= 4: + w = uint64(load4(s, 0)) | uint64(load4(s, n-4))<<32 + case n > 0: + w = uint64(s[0]) | uint64(s[n>>1])<<8 | uint64(s[n-1])<<16 + } + return hashFoldMix(swar.ToLowerWord(w)^hashFoldK0, hashFoldK1^uint64(n)<<56) + } + // Longer keys go as wyhash does: sixteen bytes per multiply, then the + // last sixteen, overlapping what came before when fewer are left, and a + // final mix that takes in the length. + h := hashFoldK2 + for i := 0; n-i > 16; i += 16 { + h = hashFoldMix(swar.ToLowerWord(swar.Load8(s, i))^hashFoldK1, swar.ToLowerWord(swar.Load8(s, i+8))^h) + } + hi, lo := bits.Mul64( + swar.ToLowerWord(swar.Load8(s, max(n-16, 0)))^hashFoldK1, + swar.ToLowerWord(swar.Load8(s, n-8))^h, + ) + return hashFoldMix(lo^hashFoldK0^uint64(n), hi^hashFoldK1) +} + +// The constants of HashFold, wyhash's. +const ( + hashFoldK0 uint64 = 0xa0761d6478bd642f + hashFoldK1 uint64 = 0xe7037ed1a0b428db + hashFoldK2 uint64 = 0x8ebc6af09c88c6e3 +) + +// hashFoldMix folds the 128-bit product of a and b into 64 bits, the mixing +// step of the wyhash family: a single widening multiply spreads every bit of +// a and b across the result. +func hashFoldMix(a, b uint64) uint64 { + hi, lo := bits.Mul64(a, b) + return hi ^ lo +} + // TrimLeft removes all leading occurrences of the byte cutset from s. // Unlike strings/bytes.TrimLeft, cutset is a single byte, not a set of characters. func TrimLeft[S byteSeq](s S, cutset byte) S { diff --git a/src/vendor/github.com/gofiber/utils/v2/control.go b/src/vendor/github.com/gofiber/utils/v2/control.go new file mode 100644 index 00000000..ca72bb13 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/control.go @@ -0,0 +1,83 @@ +package utils + +import ( + "github.com/gofiber/utils/v2/swar" +) + +// noControlExemption is never a control lane, so exempting it is a no-op. +const noControlExemption = 0x80 + +// IndexControl returns the index of the first ASCII control byte in s (below +// 0x20 or DEL, the RFC 5234 CTL set), or -1. HTAB counts as a control byte; +// bytes >= 0x80 never match, unlike unicode.IsControl's C1 range. +func IndexControl[S byteSeq](s S) int { + return scanControl(s, noControlExemption) +} + +// IndexControlExceptTab is IndexControl with HTAB permitted: the bytes an +// RFC 9110 field value may not contain. +func IndexControlExceptTab[S byteSeq](s S) int { + return scanControl(s, '\t') +} + +// scanControl is the word scan behind both. Words holding no control byte, +// the common case, skip the exemption test entirely. +func scanControl[S byteSeq](s S, exempt byte) int { + n := len(s) + exemptLanes := swar.Broadcast(exempt) + i := 0 + for ; i+16 <= n; i += 16 { + w := s[i : i+16] + w0, w1 := swar.Load8(w, 0), swar.Load8(w, 8) + m0, m1 := controlLanes(w0), controlLanes(w1) + if m0|m1 != 0 { + if m0 &= otherLanes(w0, exemptLanes); m0 != 0 { + return i + swar.FirstLane(m0) + } + if m1 &= otherLanes(w1, exemptLanes); m1 != 0 { + return i + 8 + swar.FirstLane(m1) + } + } + } + for ; i+8 <= n; i += 8 { + w := swar.Load8(s, i) + if m := controlLanes(w); m != 0 { + if m &= otherLanes(w, exemptLanes); m != 0 { + return i + swar.FirstLane(m) + } + } + } + if i == n { + return -1 + } + if n >= 8 { + w := swar.Load8(s, n-8) + if m := controlLanes(w); m != 0 { + if m &= otherLanes(w, exemptLanes); m != 0 { + return n - 8 + swar.FirstLane(m) + } + } + return -1 + } + for ; i < n; i++ { + if c := s[i]; (c < 0x20 || c == 0x7f) && c != exempt { + return i + } + } + return -1 +} + +// controlLanes flags the lanes of w below 0x20 or equal to DEL, exactly per +// lane; the biased lanes stay below 0xE0, so no carries. +func controlLanes(w uint64) uint64 { + b := w & swar.LowSeven + return (^(b + (0x80-0x20)*swar.Ones) | (b + swar.Ones)) &^ w & swar.HighBits +} + +// otherLanes flags the lanes of w that differ from the byte broadcast in +// lanes, exactly per lane: x is zero only in the equal lanes, and only there +// is the high bit of ((x | HighBits) - Ones) | x clear (swar.MatchByteMask's test). +func otherLanes(w, lanes uint64) uint64 { + x := w ^ lanes + return ((x | swar.HighBits) - swar.Ones) | x +} diff --git a/src/vendor/github.com/gofiber/utils/v2/cut.go b/src/vendor/github.com/gofiber/utils/v2/cut.go new file mode 100644 index 00000000..fa1eab2f --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/cut.go @@ -0,0 +1,25 @@ +package utils + +import ( + "bytes" + + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// CutByte is strings.Cut/bytes.Cut for a single-byte separator, generic over +// strings and byte slices; a miss returns s, the zero S ("" or nil), and +// false. The parts alias s. +func CutByte[S byteSeq](s S, sep byte) (before, after S, found bool) { //nolint:nonamedreturns // the two same-typed parts are only readable named + if i := bytes.IndexByte(unsafeconv.Bytes(s), sep); i >= 0 { + return s[:i], s[i+1:], true + } + return s, after, false +} + +// LastCutByte is CutByte around the last occurrence of sep. +func LastCutByte[S byteSeq](s S, sep byte) (before, after S, found bool) { //nolint:nonamedreturns // the two same-typed parts are only readable named + if i := bytes.LastIndexByte(unsafeconv.Bytes(s), sep); i >= 0 { + return s[:i], s[i+1:], true + } + return s, after, false +} diff --git a/src/vendor/github.com/gofiber/utils/v2/duration.go b/src/vendor/github.com/gofiber/utils/v2/duration.go new file mode 100644 index 00000000..434cd97d --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/duration.go @@ -0,0 +1,121 @@ +package utils + +import ( + "time" +) + +const durationBufLen = 32 // the longest rendering is "-2562047h47m16.854775808s" + +// AppendDuration appends d formatted exactly like time.Duration.String to dst +// and returns the extended slice, without the string allocation. +func AppendDuration(dst []byte, d time.Duration) []byte { + var buf [durationBufLen]byte + w := durationToBuf(&buf, d) + return append(dst, buf[w:]...) +} + +// durationToBuf renders d right-aligned into buf and returns the first offset. +func durationToBuf(buf *[durationBufLen]byte, d time.Duration) int { + w := len(buf) + u := uint64(d) + neg := d < 0 + if neg { + u = -u + } + + w-- + buf[w] = 's' + if u < uint64(time.Second) { + // Sub-second: ns, µs (two UTF-8 bytes), or ms. The unit splits are + // constant divisions, which compile to multiplies. + w-- + switch { + case u == 0: + buf[w] = '0' + return w + case u < uint64(time.Microsecond): + buf[w] = 'n' + case u < uint64(time.Millisecond): + w-- + buf[w] = 0xC2 // "µ" is 0xC2 0xB5 + buf[w+1] = 0xB5 + w = durationFrac(buf, w, u%uint64(time.Microsecond), 3) + u /= uint64(time.Microsecond) + default: + buf[w] = 'm' + w = durationFrac(buf, w, u%uint64(time.Millisecond), 6) + u /= uint64(time.Millisecond) + } + w = durationInt(buf, w, u) + } else { + w = durationFrac(buf, w, u%uint64(time.Second), 9) + u /= uint64(time.Second) + w = durationInt(buf, w, u%60) + u /= 60 + if u > 0 { + w-- + buf[w] = 'm' + w = durationInt(buf, w, u%60) + u /= 60 + if u > 0 { + w-- + buf[w] = 'h' + w = durationInt(buf, w, u) + } + } + } + + if neg { + w-- + buf[w] = '-' + } + return w +} + +// durationFrac writes the prec-digit fraction frac ending at buf[w] without +// its trailing zeros (nothing at all when it is zero, the common case) and +// returns the new offset. +func durationFrac(buf *[durationBufLen]byte, w int, frac uint64, prec int) int { + if frac == 0 { + return w + } + for frac%1000 == 0 { + frac /= 1000 + prec -= 3 + } + for frac%10 == 0 { + frac /= 10 + prec-- + } + for ; prec >= 2; prec -= 2 { + q := frac / 100 + w -= 2 + putPair(buf[:], w, frac-q*100) + frac = q + } + if prec == 1 { + w-- + buf[w] = byte(frac) + '0' + } + w-- + buf[w] = '.' + return w +} + +// durationInt writes the digits of v ending at buf[w] and returns the new offset. +func durationInt(buf *[durationBufLen]byte, w int, v uint64) int { + for v >= 100 { + q := v / 100 + w -= 2 + putPair(buf[:], w, v-q*100) + v = q + } + if v >= 10 { + w -= 2 + putPair(buf[:], w, v) + return w + } + w-- + buf[w] = byte(v) + '0' + return w +} diff --git a/src/vendor/github.com/gofiber/utils/v2/format.go b/src/vendor/github.com/gofiber/utils/v2/format.go index 6c81d14a..fa671283 100644 --- a/src/vendor/github.com/gofiber/utils/v2/format.go +++ b/src/vendor/github.com/gofiber/utils/v2/format.go @@ -1,6 +1,7 @@ package utils import ( + "encoding/binary" "math/bits" ) @@ -51,18 +52,63 @@ func formatUint8Slow(n uint8) string { return string([]byte{n/100 + '0', (n/10)%10 + '0', n%10 + '0'}) } -// formatUintBuf writes the digits of n into buf from the end and returns the start index. -// buf must be at least 20 bytes. -func formatUintBuf(buf *[20]byte, n uint64) int { - i := 20 - for n >= 10 { - i-- - buf[i] = byte(n%10) + '0' - n /= 10 - } - i-- - buf[i] = byte(n) + '0' - return i +// decimalPairs holds "00".."99" back to back: decimalPairs[2*n:2*n+2] is n zero-padded. +const decimalPairs = "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899" + +// Formatting works on 8-digit groups: digits8 turns a value below 1e8 into +// eight zero-padded digit lanes (most significant first) with lane-parallel +// divisions, and leading zeros are zero lanes found by a trailing-zero count. +const ( + digitZeros = 0x3030303030303030 // '0' in every lane; digit lanes are below 16, so OR equals add + digitsBufLen = 24 // three lane groups; 20 digits plus a sign fit + digitsGroup = 100000000 // value of one lane group +) + +// digits8 returns the eight zero-padded digits of n < 1e8 as 0..9 byte lanes. +// Each multiply is a per-lane division by 100 or 10; no step carries across lanes. +func digits8(n uint32) uint64 { + hi := n / 10000 // two 4-digit halves in 32-bit lanes, high half in the low lane + x := uint64(hi) | uint64(n-hi*10000)<<32 + q := (x * 5243 >> 19) & 0x0000007F0000007F // lane/100, exact below 43699 + y := q | (x-q*100)<<16 // lane%100 into the upper 16 bits + q = (y * 103 >> 10) & 0x000F000F000F000F // lane/10, exact below 100 + return q | (y-q*10)<<8 // lane%10 into the upper byte +} + +// uintToBuf writes the digits of n >= 100 right-aligned into buf and returns +// the index of the first digit. +func uintToBuf(buf *[digitsBufLen]byte, n uint64) int { + if n < digitsGroup { + z := digits8(uint32(n)) + binary.LittleEndian.PutUint64(buf[16:24], z|digitZeros) + return 16 + bits.TrailingZeros64(z)>>3 + } + hi := n / digitsGroup + binary.LittleEndian.PutUint64(buf[16:24], digits8(uint32(n-hi*digitsGroup))|digitZeros) + if hi < digitsGroup { + z := digits8(uint32(hi)) + binary.LittleEndian.PutUint64(buf[8:16], z|digitZeros) + return 8 + bits.TrailingZeros64(z)>>3 + } + top := uint32(hi / digitsGroup) // at most 1844 + binary.LittleEndian.PutUint64(buf[8:16], digits8(uint32(hi-uint64(top)*digitsGroup))|digitZeros) + z := digits8(top) + binary.LittleEndian.PutUint64(buf[0:8], z|digitZeros) + return bits.TrailingZeros64(z) >> 3 +} + +// uint32ToBuf is uintToBuf for 32-bit values, which need at most two groups. +func uint32ToBuf(buf *[16]byte, n uint32) int { + if n < digitsGroup { + z := digits8(n) + binary.LittleEndian.PutUint64(buf[8:16], z|digitZeros) + return 8 + bits.TrailingZeros64(z)>>3 + } + hi := n / digitsGroup // at most 42 + binary.LittleEndian.PutUint64(buf[8:16], digits8(n-hi*digitsGroup)|digitZeros) + z := digits8(hi) + binary.LittleEndian.PutUint64(buf[0:8], z|digitZeros) + return bits.TrailingZeros64(z) >> 3 } // FormatUint formats a uint64 as a decimal string. @@ -71,28 +117,25 @@ func FormatUint(n uint64) string { if n < 100 { return smallInts[n] } - var buf [20]byte - i := formatUintBuf(&buf, n) + var buf [digitsBufLen]byte + i := uintToBuf(&buf, n) return string(buf[i:]) } // FormatInt formats an int64 as a decimal string. // It is faster than strconv.FormatInt for most inputs. func FormatInt(n int64) string { - if n >= 0 && n < 100 { - return smallInts[n] + if n >= 0 { + if n < 100 { + return smallInts[n] // inline: a FormatUint call would double the cost + } + return FormatUint(uint64(n)) } - if n < 0 && n > -100 { + if n > -100 { return smallNegInts[-n] } - if n >= 0 { - var buf [20]byte - i := formatUintBuf(&buf, uint64(n)) - return string(buf[i:]) - } - var buf [20]byte - i := formatUintBuf(&buf, uint64(-n)) - i-- + var buf [digitsBufLen]byte + i := uintToBuf(&buf, uint64(-n)) - 1 // uint64(-n) is the magnitude, math.MinInt64 included buf[i] = '-' return string(buf[i:]) } @@ -102,85 +145,36 @@ func FormatUint32(n uint32) string { if n < 100 { return smallInts[n] } - var buf [10]byte // max 4294967295 - i := 10 - for n >= 10 { - i-- - buf[i] = byte(n%10) + '0' - n /= 10 - } - i-- - buf[i] = byte(n) + '0' + var buf [16]byte + i := uint32ToBuf(&buf, n) return string(buf[i:]) } // FormatInt32 formats an int32 as a decimal string. func FormatInt32(n int32) string { - if n >= 0 && n < 100 { - return smallInts[n] - } - if n < 0 && n > -100 { - return smallNegInts[-n] - } if n >= 0 { + if n < 100 { + return smallInts[n] + } return FormatUint32(uint32(n)) } - var buf [11]byte // max -2147483648 - un := uint32(-n) - i := 11 - for un >= 10 { - i-- - buf[i] = byte(un%10) + '0' - un /= 10 - } - i-- - buf[i] = byte(un) + '0' - i-- + if n > -100 { + return smallNegInts[-n] + } + var buf [16]byte + i := uint32ToBuf(&buf, uint32(-n)) - 1 buf[i] = '-' return string(buf[i:]) } // FormatUint16 formats a uint16 as a decimal string. func FormatUint16(n uint16) string { - if n < 100 { - return smallInts[n] - } - var buf [5]byte // max 65535 - i := 5 - for n >= 10 { - i-- - buf[i] = byte(n%10) + '0' - n /= 10 - } - i-- - buf[i] = byte(n) + '0' - return string(buf[i:]) + return FormatUint32(uint32(n)) } // FormatInt16 formats an int16 as a decimal string. func FormatInt16(n int16) string { - if n >= 0 && n < 100 { - return smallInts[n] - } - if n < 0 && n > -100 { - return smallNegInts[-n] - } - if n >= 0 { - return FormatUint16(uint16(n)) - } - var buf [6]byte // max -32768 - un := uint16(-n) - i := 6 - for un >= 10 { - i-- - buf[i] = byte(un%10) + '0' - un /= 10 - } - i-- - buf[i] = byte(un) + '0' - i-- - buf[i] = '-' - return string(buf[i:]) + return FormatInt32(int32(n)) } // FormatUint8 formats a uint8 as a decimal string. @@ -229,22 +223,24 @@ func AppendUint(dst []byte, n uint64) []byte { if n < 100 { return append(dst, smallInts[n]...) } - var buf [20]byte - i := formatUintBuf(&buf, n) + var buf [digitsBufLen]byte + i := uintToBuf(&buf, n) return append(dst, buf[i:]...) } // AppendInt appends the decimal string representation of n to dst. func AppendInt(dst []byte, n int64) []byte { if n >= 0 { + if n < 100 { + return append(dst, smallInts[n]...) + } return AppendUint(dst, uint64(n)) } if n > -100 { return append(dst, smallNegInts[-n]...) } - var buf [20]byte - i := formatUintBuf(&buf, uint64(-n)) - i-- + var buf [digitsBufLen]byte + i := uintToBuf(&buf, uint64(-n)) - 1 buf[i] = '-' return append(dst, buf[i:]...) } diff --git a/src/vendor/github.com/gofiber/utils/v2/headerkey.go b/src/vendor/github.com/gofiber/utils/v2/headerkey.go new file mode 100644 index 00000000..971e0d9f --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/headerkey.go @@ -0,0 +1,71 @@ +package utils + +import ( + "github.com/gofiber/utils/v2/internal/caseconv" + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// headerTokenTable flags the bytes valid in an HTTP header field name — the +// RFC 9110 token alphabet, matching net/http's validHeaderFieldByte. +var headerTokenTable = buildHeaderTokenTable() + +func buildHeaderTokenTable() [256]bool { + var t [256]bool + for c := byte('0'); c <= '9'; c++ { + t[c] = true + } + for c := byte('a'); c <= 'z'; c++ { + t[c] = true + } + for c := byte('A'); c <= 'Z'; c++ { + t[c] = true + } + for _, c := range []byte("!#$%&'*+-.^_`|~") { + t[c] = true + } + return t +} + +// CanonicalHeaderKey returns the canonical form of the HTTP header key: +// the first letter and any letter following a hyphen upper-cased, the rest +// lower-cased. The output matches net/http.CanonicalHeaderKey byte for +// byte, including its guard: a key containing any byte outside the header +// token alphabet is returned unchanged. Unlike the stdlib it accepts byte +// slices as well as strings and allocates only when the key actually needs +// rewriting — already-canonical keys, the overwhelmingly common case on +// receive paths, are validated in one table pass and returned as-is +// without the stdlib's canonical-key cache lookup. +func CanonicalHeaderKey[S byteSeq](key S) S { + upper := true + fix := -1 + for i := 0; i < len(key); i++ { + c := key[i] + if !headerTokenTable[c] { + return key + } + if fix < 0 && (upper && 'a' <= c && c <= 'z' || !upper && 'A' <= c && c <= 'Z') { + fix = i + } + upper = c == '-' + } + if fix < 0 { + return key + } + + buf := make([]byte, len(key)) + copy(buf, unsafeconv.Bytes(key)) + upper = fix == 0 || buf[fix-1] == '-' + for i := fix; i < len(buf); i++ { + c := buf[i] + if upper { + c = caseconv.ToUpperTable[c] + } else { + c = caseconv.ToLowerTable[c] + } + buf[i] = c + upper = c == '-' + } + // The zero-copy view is sound: buf is uniquely owned here and is never + // written again, which is what the string instantiation requires. + return unsafeconv.Seq[S](buf) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/hostport.go b/src/vendor/github.com/gofiber/utils/v2/hostport.go new file mode 100644 index 00000000..964191b7 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/hostport.go @@ -0,0 +1,35 @@ +package utils + +import ( + "bytes" + + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// SplitHostPort splits "host:port", "[host]:port", and their %zone forms +// with net.SplitHostPort's exact rules, reporting failure as ok == false +// instead of a *net.AddrError; it accepts byte slices as well as strings, +// and the parts alias hostport. +func SplitHostPort[S byteSeq](hostport S) (host, port S, ok bool) { //nolint:nonamedreturns // the two same-typed parts are only readable named + b := unsafeconv.Bytes(hostport) + // The port starts after the last colon. + i := bytes.LastIndexByte(b, ':') + if i < 0 { + return host, port, false + } + j, k, hostEnd := 0, 0, i + if hostport[0] == '[' { + // Expect the first ']' just before the last ':'. + end := bytes.IndexByte(b, ']') + if end < 0 || end+1 != i { + return host, port, false + } + j, k, hostEnd = 1, end+1, end // there can't be a '[' resp. ']' before these positions + } else if bytes.IndexByte(b[:i], ':') >= 0 { + return host, port, false + } + if bytes.IndexByte(b[j:], '[') >= 0 || bytes.IndexByte(b[k:], ']') >= 0 { + return host, port, false + } + return hostport[j:hostEnd], hostport[i+1:], true +} diff --git a/src/vendor/github.com/gofiber/utils/v2/http.go b/src/vendor/github.com/gofiber/utils/v2/http.go index 99e762bd..08f96ece 100644 --- a/src/vendor/github.com/gofiber/utils/v2/http.go +++ b/src/vendor/github.com/gofiber/utils/v2/http.go @@ -9,6 +9,7 @@ import ( "strings" casestrings "github.com/gofiber/utils/v2/strings" + "github.com/gofiber/utils/v2/swar" ) const MIMEOctetStream = "application/octet-stream" @@ -19,31 +20,79 @@ const ( contentTypePrefixApplicationWithSlash = "application/" ) -// GetMIME returns the content-type of a file extension +// Extensions are looked up in an open-addressed table keyed by the extension +// packed into one lower-cased word and built from mimeExtensions at init: a +// hit is a multiply, a shift, and usually one comparison, with no allocation. +const ( + mimeTableBits = 9 // 512 slots for ~130 entries + mimeTableMask = 1< mimeTableMaxEntries { + panic("utils: the MIME extension table holds at most " + FormatInt(mimeTableMaxEntries) + " entries; raise mimeTableBits") + } + var t [1 << mimeTableBits]mimeEntry + for ext, mimeType := range exts { + if ext == "" || len(ext) > mimeKeyMaxLen { + panic("utils: MIME extension \"" + ext + "\" must be 1.." + FormatInt(mimeKeyMaxLen) + " bytes to fit a packed key") + } + key := packExtension(ext) + h := mimeHash(key) + for t[h].mimeType != "" { + h = (h + 1) & mimeTableMask + } + t[h] = mimeEntry{key: key, mimeType: mimeType} + } + return t +} + +// packExtension packs 1..mimeKeyMaxLen bytes lower-cased into a little-endian +// word with the length in the top lane, so "html\x00" and "html" differ. +func packExtension(ext string) uint64 { + return foldNeedle(ext) | uint64(len(ext))<<(8*mimeKeyMaxLen) +} + +func mimeHash(key uint64) int { + return int(key * mimeHashMul >> (64 - mimeTableBits)) +} + +// GetMIME returns the content-type of a file extension, matched +// case-insensitively with or without the leading dot. Unknown extensions map +// to MIMEOctetStream; an empty extension yields an empty string. func GetMIME(extension string) string { if len(extension) == 0 { return "" } - // Normalize extension once at the start to avoid repeated checks - var extWithoutDot string - var extWithDot string - if extension[0] == '.' { - extWithoutDot = extension[1:] - extWithDot = extension - } else { - extWithoutDot = extension - extWithDot = "." + extension + ext := extension + if ext[0] == '.' { + ext = ext[1:] } - - // Single map lookup with normalized key. Extensions are matched - // case-insensitively; ToLower only allocates for upper-case input. - if foundMime := mimeExtensions[casestrings.ToLower(extWithoutDot)]; len(foundMime) > 0 { - return foundMime + if len(ext) > 0 && len(ext) <= mimeKeyMaxLen { + key := packExtension(ext) + for h := mimeHash(key); mimeTable[h].mimeType != ""; h = (h + 1) & mimeTableMask { + if mimeTable[h].key == key { + return mimeTable[h].mimeType + } + } } - // Fallback to mime package with pre-computed extension - if foundMime := mime.TypeByExtension(extWithDot); foundMime != "" { + // Fallback to the mime package, which wants the dotted form. + if extension[0] != '.' { + extension = "." + extension + } + if foundMime := mime.TypeByExtension(extension); foundMime != "" { return foundMime } diff --git a/src/vendor/github.com/gofiber/utils/v2/httpdate.go b/src/vendor/github.com/gofiber/utils/v2/httpdate.go new file mode 100644 index 00000000..50b08390 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/httpdate.go @@ -0,0 +1,283 @@ +package utils + +import ( + "time" +) + +// httpDateLayout is the RFC 9110 preferred date format (net/http.TimeFormat), +// a fixed-width 29-byte layout that doubles as the formatting template: every +// separator byte is already in place, so AppendHTTPDate only overwrites the +// fields. +const ( + httpDateLayout = "Mon, 02 Jan 2006 15:04:05 GMT" + httpDateLen = len(httpDateLayout) +) + +var ( + httpWeekdays = [7]string{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"} + httpMonths = [12]string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} + + // httpDaysInMonth is indexed by time.Month; February is adjusted for + // leap years in daysInHTTPMonth. + httpDaysInMonth = [13]int{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +) + +// Calendar fields are converted with Hinnant's civil_from_days and +// days_from_civil (400-year eras of 146097 days, origin -0400-03-01 so every +// intermediate is non-negative); the tests sweep every day of 0..9999. +const ( + httpDateMinUnix = -62167219200 // 0000-01-01T00:00:00Z + httpDateMaxUnix = 253402300799 // 9999-12-31T23:59:59Z + secondsPerDay = 86400 + daysPerEra = 146097 + eraDaysToMarch = daysPerEra - 60 // 0000-01-01 to -0400-03-01 + daysFromMarchEraToUnix = 719468 + daysPerEra // -0400-03-01 to 1970-01-01 + weekdayOfYearZero = 6 // 0000-01-01 was a Saturday +) + +// civilFromDays converts days since 0000-01-01 (at most 3652424) into a +// proleptic Gregorian year, month (1..12), and day (1..31). +func civilFromDays(days uint64) (year, month, day uint64) { //nolint:nonamedreturns // the three calendar fields are only readable named + z := days + eraDaysToMarch + era := z / daysPerEra + doe := z - era*daysPerEra // day of era, [0, 146096] + yoe := (doe - doe/1460 + doe/36524 - doe/146096) / 365 // year of era, [0, 399] + doy := doe - (365*yoe + yoe/4 - yoe/100) // day of March-based year, [0, 365] + mp := (5*doy + 2) / 153 // March-based month, [0, 11] + day = doy - (153*mp+2)/5 + 1 + month = mp + 3 + if mp >= 10 { + month = mp - 9 + } + year = yoe + era*400 - 400 + if month <= 2 { + year++ + } + return year, month, day +} + +// unixFromCivil returns the Unix time of valid UTC calendar fields with the +// year in 0..9999, as parseRFC1123 guarantees. +func unixFromCivil(year, month, day, hour, minute, sec int) int64 { + y := year + 400 // one era back keeps January/February of year 0 non-negative + mp := month + 9 + if month > 2 { + mp = month - 3 + } else { + y-- + } + era := y / 400 + yoe := y - era*400 + doy := (153*mp+2)/5 + day - 1 + doe := yoe*365 + yoe/4 - yoe/100 + doy + days := era*daysPerEra + doe - daysFromMarchEraToUnix + return int64(days)*secondsPerDay + int64(hour*3600+minute*60+sec) +} + +// putPair writes n < 100 as two zero-padded digits at b[i] and b[i+1]. +func putPair(b []byte, i int, n uint64) { + _ = b[i+1] + b[i] = decimalPairs[2*n] + b[i+1] = decimalPairs[2*n+1] +} + +// AppendHTTPDate appends t in the RFC 9110 preferred HTTP date format +// ("Mon, 02 Jan 2006 15:04:05 GMT", net/http.TimeFormat) to dst and returns +// the extended slice. The output is byte-identical to +// t.UTC().AppendFormat(dst, http.TimeFormat) and always 29 bytes for the +// years 0..9999 that HTTP dates can represent; times outside that range +// delegate to time.AppendFormat. +func AppendHTTPDate(dst []byte, t time.Time) []byte { + sec := t.Unix() + if sec < httpDateMinUnix || sec > httpDateMaxUnix { + // RFC 1123 assumes a four-digit year; keep stdlib behavior for the + // unrepresentable rest instead of mis-padding it. + return t.UTC().AppendFormat(dst, httpDateLayout) + } + u := uint64(sec - httpDateMinUnix) // seconds since 0000-01-01, so every split is unsigned + days := u / secondsPerDay + sod := u - days*secondsPerDay + hour := sod / 3600 + sod -= hour * 3600 + minute := sod / 60 + second := sod - minute*60 + year, month, day := civilFromDays(days) + + var b [httpDateLen]byte + copy(b[:], httpDateLayout) + weekday := httpWeekdays[(days+weekdayOfYearZero)%7] // byte stores: copy would be a memmove call + b[0], b[1], b[2] = weekday[0], weekday[1], weekday[2] + putPair(b[:], 5, day) + monthName := httpMonths[month-1] + b[8], b[9], b[10] = monthName[0], monthName[1], monthName[2] + century := year / 100 + putPair(b[:], 12, century) + putPair(b[:], 14, year-century*100) + putPair(b[:], 17, hour) + putPair(b[:], 20, minute) + putPair(b[:], 23, second) + return append(dst, b[:]...) +} + +// FormatHTTPDate returns t in the RFC 9110 preferred HTTP date format, equal +// to t.UTC().Format(http.TimeFormat) with a single allocation for the result. +func FormatHTTPDate(t time.Time) string { + var buf [httpDateLen]byte + return string(AppendHTTPDate(buf[:0], t)) +} + +// ParseHTTPDate parses an HTTP date the way net/http.ParseTime does: +// the RFC 9110 preferred format ("Mon, 02 Jan 2006 15:04:05 GMT") plus the +// obsolete RFC 850 and ANSI C asctime forms, with surrounding ASCII +// whitespace tolerated. Canonical preferred-format input takes a fast scalar +// path that never calls time.Parse; every other input — legacy formats, +// unusual casing, non-GMT zone names, padding — falls back to time.Parse +// with byte-for-byte stdlib semantics, including its errors. The returned +// time is in time.UTC on the fast path and whatever time.Parse yields on the +// fallback; the instants agree in both cases. +func ParseHTTPDate[S byteSeq](s S) (time.Time, error) { + if t, ok := parseRFC1123(s); ok { + return t, nil + } + return parseHTTPDateSlow(string(s)) +} + +// parseRFC1123 is the strict fast path for canonical +// "Mon, 02 Jan 2006 15:04:05 GMT" input: exact length, exact separators, +// exact-case names. It reports ok=false for anything else — including +// out-of-range fields — so the slow path can produce stdlib-identical +// results and errors for the long tail. +func parseRFC1123[S byteSeq](s S) (time.Time, bool) { + if len(s) != httpDateLen { + return time.Time{}, false + } + if s[3] != ',' || s[4] != ' ' || s[7] != ' ' || s[11] != ' ' || s[16] != ' ' || + s[19] != ':' || s[22] != ':' || s[25] != ' ' || + s[26] != 'G' || s[27] != 'M' || s[28] != 'T' { + return time.Time{}, false + } + if !isHTTPWeekday(pack3(s[0], s[1], s[2])) { + return time.Time{}, false + } + month := httpMonthNum(pack3(s[8], s[9], s[10])) + if month == 0 { + return time.Time{}, false + } + day, okDay := twoDigits(s[5], s[6]) + yh, okYh := twoDigits(s[12], s[13]) + yl, okYl := twoDigits(s[14], s[15]) + hour, okHour := twoDigits(s[17], s[18]) + minute, okMin := twoDigits(s[20], s[21]) + sec, okSec := twoDigits(s[23], s[24]) + if !okDay || !okYh || !okYl || !okHour || !okMin || !okSec { + return time.Time{}, false + } + year := yh*100 + yl + if hour > 23 || minute > 59 || sec > 59 || + day < 1 || day > daysInHTTPMonth(month, year) { + // time.Parse rejects these; let it produce the exact error. + return time.Time{}, false + } + return time.Unix(unixFromCivil(year, month, day, hour, minute, sec), 0).UTC(), true +} + +// parseHTTPDateSlow mirrors net/http.ParseTime: trim the whitespace +// textproto would, then try the three allowed layouts in order, returning +// the last error when none matches. +func parseHTTPDateSlow(s string) (time.Time, error) { + start, end := 0, len(s) + for start < end && isHTTPDateSpace(s[start]) { + start++ + } + for start < end && isHTTPDateSpace(s[end-1]) { + end-- + } + s = s[start:end] + t, err := time.Parse(httpDateLayout, s) + if err == nil { + return t, nil + } + if t, err850 := time.Parse(time.RFC850, s); err850 == nil { + return t, nil + } + t, errANSIC := time.Parse(time.ANSIC, s) + if errANSIC == nil { + return t, nil + } + return time.Time{}, errANSIC +} + +// isHTTPDateSpace matches textproto.TrimString's notion of whitespace. +func isHTTPDateSpace(c byte) bool { + return c == ' ' || c == '\t' || c == '\r' || c == '\n' +} + +// pack3 packs three bytes for the name switches below. +func pack3(a, b, c byte) uint32 { + return uint32(a)<<16 | uint32(b)<<8 | uint32(c) +} + +// isHTTPWeekday reports whether w is one of the seven exact-case short +// weekday names. Like time.Parse, callers do not check the name against the +// date; any valid name is accepted. +func isHTTPWeekday(w uint32) bool { + switch w { + case 'S'<<16 | 'u'<<8 | 'n', 'M'<<16 | 'o'<<8 | 'n', 'T'<<16 | 'u'<<8 | 'e', + 'W'<<16 | 'e'<<8 | 'd', 'T'<<16 | 'h'<<8 | 'u', 'F'<<16 | 'r'<<8 | 'i', + 'S'<<16 | 'a'<<8 | 't': + return true + } + return false +} + +// httpMonthNum maps an exact-case short month name to 1..12, or 0 if w is +// not one. +func httpMonthNum(w uint32) int { + switch w { + case 'J'<<16 | 'a'<<8 | 'n': + return 1 + case 'F'<<16 | 'e'<<8 | 'b': + return 2 + case 'M'<<16 | 'a'<<8 | 'r': + return 3 + case 'A'<<16 | 'p'<<8 | 'r': + return 4 + case 'M'<<16 | 'a'<<8 | 'y': + return 5 + case 'J'<<16 | 'u'<<8 | 'n': + return 6 + case 'J'<<16 | 'u'<<8 | 'l': + return 7 + case 'A'<<16 | 'u'<<8 | 'g': + return 8 + case 'S'<<16 | 'e'<<8 | 'p': + return 9 + case 'O'<<16 | 'c'<<8 | 't': + return 10 + case 'N'<<16 | 'o'<<8 | 'v': + return 11 + case 'D'<<16 | 'e'<<8 | 'c': + return 12 + } + return 0 +} + +// twoDigits parses two ASCII digits into an int, reporting whether both +// bytes were digits. +func twoDigits(a, b byte) (int, bool) { + a -= '0' + b -= '0' + if a > 9 || b > 9 { + return 0, false + } + return int(a)*10 + int(b), true +} + +// daysInHTTPMonth returns the number of days in month for year, using the +// same leap-year rule as the time package. +func daysInHTTPMonth(month, year int) int { + if month == 2 && year%4 == 0 && (year%100 != 0 || year%400 == 0) { + return 29 + } + return httpDaysInMonth[month] +} diff --git a/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go b/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go index 5bbf3a84..06d1736a 100644 --- a/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go +++ b/src/vendor/github.com/gofiber/utils/v2/internal/caseconv/swar.go @@ -16,13 +16,84 @@ import ( // word loops here (benchstat -count=10, Go 1.25, Apple M2 Pro). The lane // order is identical, so swar words and binary.LittleEndian loads/stores // can be mixed freely. +// +// The word loops pin each group of four words with a three-index reslice +// and address the words at constant offsets inside it. A two-index +// reslice at a variable offset costs a capacity check plus the +// four-instruction pointer clamp the compiler emits when the new +// capacity is not a known nonzero constant; the pinned form pays one +// check per group and no clamp, and the constant-offset accesses inside +// it are check-free. See swar.Load8 for the same note. -// WordLen is the SWAR word width in bytes, re-exported for the case -// conversion callers in the strings and bytes packages: they route inputs -// shorter than WordLen to byte-wise paths and align offsets they pass (such -// as ToLowerCopy's from) with WordLen-derived masks. +// WordLen is the SWAR word width in bytes, and the length from which these +// helpers are worth a call: below it the conversion is a table lookup per byte, +// cheaper inline. The case packages gate on it; the From converters require it. const WordLen = swar.WordLen +// ToLowerFrom returns a lower-cased copy of src. first must be FirstUpperIndex's +// own result, with 0 <= first < len(src) and len(src) >= WordLen: a larger first +// silently mis-converts, so it must not be cached or derived elsewhere. +// +// src is only read, so it may be an unsafe view over immutable string memory; +// the result is freshly allocated and unaliased. strings.ToLower needs both. +func ToLowerFrom(src []byte, first int) []byte { + n := len(src) + dst := make([]byte, n) + + // Copy verbatim up to the word holding first, then convert from there. + i := first &^ (WordLen - 1) + copy(dst, src[:i]) + + for ; i+4*WordLen <= n; i += 4 * WordLen { + sw := src[i : i+4*WordLen : i+4*WordLen] + d := dst[i : i+4*WordLen : i+4*WordLen] + binary.LittleEndian.PutUint64(d[0:WordLen], swar.ToLowerWord(binary.LittleEndian.Uint64(sw[0:WordLen]))) + binary.LittleEndian.PutUint64(d[WordLen:2*WordLen], swar.ToLowerWord(binary.LittleEndian.Uint64(sw[WordLen:2*WordLen]))) + binary.LittleEndian.PutUint64(d[2*WordLen:3*WordLen], swar.ToLowerWord(binary.LittleEndian.Uint64(sw[2*WordLen:3*WordLen]))) + binary.LittleEndian.PutUint64(d[3*WordLen:4*WordLen], swar.ToLowerWord(binary.LittleEndian.Uint64(sw[3*WordLen:4*WordLen]))) + } + for ; i+WordLen <= n; i += WordLen { + binary.LittleEndian.PutUint64(dst[i:i+WordLen:i+WordLen], swar.ToLowerWord(binary.LittleEndian.Uint64(src[i:i+WordLen:i+WordLen]))) + } + if i == n { + return dst + } + // One overlapping word finishes the tail. It re-reads src, so above the + // aligned start it recomputes what the loops wrote, and below it folds over + // the verbatim prefix -- harmless only because every byte under first is + // unchanged by the fold, which is what makes first's upper bound matter. + binary.LittleEndian.PutUint64(dst[n-WordLen:n:n], swar.ToLowerWord(binary.LittleEndian.Uint64(src[n-WordLen:n:n]))) + return dst +} + +// ToUpperFrom mirrors ToLowerFrom, with first from FirstLowerIndex. +func ToUpperFrom(src []byte, first int) []byte { + n := len(src) + dst := make([]byte, n) + + // Copy verbatim up to the word holding first, then convert from there. + i := first &^ (WordLen - 1) + copy(dst, src[:i]) + + for ; i+4*WordLen <= n; i += 4 * WordLen { + sw := src[i : i+4*WordLen : i+4*WordLen] + d := dst[i : i+4*WordLen : i+4*WordLen] + binary.LittleEndian.PutUint64(d[0:WordLen], swar.ToUpperWord(binary.LittleEndian.Uint64(sw[0:WordLen]))) + binary.LittleEndian.PutUint64(d[WordLen:2*WordLen], swar.ToUpperWord(binary.LittleEndian.Uint64(sw[WordLen:2*WordLen]))) + binary.LittleEndian.PutUint64(d[2*WordLen:3*WordLen], swar.ToUpperWord(binary.LittleEndian.Uint64(sw[2*WordLen:3*WordLen]))) + binary.LittleEndian.PutUint64(d[3*WordLen:4*WordLen], swar.ToUpperWord(binary.LittleEndian.Uint64(sw[3*WordLen:4*WordLen]))) + } + for ; i+WordLen <= n; i += WordLen { + binary.LittleEndian.PutUint64(dst[i:i+WordLen:i+WordLen], swar.ToUpperWord(binary.LittleEndian.Uint64(src[i:i+WordLen:i+WordLen]))) + } + if i == n { + return dst + } + // See ToLowerFrom for why the overlapping store is harmless. + binary.LittleEndian.PutUint64(dst[n-WordLen:n:n], swar.ToUpperWord(binary.LittleEndian.Uint64(src[n-WordLen:n:n]))) + return dst +} + // FirstUpperIndex returns the index of the first ASCII uppercase byte in b, // or -1 if b contains none. b is only ever read; it may be an unsafe view // over immutable string memory. @@ -42,10 +113,11 @@ func FirstUpperIndex(b []byte) int { // fold; only the cold hit-resolution ladder is shared, and it // inlines (the no-match loop never reaches it). for i = 8; i+32 <= n; i += 32 { - m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'A', 'Z') - m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'A', 'Z') - m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'A', 'Z') - m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'A', 'Z') + w := b[i : i+32 : i+32] + m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[0:8]), 'A', 'Z') + m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[8:16]), 'A', 'Z') + m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[16:24]), 'A', 'Z') + m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[24:32]), 'A', 'Z') if m0|m1|m2|m3 != 0 { return firstSetLane32(i, m0, m1, m2, m3) } @@ -57,10 +129,11 @@ func FirstUpperIndex(b []byte) int { // per-lane exact, so re-scanned lanes are known non-matching and the // first set lane always falls in the new bytes. i = n - 32 - m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'A', 'Z') - m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'A', 'Z') - m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'A', 'Z') - m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'A', 'Z') + w := b[i : i+32 : i+32] + m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[0:8]), 'A', 'Z') + m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[8:16]), 'A', 'Z') + m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[16:24]), 'A', 'Z') + m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[24:32]), 'A', 'Z') if m0|m1|m2|m3 != 0 { return firstSetLane32(i, m0, m1, m2, m3) } @@ -90,9 +163,6 @@ func FirstUpperIndex(b []byte) int { return -1 } -// FirstLowerIndex returns the index of the first ASCII lowercase byte in b, -// or -1 if b contains none. b is only ever read; it may be an unsafe view -// over immutable string memory. // firstSetLane32 resolves a hit inside a 32-byte block: given the block's // four per-word masks, it returns the index of the first marked byte // relative to base, the block's starting offset. It runs at most once per @@ -111,6 +181,9 @@ func firstSetLane32(base int, m0, m1, m2, m3 uint64) int { return base + 24 + swar.FirstLane(m3) } +// FirstLowerIndex returns the index of the first ASCII lowercase byte in b, +// or -1 if b contains none. b is only ever read; it may be an unsafe view +// over immutable string memory. func FirstLowerIndex(b []byte) int { n := len(b) i := 0 @@ -120,10 +193,11 @@ func FirstLowerIndex(b []byte) int { return swar.FirstLane(m) } for i = 8; i+32 <= n; i += 32 { - m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'a', 'z') - m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'a', 'z') - m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'a', 'z') - m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'a', 'z') + w := b[i : i+32 : i+32] + m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[0:8]), 'a', 'z') + m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[8:16]), 'a', 'z') + m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[16:24]), 'a', 'z') + m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[24:32]), 'a', 'z') if m0|m1|m2|m3 != 0 { return firstSetLane32(i, m0, m1, m2, m3) } @@ -132,10 +206,11 @@ func FirstLowerIndex(b []byte) int { return -1 } i = n - 32 - m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i:i+8]), 'a', 'z') - m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+8:i+16]), 'a', 'z') - m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+16:i+24]), 'a', 'z') - m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(b[i+24:i+32]), 'a', 'z') + w := b[i : i+32 : i+32] + m0 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[0:8]), 'a', 'z') + m1 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[8:16]), 'a', 'z') + m2 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[16:24]), 'a', 'z') + m3 := swar.MatchRangeMask(binary.LittleEndian.Uint64(w[24:32]), 'a', 'z') if m0|m1|m2|m3 != 0 { return firstSetLane32(i, m0, m1, m2, m3) } @@ -163,12 +238,21 @@ func FirstLowerIndex(b []byte) int { return -1 } -// ToLowerInPlace lower-cases every ASCII uppercase byte of b in place. +// ToLowerInPlace lower-cases every ASCII uppercase byte of b in place: +// four words per pinned group, then single words, then bytes. func ToLowerInPlace(b []byte) { n := len(b) i := 0 + for ; i+32 <= n; i += 32 { + w := b[i : i+32 : i+32] + binary.LittleEndian.PutUint64(w[0:8], swar.ToLowerWord(binary.LittleEndian.Uint64(w[0:8]))) + binary.LittleEndian.PutUint64(w[8:16], swar.ToLowerWord(binary.LittleEndian.Uint64(w[8:16]))) + binary.LittleEndian.PutUint64(w[16:24], swar.ToLowerWord(binary.LittleEndian.Uint64(w[16:24]))) + binary.LittleEndian.PutUint64(w[24:32], swar.ToLowerWord(binary.LittleEndian.Uint64(w[24:32]))) + } for ; i+8 <= n; i += 8 { - binary.LittleEndian.PutUint64(b[i:i+8], swar.ToLowerWord(binary.LittleEndian.Uint64(b[i:i+8]))) + w := b[i : i+8 : i+8] + binary.LittleEndian.PutUint64(w, swar.ToLowerWord(binary.LittleEndian.Uint64(w))) } // Finish byte-wise: an overlapping word here would partially overlap the // previous 8-byte store and stall on store-to-load forwarding. @@ -177,70 +261,23 @@ func ToLowerInPlace(b []byte) { } } -// ToUpperInPlace upper-cases every ASCII lowercase byte of b in place. +// ToUpperInPlace upper-cases every ASCII lowercase byte of b in place; the +// loop shape mirrors ToLowerInPlace. func ToUpperInPlace(b []byte) { n := len(b) i := 0 - for ; i+8 <= n; i += 8 { - binary.LittleEndian.PutUint64(b[i:i+8], swar.ToUpperWord(binary.LittleEndian.Uint64(b[i:i+8]))) - } - for ; i < n; i++ { - b[i] = ToUpperTable[b[i]] - } -} - -// ToLowerCopy writes the lower-cased content of src into dst starting at -// byte offset from. Bytes before from must already be present in dst, and -// len(dst) must equal len(src). src is only ever read — the strings package -// passes an unsafe view over a string's immutable backing memory — so no -// code path here may write through src. -// -// from must be a multiple of WordLen and at or below the index of the first -// byte that lower-casing changes: when len(src) >= WordLen the overlapping -// tail store rewrites dst[n-WordLen:from) with case-converted bytes, which is -// only a no-op under that precondition. -// -// Callers currently invoke this only with len(src) >= WordLen; the byte-wise -// tail below keeps the helper correct standalone for shorter inputs. -func ToLowerCopy(dst, src []byte, from int) { - n := len(src) - i := from - for ; i+8 <= n; i += 8 { - binary.LittleEndian.PutUint64(dst[i:i+8], swar.ToLowerWord(binary.LittleEndian.Uint64(src[i:i+8]))) - } - if i == n { - return + for ; i+32 <= n; i += 32 { + w := b[i : i+32 : i+32] + binary.LittleEndian.PutUint64(w[0:8], swar.ToUpperWord(binary.LittleEndian.Uint64(w[0:8]))) + binary.LittleEndian.PutUint64(w[8:16], swar.ToUpperWord(binary.LittleEndian.Uint64(w[8:16]))) + binary.LittleEndian.PutUint64(w[16:24], swar.ToUpperWord(binary.LittleEndian.Uint64(w[16:24]))) + binary.LittleEndian.PutUint64(w[24:32], swar.ToUpperWord(binary.LittleEndian.Uint64(w[24:32]))) } - if n >= 8 { - binary.LittleEndian.PutUint64(dst[n-8:n], swar.ToLowerWord(binary.LittleEndian.Uint64(src[n-8:n]))) - return - } - for ; i < n; i++ { - dst[i] = ToLowerTable[src[i]] - } -} - -// ToUpperCopy writes the upper-cased content of src into dst starting at -// byte offset from. Bytes before from must already be present in dst, and -// len(dst) must equal len(src). -// -// from must be a multiple of WordLen and at or below the index of the first -// byte that upper-casing changes; see ToLowerCopy for why, including the -// note on the byte-wise tail and the requirement that src is never written. -func ToUpperCopy(dst, src []byte, from int) { - n := len(src) - i := from for ; i+8 <= n; i += 8 { - binary.LittleEndian.PutUint64(dst[i:i+8], swar.ToUpperWord(binary.LittleEndian.Uint64(src[i:i+8]))) - } - if i == n { - return - } - if n >= 8 { - binary.LittleEndian.PutUint64(dst[n-8:n], swar.ToUpperWord(binary.LittleEndian.Uint64(src[n-8:n]))) - return + w := b[i : i+8 : i+8] + binary.LittleEndian.PutUint64(w, swar.ToUpperWord(binary.LittleEndian.Uint64(w))) } for ; i < n; i++ { - dst[i] = ToUpperTable[src[i]] + b[i] = ToUpperTable[b[i]] } } diff --git a/src/vendor/github.com/gofiber/utils/v2/internal/unsafeconv/unsafeconv.go b/src/vendor/github.com/gofiber/utils/v2/internal/unsafeconv/unsafeconv.go index a7510df5..0927938b 100644 --- a/src/vendor/github.com/gofiber/utils/v2/internal/unsafeconv/unsafeconv.go +++ b/src/vendor/github.com/gofiber/utils/v2/internal/unsafeconv/unsafeconv.go @@ -13,3 +13,25 @@ func UnsafeBytes(s string) []byte { // #nosec G103 return unsafe.Slice(unsafe.StringData(s), len(s)) } + +// Bytes returns a []byte view of s without allocation for any string- or +// byte-slice-backed type. It relies on string and slice headers both +// starting with the data pointer (guaranteed by the gc runtime layout, and +// the same assumption UnsafeString makes). When S's underlying type is +// string, the result aliases immutable memory and must only be read. +func Bytes[S ~string | ~[]byte](s S) []byte { + // #nosec G103 + return unsafe.Slice(*(**byte)(unsafe.Pointer(&s)), len(s)) +} + +// Seq is Bytes' inverse: it returns b viewed as S without allocation, for +// either instantiation. It relies on the string header being a prefix of +// the slice header (data pointer, then length), so reinterpreting a slice +// header yields a valid string view; the []byte instantiation reads the +// full header back unchanged. The caller must guarantee b is never written +// again when S's underlying type is string, since the result would alias +// memory the runtime assumes immutable. +func Seq[S ~string | ~[]byte](b []byte) S { + // #nosec G103 + return *(*S)(unsafe.Pointer(&b)) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/ipparse.go b/src/vendor/github.com/gofiber/utils/v2/ipparse.go new file mode 100644 index 00000000..1fa4ae10 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/ipparse.go @@ -0,0 +1,177 @@ +package utils + +import ( + "bytes" + "encoding/binary" + "net/netip" + + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// ParseIPv4 parses a dotted-decimal IPv4 address into a netip.Addr. It +// accepts exactly the IPv4 strings netip.ParseAddr does — four octets 0-255, +// no leading zeros, nothing before or after — and reports ok=false for +// everything else, including IPv6 forms. It never allocates, so []byte +// callers skip both the string conversion and netip's error construction. +// +// IsIPv4 is the validate-only counterpart; it accepts the same strings. +func ParseIPv4[S byteSeq](s S) (netip.Addr, bool) { + var b [4]byte + n := len(s) + i := 0 + for oct := range 4 { + if oct > 0 { + if i >= n || s[i] != '.' { + return netip.Addr{}, false + } + i++ + } + if i >= n { + return netip.Addr{}, false + } + c := s[i] - '0' + if c > 9 { + return netip.Addr{}, false + } + v := uint32(c) + i++ + digits := 1 + for i < n && digits < 3 { + c = s[i] - '0' + if c > 9 { + break + } + v = v*10 + uint32(c) + i++ + digits++ + } + // Reject values above 255 and, like netip, leading zeros. + if v > 255 || (digits > 1 && s[i-digits] == '0') { + return netip.Addr{}, false + } + b[oct] = byte(v) + } + if i != n { + return netip.Addr{}, false + } + return netip.AddrFrom4(b), true +} + +// ParseIPv6 parses an IPv6 address into a netip.Addr. It accepts exactly +// the IPv6 strings netip.ParseAddr does — 16-bit hex fields, one optional +// "::", an optional embedded dotted-decimal IPv4 tail, and an optional +// non-empty "%zone" suffix — and reports ok=false for everything else, +// including plain IPv4 forms (use ParseIPv4 for those). The parse itself +// never allocates; only a present zone is materialized as a string because +// netip.Addr stores zones as strings. +// +// IsIPv6 is the validate-only counterpart, but it follows net.ParseIP, which +// rejects zones. The two therefore disagree on zoned input by design: prefer +// ParseIPv6 when a zone is acceptable, IsIPv6 when it is not. +func ParseIPv6[S byteSeq](s S) (netip.Addr, bool) { + n := len(s) + zone := bytes.IndexByte(unsafeconv.Bytes(s), '%') + end := n + if zone >= 0 { + if zone == n-1 { + // Empty zone. + return netip.Addr{}, false + } + end = zone + } + + var ip [16]byte + off := 0 + ellipsis := -1 + i := 0 + if end >= 2 && s[0] == ':' && s[1] == ':' { + ellipsis = 0 + i = 2 + } else if end > 0 && s[0] == ':' { + // A single leading colon starts no field. + return netip.Addr{}, false + } + + for off < 16 && i < end { + // Parse up to four hex digits; a fifth is an error. + fieldStart := i + val := uint32(0) + lim := min(i+4, end) + for i < lim { + d := unhexTable[s[i]] + if d == 0xFF { + break + } + val = val<<4 | uint32(d) + i++ + } + if i == lim && i < end && unhexTable[s[i]] != 0xFF { + return netip.Addr{}, false + } + if i < end && s[i] == '.' { + // Embedded IPv4 tail filling the final four bytes. + if off > 12 { + return netip.Addr{}, false + } + v4, ok := ParseIPv4(s[fieldStart:end]) + if !ok { + return netip.Addr{}, false + } + b4 := v4.As4() + copy(ip[off:], b4[:]) + off += 4 + i = end + break + } + if i == fieldStart { + // Every colon-separated field needs at least one digit. + return netip.Addr{}, false + } + // off is always even and < 16 here, so the two-byte store fits. + binary.BigEndian.PutUint16(ip[off:], uint16(val)) + off += 2 + if i == end { + break + } + if s[i] != ':' { + return netip.Addr{}, false + } + i++ + if i < end && s[i] == ':' { + if ellipsis >= 0 { + // At most one "::". + return netip.Addr{}, false + } + ellipsis = off + i++ + continue + } + if i == end { + // A trailing single colon is invalid. + return netip.Addr{}, false + } + } + if i != end { + return netip.Addr{}, false + } + if off < 16 { + if ellipsis < 0 { + return netip.Addr{}, false + } + // Expand "::": shift the fields after it to the end, zero the gap. + gap := 16 - off + for j := off - 1; j >= ellipsis; j-- { + ip[j+gap] = ip[j] + ip[j] = 0 + } + } else if ellipsis >= 0 { + // "::" must stand for at least one field of zeros. + return netip.Addr{}, false + } + + addr := netip.AddrFrom16(ip) + if zone >= 0 { + addr = addr.WithZone(string(s[zone+1:])) + } + return addr, true +} diff --git a/src/vendor/github.com/gofiber/utils/v2/ips.go b/src/vendor/github.com/gofiber/utils/v2/ips.go index 9c342fec..0f2d404f 100644 --- a/src/vendor/github.com/gofiber/utils/v2/ips.go +++ b/src/vendor/github.com/gofiber/utils/v2/ips.go @@ -4,48 +4,26 @@ import ( "net" ) -var hexTable = [256]byte{ - '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, - 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15, - 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, -} +// hexFieldMaxLen is the number of hex digits an IPv6 field may hold. +const hexFieldMaxLen = 4 -// IsIPv4 works the same way as net.ParseIP, -// but without check for IPv6 case and without returning net.IP slice, whereby IsIPv4 makes no allocations. +// IsIPv4 reports whether s is a dotted-decimal IPv4 address. It accepts +// exactly what net.ParseIP accepts for the IPv4 case, without the net.IP slice, +// so it makes no allocations. It is the validate-only spelling of ParseIPv4, +// which accepts the same strings and also returns the address. func IsIPv4(s string) bool { - for i := range net.IPv4len { - if len(s) == 0 { - return false - } - - if i > 0 { - if s[0] != '.' { - return false - } - s = s[1:] - } - - n, ci := 0, 0 - - for ci = 0; ci < len(s) && '0' <= s[ci] && s[ci] <= '9'; ci++ { - n = n*10 + int(s[ci]-'0') - if n > 0xFF { - return false - } - } - - if ci == 0 || (ci > 1 && s[0] == '0') { - return false - } - - s = s[ci:] - } - - return len(s) == 0 + _, ok := ParseIPv4(s) + return ok } -// IsIPv6 works the same way as net.ParseIP, -// but without check for IPv4 case and without returning net.IP slice, whereby IsIPv6 makes no allocations. +// IsIPv6 reports whether s is an IPv6 address. It accepts exactly what +// net.ParseIP accepts for the IPv6 case, without the net.IP slice, so it makes +// no allocations. That excludes a "%zone" suffix, because net.ParseIP rejects +// zones. +// +// ParseIPv6 follows netip.ParseAddr instead and does accept zones, so the two +// disagree on zoned input by design. Callers relying on IsIPv6 to reject zones +// must screen '%' themselves before substituting ParseIPv6. func IsIPv6(s string) bool { ellipsis := -1 // position of ellipsis in ip @@ -62,21 +40,21 @@ func IsIPv6(s string) bool { // Loop, parsing hex numbers followed by colon. i := 0 for i < net.IPv6len { - // Hex number. - n, ci := 0, 0 - - for ci = 0; ci < len(s); ci++ { - if (s[ci] < '0' || s[ci] > '9') && (s[ci] < 'a' || s[ci] > 'f') && (s[ci] < 'A' || s[ci] > 'F') { + // Hex field. Bounding the digit count is what rejects "00001": + // leading zeros hold the value below 0xFFFF however many of them + // there are, so a value-only bound lets an over-long field through. + // Four digits cannot exceed 0xFFFF, so no value check is needed. + ci := 0 + for ; ci < len(s); ci++ { + c := s[ci] + if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') { break } - n *= 16 - n += int(hexTable[s[ci]]) - - if n > 0xFFFF { + if ci == hexFieldMaxLen { return false } } - if ci == 0 || n > 0xFFFF { + if ci == 0 { return false } diff --git a/src/vendor/github.com/gofiber/utils/v2/jsonstring.go b/src/vendor/github.com/gofiber/utils/v2/jsonstring.go new file mode 100644 index 00000000..009e8986 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/jsonstring.go @@ -0,0 +1,126 @@ +package utils + +import ( + "unicode/utf8" + + "github.com/gofiber/utils/v2/internal/unsafeconv" + "github.com/gofiber/utils/v2/swar" +) + +// ltLanes, gtLanes, and ampLanes broadcast the HTML-escaped characters to +// every lane; quoteLanes and backslashLanes live in ascii.go. +const ( + ltLanes = uint64('<') * swar.Ones + gtLanes = uint64('>') * swar.Ones + ampLanes = uint64('&') * swar.Ones +) + +// jsonHexDigits is the escape alphabet for \u00XX sequences, matching +// encoding/json. +const jsonHexDigits = "0123456789abcdef" + +// jsonSafeTable flags the ASCII bytes that pass through a JSON string +// encoder verbatim: 0x20..0x7E minus '"', '\\', and the HTML-escaped +// '<', '>', '&'. Bytes >= 0x80 are false so the scalar loop routes them +// to the UTF-8 path. +var jsonSafeTable = buildJSONSafeTable() + +func buildJSONSafeTable() [256]bool { + var t [256]bool + for c := byte(0x20); c < utf8.RuneSelf; c++ { + t[c] = c != '"' && c != '\\' && c != '<' && c != '>' && c != '&' + } + return t +} + +// AppendJSONString appends s to dst as a double-quoted JSON string and +// returns the extended slice. The output is byte-identical to +// encoding/json.Marshal of the same string value, including its default +// HTML escaping: '"' and '\\' get backslash escapes; control bytes below +// 0x20 become \b, \f, \n, \r, \t, or \u00XX; '<', '>', '&' become \u00XX; each +// invalid UTF-8 byte becomes the six literal characters \ufffd; and the +// line separators U+2028/U+2029 become the \u2028 and \u2029 escapes. +// Go 1.27's json/v2 writes that replacement raw, so for invalid UTF-8 the two +// encodings differ from 1.27 on; both still decode to the same string. +// All other bytes, including multi-byte UTF-8 sequences, are copied +// verbatim. dst must not alias s: the output is longer than the input (at +// minimum by the surrounding quotes), so in-place encoding is impossible +// and an aliased dst would overwrite bytes before they are read. Clean +// spans are located with a SWAR scan and copied wholesale, so typical log +// or header values cost one scan and one copy — with none of +// encoding/json.Marshal's reflection or allocation. +func AppendJSONString[S byteSeq](dst []byte, s S) []byte { + bs := unsafeconv.Bytes(s) + n := len(bs) + dst = append(dst, '"') + start, i := 0, 0 + for i < n { + // Skip to the next byte needing attention. Like nonQuotableMask, + // the combined mask is exact in and below its first set lane, which + // is all this first-match scan consumes. + if i+8 <= n { + m := jsonUnsafeMask(swar.Load8(bs, i)) + if m == 0 { + i += 8 + continue + } + i += swar.FirstLane(m) + } else if c := bs[i]; jsonSafeTable[c] { + i++ + continue + } + c := bs[i] + if c < utf8.RuneSelf { + dst = append(dst, bs[start:i]...) + dst = append(dst, '\\') + switch c { + case '"', '\\': + dst = append(dst, c) + case '\b': + dst = append(dst, 'b') + case '\f': + dst = append(dst, 'f') + case '\n': + dst = append(dst, 'n') + case '\r': + dst = append(dst, 'r') + case '\t': + dst = append(dst, 't') + default: + // Other control bytes and the HTML characters '<', '>', '&'. + dst = append(dst, 'u', '0', '0', jsonHexDigits[c>>4], jsonHexDigits[c&0x0F]) + } + i++ + start = i + continue + } + r, size := utf8.DecodeRune(bs[i:]) + switch { + case r == utf8.RuneError && size == 1: + dst = append(dst, bs[start:i]...) + dst = append(dst, '\\', 'u', 'f', 'f', 'f', 'd') + i++ + start = i + case r == '\u2028' || r == '\u2029': + dst = append(dst, bs[start:i]...) + dst = append(dst, '\\', 'u', '2', '0', '2', byte('8'+r-'\u2028')) + i += size + start = i + default: + i += size + } + } + dst = append(dst, bs[start:]...) + return append(dst, '"') +} + +// jsonUnsafeMask flags the lanes of w holding bytes a JSON string encoder +// cannot copy verbatim: controls below 0x20 (exact range mask), the five +// escaped ASCII characters (ZeroLanes needle matches, exact in and below +// their first hit), and all bytes >= 0x80, which the caller inspects as +// UTF-8. +func jsonUnsafeMask(w uint64) uint64 { + return swar.MatchRangeMask(w, 0x00, 0x1F) | w&swar.HighBits | + swar.ZeroLanes(w^quoteLanes) | swar.ZeroLanes(w^backslashLanes) | + swar.ZeroLanes(w^ltLanes) | swar.ZeroLanes(w^gtLanes) | swar.ZeroLanes(w^ampLanes) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/parse.go b/src/vendor/github.com/gofiber/utils/v2/parse.go index 2df8ae7c..46b52342 100644 --- a/src/vendor/github.com/gofiber/utils/v2/parse.go +++ b/src/vendor/github.com/gofiber/utils/v2/parse.go @@ -181,10 +181,9 @@ func isEightDigits(w uint64) bool { // steps. The caller must have validated that every lane is '0'..'9'. func parse8Digits(w uint64) uint64 { const ( - digitZeros = 0x3030303030303030 // '0' in every lane - pairMask = 0x000000FF000000FF - mul1 = 100 + (1000000 << 32) - mul2 = 1 + (10000 << 32) + pairMask = 0x000000FF000000FF + mul1 = 100 + (1000000 << 32) + mul2 = 1 + (10000 << 32) ) w -= digitZeros w = w*10 + w>>8 // adjacent digit pairs -> 2-digit values in even lanes diff --git a/src/vendor/github.com/gofiber/utils/v2/search.go b/src/vendor/github.com/gofiber/utils/v2/search.go index 58df1e45..6466e443 100644 --- a/src/vendor/github.com/gofiber/utils/v2/search.go +++ b/src/vendor/github.com/gofiber/utils/v2/search.go @@ -2,6 +2,8 @@ package utils import ( "github.com/gofiber/utils/v2/internal/caseconv" + "github.com/gofiber/utils/v2/internal/unsafeconv" + "github.com/gofiber/utils/v2/simd" "github.com/gofiber/utils/v2/swar" ) @@ -16,9 +18,13 @@ import ( // Inputs shorter than a word use scalar loops throughout. // IndexAny2 returns the index of the first occurrence in s of either a or b, -// or -1 if neither is present. +// or -1 if neither is present. On amd64 CPUs with AVX2, inputs of 32+ bytes +// dispatch to package simd instead. func IndexAny2[S byteSeq](s S, a, b byte) int { n := len(s) + if n >= simd.MinLen && simd.Accelerated() { + return simd.Memchr2(unsafeconv.Bytes(s), a, b) + } if n >= 8 { // The needle broadcasts are hoisted here so sub-word inputs never // pay for the multiplies. @@ -63,9 +69,13 @@ func IndexAny2[S byteSeq](s S, a, b byte) int { } // IndexAny3 returns the index of the first occurrence in s of a, b, or c, -// or -1 if none is present. +// or -1 if none is present. On amd64 CPUs with AVX2, inputs of 32+ bytes +// dispatch to package simd instead. func IndexAny3[S byteSeq](s S, a, b, c byte) int { n := len(s) + if n >= simd.MinLen && simd.Accelerated() { + return simd.Memchr3(unsafeconv.Bytes(s), a, b, c) + } if n >= 8 { bcA := swar.Broadcast(a) bcB := swar.Broadcast(b) diff --git a/src/vendor/github.com/gofiber/utils/v2/seq.go b/src/vendor/github.com/gofiber/utils/v2/seq.go new file mode 100644 index 00000000..562ded05 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/seq.go @@ -0,0 +1,32 @@ +package utils + +import ( + "bytes" + "iter" + + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// SplitTrimSeq iterates over the sep-separated elements of s with ASCII +// whitespace trimmed and empty elements skipped, as HTTP list fields are read +// (RFC 9110 Section 5.6.1); the elements alias s. +func SplitTrimSeq[S byteSeq](s S, sep byte) iter.Seq[S] { + return func(yield func(S) bool) { + rest := s // traversal state stays local, so the sequence can be ranged over again + for { + // CutByte's body, inline: it is too large to inline into the iterator. + i := bytes.IndexByte(unsafeconv.Bytes(rest), sep) + elem := rest + if i >= 0 { + elem = rest[:i] + } + if elem = TrimSpace(elem); len(elem) > 0 && !yield(elem) { + return + } + if i < 0 { + return + } + rest = rest[i+1:] + } + } +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/LICENSE b/src/vendor/github.com/gofiber/utils/v2/simd/LICENSE new file mode 100644 index 00000000..6fc282c7 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Andrey Kolkov and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/ascii.go b/src/vendor/github.com/gofiber/utils/v2/simd/ascii.go new file mode 100644 index 00000000..0c49f7c4 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/ascii.go @@ -0,0 +1,177 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +import ( + "math/bits" + + "github.com/gofiber/utils/v2/swar" +) + +// IsASCII reports whether every byte in data is ASCII (< 0x80). An empty +// slice is trivially ASCII. +// +// On amd64 with AVX2 and inputs of MinLen+ bytes it ORs four 32-byte +// vectors and tests all 128 bytes with a single VPMOVMSKB; elsewhere it +// uses a SWAR loop over 8-byte words. +func IsASCII(data []byte) bool { + if len(data) == 0 { + return true + } + return isASCIIImpl(data) +} + +// FirstNonASCII returns the index of the first byte >= 0x80 in data, or -1 +// if data is all ASCII. Use it to find where UTF-8 sequences begin. +// +// It reads the same signal as IsASCII — a non-ASCII byte is exactly a byte +// with its high bit set — so on amd64 with AVX2 and inputs of MinLen+ +// bytes it also tests 128 bytes per VPMOVMSKB, keeping the four vectors +// live so the hit path can pinpoint the byte; elsewhere it falls back to +// SWAR words. +func FirstNonASCII(data []byte) int { + if len(data) == 0 { + return -1 + } + return firstNonASCIIImpl(data) +} + +// CountNonASCII returns the number of bytes >= 0x80 in data. +// +// On amd64 with AVX2 and inputs of MinLen+ bytes it accumulates a per-lane +// count of high-bit bytes in vector byte lanes, four 32-byte vectors per +// iteration, sums the lanes once at the end, and population-counts the +// high-bit masks of the remaining whole vectors; elsewhere it counts +// SWAR-word-wise with a popcount per word. +func CountNonASCII(data []byte) int { + return countNonASCIIImpl(data) +} + +// The unrolled loops below all pin their group of words with a +// three-index reslice before loading from it. swar.Load8's own reslice is +// bounds-checked against the backing array's capacity, which the loop +// condition (stated in terms of length) does not imply, so a variable +// index costs a compare, a branch and a four-instruction empty-slice +// pointer clamp per load. Pinning the window once pays that at group +// granularity and leaves the loads inside it at constant offsets, where +// the checks fold away entirely: measured -20% at 32B rising to -62% at +// 4KiB for the ASCII scan, and the same shape for the first-match scans. + +// isASCIIGeneric is the portable SWAR implementation behind IsASCII. No +// index is needed, so detection can be deferred: whole groups of words are +// OR-ed into one accumulator and tested once, four words per branch and +// then two, which is what turns the per-word test into a per-32-byte one. +// Inputs of 8..15 bytes skip the loops entirely — two overlapping words +// already cover them — and every 8+ byte input finishes with one +// overlapping word at n-8. +func isASCIIGeneric(data []byte) bool { + n := len(data) + if n < swar.WordLen { + for i := range n { + if data[i] >= 0x80 { + return false + } + } + return true + } + if n < 2*swar.WordLen { + return (swar.Load8(data, 0)|swar.Load8(data, n-swar.WordLen))&swar.HighBits == 0 + } + i := 0 + for ; i+4*swar.WordLen <= n; i += 4 * swar.WordLen { + w := data[i : i+4*swar.WordLen : i+4*swar.WordLen] + acc := swar.Load8(w, 0) | + swar.Load8(w, swar.WordLen) | + swar.Load8(w, 2*swar.WordLen) | + swar.Load8(w, 3*swar.WordLen) + if acc&swar.HighBits != 0 { + return false + } + } + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + w := data[i : i+2*swar.WordLen : i+2*swar.WordLen] + if (swar.Load8(w, 0)|swar.Load8(w, swar.WordLen))&swar.HighBits != 0 { + return false + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + if swar.Load8(data, i)&swar.HighBits != 0 { + return false + } + } + if i == n { + return true + } + return swar.Load8(data, n-swar.WordLen)&swar.HighBits == 0 +} + +// firstNonASCIIGeneric is the portable SWAR implementation behind +// FirstNonASCII: two words per branch, then one overlapping word at n-8. +func firstNonASCIIGeneric(data []byte) int { + n := len(data) + if n < swar.WordLen { + for i := range n { + if data[i] >= 0x80 { + return i + } + } + return -1 + } + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + w := data[i : i+2*swar.WordLen : i+2*swar.WordLen] + m0 := swar.Load8(w, 0) & swar.HighBits + m1 := swar.Load8(w, swar.WordLen) & swar.HighBits + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m := swar.Load8(data, i) & swar.HighBits; m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + // Overlapping final word: lanes before i are known ASCII, so any set + // lane falls in the new bytes. + if m := swar.Load8(data, n-swar.WordLen) & swar.HighBits; m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} + +// countNonASCIIGeneric is the portable SWAR implementation behind +// CountNonASCII: a popcount of the 0x80 lane bits per word, four words per +// pinned window. Every word has to be visited whatever happens, so unlike +// the first-match scans there is no branch to amortize — the win here is +// purely the bounds checks the window removes. +func countNonASCIIGeneric(data []byte) int { + count := 0 + i := 0 + n := len(data) + for ; i+4*swar.WordLen <= n; i += 4 * swar.WordLen { + w := data[i : i+4*swar.WordLen : i+4*swar.WordLen] + count += bits.OnesCount64(swar.Load8(w, 0)&swar.HighBits) + + bits.OnesCount64(swar.Load8(w, swar.WordLen)&swar.HighBits) + + bits.OnesCount64(swar.Load8(w, 2*swar.WordLen)&swar.HighBits) + + bits.OnesCount64(swar.Load8(w, 3*swar.WordLen)&swar.HighBits) + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + count += bits.OnesCount64(swar.Load8(data, i) & swar.HighBits) + } + // No overlapping word here: it would double-count. The tail is at most + // seven bytes. + for ; i < n; i++ { + if data[i] >= 0x80 { + count++ + } + } + return count +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.go b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.go new file mode 100644 index 00000000..04ec50e5 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.go @@ -0,0 +1,55 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build amd64 + +package simd + +// The ASCII kernels are implemented in ascii_amd64.s. All three read the +// same signal (a byte is non-ASCII exactly when its high bit is set, which +// VPMOVMSKB gathers 32 at a time) and process four vectors per iteration. +// Like the rest of the package's kernels they are self-bounding: each one +// clamps its own vector loops and finishes short remainders itself, so +// none of them carries a length precondition for the caller to uphold. +// +//go:noescape +func isASCIIAVX2(data []byte) bool + +//go:noescape +func firstNonASCIIAVX2(data []byte) int + +//go:noescape +func countNonASCIIAVX2(data []byte) int + +// isASCIIImpl dispatches to the AVX2 kernel for inputs large enough to amortize +// the vector setup; smaller inputs and pre-AVX2 CPUs take the SWAR path. +func isASCIIImpl(data []byte) bool { + if hasAVX2 && len(data) >= MinLen { + return isASCIIAVX2(data) + } + return isASCIIGeneric(data) +} + +// firstNonASCIIImpl dispatches like isASCIIImpl. +func firstNonASCIIImpl(data []byte) int { + if hasAVX2 && len(data) >= MinLen { + return firstNonASCIIAVX2(data) + } + return firstNonASCIIGeneric(data) +} + +// countNonASCIIImpl dispatches like isASCIIImpl, with the extra POPCNT +// check its kernel needs. The kernel counts its own sub-vector remainder, +// so there is no prefix/suffix split here. An earlier version did split, +// handing the remainder to countNonASCIIGeneric, and paid a second +// non-inlinable call even when the remainder was empty — enough to put +// this scan behind its own SWAR fallback at MinLen (11.3ns vs 8.8ns at +// 32B). With the split gone the two are level at 32B and the kernel pulls +// ahead from 64B up, so MinLen stays the shared threshold. +func countNonASCIIImpl(data []byte) int { + if hasAVX2 && hasPOPCNT && len(data) >= MinLen { + return countNonASCIIAVX2(data) + } + return countNonASCIIGeneric(data) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.s b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.s new file mode 100644 index 00000000..b815c546 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_amd64.s @@ -0,0 +1,399 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. +// Modified: legacy-SSE MOVD/MOVQ register moves replaced with VEX-encoded +// VMOVD/VMOVQ to avoid AVX-SSE transition penalties on Intel CPUs, the +// scalar tail loop replaced with one overlapping vector at the buffer end +// for the MinLen+ inputs the Go dispatch guarantees, the 32-byte main loop +// replaced with a 4x unrolled 128-byte block, and firstNonASCIIAVX2 / +// countNonASCIIAVX2 added so the locating and counting scans no longer +// have to fall back to SWAR words on amd64 (the counting kernel's block +// loop accumulating in vector byte lanes rather than extracting and +// population-counting every vector's mask). + +//go:build amd64 + +#include "textflag.h" +#include "block_align_amd64.h" + +// All three kernels share one observation: a byte is non-ASCII exactly when +// its high bit is set, and VPMOVMSKB gathers those 32 high bits into a +// scalar register in one instruction. OR-ing four vectors before the +// extraction therefore preserves "some byte in these 128 was non-ASCII" +// exactly, which is what lets the block loop test 128 bytes with a single +// port-0 VPMOVMSKB. Both loops test their bound at the bottom against a +// precomputed limit pointer. + +// func isASCIIAVX2(data []byte) bool +// +// AVX2 implementation of ASCII detection that checks if all bytes are < 0x80. +// +// Algorithm: +// 1. Block loop: OR four 32-byte vectors, extract the high bits with +// VPMOVMSKB, and return false if any is set. The loads fold into the +// VPOR operands, so a block costs four memory ops and one extraction. +// 2. 32-byte loop for the remainder, then one overlapping 32-byte window +// ending at the buffer end (rescanning bytes already proven ASCII +// cannot change the outcome). A scalar loop serves only sub-32 direct +// calls, unreachable through the Go dispatch. +// 3. Always call VZEROUPPER before returning (critical for performance) +// +// Parameters (FP offsets): +// data_base+0(FP) - pointer to data (8 bytes) +// data_len+8(FP) - data length (8 bytes) +// data_cap+16(FP) - data capacity (8 bytes, unused but part of slice) +// ret+24(FP) - return value: bool (1 byte) +// +// Total argument frame size: 25 bytes (8+8+8+1) +TEXT ·isASCIIAVX2(SB), NOSPLIT, $0-25 + // Load parameters + MOVQ data_base+0(FP), SI // SI = data pointer + MOVQ data_len+8(FP), DX // DX = data length + + // Empty data check + TESTQ DX, DX + JZ all_ascii + + // Calculate end pointer + LEAQ (SI)(DX*1), R8 // R8 = SI + length (end pointer) + + CMPQ DX, $32 + JB tail_loop // sub-32 direct call: scalar + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA loop32_entry + + BLOCKALIGN +loop128: + VMOVDQU (SI), Y0 + VPOR 32(SI), Y0, Y0 + VPOR 64(SI), Y0, Y0 + VPOR 96(SI), Y0, Y0 + VPMOVMSKB Y0, AX + TESTL AX, AX + JNZ found_non_ascii + + ADDQ $128, SI + CMPQ SI, R11 + JBE loop128 + +loop32_entry: + CMPQ SI, R12 + JA last32 + +loop32: + // Load 32 bytes (unaligned load is safe and fast with AVX2) and + // extract the high bit of each byte into a 32-bit mask. + VMOVDQU (SI), Y0 + VPMOVMSKB Y0, AX + TESTL AX, AX + JNZ found_non_ascii + + ADDQ $32, SI + CMPQ SI, R12 + JBE loop32 + +last32: + // Fewer than 32 bytes remain past SI; retest the final window. + CMPQ SI, R8 + JAE all_ascii + VMOVDQU (R12), Y0 + VPMOVMSKB Y0, AX + TESTL AX, AX + JNZ found_non_ascii + JMP all_ascii + +tail_loop: + // Load one byte and check high bit + MOVBLZX (SI), AX // AX = data[SI] (zero-extended) + TESTB $0x80, AL // Check if high bit is set + JNZ found_non_ascii // If set, non-ASCII found + + // Advance to next byte + INCQ SI + CMPQ SI, R8 // Check if reached end + JB tail_loop // Continue if SI < end + +all_ascii: + // All bytes are ASCII + MOVB $1, ret+24(FP) // Return true + VZEROUPPER // Clear upper YMM bits (CRITICAL!) + RET + +found_non_ascii: + MOVB $0, ret+24(FP) // Return false + VZEROUPPER // Clear upper YMM bits + RET + +// func firstNonASCIIAVX2(data []byte) int +// +// AVX2 kernel behind FirstNonASCII: the same scan as isASCIIAVX2, but the +// block loop keeps the four source vectors live so the hit path can +// re-extract them in address order and BSF the first non-ASCII byte. +// +// Parameters (FP offsets): +// data_base+0(FP) - pointer to data (8 bytes) +// data_len+8(FP) - data length (8 bytes) +// data_cap+16(FP) - data capacity (8 bytes, unused) +// ret+24(FP) - return value: index or -1 (8 bytes) +TEXT ·firstNonASCIIAVX2(SB), NOSPLIT, $0-32 + MOVQ data_base+0(FP), SI + MOVQ data_len+8(FP), DX + + TESTQ DX, DX + JZ fna_not_found + + MOVQ SI, DI // DI = data start (preserved) + LEAQ (SI)(DX*1), R8 + + CMPQ DX, $32 + JB fna_tail_loop // sub-32 direct call: scalar + + LEAQ -32(R8), R12 + LEAQ -128(R8), R11 + CMPQ SI, R11 + JA fna_loop32_entry + + BLOCKALIGN +fna_loop128: + VMOVDQU (SI), Y0 + VMOVDQU 32(SI), Y1 + VMOVDQU 64(SI), Y2 + VMOVDQU 96(SI), Y3 + VPOR Y0, Y1, Y4 + VPOR Y2, Y3, Y5 + VPOR Y4, Y5, Y4 + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ fna_found_in_block + + ADDQ $128, SI + CMPQ SI, R11 + JBE fna_loop128 + +fna_loop32_entry: + CMPQ SI, R12 + JA fna_last32 + +fna_loop32: + VMOVDQU (SI), Y0 + VPMOVMSKB Y0, CX + TESTL CX, CX + JNZ fna_found_in_vector + + ADDQ $32, SI + CMPQ SI, R12 + JBE fna_loop32 + +fna_last32: + // Fewer than 32 bytes remain past SI; rescan the final window. Lanes + // before SI are known ASCII, so the first set lane falls in the new + // bytes. + CMPQ SI, R8 + JAE fna_not_found + MOVQ R12, SI + VMOVDQU (SI), Y0 + VPMOVMSKB Y0, CX + TESTL CX, CX + JNZ fna_found_in_vector + JMP fna_not_found + +fna_tail_loop: + MOVBLZX (SI), AX + TESTB $0x80, AL + JNZ fna_found_scalar + INCQ SI + CMPQ SI, R8 + JB fna_tail_loop + +fna_not_found: + MOVQ $-1, AX + MOVQ AX, ret+24(FP) + VZEROUPPER + RET + +fna_found_in_block: + VPMOVMSKB Y0, CX + TESTL CX, CX + JNZ fna_found_in_vector + ADDQ $32, SI + VPMOVMSKB Y1, CX + TESTL CX, CX + JNZ fna_found_in_vector + ADDQ $32, SI + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ fna_found_in_vector + ADDQ $32, SI + VPMOVMSKB Y3, CX + +fna_found_in_vector: + BSFL CX, CX + SUBQ DI, SI + ADDQ SI, CX + MOVQ CX, ret+24(FP) + VZEROUPPER + RET + +fna_found_scalar: + SUBQ DI, SI + MOVQ SI, ret+24(FP) + VZEROUPPER + RET + +// func countNonASCIIAVX2(data []byte) int +// +// AVX2 kernel behind CountNonASCII. Counting is the one scan here that +// cannot finish with the overlapping final window the first-match kernels +// use — rescanning bytes would count them twice — so instead the vector +// loops stop at the last whole vector and a branch-free byte loop takes +// the remaining 0-31 bytes. That keeps the kernel self-bounding for any +// length, like every other kernel in this package: it never reads past +// data[len(data)-1], so no caller-side length preconditioning stands +// between it and an out-of-bounds read. +// +// The block loop accumulates in vector byte lanes rather than extracting +// a mask per vector. A signed compare against zero turns each non-ASCII +// byte (the only bytes that read as negative) into 0xFF, and subtracting +// that lane from a byte accumulator adds one to it; the compare takes its +// input straight from memory, so a vector costs two vector ops and no +// scalar work. An earlier version extracted every vector's high bits +// with VPMOVMSKB and population-counted them, four extractions per block +// on the one port that executes them, which held the block loop to about +// half the throughput of the ASCII scans. Two accumulators alternate so +// each carries a two-op dependency chain per block. +// +// A byte lane can hold 255 and gains at most two per block, so the block +// loop flushes both accumulators every 127 blocks: VPSADBW against zero +// sums each accumulator's bytes into four 64-bit lanes, which are added +// to a running vector total. After the last block the totals are reduced +// to one scalar. That reduction is a fixed ten-cycle latency chain, which +// the 1-3 vectors left after the block loop (or the 1-3 vectors of a +// sub-block input) could not amortize, so those are still extracted with +// VPMOVMSKB and population-counted, exactly as before; each POPCNT writes +// the register its own VPMOVMSKB just produced, so the destination false +// dependency Intel CPUs carry on POPCNT is already satisfied. Inputs +// below one block therefore never touch the vector accumulators. +// +// POPCNT is a separate CPUID feature from AVX2, so countNonASCIIImpl gates +// on both; see cpu_amd64.go. +// +// Parameters (FP offsets): +// data_base+0(FP) - pointer to data (8 bytes) +// data_len+8(FP) - data length (8 bytes) +// data_cap+16(FP) - data capacity (8 bytes, unused) +// ret+24(FP) - number of bytes >= 0x80 (8 bytes) + +// FLUSH folds the two byte accumulators Y4 and Y5 into the 64-bit lane +// totals in Y8 and clears them. Y7 is the zero vector; Y0 and Y1 are +// scratch. +#define FLUSH \ + VPSADBW Y7, Y4, Y0; \ + VPSADBW Y7, Y5, Y1; \ + VPADDQ Y0, Y8, Y8; \ + VPADDQ Y1, Y8, Y8; \ + VPXOR Y4, Y4, Y4; \ + VPXOR Y5, Y5, Y5 + +TEXT ·countNonASCIIAVX2(SB), NOSPLIT, $0-32 + MOVQ data_base+0(FP), SI + MOVQ data_len+8(FP), DX + + XORQ R9, R9 // R9 = block loop total + XORQ R10, R10 // R10 = remainder total (kept apart so + // the remainder need not wait for the + // vector reduction) + + TESTQ DX, DX + JZ cna_done + + LEAQ (SI)(DX*1), R8 // R8 = end pointer + CMPQ DX, $32 + JB cna_tail // no whole vector: byte loop only + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA cna_loop32_entry // no whole block: extract and count + + VPXOR Y7, Y7, Y7 // Y7 = zero (compare and SAD operand) + VPXOR Y4, Y4, Y4 // Y4 = byte accumulator A + VPXOR Y5, Y5, Y5 // Y5 = byte accumulator B + VPXOR Y8, Y8, Y8 // Y8 = 64-bit lane totals + MOVQ $127, R13 // blocks until a byte lane could overflow + + // This loop carries a third fused pair, the DECQ/JZ flush countdown, + // which at BLOCKALIGN's offset would straddle a window boundary; see + // block_align_amd64.h. + BLOCKALIGN_LONG +cna_loop128: + // 0 > byte is exactly "high bit set"; the compares read their data + // operand from memory. + VPCMPGTB (SI), Y7, Y0 + VPCMPGTB 32(SI), Y7, Y1 + VPCMPGTB 64(SI), Y7, Y2 + VPCMPGTB 96(SI), Y7, Y3 + VPSUBB Y0, Y4, Y4 // lane -= 0xFF, i.e. += 1 where non-ASCII + VPSUBB Y1, Y5, Y5 + VPSUBB Y2, Y4, Y4 + VPSUBB Y3, Y5, Y5 + + ADDQ $128, SI + DECQ R13 + JZ cna_flush + +cna_loop128_next: + CMPQ SI, R11 + JBE cna_loop128 + JMP cna_block_done + +cna_flush: + FLUSH + MOVQ $127, R13 + JMP cna_loop128_next + +cna_block_done: + // Fold the accumulators into the lane totals and the four totals into + // one scalar: high half onto low, then the high 64-bit lane onto the + // low one. + VPSADBW Y7, Y4, Y0 + VPSADBW Y7, Y5, Y1 + VPADDQ Y0, Y8, Y8 + VPADDQ Y1, Y8, Y8 + VEXTRACTI128 $1, Y8, X0 + VPADDQ X0, X8, X8 + VPSRLDQ $8, X8, X0 + VPADDQ X0, X8, X8 + VMOVQ X8, R9 + +cna_loop32_entry: + CMPQ SI, R12 + JA cna_tail + +cna_loop32: + VMOVDQU (SI), Y0 + VPMOVMSKB Y0, AX + POPCNTL AX, AX + ADDQ AX, R10 + ADDQ $32, SI + CMPQ SI, R12 + JBE cna_loop32 + +cna_tail: + // 0-31 bytes left. Shifting the byte down to its high bit turns the + // test into an add, so the loop carries no data-dependent branch. + CMPQ SI, R8 + JAE cna_done + MOVBLZX (SI), AX + SHRL $7, AX + ADDQ AX, R10 + INCQ SI + JMP cna_tail + +cna_done: + ADDQ R10, R9 + MOVQ R9, ret+24(FP) + VZEROUPPER + RET diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/ascii_other.go b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_other.go new file mode 100644 index 00000000..19c55813 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/ascii_other.go @@ -0,0 +1,21 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build !amd64 + +package simd + +// The portable SWAR implementations are the only ones off amd64. + +func isASCIIImpl(data []byte) bool { + return isASCIIGeneric(data) +} + +func firstNonASCIIImpl(data []byte) int { + return firstNonASCIIGeneric(data) +} + +func countNonASCIIImpl(data []byte) int { + return countNonASCIIGeneric(data) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/block_align_amd64.h b/src/vendor/github.com/gofiber/utils/v2/simd/block_align_amd64.h new file mode 100644 index 00000000..f928e805 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/block_align_amd64.h @@ -0,0 +1,31 @@ +// BLOCKALIGN and BLOCKALIGN_LONG place the 128-byte block loop that +// follows them at byte 18, respectively 27, of a 32-byte code window: +// PCALIGN pads to the window, then two (or three) nine-byte NOPs — the +// canonical 66 0F 1F 84 00 00 00 00 00 form — shift the loop head. The +// NOPs sit before the label, so they run once per call that enters the +// block loop, never per iteration. +// +// The offset matters because of the Intel JCC erratum: on Skylake-derived +// cores (Skylake, Cascade Lake, Coffee Lake and their siblings) the +// microcode mitigation refuses to keep a jump — or a macro-fused +// compare-and-jump pair — in the decoded-uop cache when it crosses a +// 32-byte boundary or ends exactly on one. A block loop whose TEST/JNZ, +// DEC/JZ or CMP/JBE lands on such a boundary then runs from the legacy +// decoder every iteration, which measured ~10% slower on the pair kernel +// at 4KiB, and whether that happened used to depend on where the linker +// placed each kernel. Which offsets keep every pair of a loop inside one +// window depends on the loop's exact byte layout: 18 does for the six +// loops that use BLOCKALIGN, 27 for the three that use BLOCKALIGN_LONG. +// block_align_amd64_test.go checks the property against the linked test +// binary and logs each pair's position relative to its loop head, so a +// kernel edit that moves a branch onto a boundary fails the test (and +// the log shows which offset to pick) instead of silently costing +// throughput. +#define BLOCKALIGN \ + PCALIGN $32; \ + BYTE $0x66; BYTE $0x0F; BYTE $0x1F; BYTE $0x84; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; \ + BYTE $0x66; BYTE $0x0F; BYTE $0x1F; BYTE $0x84; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 + +#define BLOCKALIGN_LONG \ + BLOCKALIGN; \ + BYTE $0x66; BYTE $0x0F; BYTE $0x1F; BYTE $0x84; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/byte_frequencies.go b/src/vendor/github.com/gofiber/utils/v2/simd/byte_frequencies.go new file mode 100644 index 00000000..04160d6f --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/byte_frequencies.go @@ -0,0 +1,102 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +// byteFrequencies holds empirical byte frequency ranks derived from English +// text, source code, and binary data samples. Lower rank means rarer byte, +// which makes it a better anchor for a search prefilter. The approach +// mirrors Rust's memchr crate (https://github.com/BurntSushi/memchr). +// The table is unexported (read it through ByteRank) so callers cannot +// mutate the ranking Memmem's prefilter selection depends on. +var byteFrequencies = [256]byte{ + // 0x00-0x0F: control characters (generally rare) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + // 0x10-0x1F: more control characters + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0x20-0x2F: space and punctuation + 255, 60, 140, 50, 40, 35, 30, 160, 130, 130, 80, 55, 200, 140, 210, 100, + // 0x30-0x3F: digits and more punctuation + 180, 190, 170, 150, 140, 140, 130, 120, 120, 120, 150, 100, 70, 160, 70, 50, + // 0x40-0x4F: '@' and uppercase A-O + 25, 120, 80, 90, 85, 130, 75, 70, 80, 115, 30, 35, 90, 85, 100, 105, + // 0x50-0x5F: uppercase P-Z and brackets + 80, 15, 100, 110, 115, 70, 45, 55, 20, 50, 10, 90, 60, 90, 20, 110, + // 0x60-0x6F: backtick and lowercase a-o + 30, 225, 140, 170, 165, 245, 135, 130, 150, 200, 25, 65, 175, 155, 195, 205, + // 0x70-0x7F: lowercase p-z and braces + 145, 15, 195, 200, 215, 150, 75, 95, 45, 120, 20, 85, 40, 85, 15, 0, + // 0x80-0xFF: UTF-8 continuation/lead bytes (rare in typical text) + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +} + +// ByteRank returns the empirical frequency rank of b. Lower values indicate +// rarer bytes, which are better anchors for search prefilters; SelectRareBytes +// and Memmem rank needle bytes with it. +func ByteRank(b byte) byte { + return byteFrequencies[b] +} + +// RareByteInfo describes the two rarest bytes of a needle, as selected by +// SelectRareBytes. When the needle contains at least two distinct byte +// values, Byte2 always differs from Byte1; only for empty, single-byte, or +// all-identical needles do Byte2/Index2 equal Byte1/Index1. +type RareByteInfo struct { + // Byte1 is the rarest byte found in the needle. + Byte1 byte + // Byte2 is the rarest byte with a value different from Byte1, when the + // needle has one; otherwise it equals Byte1. + Byte2 byte + // Index1 is the position of Byte1's first occurrence in the needle. + Index1 int + // Index2 is the position of Byte2's first occurrence in the needle. + Index2 int +} + +// SelectRareBytes returns the two rarest bytes of needle according to +// ByteRank, preferring distinct byte values: whenever the needle contains +// two distinct values, Byte2 is the rarest byte different from Byte1, so +// duplicated occurrences of the rarest byte never crowd out a usable +// second anchor. Memmem feeds the result to MemchrPair to build a highly +// selective substring prefilter; it is exported so downstream code can +// build its own prefilters the same way. +func SelectRareBytes(needle []byte) RareByteInfo { + n := len(needle) + if n == 0 { + return RareByteInfo{} + } + + byte1, idx1 := needle[0], 0 + byte2, idx2 := needle[0], 0 + have2 := false + + for i := 1; i < n; i++ { + b := needle[i] + switch { + case byteFrequencies[b] < byteFrequencies[byte1]: + // b is strictly rarer than byte1, so it also has a different + // value; the demoted byte1 is at least as rare as any previous + // byte2 and becomes the second anchor. + byte2, idx2 = byte1, idx1 + byte1, idx1 = b, i + have2 = true + case b != byte1 && (!have2 || byteFrequencies[b] < byteFrequencies[byte2]): + byte2, idx2 = b, i + have2 = true + } + } + if !have2 { + // All bytes identical: no distinct second anchor exists. + byte2, idx2 = byte1, idx1 + } + + return RareByteInfo{Byte1: byte1, Byte2: byte2, Index1: idx1, Index2: idx2} +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/cpu_amd64.go b/src/vendor/github.com/gofiber/utils/v2/simd/cpu_amd64.go new file mode 100644 index 00000000..3ee4864f --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/cpu_amd64.go @@ -0,0 +1,22 @@ +//go:build amd64 + +package simd + +import ( + "golang.org/x/sys/cpu" +) + +// hasAVX2 gates every AVX2 kernel in this package. golang.org/x/sys/cpu +// verifies both the CPU capability and OS support for saving the YMM +// register state, and the value is read once at init so the per-call +// dispatch is a single predictable branch. +var hasAVX2 = cpu.X86.HasAVX2 + +// hasPOPCNT gates countNonASCIIAVX2, the one kernel that reaches outside +// the AVX/AVX2 instruction set: its remainder loop turns a vector's +// high-bit mask into a lane count with POPCNT, whose CPUID bit +// (01H:ECX[23]) is independent of AVX2's. Every shipping AVX2 part has +// POPCNT, but a hypervisor can mask the two separately, and an ungated +// POPCNT would be SIGILL rather than a fallback — so the count dispatch +// checks both and drops to the SWAR path if either is missing. +var hasPOPCNT = cpu.X86.HasPOPCNT diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/cpu_other.go b/src/vendor/github.com/gofiber/utils/v2/simd/cpu_other.go new file mode 100644 index 00000000..f9de7075 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/cpu_other.go @@ -0,0 +1,7 @@ +//go:build !amd64 + +package simd + +// hasAVX2 is constant false off amd64, letting the compiler prune the +// accelerated branches entirely. +const hasAVX2 = false diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr.go new file mode 100644 index 00000000..8a536b71 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr.go @@ -0,0 +1,242 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +import ( + "bytes" + + "github.com/gofiber/utils/v2/swar" +) + +// The portable fallbacks below are composed from the swar package's +// primitives rather than re-deriving the bit tricks; see swar's package +// documentation for the ZeroLanes contract the first-match scans rely on +// (false positives only above the first true match, so the first set lane +// is always exact). + +// Memchr2 returns the index of the first occurrence in haystack of either +// needle1 or needle2, or -1 if neither is present. Both needles are checked +// in the same pass, so it costs the same as a single-byte scan. +// +// There is deliberately no single-needle Memchr: use bytes.IndexByte, which +// the Go runtime already accelerates on all major architectures. +func Memchr2(haystack []byte, needle1, needle2 byte) int { + if len(haystack) == 0 { + return -1 + } + return memchr2Impl(haystack, needle1, needle2) +} + +// Memchr3 returns the index of the first occurrence in haystack of needle1, +// needle2, or needle3, or -1 if none is present. All three needles are +// checked in the same pass. +func Memchr3(haystack []byte, needle1, needle2, needle3 byte) int { + if len(haystack) == 0 { + return -1 + } + return memchr3Impl(haystack, needle1, needle2, needle3) +} + +// MemchrPair returns the first index i such that haystack[i] == byte1 and +// haystack[i+offset] == byte2, or -1 if no such position exists. offset must +// be >= 0; a negative offset returns -1. +// +// Requiring two bytes at a fixed distance makes the scan far more selective +// than a single-byte search, which is what makes it a good substring +// prefilter: false candidates need both bytes at exactly the right distance. +// Memmem uses it for short needles. +func MemchrPair(haystack []byte, byte1, byte2 byte, offset int) int { + if offset < 0 || len(haystack) <= offset { + return -1 + } + if offset == 0 { + // Both bytes would occupy the same position, so they must be equal. + if byte1 != byte2 { + return -1 + } + return bytes.IndexByte(haystack, byte1) + } + return memchrPairImpl(haystack, byte1, byte2, offset) +} + +// memchr2Generic is the portable SWAR fallback for Memchr2: a ZeroLanes +// first-match scan over both needle broadcasts, finishing 8+ byte inputs +// with one overlapping word at n-8 (already-scanned lanes are known +// non-matching, so the first set lane falls in the new bytes). +func memchr2Generic(haystack []byte, needle1, needle2 byte) int { + n := len(haystack) + if n < swar.WordLen { + for i := range n { + if haystack[i] == needle1 || haystack[i] == needle2 { + return i + } + } + return -1 + } + + bc1 := swar.Broadcast(needle1) + bc2 := swar.Broadcast(needle2) + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + // Pinned window: see the note above isASCIIGeneric in ascii.go for + // why the loads use constant offsets into it. + win := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + w0, w1 := swar.Load8(win, 0), swar.Load8(win, swar.WordLen) + m0 := swar.ZeroLanes(w0^bc1) | swar.ZeroLanes(w0^bc2) + m1 := swar.ZeroLanes(w1^bc1) | swar.ZeroLanes(w1^bc2) + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + w := swar.Load8(haystack, i) + if m := swar.ZeroLanes(w^bc1) | swar.ZeroLanes(w^bc2); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + w := swar.Load8(haystack, n-swar.WordLen) + if m := swar.ZeroLanes(w^bc1) | swar.ZeroLanes(w^bc2); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} + +// memchr3Generic is the portable SWAR fallback for Memchr3; see +// memchr2Generic for the scan shape. +func memchr3Generic(haystack []byte, needle1, needle2, needle3 byte) int { + n := len(haystack) + if n < swar.WordLen { + for i := range n { + if haystack[i] == needle1 || haystack[i] == needle2 || haystack[i] == needle3 { + return i + } + } + return -1 + } + + bc1 := swar.Broadcast(needle1) + bc2 := swar.Broadcast(needle2) + bc3 := swar.Broadcast(needle3) + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + win := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + w0, w1 := swar.Load8(win, 0), swar.Load8(win, swar.WordLen) + m0 := swar.ZeroLanes(w0^bc1) | swar.ZeroLanes(w0^bc2) | swar.ZeroLanes(w0^bc3) + m1 := swar.ZeroLanes(w1^bc1) | swar.ZeroLanes(w1^bc2) | swar.ZeroLanes(w1^bc3) + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + w := swar.Load8(haystack, i) + if m := swar.ZeroLanes(w^bc1) | swar.ZeroLanes(w^bc2) | swar.ZeroLanes(w^bc3); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + w := swar.Load8(haystack, n-swar.WordLen) + if m := swar.ZeroLanes(w^bc1) | swar.ZeroLanes(w^bc2) | swar.ZeroLanes(w^bc3); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} + +// memchrPairGeneric is the portable SWAR fallback for MemchrPair. It leans +// on ZeroLanes flagging every true zero lane (part of its contract), so +// ANDing the two per-position masks can never drop a real pair; what the +// AND does lose is lane exactness — a flagged lane may be a false +// candidate sitting strictly below the first true pair — so every +// candidate is re-verified scalar and refuted ones are stepped past. +// ZeroLanes plus this rare verify step beats a pair of exact +// swar.MatchByteMask masks on the no-candidate fast path, which is the +// common case. The caller guarantees offset >= 1 and +// len(haystack) > offset. +// +// The scan runs over the candidate positions 0..len-offset-1: two words +// per branch through pinned windows (see ascii.go), then one word, then +// one overlapping word ending at the last candidate. Positions below the +// overlap were either never flagged or refuted by the verify step, so +// both are known non-pairs and any candidate the overlap flags there +// fails verification harmlessly; the first candidate to verify is the +// first pair. An earlier version loaded both words of every step through +// swar.Load8 at variable offsets and finished the last 1-7 positions +// scalar, which at 32 bytes ran no faster than a plain scalar loop. +func memchrPairGeneric(haystack []byte, byte1, byte2 byte, offset int) int { + n := len(haystack) + if n < swar.WordLen+offset { + for i := 0; i+offset < n; i++ { + if haystack[i] == byte1 && haystack[i+offset] == byte2 { + return i + } + } + return -1 + } + + bc1 := swar.Broadcast(byte1) + bc2 := swar.Broadcast(byte2) + last := n - offset // candidate positions are 0..last-1 + i := 0 + for ; i+2*swar.WordLen <= last; i += 2 * swar.WordLen { + a := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + b := haystack[i+offset : i+offset+2*swar.WordLen : i+offset+2*swar.WordLen] + c0 := swar.ZeroLanes(swar.Load8(a, 0)^bc1) & swar.ZeroLanes(swar.Load8(b, 0)^bc2) + c1 := swar.ZeroLanes(swar.Load8(a, swar.WordLen)^bc1) & swar.ZeroLanes(swar.Load8(b, swar.WordLen)^bc2) + if c0|c1 != 0 { + if pos := verifyPairCandidates(haystack, byte1, byte2, offset, i, c0); pos >= 0 { + return pos + } + if pos := verifyPairCandidates(haystack, byte1, byte2, offset, i+swar.WordLen, c1); pos >= 0 { + return pos + } + } + } + for ; i+swar.WordLen <= last; i += swar.WordLen { + a := haystack[i : i+swar.WordLen : i+swar.WordLen] + b := haystack[i+offset : i+offset+swar.WordLen : i+offset+swar.WordLen] + c := swar.ZeroLanes(swar.Load8(a, 0)^bc1) & swar.ZeroLanes(swar.Load8(b, 0)^bc2) + if c != 0 { + if pos := verifyPairCandidates(haystack, byte1, byte2, offset, i, c); pos >= 0 { + return pos + } + } + } + if i == last { + return -1 + } + i = last - swar.WordLen + a := haystack[i : i+swar.WordLen : i+swar.WordLen] + b := haystack[i+offset : i+offset+swar.WordLen : i+offset+swar.WordLen] + c := swar.ZeroLanes(swar.Load8(a, 0)^bc1) & swar.ZeroLanes(swar.Load8(b, 0)^bc2) + if c != 0 { + return verifyPairCandidates(haystack, byte1, byte2, offset, i, c) + } + return -1 +} + +// verifyPairCandidates checks the candidate lanes of cand, a ZeroLanes AND +// mask for the word at base, in address order and returns the first +// position that really holds byte1 and byte2 at distance offset, or -1. +// It runs only on the rare candidate path, so the scalar re-reads are +// never on the no-match loop. +func verifyPairCandidates(haystack []byte, byte1, byte2 byte, offset, base int, cand uint64) int { + for ; cand != 0; cand &= cand - 1 { + pos := base + swar.FirstLane(cand) + if haystack[pos] == byte1 && haystack[pos+offset] == byte2 { + return pos + } + } + return -1 +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.go new file mode 100644 index 00000000..bc282eac --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.go @@ -0,0 +1,52 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build amd64 + +package simd + +// Assembly kernels implemented in memchr_amd64.s. Each consumes four +// 32-byte AVX2 vectors per iteration (OR-ing the per-vector match masks so +// a 128-byte block needs one extraction and one branch), drops to a +// 32-byte loop for the remainder, and finishes the last 1-31 positions +// with an overlapping rescan: memchr2 and memchr3 reload one 32-byte +// vector ending at the buffer end, while memchrPair reloads both of its +// windows — the byte1 side ending at len-offset, the byte2 side at the +// buffer end. +// +//go:noescape +func memchr2AVX2(haystack []byte, needle1, needle2 byte) int + +//go:noescape +func memchr3AVX2(haystack []byte, needle1, needle2, needle3 byte) int + +//go:noescape +func memchrPairAVX2(haystack []byte, byte1, byte2 byte, offset int) int + +// memchr2Impl dispatches to the AVX2 kernel for inputs large enough to amortize +// the vector setup. The caller guarantees a non-empty haystack. +func memchr2Impl(haystack []byte, needle1, needle2 byte) int { + if hasAVX2 && len(haystack) >= MinLen { + return memchr2AVX2(haystack, needle1, needle2) + } + return memchr2Generic(haystack, needle1, needle2) +} + +// memchr3Impl dispatches like memchr2Impl. +func memchr3Impl(haystack []byte, needle1, needle2, needle3 byte) int { + if hasAVX2 && len(haystack) >= MinLen { + return memchr3AVX2(haystack, needle1, needle2, needle3) + } + return memchr3Generic(haystack, needle1, needle2, needle3) +} + +// memchrPairImpl dispatches to the AVX2 kernel when there is room for at least +// one 32-byte vector of pair positions. The caller guarantees offset >= 1 +// and len(haystack) > offset. +func memchrPairImpl(haystack []byte, byte1, byte2 byte, offset int) int { + if hasAVX2 && len(haystack) >= MinLen+offset { + return memchrPairAVX2(haystack, byte1, byte2, offset) + } + return memchrPairGeneric(haystack, byte1, byte2, offset) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.s b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.s new file mode 100644 index 00000000..de56502c --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_amd64.s @@ -0,0 +1,570 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. +// Modified: legacy-SSE MOVD/MOVQ register moves replaced with VEX-encoded +// VMOVD/VMOVQ to avoid AVX-SSE transition penalties on Intel CPUs, the +// scalar tail loops replaced with overlapping vector rescans of the final +// window (a vector pair in memchrPairAVX2) for the MinLen+ inputs the Go +// dispatch guarantees, and the 32-byte main loops replaced with 4x +// unrolled 128-byte blocks that OR the per-vector masks together and +// extract a single VPMOVMSKB per block. + +//go:build amd64 + +#include "textflag.h" +#include "block_align_amd64.h" + +// The kernels below share one loop skeleton: +// +// 1. A 128-byte block loop, entered only while base <= end-128. Four +// vectors are compared in parallel, their match masks OR-ed together, +// and a single VPMOVMSKB tests all 128 bytes at once. The per-vector +// masks stay live, so the (rare) hit path re-extracts them in address +// order to locate the first match. This keeps the port-0-only +// VPMOVMSKB and the loop bookkeeping off the critical path: the block +// loop retires four 32-byte compares for the branch overhead of one. +// 2. A 32-byte loop for the remainder, entered while base <= end-32. +// 3. One overlapping 32-byte window ending at the buffer end for the +// last 1-31 bytes. Lanes before the current base were already +// resolved as non-matching, so the first set lane of the overlap +// always falls in the new bytes and BSF stays exact. +// +// Both loops test their bound at the bottom against a precomputed limit +// pointer, so the steady state costs one ADDQ/CMPQ/JBE instead of the +// LEAQ/CMPQ/JA/ADDQ/JMP the original 32-byte loops carried. Inputs shorter +// than one vector — unreachable through the Go dispatch, which routes them +// to the SWAR fallbacks — take the scalar tail loops. + +// func memchr2AVX2(haystack []byte, needle1, needle2 byte) int +// +// AVX2 kernel behind Memchr2 that searches for either of two bytes. +// Uses parallel comparison with two broadcast vectors and combines results +// with VPOR. +// +// Parameters (FP offsets, ABI0; the byte arguments are packed into +// adjacent 1-byte slots after the 24-byte slice header, then padded to +// align the return value): +// haystack_base+0(FP) - pointer (8 bytes) +// haystack_len+8(FP) - length (8 bytes) +// haystack_cap+16(FP) - capacity (8 bytes, unused) +// needle1+24(FP) - first needle (1 byte) +// needle2+25(FP) - second needle (1 byte, then 6 bytes padding) +// ret+32(FP) - return value (8 bytes) +// +// Total argument frame: 40 bytes (24 slice + 1 + 1 + 6 padding + 8 ret) +TEXT ·memchr2AVX2(SB), NOSPLIT, $0-40 + // Load parameters + MOVQ haystack_base+0(FP), SI + MOVQ haystack_len+8(FP), DX + MOVBQZX needle1+24(FP), AX + MOVBQZX needle2+25(FP), BX + + // Empty check + TESTQ DX, DX + JZ not_found2 + + // Broadcast both needles + VMOVD AX, X0 + VPBROADCASTB X0, Y0 // Y0 = [needle1 × 32] + VMOVD BX, X1 + VPBROADCASTB X1, Y1 // Y1 = [needle2 × 32] + + // Save start pointer and compute the end + MOVQ SI, DI + LEAQ (SI)(DX*1), R8 + + CMPQ DX, $32 + JB tail_loop2 // sub-32 direct call: scalar + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA loop32_2_entry + + BLOCKALIGN +loop128_2: + VMOVDQU (SI), Y2 + VMOVDQU 32(SI), Y3 + VMOVDQU 64(SI), Y4 + VMOVDQU 96(SI), Y5 + + VPCMPEQB Y0, Y2, Y6 + VPCMPEQB Y1, Y2, Y7 + VPOR Y6, Y7, Y2 // Y2 = matches in bytes 0-31 + VPCMPEQB Y0, Y3, Y6 + VPCMPEQB Y1, Y3, Y7 + VPOR Y6, Y7, Y3 // Y3 = matches in bytes 32-63 + VPCMPEQB Y0, Y4, Y6 + VPCMPEQB Y1, Y4, Y7 + VPOR Y6, Y7, Y4 // Y4 = matches in bytes 64-95 + VPCMPEQB Y0, Y5, Y6 + VPCMPEQB Y1, Y5, Y7 + VPOR Y6, Y7, Y5 // Y5 = matches in bytes 96-127 + + VPOR Y2, Y3, Y6 + VPOR Y4, Y5, Y7 + VPOR Y6, Y7, Y6 // Y6 = matches anywhere in the block + VPMOVMSKB Y6, CX + TESTL CX, CX + JNZ found_in_block2 + + ADDQ $128, SI + CMPQ SI, R11 + JBE loop128_2 + +loop32_2_entry: + CMPQ SI, R12 + JA last32_2 + +loop32_2: + VMOVDQU (SI), Y2 + VPCMPEQB Y0, Y2, Y3 + VPCMPEQB Y1, Y2, Y4 + VPOR Y3, Y4, Y3 + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector2 + + ADDQ $32, SI + CMPQ SI, R12 + JBE loop32_2 + +last32_2: + // Fewer than 32 bytes remain past SI; rescan the final window. + CMPQ SI, R8 + JAE not_found2 + MOVQ R12, SI + VMOVDQU (SI), Y2 + VPCMPEQB Y0, Y2, Y3 + VPCMPEQB Y1, Y2, Y4 + VPOR Y3, Y4, Y3 + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector2 + JMP not_found2 + +tail_loop2: + MOVBLZX (SI), CX + CMPB CL, AL // Compare with needle1 + JE found_scalar2 + CMPB CL, BL // Compare with needle2 + JE found_scalar2 + + INCQ SI + CMPQ SI, R8 + JB tail_loop2 + +not_found2: + MOVQ $-1, AX + MOVQ AX, ret+32(FP) + VZEROUPPER + RET + +found_in_block2: + // Locate the first hit by re-extracting the per-vector masks in + // address order; only one of the four can hold the lowest match. + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ found_in_vector2 + ADDQ $32, SI + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector2 + ADDQ $32, SI + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector2 + ADDQ $32, SI + VPMOVMSKB Y5, CX + +found_in_vector2: + BSFL CX, CX + SUBQ DI, SI + ADDQ SI, CX + MOVQ CX, ret+32(FP) + VZEROUPPER + RET + +found_scalar2: + SUBQ DI, SI + MOVQ SI, ret+32(FP) + VZEROUPPER + RET + +// func memchr3AVX2(haystack []byte, needle1, needle2, needle3 byte) int +// +// AVX2 kernel behind Memchr3 that searches for any of three bytes. Same +// skeleton as memchr2AVX2 with a third broadcast/compare. +// +// Parameters (FP offsets, ABI0; byte arguments packed into adjacent 1-byte +// slots after the slice header, then padded): +// haystack_base+0(FP) - pointer (8 bytes) +// haystack_len+8(FP) - length (8 bytes) +// haystack_cap+16(FP) - capacity (8 bytes, unused) +// needle1+24(FP) - first needle (1 byte) +// needle2+25(FP) - second needle (1 byte) +// needle3+26(FP) - third needle (1 byte, then 5 bytes padding) +// ret+32(FP) - return value (8 bytes) +// +// Total argument frame: 40 bytes (24 slice + 3 + 5 padding + 8 ret) +TEXT ·memchr3AVX2(SB), NOSPLIT, $0-40 + // Load parameters + MOVQ haystack_base+0(FP), SI + MOVQ haystack_len+8(FP), DX + MOVBQZX needle1+24(FP), AX + MOVBQZX needle2+25(FP), BX + MOVBQZX needle3+26(FP), R10 + + // Empty check + TESTQ DX, DX + JZ not_found3 + + // Broadcast all three needles + VMOVD AX, X0 + VPBROADCASTB X0, Y0 // Y0 = [needle1 × 32] + VMOVD BX, X1 + VPBROADCASTB X1, Y1 // Y1 = [needle2 × 32] + VMOVD R10, X2 + VPBROADCASTB X2, Y2 // Y2 = [needle3 × 32] + + // Save start pointer and compute the end + MOVQ SI, DI + LEAQ (SI)(DX*1), R8 + + CMPQ DX, $32 + JB tail_loop3 // sub-32 direct call: scalar + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA loop32_3_entry + + BLOCKALIGN +loop128_3: + VMOVDQU (SI), Y3 + VMOVDQU 32(SI), Y4 + VMOVDQU 64(SI), Y5 + VMOVDQU 96(SI), Y6 + + VPCMPEQB Y0, Y3, Y7 + VPCMPEQB Y1, Y3, Y8 + VPCMPEQB Y2, Y3, Y9 + VPOR Y7, Y8, Y7 + VPOR Y7, Y9, Y3 // Y3 = matches in bytes 0-31 + VPCMPEQB Y0, Y4, Y7 + VPCMPEQB Y1, Y4, Y8 + VPCMPEQB Y2, Y4, Y9 + VPOR Y7, Y8, Y7 + VPOR Y7, Y9, Y4 // Y4 = matches in bytes 32-63 + VPCMPEQB Y0, Y5, Y7 + VPCMPEQB Y1, Y5, Y8 + VPCMPEQB Y2, Y5, Y9 + VPOR Y7, Y8, Y7 + VPOR Y7, Y9, Y5 // Y5 = matches in bytes 64-95 + VPCMPEQB Y0, Y6, Y7 + VPCMPEQB Y1, Y6, Y8 + VPCMPEQB Y2, Y6, Y9 + VPOR Y7, Y8, Y7 + VPOR Y7, Y9, Y6 // Y6 = matches in bytes 96-127 + + VPOR Y3, Y4, Y7 + VPOR Y5, Y6, Y8 + VPOR Y7, Y8, Y7 // Y7 = matches anywhere in the block + VPMOVMSKB Y7, CX + TESTL CX, CX + JNZ found_in_block3 + + ADDQ $128, SI + CMPQ SI, R11 + JBE loop128_3 + +loop32_3_entry: + CMPQ SI, R12 + JA last32_3 + +loop32_3: + VMOVDQU (SI), Y3 + VPCMPEQB Y0, Y3, Y4 + VPCMPEQB Y1, Y3, Y5 + VPCMPEQB Y2, Y3, Y6 + VPOR Y4, Y5, Y4 + VPOR Y4, Y6, Y4 + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector3 + + ADDQ $32, SI + CMPQ SI, R12 + JBE loop32_3 + +last32_3: + CMPQ SI, R8 + JAE not_found3 + MOVQ R12, SI + VMOVDQU (SI), Y3 + VPCMPEQB Y0, Y3, Y4 + VPCMPEQB Y1, Y3, Y5 + VPCMPEQB Y2, Y3, Y6 + VPOR Y4, Y5, Y4 + VPOR Y4, Y6, Y4 + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector3 + JMP not_found3 + +tail_loop3: + MOVBLZX (SI), CX + CMPB CL, AL // Compare with needle1 + JE found_scalar3 + CMPB CL, BL // Compare with needle2 + JE found_scalar3 + CMPB CL, R10B // Compare with needle3 + JE found_scalar3 + + INCQ SI + CMPQ SI, R8 + JB tail_loop3 + +not_found3: + MOVQ $-1, AX + MOVQ AX, ret+32(FP) + VZEROUPPER + RET + +found_in_block3: + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector3 + ADDQ $32, SI + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector3 + ADDQ $32, SI + VPMOVMSKB Y5, CX + TESTL CX, CX + JNZ found_in_vector3 + ADDQ $32, SI + VPMOVMSKB Y6, CX + +found_in_vector3: + BSFL CX, CX + SUBQ DI, SI + ADDQ SI, CX + MOVQ CX, ret+32(FP) + VZEROUPPER + RET + +found_scalar3: + SUBQ DI, SI + MOVQ SI, ret+32(FP) + VZEROUPPER + RET + +// func memchrPairAVX2(haystack []byte, byte1, byte2 byte, offset int) int +// +// AVX2 implementation of paired-byte search. Finds positions where byte1 +// appears at position i and byte2 appears at position i+offset. +// +// Algorithm: +// 1. Broadcast byte1 to YMM0, byte2 to YMM1 +// 2. For each 32-byte chunk at position p: +// - Load haystack[p:p+32], compare with byte1 → mask1 +// - Load haystack[p+offset:p+offset+32], compare with byte2 → mask2 +// - AND mask1, mask2 → combined mask (both bytes at correct distance) +// 3. First set bit in combined mask is the answer +// 4. The block loop runs the same AND over four chunk pairs at a time. +// 5. The final 1-31 pair positions are rescanned with one overlapping +// vector pair whose second load ends exactly at the buffer end; pair +// positions before it are known non-matching, so BSF stays exact. +// Inputs with fewer than offset+32 bytes — unreachable through the Go +// dispatch — take a scalar loop instead. +// +// Parameters (FP offsets, ABI0; the byte arguments are packed into +// adjacent 1-byte slots, then padded to align the int argument): +// haystack_base+0(FP) - pointer (8 bytes) +// haystack_len+8(FP) - length (8 bytes) +// haystack_cap+16(FP) - capacity (8 bytes, unused) +// byte1+24(FP) - first byte to find (1 byte) +// byte2+25(FP) - second byte to find (1 byte, then 6 bytes padding) +// offset+32(FP) - distance between byte1 and byte2 (8 bytes) +// ret+40(FP) - return value (8 bytes) +// +// Total argument frame: 48 bytes (24 slice + 1 + 1 + 6 padding + 8 + 8 ret) +TEXT ·memchrPairAVX2(SB), NOSPLIT, $0-48 + // Load parameters + MOVQ haystack_base+0(FP), SI // SI = haystack pointer + MOVQ haystack_len+8(FP), DX // DX = haystack length + MOVBQZX byte1+24(FP), AX // AX = byte1 + MOVBQZX byte2+25(FP), BX // BX = byte2 + MOVQ offset+32(FP), R10 // R10 = offset + + // Empty check and bounds check + TESTQ DX, DX + JZ not_found_pair + CMPQ R10, DX // offset >= length? + JAE not_found_pair + + // Broadcast both bytes + VMOVD AX, X0 + VPBROADCASTB X0, Y0 // Y0 = [byte1 × 32] + VMOVD BX, X1 + VPBROADCASTB X1, Y1 // Y1 = [byte2 × 32] + + // Save start pointer + MOVQ SI, DI // DI = haystack start + + // Calculate limits: + // - We need 32 bytes at position p (for byte1 check) + // - We need 32 bytes at position p+offset (for byte2 check) + // - So we need p + offset + 32 <= length + // - Which means p <= length - offset - 32 + MOVQ DX, R12 // R12 = length + SUBQ R10, R12 // R12 = length - offset + SUBQ $32, R12 // R12 = length - offset - 32 (last valid p) + JL scalar_entry_pair // sub-(offset+32) direct call: scalar + ADDQ SI, R12 // R12 = absolute last valid base + + LEAQ -96(R12), R11 // last valid 128-position block base + CMPQ SI, R11 + JA loop32_pair_entry + + BLOCKALIGN +loop128_pair: + // byte1 side: four consecutive 32-byte chunks + VMOVDQU (SI), Y2 + VMOVDQU 32(SI), Y3 + VMOVDQU 64(SI), Y4 + VMOVDQU 96(SI), Y5 + VPCMPEQB Y0, Y2, Y2 + VPCMPEQB Y0, Y3, Y3 + VPCMPEQB Y0, Y4, Y4 + VPCMPEQB Y0, Y5, Y5 + + // byte2 side: the same chunks shifted by offset + VMOVDQU (SI)(R10*1), Y6 + VMOVDQU 32(SI)(R10*1), Y7 + VMOVDQU 64(SI)(R10*1), Y8 + VMOVDQU 96(SI)(R10*1), Y9 + VPCMPEQB Y1, Y6, Y6 + VPCMPEQB Y1, Y7, Y7 + VPCMPEQB Y1, Y8, Y8 + VPCMPEQB Y1, Y9, Y9 + + VPAND Y2, Y6, Y2 // Y2 = pairs in positions 0-31 + VPAND Y3, Y7, Y3 // Y3 = pairs in positions 32-63 + VPAND Y4, Y8, Y4 // Y4 = pairs in positions 64-95 + VPAND Y5, Y9, Y5 // Y5 = pairs in positions 96-127 + + VPOR Y2, Y3, Y6 + VPOR Y4, Y5, Y7 + VPOR Y6, Y7, Y6 + VPMOVMSKB Y6, CX + TESTL CX, CX + JNZ found_in_block_pair + + ADDQ $128, SI + CMPQ SI, R11 + JBE loop128_pair + +loop32_pair_entry: + CMPQ SI, R12 + JA vector_tail_pair + +loop32_pair: + // Load 32 bytes at position p (for byte1) and at p+offset (for byte2) + VMOVDQU (SI), Y2 // Y2 = haystack[p:p+32] + VMOVDQU (SI)(R10*1), Y3 // Y3 = haystack[p+offset:p+offset+32] + VPCMPEQB Y0, Y2, Y4 // Y4 = positions where haystack[p+k] == byte1 + VPCMPEQB Y1, Y3, Y5 // Y5 = positions where haystack[p+offset+k] == byte2 + + // AND the results: bit k is set only if: + // - haystack[p+k] == byte1 + // - haystack[p+offset+k] == byte2 + VPAND Y4, Y5, Y4 // Y4 = combined mask + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector_pair + + ADDQ $32, SI + CMPQ SI, R12 + JBE loop32_pair + +vector_tail_pair: + // Fewer than 32 pair positions remain past SI. If any do, rescan the + // final 32-position window based at R12 = base+len-offset-32: its second + // load ends exactly at the buffer end, and pair positions before SI are + // known non-matching. + LEAQ (DI)(DX*1), R9 // R9 = buffer end + SUBQ R10, R9 // R9 = end of valid pair positions + CMPQ SI, R9 + JAE not_found_pair + MOVQ R12, SI // SI = base of the final window + VMOVDQU (SI), Y2 + VMOVDQU (SI)(R10*1), Y3 + VPCMPEQB Y0, Y2, Y4 + VPCMPEQB Y1, Y3, Y5 + VPAND Y4, Y5, Y4 + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector_pair + JMP not_found_pair + +scalar_entry_pair: + // Scalar path for direct calls with fewer than offset+32 bytes. + LEAQ (DI)(DX*1), R8 // R8 = end pointer + +tail_loop_pair: + // Check if SI + offset < end + LEAQ (SI)(R10*1), R9 // R9 = SI + offset + CMPQ R9, R8 + JAE not_found_pair // If SI + offset >= end, we're done + + // Load and compare both bytes + MOVBLZX (SI), CX // CX = haystack[SI] + CMPB CL, AL // Compare with byte1 + JNE tail_next_pair // Not byte1, skip + + // byte1 matches, check byte2 + MOVBLZX (SI)(R10*1), CX // CX = haystack[SI + offset] + CMPB CL, BL // Compare with byte2 + JE found_scalar_pair // Both match! + +tail_next_pair: + INCQ SI + JMP tail_loop_pair + +not_found_pair: + MOVQ $-1, AX + MOVQ AX, ret+40(FP) + VZEROUPPER + RET + +found_in_block_pair: + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ found_in_vector_pair + ADDQ $32, SI + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector_pair + ADDQ $32, SI + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector_pair + ADDQ $32, SI + VPMOVMSKB Y5, CX + +found_in_vector_pair: + // Match found in vector! CX contains mask + BSFL CX, CX // CX = index of first set bit (0-31) + SUBQ DI, SI // SI = offset from start to current chunk + ADDQ SI, CX // CX = absolute index + MOVQ CX, ret+40(FP) + VZEROUPPER + RET + +found_scalar_pair: + SUBQ DI, SI + MOVQ SI, ret+40(FP) + VZEROUPPER + RET diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class.go new file mode 100644 index 00000000..95889a61 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class.go @@ -0,0 +1,177 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +import ( + "github.com/gofiber/utils/v2/swar" +) + +// MemchrWord returns the index of the first word character — 'A'..'Z', +// 'a'..'z', '0'..'9', or '_' (the regex \w class) — in haystack, or -1 if +// none is present. +func MemchrWord(haystack []byte) int { + if len(haystack) == 0 { + return -1 + } + return memchrWordImpl(haystack) +} + +// MemchrNotWord is the complement of MemchrWord: it returns the index of the +// first byte that is NOT a word character, or -1 if every byte is one. +func MemchrNotWord(haystack []byte) int { + if len(haystack) == 0 { + return -1 + } + return memchrNotWordImpl(haystack) +} + +// MemchrInTable returns the index of the first byte b of haystack with +// table[b] true, or -1 if none matches or table is nil. +// +// This is a plain scalar table scan on every architecture — an arbitrary +// 256-entry membership test has no cheap SIMD or SWAR form — so unlike the +// rest of this package it carries no acceleration. For the \w class +// specifically, MemchrWord is much faster. +func MemchrInTable(haystack []byte, table *[256]bool) int { + if table == nil { + return -1 + } + for i, b := range haystack { + if table[b] { + return i + } + } + return -1 +} + +// MemchrNotInTable is the complement of MemchrInTable: it returns the index +// of the first byte b with table[b] false, or -1 if every byte is in the +// table or table is nil. Like MemchrInTable it is a plain scalar loop on +// every architecture. +func MemchrNotInTable(haystack []byte, table *[256]bool) int { + if table == nil { + return -1 + } + for i, b := range haystack { + if !table[b] { + return i + } + } + return -1 +} + +// isWordChar reports whether b is in [A-Za-z0-9_]. +func isWordChar(b byte) bool { + return (b >= 'A' && b <= 'Z') || + (b >= 'a' && b <= 'z') || + (b >= '0' && b <= '9') || + b == '_' +} + +// wordMask flags the lanes of w holding word characters, exactly per lane; +// bytes >= 0x80 never match. It is the swar.MatchRangeMask construction +// with the three range tests fused into one expression: +// +// - the ASCII gate (&^ w & HighBits) is applied once to the OR of the +// tests instead of once per test; +// - 'A'..'Z' and 'a'..'z' collapse into a single 'a'..'z' test on a +// case-folded copy (bit 5 set in every lane), which maps exactly the +// two letter ranges onto 0x61..0x7A; +// - '_' (0x5F) is the only byte besides DEL (0x7F) that folds to 0x7F, +// so "folded lane == 0x7F" is one biased add, and the DEL lanes are +// removed by w<<2, which moves each lane's bit 5 — clear for '_', set +// for DEL — into the bit-7 marker position. +// +// Every addition below adds a per-lane bias of at most 0x50 to lanes that +// are at most 0x7F, so no lane can carry into its neighbor and the bit-7 +// markers stay exact. That is 15 ALU operations per word instead of 26 +// for the four separate masks. +func wordMask(w uint64) uint64 { + b := w & swar.LowSeven + bf := b | 0x20*swar.Ones + letters := (bf + (0x80-'a')*swar.Ones) &^ (bf + (0x80-'z'-1)*swar.Ones) + digits := (b + (0x80-'0')*swar.Ones) &^ (b + (0x80-'9'-1)*swar.Ones) + underscore := (bf + swar.Ones) &^ (w << 2) + return (letters | digits | underscore) &^ w & swar.HighBits +} + +// memchrWordGeneric is the portable SWAR fallback for MemchrWord, finishing +// 8+ byte inputs with one overlapping word at n-8. +func memchrWordGeneric(haystack []byte) int { + n := len(haystack) + if n < swar.WordLen { + for i := range n { + if isWordChar(haystack[i]) { + return i + } + } + return -1 + } + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + // Pinned window: see the note above isASCIIGeneric in ascii.go for + // why the loads use constant offsets into it. + w := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + m0 := wordMask(swar.Load8(w, 0)) + m1 := wordMask(swar.Load8(w, swar.WordLen)) + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m := wordMask(swar.Load8(haystack, i)); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + if m := wordMask(swar.Load8(haystack, n-swar.WordLen)); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} + +// memchrNotWordGeneric is the portable SWAR fallback for MemchrNotWord. +// wordMask is exact per lane, so its complement within the 0x80 lane +// markers is exact as well. +func memchrNotWordGeneric(haystack []byte) int { + n := len(haystack) + if n < swar.WordLen { + for i := range n { + if !isWordChar(haystack[i]) { + return i + } + } + return -1 + } + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + w := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + m0 := swar.HighBits &^ wordMask(swar.Load8(w, 0)) + m1 := swar.HighBits &^ wordMask(swar.Load8(w, swar.WordLen)) + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m := swar.HighBits &^ wordMask(swar.Load8(haystack, i)); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + if m := swar.HighBits &^ wordMask(swar.Load8(haystack, n-swar.WordLen)); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.go new file mode 100644 index 00000000..1a331a4d --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.go @@ -0,0 +1,35 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build amd64 + +package simd + +// Assembly kernels implemented in memchr_class_amd64.s. Class membership +// is computed with a pair of VPSHUFB nibble lookups instead of one +// clamp-and-compare per range, and four 32-byte vectors are classified per +// iteration. +// +//go:noescape +func memchrWordAVX2(haystack []byte) int + +//go:noescape +func memchrNotWordAVX2(haystack []byte) int + +// memchrWordImpl dispatches to the AVX2 kernel for inputs large enough to +// amortize the vector setup. The caller guarantees a non-empty haystack. +func memchrWordImpl(haystack []byte) int { + if hasAVX2 && len(haystack) >= MinLen { + return memchrWordAVX2(haystack) + } + return memchrWordGeneric(haystack) +} + +// memchrNotWordImpl dispatches like memchrWordImpl. +func memchrNotWordImpl(haystack []byte) int { + if hasAVX2 && len(haystack) >= MinLen { + return memchrNotWordAVX2(haystack) + } + return memchrNotWordGeneric(haystack) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.s b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.s new file mode 100644 index 00000000..5faee304 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_amd64.s @@ -0,0 +1,417 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. +// Modified: legacy-SSE MOVD/MOVQ register moves replaced with VEX-encoded +// VMOVD/VMOVQ to avoid AVX-SSE transition penalties on Intel CPUs, the +// scalar tail loops replaced with one overlapping vector at the buffer end +// for the MinLen+ inputs the Go dispatch guarantees, the per-range +// clamp-and-compare classifier replaced with a nibble table lookup, the +// 32-byte main loops replaced with 4x unrolled 128-byte blocks, and the +// block test reduced to one compare over the four raw class values. + +//go:build amd64 + +#include "textflag.h" +#include "block_align_amd64.h" + +// Classifying \w = [A-Za-z0-9_] with unsigned clamp-and-compare costs three +// VPMINUB/VPMAXUB/VPCMPEQB triples plus a VPCMPEQB for '_' and three VPORs: +// thirteen vector ops per 32 bytes, ten of them on the two general vector +// ALU ports. A nibble table does the same job in six (five in the block +// loops, which defer the compare to the reduced block value), and the two +// VPSHUFBs it adds run on the otherwise idle shuffle port. +// +// The table splits each byte into its high and low nibble. Every high +// nibble that contains word characters gets one bit: +// +// 0x3_ -> 0x01 0x4_ -> 0x02 0x5_ -> 0x04 0x6_ -> 0x08 0x7_ -> 0x10 +// +// and each low-nibble entry carries the set of high-nibble rows in which +// that low nibble is a word character, so a byte is a word character +// exactly when lowTable[lo] & highTable[hi] != 0: +// +// lo 0x0 -> 0x15 ('0', 'P', 'p') +// lo 0x1..0x9 -> 0x1F (digits and letters in every row) +// lo 0xA -> 0x1E ('J', 'Z', 'j', 'z' but not ':') +// lo 0xB..0xE -> 0x0A ('K'..'N', 'k'..'n' only) +// lo 0xF -> 0x0E ('O', '_', 'o') +// +// Bytes >= 0x80 need no separate guard: VPSHUFB zeroes any lane whose +// index byte has bit 7 set, so the low-nibble lookup already returns 0 for +// them and they classify as non-word, matching the SWAR fallback. +// +// Both kernels compute the same per-lane class value: the AND of the two +// lookups, which is nonzero exactly in the word-character lanes. The +// 32-byte paths compare it against zero at once, giving the "not a word +// character" mask (0xFF per non-word lane) that VPMOVMSKB can extract; +// memchrNotWord scans those bits directly and memchrWord inverts them +// with a single NOTL. The block loops instead reduce the four raw class +// values first and compare only the reduction: memchrNotWord takes the +// per-lane minimum (zero exactly where some vector has a non-word lane), +// memchrWord the per-lane OR (nonzero exactly where some vector has a +// word lane). That is three reductions and one compare per block instead +// of four compares and three reductions, and the four raw values stay +// live so the (rare) hit path can still compare them one at a time. + +// WORDBITS leaves in dst the class value of every lane of src: nonzero +// for a word character, zero otherwise. t0 is scratch; dst may alias src. +#define WORDBITS(src, dst, t0) \ + VPSRLW $4, src, t0; \ + VPAND Y2, t0, t0; \ + VPSHUFB t0, Y1, t0; \ + VPSHUFB src, Y0, dst; \ + VPAND t0, dst, dst + +// NOTWORD leaves in dst a mask with 0xFF in every lane of src that is NOT +// a word character. t0 is scratch; dst may alias src. +#define NOTWORD(src, dst, t0) \ + WORDBITS(src, dst, t0); \ + VPCMPEQB Y3, dst, dst + +// SETUPTABLES loads the nibble tables, the low-nibble mask and a zero +// vector into Y0-Y3. The tables are built from immediates rather than a +// RODATA section so the kernels stay position-independent and free of +// relocations. +#define SETUPTABLES \ + MOVQ $0x1F1F1F1F1F1F1F15, AX; \ + VMOVQ AX, X0; \ + MOVQ $0x0E0A0A0A0A1E1F1F, AX; \ + VPINSRQ $1, AX, X0, X0; \ + VINSERTI128 $1, X0, Y0, Y0; \ + MOVQ $0x1008040201000000, AX; \ + VMOVQ AX, X1; \ + VINSERTI128 $1, X1, Y1, Y1; \ + MOVQ $0x0F0F0F0F0F0F0F0F, AX; \ + VMOVQ AX, X2; \ + VPBROADCASTQ X2, Y2; \ + VPXOR Y3, Y3, Y3 + +// func memchrWordAVX2(haystack []byte) int +// +// AVX2 implementation to find the first word character [A-Za-z0-9_]. +// +// Parameters: +// haystack_base+0(FP) - pointer to haystack (8 bytes) +// haystack_len+8(FP) - length (8 bytes) +// haystack_cap+16(FP) - capacity (8 bytes, unused) +// ret+24(FP) - return value (8 bytes) +// +TEXT ·memchrWordAVX2(SB), NOSPLIT, $0-32 + // Load parameters + MOVQ haystack_base+0(FP), SI // SI = haystack pointer + MOVQ haystack_len+8(FP), DX // DX = length + + // Empty check + TESTQ DX, DX + JZ word_not_found + + // Save start for offset calculation and compute the end pointer + MOVQ SI, DI // DI = start pointer + LEAQ (SI)(DX*1), R8 // R8 = end pointer + + CMPQ DX, $32 + JB word_tail_loop // sub-32 direct call: scalar + + SETUPTABLES + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA word_loop32_entry + + BLOCKALIGN_LONG +word_loop128: + VMOVDQU (SI), Y4 + VMOVDQU 32(SI), Y5 + VMOVDQU 64(SI), Y6 + VMOVDQU 96(SI), Y7 + WORDBITS(Y4, Y4, Y8) + WORDBITS(Y5, Y5, Y8) + WORDBITS(Y6, Y6, Y8) + WORDBITS(Y7, Y7, Y8) + + // A word character exists in the block iff some lane's class value is + // nonzero in some vector, so OR the four values and look for a lane + // that is not zero. + VPOR Y4, Y5, Y8 + VPOR Y6, Y7, Y9 + VPOR Y8, Y9, Y8 + VPCMPEQB Y3, Y8, Y8 + VPMOVMSKB Y8, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_block + + ADDQ $128, SI + CMPQ SI, R11 + JBE word_loop128 + +word_loop32_entry: + CMPQ SI, R12 + JA word_last32 + +word_loop32: + VMOVDQU (SI), Y4 + NOTWORD(Y4, Y4, Y8) + VPMOVMSKB Y4, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_vector + + ADDQ $32, SI + CMPQ SI, R12 + JBE word_loop32 + +word_last32: + // Fewer than 32 bytes remain past SI; rescan the final window. Lanes + // before SI were already resolved as non-matching, so BSF stays exact. + CMPQ SI, R8 + JAE word_not_found + MOVQ R12, SI + VMOVDQU (SI), Y4 + NOTWORD(Y4, Y4, Y8) + VPMOVMSKB Y4, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_vector + JMP word_not_found + +word_tail_loop: + MOVBLZX (SI), AX // AX = byte + + // Check [A-Z]: 65 <= b <= 90 + CMPB AL, $65 + JB word_check_lower + CMPB AL, $90 + JBE word_found_scalar + +word_check_lower: + // Check [a-z]: 97 <= b <= 122 + CMPB AL, $97 + JB word_check_digit + CMPB AL, $122 + JBE word_found_scalar + +word_check_digit: + // Check [0-9]: 48 <= b <= 57 + CMPB AL, $48 + JB word_check_underscore + CMPB AL, $57 + JBE word_found_scalar + +word_check_underscore: + // Check '_': 95 + CMPB AL, $95 + JE word_found_scalar + + // Not a word char, continue + INCQ SI + CMPQ SI, R8 + JB word_tail_loop + +word_not_found: + MOVQ $-1, AX + MOVQ AX, ret+24(FP) + VZEROUPPER + RET + +word_found_in_block: + // Locate the first hit by comparing and extracting the per-vector + // class values in address order; only one of the four can hold the + // lowest match. + VPCMPEQB Y3, Y4, Y4 + VPMOVMSKB Y4, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y5, Y5 + VPMOVMSKB Y5, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y6, Y6 + VPMOVMSKB Y6, CX + NOTL CX + TESTL CX, CX + JNZ word_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y7, Y7 + VPMOVMSKB Y7, CX + NOTL CX + +word_found_in_vector: + BSFL CX, BX + SUBQ DI, SI // SI = offset to chunk start + ADDQ SI, BX // BX = absolute position + MOVQ BX, ret+24(FP) + VZEROUPPER + RET + +word_found_scalar: + SUBQ DI, SI + MOVQ SI, ret+24(FP) + VZEROUPPER + RET + +// func memchrNotWordAVX2(haystack []byte) int +// +// AVX2 implementation to find the first non-word character, the complement +// of memchrWordAVX2. The nibble classifier already produces the non-word +// mask directly, so this kernel skips the NOTL memchrWordAVX2 needs. +// +TEXT ·memchrNotWordAVX2(SB), NOSPLIT, $0-32 + // Load parameters + MOVQ haystack_base+0(FP), SI + MOVQ haystack_len+8(FP), DX + + // Empty check + TESTQ DX, DX + JZ notword_not_found + + // Save start for offset calculation and compute the end pointer + MOVQ SI, DI + LEAQ (SI)(DX*1), R8 + + CMPQ DX, $32 + JB notword_tail_loop // sub-32 direct call: scalar + + SETUPTABLES + + LEAQ -32(R8), R12 + LEAQ -128(R8), R11 + CMPQ SI, R11 + JA notword_loop32_entry + + BLOCKALIGN_LONG +notword_loop128: + VMOVDQU (SI), Y4 + VMOVDQU 32(SI), Y5 + VMOVDQU 64(SI), Y6 + VMOVDQU 96(SI), Y7 + WORDBITS(Y4, Y4, Y8) + WORDBITS(Y5, Y5, Y8) + WORDBITS(Y6, Y6, Y8) + WORDBITS(Y7, Y7, Y8) + + // A non-word character exists in the block iff some lane's class + // value is zero in some vector, so take the per-lane minimum of the + // four values and look for a zero lane. + VPMINUB Y4, Y5, Y8 + VPMINUB Y6, Y7, Y9 + VPMINUB Y8, Y9, Y8 + VPCMPEQB Y3, Y8, Y8 + VPMOVMSKB Y8, CX + TESTL CX, CX + JNZ notword_found_in_block + + ADDQ $128, SI + CMPQ SI, R11 + JBE notword_loop128 + +notword_loop32_entry: + CMPQ SI, R12 + JA notword_last32 + +notword_loop32: + VMOVDQU (SI), Y4 + NOTWORD(Y4, Y4, Y8) + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ notword_found_in_vector + + ADDQ $32, SI + CMPQ SI, R12 + JBE notword_loop32 + +notword_last32: + CMPQ SI, R8 + JAE notword_not_found + MOVQ R12, SI + VMOVDQU (SI), Y4 + NOTWORD(Y4, Y4, Y8) + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ notword_found_in_vector + JMP notword_not_found + +notword_tail_loop: + MOVBLZX (SI), AX + + // Check if NOT a word char (inverse of word_tail_loop logic) + // Word chars: [A-Z], [a-z], [0-9], '_' + // If it's a word char, skip; if not, found + + // Check [A-Z]: 65 <= b <= 90 + CMPB AL, $65 + JB notword_check_lower_gap + CMPB AL, $90 + JBE notword_is_word // It's [A-Z], skip + +notword_check_lower_gap: + // Check [a-z]: 97 <= b <= 122 + CMPB AL, $97 + JB notword_check_digit_gap + CMPB AL, $122 + JBE notword_is_word // It's [a-z], skip + +notword_check_digit_gap: + // Check [0-9]: 48 <= b <= 57 + CMPB AL, $48 + JB notword_check_underscore_gap + CMPB AL, $57 + JBE notword_is_word // It's [0-9], skip + +notword_check_underscore_gap: + // Check '_': 95 + CMPB AL, $95 + JE notword_is_word // It's '_', skip + + // Not a word char - found! + JMP notword_found_scalar + +notword_is_word: + // It's a word char, continue searching + INCQ SI + CMPQ SI, R8 + JB notword_tail_loop + +notword_not_found: + MOVQ $-1, AX + MOVQ AX, ret+24(FP) + VZEROUPPER + RET + +notword_found_in_block: + VPCMPEQB Y3, Y4, Y4 + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ notword_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y5, Y5 + VPMOVMSKB Y5, CX + TESTL CX, CX + JNZ notword_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y6, Y6 + VPMOVMSKB Y6, CX + TESTL CX, CX + JNZ notword_found_in_vector + ADDQ $32, SI + VPCMPEQB Y3, Y7, Y7 + VPMOVMSKB Y7, CX + +notword_found_in_vector: + BSFL CX, BX + SUBQ DI, SI + ADDQ SI, BX + MOVQ BX, ret+24(FP) + VZEROUPPER + RET + +notword_found_scalar: + SUBQ DI, SI + MOVQ SI, ret+24(FP) + VZEROUPPER + RET diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_other.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_other.go new file mode 100644 index 00000000..2cd88cf7 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_class_other.go @@ -0,0 +1,17 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build !amd64 + +package simd + +// The portable implementations are the only ones off amd64. + +func memchrWordImpl(haystack []byte) int { + return memchrWordGeneric(haystack) +} + +func memchrNotWordImpl(haystack []byte) int { + return memchrNotWordGeneric(haystack) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit.go new file mode 100644 index 00000000..02947406 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit.go @@ -0,0 +1,79 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +import ( + "github.com/gofiber/utils/v2/swar" +) + +// MemchrDigit returns the index of the first ASCII digit '0'..'9' in +// haystack, or -1 if no digit is present. Only ASCII digits match; Unicode +// digit characters do not. +// +// On amd64 with AVX2 the range check runs on 32 bytes per vector, four +// vectors per iteration, which is useful for locating numeric fields +// (ports, lengths, IP octets) in request data. +func MemchrDigit(haystack []byte) int { + if len(haystack) == 0 { + return -1 + } + return memchrDigitImpl(haystack) +} + +// MemchrDigitAt is MemchrDigit(haystack[at:]) with the result translated +// back to an absolute index in haystack. It returns -1 when no digit is +// found or when at is out of bounds. +func MemchrDigitAt(haystack []byte, at int) int { + if at < 0 || at >= len(haystack) { + return -1 + } + pos := MemchrDigit(haystack[at:]) + if pos < 0 { + return -1 + } + return pos + at +} + +// memchrDigitGeneric is the portable SWAR fallback for MemchrDigit: a +// MatchRangeMask first-match scan (exact per lane; bytes >= 0x80 never +// match), two words per branch, finishing 8+ byte inputs with one +// overlapping word at n-8. +func memchrDigitGeneric(haystack []byte) int { + n := len(haystack) + if n < swar.WordLen { + for i, b := range haystack { + if b >= '0' && b <= '9' { + return i + } + } + return -1 + } + i := 0 + for ; i+2*swar.WordLen <= n; i += 2 * swar.WordLen { + // Pinned window: see the note above isASCIIGeneric in ascii.go for + // why the loads use constant offsets into it. + w := haystack[i : i+2*swar.WordLen : i+2*swar.WordLen] + m0 := swar.MatchRangeMask(swar.Load8(w, 0), '0', '9') + m1 := swar.MatchRangeMask(swar.Load8(w, swar.WordLen), '0', '9') + if m0|m1 != 0 { + if m0 != 0 { + return i + swar.FirstLane(m0) + } + return i + swar.WordLen + swar.FirstLane(m1) + } + } + for ; i+swar.WordLen <= n; i += swar.WordLen { + if m := swar.MatchRangeMask(swar.Load8(haystack, i), '0', '9'); m != 0 { + return i + swar.FirstLane(m) + } + } + if i == n { + return -1 + } + if m := swar.MatchRangeMask(swar.Load8(haystack, n-swar.WordLen), '0', '9'); m != 0 { + return n - swar.WordLen + swar.FirstLane(m) + } + return -1 +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.go new file mode 100644 index 00000000..13de5cc1 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.go @@ -0,0 +1,23 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build amd64 + +package simd + +// memchrDigitAVX2 is implemented in memchr_digit_amd64.s. It finds bytes in +// ['0','9'] with one biased VPADDB and one signed VPCMPGTB per vector, four +// 32-byte vectors per iteration. +// +//go:noescape +func memchrDigitAVX2(haystack []byte) int + +// memchrDigitImpl dispatches to the AVX2 kernel for inputs large enough to +// amortize the vector setup. The caller guarantees a non-empty haystack. +func memchrDigitImpl(haystack []byte) int { + if hasAVX2 && len(haystack) >= MinLen { + return memchrDigitAVX2(haystack) + } + return memchrDigitGeneric(haystack) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.s b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.s new file mode 100644 index 00000000..69fe0eb7 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_amd64.s @@ -0,0 +1,192 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. +// Modified: legacy-SSE MOVD/MOVQ register moves replaced with VEX-encoded +// VMOVD/VMOVQ to avoid AVX-SSE transition penalties on Intel CPUs, the +// scalar tail loop replaced with one overlapping vector at the buffer end +// for the MinLen+ inputs the Go dispatch guarantees, and the 32-byte main +// loop replaced with a 4x unrolled 128-byte block. + +//go:build amd64 + +#include "textflag.h" +#include "block_align_amd64.h" + +// DIGITS leaves in dst a mask with 0xFF in every lane of src holding an +// ASCII digit. t0 is scratch; dst may alias src. +// +// Y0 = [0x46 x 32] (0x7F - '9') Y1 = [0x75 x 32] ('0' + 0x46 - 1) +// +// A range test needs only one compare when the range is first slid up +// against the signed maximum: adding 0x46 maps '0'..'9' onto 0x76..0x7F, +// the ten largest positive int8 values, so a signed "> 0x75" is exact for +// every byte value. Everything above '9' lands in 0x80..0xFF and reads as +// negative, everything below '0' stays at or under 0x75, and the byte +// values from 0xBA up wrap around to 0x00..0x45, still under the +// threshold. The earlier two-compare form (> 0x2F, then not > 0x39, AND-ed +// with VPANDN) cost three vector ops and two scratch registers per vector; +// this is two ops and one. +#define DIGITS(src, dst, t0) \ + VPADDB Y0, src, t0; \ + VPCMPGTB Y1, t0, dst + +// func memchrDigitAVX2(haystack []byte) int +// +// AVX2 implementation of digit search that finds the first ASCII digit [0-9]. +// +// Algorithm for range check [0-9] (bytes 0x30-0x39): +// 1. Broadcast the 0x46 bias and the 0x75 threshold to YMM registers +// 2. Load 32 bytes from haystack +// 3. VPADDB: slide the digit range up to 0x76..0x7F +// 4. VPCMPGTB: signed compare against 0x75 (see DIGITS above) +// 5. VPMOVMSKB: extract 32-bit mask +// 6. BSFL: find first set bit +// +// The block loop runs steps 2-4 over four vectors, ORs the four masks and +// extracts once; the (rare) hit path re-extracts the per-vector masks in +// address order to locate the first digit. +// +// Parameters (FP offsets): +// haystack_base+0(FP) - pointer to haystack data (8 bytes) +// haystack_len+8(FP) - haystack length (8 bytes) +// haystack_cap+16(FP) - haystack capacity (8 bytes, unused but part of slice) +// ret+24(FP) - return value: index or -1 (8 bytes) +// +// Total argument frame size: 32 bytes (8+8+8+8) +TEXT ·memchrDigitAVX2(SB), NOSPLIT, $0-32 + // Load parameters + MOVQ haystack_base+0(FP), SI // SI = haystack pointer + MOVQ haystack_len+8(FP), DX // DX = haystack length + + // Empty haystack check + TESTQ DX, DX + JZ not_found + + // Prepare constants for range check ['0'-'9'] = [0x30-0x39]: + // the bias that slides the range up to 0x76..0x7F and the signed + // threshold just below it. + MOVQ $0x4646464646464646, AX + VMOVQ AX, X0 + VPBROADCASTQ X0, Y0 // Y0 = [0x46 x 32] + + MOVQ $0x7575757575757575, AX + VMOVQ AX, X1 + VPBROADCASTQ X1, Y1 // Y1 = [0x75 x 32] + + // Save start pointer for offset calculation, compute the end pointer + MOVQ SI, DI // DI = haystack start (preserved) + LEAQ (SI)(DX*1), R8 // R8 = SI + length (end pointer) + + CMPQ DX, $32 + JB tail_loop // sub-32 direct call: scalar + + LEAQ -32(R8), R12 // last valid 32-byte window base + LEAQ -128(R8), R11 // last valid 128-byte block base + CMPQ SI, R11 + JA loop32_entry + + BLOCKALIGN +loop128: + VMOVDQU (SI), Y2 + VMOVDQU 32(SI), Y3 + VMOVDQU 64(SI), Y4 + VMOVDQU 96(SI), Y5 + DIGITS(Y2, Y2, Y6) + DIGITS(Y3, Y3, Y6) + DIGITS(Y4, Y4, Y6) + DIGITS(Y5, Y5, Y6) + + VPOR Y2, Y3, Y6 + VPOR Y4, Y5, Y7 + VPOR Y6, Y7, Y6 + VPMOVMSKB Y6, CX + TESTL CX, CX + JNZ found_in_block + + ADDQ $128, SI + CMPQ SI, R11 + JBE loop128 + +loop32_entry: + CMPQ SI, R12 + JA last32 + +loop32: + VMOVDQU (SI), Y2 + DIGITS(Y2, Y2, Y6) + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ found_in_vector + + ADDQ $32, SI + CMPQ SI, R12 + JBE loop32 + +last32: + // Fewer than 32 bytes remain past SI; rescan the final window. Lanes + // before SI were already resolved as non-digits, so BSF stays exact. + CMPQ SI, R8 + JAE not_found + MOVQ R12, SI + VMOVDQU (SI), Y2 + DIGITS(Y2, Y2, Y6) + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ found_in_vector + JMP not_found + +tail_loop: + // Load one byte + MOVBLZX (SI), BX // BX = haystack[SI] (zero-extended) + + // Check if byte is in range ['0'-'9'] (0x30-0x39) + CMPB BL, $0x30 // Compare with '0' + JB tail_next // If < '0', not a digit + CMPB BL, $0x39 // Compare with '9' + JA tail_next // If > '9', not a digit + + // Found digit! + SUBQ DI, SI // SI = offset from start + MOVQ SI, ret+24(FP) // Return index + VZEROUPPER // Clear upper YMM bits (CRITICAL!) + RET + +tail_next: + // Advance to next byte + INCQ SI + CMPQ SI, R8 // Check if reached end + JB tail_loop // Continue if SI < end + +not_found: + // No digit found in entire haystack + MOVQ $-1, AX // Return -1 + MOVQ AX, ret+24(FP) + VZEROUPPER // Clear upper YMM bits (CRITICAL!) + RET + +found_in_block: + // Locate the first digit by re-extracting the per-vector masks in + // address order; only one of the four can hold the lowest match. + VPMOVMSKB Y2, CX + TESTL CX, CX + JNZ found_in_vector + ADDQ $32, SI + VPMOVMSKB Y3, CX + TESTL CX, CX + JNZ found_in_vector + ADDQ $32, SI + VPMOVMSKB Y4, CX + TESTL CX, CX + JNZ found_in_vector + ADDQ $32, SI + VPMOVMSKB Y5, CX + +found_in_vector: + // Digit found in vector! CX contains a 32-bit mask with set bits at + // digit positions; BSFL finds the index of the first one. + BSFL CX, BX // BX = index of first set bit (0-31) + SUBQ DI, SI // SI = offset from start to current chunk + ADDQ SI, BX // BX = absolute index + MOVQ BX, ret+24(FP) // Return index + VZEROUPPER // Clear upper YMM bits + RET diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_other.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_other.go new file mode 100644 index 00000000..9799c5f0 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_digit_other.go @@ -0,0 +1,12 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build !amd64 + +package simd + +// memchrDigitImpl uses the portable implementation off amd64. +func memchrDigitImpl(haystack []byte) int { + return memchrDigitGeneric(haystack) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memchr_other.go b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_other.go new file mode 100644 index 00000000..891be6f5 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memchr_other.go @@ -0,0 +1,21 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +//go:build !amd64 + +package simd + +// The portable SWAR implementations are the only ones off amd64. + +func memchr2Impl(haystack []byte, needle1, needle2 byte) int { + return memchr2Generic(haystack, needle1, needle2) +} + +func memchr3Impl(haystack []byte, needle1, needle2, needle3 byte) int { + return memchr3Generic(haystack, needle1, needle2, needle3) +} + +func memchrPairImpl(haystack []byte, byte1, byte2 byte, offset int) int { + return memchrPairGeneric(haystack, byte1, byte2, offset) +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/memmem.go b/src/vendor/github.com/gofiber/utils/v2/simd/memmem.go new file mode 100644 index 00000000..8059f005 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/memmem.go @@ -0,0 +1,162 @@ +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. + +package simd + +import ( + "bytes" +) + +// memmemMinPairedHaystack is the haystack size from which Memmem routes +// needles eligible for the paired prefilter through it instead of +// bytes.Index. bytes.Index brute-forces haystacks of up to 64 bytes with +// a vector kernel the prefilter cannot beat — Benchmark_Memmem_Prefilter +// shows the two level at 64B before SelectRareBytes is even paid — and +// from 65 bytes switches to a loop anchored on the needle's first byte, +// which is where a scan anchored on the needle's two rarest bytes at +// their exact distance pulls ahead. Benchmark_Memmem shows the resulting +// end-to-end routing; its 96B row is the band this constant opens up. +const memmemMinPairedHaystack = 65 + +// memmemMinSingleHaystack is the same routing point for needles that take +// the single rare-byte scan. That scan is far less selective (its false +// candidates need only one byte to match) and its verification is +// longer, so it needs more haystack to amortize the rare-byte selection +// and the candidate loop; 128 keeps a conservative margin over the band +// where Benchmark_Memmem_Prefilter's single rows trail bytes.Index. +const memmemMinSingleHaystack = 128 + +// memmemMaxPairNeedle is the needle length up to which the paired-byte +// prefilter beats a single rare-byte scan: short needles produce frequent +// single-byte false positives, and verifying them costs more than the second +// byte check saves. +const memmemMaxPairNeedle = 6 + +// memmemMaxMisses caps how many failed candidate verifications the +// prefilter loops tolerate before handing the search to bytes.Index. A +// pathological input (rare byte everywhere, long almost-matching needle) +// would otherwise cost O(len(haystack) * len(needle)); the cap bounds the +// wasted work at memmemMaxMisses needle comparisons, keeping the worst case +// at bytes.Index's O(n+m) plus a constant. +const memmemMaxMisses = 16 + +// Memmem returns the index of the first occurrence of needle in haystack, +// or -1 if needle is not present. An empty needle matches at index 0, +// mirroring bytes.Index. +// +// On amd64 with AVX2 it prefilters with the needle's rarest bytes (per +// ByteRank) and verifies only the candidate positions, which typically +// beats bytes.Index by a wide margin on large inputs: needles of 2-6 +// bytes containing two distinct byte values are scanned, on haystacks of +// 65+ bytes, for their two rarest values at the exact relative distance, +// while longer or single-valued needles are scanned, on haystacks of +// 128+ bytes, for the single rarest byte. In all other cases it delegates +// to bytes.Index directly, and the prefilter itself falls back to +// bytes.Index after a bounded number of failed candidate verifications, +// so the worst case stays within a constant of the stdlib's O(n+m). +func Memmem(haystack, needle []byte) int { + needleLen := len(needle) + if needleLen == 0 { + return 0 + } + if len(haystack) < needleLen { + return -1 + } + if needleLen == 1 { + return bytes.IndexByte(haystack, needle[0]) + } + if !hasAVX2 || len(haystack) < memmemMinPairedHaystack { + return bytes.Index(haystack, needle) + } + + var info RareByteInfo + pairable := needleLen <= memmemMaxPairNeedle + if pairable { + info = SelectRareBytes(needle) + // Distinct byte values imply distinct indices, so Byte1 != Byte2 + // alone guarantees the offset MemchrPair needs is >= 1. + if info.Byte1 != info.Byte2 { + return memmemPaired(haystack, needle, info) + } + } + if len(haystack) < memmemMinSingleHaystack { + return bytes.Index(haystack, needle) + } + if !pairable { + info = SelectRareBytes(needle) + } + return memmemSingle(haystack, needle, info.Byte1, info.Index1) +} + +// memmemPaired scans for the needle's two rarest bytes at their exact +// relative distance with MemchrPair and verifies each candidate. False +// candidates need both bytes at the right distance, so verification is +// rare; if it still misses too often, memmemFallback finishes the search. +func memmemPaired(haystack, needle []byte, info RareByteInfo) int { + byte1, idx1 := info.Byte1, info.Index1 + byte2, idx2 := info.Byte2, info.Index2 + if idx1 > idx2 { + byte1, byte2 = byte2, byte1 + idx1, idx2 = idx2, idx1 + } + offset := idx2 - idx1 + + misses := 0 + for start := 0; ; { + cand := MemchrPair(haystack[start:], byte1, byte2, offset) + if cand == -1 { + return -1 + } + // cand is the position of byte1; the needle would start idx1 earlier. + pos := start + cand - idx1 + if pos >= 0 && pos+len(needle) <= len(haystack) && + bytes.Equal(haystack[pos:pos+len(needle)], needle) { + return pos + } + start += cand + 1 + if misses++; misses >= memmemMaxMisses { + return memmemFallback(haystack, needle, start, idx1) + } + } +} + +// memmemSingle scans for the needle's rarest byte and verifies each +// candidate; for longer needles the rare byte alone is selective enough +// that the paired scan's second comparison stops paying for itself. Like +// memmemPaired it hands persistent misses to memmemFallback. +func memmemSingle(haystack, needle []byte, rareByte byte, rareIdx int) int { + misses := 0 + for start := 0; ; { + cand := bytes.IndexByte(haystack[start:], rareByte) + if cand == -1 { + return -1 + } + pos := start + cand - rareIdx + if pos >= 0 && pos+len(needle) <= len(haystack) && + bytes.Equal(haystack[pos:pos+len(needle)], needle) { + return pos + } + start += cand + 1 + if misses++; misses >= memmemMaxMisses { + return memmemFallback(haystack, needle, start, rareIdx) + } + } +} + +// memmemFallback finishes a prefiltered search with bytes.Index once the +// candidate loops exhaust their miss budget. Every anchor before start has +// been checked, and any remaining occurrence carries its anchor byte at +// anchorIdx, so it starts at or after start-anchorIdx; searching from there +// cannot skip a match or return one out of order. The subtraction is in +// fact defensive: start-1 is always an anchor at handover and anchorIdx is +// the anchor byte's first occurrence in the needle, so no remaining +// occurrence can start below start itself — resuming at start-anchorIdx +// keeps correctness independent of that selection detail. +func memmemFallback(haystack, needle []byte, start, anchorIdx int) int { + from := max(start-anchorIdx, 0) + if pos := bytes.Index(haystack[from:], needle); pos >= 0 { + return from + pos + } + return -1 +} diff --git a/src/vendor/github.com/gofiber/utils/v2/simd/simd.go b/src/vendor/github.com/gofiber/utils/v2/simd/simd.go new file mode 100644 index 00000000..a769f402 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/simd/simd.go @@ -0,0 +1,51 @@ +// Package simd provides SIMD-accelerated byte searching and validation +// primitives for the Fiber ecosystem: multi-needle scans, character-class +// scans, paired-byte scans, substring search, and ASCII validation. +// +// Acceleration comes in two tiers. The scan kernels — Memchr2, Memchr3, +// MemchrPair, MemchrDigit, MemchrWord, MemchrNotWord, IsASCII, +// FirstNonASCII, and CountNonASCII — dispatch to AVX2 assembly on amd64 +// CPUs (for inputs of MinLen+ bytes) and fall back to portable SWAR loops +// built on the swar package everywhere else. The kernels consume four +// 32-byte vectors per iteration. The first-match scans and IsASCII combine +// the per-vector masks, so a 128-byte block costs one mask extraction and +// one branch, and the scans that report a position then re-extract the +// four masks in address order to locate the hit. CountNonASCII is the +// exception: a count cannot be recovered from a combined mask, so its +// block loop accumulates per-lane counts in vector byte lanes and reduces +// them once at the end, and the remaining whole vectors are extracted and +// population-counted (which is why it, unlike the others, gates on POPCNT +// as well as AVX2). +// Memmem prefilters on amd64 — needles of 2-6 bytes containing two +// distinct values through the MemchrPair kernel from 65-byte haystacks, +// longer or single-valued needles through a single rare-byte +// bytes.IndexByte scan from 128 bytes — and delegates to bytes.Index for +// shorter haystacks or without AVX2. +// MemchrInTable/MemchrNotInTable are plain scalar loops on every +// architecture, since an arbitrary 256-entry membership test has no cheap +// vector form. Accelerated reports whether the AVX2 tier is active. +// Single-byte search is deliberately absent: bytes.IndexByte is already +// vector-accelerated by the Go runtime on all major architectures. +// +// Unlike the top-level utils helpers, this package operates on []byte only — +// it is the raw engine underneath the generic helpers. Callers holding a +// string can use the top-level generic functions instead of converting. +// +// Adapted from the coregex project, https://github.com/coregx/coregex +// (package simd), Copyright (c) 2025 Andrey Kolkov and contributors, +// MIT License. See the LICENSE file in this directory for the full text. +package simd + +// MinLen is the input length from which the AVX2 kernels engage on amd64: +// they consume whole 32-byte vectors, and below one vector their setup cost +// outweighs the win, so shorter inputs take the SWAR fallbacks. Callers +// that route between their own word loops and this package (as the +// top-level utils helpers do) should gate on this constant rather than +// hard-coding 32, so a retune here propagates everywhere. +const MinLen = 32 + +// Accelerated reports whether the AVX2 assembly kernels are in use on this +// CPU. When false, all functions use portable fallback implementations. +func Accelerated() bool { + return hasAVX2 +} diff --git a/src/vendor/github.com/gofiber/utils/v2/strings/case.go b/src/vendor/github.com/gofiber/utils/v2/strings/case.go index c50654cb..38115dd2 100644 --- a/src/vendor/github.com/gofiber/utils/v2/strings/case.go +++ b/src/vendor/github.com/gofiber/utils/v2/strings/case.go @@ -5,14 +5,11 @@ import ( "github.com/gofiber/utils/v2/internal/unsafeconv" ) -// swarMinLen is the smallest input length worth routing through the -// word-at-a-time (SWAR) helpers; shorter inputs are cheaper byte-by-byte. -const swarMinLen = caseconv.WordLen - +// Sub-word inputs convert here; see the bytes package for the measurement. // ToLower converts an ASCII string to lower-case without modifying the input. func ToLower(s string) string { n := len(s) - if n < swarMinLen { + if n < caseconv.WordLen { table := caseconv.ToLowerTable for i := 0; i < n; i++ { c := s[i] @@ -30,25 +27,20 @@ func ToLower(s string) string { return s } + // caseconv only reads src, so the zero-copy view is sound. src := unsafeconv.UnsafeBytes(s) i := caseconv.FirstUpperIndex(src) if i < 0 { return s } - - res := make([]byte, n) - // Copy the unchanged prefix up to the word containing the first - // uppercase byte, then convert the rest word-at-a-time. - from := i &^ (caseconv.WordLen - 1) - copy(res, src[:from]) - caseconv.ToLowerCopy(res, src, from) - return unsafeconv.UnsafeString(res) + // Its result is freshly allocated and never written again. + return unsafeconv.UnsafeString(caseconv.ToLowerFrom(src, i)) } // ToUpper converts an ASCII string to upper-case without modifying the input. func ToUpper(s string) string { n := len(s) - if n < swarMinLen { + if n < caseconv.WordLen { table := caseconv.ToUpperTable for i := 0; i < n; i++ { c := s[i] @@ -66,17 +58,14 @@ func ToUpper(s string) string { return s } + // caseconv only reads src, so the zero-copy view is sound. src := unsafeconv.UnsafeBytes(s) i := caseconv.FirstLowerIndex(src) if i < 0 { return s } - - res := make([]byte, n) - from := i &^ (caseconv.WordLen - 1) - copy(res, src[:from]) - caseconv.ToUpperCopy(res, src, from) - return unsafeconv.UnsafeString(res) + // Its result is freshly allocated and never written again. + return unsafeconv.UnsafeString(caseconv.ToUpperFrom(src, i)) } // UnsafeToLower converts an ASCII string to lower-case by mutating its backing bytes in-place. @@ -84,7 +73,7 @@ func ToUpper(s string) string { // string is known to reference mutable memory. func UnsafeToLower(s string) string { b := unsafeconv.UnsafeBytes(s) - if len(b) < swarMinLen { + if len(b) < caseconv.WordLen { table := caseconv.ToLowerTable for i := range b { b[i] = table[b[i]] @@ -100,7 +89,7 @@ func UnsafeToLower(s string) string { // string is known to reference mutable memory. func UnsafeToUpper(s string) string { b := unsafeconv.UnsafeBytes(s) - if len(b) < swarMinLen { + if len(b) < caseconv.WordLen { table := caseconv.ToUpperTable for i := range b { b[i] = table[b[i]] diff --git a/src/vendor/github.com/gofiber/utils/v2/swar/swar.go b/src/vendor/github.com/gofiber/utils/v2/swar/swar.go index 6290a000..dcf7fa61 100644 --- a/src/vendor/github.com/gofiber/utils/v2/swar/swar.go +++ b/src/vendor/github.com/gofiber/utils/v2/swar/swar.go @@ -44,6 +44,22 @@ const ( // reslice pins the length so the constant-index reads are bounds-check free, // and the compiler fuses them into a single 8-byte load on little-endian // targets (verified for both the string and []byte instantiations). +// +// The reslice itself is still checked, against the backing array's +// capacity, which a loop condition written in terms of len does not imply. +// A loop that loads several words per iteration should therefore pin the +// whole group once and index into it with constants rather than call Load8 +// at a variable offset each time: +// +// for ; i+4*WordLen <= n; i += 4 * WordLen { +// w := b[i : i+4*WordLen : i+4*WordLen] +// acc := Load8(w, 0) | Load8(w, WordLen) | Load8(w, 2*WordLen) | Load8(w, 3*WordLen) +// // ... +// } +// +// That moves four checks and their empty-slice pointer clamps down to one +// per group; on []byte the three-index form pins the capacity too and +// removes the rest. It is worth 20-60% on the word loops in package simd. func Load8[S ~string | ~[]byte](s S, i int) uint64 { w := s[i : i+8] return uint64(w[0]) | @@ -94,11 +110,17 @@ func ToUpperWord(w uint64) uint64 { return w &^ (MatchRangeMask(w, 'a', 'z') >> 2) // clear bit 5 on matched lanes } -// ZeroLanes returns a mask whose lowest set lane is the lowest zero-byte -// lane of x; higher lanes may carry false positives (borrows propagate -// strictly upward from true zero lanes), and the mask is zero iff x has no -// zero byte. It is two ops cheaper than MatchByteMask, which makes it the -// right primitive for first-match scans, typically as +// ZeroLanes returns a mask flagging the zero-byte lanes of x. Three +// properties are part of the contract: the mask is zero iff x has no zero +// byte; the lowest set lane is always the lowest true zero lane; and every +// true zero lane has its high bit set — a 0x00 lane leaves the subtraction +// as 0xFF or 0xFE regardless of borrow-in, and &^ x keeps its high bit — +// so combining masks (OR for multi-needle scans, AND for pair scans, as +// simd.Memchr2 and simd.MemchrPair's fallbacks do) never loses a true +// match. Lanes above the first true zero may carry false positives +// (borrows propagate strictly upward), so anything beyond the lowest set +// lane must be re-verified. It is two ops cheaper than MatchByteMask, +// which makes it the right primitive for first-match scans, typically as // ZeroLanes(w ^ Broadcast(c)) with the broadcast hoisted out of the word // loop. Use MatchByteMask when every lane must be exact. func ZeroLanes(x uint64) uint64 { diff --git a/src/vendor/github.com/gofiber/utils/v2/time.go b/src/vendor/github.com/gofiber/utils/v2/time.go index 91b970af..85b7cb70 100644 --- a/src/vendor/github.com/gofiber/utils/v2/time.go +++ b/src/vendor/github.com/gofiber/utils/v2/time.go @@ -13,6 +13,22 @@ var ( updaterDone chan struct{} ) +// now and newTicker are this package's clock: every production read of the wall +// clock goes through them, so replacing the pair is enough to drive the updater +// from a test without waiting on real time. Neither is reachable from outside +// the package, and Timestamp itself touches neither. +// +// newTicker hands back a channel and a stop function instead of a *time.Ticker +// because a Ticker the runtime did not build cannot stand in for one: its Stop +// panics. +var ( + now = time.Now + newTicker = func(d time.Duration) (<-chan time.Time, func()) { + t := time.NewTicker(d) + return t.C, t.Stop + } +) + // Timestamp returns the current cached Unix timestamp (seconds). // Call StartTimeStampUpdater() once at app startup for best performance. func Timestamp() uint32 { @@ -28,19 +44,25 @@ func StartTimeStampUpdater() { return } - timestamp.Store(uint32(time.Now().Unix())) + timestamp.Store(uint32(now().Unix())) stopUpdater = make(chan struct{}) updaterDone = make(chan struct{}) + // The tick source is created here, not in the goroutine, so it exists by + // the time this returns and a caller cannot race the goroutine's first + // statement. + tick, stopTick := newTicker(time.Second) + go func(stop, done chan struct{}) { - ticker := time.NewTicker(time.Second) - defer ticker.Stop() + // stopTick before close(done), so that once StopTimeStampUpdater's + // wait returns the tick source is released rather than about to be. defer close(done) + defer stopTick() for { select { - case <-ticker.C: - timestamp.Store(uint32(time.Now().Unix())) + case <-tick: + timestamp.Store(uint32(now().Unix())) case <-stop: return } diff --git a/src/vendor/github.com/gofiber/utils/v2/url.go b/src/vendor/github.com/gofiber/utils/v2/url.go new file mode 100644 index 00000000..c3895555 --- /dev/null +++ b/src/vendor/github.com/gofiber/utils/v2/url.go @@ -0,0 +1,182 @@ +package utils + +import ( + "bytes" + "net/url" + "strings" + + "github.com/gofiber/utils/v2/internal/unsafeconv" +) + +// escapeMode selects between net/url's query-component and path-segment +// escaping dialects: only the query dialect maps '+' to space. +type escapeMode uint8 + +const ( + escapeQuery escapeMode = iota + escapePath +) + +// upperHexDigits is the escape alphabet used by the Append*Escape helpers, +// matching net/url. +const upperHexDigits = "0123456789ABCDEF" + +// unhexTable maps an ASCII byte to its hexadecimal digit value, or 0xFF for +// bytes that are not hex digits. +var unhexTable = buildUnhexTable() + +func buildUnhexTable() [256]byte { + var t [256]byte + for i := range t { + t[i] = 0xFF + } + for c := byte('0'); c <= '9'; c++ { + t[c] = c - '0' + } + for c := byte('a'); c <= 'f'; c++ { + t[c] = c - 'a' + 10 + } + for c := byte('A'); c <= 'F'; c++ { + t[c] = c - 'A' + 10 + } + return t +} + +// queryNoEscapeTable and pathNoEscapeTable flag the bytes net/url leaves +// verbatim in query components and path segments respectively. They are +// derived from net/url's shouldEscape rules and pinned to them by +// exhaustive per-byte tests. Path segments additionally keep the sub-delims +// net/url's encodePathSegment mode does not escape. +var ( + queryNoEscapeTable = buildNoEscapeTable("") + pathNoEscapeTable = buildNoEscapeTable("$&+:=@") + // A multi-segment path keeps '/', which separates its segments rather than + // belonging to one of them. + pathSegmentsNoEscapeTable = buildNoEscapeTable("$&+:=@/") +) + +// buildNoEscapeTable flags the RFC 3986 unreserved bytes plus alsoSafe as +// not needing escape. +func buildNoEscapeTable(alsoSafe string) [256]bool { + var t [256]bool + for i := range 256 { + c := byte(i) + t[i] = c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || + c == '-' || c == '_' || c == '.' || c == '~' || + strings.IndexByte(alsoSafe, c) >= 0 + } + return t +} + +// AppendQueryEscape appends the percent-encoded form of s to dst and returns +// the extended slice. The output is byte-identical to net/url.QueryEscape: +// unreserved bytes pass through, space becomes '+', everything else becomes +// %XX with uppercase hex. dst must not alias s: escaping can grow the input, +// so in-place operation is impossible. +func AppendQueryEscape[S byteSeq](dst []byte, s S) []byte { + return appendEscape(dst, unsafeconv.Bytes(s), &queryNoEscapeTable, escapeQuery) +} + +// AppendPathEscape appends the percent-encoded path-segment form of s to dst +// and returns the extended slice. The output is byte-identical to +// net/url.PathEscape; the aliasing rule matches AppendQueryEscape. +func AppendPathEscape[S byteSeq](dst []byte, s S) []byte { + return appendEscape(dst, unsafeconv.Bytes(s), &pathNoEscapeTable, escapePath) +} + +// AppendPathSegmentsEscape appends the percent-encoded form of the multi-segment +// path s to dst and returns the extended slice. It escapes every segment as +// AppendPathEscape does but leaves the '/' between them, so the output matches +// escaping each segment separately and joining the results with '/'. Use it for +// a value whose slashes are separators; use AppendPathEscape for one segment, +// where a slash is data and has to be encoded. Empty and dot segments pass +// through unchanged, so clean or reject an untrusted value before appending it +// under a fixed prefix. The aliasing rule matches AppendQueryEscape. +func AppendPathSegmentsEscape[S byteSeq](dst []byte, s S) []byte { + return appendEscape(dst, unsafeconv.Bytes(s), &pathSegmentsNoEscapeTable, escapePath) +} + +// appendEscape copies runs of unescaped bytes wholesale and expands the rest, +// in one pass with no intermediate allocation — unlike net/url, which counts +// in a first pass and then rebuilds the string byte by byte. +func appendEscape(dst, s []byte, noEscape *[256]bool, mode escapeMode) []byte { + i, n := 0, len(s) + for i < n { + j := i + for j < n && noEscape[s[j]] { + j++ + } + dst = append(dst, s[i:j]...) + if j == n { + break + } + if c := s[j]; mode == escapeQuery && c == ' ' { + dst = append(dst, '+') + } else { + dst = append(dst, '%', upperHexDigits[c>>4], upperHexDigits[c&0x0F]) + } + i = j + 1 + } + return dst +} + +// AppendQueryUnescape appends the decoded form of the query component s to +// dst and returns the extended slice, converting '+' to space and %XX to the +// byte it encodes, exactly like net/url.QueryUnescape including its +// url.EscapeError values for malformed escapes. On error the returned slice +// is dst with its original length (its backing array may still have been +// reallocated by growth). Decoding never grows the input, so dst may be +// s[:0] on a common backing array to decode in place; any other overlap is +// invalid. Note that an in-place decode that fails has already overwritten +// the prefix of s before the malformed escape with decoded bytes — treat s +// as consumed once an in-place decode starts, error or not. +func AppendQueryUnescape[S byteSeq](dst []byte, s S) ([]byte, error) { + return appendUnescape(dst, unsafeconv.Bytes(s), escapeQuery) +} + +// AppendPathUnescape appends the decoded form of the path component s to dst +// and returns the extended slice, decoding %XX and leaving '+' verbatim, +// exactly like net/url.PathUnescape. Error and aliasing behavior match +// AppendQueryUnescape. +func AppendPathUnescape[S byteSeq](dst []byte, s S) ([]byte, error) { + return appendUnescape(dst, unsafeconv.Bytes(s), escapePath) +} + +// appendUnescape jumps between escape sites with vectorized scans — +// IndexAny2 (SWAR/AVX2) when '+' also needs rewriting, bytes.IndexByte +// otherwise — and copies the clean spans between them wholesale, so input +// without escapes costs one scan and one copy. +func appendUnescape(dst, s []byte, mode escapeMode) ([]byte, error) { + off := len(dst) + i, n := 0, len(s) + for i < n { + var j int + if mode == escapeQuery { + j = IndexAny2(s[i:], '%', '+') + } else { + j = bytes.IndexByte(s[i:], '%') + } + if j < 0 { + return append(dst, s[i:]...), nil + } + j += i + dst = append(dst, s[i:j]...) + if s[j] == '+' { + dst = append(dst, ' ') + i = j + 1 + continue + } + // s[j] == '%': the error substrings below match net/url's unescape. + if j+2 >= n { + return dst[:off], url.EscapeError(s[j:]) + } + hi := unhexTable[s[j+1]] + lo := unhexTable[s[j+2]] + if hi > 0x0F || lo > 0x0F { + return dst[:off], url.EscapeError(s[j : j+3]) + } + dst = append(dst, hi<<4|lo) + i = j + 3 + } + return dst, nil +} diff --git a/src/vendor/github.com/klauspost/compress/README.md b/src/vendor/github.com/klauspost/compress/README.md index 0e9f170d..bf31b905 100644 --- a/src/vendor/github.com/klauspost/compress/README.md +++ b/src/vendor/github.com/klauspost/compress/README.md @@ -6,7 +6,9 @@ This package provides various compression algorithms. * [S2](https://github.com/klauspost/compress/tree/master/s2#s2-compression) is a high performance replacement for Snappy. * Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). * [snappy](https://github.com/klauspost/compress/tree/master/snappy) is a drop-in replacement for `github.com/golang/snappy` offering better compression and concurrent streams. +* [lzw](https://github.com/klauspost/compress/tree/master/lzw) is a drop-in replacement for `compress/lzw` with 1.4-4x faster decompression and 1.1-2.7x faster compression, depending on the data. * [huff0](https://github.com/klauspost/compress/tree/master/huff0) and [FSE](https://github.com/klauspost/compress/tree/master/fse) implementations for raw entropy encoding. +* [Xpress](https://github.com/klauspost/compress/tree/master/xpress) decompression of the Microsoft XPRESS (MS-XCA) plain LZ77 and LZ77+Huffman formats (the LZ77+Huffman variant is the one used in WIM images and Windows Compact OS / WOF data). * [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped/zstd HTTP requests efficiently. * [pgzip](https://github.com/klauspost/pgzip) is a separate package that provides a very fast parallel gzip implementation. diff --git a/src/vendor/github.com/klauspost/compress/flate/deflate.go b/src/vendor/github.com/klauspost/compress/flate/deflate.go index 57d17eea..238b1bcd 100644 --- a/src/vendor/github.com/klauspost/compress/flate/deflate.go +++ b/src/vendor/github.com/klauspost/compress/flate/deflate.go @@ -95,6 +95,11 @@ type advancedState struct { index int hashMatch [maxMatchLength + minMatchLength]uint32 + // litBits[i] is the number of bits needed to encode window[index:i] + // as literals, where index is the window index at the start of the + // current deflateLazy call. Only allocated when d.chain > 100 (level 9). + litBits []int32 + // Input hash chains // hashHead[hashValue] contains the largest inputIndex with the specified hash value // If hashHead[hashValue] is within the current window, then @@ -260,6 +265,7 @@ func (d *compressor) fillWindow(b []byte) { } // Update window information. d.windowEnd += n + d.blockStart = d.windowEnd s.index = n } @@ -283,7 +289,9 @@ func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, of minIndex := max(pos-windowSize, 0) offset = 0 - if d.chain < 100 { + // The gain estimate below needs the tables that deflateLazy only + // generates when d.chain > 100, so the conditions must match. + if d.chain <= 100 { for i := prevHead; tries > 0; tries-- { if wEnd == win[i+length] { n := matchLen(win[i:i+minMatchLook], wPos) @@ -311,21 +319,25 @@ func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, of } // Minimum gain to accept a match. - cGain := 4 + cGain := int32(4) // Some like it higher (CSV), some like it lower (JSON) const baseCost = 3 // Base is 4 bytes at with an additional cost. // Matches must be better than this. + s := d.state + hashPrev := &s.hashPrev + hashOffset := s.hashOffset + litBits := s.litBits[pos : pos+minMatchLook+1] + for i := prevHead; tries > 0; tries-- { if wEnd == win[i+length] { n := matchLen(win[i:i+minMatchLook], wPos) if n > length { // Calculate gain. Estimate - newGain := d.h.bitLengthRaw(wPos[:n]) - int(offsetExtraBits[offsetCode(uint32(pos-i))]) - baseCost - int(lengthExtraBits[lengthCodes[(n-3)&255]]) + newGain := litBits[n] - litBits[0] - int32(offsetExtraBits[offsetCode(uint32(pos-i))]) - baseCost - int32(lengthExtraBits[lengthCodes[(n-3)&255]]) - //fmt.Println("gain:", newGain, "prev:", cGain, "raw:", d.h.bitLengthRaw(wPos[:n]), "this-len:", n, "prev-len:", length) if newGain > cGain { length = n offset = pos - i @@ -343,7 +355,7 @@ func (d *compressor) findMatch(pos int, prevHead int, lookahead int) (length, of // hashPrev[i & windowMask] has already been overwritten, so stop now. break } - i = int(d.state.hashPrev[i&windowMask]) - d.state.hashOffset + i = int(hashPrev[i&windowMask]) - hashOffset if i < minIndex { break } @@ -427,6 +439,20 @@ func (d *compressor) deflateLazy() { tmp[v]++ } d.h.generate(tmp[:], 15) + + // Compute the cumulative cost of encoding the window as literals, + // so findMatch can look up the cost of any range in constant time. + if s.litBits == nil { + s.litBits = make([]int32, 2*windowSize+1) + } + codes := d.h.codes[:256] + litBits := s.litBits[s.index : d.windowEnd+1] + total := int32(0) + litBits[0] = 0 + for i, v := range d.window[s.index:d.windowEnd] { + total += int32(codes[v].len()) + litBits[i+1] = total + } } s.maxInsertIndex = d.windowEnd - (minMatchLength - 1) diff --git a/src/vendor/github.com/klauspost/compress/flate/fast_encoder.go b/src/vendor/github.com/klauspost/compress/flate/fast_encoder.go index 791c9dcb..a8cdc5c9 100644 --- a/src/vendor/github.com/klauspost/compress/flate/fast_encoder.go +++ b/src/vendor/github.com/klauspost/compress/flate/fast_encoder.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/klauspost/compress/internal/le" + "github.com/klauspost/compress/internal/regmask" ) type fastEnc interface { @@ -108,7 +109,7 @@ type tableEntryPrev struct { // hash7 returns the hash of the lowest 7 bytes of u to fit in a hash table with h bits. // Preferably h should be a constant and should always be <64. func hash7(u uint64, h uint8) uint32 { - return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & reg8SizeMask64)) + return uint32(((u << (64 - 56)) * prime7bytes) >> ((64 - h) & regmask.Shift64ByUint8)) } // hashLen returns a hash of the lowest mls bytes of with length output bits. diff --git a/src/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go b/src/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go index 7151140c..a0c918ae 100644 --- a/src/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go +++ b/src/vendor/github.com/klauspost/compress/flate/huffman_bit_writer.go @@ -32,14 +32,12 @@ const ( // bufferFlushSize indicates the buffer size // after which bytes are flushed to the writer. - // Should preferably be a multiple of 6, since - // we accumulate 6 bytes between writes to the buffer. + // Between checks, at most 7 bytes are added to the buffer, + // and writes are done as unconditional 8-byte stores, so the + // buffer must have at least bufferFlushSize+7+8 bytes. bufferFlushSize = 246 ) -// Minimum length code that emits bits. -const lengthExtraBitsMinCode = 8 - // The number of extra bits needed by length code X - LENGTH_CODES_START. var lengthExtraBits = [32]uint8{ /* 257 */ 0, 0, 0, @@ -55,9 +53,6 @@ var lengthBase = [32]uint8{ 64, 80, 96, 112, 128, 160, 192, 224, 255, } -// Minimum offset code that emits bits. -const offsetExtraBitsMinCode = 4 - // offset code word extra bits. var offsetExtraBits = [32]int8{ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, @@ -67,8 +62,24 @@ var offsetExtraBits = [32]int8{ 14, 14, } +// offsetCombined combines the number of extra bits and the base offset +// of each offset code in a single table: extra bits in the low 8 bits, +// and the base offset (already reduced by baseMatchOffset) in the upper bits. +// Entries for the extended window codes 30 and 31 are unused. var offsetCombined = [32]uint32{} +// lengthCombined combines, for each match length (reduced by +// baseMatchLength), the length code (relative to lengthCodesStart) in +// bits 0-4, the number of extra bits in bits 5-7 and the value of the +// extra bits in bits 8-12. +var lengthCombined = func() (t [256]uint32) { + for i := range t { + code := lengthCodes[i] + t[i] = uint32(code) | uint32(lengthExtraBits[code])<<5 | uint32(uint8(i)-lengthBase[code])<<8 + } + return t +}() + func init() { var offsetBase = [32]uint32{ /* normal deflate */ @@ -85,7 +96,7 @@ func init() { for i := range offsetCombined[:] { // Don't use extended window values... - if offsetExtraBits[i] == 0 || offsetBase[i] > 0x006000 { + if offsetBase[i] > 0x006000 { continue } offsetCombined[i] = uint32(offsetExtraBits[i]) | (offsetBase[i] << 8) @@ -115,10 +126,14 @@ type huffmanBitWriter struct { lastHeader int // Set between 0 (reused block can be up to 2x the size) logNewTablePenalty uint - bytes [256 + 8]byte - literalFreq [lengthCodesStart + 32]uint16 - offsetFreq [32]uint16 - codegenFreq [codegenCodeCount]uint16 + + // bytes must hold at least bufferFlushSize+7+8 bytes (see bufferFlushSize). + // Its size is rounded up to a multiple of 8 to keep the following + // fields aligned, which is measurably faster in writeBlockHuff. + bytes [(bufferFlushSize + 7 + 8 + 7) &^ 7]byte + literalFreq [lengthCodesStart + 32]uint16 + offsetFreq [32]uint16 + codegenFreq [codegenCodeCount]uint16 // codegen must have an extra space for the final symbol. codegen [literalCount + offsetCodeCount + 1]uint8 @@ -842,124 +857,75 @@ func (w *huffmanBitWriter) writeTokens(tokens []token, leCodes, oeCodes []hcode) lengths := leCodes[lengthCodesStart:] lengths = lengths[:32] - // Go 1.16 LOVES having these on stack. + // Keeping these on the stack instead of in w is significantly faster. bits, nbits, nbytes := w.bits, w.nbits, w.nbytes - for _, t := range tokens { - if t < 256 { - //w.writeCode(lits[t.literal()]) - c := lits[t] - bits |= c.code64() << (nbits & 63) - nbits += c.len() - if nbits >= 48 { - le.Store64(w.bytes[:], nbytes, bits) - bits >>= 48 - nbits -= 48 - nbytes += 6 - if nbytes >= bufferFlushSize { - if w.err != nil { - nbytes = 0 - return - } - _, w.err = w.writer.Write(w.bytes[:nbytes]) - nbytes = 0 - } - } - continue + // Flush whole bytes, so that nbits <= 7 when entering the loop below. + le.Store64(w.bytes[:], nbytes, bits) + nbytes += nbits >> 3 + bits >>= nbits & 56 + nbits &= 7 + if nbytes >= bufferFlushSize { + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 + if w.err != nil { + return } + } - // Write the length - length := t.length() - lengthCode := lengthCode(length) & 31 - if false { - w.writeCode(lengths[lengthCode]) - } else { - // inlined - c := lengths[lengthCode] + // The loop below flushes whole bytes at the end of every iteration, + // so that nbits <= 7 at the top of every iteration. + // A literal adds at most 15 bits and a match at most + // 15+5+15+13 = 48 bits, so up to three literals or a single match + // can be added to the 64-bit accumulator without an intermediate flush. + // Unconditionally storing 8 bytes and advancing by the number of + // whole bytes avoids a poorly predicted branch per token. + for i := 0; i < len(tokens); i++ { + t := tokens[i] + if t < 256 { + c := lits[t] bits |= c.code64() << (nbits & 63) nbits += c.len() - if nbits >= 48 { - le.Store64(w.bytes[:], nbytes, bits) - bits >>= 48 - nbits -= 48 - nbytes += 6 - if nbytes >= bufferFlushSize { - if w.err != nil { - nbytes = 0 - return - } - _, w.err = w.writer.Write(w.bytes[:nbytes]) - nbytes = 0 - } - } - } - - if lengthCode >= lengthExtraBitsMinCode { - extraLengthBits := lengthExtraBits[lengthCode] - //w.writeBits(extraLength, extraLengthBits) - extraLength := int32(length - lengthBase[lengthCode]) - bits |= uint64(extraLength) << (nbits & 63) - nbits += extraLengthBits - if nbits >= 48 { - le.Store64(w.bytes[:], nbytes, bits) - bits >>= 48 - nbits -= 48 - nbytes += 6 - if nbytes >= bufferFlushSize { - if w.err != nil { - nbytes = 0 - return - } - _, w.err = w.writer.Write(w.bytes[:nbytes]) - nbytes = 0 + // Add up to two more literals before flushing. + if i+1 < len(tokens) && tokens[i+1] < 256 { + i++ + c := lits[tokens[i]] + bits |= c.code64() << (nbits & 63) + nbits += c.len() + if i+1 < len(tokens) && tokens[i+1] < 256 { + i++ + c := lits[tokens[i]] + bits |= c.code64() << (nbits & 63) + nbits += c.len() } } - } - // Write the offset - offset := t.offset() - offsetCode := (offset >> 16) & 31 - if false { - w.writeCode(offs[offsetCode]) } else { - // inlined - c := offs[offsetCode] - bits |= c.code64() << (nbits & 63) - nbits += c.len() - if nbits >= 48 { - le.Store64(w.bytes[:], nbytes, bits) - bits >>= 48 - nbits -= 48 - nbytes += 6 - if nbytes >= bufferFlushSize { - if w.err != nil { - nbytes = 0 - return - } - _, w.err = w.writer.Write(w.bytes[:nbytes]) - nbytes = 0 - } - } + // Write the length code and its extra bits as one unit. + lc := lengthCombined[t.length()] + c := lengths[lc&31] + bits |= (c.code64() | uint64(lc>>8)<<(c.len()&63)) << (nbits & 63) + nbits += c.len() + uint8(lc>>5)&7 + + // Write the offset code and its extra bits as one unit. + offset := t.offset() + offCode := (offset >> 16) & 31 + c = offs[offCode] + offComb := offsetCombined[offCode] + extra := (offset - (offComb >> 8)) & matchOffsetOnlyMask + bits |= (c.code64() | uint64(extra)<<(c.len()&63)) << (nbits & 63) + nbits += c.len() + uint8(offComb) } - - if offsetCode >= offsetExtraBitsMinCode { - offsetComb := offsetCombined[offsetCode] - //w.writeBits(extraOffset, extraOffsetBits) - bits |= uint64((offset-(offsetComb>>8))&matchOffsetOnlyMask) << (nbits & 63) - nbits += uint8(offsetComb) - if nbits >= 48 { - le.Store64(w.bytes[:], nbytes, bits) - bits >>= 48 - nbits -= 48 - nbytes += 6 - if nbytes >= bufferFlushSize { - if w.err != nil { - nbytes = 0 - return - } - _, w.err = w.writer.Write(w.bytes[:nbytes]) - nbytes = 0 - } + le.Store64(w.bytes[:], nbytes, bits) + nbytes += nbits >> 3 + bits >>= nbits & 56 + nbits &= 7 + if nbytes >= bufferFlushSize { + if w.err != nil { + nbytes = 0 + return } + _, w.err = w.writer.Write(w.bytes[:nbytes]) + nbytes = 0 } } // Restore... @@ -1094,8 +1060,8 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { if debugDeflate { count -= int(nbytes)*8 + int(nbits) } - // Unroll, write 3 codes/loop. - // Fastest number of unrolls. + // Write 3 codes per iteration. The three codes are combined first, + // independently of the accumulator, and merged with a single shift. for len(input) > 3 { // We must have at least 48 bits free. if nbits >= 8 { @@ -1116,13 +1082,13 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte, sync bool) { _, w.err = w.writer.Write(w.bytes[:nbytes]) nbytes = 0 } - a, b := encoding[input[0]], encoding[input[1]] - bits |= a.code64() << (nbits & 63) - bits |= b.code64() << ((nbits + a.len()) & 63) - c := encoding[input[2]] - nbits += b.len() + a.len() - bits |= c.code64() << (nbits & 63) - nbits += c.len() + a, b, c := encoding[input[0]], encoding[input[1]], encoding[input[2]] + v := a.code64() | b.code64()<<(a.len()&63) + n := a.len() + b.len() + v |= c.code64() << (n & 63) + n += c.len() + bits |= v << (nbits & 63) + nbits += n input = input[3:] } diff --git a/src/vendor/github.com/klauspost/compress/flate/huffman_code.go b/src/vendor/github.com/klauspost/compress/flate/huffman_code.go index 4b312dea..6082bee3 100644 --- a/src/vendor/github.com/klauspost/compress/flate/huffman_code.go +++ b/src/vendor/github.com/klauspost/compress/flate/huffman_code.go @@ -38,6 +38,9 @@ type huffmanEncoder struct { // Possible lengths are codegenCodeCount, offsetCodeCount and literalCount. // The largest of these is literalCount, so we allocate for that case. freqcache [literalCount + 1]literalNode + + // sortcache is scratch space for sortByFreq. + sortcache [literalCount + 1]literalNode } type literalNode struct { @@ -139,14 +142,6 @@ func (h *huffmanEncoder) bitLength(freq []uint16) int { return total } -func (h *huffmanEncoder) bitLengthRaw(b []byte) int { - var total int - for _, f := range b { - total += int(h.codes[f].len()) - } - return total -} - // canReuseBits returns the number of bits or math.MaxInt32 if the encoder cannot be reused. func (h *huffmanEncoder) canReuseBits(freq []uint16) int { var total int @@ -309,27 +304,93 @@ func (h *huffmanEncoder) bitCounts(list []literalNode, maxBits int32) []int32 { } // Look at the leaves and assign them a bit count and an encoding as specified -// in RFC 1951 3.2.2 -func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode) { - code := uint16(0) +// in RFC 1951 3.2.2. +// list must be sorted by increasing frequency and codes must have +// all entries for literals not in list set to zero. +func (h *huffmanEncoder) assignEncodingAndSize(bitCount []int32, list []literalNode, codes []hcode) { + // The literals list[len(list)-bits] .. list[len(list)-1] + // are encoded using "bits" bits. Record the length of each literal + // temporarily in codes. for n, bits := range bitCount { - code <<= 1 if n == 0 || bits == 0 { continue } - // The literals list[len(list)-bits] .. list[len(list)-bits] - // are encoded using "bits" bits, and get the values - // code, code + 1, .... The code values are - // assigned in literal order (not frequency order). - chunk := list[len(list)-int(bits):] - - sortByLiteral(chunk) - for _, node := range chunk { - h.codes[node.literal] = newhcode(reverseBits(code, uint8(n)), uint8(n)) - code++ + for _, node := range list[len(list)-int(bits):] { + codes[node.literal] = hcode(n) } list = list[0 : len(list)-int(bits)] } + + // Code values are assigned in literal order (not frequency order) + // within each code length, starting from the first code of each length. + var nextCode [maxBitsLimit]uint16 + code := uint16(0) + for n := 1; n < len(bitCount); n++ { + code = (code + uint16(bitCount[n-1])) << 1 + nextCode[n] = code + } + for i, c := range codes { + if c == 0 { + continue + } + // n is at most maxBitsLimit-1; the mask only elides bounds checks. + n := uint8(c) + codes[i] = newhcode(reverseBits(nextCode[n&15], n), n) + nextCode[n&15]++ + } +} + +// sortByFreq sorts list by increasing frequency. +// The sort is stable, so nodes with equal frequencies keep their order. +func (h *huffmanEncoder) sortByFreq(list []literalNode) { + if len(list) <= 32 { + // Insertion sort is faster for small lists. + for i := 1; i < len(list); i++ { + n := list[i] + j := i + for ; j > 0 && list[j-1].freq > n.freq; j-- { + list[j] = list[j-1] + } + list[j] = n + } + return + } + + // Counting sort on the low byte and then on the high byte + // of the frequency. Both passes are stable. + tmp := h.sortcache[:len(list)] + var count [256]uint16 + var maxFreq uint16 + for _, n := range list { + count[n.freq&0xff]++ + maxFreq |= n.freq + } + var pos uint16 + for i, c := range count { + count[i] = pos + pos += c + } + for _, n := range list { + tmp[count[n.freq&0xff]] = n + count[n.freq&0xff]++ + } + if maxFreq < 256 { + copy(list, tmp) + return + } + count = [256]uint16{} + for _, n := range tmp { + count[n.freq>>8]++ + } + pos = 0 + for i, c := range count { + count[i] = pos + pos += c + } + for _, n := range tmp { + list[count[n.freq>>8]] = n + count[n.freq>>8]++ + } } // Update this Huffman Code object to be the minimum code for the specified frequency count. @@ -362,12 +423,14 @@ func (h *huffmanEncoder) generate(freq []uint16, maxBits int32) { } return } - sortByFreq(list) + // list is in order of increasing literal value, so a stable sort + // by frequency orders it by (frequency, literal). + h.sortByFreq(list) // Get the number of literals for each bit count bitCount := h.bitCounts(list, maxBits) // And do the assignment - h.assignEncodingAndSize(bitCount, list) + h.assignEncodingAndSize(bitCount, list, codes) } // atLeastOne clamps the result between 1 and 15. @@ -394,24 +457,27 @@ func histogram(b []byte, h []uint16) { } func histogramSplit(b []byte, h []uint16) { - // Tested, and slightly faster than 2-way. - // Writing to separate arrays and combining is also slightly slower. - h = h[:256] + // Walk four quarters in parallel, each into its own table. + // Tested to be faster than walking halves. Using separate tables + // avoids the load/store dependencies that arise when two of the + // streams hit the same byte value, which is common for text. + var h0, h1, h2, h3 [256]uint16 + // Make size divisible by 4 for len(b)&3 != 0 { - h[b[0]]++ + h0[b[0]]++ b = b[1:] } n := len(b) / 4 x, y, z, w := b[:n], b[n:], b[n+n:], b[n+n+n:] y, z, w = y[:len(x)], z[:len(x)], w[:len(x)] for i, t := range x { - v0 := &h[t] - v1 := &h[y[i]] - v2 := &h[z[i]] - v3 := &h[w[i]] - *v0++ - *v1++ - *v2++ - *v3++ + h0[t]++ + h1[y[i]]++ + h2[z[i]]++ + h3[w[i]]++ + } + h = h[:256] + for i := range h { + h[i] += h0[i] + h1[i] + h2[i] + h3[i] } } diff --git a/src/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go b/src/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go deleted file mode 100644 index 6c05ba8c..00000000 --- a/src/vendor/github.com/klauspost/compress/flate/huffman_sortByFreq.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flate - -// Sort sorts data. -// It makes one call to data.Len to determine n, and O(n*log(n)) calls to -// data.Less and data.Swap. The sort is not guaranteed to be stable. -func sortByFreq(data []literalNode) { - n := len(data) - quickSortByFreq(data, 0, n, maxDepth(n)) -} - -func quickSortByFreq(data []literalNode, a, b, maxDepth int) { - for b-a > 12 { // Use ShellSort for slices <= 12 elements - if maxDepth == 0 { - heapSort(data, a, b) - return - } - maxDepth-- - mlo, mhi := doPivotByFreq(data, a, b) - // Avoiding recursion on the larger subproblem guarantees - // a stack depth of at most lg(b-a). - if mlo-a < b-mhi { - quickSortByFreq(data, a, mlo, maxDepth) - a = mhi // i.e., quickSortByFreq(data, mhi, b) - } else { - quickSortByFreq(data, mhi, b, maxDepth) - b = mlo // i.e., quickSortByFreq(data, a, mlo) - } - } - if b-a > 1 { - // Do ShellSort pass with gap 6 - // It could be written in this simplified form cause b-a <= 12 - for i := a + 6; i < b; i++ { - if data[i].freq == data[i-6].freq && data[i].literal < data[i-6].literal || data[i].freq < data[i-6].freq { - data[i], data[i-6] = data[i-6], data[i] - } - } - insertionSortByFreq(data, a, b) - } -} - -func doPivotByFreq(data []literalNode, lo, hi int) (midlo, midhi int) { - m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. - if hi-lo > 40 { - // Tukey's ``Ninther,'' median of three medians of three. - s := (hi - lo) / 8 - medianOfThreeSortByFreq(data, lo, lo+s, lo+2*s) - medianOfThreeSortByFreq(data, m, m-s, m+s) - medianOfThreeSortByFreq(data, hi-1, hi-1-s, hi-1-2*s) - } - medianOfThreeSortByFreq(data, lo, m, hi-1) - - // Invariants are: - // data[lo] = pivot (set up by ChoosePivot) - // data[lo < i < a] < pivot - // data[a <= i < b] <= pivot - // data[b <= i < c] unexamined - // data[c <= i < hi-1] > pivot - // data[hi-1] >= pivot - pivot := lo - a, c := lo+1, hi-1 - - for ; a < c && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { - } - b := a - for { - for ; b < c && (data[pivot].freq == data[b].freq && data[pivot].literal > data[b].literal || data[pivot].freq > data[b].freq); b++ { // data[b] <= pivot - } - for ; b < c && (data[pivot].freq == data[c-1].freq && data[pivot].literal < data[c-1].literal || data[pivot].freq < data[c-1].freq); c-- { // data[c-1] > pivot - } - if b >= c { - break - } - // data[b] > pivot; data[c-1] <= pivot - data[b], data[c-1] = data[c-1], data[b] - b++ - c-- - } - // If hi-c<3 then there are duplicates (by property of median of nine). - // Let's be a bit more conservative, and set border to 5. - protect := hi-c < 5 - if !protect && hi-c < (hi-lo)/4 { - // Lets test some points for equality to pivot - dups := 0 - if data[pivot].freq == data[hi-1].freq && data[pivot].literal > data[hi-1].literal || data[pivot].freq > data[hi-1].freq { // data[hi-1] = pivot - data[c], data[hi-1] = data[hi-1], data[c] - c++ - dups++ - } - if data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq { // data[b-1] = pivot - b-- - dups++ - } - // m-lo = (hi-lo)/2 > 6 - // b-lo > (hi-lo)*3/4-1 > 8 - // ==> m < b ==> data[m] <= pivot - if data[m].freq == data[pivot].freq && data[m].literal > data[pivot].literal || data[m].freq > data[pivot].freq { // data[m] = pivot - data[m], data[b-1] = data[b-1], data[m] - b-- - dups++ - } - // if at least 2 points are equal to pivot, assume skewed distribution - protect = dups > 1 - } - if protect { - // Protect against a lot of duplicates - // Add invariant: - // data[a <= i < b] unexamined - // data[b <= i < c] = pivot - for { - for ; a < b && (data[b-1].freq == data[pivot].freq && data[b-1].literal > data[pivot].literal || data[b-1].freq > data[pivot].freq); b-- { // data[b] == pivot - } - for ; a < b && (data[a].freq == data[pivot].freq && data[a].literal < data[pivot].literal || data[a].freq < data[pivot].freq); a++ { // data[a] < pivot - } - if a >= b { - break - } - // data[a] == pivot; data[b-1] < pivot - data[a], data[b-1] = data[b-1], data[a] - a++ - b-- - } - } - // Swap pivot into middle - data[pivot], data[b-1] = data[b-1], data[pivot] - return b - 1, c -} - -// Insertion sort -func insertionSortByFreq(data []literalNode, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && (data[j].freq == data[j-1].freq && data[j].literal < data[j-1].literal || data[j].freq < data[j-1].freq); j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// quickSortByFreq, loosely following Bentley and McIlroy, -// ``Engineering a Sort Function,'' SP&E November 1993. - -// medianOfThreeSortByFreq moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. -func medianOfThreeSortByFreq(data []literalNode, m1, m0, m2 int) { - // sort 3 elements - if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { - data[m1], data[m0] = data[m0], data[m1] - } - // data[m0] <= data[m1] - if data[m2].freq == data[m1].freq && data[m2].literal < data[m1].literal || data[m2].freq < data[m1].freq { - data[m2], data[m1] = data[m1], data[m2] - // data[m0] <= data[m2] && data[m1] < data[m2] - if data[m1].freq == data[m0].freq && data[m1].literal < data[m0].literal || data[m1].freq < data[m0].freq { - data[m1], data[m0] = data[m0], data[m1] - } - } - // now data[m0] <= data[m1] <= data[m2] -} diff --git a/src/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go b/src/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go deleted file mode 100644 index 93f1aea1..00000000 --- a/src/vendor/github.com/klauspost/compress/flate/huffman_sortByLiteral.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flate - -// Sort sorts data. -// It makes one call to data.Len to determine n, and O(n*log(n)) calls to -// data.Less and data.Swap. The sort is not guaranteed to be stable. -func sortByLiteral(data []literalNode) { - n := len(data) - quickSort(data, 0, n, maxDepth(n)) -} - -func quickSort(data []literalNode, a, b, maxDepth int) { - for b-a > 12 { // Use ShellSort for slices <= 12 elements - if maxDepth == 0 { - heapSort(data, a, b) - return - } - maxDepth-- - mlo, mhi := doPivot(data, a, b) - // Avoiding recursion on the larger subproblem guarantees - // a stack depth of at most lg(b-a). - if mlo-a < b-mhi { - quickSort(data, a, mlo, maxDepth) - a = mhi // i.e., quickSort(data, mhi, b) - } else { - quickSort(data, mhi, b, maxDepth) - b = mlo // i.e., quickSort(data, a, mlo) - } - } - if b-a > 1 { - // Do ShellSort pass with gap 6 - // It could be written in this simplified form cause b-a <= 12 - for i := a + 6; i < b; i++ { - if data[i].literal < data[i-6].literal { - data[i], data[i-6] = data[i-6], data[i] - } - } - insertionSort(data, a, b) - } -} -func heapSort(data []literalNode, a, b int) { - first := a - lo := 0 - hi := b - a - - // Build heap with greatest element at top. - for i := (hi - 1) / 2; i >= 0; i-- { - siftDown(data, i, hi, first) - } - - // Pop elements, largest first, into end of data. - for i := hi - 1; i >= 0; i-- { - data[first], data[first+i] = data[first+i], data[first] - siftDown(data, lo, i, first) - } -} - -// siftDown implements the heap property on data[lo, hi). -// first is an offset into the array where the root of the heap lies. -func siftDown(data []literalNode, lo, hi, first int) { - root := lo - for { - child := 2*root + 1 - if child >= hi { - break - } - if child+1 < hi && data[first+child].literal < data[first+child+1].literal { - child++ - } - if data[first+root].literal > data[first+child].literal { - return - } - data[first+root], data[first+child] = data[first+child], data[first+root] - root = child - } -} -func doPivot(data []literalNode, lo, hi int) (midlo, midhi int) { - m := int(uint(lo+hi) >> 1) // Written like this to avoid integer overflow. - if hi-lo > 40 { - // Tukey's ``Ninther,'' median of three medians of three. - s := (hi - lo) / 8 - medianOfThree(data, lo, lo+s, lo+2*s) - medianOfThree(data, m, m-s, m+s) - medianOfThree(data, hi-1, hi-1-s, hi-1-2*s) - } - medianOfThree(data, lo, m, hi-1) - - // Invariants are: - // data[lo] = pivot (set up by ChoosePivot) - // data[lo < i < a] < pivot - // data[a <= i < b] <= pivot - // data[b <= i < c] unexamined - // data[c <= i < hi-1] > pivot - // data[hi-1] >= pivot - pivot := lo - a, c := lo+1, hi-1 - - for ; a < c && data[a].literal < data[pivot].literal; a++ { - } - b := a - for { - for ; b < c && data[pivot].literal > data[b].literal; b++ { // data[b] <= pivot - } - for ; b < c && data[pivot].literal < data[c-1].literal; c-- { // data[c-1] > pivot - } - if b >= c { - break - } - // data[b] > pivot; data[c-1] <= pivot - data[b], data[c-1] = data[c-1], data[b] - b++ - c-- - } - // If hi-c<3 then there are duplicates (by property of median of nine). - // Let's be a bit more conservative, and set border to 5. - protect := hi-c < 5 - if !protect && hi-c < (hi-lo)/4 { - // Lets test some points for equality to pivot - dups := 0 - if data[pivot].literal > data[hi-1].literal { // data[hi-1] = pivot - data[c], data[hi-1] = data[hi-1], data[c] - c++ - dups++ - } - if data[b-1].literal > data[pivot].literal { // data[b-1] = pivot - b-- - dups++ - } - // m-lo = (hi-lo)/2 > 6 - // b-lo > (hi-lo)*3/4-1 > 8 - // ==> m < b ==> data[m] <= pivot - if data[m].literal > data[pivot].literal { // data[m] = pivot - data[m], data[b-1] = data[b-1], data[m] - b-- - dups++ - } - // if at least 2 points are equal to pivot, assume skewed distribution - protect = dups > 1 - } - if protect { - // Protect against a lot of duplicates - // Add invariant: - // data[a <= i < b] unexamined - // data[b <= i < c] = pivot - for { - for ; a < b && data[b-1].literal > data[pivot].literal; b-- { // data[b] == pivot - } - for ; a < b && data[a].literal < data[pivot].literal; a++ { // data[a] < pivot - } - if a >= b { - break - } - // data[a] == pivot; data[b-1] < pivot - data[a], data[b-1] = data[b-1], data[a] - a++ - b-- - } - } - // Swap pivot into middle - data[pivot], data[b-1] = data[b-1], data[pivot] - return b - 1, c -} - -// Insertion sort -func insertionSort(data []literalNode, a, b int) { - for i := a + 1; i < b; i++ { - for j := i; j > a && data[j].literal < data[j-1].literal; j-- { - data[j], data[j-1] = data[j-1], data[j] - } - } -} - -// maxDepth returns a threshold at which quicksort should switch -// to heapsort. It returns 2*ceil(lg(n+1)). -func maxDepth(n int) int { - var depth int - for i := n; i > 0; i >>= 1 { - depth++ - } - return depth * 2 -} - -// medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1]. -func medianOfThree(data []literalNode, m1, m0, m2 int) { - // sort 3 elements - if data[m1].literal < data[m0].literal { - data[m1], data[m0] = data[m0], data[m1] - } - // data[m0] <= data[m1] - if data[m2].literal < data[m1].literal { - data[m2], data[m1] = data[m1], data[m2] - // data[m0] <= data[m2] && data[m1] < data[m2] - if data[m1].literal < data[m0].literal { - data[m1], data[m0] = data[m0], data[m1] - } - } - // now data[m0] <= data[m1] <= data[m2] -} diff --git a/src/vendor/github.com/klauspost/compress/flate/inflate.go b/src/vendor/github.com/klauspost/compress/flate/inflate.go index 39dd683b..ad0ad3e2 100644 --- a/src/vendor/github.com/klauspost/compress/flate/inflate.go +++ b/src/vendor/github.com/klauspost/compress/flate/inflate.go @@ -14,6 +14,8 @@ import ( "io" "math/bits" "sync" + + "github.com/klauspost/compress/internal/regmask" ) const ( @@ -557,8 +559,8 @@ func (f *decompressor) readHuffman() error { return err } } - rep += int(f.b & uint32(1<<(nb®SizeMaskUint32)-1)) - f.b >>= nb & regSizeMaskUint32 + rep += int(f.b & uint32(1<<(nb®mask.Shift32ByUint)-1)) + f.b >>= nb & regmask.Shift32ByUint f.nb -= nb if i+rep > n { if debugDecode { @@ -731,7 +733,7 @@ func (f *decompressor) moreBits() error { return noEOF(err) } f.roffset++ - f.b |= uint32(c) << (f.nb & regSizeMaskUint32) + f.b |= uint32(c) << (f.nb & regmask.Shift32ByUint) f.nb += 8 return nil } @@ -756,7 +758,7 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { return 0, noEOF(err) } f.roffset++ - b |= uint32(c) << (nb & regSizeMaskUint32) + b |= uint32(c) << (nb & regmask.Shift32ByUint) nb += 8 } chunk := h.chunks[b&(huffmanNumChunks-1)] @@ -775,7 +777,7 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { f.err = CorruptInputError(f.roffset) return 0, f.err } - f.b = b >> (n & regSizeMaskUint32) + f.b = b >> (n & regmask.Shift32ByUint) f.nb = nb - n return int(chunk >> huffmanValueShift), nil } diff --git a/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go b/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go index e80f1965..55539156 100644 --- a/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go +++ b/src/vendor/github.com/klauspost/compress/flate/inflate_gen.go @@ -8,6 +8,8 @@ import ( "fmt" "math/bits" "strings" + + "github.com/klauspost/compress/internal/regmask" ) func peekBufio(fr *bufio.Reader) ([]byte, error) { @@ -62,7 +64,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] @@ -80,7 +82,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n v = int(chunk >> huffmanValueShift) break @@ -118,15 +120,15 @@ readLiteral: if debugDecode { fmt.Println("morebits n>0:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } length += int(fb & bitMask32[n]) - fb >>= n & regSizeMaskUint32 + fb >>= n & regmask.Shift32ByUint fnb -= n default: if debugDecode { @@ -146,11 +148,11 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb<5:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) @@ -174,7 +176,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] @@ -192,7 +194,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n dist = uint32(chunk >> huffmanValueShift) break @@ -206,7 +208,7 @@ readLiteral: case dist < maxNumDist: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. - extra := (dist & 1) << (nb & regSizeMaskUint32) + extra := (dist & 1) << (nb & regmask.Shift32ByUint) for fnb < nb { c, err := fr.ReadByte() if err != nil { @@ -214,17 +216,17 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fb >>= nb & regmask.Shift32ByUint fnb -= nb - dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + dist = 1<<((nb+1)®mask.Shift32ByUint) + 1 + extra // slower: dist = bitMask32[nb+1] + 2 + extra default: f.b, f.nb = fb, fnb @@ -313,7 +315,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] @@ -331,7 +333,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n v = int(chunk >> huffmanValueShift) break @@ -369,15 +371,15 @@ readLiteral: if debugDecode { fmt.Println("morebits n>0:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } length += int(fb & bitMask32[n]) - fb >>= n & regSizeMaskUint32 + fb >>= n & regmask.Shift32ByUint fnb -= n default: if debugDecode { @@ -397,11 +399,11 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb<5:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) @@ -425,7 +427,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] @@ -443,7 +445,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n dist = uint32(chunk >> huffmanValueShift) break @@ -457,7 +459,7 @@ readLiteral: case dist < maxNumDist: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. - extra := (dist & 1) << (nb & regSizeMaskUint32) + extra := (dist & 1) << (nb & regmask.Shift32ByUint) for fnb < nb { c, err := fr.ReadByte() if err != nil { @@ -465,17 +467,17 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fb >>= nb & regmask.Shift32ByUint fnb -= nb - dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + dist = 1<<((nb+1)®mask.Shift32ByUint) + 1 + extra // slower: dist = bitMask32[nb+1] + 2 + extra default: f.b, f.nb = fb, fnb @@ -573,7 +575,7 @@ readLiteral: c := pbuf[pos] pos++ f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] @@ -592,7 +594,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n v = int(chunk >> huffmanValueShift) break @@ -636,18 +638,18 @@ readLiteral: if debugDecode { fmt.Println("morebits n>0:", err) } - f.err = err + f.err = noEOF(err) return } } c := pbuf[pos] pos++ f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } length += int(fb & bitMask32[n]) - fb >>= n & regSizeMaskUint32 + fb >>= n & regmask.Shift32ByUint fnb -= n default: fr.Discard(pos) @@ -672,14 +674,14 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb<5:", err) } - f.err = err + f.err = noEOF(err) return } } c := pbuf[pos] pos++ f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) @@ -710,7 +712,7 @@ readLiteral: c := pbuf[pos] pos++ f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] @@ -729,7 +731,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n dist = uint32(chunk >> huffmanValueShift) break @@ -743,7 +745,7 @@ readLiteral: case dist < maxNumDist: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. - extra := (dist & 1) << (nb & regSizeMaskUint32) + extra := (dist & 1) << (nb & regmask.Shift32ByUint) for fnb < nb { if pos >= len(pbuf) { fr.Discard(pos) @@ -755,20 +757,20 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fb >>= nb & regmask.Shift32ByUint fnb -= nb - dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + dist = 1<<((nb+1)®mask.Shift32ByUint) + 1 + extra // slower: dist = bitMask32[nb+1] + 2 + extra default: fr.Discard(pos) @@ -860,7 +862,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] @@ -878,7 +880,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n v = int(chunk >> huffmanValueShift) break @@ -916,15 +918,15 @@ readLiteral: if debugDecode { fmt.Println("morebits n>0:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } length += int(fb & bitMask32[n]) - fb >>= n & regSizeMaskUint32 + fb >>= n & regmask.Shift32ByUint fnb -= n default: if debugDecode { @@ -944,11 +946,11 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb<5:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) @@ -972,7 +974,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] @@ -990,7 +992,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n dist = uint32(chunk >> huffmanValueShift) break @@ -1004,7 +1006,7 @@ readLiteral: case dist < maxNumDist: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. - extra := (dist & 1) << (nb & regSizeMaskUint32) + extra := (dist & 1) << (nb & regmask.Shift32ByUint) for fnb < nb { c, err := fr.ReadByte() if err != nil { @@ -1012,17 +1014,17 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fb >>= nb & regmask.Shift32ByUint fnb -= nb - dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + dist = 1<<((nb+1)®mask.Shift32ByUint) + 1 + extra // slower: dist = bitMask32[nb+1] + 2 + extra default: f.b, f.nb = fb, fnb @@ -1111,7 +1113,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hl.chunks[fb&(huffmanNumChunks-1)] @@ -1129,7 +1131,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n v = int(chunk >> huffmanValueShift) break @@ -1167,15 +1169,15 @@ readLiteral: if debugDecode { fmt.Println("morebits n>0:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } length += int(fb & bitMask32[n]) - fb >>= n & regSizeMaskUint32 + fb >>= n & regmask.Shift32ByUint fnb -= n default: if debugDecode { @@ -1195,11 +1197,11 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb<5:", err) } - f.err = err + f.err = noEOF(err) return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } dist = uint32(bits.Reverse8(uint8(fb & 0x1F << 3))) @@ -1223,7 +1225,7 @@ readLiteral: return } f.roffset++ - fb |= uint32(c) << (fnb & regSizeMaskUint32) + fb |= uint32(c) << (fnb & regmask.Shift32ByUint) fnb += 8 } chunk := f.hd.chunks[fb&(huffmanNumChunks-1)] @@ -1241,7 +1243,7 @@ readLiteral: f.err = CorruptInputError(f.roffset) return } - fb = fb >> (n & regSizeMaskUint32) + fb = fb >> (n & regmask.Shift32ByUint) fnb = fnb - n dist = uint32(chunk >> huffmanValueShift) break @@ -1255,7 +1257,7 @@ readLiteral: case dist < maxNumDist: nb := uint(dist-2) >> 1 // have 1 bit in bottom of dist, need nb more. - extra := (dist & 1) << (nb & regSizeMaskUint32) + extra := (dist & 1) << (nb & regmask.Shift32ByUint) for fnb < nb { c, err := fr.ReadByte() if err != nil { @@ -1263,17 +1265,17 @@ readLiteral: if debugDecode { fmt.Println("morebits f.nb>= nb & regSizeMaskUint32 + fb >>= nb & regmask.Shift32ByUint fnb -= nb - dist = 1<<((nb+1)®SizeMaskUint32) + 1 + extra + dist = 1<<((nb+1)®mask.Shift32ByUint) + 1 + extra // slower: dist = bitMask32[nb+1] + 2 + extra default: f.b, f.nb = fb, fnb diff --git a/src/vendor/github.com/klauspost/compress/flate/matchlen_generic.go b/src/vendor/github.com/klauspost/compress/flate/matchlen_generic.go index 6149384a..b897261a 100644 --- a/src/vendor/github.com/klauspost/compress/flate/matchlen_generic.go +++ b/src/vendor/github.com/klauspost/compress/flate/matchlen_generic.go @@ -12,18 +12,17 @@ import ( // matchLen returns the maximum common prefix length of a and b. // a must be the shortest of the two. func matchLen(a, b []byte) (n int) { - left := len(a) - for left >= 8 { - diff := le.Load64(a, n) ^ le.Load64(b, n) + // Keeping a and b the same length and reslicing them as we go + // lets the compiler prove that no bounds checks are needed. + b = b[:len(a)] + for len(a) >= 8 { + diff := le.Load64(a, 0) ^ le.Load64(b, 0) if diff != 0 { return n + bits.TrailingZeros64(diff)>>3 } + a, b = a[8:], b[8:] n += 8 - left -= 8 } - - a = a[n:] - b = b[n:] for i := range a { if a[i] != b[i] { break diff --git a/src/vendor/github.com/klauspost/compress/flate/regmask_amd64.go b/src/vendor/github.com/klauspost/compress/flate/regmask_amd64.go deleted file mode 100644 index 6ed28061..00000000 --- a/src/vendor/github.com/klauspost/compress/flate/regmask_amd64.go +++ /dev/null @@ -1,37 +0,0 @@ -package flate - -const ( - // Masks for shifts with register sizes of the shift value. - // This can be used to work around the x86 design of shifting by mod register size. - // It can be used when a variable shift is always smaller than the register size. - - // reg8SizeMaskX - shift value is 8 bits, shifted is X - reg8SizeMask8 = 7 - reg8SizeMask16 = 15 - reg8SizeMask32 = 31 - reg8SizeMask64 = 63 - - // reg16SizeMaskX - shift value is 16 bits, shifted is X - reg16SizeMask8 = reg8SizeMask8 - reg16SizeMask16 = reg8SizeMask16 - reg16SizeMask32 = reg8SizeMask32 - reg16SizeMask64 = reg8SizeMask64 - - // reg32SizeMaskX - shift value is 32 bits, shifted is X - reg32SizeMask8 = reg8SizeMask8 - reg32SizeMask16 = reg8SizeMask16 - reg32SizeMask32 = reg8SizeMask32 - reg32SizeMask64 = reg8SizeMask64 - - // reg64SizeMaskX - shift value is 64 bits, shifted is X - reg64SizeMask8 = reg8SizeMask8 - reg64SizeMask16 = reg8SizeMask16 - reg64SizeMask32 = reg8SizeMask32 - reg64SizeMask64 = reg8SizeMask64 - - // regSizeMaskUintX - shift value is uint, shifted is X - regSizeMaskUint8 = reg8SizeMask8 - regSizeMaskUint16 = reg8SizeMask16 - regSizeMaskUint32 = reg8SizeMask32 - regSizeMaskUint64 = reg8SizeMask64 -) diff --git a/src/vendor/github.com/klauspost/compress/flate/regmask_other.go b/src/vendor/github.com/klauspost/compress/flate/regmask_other.go deleted file mode 100644 index e62caf71..00000000 --- a/src/vendor/github.com/klauspost/compress/flate/regmask_other.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build !amd64 - -package flate - -const ( - // Masks for shifts with register sizes of the shift value. - // This can be used to work around the x86 design of shifting by mod register size. - // It can be used when a variable shift is always smaller than the register size. - - // reg8SizeMaskX - shift value is 8 bits, shifted is X - reg8SizeMask8 = 0xff - reg8SizeMask16 = 0xff - reg8SizeMask32 = 0xff - reg8SizeMask64 = 0xff - - // reg16SizeMaskX - shift value is 16 bits, shifted is X - reg16SizeMask8 = 0xffff - reg16SizeMask16 = 0xffff - reg16SizeMask32 = 0xffff - reg16SizeMask64 = 0xffff - - // reg32SizeMaskX - shift value is 32 bits, shifted is X - reg32SizeMask8 = 0xffffffff - reg32SizeMask16 = 0xffffffff - reg32SizeMask32 = 0xffffffff - reg32SizeMask64 = 0xffffffff - - // reg64SizeMaskX - shift value is 64 bits, shifted is X - reg64SizeMask8 = 0xffffffffffffffff - reg64SizeMask16 = 0xffffffffffffffff - reg64SizeMask32 = 0xffffffffffffffff - reg64SizeMask64 = 0xffffffffffffffff - - // regSizeMaskUintX - shift value is uint, shifted is X - regSizeMaskUint8 = ^uint(0) - regSizeMaskUint16 = ^uint(0) - regSizeMaskUint32 = ^uint(0) - regSizeMaskUint64 = ^uint(0) -) diff --git a/src/vendor/github.com/klauspost/compress/flate/token.go b/src/vendor/github.com/klauspost/compress/flate/token.go index d818790c..d31f6ccb 100644 --- a/src/vendor/github.com/klauspost/compress/flate/token.go +++ b/src/vendor/github.com/klauspost/compress/flate/token.go @@ -215,7 +215,11 @@ func mFastLog2(val float32) float32 { ux &= -0x7f800001 ux += 127 << 23 uval := math.Float32frombits(uint32(ux)) - log2 += ((-0.34484843)*uval+2.02466578)*uval - 0.67487759 + + p := float32(-0.34484843*uval) + 2.02466578 + q := float32(p*uval) - 0.67487759 + log2 += q + return log2 } @@ -232,7 +236,8 @@ func (t *tokens) EstimatedBits() int { for _, v := range t.litHist[:] { if v > 0 { n := float32(v) - shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + w := float32(atLeastOne(-mFastLog2(n*invTotal)) * n) + shannon += w } } // Just add 15 for EOB @@ -240,7 +245,8 @@ func (t *tokens) EstimatedBits() int { for i, v := range t.extraHist[1 : literalCount-256] { if v > 0 { n := float32(v) - shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + w := float32(atLeastOne(-mFastLog2(n*invTotal)) * n) + shannon += w bits += int(lengthExtraBits[i&31]) * int(v) nMatches += int(v) } @@ -251,7 +257,8 @@ func (t *tokens) EstimatedBits() int { for i, v := range t.offHist[:offsetCodeCount] { if v > 0 { n := float32(v) - shannon += atLeastOne(-mFastLog2(n*invTotal)) * n + w := float32(atLeastOne(-mFastLog2(n*invTotal)) * n) + shannon += w bits += int(offsetExtraBits[i&31]) * int(v) } } @@ -358,9 +365,6 @@ func (t token) offset() uint32 { return uint32(t) & offsetMask } func (t token) length() uint8 { return uint8(t >> lengthShift) } -// Convert length to code. -func lengthCode(len uint8) uint8 { return lengthCodes[len] } - // Returns the offset code corresponding to a specific offset func offsetCode(off uint32) uint32 { if false { diff --git a/src/vendor/github.com/klauspost/compress/huff0/bitreader.go b/src/vendor/github.com/klauspost/compress/huff0/bitreader.go index bfc7a523..faaa418a 100644 --- a/src/vendor/github.com/klauspost/compress/huff0/bitreader.go +++ b/src/vendor/github.com/klauspost/compress/huff0/bitreader.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "math/bits" "github.com/klauspost/compress/internal/le" ) @@ -210,6 +211,68 @@ func (b *bitReaderShifted) remaining() uint { return b.off*8 + uint(64-b.bitsRead) } +// canUseAsm reports whether the reader has a full 8-byte window ahead of +// its read pointer, which the Decompress4X asm loops need to take over. +func (b *bitReaderShifted) canUseAsm() bool { + return b.off >= 8 +} + +// prepareForAsm establishes the invariant the Decompress4X asm loops rely +// on: value == load64(in[off:off+8]) << bitsRead with bitsRead <= 7, so +// that a full group of symbols can never shift their sentinel bit out of +// the container. init leaves bitsRead == 8 when the final byte of the +// stream is exactly 0x01; that whole byte is consumed, so the same position +// is the window one byte lower with nothing consumed. Requires canUseAsm. +func (b *bitReaderShifted) prepareForAsm() { + if b.bitsRead >= 8 { + b.off-- + b.value = le.Load64(b.in, b.off) + b.bitsRead -= 8 + } +} + +// restoreFromAsm converts the state left behind by the Decompress4X asm +// loops back to the invariant the Go code relies on: value holds the 8 +// bytes at in[off:off+8] shifted left by bitsRead, with the low bitsRead +// bits zero. +// +// The asm keeps a sentinel bit in value just below the unread bits, so its +// trailing zero count is the number of consumed bits. The sentinel is ORed +// over the lowest bit of the window, which the loop never consumes before +// re-reading memory, so the window is re-read here too rather than taken +// from value. The asm reports off as the signed distance from the start of +// the stream, and it can be negative: a reload always reads a whole 8-byte +// window, so a stream that is nearly drained ends with up to 7 bytes of the +// previous stream (or the jump table) below its start inside the window. +// Those bytes sit below the stream's own bits and count as consumed. +// Anything further below, or more bits consumed than the stream holds, is +// corruption. +func (b *bitReaderShifted) restoreFromAsm() error { + off := int(b.off) + consumed := uint(bits.TrailingZeros64(b.value)) + if off < 0 { + if off < -7 { + return errors.New("corruption detected: stream underrun") + } + consumed += uint(-off) * 8 + if consumed > 64 { + return errors.New("corruption detected: stream underrun") + } + off = 0 + } + if off+8 > len(b.in) { + return errors.New("corruption detected: stream overrun") + } + b.off = uint(off) + b.bitsRead = uint8(consumed) + if consumed >= 64 { + b.value = 0 + } else { + b.value = le.Load64(b.in, b.off) << consumed + } + return nil +} + // close the bitstream and returns an error if out-of-buffer reads occurred. func (b *bitReaderShifted) close() error { // Release reference. diff --git a/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go b/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go index 2d6ef64b..e651f30e 100644 --- a/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go +++ b/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go @@ -1,222 +1,128 @@ //go:build amd64 && !appengine && !noasm && gc -// This file contains the specialisation of Decoder.Decompress4X -// and Decoder.Decompress1X that use an asm implementation of thir main loops. +// amd64 stubs and dispatch for the asm loops used by decompress_asm.go. package huff0 import ( - "errors" - "fmt" - "github.com/klauspost/compress/internal/cpuinfo" ) -// decompress4x_main_loop_x86 is an x86 assembler implementation -// of Decompress4X when tablelog > 8. +// decompress4x_main_loop_amd64 is an x86 assembler implementation +// of Decompress4X when tablelog > 8, decoding fastSymbols symbols per +// stream between bit container reloads. // //go:noescape func decompress4x_main_loop_amd64(ctx *decompress4xContext) -// decompress4x_8b_loop_x86 is an x86 assembler implementation -// of Decompress4X when tablelog <= 8 which decodes 4 entries -// per loop. +// decompress4x_8b_main_loop_amd64 is an x86 assembler implementation +// of Decompress4X when tablelog <= 8, decoding fast8bSymbols symbols +// per stream between bit container reloads. // //go:noescape func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) -// fallback8BitSize is the size where using Go version is faster. -const fallback8BitSize = 800 - -type decompress4xContext struct { - pbr *[4]bitReaderShifted - peekBits uint8 - out *byte - dstEvery int - tbl *dEntrySingle - decoded int - limit *byte -} +// decompress4x_4b_main_loop_amd64 is an x86 assembler implementation +// of Decompress4X when tablelog <= 4, decoding fast4bSymbols symbols +// per stream between bit container reloads. +// +//go:noescape +func decompress4x_4b_main_loop_amd64(ctx *decompress4xContext) -// Decompress4X will decompress a 4X encoded stream. -// The length of the supplied input must match the end of a block exactly. -// The *capacity* of the dst slice must match the destination size of -// the uncompressed data exactly. -func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { - if len(d.dt.single) == 0 { - return nil, errors.New("no table loaded") - } - if len(src) < 6+(4*1) { - return nil, errors.New("input too small") - } +// decompress4x_4b_main_loop_bmi2 is the BMI2 twin of decompress4x_4b_main_loop_amd64. +// +//go:noescape +func decompress4x_4b_main_loop_bmi2(ctx *decompress4xContext) - use8BitTables := d.actualTableLog <= 8 - if cap(dst) < fallback8BitSize && use8BitTables { - return d.decompress4X8bit(dst, src) - } +// decompress4x_main_loop_bmi2 is the BMI2 twin of decompress4x_main_loop_amd64. +// +//go:noescape +func decompress4x_main_loop_bmi2(ctx *decompress4xContext) - var br [4]bitReaderShifted - // Decode "jump table" - start := 6 - for i := range 3 { - length := int(src[i*2]) | (int(src[i*2+1]) << 8) - if start+length >= len(src) { - return nil, errors.New("truncated input (or invalid offset)") - } - err := br[i].init(src[start : start+length]) - if err != nil { - return nil, err - } - start += length - } - err := br[3].init(src[start:]) - if err != nil { - return nil, err - } +// decompress4x_8b_main_loop_bmi2 is the BMI2 twin of decompress4x_8b_main_loop_amd64. +// +//go:noescape +func decompress4x_8b_main_loop_bmi2(ctx *decompress4xContext) - // destination, offset to match first output - dstSize := cap(dst) - dst = dst[:dstSize] - out := dst - dstEvery := (dstSize + 3) / 4 - - const tlSize = 1 << tableLogMax - const tlMask = tlSize - 1 - single := d.dt.single[:tlSize] - - var decoded int - - if len(out) > 4*4 && !(br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4) { - ctx := decompress4xContext{ - pbr: &br, - peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() - out: &out[0], - dstEvery: dstEvery, - tbl: &single[0], - limit: &out[dstEvery-4], // Always stop decoding when first buffer gets here to avoid writing OOB on last. - } - if use8BitTables { - decompress4x_8b_main_loop_amd64(&ctx) - } else { - decompress4x_main_loop_amd64(&ctx) - } - - decoded = ctx.decoded - out = out[decoded/4:] - } +// decompress1x_main_loop_amd64 is an x86 assembler implementation +// of Decompress1X when tablelog > 8, decoding fastSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_main_loop_amd64(ctx *decompress1xContext) - // Decode remaining. - remainBytes := dstEvery - (decoded / 4) - for i := range br { - offset := dstEvery * i - endsAt := min(offset+remainBytes, len(out)) - br := &br[i] - bitsLeft := br.remaining() - for bitsLeft > 0 { - br.fill() - if offset >= endsAt { - return nil, errors.New("corruption detected: stream overrun 4") - } - - // Read value and increment offset. - val := br.peekBitsFast(d.actualTableLog) - v := single[val&tlMask].entry - nBits := uint8(v) - br.advance(nBits) - bitsLeft -= uint(nBits) - out[offset] = uint8(v >> 8) - offset++ - } - if offset != endsAt { - return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) - } - decoded += offset - dstEvery*i - err = br.close() - if err != nil { - return nil, err - } - } - if dstSize != decoded { - return nil, errors.New("corruption detected: short output block") - } - return dst, nil -} +// decompress1x_8b_main_loop_amd64 is an x86 assembler implementation +// of Decompress1X when tablelog <= 8, decoding fast8bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_8b_main_loop_amd64(ctx *decompress1xContext) -// decompress4x_main_loop_x86 is an x86 assembler implementation -// of Decompress1X when tablelog > 8. +// decompress1x_4b_main_loop_amd64 is an x86 assembler implementation +// of Decompress1X when tablelog <= 4, decoding fast4bSymbols symbols +// between bit container reloads. // //go:noescape -func decompress1x_main_loop_amd64(ctx *decompress1xContext) +func decompress1x_4b_main_loop_amd64(ctx *decompress1xContext) -// decompress4x_main_loop_x86 is an x86 with BMI2 assembler implementation -// of Decompress1X when tablelog > 8. +// decompress1x_main_loop_bmi2 is the BMI2 twin of decompress1x_main_loop_amd64. // //go:noescape func decompress1x_main_loop_bmi2(ctx *decompress1xContext) -type decompress1xContext struct { - pbr *bitReaderShifted - peekBits uint8 - out *byte - outCap int - tbl *dEntrySingle - decoded int +// decompress1x_8b_main_loop_bmi2 is the BMI2 twin of decompress1x_8b_main_loop_amd64. +// +//go:noescape +func decompress1x_8b_main_loop_bmi2(ctx *decompress1xContext) + +// decompress1x_4b_main_loop_bmi2 is the BMI2 twin of decompress1x_4b_main_loop_amd64. +// +//go:noescape +func decompress1x_4b_main_loop_bmi2(ctx *decompress1xContext) + +func decompress4x_main_loop_asm(ctx *decompress4xContext) { + if cpuinfo.HasBMI2() { + decompress4x_main_loop_bmi2(ctx) + } else { + decompress4x_main_loop_amd64(ctx) + } } -// Error reported by asm implementations -const error_max_decoded_size_exeeded = -1 +func decompress4x_8b_main_loop_asm(ctx *decompress4xContext) { + if cpuinfo.HasBMI2() { + decompress4x_8b_main_loop_bmi2(ctx) + } else { + decompress4x_8b_main_loop_amd64(ctx) + } +} -// Decompress1X will decompress a 1X encoded stream. -// The cap of the output buffer will be the maximum decompressed size. -// The length of the supplied input must match the end of a block exactly. -func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { - if len(d.dt.single) == 0 { - return nil, errors.New("no table loaded") +func decompress4x_4b_main_loop_asm(ctx *decompress4xContext) { + if cpuinfo.HasBMI2() { + decompress4x_4b_main_loop_bmi2(ctx) + } else { + decompress4x_4b_main_loop_amd64(ctx) } - var br bitReaderShifted - err := br.init(src) - if err != nil { - return dst, err +} + +func decompress1x_main_loop_asm(ctx *decompress1xContext) { + if cpuinfo.HasBMI2() { + decompress1x_main_loop_bmi2(ctx) + } else { + decompress1x_main_loop_amd64(ctx) } - maxDecodedSize := cap(dst) - dst = dst[:maxDecodedSize] - - const tlSize = 1 << tableLogMax - const tlMask = tlSize - 1 - - if maxDecodedSize >= 4 { - ctx := decompress1xContext{ - pbr: &br, - out: &dst[0], - outCap: maxDecodedSize, - peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() - tbl: &d.dt.single[0], - } - - if cpuinfo.HasBMI2() { - decompress1x_main_loop_bmi2(&ctx) - } else { - decompress1x_main_loop_amd64(&ctx) - } - if ctx.decoded == error_max_decoded_size_exeeded { - return nil, ErrMaxDecodedSizeExceeded - } - - dst = dst[:ctx.decoded] +} + +func decompress1x_8b_main_loop_asm(ctx *decompress1xContext) { + if cpuinfo.HasBMI2() { + decompress1x_8b_main_loop_bmi2(ctx) + } else { + decompress1x_8b_main_loop_amd64(ctx) } +} - // br < 8, so uint8 is fine - bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead - for bitsLeft > 0 { - br.fill() - if len(dst) >= maxDecodedSize { - br.close() - return nil, ErrMaxDecodedSizeExceeded - } - v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask] - nBits := uint8(v.entry) - br.advance(nBits) - bitsLeft -= nBits - dst = append(dst, uint8(v.entry>>8)) +func decompress1x_4b_main_loop_asm(ctx *decompress1xContext) { + if cpuinfo.HasBMI2() { + decompress1x_4b_main_loop_bmi2(ctx) + } else { + decompress1x_4b_main_loop_amd64(ctx) } - return dst, br.close() } diff --git a/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s b/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s index c4c7ab2d..f072c18f 100644 --- a/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s +++ b/src/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s @@ -1,830 +1,3386 @@ -// Code generated by command: go run gen.go -out ../decompress_amd64.s -pkg=huff0. DO NOT EDIT. +// Code generated by command: go run gen.go -out ../decompress.s -arch amd64,arm64 -pkg=huff0. DO NOT EDIT. -//go:build amd64 && !appengine && !noasm && gc +//go:build !appengine && !noasm && gc // func decompress4x_main_loop_amd64(ctx *decompress4xContext) +// Requires: BMI, CMOV TEXT ·decompress4x_main_loop_amd64(SB), $0-8 - // Preload values - MOVQ ctx+0(FP), AX - MOVBQZX 8(AX), DI - MOVQ 16(AX), BX - MOVQ 48(AX), SI - MOVQ 24(AX), R8 - MOVQ 32(AX), R9 - MOVQ (AX), R10 - - // Main loop -main_loop: - XORL DX, DX - CMPQ BX, SI - SETGE DL - - // br0.fillFast32() - MOVQ 32(R10), R11 - MOVBQZX 40(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill0 - MOVQ 24(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ (R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 24(R10) - ORQ R13, R11 - - // exhausted += (br0.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill0: - // val0 := br0.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br0.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br0.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 - - // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX - - // br0.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX) - - // update the bitreader structure - MOVQ R11, 32(R10) - MOVB R12, 40(R10) - - // br1.fillFast32() - MOVQ 80(R10), R11 - MOVBQZX 88(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill1 - MOVQ 72(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 48(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 72(R10) - ORQ R13, R11 - - // exhausted += (br1.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br1.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br1.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 - - // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX - - // br1.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX)(R8*1) - - // update the bitreader structure - MOVQ R11, 80(R10) - MOVB R12, 88(R10) - - // br2.fillFast32() - MOVQ 128(R10), R11 - MOVBQZX 136(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill2 - MOVQ 120(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 96(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 120(R10) - ORQ R13, R11 - - // exhausted += (br2.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br2.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br2.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 - - // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX - - // br2.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - MOVW AX, (BX)(R8*2) - - // update the bitreader structure - MOVQ R11, 128(R10) - MOVB R12, 136(R10) - - // br3.fillFast32() - MOVQ 176(R10), R11 - MOVBQZX 184(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill3 - MOVQ 168(R10), AX - SUBQ $0x20, R12 - SUBQ $0x04, AX - MOVQ 144(R10), R13 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (AX)(R13*1), R13 - MOVQ R12, CX - SHLQ CL, R13 - MOVQ AX, 168(R10) - ORQ R13, R11 - - // exhausted += (br3.off < 4) - CMPQ AX, $0x04 - ADCB $+0, DL - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br3.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 + MOVQ ctx+0(FP), AX - // val1 := br3.peekTopBits(peekBits) - MOVQ DI, CX - MOVQ R11, R13 - SHRQ CL, R13 - - // v1 := table[val1&mask] - MOVW (R9)(R13*2), CX - - // br3.advance(uint8(v1.entry)) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - - // these two writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - LEAQ (R8)(R8*2), CX - MOVW AX, (BX)(CX*1) - - // update the bitreader structure - MOVQ R11, 176(R10) - MOVB R12, 184(R10) - ADDQ $0x02, BX - TESTB DL, DL - JZ main_loop - MOVQ ctx+0(FP), AX - SUBQ 16(AX), BX - SHLQ $0x02, BX - MOVQ BX, 40(AX) + // Preload values + MOVBQZX 8(AX), DX + MOVQ 32(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), CX + LEAQ (SI)(CX*1), R8 + LEAQ (SI)(CX*2), R10 + LEAQ (CX)(CX*2), R12 + ADDQ SI, R12 + + // Convert each bit reader to sentinel form: bits = value | 1<> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX) - - // update the bitreader structure - MOVQ R11, 32(R10) - MOVB R12, 40(R10) - - // br1.fillFast32() - MOVQ 80(R10), R11 - MOVBQZX 88(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill1 - MOVQ 72(R10), R13 - SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 48(R10), R14 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 - MOVQ R12, CX - SHLQ CL, R14 - MOVQ R13, 72(R10) - ORQ R14, R11 + TZCNTQ R13, R14 + MOVQ R14, CX + ANDQ $0x07, CX + SHRQ $0x03, R14 + MOVQ 88(AX), R13 + SUBQ R14, R13 + MOVQ R13, 88(AX) + MOVQ (R13), R13 + ORQ $0x01, R13 + SHLQ CL, R13 + ADDQ $0x0e, SI + ADDQ $0x0e, R8 + ADDQ $0x0e, R10 + ADDQ $0x0e, R12 + CMPQ SI, 96(AX) + JB inner_loop + JMP outer_loop + +done: + // Hand the state back: off = ip - in (negative when the window reached below the stream start), + // value = the sentinel-form container. bitReaderShifted.restoreFromAsm normalizes both. + MOVQ (AX), CX + MOVQ 64(AX), DX + SUBQ (CX), DX + MOVQ DX, 24(CX) + MOVQ DI, 32(CX) + MOVQ 72(AX), DX + SUBQ 48(CX), DX + MOVQ DX, 72(CX) + MOVQ R9, 80(CX) + MOVQ 80(AX), DX + SUBQ 96(CX), DX + MOVQ DX, 120(CX) + MOVQ R11, 128(CX) + MOVQ 88(AX), DX + SUBQ 144(CX), DX + MOVQ DX, 168(CX) + MOVQ R13, 176(CX) + SUBQ 16(AX), SI + SHLQ $0x02, SI + MOVQ SI, 40(AX) + RET - // exhausted += (br1.off < 4) - CMPQ R13, $0x04 - ADCB $+0, DL +// func decompress4x_main_loop_bmi2(ctx *decompress4xContext) +// Requires: BMI, BMI2, CMOV +TEXT ·decompress4x_main_loop_bmi2(SB), $0-8 + MOVQ ctx+0(FP), AX -skip_fill1: - // val0 := br1.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 + // Preload values + MOVBQZX 8(AX), CX + MOVQ 32(AX), DX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + LEAQ (BX)(SI*1), DI + LEAQ (BX)(SI*2), R9 + LEAQ (SI)(SI*2), R11 + ADDQ BX, R11 + + // Convert each bit reader to sentinel form: bits = value | 1<> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX)(R8*1) - - // update the bitreader structure - MOVQ R11, 80(R10) - MOVB R12, 88(R10) - - // br2.fillFast32() - MOVQ 128(R10), R11 - MOVBQZX 136(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill2 - MOVQ 120(R10), R13 - SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 96(R10), R14 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 - MOVQ R12, CX + ANDQ $0x38, R13 + MOVQ -8(R8), R14 + SHRQ $0x01, R14 + ANDQ $0x07, R11 + MOVQ R13, CX + XORQ $0x3f, CX + SHRQ CL, R14 + MOVQ R11, CX SHLQ CL, R14 - MOVQ R13, 120(R10) - ORQ R14, R11 - - // exhausted += (br2.off < 4) - CMPQ R13, $0x04 - ADCB $+0, DL - -skip_fill2: - // val0 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br2.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br2.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX + ORQ R14, R10 + SHRQ $0x03, R13 + SUBQ R13, R8 + ADDQ $0x05, SI + CMPQ SI, R12 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), R8 + MOVQ R8, 24(CX) + MOVQ R10, 32(CX) + MOVB R11, 40(CX) + SUBQ 16(AX), SI + MOVQ SI, 40(AX) + RET - // br2.advance(uint8(v1.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX +// func decompress1x_8b_main_loop_amd64(ctx *decompress1xContext) +// Requires: CMOV +TEXT ·decompress1x_8b_main_loop_amd64(SB), $0-8 + MOVQ ctx+0(FP), AX - // val2 := br2.peekTopBits(peekBits) - MOVQ R11, R13 + // Preload values + MOVBQZX 8(AX), DX + MOVQ 32(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), DI + ADDQ SI, DI + MOVQ 56(AX), R8 + MOVQ 48(AX), R9 + MOVQ (AX), CX + MOVQ 32(CX), R10 + MOVBQZX 40(CX), R11 + +outer_loop: + // Iterations allowed by the output: (limit - op) / 8 MOVQ DI, CX - SHRQ CL, R13 - - // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br2.advance(uint8(v2.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 + SUBQ SI, CX + JLE done + SHRQ $0x03, CX + + // Iterations allowed by the input: a refill reads the 8 bytes below the window and + // moves it down by at most 7, so every read stays inside the stream while ip stays + // at least 8 above ilowest. + MOVQ R8, R12 + SUBQ R9, R12 + SHRQ $0x03, R12 + CMPQ R12, CX + CMOVQCS R12, CX + TESTQ CX, CX + JZ done + IMUL3Q $0x07, CX, R12 + ADDQ SI, R12 + +inner_loop: + // symbol 0 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, (SI) + + // symbol 1 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 1(SI) + + // symbol 2 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 2(SI) + + // symbol 3 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 3(SI) + + // symbol 4 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 4(SI) + + // symbol 5 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 5(SI) + + // symbol 6 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 6(SI) - // val3 := br2.peekTopBits(peekBits) + // Refill the whole bytes consumed from below the window MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br2.advance(uint8(v3.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - MOVL AX, (BX)(R8*2) - - // update the bitreader structure - MOVQ R11, 128(R10) - MOVB R12, 136(R10) - - // br3.fillFast32() - MOVQ 176(R10), R11 - MOVBQZX 184(R10), R12 - CMPQ R12, $0x20 - JBE skip_fill3 - MOVQ 168(R10), R13 - SUBQ $0x20, R12 - SUBQ $0x04, R13 - MOVQ 144(R10), R14 - - // b.value |= uint64(low) << (b.bitsRead & 63) - MOVL (R13)(R14*1), R14 - MOVQ R12, CX + ANDQ $0x38, R13 + MOVQ -8(R8), R14 + SHRQ $0x01, R14 + ANDQ $0x07, R11 + MOVQ R13, CX + XORQ $0x3f, CX + SHRQ CL, R14 + MOVQ R11, CX SHLQ CL, R14 - MOVQ R13, 168(R10) - ORQ R14, R11 - - // exhausted += (br3.off < 4) - CMPQ R13, $0x04 - ADCB $+0, DL - -skip_fill3: - // val0 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v0 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br3.advance(uint8(v0.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - - // val1 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v1 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br3.advance(uint8(v1.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // val2 := br3.peekTopBits(peekBits) - MOVQ R11, R13 - MOVQ DI, CX - SHRQ CL, R13 - - // v2 := table[val0&mask] - MOVW (R9)(R13*2), CX + ORQ R14, R10 + SHRQ $0x03, R13 + SUBQ R13, R8 + ADDQ $0x07, SI + CMPQ SI, R12 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), R8 + MOVQ R8, 24(CX) + MOVQ R10, 32(CX) + MOVB R11, 40(CX) + SUBQ 16(AX), SI + MOVQ SI, 40(AX) + RET - // br3.advance(uint8(v2.entry) - MOVB CH, AH - SHLQ CL, R11 - ADDB CL, R12 +// func decompress1x_4b_main_loop_amd64(ctx *decompress1xContext) +// Requires: CMOV +TEXT ·decompress1x_4b_main_loop_amd64(SB), $0-8 + MOVQ ctx+0(FP), AX - // val3 := br3.peekTopBits(peekBits) - MOVQ R11, R13 + // Preload values + MOVBQZX 8(AX), DX + MOVQ 32(AX), BX + MOVQ 16(AX), SI + MOVQ 24(AX), DI + ADDQ SI, DI + MOVQ 56(AX), R8 + MOVQ 48(AX), R9 + MOVQ (AX), CX + MOVQ 32(CX), R10 + MOVBQZX 40(CX), R11 + +outer_loop: + // Iterations allowed by the output: (limit - op) / 16 MOVQ DI, CX - SHRQ CL, R13 - - // v3 := table[val0&mask] - MOVW (R9)(R13*2), CX - - // br3.advance(uint8(v3.entry) - MOVB CH, AL - SHLQ CL, R11 - ADDB CL, R12 - BSWAPL AX - - // these four writes get coalesced - // out[id * dstEvery + 0] = uint8(v0.entry >> 8) - // out[id * dstEvery + 1] = uint8(v1.entry >> 8) - // out[id * dstEvery + 3] = uint8(v2.entry >> 8) - // out[id * dstEvery + 4] = uint8(v3.entry >> 8) - LEAQ (R8)(R8*2), CX - MOVL AX, (BX)(CX*1) - - // update the bitreader structure - MOVQ R11, 176(R10) - MOVB R12, 184(R10) - ADDQ $0x04, BX - TESTB DL, DL - JZ main_loop - MOVQ ctx+0(FP), AX - SUBQ 16(AX), BX - SHLQ $0x02, BX - MOVQ BX, 40(AX) - RET - -// func decompress1x_main_loop_amd64(ctx *decompress1xContext) -TEXT ·decompress1x_main_loop_amd64(SB), $0-8 - MOVQ ctx+0(FP), CX - MOVQ 16(CX), DX - MOVQ 24(CX), BX - CMPQ BX, $0x04 - JB error_max_decoded_size_exceeded - LEAQ (DX)(BX*1), BX - MOVQ (CX), SI - MOVQ (SI), R8 - MOVQ 24(SI), R9 - MOVQ 32(SI), R10 - MOVBQZX 40(SI), R11 - MOVQ 32(CX), SI - MOVBQZX 8(CX), DI - JMP loop_condition - -main_loop: - // Check if we have room for 4 bytes in the output buffer - LEAQ 4(DX), CX - CMPQ CX, BX - JGE error_max_decoded_size_exceeded - - // Decode 4 values - CMPQ R11, $0x20 - JL bitReader_fillFast_1_end - SUBQ $0x20, R11 - SUBQ $0x04, R9 - MOVL (R8)(R9*1), R12 - MOVQ R11, CX - SHLQ CL, R12 - ORQ R12, R10 - -bitReader_fillFast_1_end: - MOVQ DI, CX - MOVQ R10, R12 - SHRQ CL, R12 - MOVW (SI)(R12*2), CX - MOVB CH, AL - MOVBQZX CL, CX + SUBQ SI, CX + JLE done + SHRQ $0x04, CX + + // Iterations allowed by the input: a refill reads the 8 bytes below the window and + // moves it down by at most 7, so every read stays inside the stream while ip stays + // at least 8 above ilowest. + MOVQ R8, R12 + SUBQ R9, R12 + SHRQ $0x03, R12 + CMPQ R12, CX + CMOVQCS R12, CX + TESTQ CX, CX + JZ done + IMUL3Q $0x0e, CX, R12 + ADDQ SI, R12 + +inner_loop: + // symbol 0 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, (SI) + + // symbol 1 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX SHLQ CL, R10 - MOVQ DI, CX - MOVQ R10, R12 - SHRQ CL, R12 - MOVW (SI)(R12*2), CX - MOVB CH, AH - MOVBQZX CL, CX ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 1(SI) + + // symbol 2 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX SHLQ CL, R10 - BSWAPL AX - CMPQ R11, $0x20 - JL bitReader_fillFast_2_end - SUBQ $0x20, R11 - SUBQ $0x04, R9 - MOVL (R8)(R9*1), R12 - MOVQ R11, CX - SHLQ CL, R12 - ORQ R12, R10 - -bitReader_fillFast_2_end: - MOVQ DI, CX - MOVQ R10, R12 - SHRQ CL, R12 - MOVW (SI)(R12*2), CX - MOVB CH, AH - MOVBQZX CL, CX ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 2(SI) + + // symbol 3 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX SHLQ CL, R10 - MOVQ DI, CX - MOVQ R10, R12 - SHRQ CL, R12 - MOVW (SI)(R12*2), CX - MOVB CH, AL - MOVBQZX CL, CX ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 3(SI) + + // symbol 4 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 4(SI) + + // symbol 5 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 5(SI) + + // symbol 6 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 6(SI) + + // symbol 7 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 7(SI) + + // symbol 8 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 8(SI) + + // symbol 9 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX SHLQ CL, R10 - BSWAPL AX - - // Store the decoded values - MOVL AX, (DX) - ADDQ $0x04, DX - -loop_condition: - CMPQ R9, $0x08 - JGE main_loop - - // Update ctx structure - MOVQ ctx+0(FP), AX - SUBQ 16(AX), DX - MOVQ DX, 40(AX) - MOVQ (AX), AX - MOVQ R9, 24(AX) - MOVQ R10, 32(AX) - MOVB R11, 40(AX) - RET - - // Report error -error_max_decoded_size_exceeded: - MOVQ ctx+0(FP), AX - MOVQ $-1, CX - MOVQ CX, 40(AX) - RET - -// func decompress1x_main_loop_bmi2(ctx *decompress1xContext) -// Requires: BMI2 -TEXT ·decompress1x_main_loop_bmi2(SB), $0-8 - MOVQ ctx+0(FP), CX - MOVQ 16(CX), DX - MOVQ 24(CX), BX - CMPQ BX, $0x04 - JB error_max_decoded_size_exceeded - LEAQ (DX)(BX*1), BX - MOVQ (CX), SI - MOVQ (SI), R8 - MOVQ 24(SI), R9 - MOVQ 32(SI), R10 - MOVBQZX 40(SI), R11 - MOVQ 32(CX), SI - MOVBQZX 8(CX), DI - JMP loop_condition - -main_loop: - // Check if we have room for 4 bytes in the output buffer - LEAQ 4(DX), CX - CMPQ CX, BX - JGE error_max_decoded_size_exceeded - - // Decode 4 values - CMPQ R11, $0x20 - JL bitReader_fillFast_1_end - SUBQ $0x20, R11 - SUBQ $0x04, R9 - MOVL (R8)(R9*1), CX - SHLXQ R11, CX, CX - ORQ CX, R10 - -bitReader_fillFast_1_end: - SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX - MOVB CH, AL - MOVBQZX CL, CX ADDQ CX, R11 - SHLXQ CX, R10, R10 - SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX - MOVB CH, AH - MOVBQZX CL, CX + SHRQ $0x08, CX + MOVB CL, 9(SI) + + // symbol 10 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 ADDQ CX, R11 - SHLXQ CX, R10, R10 - BSWAPL AX - CMPQ R11, $0x20 - JL bitReader_fillFast_2_end - SUBQ $0x20, R11 - SUBQ $0x04, R9 - MOVL (R8)(R9*1), CX - SHLXQ R11, CX, CX - ORQ CX, R10 - -bitReader_fillFast_2_end: - SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX - MOVB CH, AH - MOVBQZX CL, CX + SHRQ $0x08, CX + MOVB CL, 10(SI) + + // symbol 11 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 ADDQ CX, R11 - SHLXQ CX, R10, R10 - SHRXQ DI, R10, CX - MOVW (SI)(CX*2), CX - MOVB CH, AL - MOVBQZX CL, CX + SHRQ $0x08, CX + MOVB CL, 11(SI) + + // symbol 12 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 ADDQ CX, R11 - SHLXQ CX, R10, R10 - BSWAPL AX + SHRQ $0x08, CX + MOVB CL, 12(SI) + + // symbol 13 + MOVQ DX, CX + MOVQ R10, R13 + SHRQ CL, R13 + MOVWQZX (BX)(R13*2), CX + SHLQ CL, R10 + ADDQ CX, R11 + SHRQ $0x08, CX + MOVB CL, 13(SI) - // Store the decoded values - MOVL AX, (DX) - ADDQ $0x04, DX + // Refill the whole bytes consumed from below the window + MOVQ R11, R13 + ANDQ $0x38, R13 + MOVQ -8(R8), R14 + SHRQ $0x01, R14 + ANDQ $0x07, R11 + MOVQ R13, CX + XORQ $0x3f, CX + SHRQ CL, R14 + MOVQ R11, CX + SHLQ CL, R14 + ORQ R14, R10 + SHRQ $0x03, R13 + SUBQ R13, R8 + ADDQ $0x0e, SI + CMPQ SI, R12 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), R8 + MOVQ R8, 24(CX) + MOVQ R10, 32(CX) + MOVB R11, 40(CX) + SUBQ 16(AX), SI + MOVQ SI, 40(AX) + RET + +// func decompress1x_main_loop_bmi2(ctx *decompress1xContext) +// Requires: BMI2, CMOV +TEXT ·decompress1x_main_loop_bmi2(SB), $0-8 + MOVQ ctx+0(FP), AX -loop_condition: - CMPQ R9, $0x08 - JGE main_loop + // Preload values + MOVBQZX 8(AX), CX + MOVQ 32(AX), DX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ BX, SI + MOVQ 56(AX), DI + MOVQ 48(AX), R8 + MOVQ (AX), R10 + MOVQ 32(R10), R9 + MOVBQZX 40(R10), R10 + +outer_loop: + // Iterations allowed by the output: (limit - op) / 8 + MOVQ SI, R11 + SUBQ BX, R11 + JLE done + SHRQ $0x03, R11 + + // Iterations allowed by the input: a refill reads the 8 bytes below the window and + // moves it down by at most 7, so every read stays inside the stream while ip stays + // at least 8 above ilowest. + MOVQ DI, R12 + SUBQ R8, R12 + SHRQ $0x03, R12 + CMPQ R12, R11 + CMOVQCS R12, R11 + TESTQ R11, R11 + JZ done + IMUL3Q $0x05, R11, R11 + ADDQ BX, R11 + +inner_loop: + // symbol 0 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, (BX) + + // symbol 1 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 1(BX) + + // symbol 2 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 2(BX) + + // symbol 3 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 3(BX) + + // symbol 4 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 4(BX) + + // Refill the whole bytes consumed from below the window + MOVQ R10, R12 + ANDQ $0x38, R12 + MOVQ -8(DI), R13 + SHRQ $0x01, R13 + ANDQ $0x07, R10 + MOVQ R12, R14 + XORQ $0x3f, R14 + SHRXQ R14, R13, R13 + SHLXQ R10, R13, R13 + ORQ R13, R9 + SHRQ $0x03, R12 + SUBQ R12, DI + ADDQ $0x05, BX + CMPQ BX, R11 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), DI + MOVQ DI, 24(CX) + MOVQ R9, 32(CX) + MOVB R10, 40(CX) + SUBQ 16(AX), BX + MOVQ BX, 40(AX) + RET - // Update ctx structure +// func decompress1x_8b_main_loop_bmi2(ctx *decompress1xContext) +// Requires: BMI2, CMOV +TEXT ·decompress1x_8b_main_loop_bmi2(SB), $0-8 MOVQ ctx+0(FP), AX - SUBQ 16(AX), DX - MOVQ DX, 40(AX) - MOVQ (AX), AX - MOVQ R9, 24(AX) - MOVQ R10, 32(AX) - MOVB R11, 40(AX) + + // Preload values + MOVBQZX 8(AX), CX + MOVQ 32(AX), DX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ BX, SI + MOVQ 56(AX), DI + MOVQ 48(AX), R8 + MOVQ (AX), R10 + MOVQ 32(R10), R9 + MOVBQZX 40(R10), R10 + +outer_loop: + // Iterations allowed by the output: (limit - op) / 8 + MOVQ SI, R11 + SUBQ BX, R11 + JLE done + SHRQ $0x03, R11 + + // Iterations allowed by the input: a refill reads the 8 bytes below the window and + // moves it down by at most 7, so every read stays inside the stream while ip stays + // at least 8 above ilowest. + MOVQ DI, R12 + SUBQ R8, R12 + SHRQ $0x03, R12 + CMPQ R12, R11 + CMOVQCS R12, R11 + TESTQ R11, R11 + JZ done + IMUL3Q $0x07, R11, R11 + ADDQ BX, R11 + +inner_loop: + // symbol 0 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, (BX) + + // symbol 1 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 1(BX) + + // symbol 2 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 2(BX) + + // symbol 3 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 3(BX) + + // symbol 4 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 4(BX) + + // symbol 5 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 5(BX) + + // symbol 6 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 6(BX) + + // Refill the whole bytes consumed from below the window + MOVQ R10, R12 + ANDQ $0x38, R12 + MOVQ -8(DI), R13 + SHRQ $0x01, R13 + ANDQ $0x07, R10 + MOVQ R12, R14 + XORQ $0x3f, R14 + SHRXQ R14, R13, R13 + SHLXQ R10, R13, R13 + ORQ R13, R9 + SHRQ $0x03, R12 + SUBQ R12, DI + ADDQ $0x07, BX + CMPQ BX, R11 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), DI + MOVQ DI, 24(CX) + MOVQ R9, 32(CX) + MOVB R10, 40(CX) + SUBQ 16(AX), BX + MOVQ BX, 40(AX) RET - // Report error -error_max_decoded_size_exceeded: +// func decompress1x_4b_main_loop_bmi2(ctx *decompress1xContext) +// Requires: BMI2, CMOV +TEXT ·decompress1x_4b_main_loop_bmi2(SB), $0-8 MOVQ ctx+0(FP), AX - MOVQ $-1, CX - MOVQ CX, 40(AX) + + // Preload values + MOVBQZX 8(AX), CX + MOVQ 32(AX), DX + MOVQ 16(AX), BX + MOVQ 24(AX), SI + ADDQ BX, SI + MOVQ 56(AX), DI + MOVQ 48(AX), R8 + MOVQ (AX), R10 + MOVQ 32(R10), R9 + MOVBQZX 40(R10), R10 + +outer_loop: + // Iterations allowed by the output: (limit - op) / 16 + MOVQ SI, R11 + SUBQ BX, R11 + JLE done + SHRQ $0x04, R11 + + // Iterations allowed by the input: a refill reads the 8 bytes below the window and + // moves it down by at most 7, so every read stays inside the stream while ip stays + // at least 8 above ilowest. + MOVQ DI, R12 + SUBQ R8, R12 + SHRQ $0x03, R12 + CMPQ R12, R11 + CMOVQCS R12, R11 + TESTQ R11, R11 + JZ done + IMUL3Q $0x0e, R11, R11 + ADDQ BX, R11 + +inner_loop: + // symbol 0 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, (BX) + + // symbol 1 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 1(BX) + + // symbol 2 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 2(BX) + + // symbol 3 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 3(BX) + + // symbol 4 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 4(BX) + + // symbol 5 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 5(BX) + + // symbol 6 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 6(BX) + + // symbol 7 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 7(BX) + + // symbol 8 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 8(BX) + + // symbol 9 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 9(BX) + + // symbol 10 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 10(BX) + + // symbol 11 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 11(BX) + + // symbol 12 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 12(BX) + + // symbol 13 + SHRXQ CX, R9, R12 + MOVWQZX (DX)(R12*2), R12 + SHLXQ R12, R9, R9 + ADDQ R12, R10 + SHRQ $0x08, R12 + MOVB R12, 13(BX) + + // Refill the whole bytes consumed from below the window + MOVQ R10, R12 + ANDQ $0x38, R12 + MOVQ -8(DI), R13 + SHRQ $0x01, R13 + ANDQ $0x07, R10 + MOVQ R12, R14 + XORQ $0x3f, R14 + SHRXQ R14, R13, R13 + SHLXQ R10, R13, R13 + ORQ R13, R9 + SHRQ $0x03, R12 + SUBQ R12, DI + ADDQ $0x0e, BX + CMPQ BX, R11 + JB inner_loop + JMP outer_loop + +done: + // Hand the state back in the Go bit reader's own form: off = ip - in, value, bitsRead. + MOVQ (AX), CX + SUBQ (CX), DI + MOVQ DI, 24(CX) + MOVQ R9, 32(CX) + MOVB R10, 40(CX) + SUBQ 16(AX), BX + MOVQ BX, 40(AX) RET diff --git a/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.go b/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.go new file mode 100644 index 00000000..d1988ad5 --- /dev/null +++ b/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.go @@ -0,0 +1,72 @@ +//go:build arm64 && !appengine && !noasm && gc + +// arm64 stubs and dispatch for the asm loops used by decompress_asm.go. +// The asm (decompress_arm64.s) is generated by the avo arm64 lowering +// printer from the same source as the amd64 asm; see _generate/gen.go. +package huff0 + +// decompress4x_main_loop_arm64 is an arm64 assembler implementation +// of Decompress4X when tablelog > 8, decoding fastSymbols symbols per +// stream between bit container reloads. +// +//go:noescape +func decompress4x_main_loop_arm64(ctx *decompress4xContext) + +// decompress4x_8b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress4X when tablelog <= 8, decoding fast8bSymbols symbols +// per stream between bit container reloads. +// +//go:noescape +func decompress4x_8b_main_loop_arm64(ctx *decompress4xContext) + +// decompress4x_4b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress4X when tablelog <= 4, decoding fast4bSymbols symbols +// per stream between bit container reloads. +// +//go:noescape +func decompress4x_4b_main_loop_arm64(ctx *decompress4xContext) + +// decompress1x_main_loop_arm64 is an arm64 assembler implementation +// of Decompress1X when tablelog > 8, decoding fastSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_main_loop_arm64(ctx *decompress1xContext) + +// decompress1x_8b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress1X when tablelog <= 8, decoding fast8bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_8b_main_loop_arm64(ctx *decompress1xContext) + +// decompress1x_4b_main_loop_arm64 is an arm64 assembler implementation +// of Decompress1X when tablelog <= 4, decoding fast4bSymbols symbols +// between bit container reloads. +// +//go:noescape +func decompress1x_4b_main_loop_arm64(ctx *decompress1xContext) + +func decompress4x_main_loop_asm(ctx *decompress4xContext) { + decompress4x_main_loop_arm64(ctx) +} + +func decompress4x_8b_main_loop_asm(ctx *decompress4xContext) { + decompress4x_8b_main_loop_arm64(ctx) +} + +func decompress4x_4b_main_loop_asm(ctx *decompress4xContext) { + decompress4x_4b_main_loop_arm64(ctx) +} + +func decompress1x_main_loop_asm(ctx *decompress1xContext) { + decompress1x_main_loop_arm64(ctx) +} + +func decompress1x_8b_main_loop_asm(ctx *decompress1xContext) { + decompress1x_8b_main_loop_arm64(ctx) +} + +func decompress1x_4b_main_loop_asm(ctx *decompress1xContext) { + decompress1x_4b_main_loop_arm64(ctx) +} diff --git a/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s b/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s new file mode 100644 index 00000000..971b8eb8 --- /dev/null +++ b/src/vendor/github.com/klauspost/compress/huff0/decompress_arm64.s @@ -0,0 +1,1657 @@ +// Code generated by command: go run gen.go -out ../decompress.s -arch amd64,arm64 -pkg=huff0. DO NOT EDIT. +// EXPERIMENTAL arm64 output lowered from an amd64 avo program. + +//go:build arm64 && (!appengine && !noasm && gc) + +// func decompress4x_main_loop_amd64(ctx *decompress4xContext) +// Requires: BMI, CMOV +TEXT ·decompress4x_main_loop_arm64(SB), $0-8 + MOVD ctx+0(FP), R0 + + // Preload values + MOVBU 8(R0), R2 + MOVD 32(R0), R3 + MOVD 16(R0), R5 + MOVD 24(R0), R1 + ADD R1, R5, R7 + ADD R1<<1, R5, R9 + ADD R1<<1, R1, R11 + ADD R5, R11, R11 + + // Convert each bit reader to sentinel form: bits = value | 1<= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + single := d.dt.single[:tlSize] + + var decoded int + + nSyms := fastSymbols + if d.actualTableLog <= 4 { + nSyms = fast4bSymbols + } else if use8BitTables { + nSyms = fast8bSymbols + } + // The asm writes nSyms bytes per stream per iteration and only re-checks + // its bounds between batches of iterations (the batch size is derived + // from limit in _generate/gen.go), so stream 0 must stop early enough + // that stream 3 (which may be up to 3 bytes shorter than dstEvery) + // never writes past the end of out. Every stream needs a full 8-byte + // window ahead of its read pointer to enter the loop. + if limit := dstEvery - nSyms - 2; limit > 0 && br[0].canUseAsm() && br[1].canUseAsm() && br[2].canUseAsm() && br[3].canUseAsm() { + for i := range br { + br[i].prepareForAsm() + } + ctx := decompress4xContext{ + pbr: &br, + peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() + out: &out[0], + dstEvery: dstEvery, + tbl: &single[0], + limit: &out[limit], + // The 6-byte jump table sits below stream 0 inside src, so the + // lowest window may reach into it; restoreFromAsm accounts for + // bytes below a stream's start. Bounding by src rather than by + // stream 0 keeps the asm running about six bytes longer, which + // matters for streams with very short codes. + ilowest: &src[0], + } + for i := range br { + ctx.ip[i] = &br[i].in[br[i].off] + } + switch nSyms { + case fast4bSymbols: + decompress4x_4b_main_loop_asm(&ctx) + case fast8bSymbols: + decompress4x_8b_main_loop_asm(&ctx) + default: + decompress4x_main_loop_asm(&ctx) + } + + decoded = ctx.decoded + out = out[decoded/4:] + for i := range br { + if err := br[i].restoreFromAsm(); err != nil { + return nil, err + } + } + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := min(offset+remainBytes, len(out)) + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if offset >= endsAt { + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + val := br.peekBitsFast(d.actualTableLog) + v := single[val&tlMask].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + return nil, err + } + } + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} + +// decompress1xContext is the argument block of the Decompress1X asm loops. +// Go fills every field but decoded; the asm advances ip, and on return +// leaves the bit reader in the form bitReaderShifted.restoreFromAsm expects. +type decompress1xContext struct { + pbr *bitReaderShifted + peekBits uint8 + out *byte + outCap int // no write reaches out[outCap] + tbl *dEntrySingle + decoded int + ilowest *byte // start of the stream; no read goes below it + ip *byte // the 8-byte input window, advanced by the asm +} + +// Decompress1X will decompress a 1X encoded stream. +// The cap of the output buffer will be the maximum decompressed size. +// The length of the supplied input must match the end of a block exactly. +func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + var br bitReaderShifted + err := br.init(src) + if err != nil { + return dst, err + } + maxDecodedSize := cap(dst) + dst = dst[:maxDecodedSize] + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + + // The asm decodes whole batches of symbols and only re-checks its + // bounds between them, so it needs at least one batch of room (the + // output bound rounds nSyms up to 16, see _generate/gen.go) and a full + // 8-byte window ahead of the read pointer to enter the loop. It also + // needs at most 7 bits consumed on entry so that a batch cannot run + // the container dry, which prepareForAsm establishes. + decoded := 0 + if maxDecodedSize >= 16 && br.canUseAsm() { + br.prepareForAsm() + ctx := decompress1xContext{ + pbr: &br, + out: &dst[0], + outCap: maxDecodedSize, + peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() + tbl: &d.dt.single[0], + ilowest: &src[0], + ip: &br.in[br.off], + } + if d.actualTableLog <= 4 { + decompress1x_4b_main_loop_asm(&ctx) + } else if d.actualTableLog <= 8 { + decompress1x_8b_main_loop_asm(&ctx) + } else { + decompress1x_main_loop_asm(&ctx) + } + decoded = ctx.decoded + } + dst = dst[:decoded] + + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if len(dst) >= maxDecodedSize { + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask] + nBits := uint8(v.entry) + br.advance(nBits) + bitsLeft -= uint(nBits) + dst = append(dst, uint8(v.entry>>8)) + } + return dst, br.close() +} diff --git a/src/vendor/github.com/klauspost/compress/huff0/decompress_generic.go b/src/vendor/github.com/klauspost/compress/huff0/decompress_generic.go index 61039232..e1bca5c6 100644 --- a/src/vendor/github.com/klauspost/compress/huff0/decompress_generic.go +++ b/src/vendor/github.com/klauspost/compress/huff0/decompress_generic.go @@ -1,4 +1,4 @@ -//go:build !amd64 || appengine || !gc || noasm +//go:build (!amd64 && !arm64) || appengine || !gc || noasm // This file contains a generic implementation of Decoder.Decompress4X. package huff0 diff --git a/src/vendor/github.com/klauspost/compress/internal/regmask/regmask.go b/src/vendor/github.com/klauspost/compress/internal/regmask/regmask.go new file mode 100644 index 00000000..3da49d15 --- /dev/null +++ b/src/vendor/github.com/klauspost/compress/internal/regmask/regmask.go @@ -0,0 +1,50 @@ +//go:build !386 + +// Package regmask provides masks for variable shift counts. +// +// Go defines a shift by more than the width of the shifted value as producing +// zero, so the compiler has to guard every variable shift against that: on +// amd64 with a CMP and an SBB, on arm64 with a CMP and a CSEL, and so on. When +// the count is known to be smaller than the width anyway, masking it with the +// width minus one lets the compiler drop the guard. The mask itself costs +// nothing on the architectures whose shift instructions already use only the +// low bits of the count, which the compiler knows about. +// +// Each constant is named for the width of the value being shifted and the type +// of the shift count, and may only be used where the count is always smaller +// than that width: +// +// x := y >> (n & regmask.Shift64ByUint) // y is 64 bits, n is a uint below 64 +package regmask + +const ( + // ShiftNByUint8 - shifting an N bit value by a uint8 + Shift8ByUint8 = 7 + Shift16ByUint8 = 15 + Shift32ByUint8 = 31 + Shift64ByUint8 = 63 + + // ShiftNByUint16 - shifting an N bit value by a uint16 + Shift8ByUint16 = Shift8ByUint8 + Shift16ByUint16 = Shift16ByUint8 + Shift32ByUint16 = Shift32ByUint8 + Shift64ByUint16 = Shift64ByUint8 + + // ShiftNByUint32 - shifting an N bit value by a uint32 + Shift8ByUint32 = Shift8ByUint8 + Shift16ByUint32 = Shift16ByUint8 + Shift32ByUint32 = Shift32ByUint8 + Shift64ByUint32 = Shift64ByUint8 + + // ShiftNByUint64 - shifting an N bit value by a uint64 + Shift8ByUint64 = Shift8ByUint8 + Shift16ByUint64 = Shift16ByUint8 + Shift32ByUint64 = Shift32ByUint8 + Shift64ByUint64 = Shift64ByUint8 + + // ShiftNByUint - shifting an N bit value by a uint + Shift8ByUint = Shift8ByUint8 + Shift16ByUint = Shift16ByUint8 + Shift32ByUint = Shift32ByUint8 + Shift64ByUint = Shift64ByUint8 +) diff --git a/src/vendor/github.com/klauspost/compress/internal/regmask/regmask_386.go b/src/vendor/github.com/klauspost/compress/internal/regmask/regmask_386.go new file mode 100644 index 00000000..ff15f7c1 --- /dev/null +++ b/src/vendor/github.com/klauspost/compress/internal/regmask/regmask_386.go @@ -0,0 +1,39 @@ +//go:build 386 + +package regmask + +// A 64 bit shift on 386 is synthesized from 32 bit instructions, and masking its +// count makes the compiler emit more code rather than less, so those masks are +// no-ops here: each is the largest value its count type can hold, which the +// compiler folds away. Shifts of narrower values behave as elsewhere. +const ( + // ShiftNByUint8 - shifting an N bit value by a uint8 + Shift8ByUint8 = 7 + Shift16ByUint8 = 15 + Shift32ByUint8 = 31 + Shift64ByUint8 = 0xff + + // ShiftNByUint16 - shifting an N bit value by a uint16 + Shift8ByUint16 = Shift8ByUint8 + Shift16ByUint16 = Shift16ByUint8 + Shift32ByUint16 = Shift32ByUint8 + Shift64ByUint16 = 0xffff + + // ShiftNByUint32 - shifting an N bit value by a uint32 + Shift8ByUint32 = Shift8ByUint8 + Shift16ByUint32 = Shift16ByUint8 + Shift32ByUint32 = Shift32ByUint8 + Shift64ByUint32 = 0xffffffff + + // ShiftNByUint64 - shifting an N bit value by a uint64 + Shift8ByUint64 = Shift8ByUint8 + Shift16ByUint64 = Shift16ByUint8 + Shift32ByUint64 = Shift32ByUint8 + Shift64ByUint64 = 0xffffffffffffffff + + // ShiftNByUint - shifting an N bit value by a uint + Shift8ByUint = Shift8ByUint8 + Shift16ByUint = Shift16ByUint8 + Shift32ByUint = Shift32ByUint8 + Shift64ByUint = ^uint(0) +) diff --git a/src/vendor/github.com/klauspost/compress/s2/encode_amd64.go b/src/vendor/github.com/klauspost/compress/s2/encode_asm.go similarity index 98% rename from src/vendor/github.com/klauspost/compress/s2/encode_amd64.go rename to src/vendor/github.com/klauspost/compress/s2/encode_asm.go index 68d72a41..eee24e72 100644 --- a/src/vendor/github.com/klauspost/compress/s2/encode_amd64.go +++ b/src/vendor/github.com/klauspost/compress/s2/encode_asm.go @@ -1,4 +1,4 @@ -//go:build !appengine && !noasm && gc +//go:build (amd64 || arm64) && !appengine && !noasm && gc package s2 @@ -8,7 +8,7 @@ import ( "github.com/klauspost/compress/internal/race" ) -const hasAmd64Asm = true +const hasAsm = true var encPools [4]sync.Pool diff --git a/src/vendor/github.com/klauspost/compress/s2/encode_better.go b/src/vendor/github.com/klauspost/compress/s2/encode_better.go index adbc57c4..2509d1c9 100644 --- a/src/vendor/github.com/klauspost/compress/s2/encode_better.go +++ b/src/vendor/github.com/klauspost/compress/s2/encode_better.go @@ -86,12 +86,18 @@ func encodeBlockBetterGo(dst, src []byte) (d int) { // We initialize repeat to 0, so we never match on first attempt repeat := 0 + // Cap the adaptive skip, as encodeBetterBlockAsm and the snappy Go encoder + // below already do. Without a cap, a long stretch with no matches lets the + // skip grow geometrically until it strides past the start of the next + // compressible region and loses the matches there. + const maxSkip = 100 + for { candidateL := 0 nextS := 0 for { // Next src position to check - nextS = s + (s-nextEmit)>>7 + 1 + nextS = s + min((s-nextEmit)>>7+1, maxSkip) if nextS > sLimit { goto emitRemainder } diff --git a/src/vendor/github.com/klauspost/compress/s2/encode_go.go b/src/vendor/github.com/klauspost/compress/s2/encode_go.go index 5597f3ef..0270d33b 100644 --- a/src/vendor/github.com/klauspost/compress/s2/encode_go.go +++ b/src/vendor/github.com/klauspost/compress/s2/encode_go.go @@ -1,4 +1,4 @@ -//go:build !amd64 || appengine || !gc || noasm +//go:build (!amd64 && !arm64) || appengine || !gc || noasm package s2 @@ -7,7 +7,7 @@ import ( "math/bits" ) -const hasAmd64Asm = false +const hasAsm = false // encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It // assumes that the varint-encoded length of the decompressed bytes has already diff --git a/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s b/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s index df9be687..92a17756 100644 --- a/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s +++ b/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s @@ -1,6 +1,6 @@ -// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg=s2. DO NOT EDIT. +// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_asm.go -pkg=s2. DO NOT EDIT. -//go:build !appengine && !noasm && gc && !noasm +//go:build (amd64 || arm64) && !appengine && !noasm && gc && !noasm #include "textflag.h" @@ -274,16 +274,10 @@ matchlen_loopback_16_repeat_extend_encodeBlockAsm: JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm matchlen_bsf_16repeat_extend_encodeBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm matchlen_match8_repeat_extend_encodeBlockAsm: CMPL R9, $0x08 @@ -296,16 +290,10 @@ matchlen_match8_repeat_extend_encodeBlockAsm: JMP matchlen_match4_repeat_extend_encodeBlockAsm matchlen_bsf_8_repeat_extend_encodeBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm matchlen_match4_repeat_extend_encodeBlockAsm: CMPL R9, $0x04 @@ -898,16 +886,10 @@ matchlen_loopback_16_match_nolit_encodeBlockAsm: JMP matchlen_loopback_16_match_nolit_encodeBlockAsm matchlen_bsf_16match_nolit_encodeBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeBlockAsm + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm matchlen_match8_match_nolit_encodeBlockAsm: CMPL DI, $0x08 @@ -920,16 +902,10 @@ matchlen_match8_match_nolit_encodeBlockAsm: JMP matchlen_match4_match_nolit_encodeBlockAsm matchlen_bsf_8_match_nolit_encodeBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeBlockAsm + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm matchlen_match4_match_nolit_encodeBlockAsm: CMPL DI, $0x04 @@ -1689,16 +1665,10 @@ matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB: JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB matchlen_bsf_16repeat_extend_encodeBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm4MB + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm4MB matchlen_match8_repeat_extend_encodeBlockAsm4MB: CMPL R9, $0x08 @@ -1711,16 +1681,10 @@ matchlen_match8_repeat_extend_encodeBlockAsm4MB: JMP matchlen_match4_repeat_extend_encodeBlockAsm4MB matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm4MB + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm4MB matchlen_match4_repeat_extend_encodeBlockAsm4MB: CMPL R9, $0x04 @@ -2263,16 +2227,10 @@ matchlen_loopback_16_match_nolit_encodeBlockAsm4MB: JMP matchlen_loopback_16_match_nolit_encodeBlockAsm4MB matchlen_bsf_16match_nolit_encodeBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeBlockAsm4MB + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm4MB matchlen_match8_match_nolit_encodeBlockAsm4MB: CMPL DI, $0x08 @@ -2285,16 +2243,10 @@ matchlen_match8_match_nolit_encodeBlockAsm4MB: JMP matchlen_match4_match_nolit_encodeBlockAsm4MB matchlen_bsf_8_match_nolit_encodeBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeBlockAsm4MB + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm4MB matchlen_match4_match_nolit_encodeBlockAsm4MB: CMPL DI, $0x04 @@ -3006,16 +2958,10 @@ matchlen_loopback_16_repeat_extend_encodeBlockAsm12B: JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm12B matchlen_bsf_16repeat_extend_encodeBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm12B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm12B matchlen_match8_repeat_extend_encodeBlockAsm12B: CMPL R9, $0x08 @@ -3028,16 +2974,10 @@ matchlen_match8_repeat_extend_encodeBlockAsm12B: JMP matchlen_match4_repeat_extend_encodeBlockAsm12B matchlen_bsf_8_repeat_extend_encodeBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm12B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm12B matchlen_match4_repeat_extend_encodeBlockAsm12B: CMPL R9, $0x04 @@ -3458,16 +3398,10 @@ matchlen_loopback_16_match_nolit_encodeBlockAsm12B: JMP matchlen_loopback_16_match_nolit_encodeBlockAsm12B matchlen_bsf_16match_nolit_encodeBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeBlockAsm12B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm12B matchlen_match8_match_nolit_encodeBlockAsm12B: CMPL DI, $0x08 @@ -3480,16 +3414,10 @@ matchlen_match8_match_nolit_encodeBlockAsm12B: JMP matchlen_match4_match_nolit_encodeBlockAsm12B matchlen_bsf_8_match_nolit_encodeBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeBlockAsm12B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm12B matchlen_match4_match_nolit_encodeBlockAsm12B: CMPL DI, $0x04 @@ -4091,16 +4019,10 @@ matchlen_loopback_16_repeat_extend_encodeBlockAsm10B: JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm10B matchlen_bsf_16repeat_extend_encodeBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm10B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm10B matchlen_match8_repeat_extend_encodeBlockAsm10B: CMPL R9, $0x08 @@ -4113,16 +4035,10 @@ matchlen_match8_repeat_extend_encodeBlockAsm10B: JMP matchlen_match4_repeat_extend_encodeBlockAsm10B matchlen_bsf_8_repeat_extend_encodeBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm10B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm10B matchlen_match4_repeat_extend_encodeBlockAsm10B: CMPL R9, $0x04 @@ -4543,16 +4459,10 @@ matchlen_loopback_16_match_nolit_encodeBlockAsm10B: JMP matchlen_loopback_16_match_nolit_encodeBlockAsm10B matchlen_bsf_16match_nolit_encodeBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeBlockAsm10B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm10B matchlen_match8_match_nolit_encodeBlockAsm10B: CMPL DI, $0x08 @@ -4565,16 +4475,10 @@ matchlen_match8_match_nolit_encodeBlockAsm10B: JMP matchlen_match4_match_nolit_encodeBlockAsm10B matchlen_bsf_8_match_nolit_encodeBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeBlockAsm10B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm10B matchlen_match4_match_nolit_encodeBlockAsm10B: CMPL DI, $0x04 @@ -5176,16 +5080,10 @@ matchlen_loopback_16_repeat_extend_encodeBlockAsm8B: JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm8B matchlen_bsf_16repeat_extend_encodeBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm8B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm8B matchlen_match8_repeat_extend_encodeBlockAsm8B: CMPL R9, $0x08 @@ -5198,16 +5096,10 @@ matchlen_match8_repeat_extend_encodeBlockAsm8B: JMP matchlen_match4_repeat_extend_encodeBlockAsm8B matchlen_bsf_8_repeat_extend_encodeBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP repeat_extend_forward_end_encodeBlockAsm8B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP repeat_extend_forward_end_encodeBlockAsm8B matchlen_match4_repeat_extend_encodeBlockAsm8B: CMPL R9, $0x04 @@ -5614,16 +5506,10 @@ matchlen_loopback_16_match_nolit_encodeBlockAsm8B: JMP matchlen_loopback_16_match_nolit_encodeBlockAsm8B matchlen_bsf_16match_nolit_encodeBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeBlockAsm8B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeBlockAsm8B matchlen_match8_match_nolit_encodeBlockAsm8B: CMPL DI, $0x08 @@ -5636,16 +5522,10 @@ matchlen_match8_match_nolit_encodeBlockAsm8B: JMP matchlen_match4_match_nolit_encodeBlockAsm8B matchlen_bsf_8_match_nolit_encodeBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeBlockAsm8B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeBlockAsm8B matchlen_match4_match_nolit_encodeBlockAsm8B: CMPL DI, $0x04 @@ -6140,16 +6020,10 @@ matchlen_loopback_16_match_nolit_encodeBetterBlockAsm: JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm matchlen_bsf_16match_nolit_encodeBetterBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm matchlen_match8_match_nolit_encodeBetterBlockAsm: CMPL R8, $0x08 @@ -6162,16 +6036,10 @@ matchlen_match8_match_nolit_encodeBetterBlockAsm: JMP matchlen_match4_match_nolit_encodeBetterBlockAsm matchlen_bsf_8_match_nolit_encodeBetterBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm matchlen_match4_match_nolit_encodeBetterBlockAsm: CMPL R8, $0x04 @@ -7235,16 +7103,10 @@ matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB: JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm4MB + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm4MB matchlen_match8_match_nolit_encodeBetterBlockAsm4MB: CMPL R8, $0x08 @@ -7257,16 +7119,10 @@ matchlen_match8_match_nolit_encodeBetterBlockAsm4MB: JMP matchlen_match4_match_nolit_encodeBetterBlockAsm4MB matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm4MB + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm4MB matchlen_match4_match_nolit_encodeBetterBlockAsm4MB: CMPL R8, $0x04 @@ -8256,16 +8112,10 @@ matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B: JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm12B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm12B matchlen_match8_match_nolit_encodeBetterBlockAsm12B: CMPL R8, $0x08 @@ -8278,16 +8128,10 @@ matchlen_match8_match_nolit_encodeBetterBlockAsm12B: JMP matchlen_match4_match_nolit_encodeBetterBlockAsm12B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm12B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm12B matchlen_match4_match_nolit_encodeBetterBlockAsm12B: CMPL R8, $0x04 @@ -9130,16 +8974,10 @@ matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B: JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm10B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm10B matchlen_match8_match_nolit_encodeBetterBlockAsm10B: CMPL R8, $0x08 @@ -9152,16 +8990,10 @@ matchlen_match8_match_nolit_encodeBetterBlockAsm10B: JMP matchlen_match4_match_nolit_encodeBetterBlockAsm10B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm10B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm10B matchlen_match4_match_nolit_encodeBetterBlockAsm10B: CMPL R8, $0x04 @@ -10004,16 +9836,10 @@ matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B: JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm8B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm8B matchlen_match8_match_nolit_encodeBetterBlockAsm8B: CMPL R8, $0x08 @@ -10026,16 +9852,10 @@ matchlen_match8_match_nolit_encodeBetterBlockAsm8B: JMP matchlen_match4_match_nolit_encodeBetterBlockAsm8B matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeBetterBlockAsm8B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeBetterBlockAsm8B matchlen_match4_match_nolit_encodeBetterBlockAsm8B: CMPL R8, $0x04 @@ -10985,16 +10805,10 @@ matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm: JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm matchlen_match8_repeat_extend_encodeSnappyBlockAsm: CMPL R8, $0x08 @@ -11007,16 +10821,10 @@ matchlen_match8_repeat_extend_encodeSnappyBlockAsm: JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm matchlen_match4_repeat_extend_encodeSnappyBlockAsm: CMPL R8, $0x04 @@ -11329,16 +11137,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm: JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm matchlen_bsf_16match_nolit_encodeSnappyBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm matchlen_match8_match_nolit_encodeSnappyBlockAsm: CMPL DI, $0x08 @@ -11351,16 +11153,10 @@ matchlen_match8_match_nolit_encodeSnappyBlockAsm: JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm matchlen_match4_match_nolit_encodeSnappyBlockAsm: CMPL DI, $0x04 @@ -11901,16 +11697,10 @@ matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K: JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K: CMPL R8, $0x08 @@ -11923,16 +11713,10 @@ matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K: JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K: CMPL R8, $0x04 @@ -12205,16 +11989,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K: JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm64K + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm64K matchlen_match8_match_nolit_encodeSnappyBlockAsm64K: CMPL DI, $0x08 @@ -12227,16 +12005,10 @@ matchlen_match8_match_nolit_encodeSnappyBlockAsm64K: JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm64K matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm64K + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm64K matchlen_match4_match_nolit_encodeSnappyBlockAsm64K: CMPL DI, $0x04 @@ -12737,16 +12509,10 @@ matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B: JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B: CMPL R8, $0x08 @@ -12759,16 +12525,10 @@ matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B: JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B: CMPL R8, $0x04 @@ -13041,16 +12801,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm12B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm12B matchlen_match8_match_nolit_encodeSnappyBlockAsm12B: CMPL DI, $0x08 @@ -13063,16 +12817,10 @@ matchlen_match8_match_nolit_encodeSnappyBlockAsm12B: JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm12B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm12B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm12B matchlen_match4_match_nolit_encodeSnappyBlockAsm12B: CMPL DI, $0x04 @@ -13573,16 +13321,10 @@ matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B: JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B: CMPL R8, $0x08 @@ -13595,16 +13337,10 @@ matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B: JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B: CMPL R8, $0x04 @@ -13877,16 +13613,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm10B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm10B matchlen_match8_match_nolit_encodeSnappyBlockAsm10B: CMPL DI, $0x08 @@ -13899,16 +13629,10 @@ matchlen_match8_match_nolit_encodeSnappyBlockAsm10B: JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm10B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm10B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm10B matchlen_match4_match_nolit_encodeSnappyBlockAsm10B: CMPL DI, $0x04 @@ -14409,16 +14133,10 @@ matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B: JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B: CMPL R8, $0x08 @@ -14431,16 +14149,10 @@ matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B: JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B: CMPL R8, $0x04 @@ -14711,16 +14423,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm8B + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm8B matchlen_match8_match_nolit_encodeSnappyBlockAsm8B: CMPL DI, $0x08 @@ -14733,16 +14439,10 @@ matchlen_match8_match_nolit_encodeSnappyBlockAsm8B: JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm8B matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_encodeSnappyBlockAsm8B + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_encodeSnappyBlockAsm8B matchlen_match4_match_nolit_encodeSnappyBlockAsm8B: CMPL DI, $0x04 @@ -15144,16 +14844,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm: JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm: CMPL R8, $0x08 @@ -15166,16 +14860,10 @@ matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm: JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm: CMPL R8, $0x04 @@ -15790,16 +15478,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K: JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K: CMPL R8, $0x08 @@ -15812,16 +15494,10 @@ matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K: JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K: CMPL R8, $0x04 @@ -16371,16 +16047,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B: CMPL R8, $0x08 @@ -16393,16 +16063,10 @@ matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B: JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B: CMPL R8, $0x04 @@ -16952,16 +16616,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B: CMPL R8, $0x08 @@ -16974,16 +16632,10 @@ matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B: JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B: CMPL R8, $0x04 @@ -17533,16 +17185,10 @@ matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B: JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R13, R13 - -#else - BSFQ R13, R13 - -#endif - SARQ $0x03, R13 - LEAL 8(R12)(R13*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + SARQ $0x03, R13 + LEAL 8(R12)(R13*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B: CMPL R8, $0x08 @@ -17555,16 +17201,10 @@ matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B: JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL (R12)(R11*1), R12 - JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + SARQ $0x03, R11 + LEAL (R12)(R11*1), R12 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B: CMPL R8, $0x04 @@ -18138,16 +17778,10 @@ matchlen_loopback_16_repeat_extend_calcBlockSize: JMP matchlen_loopback_16_repeat_extend_calcBlockSize matchlen_bsf_16repeat_extend_calcBlockSize: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_calcBlockSize + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_calcBlockSize matchlen_match8_repeat_extend_calcBlockSize: CMPL R8, $0x08 @@ -18160,16 +17794,10 @@ matchlen_match8_repeat_extend_calcBlockSize: JMP matchlen_match4_repeat_extend_calcBlockSize matchlen_bsf_8_repeat_extend_calcBlockSize: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_calcBlockSize + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_calcBlockSize matchlen_match4_repeat_extend_calcBlockSize: CMPL R8, $0x04 @@ -18371,16 +17999,10 @@ matchlen_loopback_16_match_nolit_calcBlockSize: JMP matchlen_loopback_16_match_nolit_calcBlockSize matchlen_bsf_16match_nolit_calcBlockSize: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_calcBlockSize + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_calcBlockSize matchlen_match8_match_nolit_calcBlockSize: CMPL DI, $0x08 @@ -18393,16 +18015,10 @@ matchlen_match8_match_nolit_calcBlockSize: JMP matchlen_match4_match_nolit_calcBlockSize matchlen_bsf_8_match_nolit_calcBlockSize: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_calcBlockSize + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_calcBlockSize matchlen_match4_match_nolit_calcBlockSize: CMPL DI, $0x04 @@ -18723,16 +18339,10 @@ matchlen_loopback_16_repeat_extend_calcBlockSizeSmall: JMP matchlen_loopback_16_repeat_extend_calcBlockSizeSmall matchlen_bsf_16repeat_extend_calcBlockSizeSmall: -#ifdef GOAMD64_v3 TZCNTQ R12, R12 - -#else - BSFQ R12, R12 - -#endif - SARQ $0x03, R12 - LEAL 8(R11)(R12*1), R11 - JMP repeat_extend_forward_end_calcBlockSizeSmall + SARQ $0x03, R12 + LEAL 8(R11)(R12*1), R11 + JMP repeat_extend_forward_end_calcBlockSizeSmall matchlen_match8_repeat_extend_calcBlockSizeSmall: CMPL R8, $0x08 @@ -18745,16 +18355,10 @@ matchlen_match8_repeat_extend_calcBlockSizeSmall: JMP matchlen_match4_repeat_extend_calcBlockSizeSmall matchlen_bsf_8_repeat_extend_calcBlockSizeSmall: -#ifdef GOAMD64_v3 TZCNTQ R10, R10 - -#else - BSFQ R10, R10 - -#endif - SARQ $0x03, R10 - LEAL (R11)(R10*1), R11 - JMP repeat_extend_forward_end_calcBlockSizeSmall + SARQ $0x03, R10 + LEAL (R11)(R10*1), R11 + JMP repeat_extend_forward_end_calcBlockSizeSmall matchlen_match4_repeat_extend_calcBlockSizeSmall: CMPL R8, $0x04 @@ -18926,16 +18530,10 @@ matchlen_loopback_16_match_nolit_calcBlockSizeSmall: JMP matchlen_loopback_16_match_nolit_calcBlockSizeSmall matchlen_bsf_16match_nolit_calcBlockSizeSmall: -#ifdef GOAMD64_v3 TZCNTQ R11, R11 - -#else - BSFQ R11, R11 - -#endif - SARQ $0x03, R11 - LEAL 8(R10)(R11*1), R10 - JMP match_nolit_end_calcBlockSizeSmall + SARQ $0x03, R11 + LEAL 8(R10)(R11*1), R10 + JMP match_nolit_end_calcBlockSizeSmall matchlen_match8_match_nolit_calcBlockSizeSmall: CMPL DI, $0x08 @@ -18948,16 +18546,10 @@ matchlen_match8_match_nolit_calcBlockSizeSmall: JMP matchlen_match4_match_nolit_calcBlockSizeSmall matchlen_bsf_8_match_nolit_calcBlockSizeSmall: -#ifdef GOAMD64_v3 TZCNTQ R9, R9 - -#else - BSFQ R9, R9 - -#endif - SARQ $0x03, R9 - LEAL (R10)(R9*1), R10 - JMP match_nolit_end_calcBlockSizeSmall + SARQ $0x03, R9 + LEAL (R10)(R9*1), R10 + JMP match_nolit_end_calcBlockSizeSmall matchlen_match4_match_nolit_calcBlockSizeSmall: CMPL DI, $0x04 @@ -19737,16 +19329,10 @@ matchlen_loopback_16_standalone: JMP matchlen_loopback_16_standalone matchlen_bsf_16standalone: -#ifdef GOAMD64_v3 TZCNTQ DI, DI - -#else - BSFQ DI, DI - -#endif - SARQ $0x03, DI - LEAL 8(SI)(DI*1), SI - JMP gen_match_len_end + SARQ $0x03, DI + LEAL 8(SI)(DI*1), SI + JMP gen_match_len_end matchlen_match8_standalone: CMPL DX, $0x08 @@ -19759,16 +19345,10 @@ matchlen_match8_standalone: JMP matchlen_match4_standalone matchlen_bsf_8_standalone: -#ifdef GOAMD64_v3 TZCNTQ BX, BX - -#else - BSFQ BX, BX - -#endif - SARQ $0x03, BX - LEAL (SI)(BX*1), SI - JMP gen_match_len_end + SARQ $0x03, BX + LEAL (SI)(BX*1), SI + JMP gen_match_len_end matchlen_match4_standalone: CMPL DX, $0x04 diff --git a/src/vendor/github.com/klauspost/compress/s2/encodeblock_arm64.s b/src/vendor/github.com/klauspost/compress/s2/encodeblock_arm64.s new file mode 100644 index 00000000..cfcb9e40 --- /dev/null +++ b/src/vendor/github.com/klauspost/compress/s2/encodeblock_arm64.s @@ -0,0 +1,23562 @@ +// Code generated by command: go run gen.go -out ../encodeblock.s -arch arm64 -arm64gen -pkg=s2. DO NOT EDIT. +// EXPERIMENTAL arm64 output lowered from an amd64 avo program. + +//go:build arm64 && ((amd64 || arm64) && !appengine && !noasm && gc && !noasm) + +#include "textflag.h" + +// func encodeBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBlockAsm: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBlockAsm + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBlockAsm: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBlockAsm + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R8, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeBlockAsm + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R7 + MOVWU R6, R5 + MOVWU 24(RSP), R16 + SUBSW R16, R5, R5 + BEQ repeat_extend_back_end_encodeBlockAsm + +repeat_extend_back_loop_encodeBlockAsm: + CMPW R7, R6 + BLS repeat_extend_back_end_encodeBlockAsm + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeBlockAsm + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R5, R5 + BNE repeat_extend_back_loop_encodeBlockAsm + +repeat_extend_back_end_encodeBlockAsm: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $5, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeBlockAsm + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeBlockAsm + CMPW $0x00010000, R5 + BLO three_bytes_repeat_emit_encodeBlockAsm + CMPW $0x01000000, R5 + BLO four_bytes_repeat_emit_encodeBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm + +four_bytes_repeat_emit_encodeBlockAsm: + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm + +three_bytes_repeat_emit_encodeBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm + +two_bytes_repeat_emit_encodeBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeBlockAsm + JMP memmove_long_repeat_emit_encodeBlockAsm + +one_byte_repeat_emit_encodeBlockAsm: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeBlockAsm: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm + +emit_lit_memmove_repeat_emit_encodeBlockAsm_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeBlockAsm: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeBlockAsm + +memmove_long_repeat_emit_encodeBlockAsm: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R11 + MOVD R8, R12 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_repeat_emit_encodeBlockAsmlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeBlockAsm: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R8 + SUBW R2, R8, R8 + ADD R2, R3, R9 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm: + CMPW $0x10, R8 + BLO matchlen_match8_repeat_extend_encodeBlockAsm + MOVD (R9)(R11), R10 + ADD R11, R9, R15 + MOVD 8(R15), R12 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm + ADD R11, R5, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16repeat_extend_encodeBlockAsm + SUB $16, R8, R8 + MOVWU R8, R8 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm + +matchlen_bsf_16repeat_extend_encodeBlockAsm: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm + +matchlen_match8_repeat_extend_encodeBlockAsm: + CMPW $0x08, R8 + BLO matchlen_match4_repeat_extend_encodeBlockAsm + MOVD (R9)(R11), R10 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm + SUB $8, R8, R8 + MOVWU R8, R8 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_repeat_extend_encodeBlockAsm + +matchlen_bsf_8_repeat_extend_encodeBlockAsm: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm + +matchlen_match4_repeat_extend_encodeBlockAsm: + CMPW $0x04, R8 + BLO matchlen_match2_repeat_extend_encodeBlockAsm + MOVWU (R9)(R11), R10 + MOVWU (R5)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_repeat_extend_encodeBlockAsm + SUB $4, R8, R8 + MOVWU R8, R8 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_repeat_extend_encodeBlockAsm: + CMPW $0x01, R8 + BEQ matchlen_match1_repeat_extend_encodeBlockAsm + BLO repeat_extend_forward_end_encodeBlockAsm + MOVHU (R9)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeBlockAsm + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R8, R8 + BEQ repeat_extend_forward_end_encodeBlockAsm + +matchlen_match1_repeat_extend_encodeBlockAsm: + MOVBU (R9)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R5, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeBlockAsm + ADD $1, R11, R11 + MOVWU R11, R11 + +repeat_extend_forward_end_encodeBlockAsm: + ADDW R11, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + TSTW R7, R7 + BEQ repeat_as_copy_encodeBlockAsm + + // emitRepeat +emit_repeat_again_match_repeat_encodeBlockAsm: + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_match_repeat_encodeBlockAsm + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_match_repeat_encodeBlockAsm + CMPW $0x00000800, R6 + BLO repeat_two_offset_match_repeat_encodeBlockAsm + +cant_repeat_two_offset_match_repeat_encodeBlockAsm: + CMPW $0x00000104, R5 + BLO repeat_three_match_repeat_encodeBlockAsm + CMPW $0x00010100, R5 + BLO repeat_four_match_repeat_encodeBlockAsm + CMPW $0x0100ffff, R5 + BLO repeat_five_match_repeat_encodeBlockAsm + SUB $16842747, R5, R5 + MOVWU R5, R5 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_repeat_encodeBlockAsm + +repeat_five_match_repeat_encodeBlockAsm: + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_match_repeat_encodeBlockAsm: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_match_repeat_encodeBlockAsm: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_match_repeat_encodeBlockAsm: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_match_repeat_encodeBlockAsm: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_as_copy_encodeBlockAsm: + // emitCopy + CMPW $0x00010000, R6 + BLO two_byte_offset_repeat_as_copy_encodeBlockAsm + CMPW $0x40, R5 + BLS four_bytes_remain_repeat_as_copy_encodeBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R6, 1(R1) + SUB $64, R5, R5 + MOVWU R5, R5 + ADD $0x05, R1, R1 + CMPW $0x04, R5 + BLO four_bytes_remain_repeat_as_copy_encodeBlockAsm + + // emitRepeat +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy: + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy + CMPW $0x0100ffff, R5 + BLO repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy + SUB $16842747, R5, R5 + MOVWU R5, R5 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy: + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +four_bytes_remain_repeat_as_copy_encodeBlockAsm: + TSTW R5, R5 + BEQ repeat_end_emit_encodeBlockAsm + MOVD $0, R7 + ADD R5<<2, R7, R5 + SUB $1, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVW R6, 1(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +two_byte_offset_repeat_as_copy_encodeBlockAsm: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeBlockAsm + CMPW $0x00000800, R6 + BHS long_offset_short_repeat_as_copy_encodeBlockAsm + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + MOVWU R6, R8 + LSRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R5, R5 + + // emitRepeat + SUB $4, R5, R5 + MOVWU R5, R5 + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + CMPW $0x0100ffff, R5 + BLO repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + SUB $16842747, R5, R5 + MOVWU R5, R5 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short_2b: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +long_offset_short_repeat_as_copy_encodeBlockAsm: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + + // emitRepeat +emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short: + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short + CMPW $0x0100ffff, R5 + BLO repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short + SUB $16842747, R5, R5 + MOVWU R5, R5 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_repeat_as_copy_encodeBlockAsm_emit_copy_short + +repeat_five_repeat_as_copy_encodeBlockAsm_emit_copy_short: + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_four_repeat_as_copy_encodeBlockAsm_emit_copy_short: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_three_repeat_as_copy_encodeBlockAsm_emit_copy_short: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_repeat_as_copy_encodeBlockAsm_emit_copy_short: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +repeat_two_offset_repeat_as_copy_encodeBlockAsm_emit_copy_short: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm + +emit_copy_three_repeat_as_copy_encodeBlockAsm: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeBlockAsm: + MOVW R2, 20(RSP) + JMP search_loop_encodeBlockAsm + +no_repeat_found_encodeBlockAsm: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBlockAsm + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeBlockAsm + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeBlockAsm + MOVWU 28(RSP), R2 + JMP search_loop_encodeBlockAsm + +candidate3_match_encodeBlockAsm: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeBlockAsm + +candidate2_match_encodeBlockAsm: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBlockAsm: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBlockAsm + +match_extend_back_loop_encodeBlockAsm: + CMPW R6, R2 + BLS match_extend_back_end_encodeBlockAsm + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBlockAsm + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBlockAsm + JMP match_extend_back_loop_encodeBlockAsm + +match_extend_back_end_encodeBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $5, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeBlockAsm + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeBlockAsm + CMPW $0x00010000, R7 + BLO three_bytes_match_emit_encodeBlockAsm + CMPW $0x01000000, R7 + BLO four_bytes_match_emit_encodeBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R7, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm + +four_bytes_match_emit_encodeBlockAsm: + MOVWU R7, R9 + LSRW $0x10, R9, R9 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + MOVB R9, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm + +three_bytes_match_emit_encodeBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm + +two_bytes_match_emit_encodeBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeBlockAsm + JMP memmove_long_match_emit_encodeBlockAsm + +one_byte_match_emit_encodeBlockAsm: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBlockAsm: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm + +emit_lit_memmove_match_emit_encodeBlockAsm_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBlockAsm: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeBlockAsm + +memmove_long_match_emit_encodeBlockAsm: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeBlockAsmlarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeBlockAsm: +match_nolit_loop_encodeBlockAsm: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeBlockAsm: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeBlockAsm + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeBlockAsm + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm + +matchlen_bsf_16match_nolit_encodeBlockAsm: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm + +matchlen_match8_match_nolit_encodeBlockAsm: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeBlockAsm + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeBlockAsm + +matchlen_bsf_8_match_nolit_encodeBlockAsm: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm + +matchlen_match4_match_nolit_encodeBlockAsm: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeBlockAsm + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeBlockAsm + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeBlockAsm: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeBlockAsm + BLO match_nolit_end_encodeBlockAsm + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBlockAsm + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeBlockAsm + +matchlen_match1_match_nolit_encodeBlockAsm: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBlockAsm + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeBlockAsm: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R5 + BLO two_byte_offset_match_nolit_encodeBlockAsm + CMPW $0x40, R9 + BLS four_bytes_remain_match_nolit_encodeBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + SUB $64, R9, R9 + MOVWU R9, R9 + ADD $0x05, R1, R1 + CMPW $0x04, R9 + BLO four_bytes_remain_match_nolit_encodeBlockAsm + + // emitRepeat +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy: + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm_emit_copy + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm_emit_copy + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm_emit_copy + CMPW $0x0100ffff, R9 + BLO repeat_five_match_nolit_encodeBlockAsm_emit_copy + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy + +repeat_five_match_nolit_encodeBlockAsm_emit_copy: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +four_bytes_remain_match_nolit_encodeBlockAsm: + TSTW R9, R9 + BEQ match_nolit_emitcopy_end_encodeBlockAsm + MOVD $0, R6 + ADD R9<<2, R6, R9 + SUB $1, R9, R9 + MOVWU R9, R9 + MOVB R9, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +two_byte_offset_match_nolit_encodeBlockAsm: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeBlockAsm + CMPW $0x00000800, R5 + BHS long_offset_short_match_nolit_encodeBlockAsm + MOVD $0x00000001, R6 + ADD $16, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + MOVWU R5, R7 + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b: + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b + CMPW $0x0100ffff, R9 + BLO repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short_2b + +repeat_five_match_nolit_encodeBlockAsm_emit_copy_short_2b: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy_short_2b: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short_2b: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +long_offset_short_match_nolit_encodeBlockAsm: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + + // emitRepeat +emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short: + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm_emit_copy_short + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm_emit_copy_short + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm_emit_copy_short + CMPW $0x0100ffff, R9 + BLO repeat_five_match_nolit_encodeBlockAsm_emit_copy_short + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBlockAsm_emit_copy_short + +repeat_five_match_nolit_encodeBlockAsm_emit_copy_short: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_four_match_nolit_encodeBlockAsm_emit_copy_short: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_three_match_nolit_encodeBlockAsm_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_match_nolit_encodeBlockAsm_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +repeat_two_offset_match_nolit_encodeBlockAsm_emit_copy_short: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +two_byte_offset_short_match_nolit_encodeBlockAsm: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeBlockAsm + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeBlockAsm + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm + +emit_copy_three_match_nolit_encodeBlockAsm: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBlockAsm + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm: + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x10, R7, R7 + MUL R8, R7, R7 + LSR $0x32, R7, R7 + LSL $0x10, R5, R5 + MUL R8, R5, R5 + LSR $0x32, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeBlockAsm + ADDW $1, R2, R2 + JMP search_loop_encodeBlockAsm + +emit_remainder_encodeBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $5, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBlockAsm + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBlockAsm + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBlockAsm + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeBlockAsm + CMPW $0x01000000, R2 + BLO four_bytes_emit_remainder_encodeBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R2, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm + +four_bytes_emit_remainder_encodeBlockAsm: + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm + +three_bytes_emit_remainder_encodeBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm + +two_bytes_emit_remainder_encodeBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBlockAsm + JMP memmove_long_emit_remainder_encodeBlockAsm + +one_byte_emit_remainder_encodeBlockAsm: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm + +emit_lit_memmove_emit_remainder_encodeBlockAsm_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBlockAsm: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBlockAsm + +memmove_long_emit_remainder_encodeBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBlockAsmlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBlockAsm: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBlockAsm4MB(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm4MB(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBlockAsm4MB: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBlockAsm4MB + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBlockAsm4MB: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBlockAsm4MB + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R8, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeBlockAsm4MB + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R7 + MOVWU R6, R5 + MOVWU 24(RSP), R16 + SUBSW R16, R5, R5 + BEQ repeat_extend_back_end_encodeBlockAsm4MB + +repeat_extend_back_loop_encodeBlockAsm4MB: + CMPW R7, R6 + BLS repeat_extend_back_end_encodeBlockAsm4MB + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeBlockAsm4MB + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R5, R5 + BNE repeat_extend_back_loop_encodeBlockAsm4MB + +repeat_extend_back_end_encodeBlockAsm4MB: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $4, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm4MB: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeBlockAsm4MB + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeBlockAsm4MB + CMPW $0x00010000, R5 + BLO three_bytes_repeat_emit_encodeBlockAsm4MB + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +three_bytes_repeat_emit_encodeBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +two_bytes_repeat_emit_encodeBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeBlockAsm4MB + JMP memmove_long_repeat_emit_encodeBlockAsm4MB + +one_byte_repeat_emit_encodeBlockAsm4MB: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm4MB + +emit_lit_memmove_repeat_emit_encodeBlockAsm4MB_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeBlockAsm4MB: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeBlockAsm4MB + +memmove_long_repeat_emit_encodeBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R11 + MOVD R8, R12 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_repeat_emit_encodeBlockAsm4MBlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeBlockAsm4MB: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R8 + SUBW R2, R8, R8 + ADD R2, R3, R9 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB: + CMPW $0x10, R8 + BLO matchlen_match8_repeat_extend_encodeBlockAsm4MB + MOVD (R9)(R11), R10 + ADD R11, R9, R15 + MOVD 8(R15), R12 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB + ADD R11, R5, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16repeat_extend_encodeBlockAsm4MB + SUB $16, R8, R8 + MOVWU R8, R8 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm4MB + +matchlen_bsf_16repeat_extend_encodeBlockAsm4MB: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match8_repeat_extend_encodeBlockAsm4MB: + CMPW $0x08, R8 + BLO matchlen_match4_repeat_extend_encodeBlockAsm4MB + MOVD (R9)(R11), R10 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB + SUB $8, R8, R8 + MOVWU R8, R8 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_repeat_extend_encodeBlockAsm4MB + +matchlen_bsf_8_repeat_extend_encodeBlockAsm4MB: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match4_repeat_extend_encodeBlockAsm4MB: + CMPW $0x04, R8 + BLO matchlen_match2_repeat_extend_encodeBlockAsm4MB + MOVWU (R9)(R11), R10 + MOVWU (R5)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_repeat_extend_encodeBlockAsm4MB + SUB $4, R8, R8 + MOVWU R8, R8 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_repeat_extend_encodeBlockAsm4MB: + CMPW $0x01, R8 + BEQ matchlen_match1_repeat_extend_encodeBlockAsm4MB + BLO repeat_extend_forward_end_encodeBlockAsm4MB + MOVHU (R9)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeBlockAsm4MB + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R8, R8 + BEQ repeat_extend_forward_end_encodeBlockAsm4MB + +matchlen_match1_repeat_extend_encodeBlockAsm4MB: + MOVBU (R9)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R5, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeBlockAsm4MB + ADD $1, R11, R11 + MOVWU R11, R11 + +repeat_extend_forward_end_encodeBlockAsm4MB: + ADDW R11, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + TSTW R7, R7 + BEQ repeat_as_copy_encodeBlockAsm4MB + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_match_repeat_encodeBlockAsm4MB + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB + CMPW $0x00000800, R6 + BLO repeat_two_offset_match_repeat_encodeBlockAsm4MB + +cant_repeat_two_offset_match_repeat_encodeBlockAsm4MB: + CMPW $0x00000104, R5 + BLO repeat_three_match_repeat_encodeBlockAsm4MB + CMPW $0x00010100, R5 + BLO repeat_four_match_repeat_encodeBlockAsm4MB + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_match_repeat_encodeBlockAsm4MB: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_match_repeat_encodeBlockAsm4MB: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_match_repeat_encodeBlockAsm4MB: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_match_repeat_encodeBlockAsm4MB: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_as_copy_encodeBlockAsm4MB: + // emitCopy + CMPW $0x00010000, R6 + BLO two_byte_offset_repeat_as_copy_encodeBlockAsm4MB + CMPW $0x40, R5 + BLS four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R6, 1(R1) + SUB $64, R5, R5 + MOVWU R5, R5 + ADD $0x05, R1, R1 + CMPW $0x04, R5 + BLO four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +four_bytes_remain_repeat_as_copy_encodeBlockAsm4MB: + TSTW R5, R5 + BEQ repeat_end_emit_encodeBlockAsm4MB + MOVD $0, R7 + ADD R5<<2, R7, R5 + SUB $1, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVW R6, 1(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +two_byte_offset_repeat_as_copy_encodeBlockAsm4MB: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB + CMPW $0x00000800, R6 + BHS long_offset_short_repeat_as_copy_encodeBlockAsm4MB + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R5, R5 + + // emitRepeat + SUB $4, R5, R5 + MOVWU R5, R5 + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short_2b: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +long_offset_short_repeat_as_copy_encodeBlockAsm4MB: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + CMPW $0x00010100, R5 + BLO repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short + SUB $65536, R5, R5 + MOVWU R5, R5 + MOVWU R5, R6 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ASRW $0x10, R6, R6 + MOVB R6, 4(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_four_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_three_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +repeat_two_offset_repeat_as_copy_encodeBlockAsm4MB_emit_copy_short: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm4MB: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm4MB + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm4MB + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm4MB + +emit_copy_three_repeat_as_copy_encodeBlockAsm4MB: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeBlockAsm4MB: + MOVW R2, 20(RSP) + JMP search_loop_encodeBlockAsm4MB + +no_repeat_found_encodeBlockAsm4MB: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBlockAsm4MB + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeBlockAsm4MB + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeBlockAsm4MB + MOVWU 28(RSP), R2 + JMP search_loop_encodeBlockAsm4MB + +candidate3_match_encodeBlockAsm4MB: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeBlockAsm4MB + +candidate2_match_encodeBlockAsm4MB: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBlockAsm4MB: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBlockAsm4MB + +match_extend_back_loop_encodeBlockAsm4MB: + CMPW R6, R2 + BLS match_extend_back_end_encodeBlockAsm4MB + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBlockAsm4MB + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBlockAsm4MB + JMP match_extend_back_loop_encodeBlockAsm4MB + +match_extend_back_end_encodeBlockAsm4MB: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $4, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm4MB: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeBlockAsm4MB + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeBlockAsm4MB + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeBlockAsm4MB + CMPW $0x00010000, R7 + BLO three_bytes_match_emit_encodeBlockAsm4MB + MOVWU R7, R9 + LSRW $0x10, R9, R9 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + MOVB R9, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm4MB + +three_bytes_match_emit_encodeBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm4MB + +two_bytes_match_emit_encodeBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeBlockAsm4MB + JMP memmove_long_match_emit_encodeBlockAsm4MB + +one_byte_match_emit_encodeBlockAsm4MB: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBlockAsm4MB: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBlockAsm4MB_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBlockAsm4MB: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeBlockAsm4MB + +memmove_long_match_emit_encodeBlockAsm4MB: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeBlockAsm4MBlarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeBlockAsm4MB: +match_nolit_loop_encodeBlockAsm4MB: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeBlockAsm4MB: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeBlockAsm4MB + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm4MB + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeBlockAsm4MB + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm4MB + +matchlen_bsf_16match_nolit_encodeBlockAsm4MB: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm4MB + +matchlen_match8_match_nolit_encodeBlockAsm4MB: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeBlockAsm4MB + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm4MB + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeBlockAsm4MB + +matchlen_bsf_8_match_nolit_encodeBlockAsm4MB: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm4MB + +matchlen_match4_match_nolit_encodeBlockAsm4MB: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeBlockAsm4MB + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeBlockAsm4MB + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeBlockAsm4MB: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeBlockAsm4MB + BLO match_nolit_end_encodeBlockAsm4MB + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBlockAsm4MB + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeBlockAsm4MB + +matchlen_match1_match_nolit_encodeBlockAsm4MB: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBlockAsm4MB + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeBlockAsm4MB: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R5 + BLO two_byte_offset_match_nolit_encodeBlockAsm4MB + CMPW $0x40, R9 + BLS four_bytes_remain_match_nolit_encodeBlockAsm4MB + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + SUB $64, R9, R9 + MOVWU R9, R9 + ADD $0x05, R1, R1 + CMPW $0x04, R9 + BLO four_bytes_remain_match_nolit_encodeBlockAsm4MB + + // emitRepeat + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +four_bytes_remain_match_nolit_encodeBlockAsm4MB: + TSTW R9, R9 + BEQ match_nolit_emitcopy_end_encodeBlockAsm4MB + MOVD $0, R6 + ADD R9<<2, R6, R9 + SUB $1, R9, R9 + MOVWU R9, R9 + MOVB R9, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +two_byte_offset_match_nolit_encodeBlockAsm4MB: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeBlockAsm4MB + CMPW $0x00000800, R5 + BHS long_offset_short_match_nolit_encodeBlockAsm4MB + MOVD $0x00000001, R6 + ADD $16, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short_2b: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +long_offset_short_match_nolit_encodeBlockAsm4MB: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short + CMPW $0x00010100, R9 + BLO repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R5 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ASRW $0x10, R5, R5 + MOVB R5, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_four_match_nolit_encodeBlockAsm4MB_emit_copy_short: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_three_match_nolit_encodeBlockAsm4MB_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_match_nolit_encodeBlockAsm4MB_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBlockAsm4MB_emit_copy_short: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +two_byte_offset_short_match_nolit_encodeBlockAsm4MB: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeBlockAsm4MB + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeBlockAsm4MB + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm4MB + +emit_copy_three_match_nolit_encodeBlockAsm4MB: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeBlockAsm4MB: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBlockAsm4MB + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm4MB: + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x10, R7, R7 + MUL R8, R7, R7 + LSR $0x32, R7, R7 + LSL $0x10, R5, R5 + MUL R8, R5, R5 + LSR $0x32, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeBlockAsm4MB + ADDW $1, R2, R2 + JMP search_loop_encodeBlockAsm4MB + +emit_remainder_encodeBlockAsm4MB: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $4, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm4MB: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBlockAsm4MB + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBlockAsm4MB + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBlockAsm4MB + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeBlockAsm4MB + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +three_bytes_emit_remainder_encodeBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +two_bytes_emit_remainder_encodeBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBlockAsm4MB + JMP memmove_long_emit_remainder_encodeBlockAsm4MB + +one_byte_emit_remainder_encodeBlockAsm4MB: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBlockAsm4MB: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBlockAsm4MB_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBlockAsm4MB: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBlockAsm4MB + +memmove_long_emit_remainder_encodeBlockAsm4MB: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBlockAsm4MBlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBlockAsm4MB: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm12B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000080, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBlockAsm12B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBlockAsm12B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBlockAsm12B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBlockAsm12B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x000000cf1bbcdcbb, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x18, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + LSL $0x18, R10, R10 + MUL R8, R10, R10 + LSR $0x34, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x18, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeBlockAsm12B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R7 + MOVWU R6, R5 + MOVWU 24(RSP), R16 + SUBSW R16, R5, R5 + BEQ repeat_extend_back_end_encodeBlockAsm12B + +repeat_extend_back_loop_encodeBlockAsm12B: + CMPW R7, R6 + BLS repeat_extend_back_end_encodeBlockAsm12B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeBlockAsm12B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R5, R5 + BNE repeat_extend_back_loop_encodeBlockAsm12B + +repeat_extend_back_end_encodeBlockAsm12B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm12B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeBlockAsm12B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeBlockAsm12B + BLO three_bytes_repeat_emit_encodeBlockAsm12B + +three_bytes_repeat_emit_encodeBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm12B + +two_bytes_repeat_emit_encodeBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeBlockAsm12B + JMP memmove_long_repeat_emit_encodeBlockAsm12B + +one_byte_repeat_emit_encodeBlockAsm12B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeBlockAsm12B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeBlockAsm12B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeBlockAsm12B + +memmove_long_repeat_emit_encodeBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R11 + MOVD R8, R12 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_repeat_emit_encodeBlockAsm12Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeBlockAsm12B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R8 + SUBW R2, R8, R8 + ADD R2, R3, R9 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm12B: + CMPW $0x10, R8 + BLO matchlen_match8_repeat_extend_encodeBlockAsm12B + MOVD (R9)(R11), R10 + ADD R11, R9, R15 + MOVD 8(R15), R12 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm12B + ADD R11, R5, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16repeat_extend_encodeBlockAsm12B + SUB $16, R8, R8 + MOVWU R8, R8 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm12B + +matchlen_bsf_16repeat_extend_encodeBlockAsm12B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match8_repeat_extend_encodeBlockAsm12B: + CMPW $0x08, R8 + BLO matchlen_match4_repeat_extend_encodeBlockAsm12B + MOVD (R9)(R11), R10 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm12B + SUB $8, R8, R8 + MOVWU R8, R8 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_repeat_extend_encodeBlockAsm12B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm12B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match4_repeat_extend_encodeBlockAsm12B: + CMPW $0x04, R8 + BLO matchlen_match2_repeat_extend_encodeBlockAsm12B + MOVWU (R9)(R11), R10 + MOVWU (R5)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_repeat_extend_encodeBlockAsm12B + SUB $4, R8, R8 + MOVWU R8, R8 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_repeat_extend_encodeBlockAsm12B: + CMPW $0x01, R8 + BEQ matchlen_match1_repeat_extend_encodeBlockAsm12B + BLO repeat_extend_forward_end_encodeBlockAsm12B + MOVHU (R9)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeBlockAsm12B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R8, R8 + BEQ repeat_extend_forward_end_encodeBlockAsm12B + +matchlen_match1_repeat_extend_encodeBlockAsm12B: + MOVBU (R9)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R5, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeBlockAsm12B + ADD $1, R11, R11 + MOVWU R11, R11 + +repeat_extend_forward_end_encodeBlockAsm12B: + ADDW R11, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + TSTW R7, R7 + BEQ repeat_as_copy_encodeBlockAsm12B + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_match_repeat_encodeBlockAsm12B + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_match_repeat_encodeBlockAsm12B + CMPW $0x00000800, R6 + BLO repeat_two_offset_match_repeat_encodeBlockAsm12B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm12B: + CMPW $0x00000104, R5 + BLO repeat_three_match_repeat_encodeBlockAsm12B + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_match_repeat_encodeBlockAsm12B: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_match_repeat_encodeBlockAsm12B: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_match_repeat_encodeBlockAsm12B: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_as_copy_encodeBlockAsm12B: + // emitCopy + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B + CMPW $0x00000800, R6 + BHS long_offset_short_repeat_as_copy_encodeBlockAsm12B + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R5, R5 + + // emitRepeat + SUB $4, R5, R5 + MOVWU R5, R5 + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short_2b: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +long_offset_short_repeat_as_copy_encodeBlockAsm12B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_three_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm12B_emit_copy_short: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm12B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm12B + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm12B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm12B + +emit_copy_three_repeat_as_copy_encodeBlockAsm12B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeBlockAsm12B: + MOVW R2, 20(RSP) + JMP search_loop_encodeBlockAsm12B + +no_repeat_found_encodeBlockAsm12B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBlockAsm12B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeBlockAsm12B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeBlockAsm12B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBlockAsm12B + +candidate3_match_encodeBlockAsm12B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeBlockAsm12B + +candidate2_match_encodeBlockAsm12B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBlockAsm12B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBlockAsm12B + +match_extend_back_loop_encodeBlockAsm12B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBlockAsm12B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBlockAsm12B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBlockAsm12B + JMP match_extend_back_loop_encodeBlockAsm12B + +match_extend_back_end_encodeBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeBlockAsm12B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeBlockAsm12B + BLO three_bytes_match_emit_encodeBlockAsm12B + +three_bytes_match_emit_encodeBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm12B + +two_bytes_match_emit_encodeBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeBlockAsm12B + JMP memmove_long_match_emit_encodeBlockAsm12B + +one_byte_match_emit_encodeBlockAsm12B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBlockAsm12B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm12B + +emit_lit_memmove_match_emit_encodeBlockAsm12B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBlockAsm12B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeBlockAsm12B + +memmove_long_match_emit_encodeBlockAsm12B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeBlockAsm12Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeBlockAsm12B: +match_nolit_loop_encodeBlockAsm12B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeBlockAsm12B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeBlockAsm12B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm12B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeBlockAsm12B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm12B + +matchlen_bsf_16match_nolit_encodeBlockAsm12B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm12B + +matchlen_match8_match_nolit_encodeBlockAsm12B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeBlockAsm12B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm12B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeBlockAsm12B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm12B + +matchlen_match4_match_nolit_encodeBlockAsm12B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeBlockAsm12B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeBlockAsm12B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeBlockAsm12B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeBlockAsm12B + BLO match_nolit_end_encodeBlockAsm12B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBlockAsm12B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeBlockAsm12B + +matchlen_match1_match_nolit_encodeBlockAsm12B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBlockAsm12B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeBlockAsm12B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeBlockAsm12B + CMPW $0x00000800, R5 + BHS long_offset_short_match_nolit_encodeBlockAsm12B + MOVD $0x00000001, R6 + ADD $16, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short_2b: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +long_offset_short_match_nolit_encodeBlockAsm12B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_three_match_nolit_encodeBlockAsm12B_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_match_nolit_encodeBlockAsm12B_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +repeat_two_offset_match_nolit_encodeBlockAsm12B_emit_copy_short: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +two_byte_offset_short_match_nolit_encodeBlockAsm12B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeBlockAsm12B + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeBlockAsm12B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm12B + +emit_copy_three_match_nolit_encodeBlockAsm12B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeBlockAsm12B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBlockAsm12B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm12B: + MOVD $0x000000cf1bbcdcbb, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x18, R7, R7 + MUL R8, R7, R7 + LSR $0x34, R7, R7 + LSL $0x18, R5, R5 + MUL R8, R5, R5 + LSR $0x34, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeBlockAsm12B + ADDW $1, R2, R2 + JMP search_loop_encodeBlockAsm12B + +emit_remainder_encodeBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBlockAsm12B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBlockAsm12B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBlockAsm12B + BLO three_bytes_emit_remainder_encodeBlockAsm12B + +three_bytes_emit_remainder_encodeBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm12B + +two_bytes_emit_remainder_encodeBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBlockAsm12B + JMP memmove_long_emit_remainder_encodeBlockAsm12B + +one_byte_emit_remainder_encodeBlockAsm12B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBlockAsm12B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBlockAsm12B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBlockAsm12B + +memmove_long_emit_remainder_encodeBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBlockAsm12Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBlockAsm12B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm10B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000020, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBlockAsm10B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBlockAsm10B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBlockAsm10B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBlockAsm10B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x9e3779b1, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R8, R10, R10 + LSR $0x36, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeBlockAsm10B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R7 + MOVWU R6, R5 + MOVWU 24(RSP), R16 + SUBSW R16, R5, R5 + BEQ repeat_extend_back_end_encodeBlockAsm10B + +repeat_extend_back_loop_encodeBlockAsm10B: + CMPW R7, R6 + BLS repeat_extend_back_end_encodeBlockAsm10B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeBlockAsm10B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R5, R5 + BNE repeat_extend_back_loop_encodeBlockAsm10B + +repeat_extend_back_end_encodeBlockAsm10B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm10B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeBlockAsm10B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeBlockAsm10B + BLO three_bytes_repeat_emit_encodeBlockAsm10B + +three_bytes_repeat_emit_encodeBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm10B + +two_bytes_repeat_emit_encodeBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeBlockAsm10B + JMP memmove_long_repeat_emit_encodeBlockAsm10B + +one_byte_repeat_emit_encodeBlockAsm10B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeBlockAsm10B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeBlockAsm10B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeBlockAsm10B + +memmove_long_repeat_emit_encodeBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R11 + MOVD R8, R12 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_repeat_emit_encodeBlockAsm10Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeBlockAsm10B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R8 + SUBW R2, R8, R8 + ADD R2, R3, R9 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm10B: + CMPW $0x10, R8 + BLO matchlen_match8_repeat_extend_encodeBlockAsm10B + MOVD (R9)(R11), R10 + ADD R11, R9, R15 + MOVD 8(R15), R12 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm10B + ADD R11, R5, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16repeat_extend_encodeBlockAsm10B + SUB $16, R8, R8 + MOVWU R8, R8 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm10B + +matchlen_bsf_16repeat_extend_encodeBlockAsm10B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match8_repeat_extend_encodeBlockAsm10B: + CMPW $0x08, R8 + BLO matchlen_match4_repeat_extend_encodeBlockAsm10B + MOVD (R9)(R11), R10 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm10B + SUB $8, R8, R8 + MOVWU R8, R8 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_repeat_extend_encodeBlockAsm10B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm10B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match4_repeat_extend_encodeBlockAsm10B: + CMPW $0x04, R8 + BLO matchlen_match2_repeat_extend_encodeBlockAsm10B + MOVWU (R9)(R11), R10 + MOVWU (R5)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_repeat_extend_encodeBlockAsm10B + SUB $4, R8, R8 + MOVWU R8, R8 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_repeat_extend_encodeBlockAsm10B: + CMPW $0x01, R8 + BEQ matchlen_match1_repeat_extend_encodeBlockAsm10B + BLO repeat_extend_forward_end_encodeBlockAsm10B + MOVHU (R9)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeBlockAsm10B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R8, R8 + BEQ repeat_extend_forward_end_encodeBlockAsm10B + +matchlen_match1_repeat_extend_encodeBlockAsm10B: + MOVBU (R9)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R5, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeBlockAsm10B + ADD $1, R11, R11 + MOVWU R11, R11 + +repeat_extend_forward_end_encodeBlockAsm10B: + ADDW R11, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + TSTW R7, R7 + BEQ repeat_as_copy_encodeBlockAsm10B + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_match_repeat_encodeBlockAsm10B + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_match_repeat_encodeBlockAsm10B + CMPW $0x00000800, R6 + BLO repeat_two_offset_match_repeat_encodeBlockAsm10B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm10B: + CMPW $0x00000104, R5 + BLO repeat_three_match_repeat_encodeBlockAsm10B + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_match_repeat_encodeBlockAsm10B: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_match_repeat_encodeBlockAsm10B: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_match_repeat_encodeBlockAsm10B: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_as_copy_encodeBlockAsm10B: + // emitCopy + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B + CMPW $0x00000800, R6 + BHS long_offset_short_repeat_as_copy_encodeBlockAsm10B + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R5, R5 + + // emitRepeat + SUB $4, R5, R5 + MOVWU R5, R5 + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short_2b: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +long_offset_short_repeat_as_copy_encodeBlockAsm10B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R5, R7 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R7 + BLS repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + CMPW $0x00000800, R6 + BLO repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_three_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +repeat_two_offset_repeat_as_copy_encodeBlockAsm10B_emit_copy_short: + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm10B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm10B + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm10B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm10B + +emit_copy_three_repeat_as_copy_encodeBlockAsm10B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeBlockAsm10B: + MOVW R2, 20(RSP) + JMP search_loop_encodeBlockAsm10B + +no_repeat_found_encodeBlockAsm10B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBlockAsm10B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeBlockAsm10B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeBlockAsm10B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBlockAsm10B + +candidate3_match_encodeBlockAsm10B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeBlockAsm10B + +candidate2_match_encodeBlockAsm10B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBlockAsm10B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBlockAsm10B + +match_extend_back_loop_encodeBlockAsm10B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBlockAsm10B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBlockAsm10B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBlockAsm10B + JMP match_extend_back_loop_encodeBlockAsm10B + +match_extend_back_end_encodeBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeBlockAsm10B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeBlockAsm10B + BLO three_bytes_match_emit_encodeBlockAsm10B + +three_bytes_match_emit_encodeBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm10B + +two_bytes_match_emit_encodeBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeBlockAsm10B + JMP memmove_long_match_emit_encodeBlockAsm10B + +one_byte_match_emit_encodeBlockAsm10B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBlockAsm10B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm10B + +emit_lit_memmove_match_emit_encodeBlockAsm10B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBlockAsm10B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeBlockAsm10B + +memmove_long_match_emit_encodeBlockAsm10B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeBlockAsm10Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeBlockAsm10B: +match_nolit_loop_encodeBlockAsm10B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeBlockAsm10B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeBlockAsm10B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm10B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeBlockAsm10B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm10B + +matchlen_bsf_16match_nolit_encodeBlockAsm10B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm10B + +matchlen_match8_match_nolit_encodeBlockAsm10B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeBlockAsm10B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm10B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeBlockAsm10B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm10B + +matchlen_match4_match_nolit_encodeBlockAsm10B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeBlockAsm10B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeBlockAsm10B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeBlockAsm10B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeBlockAsm10B + BLO match_nolit_end_encodeBlockAsm10B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBlockAsm10B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeBlockAsm10B + +matchlen_match1_match_nolit_encodeBlockAsm10B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBlockAsm10B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeBlockAsm10B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeBlockAsm10B + CMPW $0x00000800, R5 + BHS long_offset_short_match_nolit_encodeBlockAsm10B + MOVD $0x00000001, R6 + ADD $16, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short_2b: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +long_offset_short_match_nolit_encodeBlockAsm10B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R9, R6 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R6 + BLS repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short + CMPW $0x00000800, R5 + BLO repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_three_match_nolit_encodeBlockAsm10B_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_match_nolit_encodeBlockAsm10B_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +repeat_two_offset_match_nolit_encodeBlockAsm10B_emit_copy_short: + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +two_byte_offset_short_match_nolit_encodeBlockAsm10B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeBlockAsm10B + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeBlockAsm10B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm10B + +emit_copy_three_match_nolit_encodeBlockAsm10B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeBlockAsm10B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBlockAsm10B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm10B: + MOVD $0x9e3779b1, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x20, R7, R7 + MUL R8, R7, R7 + LSR $0x36, R7, R7 + LSL $0x20, R5, R5 + MUL R8, R5, R5 + LSR $0x36, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeBlockAsm10B + ADDW $1, R2, R2 + JMP search_loop_encodeBlockAsm10B + +emit_remainder_encodeBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBlockAsm10B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBlockAsm10B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBlockAsm10B + BLO three_bytes_emit_remainder_encodeBlockAsm10B + +three_bytes_emit_remainder_encodeBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm10B + +two_bytes_emit_remainder_encodeBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBlockAsm10B + JMP memmove_long_emit_remainder_encodeBlockAsm10B + +one_byte_emit_remainder_encodeBlockAsm10B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBlockAsm10B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBlockAsm10B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBlockAsm10B + +memmove_long_emit_remainder_encodeBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBlockAsm10Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBlockAsm10B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBlockAsm8B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000008, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBlockAsm8B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBlockAsm8B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBlockAsm8B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x04, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBlockAsm8B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x9e3779b1, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x38, R9, R9 + LSL $0x20, R10, R10 + MUL R8, R10, R10 + LSR $0x38, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x38, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeBlockAsm8B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R7 + MOVWU R6, R5 + MOVWU 24(RSP), R16 + SUBSW R16, R5, R5 + BEQ repeat_extend_back_end_encodeBlockAsm8B + +repeat_extend_back_loop_encodeBlockAsm8B: + CMPW R7, R6 + BLS repeat_extend_back_end_encodeBlockAsm8B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeBlockAsm8B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R5, R5 + BNE repeat_extend_back_loop_encodeBlockAsm8B + +repeat_extend_back_end_encodeBlockAsm8B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeBlockAsm8B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeBlockAsm8B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeBlockAsm8B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeBlockAsm8B + BLO three_bytes_repeat_emit_encodeBlockAsm8B + +three_bytes_repeat_emit_encodeBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeBlockAsm8B + +two_bytes_repeat_emit_encodeBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeBlockAsm8B + JMP memmove_long_repeat_emit_encodeBlockAsm8B + +one_byte_repeat_emit_encodeBlockAsm8B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeBlockAsm8B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeBlockAsm8B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeBlockAsm8B + +memmove_long_repeat_emit_encodeBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R11 + MOVD R8, R12 + +emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_repeat_emit_encodeBlockAsm8Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeBlockAsm8B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R8 + SUBW R2, R8, R8 + ADD R2, R3, R9 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_repeat_extend_encodeBlockAsm8B: + CMPW $0x10, R8 + BLO matchlen_match8_repeat_extend_encodeBlockAsm8B + MOVD (R9)(R11), R10 + ADD R11, R9, R15 + MOVD 8(R15), R12 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm8B + ADD R11, R5, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16repeat_extend_encodeBlockAsm8B + SUB $16, R8, R8 + MOVWU R8, R8 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_repeat_extend_encodeBlockAsm8B + +matchlen_bsf_16repeat_extend_encodeBlockAsm8B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match8_repeat_extend_encodeBlockAsm8B: + CMPW $0x08, R8 + BLO matchlen_match4_repeat_extend_encodeBlockAsm8B + MOVD (R9)(R11), R10 + MOVD (R5)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_repeat_extend_encodeBlockAsm8B + SUB $8, R8, R8 + MOVWU R8, R8 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_repeat_extend_encodeBlockAsm8B + +matchlen_bsf_8_repeat_extend_encodeBlockAsm8B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match4_repeat_extend_encodeBlockAsm8B: + CMPW $0x04, R8 + BLO matchlen_match2_repeat_extend_encodeBlockAsm8B + MOVWU (R9)(R11), R10 + MOVWU (R5)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_repeat_extend_encodeBlockAsm8B + SUB $4, R8, R8 + MOVWU R8, R8 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_repeat_extend_encodeBlockAsm8B: + CMPW $0x01, R8 + BEQ matchlen_match1_repeat_extend_encodeBlockAsm8B + BLO repeat_extend_forward_end_encodeBlockAsm8B + MOVHU (R9)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeBlockAsm8B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R8, R8 + BEQ repeat_extend_forward_end_encodeBlockAsm8B + +matchlen_match1_repeat_extend_encodeBlockAsm8B: + MOVBU (R9)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R5, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeBlockAsm8B + ADD $1, R11, R11 + MOVWU R11, R11 + +repeat_extend_forward_end_encodeBlockAsm8B: + ADDW R11, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + TSTW R7, R7 + BEQ repeat_as_copy_encodeBlockAsm8B + + // emitRepeat + MOVWU R5, R6 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R6 + BLS repeat_two_match_repeat_encodeBlockAsm8B + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_match_repeat_encodeBlockAsm8B + +cant_repeat_two_offset_match_repeat_encodeBlockAsm8B: + CMPW $0x00000104, R5 + BLO repeat_three_match_repeat_encodeBlockAsm8B + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_match_repeat_encodeBlockAsm8B: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_match_repeat_encodeBlockAsm8B: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_as_copy_encodeBlockAsm8B: + // emitCopy + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B + CMPW $0x00000800, R6 + BHS long_offset_short_repeat_as_copy_encodeBlockAsm8B + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R5, R5 + + // emitRepeat + SUB $4, R5, R5 + MOVWU R5, R5 + JMP cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + MOVWU R5, R6 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R6 + BLS repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short_2b: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +long_offset_short_repeat_as_copy_encodeBlockAsm8B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R5, R6 + SUB $4, R5, R5 + MOVWU R5, R5 + CMPW $0x08, R6 + BLS repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + CMPW $0x0c, R6 + BHS cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + CMPW $0x00000104, R5 + BLO repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short + SUB $256, R5, R5 + MOVWU R5, R5 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R5, 2(R1) + ADD $0x04, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_three_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + SUB $4, R5, R5 + MOVWU R5, R5 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R5, 2(R1) + ADD $0x03, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +repeat_two_repeat_as_copy_encodeBlockAsm8B_emit_copy_short: + LSLW $0x02, R5, R5 + ORRW $0x01, R5, R5 + MOVH R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + MOVD $0, R7 + ADD R5<<2, R7, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVB R6, 1(R1) + ASRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +two_byte_offset_short_repeat_as_copy_encodeBlockAsm8B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeBlockAsm8B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeBlockAsm8B + +emit_copy_three_repeat_as_copy_encodeBlockAsm8B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeBlockAsm8B: + MOVW R2, 20(RSP) + JMP search_loop_encodeBlockAsm8B + +no_repeat_found_encodeBlockAsm8B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBlockAsm8B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeBlockAsm8B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeBlockAsm8B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBlockAsm8B + +candidate3_match_encodeBlockAsm8B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeBlockAsm8B + +candidate2_match_encodeBlockAsm8B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBlockAsm8B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBlockAsm8B + +match_extend_back_loop_encodeBlockAsm8B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBlockAsm8B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBlockAsm8B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBlockAsm8B + JMP match_extend_back_loop_encodeBlockAsm8B + +match_extend_back_end_encodeBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeBlockAsm8B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeBlockAsm8B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeBlockAsm8B + BLO three_bytes_match_emit_encodeBlockAsm8B + +three_bytes_match_emit_encodeBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBlockAsm8B + +two_bytes_match_emit_encodeBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeBlockAsm8B + JMP memmove_long_match_emit_encodeBlockAsm8B + +one_byte_match_emit_encodeBlockAsm8B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBlockAsm8B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBlockAsm8B + +emit_lit_memmove_match_emit_encodeBlockAsm8B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBlockAsm8B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeBlockAsm8B + +memmove_long_match_emit_encodeBlockAsm8B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeBlockAsm8Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeBlockAsm8B: +match_nolit_loop_encodeBlockAsm8B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeBlockAsm8B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeBlockAsm8B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm8B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeBlockAsm8B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeBlockAsm8B + +matchlen_bsf_16match_nolit_encodeBlockAsm8B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm8B + +matchlen_match8_match_nolit_encodeBlockAsm8B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeBlockAsm8B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeBlockAsm8B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeBlockAsm8B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeBlockAsm8B + +matchlen_match4_match_nolit_encodeBlockAsm8B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeBlockAsm8B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeBlockAsm8B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeBlockAsm8B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeBlockAsm8B + BLO match_nolit_end_encodeBlockAsm8B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBlockAsm8B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeBlockAsm8B + +matchlen_match1_match_nolit_encodeBlockAsm8B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBlockAsm8B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeBlockAsm8B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeBlockAsm8B + CMPW $0x00000800, R5 + BHS long_offset_short_match_nolit_encodeBlockAsm8B + MOVD $0x00000001, R6 + ADD $16, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + MOVWU R9, R5 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +long_offset_short_match_nolit_encodeBlockAsm8B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R9, R5 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBlockAsm8B_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R9, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_three_match_nolit_encodeBlockAsm8B_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R9, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +repeat_two_match_nolit_encodeBlockAsm8B_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + MOVD $0, R6 + ADD R9<<2, R6, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R5, 1(R1) + ASRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R9, R9 + MOVB R9, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +two_byte_offset_short_match_nolit_encodeBlockAsm8B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeBlockAsm8B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBlockAsm8B + +emit_copy_three_match_nolit_encodeBlockAsm8B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeBlockAsm8B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBlockAsm8B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBlockAsm8B: + MOVD $0x9e3779b1, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x20, R7, R7 + MUL R8, R7, R7 + LSR $0x38, R7, R7 + LSL $0x20, R5, R5 + MUL R8, R5, R5 + LSR $0x38, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeBlockAsm8B + ADDW $1, R2, R2 + JMP search_loop_encodeBlockAsm8B + +emit_remainder_encodeBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBlockAsm8B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBlockAsm8B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBlockAsm8B + BLO three_bytes_emit_remainder_encodeBlockAsm8B + +three_bytes_emit_remainder_encodeBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBlockAsm8B + +two_bytes_emit_remainder_encodeBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBlockAsm8B + JMP memmove_long_emit_remainder_encodeBlockAsm8B + +one_byte_emit_remainder_encodeBlockAsm8B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBlockAsm8B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBlockAsm8B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBlockAsm8B + +memmove_long_emit_remainder_encodeBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBlockAsm8Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBlockAsm8B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00001200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBetterBlockAsm: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBetterBlockAsm + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $6, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBetterBlockAsm: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x07, R5, R5 + CMPW $0x63, R5 + BLS check_maxskip_ok_encodeBetterBlockAsm + ADD $100, R2, R5 + MOVWU R5, R5 + JMP check_maxskip_cont_encodeBetterBlockAsm + +check_maxskip_ok_encodeBetterBlockAsm: + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + +check_maxskip_cont_encodeBetterBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBetterBlockAsm + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x00cf1bbcdcbfa563, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 524288(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 524288(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeBetterBlockAsm + CMP R6, R10 + BNE no_short_found_encodeBetterBlockAsm + MOVWU R7, R5 + JMP candidate_match_encodeBetterBlockAsm + +no_short_found_encodeBetterBlockAsm: + CMPW R6, R9 + BEQ candidate_match_encodeBetterBlockAsm + CMPW R6, R10 + BEQ candidateS_match_encodeBetterBlockAsm + MOVWU 28(RSP), R2 + JMP search_loop_encodeBetterBlockAsm + +candidateS_match_encodeBetterBlockAsm: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBetterBlockAsm + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBetterBlockAsm: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm + +match_extend_back_loop_encodeBetterBlockAsm: + CMPW R6, R2 + BLS match_extend_back_end_encodeBetterBlockAsm + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBetterBlockAsm + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm + JMP match_extend_back_loop_encodeBetterBlockAsm + +match_extend_back_end_encodeBetterBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $5, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeBetterBlockAsm + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeBetterBlockAsm + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm + +matchlen_match8_match_nolit_encodeBetterBlockAsm: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeBetterBlockAsm + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm + +matchlen_match4_match_nolit_encodeBetterBlockAsm: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeBetterBlockAsm + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeBetterBlockAsm + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeBetterBlockAsm: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeBetterBlockAsm + BLO match_nolit_end_encodeBetterBlockAsm + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBetterBlockAsm + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeBetterBlockAsm + +matchlen_match1_match_nolit_encodeBetterBlockAsm: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBetterBlockAsm + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeBetterBlockAsm: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVWU 24(RSP), R16 + CMPW R7, R16 + BEQ match_is_repeat_encodeBetterBlockAsm + CMPW $0x01, R11 + BHI match_length_ok_encodeBetterBlockAsm + CMPW $0x0000ffff, R7 + BLS match_length_ok_encodeBetterBlockAsm + MOVWU 28(RSP), R2 + ADDW $1, R2, R2 + JMP search_loop_encodeBetterBlockAsm + +match_length_ok_encodeBetterBlockAsm: + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeBetterBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeBetterBlockAsm + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeBetterBlockAsm + CMPW $0x00010000, R5 + BLO three_bytes_match_emit_encodeBetterBlockAsm + CMPW $0x01000000, R5 + BLO four_bytes_match_emit_encodeBetterBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm + +four_bytes_match_emit_encodeBetterBlockAsm: + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm + +three_bytes_match_emit_encodeBetterBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm + +two_bytes_match_emit_encodeBetterBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeBetterBlockAsm + JMP memmove_long_match_emit_encodeBetterBlockAsm + +one_byte_match_emit_encodeBetterBlockAsm: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_encodeBetterBlockAsm_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBetterBlockAsm: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeBetterBlockAsm + +memmove_long_match_emit_encodeBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeBetterBlockAsmlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeBetterBlockAsm: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R7 + BLO two_byte_offset_match_nolit_encodeBetterBlockAsm + CMPW $0x40, R11 + BLS four_bytes_remain_match_nolit_encodeBetterBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R7, 1(R1) + SUB $64, R11, R11 + MOVWU R11, R11 + ADD $0x05, R1, R1 + CMPW $0x04, R11 + BLO four_bytes_remain_match_nolit_encodeBetterBlockAsm + + // emitRepeat +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy: + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy + CMPW $0x0100ffff, R11 + BLO repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy + SUB $16842747, R11, R11 + MOVWU R11, R11 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy: + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +four_bytes_remain_match_nolit_encodeBetterBlockAsm: + TSTW R11, R11 + BEQ match_nolit_emitcopy_end_encodeBetterBlockAsm + MOVD $0, R5 + ADD R11<<2, R5, R11 + SUB $1, R11, R11 + MOVWU R11, R11 + MOVB R11, (R1) + MOVW R7, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +two_byte_offset_match_nolit_encodeBetterBlockAsm: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeBetterBlockAsm + CMPW $0x00000800, R7 + BHS long_offset_short_match_nolit_encodeBetterBlockAsm + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + MOVWU R7, R8 + LSRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R11, R11 + + // emitRepeat + SUB $4, R11, R11 + MOVWU R11, R11 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + CMPW $0x0100ffff, R11 + BLO repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + SUB $16842747, R11, R11 + MOVWU R11, R11 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short_2b: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +long_offset_short_match_nolit_encodeBetterBlockAsm: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + + // emitRepeat +emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short: + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short + CMPW $0x0100ffff, R11 + BLO repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short + SUB $16842747, R11, R11 + MOVWU R11, R11 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_encodeBetterBlockAsm_emit_copy_short + +repeat_five_match_nolit_encodeBetterBlockAsm_emit_copy_short: + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_encodeBetterBlockAsm_emit_copy_short: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_encodeBetterBlockAsm_emit_copy_short: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_encodeBetterBlockAsm_emit_copy_short: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_encodeBetterBlockAsm_emit_copy_short: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +emit_copy_three_match_nolit_encodeBetterBlockAsm: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +match_is_repeat_encodeBetterBlockAsm: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_repeat_encodeBetterBlockAsm + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_repeat_encodeBetterBlockAsm + CMPW $0x00010000, R5 + BLO three_bytes_match_emit_repeat_encodeBetterBlockAsm + CMPW $0x01000000, R5 + BLO four_bytes_match_emit_repeat_encodeBetterBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +four_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +three_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +two_bytes_match_emit_repeat_encodeBetterBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_repeat_encodeBetterBlockAsm + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm + +one_byte_match_emit_repeat_encodeBetterBlockAsm: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_repeat_encodeBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm: + MOVD R5, R1 + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm + +memmove_long_match_emit_repeat_encodeBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsmlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitRepeat +emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm: + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_repeat_encodeBetterBlockAsm + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_repeat_encodeBetterBlockAsm + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_repeat_encodeBetterBlockAsm + CMPW $0x0100ffff, R11 + BLO repeat_five_match_nolit_repeat_encodeBetterBlockAsm + SUB $16842747, R11, R11 + MOVWU R11, R11 + MOVD $0xfffb001d, R16 + MOVW R16, (R1) + MOVD $0xff, R16 + MOVB R16, 4(R1) + ADD $0x05, R1, R1 + JMP emit_repeat_again_match_nolit_repeat_encodeBetterBlockAsm + +repeat_five_match_nolit_repeat_encodeBetterBlockAsm: + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_four_match_nolit_repeat_encodeBetterBlockAsm: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + +match_nolit_emitcopy_end_encodeBetterBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBetterBlockAsm + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm: + MOVD $0x00cf1bbcdcbfa563, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x32, R10, R10 + LSL $0x08, R11, R11 + MUL R5, R11, R11 + LSR $0x2f, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x32, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 524288(R15) + ADD R12<<2, R0, R15 + MOVW R13, 524288(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeBetterBlockAsm: + CMP R8, R7 + BHS search_loop_encodeBetterBlockAsm + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x08, R10, R10 + MUL R5, R10, R10 + LSR $0x2f, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeBetterBlockAsm + +emit_remainder_encodeBetterBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $5, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBetterBlockAsm + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBetterBlockAsm + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeBetterBlockAsm + CMPW $0x01000000, R2 + BLO four_bytes_emit_remainder_encodeBetterBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R2, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +four_bytes_emit_remainder_encodeBetterBlockAsm: + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +three_bytes_emit_remainder_encodeBetterBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +two_bytes_emit_remainder_encodeBetterBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBetterBlockAsm + JMP memmove_long_emit_remainder_encodeBetterBlockAsm + +one_byte_emit_remainder_encodeBetterBlockAsm: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBetterBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm + +memmove_long_emit_remainder_encodeBetterBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsmlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBetterBlockAsm: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBetterBlockAsm4MB(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm4MB(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00001200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBetterBlockAsm4MB: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBetterBlockAsm4MB + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $6, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBetterBlockAsm4MB: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x07, R5, R5 + CMPW $0x63, R5 + BLS check_maxskip_ok_encodeBetterBlockAsm4MB + ADD $100, R2, R5 + MOVWU R5, R5 + JMP check_maxskip_cont_encodeBetterBlockAsm4MB + +check_maxskip_ok_encodeBetterBlockAsm4MB: + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + +check_maxskip_cont_encodeBetterBlockAsm4MB: + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBetterBlockAsm4MB + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x00cf1bbcdcbfa563, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 524288(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 524288(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeBetterBlockAsm4MB + CMP R6, R10 + BNE no_short_found_encodeBetterBlockAsm4MB + MOVWU R7, R5 + JMP candidate_match_encodeBetterBlockAsm4MB + +no_short_found_encodeBetterBlockAsm4MB: + CMPW R6, R9 + BEQ candidate_match_encodeBetterBlockAsm4MB + CMPW R6, R10 + BEQ candidateS_match_encodeBetterBlockAsm4MB + MOVWU 28(RSP), R2 + JMP search_loop_encodeBetterBlockAsm4MB + +candidateS_match_encodeBetterBlockAsm4MB: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBetterBlockAsm4MB + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBetterBlockAsm4MB: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm4MB + +match_extend_back_loop_encodeBetterBlockAsm4MB: + CMPW R6, R2 + BLS match_extend_back_end_encodeBetterBlockAsm4MB + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBetterBlockAsm4MB + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm4MB + JMP match_extend_back_loop_encodeBetterBlockAsm4MB + +match_extend_back_end_encodeBetterBlockAsm4MB: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $4, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBetterBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm4MB: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeBetterBlockAsm4MB + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm4MB + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm4MB: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match8_match_nolit_encodeBetterBlockAsm4MB: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeBetterBlockAsm4MB + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm4MB + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm4MB: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match4_match_nolit_encodeBetterBlockAsm4MB: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeBetterBlockAsm4MB + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeBetterBlockAsm4MB + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeBetterBlockAsm4MB: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeBetterBlockAsm4MB + BLO match_nolit_end_encodeBetterBlockAsm4MB + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBetterBlockAsm4MB + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeBetterBlockAsm4MB + +matchlen_match1_match_nolit_encodeBetterBlockAsm4MB: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBetterBlockAsm4MB + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeBetterBlockAsm4MB: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVWU 24(RSP), R16 + CMPW R7, R16 + BEQ match_is_repeat_encodeBetterBlockAsm4MB + CMPW $0x01, R11 + BHI match_length_ok_encodeBetterBlockAsm4MB + CMPW $0x0000ffff, R7 + BLS match_length_ok_encodeBetterBlockAsm4MB + MOVWU 28(RSP), R2 + ADDW $1, R2, R2 + JMP search_loop_encodeBetterBlockAsm4MB + +match_length_ok_encodeBetterBlockAsm4MB: + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeBetterBlockAsm4MB + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeBetterBlockAsm4MB + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeBetterBlockAsm4MB + CMPW $0x00010000, R5 + BLO three_bytes_match_emit_encodeBetterBlockAsm4MB + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +three_bytes_match_emit_encodeBetterBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +two_bytes_match_emit_encodeBetterBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeBetterBlockAsm4MB + JMP memmove_long_match_emit_encodeBetterBlockAsm4MB + +one_byte_match_emit_encodeBetterBlockAsm4MB: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBetterBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_encodeBetterBlockAsm4MB_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBetterBlockAsm4MB: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeBetterBlockAsm4MB + +memmove_long_match_emit_encodeBetterBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeBetterBlockAsm4MBlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeBetterBlockAsm4MB: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R7 + BLO two_byte_offset_match_nolit_encodeBetterBlockAsm4MB + CMPW $0x40, R11 + BLS four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R7, 1(R1) + SUB $64, R11, R11 + MOVWU R11, R11 + ADD $0x05, R1, R1 + CMPW $0x04, R11 + BLO four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +four_bytes_remain_match_nolit_encodeBetterBlockAsm4MB: + TSTW R11, R11 + BEQ match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + MOVD $0, R5 + ADD R11<<2, R5, R11 + SUB $1, R11, R11 + MOVWU R11, R11 + MOVB R11, (R1) + MOVW R7, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +two_byte_offset_match_nolit_encodeBetterBlockAsm4MB: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB + CMPW $0x00000800, R7 + BHS long_offset_short_match_nolit_encodeBetterBlockAsm4MB + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R11, R11 + + // emitRepeat + SUB $4, R11, R11 + MOVWU R11, R11 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short_2b: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +long_offset_short_match_nolit_encodeBetterBlockAsm4MB: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_encodeBetterBlockAsm4MB_emit_copy_short: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm4MB: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm4MB + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm4MB + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +emit_copy_three_match_nolit_encodeBetterBlockAsm4MB: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +match_is_repeat_encodeBetterBlockAsm4MB: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_repeat_encodeBetterBlockAsm4MB + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB + CMPW $0x00010000, R5 + BLO three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +three_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +two_bytes_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_repeat_encodeBetterBlockAsm4MB + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB + +one_byte_match_emit_repeat_encodeBetterBlockAsm4MB: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_repeat_encodeBetterBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm4MB_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm4MB: + MOVD R5, R1 + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB + +memmove_long_match_emit_repeat_encodeBetterBlockAsm4MB: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm4MBlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm4MB: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB + CMPW $0x00010100, R11 + BLO repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB + SUB $65536, R11, R11 + MOVWU R11, R11 + MOVWU R11, R7 + MOVD $0x001d, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ASRW $0x10, R7, R7 + MOVB R7, 4(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_four_match_nolit_repeat_encodeBetterBlockAsm4MB: + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm4MB: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm4MB: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm4MB + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm4MB: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + +match_nolit_emitcopy_end_encodeBetterBlockAsm4MB: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBetterBlockAsm4MB + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBetterBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm4MB: + MOVD $0x00cf1bbcdcbfa563, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x32, R10, R10 + LSL $0x08, R11, R11 + MUL R5, R11, R11 + LSR $0x2f, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x32, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 524288(R15) + ADD R12<<2, R0, R15 + MOVW R13, 524288(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeBetterBlockAsm4MB: + CMP R8, R7 + BHS search_loop_encodeBetterBlockAsm4MB + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x08, R10, R10 + MUL R5, R10, R10 + LSR $0x2f, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeBetterBlockAsm4MB + +emit_remainder_encodeBetterBlockAsm4MB: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $4, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBetterBlockAsm4MB + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm4MB: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBetterBlockAsm4MB + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBetterBlockAsm4MB + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeBetterBlockAsm4MB + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +three_bytes_emit_remainder_encodeBetterBlockAsm4MB: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +two_bytes_emit_remainder_encodeBetterBlockAsm4MB: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBetterBlockAsm4MB + JMP memmove_long_emit_remainder_encodeBetterBlockAsm4MB + +one_byte_emit_remainder_encodeBetterBlockAsm4MB: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBetterBlockAsm4MB: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm4MB_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm4MB: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB + +memmove_long_emit_remainder_encodeBetterBlockAsm4MB: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm4MBlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBetterBlockAsm4MB: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm12B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000280, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBetterBlockAsm12B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $6, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBetterBlockAsm12B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBetterBlockAsm12B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x34, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 65536(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 65536(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeBetterBlockAsm12B + CMP R6, R10 + BNE no_short_found_encodeBetterBlockAsm12B + MOVWU R7, R5 + JMP candidate_match_encodeBetterBlockAsm12B + +no_short_found_encodeBetterBlockAsm12B: + CMPW R6, R9 + BEQ candidate_match_encodeBetterBlockAsm12B + CMPW R6, R10 + BEQ candidateS_match_encodeBetterBlockAsm12B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBetterBlockAsm12B + +candidateS_match_encodeBetterBlockAsm12B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBetterBlockAsm12B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBetterBlockAsm12B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm12B + +match_extend_back_loop_encodeBetterBlockAsm12B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBetterBlockAsm12B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBetterBlockAsm12B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm12B + JMP match_extend_back_loop_encodeBetterBlockAsm12B + +match_extend_back_end_encodeBetterBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm12B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeBetterBlockAsm12B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm12B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm12B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match8_match_nolit_encodeBetterBlockAsm12B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeBetterBlockAsm12B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm12B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match4_match_nolit_encodeBetterBlockAsm12B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeBetterBlockAsm12B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeBetterBlockAsm12B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeBetterBlockAsm12B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeBetterBlockAsm12B + BLO match_nolit_end_encodeBetterBlockAsm12B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBetterBlockAsm12B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeBetterBlockAsm12B + +matchlen_match1_match_nolit_encodeBetterBlockAsm12B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBetterBlockAsm12B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeBetterBlockAsm12B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVWU 24(RSP), R16 + CMPW R7, R16 + BEQ match_is_repeat_encodeBetterBlockAsm12B + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeBetterBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeBetterBlockAsm12B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeBetterBlockAsm12B + BLO three_bytes_match_emit_encodeBetterBlockAsm12B + +three_bytes_match_emit_encodeBetterBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm12B + +two_bytes_match_emit_encodeBetterBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeBetterBlockAsm12B + JMP memmove_long_match_emit_encodeBetterBlockAsm12B + +one_byte_match_emit_encodeBetterBlockAsm12B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm12B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBetterBlockAsm12B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeBetterBlockAsm12B + +memmove_long_match_emit_encodeBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeBetterBlockAsm12Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeBetterBlockAsm12B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B + CMPW $0x00000800, R7 + BHS long_offset_short_match_nolit_encodeBetterBlockAsm12B + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R11, R11 + + // emitRepeat + SUB $4, R11, R11 + MOVWU R11, R11 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short_2b: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +long_offset_short_match_nolit_encodeBetterBlockAsm12B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm12B_emit_copy_short: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm12B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm12B + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm12B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +emit_copy_three_match_nolit_encodeBetterBlockAsm12B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +match_is_repeat_encodeBetterBlockAsm12B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_repeat_encodeBetterBlockAsm12B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_repeat_encodeBetterBlockAsm12B + BLO three_bytes_match_emit_repeat_encodeBetterBlockAsm12B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_repeat_encodeBetterBlockAsm12B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm12B + +one_byte_match_emit_repeat_encodeBetterBlockAsm12B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_repeat_encodeBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm12B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm12B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm12Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm12B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm12B: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm12B: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm12B + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm12B: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + +match_nolit_emitcopy_end_encodeBetterBlockAsm12B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBetterBlockAsm12B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm12B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x32, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x34, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x32, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x34, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 65536(R15) + ADD R12<<2, R0, R15 + MOVW R13, 65536(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeBetterBlockAsm12B: + CMP R8, R7 + BHS search_loop_encodeBetterBlockAsm12B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x32, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeBetterBlockAsm12B + +emit_remainder_encodeBetterBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm12B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBetterBlockAsm12B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBetterBlockAsm12B + BLO three_bytes_emit_remainder_encodeBetterBlockAsm12B + +three_bytes_emit_remainder_encodeBetterBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B + +two_bytes_emit_remainder_encodeBetterBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBetterBlockAsm12B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm12B + +one_byte_emit_remainder_encodeBetterBlockAsm12B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBetterBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm12B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm12B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm12B + +memmove_long_emit_remainder_encodeBetterBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm12Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBetterBlockAsm12B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm10B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x000000a0, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBetterBlockAsm10B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $6, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBetterBlockAsm10B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBetterBlockAsm10B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x36, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 16384(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 16384(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeBetterBlockAsm10B + CMP R6, R10 + BNE no_short_found_encodeBetterBlockAsm10B + MOVWU R7, R5 + JMP candidate_match_encodeBetterBlockAsm10B + +no_short_found_encodeBetterBlockAsm10B: + CMPW R6, R9 + BEQ candidate_match_encodeBetterBlockAsm10B + CMPW R6, R10 + BEQ candidateS_match_encodeBetterBlockAsm10B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBetterBlockAsm10B + +candidateS_match_encodeBetterBlockAsm10B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBetterBlockAsm10B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBetterBlockAsm10B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm10B + +match_extend_back_loop_encodeBetterBlockAsm10B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBetterBlockAsm10B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBetterBlockAsm10B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm10B + JMP match_extend_back_loop_encodeBetterBlockAsm10B + +match_extend_back_end_encodeBetterBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm10B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeBetterBlockAsm10B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm10B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm10B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match8_match_nolit_encodeBetterBlockAsm10B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeBetterBlockAsm10B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm10B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match4_match_nolit_encodeBetterBlockAsm10B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeBetterBlockAsm10B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeBetterBlockAsm10B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeBetterBlockAsm10B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeBetterBlockAsm10B + BLO match_nolit_end_encodeBetterBlockAsm10B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBetterBlockAsm10B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeBetterBlockAsm10B + +matchlen_match1_match_nolit_encodeBetterBlockAsm10B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBetterBlockAsm10B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeBetterBlockAsm10B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVWU 24(RSP), R16 + CMPW R7, R16 + BEQ match_is_repeat_encodeBetterBlockAsm10B + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeBetterBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeBetterBlockAsm10B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeBetterBlockAsm10B + BLO three_bytes_match_emit_encodeBetterBlockAsm10B + +three_bytes_match_emit_encodeBetterBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm10B + +two_bytes_match_emit_encodeBetterBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeBetterBlockAsm10B + JMP memmove_long_match_emit_encodeBetterBlockAsm10B + +one_byte_match_emit_encodeBetterBlockAsm10B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm10B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBetterBlockAsm10B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeBetterBlockAsm10B + +memmove_long_match_emit_encodeBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeBetterBlockAsm10Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeBetterBlockAsm10B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B + CMPW $0x00000800, R7 + BHS long_offset_short_match_nolit_encodeBetterBlockAsm10B + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R11, R11 + + // emitRepeat + SUB $4, R11, R11 + MOVWU R11, R11 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short_2b: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +long_offset_short_match_nolit_encodeBetterBlockAsm10B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_encodeBetterBlockAsm10B_emit_copy_short: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm10B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm10B + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm10B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +emit_copy_three_match_nolit_encodeBetterBlockAsm10B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +match_is_repeat_encodeBetterBlockAsm10B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_repeat_encodeBetterBlockAsm10B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_repeat_encodeBetterBlockAsm10B + BLO three_bytes_match_emit_repeat_encodeBetterBlockAsm10B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_repeat_encodeBetterBlockAsm10B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm10B + +one_byte_match_emit_repeat_encodeBetterBlockAsm10B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_repeat_encodeBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm10B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm10B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm10Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm10B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B + CMPW $0x00000800, R7 + BLO repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm10B: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm10B: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm10B + +repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm10B: + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + +match_nolit_emitcopy_end_encodeBetterBlockAsm10B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBetterBlockAsm10B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm10B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x34, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x36, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x34, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x36, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 16384(R15) + ADD R12<<2, R0, R15 + MOVW R13, 16384(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeBetterBlockAsm10B: + CMP R8, R7 + BHS search_loop_encodeBetterBlockAsm10B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x34, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x34, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeBetterBlockAsm10B + +emit_remainder_encodeBetterBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm10B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBetterBlockAsm10B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBetterBlockAsm10B + BLO three_bytes_emit_remainder_encodeBetterBlockAsm10B + +three_bytes_emit_remainder_encodeBetterBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B + +two_bytes_emit_remainder_encodeBetterBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBetterBlockAsm10B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm10B + +one_byte_emit_remainder_encodeBetterBlockAsm10B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBetterBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm10B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm10B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm10B + +memmove_long_emit_remainder_encodeBetterBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm10Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBetterBlockAsm10B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeBetterBlockAsm8B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000028, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeBetterBlockAsm8B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $6, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeBetterBlockAsm8B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x04, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeBetterBlockAsm8B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x38, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 4096(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 4096(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeBetterBlockAsm8B + CMP R6, R10 + BNE no_short_found_encodeBetterBlockAsm8B + MOVWU R7, R5 + JMP candidate_match_encodeBetterBlockAsm8B + +no_short_found_encodeBetterBlockAsm8B: + CMPW R6, R9 + BEQ candidate_match_encodeBetterBlockAsm8B + CMPW R6, R10 + BEQ candidateS_match_encodeBetterBlockAsm8B + MOVWU 28(RSP), R2 + JMP search_loop_encodeBetterBlockAsm8B + +candidateS_match_encodeBetterBlockAsm8B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeBetterBlockAsm8B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeBetterBlockAsm8B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm8B + +match_extend_back_loop_encodeBetterBlockAsm8B: + CMPW R6, R2 + BLS match_extend_back_end_encodeBetterBlockAsm8B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeBetterBlockAsm8B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeBetterBlockAsm8B + JMP match_extend_back_loop_encodeBetterBlockAsm8B + +match_extend_back_end_encodeBetterBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeBetterBlockAsm8B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeBetterBlockAsm8B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeBetterBlockAsm8B + +matchlen_bsf_16match_nolit_encodeBetterBlockAsm8B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match8_match_nolit_encodeBetterBlockAsm8B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeBetterBlockAsm8B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeBetterBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeBetterBlockAsm8B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match4_match_nolit_encodeBetterBlockAsm8B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeBetterBlockAsm8B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeBetterBlockAsm8B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeBetterBlockAsm8B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeBetterBlockAsm8B + BLO match_nolit_end_encodeBetterBlockAsm8B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeBetterBlockAsm8B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeBetterBlockAsm8B + +matchlen_match1_match_nolit_encodeBetterBlockAsm8B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeBetterBlockAsm8B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeBetterBlockAsm8B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVWU 24(RSP), R16 + CMPW R7, R16 + BEQ match_is_repeat_encodeBetterBlockAsm8B + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeBetterBlockAsm8B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeBetterBlockAsm8B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeBetterBlockAsm8B + BLO three_bytes_match_emit_encodeBetterBlockAsm8B + +three_bytes_match_emit_encodeBetterBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeBetterBlockAsm8B + +two_bytes_match_emit_encodeBetterBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeBetterBlockAsm8B + JMP memmove_long_match_emit_encodeBetterBlockAsm8B + +one_byte_match_emit_encodeBetterBlockAsm8B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeBetterBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x04, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4 + CMP $0x08, R8 + BLO emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4: + MOVWU (R9), R10 + MOVW R10, (R1) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVWU (R9), R10 + ADD R8, R9, R15 + MOVWU -4(R15), R9 + MOVW R10, (R1) + ADD R8, R1, R15 + MOVW R9, -4(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeBetterBlockAsm8B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeBetterBlockAsm8B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeBetterBlockAsm8B + +memmove_long_match_emit_encodeBetterBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeBetterBlockAsm8Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeBetterBlockAsm8B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B + CMPW $0x00000800, R7 + BHS long_offset_short_match_nolit_encodeBetterBlockAsm8B + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + SUBW $0x08, R11, R11 + + // emitRepeat + SUB $4, R11, R11 + MOVWU R11, R11 + JMP cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short_2b: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +long_offset_short_match_nolit_encodeBetterBlockAsm8B: + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + +cant_repeat_two_offset_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_encodeBetterBlockAsm8B_emit_copy_short: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +two_byte_offset_short_match_nolit_encodeBetterBlockAsm8B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeBetterBlockAsm8B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +emit_copy_three_match_nolit_encodeBetterBlockAsm8B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +match_is_repeat_encodeBetterBlockAsm8B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_repeat_encodeBetterBlockAsm8B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_repeat_encodeBetterBlockAsm8B + BLO three_bytes_match_emit_repeat_encodeBetterBlockAsm8B + +three_bytes_match_emit_repeat_encodeBetterBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B + +two_bytes_match_emit_repeat_encodeBetterBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_repeat_encodeBetterBlockAsm8B + JMP memmove_long_match_emit_repeat_encodeBetterBlockAsm8B + +one_byte_match_emit_repeat_encodeBetterBlockAsm8B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_repeat_encodeBetterBlockAsm8B: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x04, R7 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4 + CMP $0x08, R7 + BLO emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7 + CMP $0x10, R7 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4: + MOVWU (R8), R9 + MOVW R9, (R1) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVWU (R8), R9 + ADD R7, R8, R15 + MOVWU -4(R15), R8 + MOVW R9, (R1) + ADD R7, R1, R15 + MOVW R8, -4(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B + +emit_lit_memmove_match_emit_repeat_encodeBetterBlockAsm8B_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_repeat_encodeBetterBlockAsm8B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B + +memmove_long_match_emit_repeat_encodeBetterBlockAsm8B: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R12 + +emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_match_emit_repeat_encodeBetterBlockAsm8Blarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_repeat_encodeBetterBlockAsm8B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitRepeat + MOVWU R11, R5 + SUB $4, R11, R11 + MOVWU R11, R11 + CMPW $0x08, R5 + BLS repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B + +cant_repeat_two_offset_match_nolit_repeat_encodeBetterBlockAsm8B: + CMPW $0x00000104, R11 + BLO repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B + SUB $256, R11, R11 + MOVWU R11, R11 + MOVD $0x0019, R16 + MOVH R16, (R1) + MOVH R11, 2(R1) + ADD $0x04, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_three_match_nolit_repeat_encodeBetterBlockAsm8B: + SUB $4, R11, R11 + MOVWU R11, R11 + MOVD $0x0015, R16 + MOVH R16, (R1) + MOVB R11, 2(R1) + ADD $0x03, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + +repeat_two_match_nolit_repeat_encodeBetterBlockAsm8B: + LSLW $0x02, R11, R11 + ORRW $0x01, R11, R11 + MOVH R11, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeBetterBlockAsm8B + MOVD $0, R5 + ADD R11<<2, R5, R11 + ADD $1, R11, R11 + MOVWU R11, R11 + MOVB R7, 1(R1) + ASRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R11, R11 + MOVB R11, (R1) + ADD $0x02, R1, R1 + +match_nolit_emitcopy_end_encodeBetterBlockAsm8B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeBetterBlockAsm8B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeBetterBlockAsm8B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x38, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x36, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x38, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 4096(R15) + ADD R12<<2, R0, R15 + MOVW R13, 4096(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeBetterBlockAsm8B: + CMP R8, R7 + BHS search_loop_encodeBetterBlockAsm8B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x36, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x36, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeBetterBlockAsm8B + +emit_remainder_encodeBetterBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeBetterBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeBetterBlockAsm8B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeBetterBlockAsm8B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeBetterBlockAsm8B + BLO three_bytes_emit_remainder_encodeBetterBlockAsm8B + +three_bytes_emit_remainder_encodeBetterBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B + +two_bytes_emit_remainder_encodeBetterBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeBetterBlockAsm8B + JMP memmove_long_emit_remainder_encodeBetterBlockAsm8B + +one_byte_emit_remainder_encodeBetterBlockAsm8B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeBetterBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeBetterBlockAsm8B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeBetterBlockAsm8B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeBetterBlockAsm8B + +memmove_long_emit_remainder_encodeBetterBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeBetterBlockAsm8Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeBetterBlockAsm8B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBlockAsm(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBlockAsm: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBlockAsm + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBlockAsm: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBlockAsm + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R8, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeSnappyBlockAsm + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_encodeSnappyBlockAsm + +repeat_extend_back_loop_encodeSnappyBlockAsm: + CMPW R5, R6 + BLS repeat_extend_back_end_encodeSnappyBlockAsm + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeSnappyBlockAsm + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_encodeSnappyBlockAsm + +repeat_extend_back_end_encodeSnappyBlockAsm: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $5, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeSnappyBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeSnappyBlockAsm + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeSnappyBlockAsm + CMPW $0x00010000, R5 + BLO three_bytes_repeat_emit_encodeSnappyBlockAsm + CMPW $0x01000000, R5 + BLO four_bytes_repeat_emit_encodeSnappyBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +four_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVWU R5, R9 + LSRW $0x10, R9, R9 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R9, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +three_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +two_bytes_repeat_emit_encodeSnappyBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeSnappyBlockAsm + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm + +one_byte_repeat_emit_encodeSnappyBlockAsm: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeSnappyBlockAsm: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8: + MOVD (R8), R9 + MOVD R9, (R1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm + +memmove_long_repeat_emit_encodeSnappyBlockAsm: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R11 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsmlarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_encodeSnappyBlockAsm + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_encodeSnappyBlockAsm + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_encodeSnappyBlockAsm + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_encodeSnappyBlockAsm + BLO repeat_extend_forward_end_encodeSnappyBlockAsm + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_encodeSnappyBlockAsm + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeSnappyBlockAsm + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_encodeSnappyBlockAsm: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy + CMPW $0x00010000, R6 + BLO two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm + +four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm: + CMPW $0x40, R5 + BLS four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R6, 1(R1) + SUB $64, R5, R5 + MOVWU R5, R5 + ADD $0x05, R1, R1 + CMPW $0x04, R5 + BLO four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm + JMP four_bytes_loop_back_repeat_as_copy_encodeSnappyBlockAsm + +four_bytes_remain_repeat_as_copy_encodeSnappyBlockAsm: + TSTW R5, R5 + BEQ repeat_end_emit_encodeSnappyBlockAsm + MOVD $0, R7 + ADD R5<<2, R7, R5 + SUB $1, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVW R6, 1(R1) + ADD $0x05, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm + +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeSnappyBlockAsm: + MOVW R2, 20(RSP) + JMP search_loop_encodeSnappyBlockAsm + +no_repeat_found_encodeSnappyBlockAsm: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBlockAsm + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeSnappyBlockAsm + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeSnappyBlockAsm + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBlockAsm + +candidate3_match_encodeSnappyBlockAsm: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeSnappyBlockAsm + +candidate2_match_encodeSnappyBlockAsm: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBlockAsm: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm + +match_extend_back_loop_encodeSnappyBlockAsm: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBlockAsm + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBlockAsm + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm + JMP match_extend_back_loop_encodeSnappyBlockAsm + +match_extend_back_end_encodeSnappyBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $5, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeSnappyBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeSnappyBlockAsm + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeSnappyBlockAsm + CMPW $0x00010000, R7 + BLO three_bytes_match_emit_encodeSnappyBlockAsm + CMPW $0x01000000, R7 + BLO four_bytes_match_emit_encodeSnappyBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R7, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +four_bytes_match_emit_encodeSnappyBlockAsm: + MOVWU R7, R9 + LSRW $0x10, R9, R9 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + MOVB R9, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +three_bytes_match_emit_encodeSnappyBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +two_bytes_match_emit_encodeSnappyBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeSnappyBlockAsm + JMP memmove_long_match_emit_encodeSnappyBlockAsm + +one_byte_match_emit_encodeSnappyBlockAsm: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBlockAsm: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm + +memmove_long_match_emit_encodeSnappyBlockAsm: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBlockAsmlarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeSnappyBlockAsm: +match_nolit_loop_encodeSnappyBlockAsm: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeSnappyBlockAsm + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeSnappyBlockAsm + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm + +matchlen_match8_match_nolit_encodeSnappyBlockAsm: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeSnappyBlockAsm + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm + +matchlen_match4_match_nolit_encodeSnappyBlockAsm: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeSnappyBlockAsm + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBlockAsm + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeSnappyBlockAsm + BLO match_nolit_end_encodeSnappyBlockAsm + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBlockAsm + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeSnappyBlockAsm + +matchlen_match1_match_nolit_encodeSnappyBlockAsm: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBlockAsm + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeSnappyBlockAsm: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R5 + BLO two_byte_offset_match_nolit_encodeSnappyBlockAsm + +four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm: + CMPW $0x40, R9 + BLS four_bytes_remain_match_nolit_encodeSnappyBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + SUB $64, R9, R9 + MOVWU R9, R9 + ADD $0x05, R1, R1 + CMPW $0x04, R9 + BLO four_bytes_remain_match_nolit_encodeSnappyBlockAsm + JMP four_bytes_loop_back_match_nolit_encodeSnappyBlockAsm + +four_bytes_remain_match_nolit_encodeSnappyBlockAsm: + TSTW R9, R9 + BEQ match_nolit_emitcopy_end_encodeSnappyBlockAsm + MOVD $0, R6 + ADD R9<<2, R6, R9 + SUB $1, R9, R9 + MOVWU R9, R9 + MOVB R9, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm + +two_byte_offset_match_nolit_encodeSnappyBlockAsm: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeSnappyBlockAsm + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm + +emit_copy_three_match_nolit_encodeSnappyBlockAsm: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBlockAsm + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm: + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x10, R7, R7 + MUL R8, R7, R7 + LSR $0x32, R7, R7 + LSL $0x10, R5, R5 + MUL R8, R5, R5 + LSR $0x32, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeSnappyBlockAsm + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBlockAsm + +emit_remainder_encodeSnappyBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $5, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBlockAsm + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBlockAsm + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeSnappyBlockAsm + CMPW $0x01000000, R2 + BLO four_bytes_emit_remainder_encodeSnappyBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R2, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +four_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +three_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +two_bytes_emit_remainder_encodeSnappyBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBlockAsm + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm + +one_byte_emit_remainder_encodeSnappyBlockAsm: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm + +memmove_long_emit_remainder_encodeSnappyBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsmlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBlockAsm64K(dst []byte, src []byte, tmp *[65536]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm64K(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBlockAsm64K: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBlockAsm64K + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBlockAsm64K: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBlockAsm64K + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R8, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeSnappyBlockAsm64K + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_encodeSnappyBlockAsm64K + +repeat_extend_back_loop_encodeSnappyBlockAsm64K: + CMPW R5, R6 + BLS repeat_extend_back_end_encodeSnappyBlockAsm64K + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeSnappyBlockAsm64K + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_encodeSnappyBlockAsm64K + +repeat_extend_back_end_encodeSnappyBlockAsm64K: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeSnappyBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm64K: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeSnappyBlockAsm64K + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeSnappyBlockAsm64K + BLO three_bytes_repeat_emit_encodeSnappyBlockAsm64K + +three_bytes_repeat_emit_encodeSnappyBlockAsm64K: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K + +two_bytes_repeat_emit_encodeSnappyBlockAsm64K: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeSnappyBlockAsm64K + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm64K + +one_byte_repeat_emit_encodeSnappyBlockAsm64K: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeSnappyBlockAsm64K: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8: + MOVD (R8), R9 + MOVD R9, (R1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm64K: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K + +memmove_long_repeat_emit_encodeSnappyBlockAsm64K: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R11 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm64Klarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm64K + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm64K: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm64K: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm64K: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm64K: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm64K: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K + BLO repeat_extend_forward_end_encodeSnappyBlockAsm64K + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_encodeSnappyBlockAsm64K + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm64K: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeSnappyBlockAsm64K + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_encodeSnappyBlockAsm64K: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm64K + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm64K: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm64K + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm64K: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeSnappyBlockAsm64K: + MOVW R2, 20(RSP) + JMP search_loop_encodeSnappyBlockAsm64K + +no_repeat_found_encodeSnappyBlockAsm64K: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBlockAsm64K + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeSnappyBlockAsm64K + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeSnappyBlockAsm64K + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBlockAsm64K + +candidate3_match_encodeSnappyBlockAsm64K: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeSnappyBlockAsm64K + +candidate2_match_encodeSnappyBlockAsm64K: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBlockAsm64K: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm64K + +match_extend_back_loop_encodeSnappyBlockAsm64K: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBlockAsm64K + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBlockAsm64K + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm64K + JMP match_extend_back_loop_encodeSnappyBlockAsm64K + +match_extend_back_end_encodeSnappyBlockAsm64K: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm64K: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeSnappyBlockAsm64K + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeSnappyBlockAsm64K + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeSnappyBlockAsm64K + BLO three_bytes_match_emit_encodeSnappyBlockAsm64K + +three_bytes_match_emit_encodeSnappyBlockAsm64K: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm64K + +two_bytes_match_emit_encodeSnappyBlockAsm64K: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeSnappyBlockAsm64K + JMP memmove_long_match_emit_encodeSnappyBlockAsm64K + +one_byte_match_emit_encodeSnappyBlockAsm64K: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBlockAsm64K: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm64K_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm64K: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm64K + +memmove_long_match_emit_encodeSnappyBlockAsm64K: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm64Klarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeSnappyBlockAsm64K: +match_nolit_loop_encodeSnappyBlockAsm64K: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeSnappyBlockAsm64K + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm64K + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm64K: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match8_match_nolit_encodeSnappyBlockAsm64K: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeSnappyBlockAsm64K + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm64K + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm64K: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match4_match_nolit_encodeSnappyBlockAsm64K: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeSnappyBlockAsm64K + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBlockAsm64K + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm64K: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeSnappyBlockAsm64K + BLO match_nolit_end_encodeSnappyBlockAsm64K + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBlockAsm64K + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeSnappyBlockAsm64K + +matchlen_match1_match_nolit_encodeSnappyBlockAsm64K: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBlockAsm64K + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeSnappyBlockAsm64K: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm64K: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm64K + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm64K: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm64K + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm64K + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm64K + +emit_copy_three_match_nolit_encodeSnappyBlockAsm64K: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBlockAsm64K: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBlockAsm64K + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm64K: + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x10, R7, R7 + MUL R8, R7, R7 + LSR $0x32, R7, R7 + LSL $0x10, R5, R5 + MUL R8, R5, R5 + LSR $0x32, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeSnappyBlockAsm64K + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBlockAsm64K + +emit_remainder_encodeSnappyBlockAsm64K: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm64K: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBlockAsm64K + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBlockAsm64K + BLO three_bytes_emit_remainder_encodeSnappyBlockAsm64K + +three_bytes_emit_remainder_encodeSnappyBlockAsm64K: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K + +two_bytes_emit_remainder_encodeSnappyBlockAsm64K: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBlockAsm64K + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm64K + +one_byte_emit_remainder_encodeSnappyBlockAsm64K: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBlockAsm64K: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm64K_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm64K: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K + +memmove_long_emit_remainder_encodeSnappyBlockAsm64K: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm64Klarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm64K: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBlockAsm12B(dst []byte, src []byte, tmp *[16384]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm12B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000080, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBlockAsm12B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBlockAsm12B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBlockAsm12B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBlockAsm12B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x000000cf1bbcdcbb, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x18, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + LSL $0x18, R10, R10 + MUL R8, R10, R10 + LSR $0x34, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x18, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeSnappyBlockAsm12B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_encodeSnappyBlockAsm12B + +repeat_extend_back_loop_encodeSnappyBlockAsm12B: + CMPW R5, R6 + BLS repeat_extend_back_end_encodeSnappyBlockAsm12B + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeSnappyBlockAsm12B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_encodeSnappyBlockAsm12B + +repeat_extend_back_end_encodeSnappyBlockAsm12B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeSnappyBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm12B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeSnappyBlockAsm12B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeSnappyBlockAsm12B + BLO three_bytes_repeat_emit_encodeSnappyBlockAsm12B + +three_bytes_repeat_emit_encodeSnappyBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B + +two_bytes_repeat_emit_encodeSnappyBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeSnappyBlockAsm12B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm12B + +one_byte_repeat_emit_encodeSnappyBlockAsm12B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeSnappyBlockAsm12B: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8: + MOVD (R8), R9 + MOVD R9, (R1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm12B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B + +memmove_long_repeat_emit_encodeSnappyBlockAsm12B: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R11 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm12Blarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm12B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm12B: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm12B: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm12B: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm12B: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm12B: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B + BLO repeat_extend_forward_end_encodeSnappyBlockAsm12B + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_encodeSnappyBlockAsm12B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm12B: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeSnappyBlockAsm12B + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_encodeSnappyBlockAsm12B: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm12B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm12B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm12B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm12B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeSnappyBlockAsm12B: + MOVW R2, 20(RSP) + JMP search_loop_encodeSnappyBlockAsm12B + +no_repeat_found_encodeSnappyBlockAsm12B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBlockAsm12B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeSnappyBlockAsm12B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeSnappyBlockAsm12B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBlockAsm12B + +candidate3_match_encodeSnappyBlockAsm12B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeSnappyBlockAsm12B + +candidate2_match_encodeSnappyBlockAsm12B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBlockAsm12B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm12B + +match_extend_back_loop_encodeSnappyBlockAsm12B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBlockAsm12B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBlockAsm12B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm12B + JMP match_extend_back_loop_encodeSnappyBlockAsm12B + +match_extend_back_end_encodeSnappyBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeSnappyBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeSnappyBlockAsm12B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeSnappyBlockAsm12B + BLO three_bytes_match_emit_encodeSnappyBlockAsm12B + +three_bytes_match_emit_encodeSnappyBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm12B + +two_bytes_match_emit_encodeSnappyBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeSnappyBlockAsm12B + JMP memmove_long_match_emit_encodeSnappyBlockAsm12B + +one_byte_match_emit_encodeSnappyBlockAsm12B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBlockAsm12B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm12B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm12B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm12B + +memmove_long_match_emit_encodeSnappyBlockAsm12B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm12Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeSnappyBlockAsm12B: +match_nolit_loop_encodeSnappyBlockAsm12B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeSnappyBlockAsm12B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm12B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm12B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm12B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeSnappyBlockAsm12B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm12B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm12B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeSnappyBlockAsm12B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBlockAsm12B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm12B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeSnappyBlockAsm12B + BLO match_nolit_end_encodeSnappyBlockAsm12B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBlockAsm12B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeSnappyBlockAsm12B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm12B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBlockAsm12B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeSnappyBlockAsm12B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm12B: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm12B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm12B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm12B + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm12B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm12B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm12B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBlockAsm12B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBlockAsm12B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm12B: + MOVD $0x000000cf1bbcdcbb, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x18, R7, R7 + MUL R8, R7, R7 + LSR $0x34, R7, R7 + LSL $0x18, R5, R5 + MUL R8, R5, R5 + LSR $0x34, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeSnappyBlockAsm12B + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBlockAsm12B + +emit_remainder_encodeSnappyBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBlockAsm12B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBlockAsm12B + BLO three_bytes_emit_remainder_encodeSnappyBlockAsm12B + +three_bytes_emit_remainder_encodeSnappyBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B + +two_bytes_emit_remainder_encodeSnappyBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBlockAsm12B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm12B + +one_byte_emit_remainder_encodeSnappyBlockAsm12B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm12B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm12B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B + +memmove_long_emit_remainder_encodeSnappyBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm12Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm12B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBlockAsm10B(dst []byte, src []byte, tmp *[4096]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm10B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000020, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBlockAsm10B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBlockAsm10B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBlockAsm10B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBlockAsm10B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x9e3779b1, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R8, R10, R10 + LSR $0x36, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeSnappyBlockAsm10B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_encodeSnappyBlockAsm10B + +repeat_extend_back_loop_encodeSnappyBlockAsm10B: + CMPW R5, R6 + BLS repeat_extend_back_end_encodeSnappyBlockAsm10B + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeSnappyBlockAsm10B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_encodeSnappyBlockAsm10B + +repeat_extend_back_end_encodeSnappyBlockAsm10B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeSnappyBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm10B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeSnappyBlockAsm10B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeSnappyBlockAsm10B + BLO three_bytes_repeat_emit_encodeSnappyBlockAsm10B + +three_bytes_repeat_emit_encodeSnappyBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B + +two_bytes_repeat_emit_encodeSnappyBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeSnappyBlockAsm10B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm10B + +one_byte_repeat_emit_encodeSnappyBlockAsm10B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeSnappyBlockAsm10B: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8: + MOVD (R8), R9 + MOVD R9, (R1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm10B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B + +memmove_long_repeat_emit_encodeSnappyBlockAsm10B: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R11 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm10Blarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm10B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm10B: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm10B: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm10B: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm10B: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm10B: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B + BLO repeat_extend_forward_end_encodeSnappyBlockAsm10B + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_encodeSnappyBlockAsm10B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm10B: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeSnappyBlockAsm10B + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_encodeSnappyBlockAsm10B: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm10B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm10B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm10B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm10B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeSnappyBlockAsm10B: + MOVW R2, 20(RSP) + JMP search_loop_encodeSnappyBlockAsm10B + +no_repeat_found_encodeSnappyBlockAsm10B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBlockAsm10B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeSnappyBlockAsm10B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeSnappyBlockAsm10B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBlockAsm10B + +candidate3_match_encodeSnappyBlockAsm10B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeSnappyBlockAsm10B + +candidate2_match_encodeSnappyBlockAsm10B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBlockAsm10B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm10B + +match_extend_back_loop_encodeSnappyBlockAsm10B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBlockAsm10B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBlockAsm10B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm10B + JMP match_extend_back_loop_encodeSnappyBlockAsm10B + +match_extend_back_end_encodeSnappyBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeSnappyBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeSnappyBlockAsm10B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeSnappyBlockAsm10B + BLO three_bytes_match_emit_encodeSnappyBlockAsm10B + +three_bytes_match_emit_encodeSnappyBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm10B + +two_bytes_match_emit_encodeSnappyBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeSnappyBlockAsm10B + JMP memmove_long_match_emit_encodeSnappyBlockAsm10B + +one_byte_match_emit_encodeSnappyBlockAsm10B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBlockAsm10B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm10B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm10B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm10B + +memmove_long_match_emit_encodeSnappyBlockAsm10B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm10Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeSnappyBlockAsm10B: +match_nolit_loop_encodeSnappyBlockAsm10B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeSnappyBlockAsm10B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm10B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm10B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm10B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeSnappyBlockAsm10B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm10B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm10B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeSnappyBlockAsm10B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBlockAsm10B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm10B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeSnappyBlockAsm10B + BLO match_nolit_end_encodeSnappyBlockAsm10B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBlockAsm10B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeSnappyBlockAsm10B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm10B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBlockAsm10B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeSnappyBlockAsm10B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm10B: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm10B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm10B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm10B + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm10B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm10B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm10B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBlockAsm10B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBlockAsm10B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm10B: + MOVD $0x9e3779b1, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x20, R7, R7 + MUL R8, R7, R7 + LSR $0x36, R7, R7 + LSL $0x20, R5, R5 + MUL R8, R5, R5 + LSR $0x36, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeSnappyBlockAsm10B + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBlockAsm10B + +emit_remainder_encodeSnappyBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBlockAsm10B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBlockAsm10B + BLO three_bytes_emit_remainder_encodeSnappyBlockAsm10B + +three_bytes_emit_remainder_encodeSnappyBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B + +two_bytes_emit_remainder_encodeSnappyBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBlockAsm10B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm10B + +one_byte_emit_remainder_encodeSnappyBlockAsm10B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm10B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm10B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B + +memmove_long_emit_remainder_encodeSnappyBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm10Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm10B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBlockAsm8B(dst []byte, src []byte, tmp *[1024]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBlockAsm8B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000008, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBlockAsm8B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBlockAsm8B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBlockAsm8B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x04, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBlockAsm8B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x9e3779b1, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x38, R9, R9 + LSL $0x20, R10, R10 + MUL R8, R10, R10 + LSR $0x38, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x38, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_encodeSnappyBlockAsm8B + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_encodeSnappyBlockAsm8B + +repeat_extend_back_loop_encodeSnappyBlockAsm8B: + CMPW R5, R6 + BLS repeat_extend_back_end_encodeSnappyBlockAsm8B + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_encodeSnappyBlockAsm8B + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_encodeSnappyBlockAsm8B + +repeat_extend_back_end_encodeSnappyBlockAsm8B: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_encodeSnappyBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm8B: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_encodeSnappyBlockAsm8B + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_encodeSnappyBlockAsm8B + BLO three_bytes_repeat_emit_encodeSnappyBlockAsm8B + +three_bytes_repeat_emit_encodeSnappyBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B + +two_bytes_repeat_emit_encodeSnappyBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_encodeSnappyBlockAsm8B + JMP memmove_long_repeat_emit_encodeSnappyBlockAsm8B + +one_byte_repeat_emit_encodeSnappyBlockAsm8B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_repeat_emit_encodeSnappyBlockAsm8B: + ADD R7, R1, R5 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8: + MOVD (R8), R9 + MOVD R9, (R1) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVD (R8), R9 + ADD R7, R8, R15 + MOVD -8(R15), R8 + MOVD R9, (R1) + ADD R7, R1, R15 + MOVD R8, -8(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: + FMOVQ (R8), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_repeat_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: + FMOVQ (R8), F0 + FMOVQ 16(R8), F1 + ADD R7, R8, R15 + FMOVQ -32(R15), F2 + ADD R7, R8, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R7, R1, R15 + FMOVQ F2, -32(R15) + ADD R7, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_repeat_emit_encodeSnappyBlockAsm8B: + MOVD R5, R1 + JMP emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B + +memmove_long_repeat_emit_encodeSnappyBlockAsm8B: + ADD R7, R1, R5 + + // genMemMoveLong + MOVD R8, R9 + MOVD R1, R10 + MOVD R7, R11 + +emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_repeat_emit_encodeSnappyBlockAsm8Blarge_big_loop_back + ADD R7, R8, R15 + FMOVQ -32(R15), F0 + ADD R7, R8, R15 + FMOVQ -16(R15), F1 + ADD R7, R1, R15 + FMOVQ F0, -32(R15) + ADD R7, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_encodeSnappyBlockAsm8B + +matchlen_bsf_16repeat_extend_encodeSnappyBlockAsm8B: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match8_repeat_extend_encodeSnappyBlockAsm8B: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B + +matchlen_bsf_8_repeat_extend_encodeSnappyBlockAsm8B: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match4_repeat_extend_encodeSnappyBlockAsm8B: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_encodeSnappyBlockAsm8B: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B + BLO repeat_extend_forward_end_encodeSnappyBlockAsm8B + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_encodeSnappyBlockAsm8B + +matchlen_match1_repeat_extend_encodeSnappyBlockAsm8B: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_encodeSnappyBlockAsm8B + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_encodeSnappyBlockAsm8B: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy +two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R6, 1(R1) + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_encodeSnappyBlockAsm8B + +two_byte_offset_short_repeat_as_copy_encodeSnappyBlockAsm8B: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R6, 1(R1) + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R7, R7 + MOVB R7, (R1) + ADD $0x02, R1, R1 + JMP repeat_end_emit_encodeSnappyBlockAsm8B + +emit_copy_three_repeat_as_copy_encodeSnappyBlockAsm8B: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R1) + MOVH R6, 1(R1) + ADD $0x03, R1, R1 + +repeat_end_emit_encodeSnappyBlockAsm8B: + MOVW R2, 20(RSP) + JMP search_loop_encodeSnappyBlockAsm8B + +no_repeat_found_encodeSnappyBlockAsm8B: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBlockAsm8B + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_encodeSnappyBlockAsm8B + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_encodeSnappyBlockAsm8B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBlockAsm8B + +candidate3_match_encodeSnappyBlockAsm8B: + ADDW $0x02, R2, R2 + JMP candidate_match_encodeSnappyBlockAsm8B + +candidate2_match_encodeSnappyBlockAsm8B: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBlockAsm8B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm8B + +match_extend_back_loop_encodeSnappyBlockAsm8B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBlockAsm8B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBlockAsm8B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBlockAsm8B + JMP match_extend_back_loop_encodeSnappyBlockAsm8B + +match_extend_back_end_encodeSnappyBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_encodeSnappyBlockAsm8B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R7 + MOVWU R7, R7 + CMPW $0x3c, R7 + BLO one_byte_match_emit_encodeSnappyBlockAsm8B + CMPW $0x00000100, R7 + BLO two_bytes_match_emit_encodeSnappyBlockAsm8B + BLO three_bytes_match_emit_encodeSnappyBlockAsm8B + +three_bytes_match_emit_encodeSnappyBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBlockAsm8B + +two_bytes_match_emit_encodeSnappyBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R7, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R7 + BLO memmove_match_emit_encodeSnappyBlockAsm8B + JMP memmove_long_match_emit_encodeSnappyBlockAsm8B + +one_byte_match_emit_encodeSnappyBlockAsm8B: + LSLW $0x02, R7, R16 + BFI $0, R16, $8, R7 + MOVB R7, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBlockAsm8B: + ADD R8, R1, R7 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8: + MOVD (R6), R9 + MOVD R9, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVD (R6), R9 + ADD R8, R6, R15 + MOVD -8(R15), R6 + MOVD R9, (R1) + ADD R8, R1, R15 + MOVD R6, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_17through32: + FMOVQ (R6), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBlockAsm8B_memmove_move_33through64: + FMOVQ (R6), F0 + FMOVQ 16(R6), F1 + ADD R8, R6, R15 + FMOVQ -32(R15), F2 + ADD R8, R6, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBlockAsm8B: + MOVD R7, R1 + JMP emit_literal_done_match_emit_encodeSnappyBlockAsm8B + +memmove_long_match_emit_encodeSnappyBlockAsm8B: + ADD R8, R1, R7 + + // genMemMoveLong + MOVD R6, R9 + MOVD R1, R10 + MOVD R8, R11 + +emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + FMOVQ F0, (R10) + FMOVQ F1, 16(R10) + ADD $0x20, R9, R9 + ADD $0x20, R10, R10 + SUB $0x20, R11, R11 + CMP $0x20, R11 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBlockAsm8Blarge_big_loop_back + ADD R8, R6, R15 + FMOVQ -32(R15), F0 + ADD R8, R6, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R7, R1 + +emit_literal_done_match_emit_encodeSnappyBlockAsm8B: +match_nolit_loop_encodeSnappyBlockAsm8B: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_encodeSnappyBlockAsm8B + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBlockAsm8B + +matchlen_bsf_16match_nolit_encodeSnappyBlockAsm8B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match8_match_nolit_encodeSnappyBlockAsm8B: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_encodeSnappyBlockAsm8B + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_encodeSnappyBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeSnappyBlockAsm8B: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match4_match_nolit_encodeSnappyBlockAsm8B: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_encodeSnappyBlockAsm8B + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBlockAsm8B + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_encodeSnappyBlockAsm8B: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_encodeSnappyBlockAsm8B + BLO match_nolit_end_encodeSnappyBlockAsm8B + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBlockAsm8B + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_encodeSnappyBlockAsm8B + +matchlen_match1_match_nolit_encodeSnappyBlockAsm8B: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBlockAsm8B + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_encodeSnappyBlockAsm8B: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBlockAsm8B: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBlockAsm8B + +two_byte_offset_short_match_nolit_encodeSnappyBlockAsm8B: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_encodeSnappyBlockAsm8B + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R5, 1(R1) + LSRW $0x08, R5, R5 + LSLW $0x05, R5, R5 + ORRW R5, R6, R6 + MOVB R6, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBlockAsm8B + +emit_copy_three_match_nolit_encodeSnappyBlockAsm8B: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBlockAsm8B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBlockAsm8B + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBlockAsm8B: + MOVD $0x9e3779b1, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x20, R7, R7 + MUL R8, R7, R7 + LSR $0x38, R7, R7 + LSL $0x20, R5, R5 + MUL R8, R5, R5 + LSR $0x38, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_encodeSnappyBlockAsm8B + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBlockAsm8B + +emit_remainder_encodeSnappyBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBlockAsm8B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBlockAsm8B + BLO three_bytes_emit_remainder_encodeSnappyBlockAsm8B + +three_bytes_emit_remainder_encodeSnappyBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B + +two_bytes_emit_remainder_encodeSnappyBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBlockAsm8B + JMP memmove_long_emit_remainder_encodeSnappyBlockAsm8B + +one_byte_emit_remainder_encodeSnappyBlockAsm8B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBlockAsm8B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBlockAsm8B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B + +memmove_long_emit_remainder_encodeSnappyBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBlockAsm8Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBlockAsm8B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm(dst []byte, src []byte, tmp *[589824]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00001200, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBetterBlockAsm: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBetterBlockAsm + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBetterBlockAsm: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x07, R5, R5 + CMPW $0x63, R5 + BLS check_maxskip_ok_encodeSnappyBetterBlockAsm + ADD $100, R2, R5 + MOVWU R5, R5 + JMP check_maxskip_cont_encodeSnappyBetterBlockAsm + +check_maxskip_ok_encodeSnappyBetterBlockAsm: + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + +check_maxskip_cont_encodeSnappyBetterBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBetterBlockAsm + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x00cf1bbcdcbfa563, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x32, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 524288(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 524288(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm + CMP R6, R10 + BNE no_short_found_encodeSnappyBetterBlockAsm + MOVWU R7, R5 + JMP candidate_match_encodeSnappyBetterBlockAsm + +no_short_found_encodeSnappyBetterBlockAsm: + CMPW R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm + CMPW R6, R10 + BEQ candidateS_match_encodeSnappyBetterBlockAsm + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBetterBlockAsm + +candidateS_match_encodeSnappyBetterBlockAsm: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x2f, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBetterBlockAsm + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBetterBlockAsm: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm + +match_extend_back_loop_encodeSnappyBetterBlockAsm: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBetterBlockAsm + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBetterBlockAsm + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm + +match_extend_back_end_encodeSnappyBetterBlockAsm: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $5, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm + BLO match_nolit_end_encodeSnappyBetterBlockAsm + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeSnappyBetterBlockAsm + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBetterBlockAsm + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeSnappyBetterBlockAsm: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + CMPW $0x01, R11 + BHI match_length_ok_encodeSnappyBetterBlockAsm + CMPW $0x0000ffff, R7 + BLS match_length_ok_encodeSnappyBetterBlockAsm + MOVWU 28(RSP), R2 + ADDW $1, R2, R2 + JMP search_loop_encodeSnappyBetterBlockAsm + +match_length_ok_encodeSnappyBetterBlockAsm: + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeSnappyBetterBlockAsm + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeSnappyBetterBlockAsm + CMPW $0x00010000, R5 + BLO three_bytes_match_emit_encodeSnappyBetterBlockAsm + CMPW $0x01000000, R5 + BLO four_bytes_match_emit_encodeSnappyBetterBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R5, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +four_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVWU R5, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + MOVB R10, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +three_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +two_bytes_match_emit_encodeSnappyBetterBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeSnappyBetterBlockAsm + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm + +one_byte_match_emit_encodeSnappyBetterBlockAsm: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm + +memmove_long_match_emit_encodeSnappyBetterBlockAsm: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsmlarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R7 + BLO two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm + +four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x40, R11 + BLS four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm + MOVD $0xff, R16 + MOVB R16, (R1) + MOVW R7, 1(R1) + SUB $64, R11, R11 + MOVWU R11, R11 + ADD $0x05, R1, R1 + CMPW $0x04, R11 + BLO four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm + JMP four_bytes_loop_back_match_nolit_encodeSnappyBetterBlockAsm + +four_bytes_remain_match_nolit_encodeSnappyBetterBlockAsm: + TSTW R11, R11 + BEQ match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + MOVD $0, R5 + ADD R11<<2, R5, R11 + SUB $1, R11, R11 + MOVWU R11, R11 + MOVB R11, (R1) + MOVW R7, 1(R1) + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBetterBlockAsm + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm: + MOVD $0x00cf1bbcdcbfa563, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x32, R10, R10 + LSL $0x08, R11, R11 + MUL R5, R11, R11 + LSR $0x2f, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x32, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 524288(R15) + ADD R12<<2, R0, R15 + MOVW R13, 524288(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeSnappyBetterBlockAsm: + CMP R8, R7 + BHS search_loop_encodeSnappyBetterBlockAsm + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x2f, R9, R9 + LSL $0x08, R10, R10 + MUL R5, R10, R10 + LSR $0x2f, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeSnappyBetterBlockAsm + +emit_remainder_encodeSnappyBetterBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $5, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBetterBlockAsm + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBetterBlockAsm + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBetterBlockAsm + CMPW $0x00010000, R2 + BLO three_bytes_emit_remainder_encodeSnappyBetterBlockAsm + CMPW $0x01000000, R2 + BLO four_bytes_emit_remainder_encodeSnappyBetterBlockAsm + MOVD $0xfc, R16 + MOVB R16, (R1) + MOVW R2, 1(R1) + ADD $0x05, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +four_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVWU R2, R3 + LSRW $0x10, R3, R3 + MOVD $0xf8, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + MOVB R3, 3(R1) + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBetterBlockAsm + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBetterBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsmlarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm64K(dst []byte, src []byte, tmp *[294912]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm64K(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000900, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBetterBlockAsm64K: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBetterBlockAsm64K + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBetterBlockAsm64K: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x07, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBetterBlockAsm64K + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x00cf1bbcdcbfa563, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x30, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x33, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 262144(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 262144(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm64K + CMP R6, R10 + BNE no_short_found_encodeSnappyBetterBlockAsm64K + MOVWU R7, R5 + JMP candidate_match_encodeSnappyBetterBlockAsm64K + +no_short_found_encodeSnappyBetterBlockAsm64K: + CMPW R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm64K + CMPW R6, R10 + BEQ candidateS_match_encodeSnappyBetterBlockAsm64K + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBetterBlockAsm64K + +candidateS_match_encodeSnappyBetterBlockAsm64K: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x08, R9, R9 + MUL R8, R9, R9 + LSR $0x30, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBetterBlockAsm64K + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBetterBlockAsm64K: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm64K + +match_extend_back_loop_encodeSnappyBetterBlockAsm64K: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBetterBlockAsm64K + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBetterBlockAsm64K + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm64K + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm64K + +match_extend_back_end_encodeSnappyBetterBlockAsm64K: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBetterBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm64K: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm64K + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm64K: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm64K: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K + BLO match_nolit_end_encodeSnappyBetterBlockAsm64K + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeSnappyBetterBlockAsm64K + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm64K: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBetterBlockAsm64K + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeSnappyBetterBlockAsm64K: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeSnappyBetterBlockAsm64K + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeSnappyBetterBlockAsm64K + BLO three_bytes_match_emit_encodeSnappyBetterBlockAsm64K + +three_bytes_match_emit_encodeSnappyBetterBlockAsm64K: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K + +two_bytes_match_emit_encodeSnappyBetterBlockAsm64K: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeSnappyBetterBlockAsm64K + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm64K + +one_byte_match_emit_encodeSnappyBetterBlockAsm64K: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBetterBlockAsm64K: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm64K: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K + +memmove_long_match_emit_encodeSnappyBetterBlockAsm64K: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm64Klarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm64K: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm64K + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm64K: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm64K: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm64K: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBetterBlockAsm64K + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm64K: + MOVD $0x00cf1bbcdcbfa563, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x30, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x33, R10, R10 + LSL $0x08, R11, R11 + MUL R5, R11, R11 + LSR $0x30, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x33, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 262144(R15) + ADD R12<<2, R0, R15 + MOVW R13, 262144(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeSnappyBetterBlockAsm64K: + CMP R8, R7 + BHS search_loop_encodeSnappyBetterBlockAsm64K + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x08, R9, R9 + MUL R5, R9, R9 + LSR $0x30, R9, R9 + LSL $0x08, R10, R10 + MUL R5, R10, R10 + LSR $0x30, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeSnappyBetterBlockAsm64K + +emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBetterBlockAsm64K + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm64K: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K + BLO three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBetterBlockAsm64K + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm64K: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBetterBlockAsm64K: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm64K_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64K: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm64Klarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm64K: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm12B(dst []byte, src []byte, tmp *[81920]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm12B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000280, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBetterBlockAsm12B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBetterBlockAsm12B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x06, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBetterBlockAsm12B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x34, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 65536(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 65536(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm12B + CMP R6, R10 + BNE no_short_found_encodeSnappyBetterBlockAsm12B + MOVWU R7, R5 + JMP candidate_match_encodeSnappyBetterBlockAsm12B + +no_short_found_encodeSnappyBetterBlockAsm12B: + CMPW R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm12B + CMPW R6, R10 + BEQ candidateS_match_encodeSnappyBetterBlockAsm12B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBetterBlockAsm12B + +candidateS_match_encodeSnappyBetterBlockAsm12B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x32, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBetterBlockAsm12B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBetterBlockAsm12B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm12B + +match_extend_back_loop_encodeSnappyBetterBlockAsm12B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBetterBlockAsm12B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBetterBlockAsm12B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm12B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm12B + +match_extend_back_end_encodeSnappyBetterBlockAsm12B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm12B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm12B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm12B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm12B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B + BLO match_nolit_end_encodeSnappyBetterBlockAsm12B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeSnappyBetterBlockAsm12B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm12B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBetterBlockAsm12B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeSnappyBetterBlockAsm12B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeSnappyBetterBlockAsm12B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeSnappyBetterBlockAsm12B + BLO three_bytes_match_emit_encodeSnappyBetterBlockAsm12B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeSnappyBetterBlockAsm12B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm12B + +one_byte_match_emit_encodeSnappyBetterBlockAsm12B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm12B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm12B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm12Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm12B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm12B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm12B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm12B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm12B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBetterBlockAsm12B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm12B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x32, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x34, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x32, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x34, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 65536(R15) + ADD R12<<2, R0, R15 + MOVW R13, 65536(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeSnappyBetterBlockAsm12B: + CMP R8, R7 + BHS search_loop_encodeSnappyBetterBlockAsm12B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x32, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x32, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeSnappyBetterBlockAsm12B + +emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBetterBlockAsm12B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm12B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B + BLO three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBetterBlockAsm12B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm12B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBetterBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm12B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm12Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm12B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm10B(dst []byte, src []byte, tmp *[20480]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm10B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x000000a0, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBetterBlockAsm10B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBetterBlockAsm10B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBetterBlockAsm10B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x36, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 16384(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 16384(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm10B + CMP R6, R10 + BNE no_short_found_encodeSnappyBetterBlockAsm10B + MOVWU R7, R5 + JMP candidate_match_encodeSnappyBetterBlockAsm10B + +no_short_found_encodeSnappyBetterBlockAsm10B: + CMPW R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm10B + CMPW R6, R10 + BEQ candidateS_match_encodeSnappyBetterBlockAsm10B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBetterBlockAsm10B + +candidateS_match_encodeSnappyBetterBlockAsm10B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x34, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBetterBlockAsm10B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBetterBlockAsm10B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm10B + +match_extend_back_loop_encodeSnappyBetterBlockAsm10B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBetterBlockAsm10B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBetterBlockAsm10B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm10B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm10B + +match_extend_back_end_encodeSnappyBetterBlockAsm10B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm10B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm10B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm10B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm10B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B + BLO match_nolit_end_encodeSnappyBetterBlockAsm10B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeSnappyBetterBlockAsm10B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm10B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBetterBlockAsm10B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeSnappyBetterBlockAsm10B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeSnappyBetterBlockAsm10B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeSnappyBetterBlockAsm10B + BLO three_bytes_match_emit_encodeSnappyBetterBlockAsm10B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeSnappyBetterBlockAsm10B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm10B + +one_byte_match_emit_encodeSnappyBetterBlockAsm10B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm10B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm10B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm10Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm10B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm10B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm10B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B + CMPW $0x00000800, R7 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm10B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm10B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBetterBlockAsm10B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm10B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x34, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x36, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x34, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x36, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 16384(R15) + ADD R12<<2, R0, R15 + MOVW R13, 16384(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeSnappyBetterBlockAsm10B: + CMP R8, R7 + BHS search_loop_encodeSnappyBetterBlockAsm10B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x34, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x34, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeSnappyBetterBlockAsm10B + +emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBetterBlockAsm10B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm10B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B + BLO three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBetterBlockAsm10B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm10B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBetterBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm10B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm10Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm10B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func encodeSnappyBetterBlockAsm8B(dst []byte, src []byte, tmp *[5120]byte) int +// Requires: BMI, SSE2 +TEXT ·encodeSnappyBetterBlockAsm8B(SB), $24-64 + MOVD tmp+48(FP), R0 + MOVD dst_base+0(FP), R1 + MOVD $0x00000028, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_encodeSnappyBetterBlockAsm8B: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_encodeSnappyBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+32(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVD $0x00000000, R16 + MOVW R16, 24(RSP) + MOVD src_base+24(FP), R3 + +search_loop_encodeSnappyBetterBlockAsm8B: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x04, R5, R5 + ADD R5, R2, R5 + ADD $1, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_encodeSnappyBetterBlockAsm8B + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD $0x9e3779b1, R5 + MOVD R6, R9 + MOVD R6, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R5, R10, R10 + LSR $0x38, R10, R10 + MOVWU (R0)(R9<<2), R5 + ADD R10<<2, R0, R15 + MOVWU 4096(R15), R7 + MOVW R2, (R0)(R9<<2) + ADD R10<<2, R0, R15 + MOVW R2, 4096(R15) + MOVD (R3)(R5), R9 + MOVD (R3)(R7), R10 + CMP R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm8B + CMP R6, R10 + BNE no_short_found_encodeSnappyBetterBlockAsm8B + MOVWU R7, R5 + JMP candidate_match_encodeSnappyBetterBlockAsm8B + +no_short_found_encodeSnappyBetterBlockAsm8B: + CMPW R6, R9 + BEQ candidate_match_encodeSnappyBetterBlockAsm8B + CMPW R6, R10 + BEQ candidateS_match_encodeSnappyBetterBlockAsm8B + MOVWU 28(RSP), R2 + JMP search_loop_encodeSnappyBetterBlockAsm8B + +candidateS_match_encodeSnappyBetterBlockAsm8B: + LSR $0x08, R6, R6 + MOVD R6, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x36, R9, R9 + MOVWU (R0)(R9<<2), R5 + ADDW $1, R2, R2 + MOVW R2, (R0)(R9<<2) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_encodeSnappyBetterBlockAsm8B + SUBW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_encodeSnappyBetterBlockAsm8B: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm8B + +match_extend_back_loop_encodeSnappyBetterBlockAsm8B: + CMPW R6, R2 + BLS match_extend_back_end_encodeSnappyBetterBlockAsm8B + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_encodeSnappyBetterBlockAsm8B + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_encodeSnappyBetterBlockAsm8B + JMP match_extend_back_loop_encodeSnappyBetterBlockAsm8B + +match_extend_back_end_encodeSnappyBetterBlockAsm8B: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_encodeSnappyBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_dst_size_check_encodeSnappyBetterBlockAsm8B: + MOVWU R2, R6 + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+32(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R9 + + // matchLen + MOVD $0, R11 + +matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPW $0x10, R7 + BLO matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B + MOVD (R8)(R11), R10 + ADD R11, R8, R15 + MOVD 8(R15), R12 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B + ADD R11, R9, R15 + MOVD 8(R15), R16 + EOR R16, R12, R12 + TST R12, R12 + BNE matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R11, R11 + MOVWU R11, R11 + JMP matchlen_loopback_16_match_nolit_encodeSnappyBetterBlockAsm8B + +matchlen_bsf_16match_nolit_encodeSnappyBetterBlockAsm8B: + RBIT R12, R12 + CLZ R12, R12 + ASR $0x03, R12, R12 + ADD R12, R11, R11 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match8_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPW $0x08, R7 + BLO matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B + MOVD (R8)(R11), R10 + MOVD (R9)(R11), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R11, R11 + MOVWU R11, R11 + JMP matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B + +matchlen_bsf_8_match_nolit_encodeSnappyBetterBlockAsm8B: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R11, R11 + MOVWU R11, R11 + JMP match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match4_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPW $0x04, R7 + BLO matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B + MOVWU (R8)(R11), R10 + MOVWU (R9)(R11), R16 + CMPW R10, R16 + BNE matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R11, R11 + MOVWU R11, R11 + +matchlen_match2_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPW $0x01, R7 + BEQ matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B + BLO match_nolit_end_encodeSnappyBetterBlockAsm8B + MOVHU (R8)(R11), R16 + BFI $0, R16, $16, R10 + ADD R11, R9, R15 + MOVHU (R15), R15 + AND $0xffff, R10, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B + ADD $2, R11, R11 + MOVWU R11, R11 + SUBSW $0x02, R7, R7 + BEQ match_nolit_end_encodeSnappyBetterBlockAsm8B + +matchlen_match1_match_nolit_encodeSnappyBetterBlockAsm8B: + MOVBU (R8)(R11), R16 + BFI $0, R16, $8, R10 + ADD R11, R9, R15 + MOVBU (R15), R15 + AND $0xff, R10, R16 + CMP R16, R15 + BNE match_nolit_end_encodeSnappyBetterBlockAsm8B + ADD $1, R11, R11 + MOVWU R11, R11 + +match_nolit_end_encodeSnappyBetterBlockAsm8B: + MOVWU R2, R7 + SUBW R5, R7, R7 + + // Check if repeat + MOVW R7, 24(RSP) + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R5, R3, R9 + SUBW R5, R8, R8 + SUB $1, R8, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_match_emit_encodeSnappyBetterBlockAsm8B + CMPW $0x00000100, R5 + BLO two_bytes_match_emit_encodeSnappyBetterBlockAsm8B + BLO three_bytes_match_emit_encodeSnappyBetterBlockAsm8B + +three_bytes_match_emit_encodeSnappyBetterBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R5, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B + +two_bytes_match_emit_encodeSnappyBetterBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R5, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_match_emit_encodeSnappyBetterBlockAsm8B + JMP memmove_long_match_emit_encodeSnappyBetterBlockAsm8B + +one_byte_match_emit_encodeSnappyBetterBlockAsm8B: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R1) + ADD $0x01, R1, R1 + +memmove_match_emit_encodeSnappyBetterBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8: + MOVD (R9), R10 + MOVD R10, (R1) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: + MOVD (R9), R10 + ADD R8, R9, R15 + MOVD -8(R15), R9 + MOVD R10, (R1) + ADD R8, R1, R15 + MOVD R9, -8(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: + FMOVQ (R9), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_match_emit_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: + FMOVQ (R9), F0 + FMOVQ 16(R9), F1 + ADD R8, R9, R15 + FMOVQ -32(R15), F2 + ADD R8, R9, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R8, R1, R15 + FMOVQ F2, -32(R15) + ADD R8, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_match_emit_encodeSnappyBetterBlockAsm8B: + MOVD R5, R1 + JMP emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B + +memmove_long_match_emit_encodeSnappyBetterBlockAsm8B: + ADD R8, R1, R5 + + // genMemMoveLong + MOVD R9, R10 + MOVD R1, R12 + MOVD R8, R13 + +emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R10, R10 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_match_emit_encodeSnappyBetterBlockAsm8Blarge_big_loop_back + ADD R8, R9, R15 + FMOVQ -32(R15), F0 + ADD R8, R9, R15 + FMOVQ -16(R15), F1 + ADD R8, R1, R15 + FMOVQ F0, -32(R15) + ADD R8, R1, R15 + FMOVQ F1, -16(R15) + MOVD R5, R1 + +emit_literal_done_match_emit_encodeSnappyBetterBlockAsm8B: + ADDW R11, R2, R2 + ADDW $0x04, R11, R11 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B: + CMPW $0x40, R11 + BLS two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B + MOVD $0xee, R16 + MOVB R16, (R1) + MOVH R7, 1(R1) + SUB $60, R11, R11 + MOVWU R11, R11 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_encodeSnappyBetterBlockAsm8B + +two_byte_offset_short_match_nolit_encodeSnappyBetterBlockAsm8B: + MOVWU R11, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R11 + BHS emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R7, 1(R1) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R5, R5 + MOVB R5, (R1) + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B + +emit_copy_three_match_nolit_encodeSnappyBetterBlockAsm8B: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R1) + MOVH R7, 1(R1) + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_encodeSnappyBetterBlockAsm8B: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_encodeSnappyBetterBlockAsm8B + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +match_nolit_dst_ok_encodeSnappyBetterBlockAsm8B: + MOVD $0x0000cf1bbcdcbf9b, R5 + MOVD $0x9e3779b1, R7 + ADD $1, R6, R6 + SUB $2, R2, R8 + MOVD (R3)(R6), R9 + ADD R6, R3, R15 + MOVD 1(R15), R10 + MOVD (R3)(R8), R11 + ADD R8, R3, R15 + MOVD 1(R15), R12 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x36, R9, R9 + LSL $0x20, R10, R10 + MUL R7, R10, R10 + LSR $0x38, R10, R10 + LSL $0x10, R11, R11 + MUL R5, R11, R11 + LSR $0x36, R11, R11 + LSL $0x20, R12, R12 + MUL R7, R12, R12 + LSR $0x38, R12, R12 + ADD $1, R6, R7 + ADD $1, R8, R13 + MOVW R6, (R0)(R9<<2) + MOVW R8, (R0)(R11<<2) + ADD R10<<2, R0, R15 + MOVW R7, 4096(R15) + ADD R12<<2, R0, R15 + MOVW R13, 4096(R15) + ADD R6, R8, R7 + ADD $1, R7, R7 + LSR $0x01, R7, R7 + ADD $0x01, R6, R6 + SUB $0x01, R8, R8 + +index_loop_encodeSnappyBetterBlockAsm8B: + CMP R8, R7 + BHS search_loop_encodeSnappyBetterBlockAsm8B + MOVD (R3)(R6), R9 + MOVD (R3)(R7), R10 + LSL $0x10, R9, R9 + MUL R5, R9, R9 + LSR $0x36, R9, R9 + LSL $0x10, R10, R10 + MUL R5, R10, R10 + LSR $0x36, R10, R10 + MOVW R6, (R0)(R9<<2) + MOVW R7, (R0)(R10<<2) + ADD $0x02, R6, R6 + ADD $0x02, R7, R7 + JMP index_loop_encodeSnappyBetterBlockAsm8B + +emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_encodeSnappyBetterBlockAsm8B + MOVD $0x00000000, R16 + MOVD R16, ret+56(FP) + RET + +emit_remainder_ok_encodeSnappyBetterBlockAsm8B: + MOVD src_len+32(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R2 + MOVWU R2, R2 + CMPW $0x3c, R2 + BLO one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B + CMPW $0x00000100, R2 + BLO two_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B + BLO three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B + +three_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVD $0xf4, R16 + MOVB R16, (R1) + MOVH R2, 1(R1) + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B + +two_bytes_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVD $0xf0, R16 + MOVB R16, (R1) + MOVB R2, 1(R1) + ADD $0x02, R1, R1 + CMPW $0x40, R2 + BLO memmove_emit_remainder_encodeSnappyBetterBlockAsm8B + JMP memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B + +one_byte_emit_remainder_encodeSnappyBetterBlockAsm8B: + LSLW $0x02, R2, R16 + BFI $0, R16, $8, R2 + MOVB R2, (R1) + ADD $0x01, R1, R1 + +memmove_emit_remainder_encodeSnappyBetterBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveShort + CMP $0x03, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_1or2 + BEQ emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_3 + CMP $0x08, R3 + BLO emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_4through7 + CMP $0x10, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_8through16 + CMP $0x20, R3 + BLS emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_17through32 + JMP emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64 + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_1or2: + MOVBU (R0), R16 + BFI $0, R16, $8, R5 + ADD R3, R0, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R0 + MOVB R5, (R1) + ADD R3, R1, R15 + MOVB R0, -1(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_3: + MOVHU (R0), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R0), R16 + BFI $0, R16, $8, R0 + MOVH R5, (R1) + MOVB R0, 2(R1) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_4through7: + MOVWU (R0), R5 + ADD R3, R0, R15 + MOVWU -4(R15), R0 + MOVW R5, (R1) + ADD R3, R1, R15 + MOVW R0, -4(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_8through16: + MOVD (R0), R5 + ADD R3, R0, R15 + MOVD -8(R15), R0 + MOVD R5, (R1) + ADD R3, R1, R15 + MOVD R0, -8(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_17through32: + FMOVQ (R0), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R1) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B + +emit_lit_memmove_emit_remainder_encodeSnappyBetterBlockAsm8B_memmove_move_33through64: + FMOVQ (R0), F0 + FMOVQ 16(R0), F1 + ADD R3, R0, R15 + FMOVQ -32(R15), F2 + ADD R3, R0, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R1) + FMOVQ F1, 16(R1) + ADD R3, R1, R15 + FMOVQ F2, -32(R15) + ADD R3, R1, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVD R2, R1 + JMP emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B + +memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8B: + ADD R5, R1, R2 + MOVWU R5, R3 + + // genMemMoveLong + MOVD R0, R5 + MOVD R1, R6 + MOVD R3, R7 + +emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_emit_remainder_encodeSnappyBetterBlockAsm8Blarge_big_loop_back + ADD R3, R0, R15 + FMOVQ -32(R15), F0 + ADD R3, R0, R15 + FMOVQ -16(R15), F1 + ADD R3, R1, R15 + FMOVQ F0, -32(R15) + ADD R3, R1, R15 + FMOVQ F1, -16(R15) + MOVD R2, R1 + +emit_literal_done_emit_remainder_encodeSnappyBetterBlockAsm8B: + MOVD dst_base+0(FP), R0 + SUB R0, R1, R1 + MOVD R1, ret+56(FP) + RET + +// func calcBlockSize(src []byte, tmp *[32768]byte) int +// Requires: BMI, SSE2 +TEXT ·calcBlockSize(SB), $24-40 + MOVD tmp+24(FP), R0 + MOVD $0, R1 + MOVD $0x00000100, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_calcBlockSize: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_calcBlockSize + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+8(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+0(FP), R3 + +search_loop_calcBlockSize: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x05, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_calcBlockSize + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x33, R9, R9 + LSL $0x10, R10, R10 + MUL R8, R10, R10 + LSR $0x33, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x10, R9, R9 + MUL R8, R9, R9 + LSR $0x33, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_calcBlockSize + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_calcBlockSize + +repeat_extend_back_loop_calcBlockSize: + CMPW R5, R6 + BLS repeat_extend_back_end_calcBlockSize + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_calcBlockSize + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_calcBlockSize + +repeat_extend_back_end_calcBlockSize: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $5, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_calcBlockSize + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +repeat_dst_size_check_calcBlockSize: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_calcBlockSize + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_calcBlockSize + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_calcBlockSize + CMPW $0x00010000, R5 + BLO three_bytes_repeat_emit_calcBlockSize + CMPW $0x01000000, R5 + BLO four_bytes_repeat_emit_calcBlockSize + ADD $0x05, R1, R1 + JMP memmove_long_repeat_emit_calcBlockSize + +four_bytes_repeat_emit_calcBlockSize: + ADD $0x04, R1, R1 + JMP memmove_long_repeat_emit_calcBlockSize + +three_bytes_repeat_emit_calcBlockSize: + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_calcBlockSize + +two_bytes_repeat_emit_calcBlockSize: + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_calcBlockSize + JMP memmove_long_repeat_emit_calcBlockSize + +one_byte_repeat_emit_calcBlockSize: + ADD $0x01, R1, R1 + +memmove_repeat_emit_calcBlockSize: + ADD R7, R1, R1 + JMP emit_literal_done_repeat_emit_calcBlockSize + +memmove_long_repeat_emit_calcBlockSize: + ADD R7, R1, R1 + +emit_literal_done_repeat_emit_calcBlockSize: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+8(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_calcBlockSize: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_calcBlockSize + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_calcBlockSize + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_calcBlockSize + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_calcBlockSize + +matchlen_bsf_16repeat_extend_calcBlockSize: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_calcBlockSize + +matchlen_match8_repeat_extend_calcBlockSize: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_calcBlockSize + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_calcBlockSize + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_calcBlockSize + +matchlen_bsf_8_repeat_extend_calcBlockSize: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_calcBlockSize + +matchlen_match4_repeat_extend_calcBlockSize: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_calcBlockSize + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_calcBlockSize + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_calcBlockSize: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_calcBlockSize + BLO repeat_extend_forward_end_calcBlockSize + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_calcBlockSize + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_calcBlockSize + +matchlen_match1_repeat_extend_calcBlockSize: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_calcBlockSize + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_calcBlockSize: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy + CMPW $0x00010000, R6 + BLO two_byte_offset_repeat_as_copy_calcBlockSize + +four_bytes_loop_back_repeat_as_copy_calcBlockSize: + CMPW $0x40, R5 + BLS four_bytes_remain_repeat_as_copy_calcBlockSize + SUB $64, R5, R5 + MOVWU R5, R5 + ADD $0x05, R1, R1 + CMPW $0x04, R5 + BLO four_bytes_remain_repeat_as_copy_calcBlockSize + JMP four_bytes_loop_back_repeat_as_copy_calcBlockSize + +four_bytes_remain_repeat_as_copy_calcBlockSize: + TSTW R5, R5 + BEQ repeat_end_emit_calcBlockSize + MOVD $0, R5 + ADD $0x05, R1, R1 + JMP repeat_end_emit_calcBlockSize + +two_byte_offset_repeat_as_copy_calcBlockSize: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_calcBlockSize + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_calcBlockSize + +two_byte_offset_short_repeat_as_copy_calcBlockSize: + MOVWU R5, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_calcBlockSize + CMPW $0x00000800, R6 + BHS emit_copy_three_repeat_as_copy_calcBlockSize + ADD $0x02, R1, R1 + JMP repeat_end_emit_calcBlockSize + +emit_copy_three_repeat_as_copy_calcBlockSize: + ADD $0x03, R1, R1 + +repeat_end_emit_calcBlockSize: + MOVW R2, 20(RSP) + JMP search_loop_calcBlockSize + +no_repeat_found_calcBlockSize: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_calcBlockSize + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_calcBlockSize + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_calcBlockSize + MOVWU 28(RSP), R2 + JMP search_loop_calcBlockSize + +candidate3_match_calcBlockSize: + ADDW $0x02, R2, R2 + JMP candidate_match_calcBlockSize + +candidate2_match_calcBlockSize: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_calcBlockSize: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_calcBlockSize + +match_extend_back_loop_calcBlockSize: + CMPW R6, R2 + BLS match_extend_back_end_calcBlockSize + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_calcBlockSize + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_calcBlockSize + JMP match_extend_back_loop_calcBlockSize + +match_extend_back_end_calcBlockSize: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $5, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_calcBlockSize + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +match_dst_size_check_calcBlockSize: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_calcBlockSize + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R6 + MOVWU R6, R6 + CMPW $0x3c, R6 + BLO one_byte_match_emit_calcBlockSize + CMPW $0x00000100, R6 + BLO two_bytes_match_emit_calcBlockSize + CMPW $0x00010000, R6 + BLO three_bytes_match_emit_calcBlockSize + CMPW $0x01000000, R6 + BLO four_bytes_match_emit_calcBlockSize + ADD $0x05, R1, R1 + JMP memmove_long_match_emit_calcBlockSize + +four_bytes_match_emit_calcBlockSize: + ADD $0x04, R1, R1 + JMP memmove_long_match_emit_calcBlockSize + +three_bytes_match_emit_calcBlockSize: + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_calcBlockSize + +two_bytes_match_emit_calcBlockSize: + ADD $0x02, R1, R1 + CMPW $0x40, R6 + BLO memmove_match_emit_calcBlockSize + JMP memmove_long_match_emit_calcBlockSize + +one_byte_match_emit_calcBlockSize: + ADD $0x01, R1, R1 + +memmove_match_emit_calcBlockSize: + ADD R8, R1, R1 + JMP emit_literal_done_match_emit_calcBlockSize + +memmove_long_match_emit_calcBlockSize: + ADD R8, R1, R1 + +emit_literal_done_match_emit_calcBlockSize: +match_nolit_loop_calcBlockSize: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+8(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_calcBlockSize: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_calcBlockSize + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_calcBlockSize + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_calcBlockSize + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_calcBlockSize + +matchlen_bsf_16match_nolit_calcBlockSize: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_calcBlockSize + +matchlen_match8_match_nolit_calcBlockSize: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_calcBlockSize + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_calcBlockSize + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_calcBlockSize + +matchlen_bsf_8_match_nolit_calcBlockSize: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_calcBlockSize + +matchlen_match4_match_nolit_calcBlockSize: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_calcBlockSize + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_calcBlockSize + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_calcBlockSize: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_calcBlockSize + BLO match_nolit_end_calcBlockSize + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_calcBlockSize + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_calcBlockSize + +matchlen_match1_match_nolit_calcBlockSize: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_calcBlockSize + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_calcBlockSize: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy + CMPW $0x00010000, R5 + BLO two_byte_offset_match_nolit_calcBlockSize + +four_bytes_loop_back_match_nolit_calcBlockSize: + CMPW $0x40, R9 + BLS four_bytes_remain_match_nolit_calcBlockSize + SUB $64, R9, R9 + MOVWU R9, R9 + ADD $0x05, R1, R1 + CMPW $0x04, R9 + BLO four_bytes_remain_match_nolit_calcBlockSize + JMP four_bytes_loop_back_match_nolit_calcBlockSize + +four_bytes_remain_match_nolit_calcBlockSize: + TSTW R9, R9 + BEQ match_nolit_emitcopy_end_calcBlockSize + MOVD $0, R5 + ADD $0x05, R1, R1 + JMP match_nolit_emitcopy_end_calcBlockSize + +two_byte_offset_match_nolit_calcBlockSize: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_calcBlockSize + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_calcBlockSize + +two_byte_offset_short_match_nolit_calcBlockSize: + MOVWU R9, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_calcBlockSize + CMPW $0x00000800, R5 + BHS emit_copy_three_match_nolit_calcBlockSize + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_calcBlockSize + +emit_copy_three_match_nolit_calcBlockSize: + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_calcBlockSize: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_calcBlockSize + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_calcBlockSize + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +match_nolit_dst_ok_calcBlockSize: + MOVD $0x0000cf1bbcdcbf9b, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x10, R7, R7 + MUL R8, R7, R7 + LSR $0x33, R7, R7 + LSL $0x10, R5, R5 + MUL R8, R5, R5 + LSR $0x33, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_calcBlockSize + ADDW $1, R2, R2 + JMP search_loop_calcBlockSize + +emit_remainder_calcBlockSize: + MOVD src_len+8(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $5, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_calcBlockSize + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +emit_remainder_ok_calcBlockSize: + MOVD src_len+8(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_calcBlockSize + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R0 + MOVWU R0, R0 + CMPW $0x3c, R0 + BLO one_byte_emit_remainder_calcBlockSize + CMPW $0x00000100, R0 + BLO two_bytes_emit_remainder_calcBlockSize + CMPW $0x00010000, R0 + BLO three_bytes_emit_remainder_calcBlockSize + CMPW $0x01000000, R0 + BLO four_bytes_emit_remainder_calcBlockSize + ADD $0x05, R1, R1 + JMP memmove_long_emit_remainder_calcBlockSize + +four_bytes_emit_remainder_calcBlockSize: + ADD $0x04, R1, R1 + JMP memmove_long_emit_remainder_calcBlockSize + +three_bytes_emit_remainder_calcBlockSize: + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_calcBlockSize + +two_bytes_emit_remainder_calcBlockSize: + ADD $0x02, R1, R1 + CMPW $0x40, R0 + BLO memmove_emit_remainder_calcBlockSize + JMP memmove_long_emit_remainder_calcBlockSize + +one_byte_emit_remainder_calcBlockSize: + ADD $0x01, R1, R1 + +memmove_emit_remainder_calcBlockSize: + ADD R5, R1, R0 + MOVD R0, R1 + JMP emit_literal_done_emit_remainder_calcBlockSize + +memmove_long_emit_remainder_calcBlockSize: + ADD R5, R1, R0 + MOVD R0, R1 + +emit_literal_done_emit_remainder_calcBlockSize: + MOVD R1, ret+32(FP) + RET + +// func calcBlockSizeSmall(src []byte, tmp *[2048]byte) int +// Requires: BMI, SSE2 +TEXT ·calcBlockSizeSmall(SB), $24-40 + MOVD tmp+24(FP), R0 + MOVD $0, R1 + MOVD $0x00000010, R2 + MOVD R0, R3 + VEOR V0.B16, V0.B16, V0.B16 + +zero_loop_calcBlockSizeSmall: + FMOVQ F0, (R3) + FMOVQ F0, 16(R3) + FMOVQ F0, 32(R3) + FMOVQ F0, 48(R3) + FMOVQ F0, 64(R3) + FMOVQ F0, 80(R3) + FMOVQ F0, 96(R3) + FMOVQ F0, 112(R3) + ADD $0x80, R3, R3 + SUBS $1, R2, R2 + BNE zero_loop_calcBlockSizeSmall + MOVD $0x00000000, R16 + MOVW R16, 20(RSP) + MOVD src_len+8(FP), R2 + SUB $9, R2, R3 + SUB $8, R2, R5 + MOVW R5, 16(RSP) + LSR $0x05, R2, R2 + SUBW R2, R3, R3 + ADD R3, R1, R3 + MOVD R3, 8(RSP) + MOVD $0x00000001, R2 + MOVW R2, 24(RSP) + MOVD src_base+0(FP), R3 + +search_loop_calcBlockSizeSmall: + MOVWU R2, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + LSRW $0x04, R5, R5 + ADD R5, R2, R5 + ADD $4, R5, R5 + MOVWU R5, R5 + MOVWU 16(RSP), R16 + CMPW R16, R5 + BHS emit_remainder_calcBlockSizeSmall + MOVD (R3)(R2), R6 + MOVW R5, 28(RSP) + MOVD $0x9e3779b1, R8 + MOVD R6, R9 + MOVD R6, R10 + LSR $0x08, R10, R10 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x37, R9, R9 + LSL $0x20, R10, R10 + MUL R8, R10, R10 + LSR $0x37, R10, R10 + MOVWU (R0)(R9<<2), R5 + MOVWU (R0)(R10<<2), R7 + MOVW R2, (R0)(R9<<2) + ADD $1, R2, R9 + MOVWU R9, R9 + MOVW R9, (R0)(R10<<2) + MOVD R6, R9 + LSR $0x10, R9, R9 + LSL $0x20, R9, R9 + MUL R8, R9, R9 + LSR $0x37, R9, R9 + MOVWU R2, R8 + MOVWU 24(RSP), R16 + SUBW R16, R8, R8 + ADD R8, R3, R15 + MOVWU 1(R15), R10 + MOVD R6, R8 + LSR $0x08, R8, R8 + CMPW R10, R8 + BNE no_repeat_found_calcBlockSizeSmall + ADD $1, R2, R6 + MOVWU R6, R6 + MOVWU 20(RSP), R5 + MOVWU R6, R7 + MOVWU 24(RSP), R16 + SUBSW R16, R7, R7 + BEQ repeat_extend_back_end_calcBlockSizeSmall + +repeat_extend_back_loop_calcBlockSizeSmall: + CMPW R5, R6 + BLS repeat_extend_back_end_calcBlockSizeSmall + ADD R7, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + ADD R6, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R9 + AND $0xff, R9, R16 + AND $0xff, R8, R15 + CMP R16, R15 + BNE repeat_extend_back_end_calcBlockSizeSmall + SUB $1, R6, R6 + MOVWU R6, R6 + SUBSW $1, R7, R7 + BNE repeat_extend_back_loop_calcBlockSizeSmall + +repeat_extend_back_end_calcBlockSizeSmall: + MOVWU R6, R5 + MOVWU 20(RSP), R16 + SUBW R16, R5, R5 + ADD R5, R1, R5 + ADD $3, R5, R5 + MOVD 8(RSP), R16 + CMP R16, R5 + BLO repeat_dst_size_check_calcBlockSizeSmall + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +repeat_dst_size_check_calcBlockSizeSmall: + MOVWU 20(RSP), R5 + CMPW R6, R5 + BEQ emit_literal_done_repeat_emit_calcBlockSizeSmall + MOVWU R6, R7 + MOVW R6, 20(RSP) + ADD R5, R3, R8 + SUBW R5, R7, R7 + SUB $1, R7, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_repeat_emit_calcBlockSizeSmall + CMPW $0x00000100, R5 + BLO two_bytes_repeat_emit_calcBlockSizeSmall + BLO three_bytes_repeat_emit_calcBlockSizeSmall + +three_bytes_repeat_emit_calcBlockSizeSmall: + ADD $0x03, R1, R1 + JMP memmove_long_repeat_emit_calcBlockSizeSmall + +two_bytes_repeat_emit_calcBlockSizeSmall: + ADD $0x02, R1, R1 + CMPW $0x40, R5 + BLO memmove_repeat_emit_calcBlockSizeSmall + JMP memmove_long_repeat_emit_calcBlockSizeSmall + +one_byte_repeat_emit_calcBlockSizeSmall: + ADD $0x01, R1, R1 + +memmove_repeat_emit_calcBlockSizeSmall: + ADD R7, R1, R1 + JMP emit_literal_done_repeat_emit_calcBlockSizeSmall + +memmove_long_repeat_emit_calcBlockSizeSmall: + ADD R7, R1, R1 + +emit_literal_done_repeat_emit_calcBlockSizeSmall: + ADDW $0x05, R2, R2 + MOVWU R2, R5 + MOVWU 24(RSP), R16 + SUBW R16, R5, R5 + MOVD src_len+8(FP), R7 + SUBW R2, R7, R7 + ADD R2, R3, R8 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R10 + +matchlen_loopback_16_repeat_extend_calcBlockSizeSmall: + CMPW $0x10, R7 + BLO matchlen_match8_repeat_extend_calcBlockSizeSmall + MOVD (R8)(R10), R9 + ADD R10, R8, R15 + MOVD 8(R15), R11 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_calcBlockSizeSmall + ADD R10, R5, R15 + MOVD 8(R15), R16 + EOR R16, R11, R11 + TST R11, R11 + BNE matchlen_bsf_16repeat_extend_calcBlockSizeSmall + SUB $16, R7, R7 + MOVWU R7, R7 + ADD $16, R10, R10 + MOVWU R10, R10 + JMP matchlen_loopback_16_repeat_extend_calcBlockSizeSmall + +matchlen_bsf_16repeat_extend_calcBlockSizeSmall: + RBIT R11, R11 + CLZ R11, R11 + ASR $0x03, R11, R11 + ADD R11, R10, R10 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match8_repeat_extend_calcBlockSizeSmall: + CMPW $0x08, R7 + BLO matchlen_match4_repeat_extend_calcBlockSizeSmall + MOVD (R8)(R10), R9 + MOVD (R5)(R10), R16 + EOR R16, R9, R9 + TST R9, R9 + BNE matchlen_bsf_8_repeat_extend_calcBlockSizeSmall + SUB $8, R7, R7 + MOVWU R7, R7 + ADD $8, R10, R10 + MOVWU R10, R10 + JMP matchlen_match4_repeat_extend_calcBlockSizeSmall + +matchlen_bsf_8_repeat_extend_calcBlockSizeSmall: + RBIT R9, R9 + CLZ R9, R9 + ASR $0x03, R9, R9 + ADD R9, R10, R10 + MOVWU R10, R10 + JMP repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match4_repeat_extend_calcBlockSizeSmall: + CMPW $0x04, R7 + BLO matchlen_match2_repeat_extend_calcBlockSizeSmall + MOVWU (R8)(R10), R9 + MOVWU (R5)(R10), R16 + CMPW R9, R16 + BNE matchlen_match2_repeat_extend_calcBlockSizeSmall + SUB $4, R7, R7 + MOVWU R7, R7 + ADD $4, R10, R10 + MOVWU R10, R10 + +matchlen_match2_repeat_extend_calcBlockSizeSmall: + CMPW $0x01, R7 + BEQ matchlen_match1_repeat_extend_calcBlockSizeSmall + BLO repeat_extend_forward_end_calcBlockSizeSmall + MOVHU (R8)(R10), R16 + BFI $0, R16, $16, R9 + ADD R10, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R9, R16 + CMP R16, R15 + BNE matchlen_match1_repeat_extend_calcBlockSizeSmall + ADD $2, R10, R10 + MOVWU R10, R10 + SUBSW $0x02, R7, R7 + BEQ repeat_extend_forward_end_calcBlockSizeSmall + +matchlen_match1_repeat_extend_calcBlockSizeSmall: + MOVBU (R8)(R10), R16 + BFI $0, R16, $8, R9 + ADD R10, R5, R15 + MOVBU (R15), R15 + AND $0xff, R9, R16 + CMP R16, R15 + BNE repeat_extend_forward_end_calcBlockSizeSmall + ADD $1, R10, R10 + MOVWU R10, R10 + +repeat_extend_forward_end_calcBlockSizeSmall: + ADDW R10, R2, R2 + MOVWU R2, R5 + SUBW R6, R5, R5 + MOVWU 24(RSP), R6 + + // emitCopy +two_byte_offset_repeat_as_copy_calcBlockSizeSmall: + CMPW $0x40, R5 + BLS two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall + SUB $60, R5, R5 + MOVWU R5, R5 + ADD $0x03, R1, R1 + JMP two_byte_offset_repeat_as_copy_calcBlockSizeSmall + +two_byte_offset_short_repeat_as_copy_calcBlockSizeSmall: + MOVWU R5, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R5 + BHS emit_copy_three_repeat_as_copy_calcBlockSizeSmall + ADD $0x02, R1, R1 + JMP repeat_end_emit_calcBlockSizeSmall + +emit_copy_three_repeat_as_copy_calcBlockSizeSmall: + ADD $0x03, R1, R1 + +repeat_end_emit_calcBlockSizeSmall: + MOVW R2, 20(RSP) + JMP search_loop_calcBlockSizeSmall + +no_repeat_found_calcBlockSizeSmall: + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate_match_calcBlockSizeSmall + LSR $0x08, R6, R6 + MOVWU (R0)(R9<<2), R5 + ADD $2, R2, R8 + MOVWU R8, R8 + MOVWU (R3)(R7), R16 + CMPW R6, R16 + BEQ candidate2_match_calcBlockSizeSmall + MOVW R8, (R0)(R9<<2) + LSR $0x08, R6, R6 + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ candidate3_match_calcBlockSizeSmall + MOVWU 28(RSP), R2 + JMP search_loop_calcBlockSizeSmall + +candidate3_match_calcBlockSizeSmall: + ADDW $0x02, R2, R2 + JMP candidate_match_calcBlockSizeSmall + +candidate2_match_calcBlockSizeSmall: + MOVW R8, (R0)(R9<<2) + ADDW $1, R2, R2 + MOVWU R7, R5 + +candidate_match_calcBlockSizeSmall: + MOVWU 20(RSP), R6 + TSTW R5, R5 + BEQ match_extend_back_end_calcBlockSizeSmall + +match_extend_back_loop_calcBlockSizeSmall: + CMPW R6, R2 + BLS match_extend_back_end_calcBlockSizeSmall + ADD R5, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R7 + ADD R2, R3, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R8 + AND $0xff, R8, R16 + AND $0xff, R7, R15 + CMP R16, R15 + BNE match_extend_back_end_calcBlockSizeSmall + SUB $1, R2, R2 + MOVWU R2, R2 + SUBSW $1, R5, R5 + BEQ match_extend_back_end_calcBlockSizeSmall + JMP match_extend_back_loop_calcBlockSizeSmall + +match_extend_back_end_calcBlockSizeSmall: + MOVWU R2, R6 + MOVWU 20(RSP), R16 + SUBW R16, R6, R6 + ADD R6, R1, R6 + ADD $3, R6, R6 + MOVD 8(RSP), R16 + CMP R16, R6 + BLO match_dst_size_check_calcBlockSizeSmall + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +match_dst_size_check_calcBlockSizeSmall: + MOVWU R2, R6 + MOVWU 20(RSP), R7 + CMPW R6, R7 + BEQ emit_literal_done_match_emit_calcBlockSizeSmall + MOVWU R6, R8 + MOVW R6, 20(RSP) + ADD R7, R3, R6 + SUBW R7, R8, R8 + SUB $1, R8, R6 + MOVWU R6, R6 + CMPW $0x3c, R6 + BLO one_byte_match_emit_calcBlockSizeSmall + CMPW $0x00000100, R6 + BLO two_bytes_match_emit_calcBlockSizeSmall + BLO three_bytes_match_emit_calcBlockSizeSmall + +three_bytes_match_emit_calcBlockSizeSmall: + ADD $0x03, R1, R1 + JMP memmove_long_match_emit_calcBlockSizeSmall + +two_bytes_match_emit_calcBlockSizeSmall: + ADD $0x02, R1, R1 + CMPW $0x40, R6 + BLO memmove_match_emit_calcBlockSizeSmall + JMP memmove_long_match_emit_calcBlockSizeSmall + +one_byte_match_emit_calcBlockSizeSmall: + ADD $0x01, R1, R1 + +memmove_match_emit_calcBlockSizeSmall: + ADD R8, R1, R1 + JMP emit_literal_done_match_emit_calcBlockSizeSmall + +memmove_long_match_emit_calcBlockSizeSmall: + ADD R8, R1, R1 + +emit_literal_done_match_emit_calcBlockSizeSmall: +match_nolit_loop_calcBlockSizeSmall: + MOVWU R2, R6 + SUBW R5, R6, R6 + MOVW R6, 24(RSP) + ADDW $0x04, R2, R2 + ADDW $0x04, R5, R5 + MOVD src_len+8(FP), R6 + SUBW R2, R6, R6 + ADD R2, R3, R7 + ADD R5, R3, R5 + + // matchLen + MOVD $0, R9 + +matchlen_loopback_16_match_nolit_calcBlockSizeSmall: + CMPW $0x10, R6 + BLO matchlen_match8_match_nolit_calcBlockSizeSmall + MOVD (R7)(R9), R8 + ADD R9, R7, R15 + MOVD 8(R15), R10 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_calcBlockSizeSmall + ADD R9, R5, R15 + MOVD 8(R15), R16 + EOR R16, R10, R10 + TST R10, R10 + BNE matchlen_bsf_16match_nolit_calcBlockSizeSmall + SUB $16, R6, R6 + MOVWU R6, R6 + ADD $16, R9, R9 + MOVWU R9, R9 + JMP matchlen_loopback_16_match_nolit_calcBlockSizeSmall + +matchlen_bsf_16match_nolit_calcBlockSizeSmall: + RBIT R10, R10 + CLZ R10, R10 + ASR $0x03, R10, R10 + ADD R10, R9, R9 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_calcBlockSizeSmall + +matchlen_match8_match_nolit_calcBlockSizeSmall: + CMPW $0x08, R6 + BLO matchlen_match4_match_nolit_calcBlockSizeSmall + MOVD (R7)(R9), R8 + MOVD (R5)(R9), R16 + EOR R16, R8, R8 + TST R8, R8 + BNE matchlen_bsf_8_match_nolit_calcBlockSizeSmall + SUB $8, R6, R6 + MOVWU R6, R6 + ADD $8, R9, R9 + MOVWU R9, R9 + JMP matchlen_match4_match_nolit_calcBlockSizeSmall + +matchlen_bsf_8_match_nolit_calcBlockSizeSmall: + RBIT R8, R8 + CLZ R8, R8 + ASR $0x03, R8, R8 + ADD R8, R9, R9 + MOVWU R9, R9 + JMP match_nolit_end_calcBlockSizeSmall + +matchlen_match4_match_nolit_calcBlockSizeSmall: + CMPW $0x04, R6 + BLO matchlen_match2_match_nolit_calcBlockSizeSmall + MOVWU (R7)(R9), R8 + MOVWU (R5)(R9), R16 + CMPW R8, R16 + BNE matchlen_match2_match_nolit_calcBlockSizeSmall + SUB $4, R6, R6 + MOVWU R6, R6 + ADD $4, R9, R9 + MOVWU R9, R9 + +matchlen_match2_match_nolit_calcBlockSizeSmall: + CMPW $0x01, R6 + BEQ matchlen_match1_match_nolit_calcBlockSizeSmall + BLO match_nolit_end_calcBlockSizeSmall + MOVHU (R7)(R9), R16 + BFI $0, R16, $16, R8 + ADD R9, R5, R15 + MOVHU (R15), R15 + AND $0xffff, R8, R16 + CMP R16, R15 + BNE matchlen_match1_match_nolit_calcBlockSizeSmall + ADD $2, R9, R9 + MOVWU R9, R9 + SUBSW $0x02, R6, R6 + BEQ match_nolit_end_calcBlockSizeSmall + +matchlen_match1_match_nolit_calcBlockSizeSmall: + MOVBU (R7)(R9), R16 + BFI $0, R16, $8, R8 + ADD R9, R5, R15 + MOVBU (R15), R15 + AND $0xff, R8, R16 + CMP R16, R15 + BNE match_nolit_end_calcBlockSizeSmall + ADD $1, R9, R9 + MOVWU R9, R9 + +match_nolit_end_calcBlockSizeSmall: + ADDW R9, R2, R2 + MOVWU 24(RSP), R5 + ADDW $0x04, R9, R9 + MOVW R2, 20(RSP) + + // emitCopy +two_byte_offset_match_nolit_calcBlockSizeSmall: + CMPW $0x40, R9 + BLS two_byte_offset_short_match_nolit_calcBlockSizeSmall + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R1, R1 + JMP two_byte_offset_match_nolit_calcBlockSizeSmall + +two_byte_offset_short_match_nolit_calcBlockSizeSmall: + MOVWU R9, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R9 + BHS emit_copy_three_match_nolit_calcBlockSizeSmall + ADD $0x02, R1, R1 + JMP match_nolit_emitcopy_end_calcBlockSizeSmall + +emit_copy_three_match_nolit_calcBlockSizeSmall: + ADD $0x03, R1, R1 + +match_nolit_emitcopy_end_calcBlockSizeSmall: + MOVWU 16(RSP), R16 + CMPW R16, R2 + BHS emit_remainder_calcBlockSizeSmall + ADD R2, R3, R15 + MOVD -2(R15), R6 + MOVD 8(RSP), R16 + CMP R16, R1 + BLO match_nolit_dst_ok_calcBlockSizeSmall + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +match_nolit_dst_ok_calcBlockSizeSmall: + MOVD $0x9e3779b1, R8 + MOVD R6, R7 + LSR $0x10, R6, R6 + MOVD R6, R5 + LSL $0x20, R7, R7 + MUL R8, R7, R7 + LSR $0x37, R7, R7 + LSL $0x20, R5, R5 + MUL R8, R5, R5 + LSR $0x37, R5, R5 + SUB $2, R2, R8 + MOVWU R8, R8 + ADD R5<<2, R0, R9 + MOVWU (R9), R5 + MOVW R8, (R0)(R7<<2) + MOVW R2, (R9) + MOVWU (R3)(R5), R16 + CMPW R6, R16 + BEQ match_nolit_loop_calcBlockSizeSmall + ADDW $1, R2, R2 + JMP search_loop_calcBlockSizeSmall + +emit_remainder_calcBlockSizeSmall: + MOVD src_len+8(FP), R0 + MOVWU 20(RSP), R16 + SUBW R16, R0, R0 + ADD R0, R1, R0 + ADD $3, R0, R0 + MOVD 8(RSP), R16 + CMP R16, R0 + BLO emit_remainder_ok_calcBlockSizeSmall + MOVD $0x00000000, R16 + MOVD R16, ret+32(FP) + RET + +emit_remainder_ok_calcBlockSizeSmall: + MOVD src_len+8(FP), R0 + MOVWU 20(RSP), R2 + CMPW R0, R2 + BEQ emit_literal_done_emit_remainder_calcBlockSizeSmall + MOVWU R0, R5 + MOVW R0, 20(RSP) + ADD R2, R3, R0 + SUBW R2, R5, R5 + SUB $1, R5, R0 + MOVWU R0, R0 + CMPW $0x3c, R0 + BLO one_byte_emit_remainder_calcBlockSizeSmall + CMPW $0x00000100, R0 + BLO two_bytes_emit_remainder_calcBlockSizeSmall + BLO three_bytes_emit_remainder_calcBlockSizeSmall + +three_bytes_emit_remainder_calcBlockSizeSmall: + ADD $0x03, R1, R1 + JMP memmove_long_emit_remainder_calcBlockSizeSmall + +two_bytes_emit_remainder_calcBlockSizeSmall: + ADD $0x02, R1, R1 + CMPW $0x40, R0 + BLO memmove_emit_remainder_calcBlockSizeSmall + JMP memmove_long_emit_remainder_calcBlockSizeSmall + +one_byte_emit_remainder_calcBlockSizeSmall: + ADD $0x01, R1, R1 + +memmove_emit_remainder_calcBlockSizeSmall: + ADD R5, R1, R0 + MOVD R0, R1 + JMP emit_literal_done_emit_remainder_calcBlockSizeSmall + +memmove_long_emit_remainder_calcBlockSizeSmall: + ADD R5, R1, R0 + MOVD R0, R1 + +emit_literal_done_emit_remainder_calcBlockSizeSmall: + MOVD R1, ret+32(FP) + RET + +// func emitLiteral(dst []byte, lit []byte) int +// Requires: SSE2 +TEXT ·emitLiteral(SB), NOSPLIT, $0-56 + MOVD lit_len+32(FP), R2 + MOVD dst_base+0(FP), R0 + MOVD lit_base+24(FP), R1 + TST R2, R2 + BEQ emit_literal_end_standalone_skip + MOVWU R2, R3 + SUB $1, R2, R5 + MOVWU R5, R5 + CMPW $0x3c, R5 + BLO one_byte_standalone + CMPW $0x00000100, R5 + BLO two_bytes_standalone + CMPW $0x00010000, R5 + BLO three_bytes_standalone + CMPW $0x01000000, R5 + BLO four_bytes_standalone + MOVD $0xfc, R16 + MOVB R16, (R0) + MOVW R5, 1(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP memmove_long_standalone + +four_bytes_standalone: + MOVWU R5, R6 + LSRW $0x10, R6, R6 + MOVD $0xf8, R16 + MOVB R16, (R0) + MOVH R5, 1(R0) + MOVB R6, 3(R0) + ADD $0x04, R3, R3 + ADD $0x04, R0, R0 + JMP memmove_long_standalone + +three_bytes_standalone: + MOVD $0xf4, R16 + MOVB R16, (R0) + MOVH R5, 1(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + JMP memmove_long_standalone + +two_bytes_standalone: + MOVD $0xf0, R16 + MOVB R16, (R0) + MOVB R5, 1(R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + CMPW $0x40, R5 + BLO memmove_standalone + JMP memmove_long_standalone + +one_byte_standalone: + LSLW $0x02, R5, R16 + BFI $0, R16, $8, R5 + MOVB R5, (R0) + ADD $0x01, R3, R3 + ADD $0x01, R0, R0 + +memmove_standalone: + // genMemMoveShort + CMP $0x03, R2 + BLO emit_lit_memmove_standalone_memmove_move_1or2 + BEQ emit_lit_memmove_standalone_memmove_move_3 + CMP $0x08, R2 + BLO emit_lit_memmove_standalone_memmove_move_4through7 + CMP $0x10, R2 + BLS emit_lit_memmove_standalone_memmove_move_8through16 + CMP $0x20, R2 + BLS emit_lit_memmove_standalone_memmove_move_17through32 + JMP emit_lit_memmove_standalone_memmove_move_33through64 + +emit_lit_memmove_standalone_memmove_move_1or2: + MOVBU (R1), R16 + BFI $0, R16, $8, R5 + ADD R2, R1, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R1 + MOVB R5, (R0) + ADD R2, R0, R15 + MOVB R1, -1(R15) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_3: + MOVHU (R1), R16 + BFI $0, R16, $16, R5 + MOVBU 2(R1), R16 + BFI $0, R16, $8, R1 + MOVH R5, (R0) + MOVB R1, 2(R0) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_4through7: + MOVWU (R1), R5 + ADD R2, R1, R15 + MOVWU -4(R15), R1 + MOVW R5, (R0) + ADD R2, R0, R15 + MOVW R1, -4(R15) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_8through16: + MOVD (R1), R5 + ADD R2, R1, R15 + MOVD -8(R15), R1 + MOVD R5, (R0) + ADD R2, R0, R15 + MOVD R1, -8(R15) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_17through32: + FMOVQ (R1), F0 + ADD R2, R1, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R0) + ADD R2, R0, R15 + FMOVQ F1, -16(R15) + JMP emit_literal_end_standalone + +emit_lit_memmove_standalone_memmove_move_33through64: + FMOVQ (R1), F0 + FMOVQ 16(R1), F1 + ADD R2, R1, R15 + FMOVQ -32(R15), F2 + ADD R2, R1, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R0) + FMOVQ F1, 16(R0) + ADD R2, R0, R15 + FMOVQ F2, -32(R15) + ADD R2, R0, R15 + FMOVQ F3, -16(R15) + JMP emit_literal_end_standalone + JMP emit_literal_end_standalone + +memmove_long_standalone: + // genMemMoveLong + MOVD R1, R5 + MOVD R0, R6 + MOVD R2, R7 + +emit_lit_memmove_long_standalonelarge_big_loop_back: + FMOVQ (R5), F0 + FMOVQ 16(R5), F1 + FMOVQ F0, (R6) + FMOVQ F1, 16(R6) + ADD $0x20, R5, R5 + ADD $0x20, R6, R6 + SUB $0x20, R7, R7 + CMP $0x20, R7 + BHS emit_lit_memmove_long_standalonelarge_big_loop_back + ADD R2, R1, R15 + FMOVQ -32(R15), F0 + ADD R2, R1, R15 + FMOVQ -16(R15), F1 + ADD R2, R0, R15 + FMOVQ F0, -32(R15) + ADD R2, R0, R15 + FMOVQ F1, -16(R15) + JMP emit_literal_end_standalone + JMP emit_literal_end_standalone + +emit_literal_end_standalone_skip: + MOVD $0, R3 + +emit_literal_end_standalone: + MOVD R3, ret+48(FP) + RET + +// func emitRepeat(dst []byte, offset int, length int) int +TEXT ·emitRepeat(SB), NOSPLIT, $0-48 + MOVD $0, R3 + MOVD dst_base+0(FP), R0 + MOVD offset+24(FP), R1 + MOVD length+32(FP), R2 + + // emitRepeat +emit_repeat_again_standalone: + MOVWU R2, R5 + SUB $4, R2, R2 + MOVWU R2, R2 + CMPW $0x08, R5 + BLS repeat_two_standalone + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_standalone + CMPW $0x00000800, R1 + BLO repeat_two_offset_standalone + +cant_repeat_two_offset_standalone: + CMPW $0x00000104, R2 + BLO repeat_three_standalone + CMPW $0x00010100, R2 + BLO repeat_four_standalone + CMPW $0x0100ffff, R2 + BLO repeat_five_standalone + SUB $16842747, R2, R2 + MOVWU R2, R2 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + ADD $0x05, R3, R3 + JMP emit_repeat_again_standalone + +repeat_five_standalone: + SUB $65536, R2, R2 + MOVWU R2, R2 + MOVWU R2, R1 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ASRW $0x10, R1, R1 + MOVB R1, 4(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_repeat_end + +repeat_four_standalone: + SUB $256, R2, R2 + MOVWU R2, R2 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ADD $0x04, R3, R3 + ADD $0x04, R0, R0 + JMP gen_emit_repeat_end + +repeat_three_standalone: + SUB $4, R2, R2 + MOVWU R2, R2 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R2, 2(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + JMP gen_emit_repeat_end + +repeat_two_standalone: + LSLW $0x02, R2, R2 + ORRW $0x01, R2, R2 + MOVH R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_repeat_end + +repeat_two_offset_standalone: + MOVD $0, R5 + ADD R2<<2, R5, R2 + ADD $1, R2, R2 + MOVWU R2, R2 + MOVB R1, 1(R0) + ASRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R2, R2 + MOVB R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + +gen_emit_repeat_end: + MOVD R3, ret+40(FP) + RET + +// func emitCopy(dst []byte, offset int, length int) int +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + MOVD $0, R3 + MOVD dst_base+0(FP), R0 + MOVD offset+24(FP), R1 + MOVD length+32(FP), R2 + + // emitCopy + CMPW $0x00010000, R1 + BLO two_byte_offset_standalone + CMPW $0x40, R2 + BLS four_bytes_remain_standalone + MOVD $0xff, R16 + MOVB R16, (R0) + MOVW R1, 1(R0) + SUB $64, R2, R2 + MOVWU R2, R2 + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + CMPW $0x04, R2 + BLO four_bytes_remain_standalone + + // emitRepeat +emit_repeat_again_standalone_emit_copy: + MOVWU R2, R5 + SUB $4, R2, R2 + MOVWU R2, R2 + CMPW $0x08, R5 + BLS repeat_two_standalone_emit_copy + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_standalone_emit_copy + CMPW $0x00000800, R1 + BLO repeat_two_offset_standalone_emit_copy + +cant_repeat_two_offset_standalone_emit_copy: + CMPW $0x00000104, R2 + BLO repeat_three_standalone_emit_copy + CMPW $0x00010100, R2 + BLO repeat_four_standalone_emit_copy + CMPW $0x0100ffff, R2 + BLO repeat_five_standalone_emit_copy + SUB $16842747, R2, R2 + MOVWU R2, R2 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + ADD $0x05, R3, R3 + JMP emit_repeat_again_standalone_emit_copy + +repeat_five_standalone_emit_copy: + SUB $65536, R2, R2 + MOVWU R2, R2 + MOVWU R2, R1 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ASRW $0x10, R1, R1 + MOVB R1, 4(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy: + SUB $256, R2, R2 + MOVWU R2, R2 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ADD $0x04, R3, R3 + ADD $0x04, R0, R0 + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy: + SUB $4, R2, R2 + MOVWU R2, R2 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R2, 2(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy: + LSLW $0x02, R2, R2 + ORRW $0x01, R2, R2 + MOVH R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy: + MOVD $0, R5 + ADD R2<<2, R5, R2 + ADD $1, R2, R2 + MOVWU R2, R2 + MOVB R1, 1(R0) + ASRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R2, R2 + MOVB R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +four_bytes_remain_standalone: + TSTW R2, R2 + BEQ gen_emit_copy_end + MOVD $0, R5 + ADD R2<<2, R5, R2 + SUB $1, R2, R2 + MOVWU R2, R2 + MOVB R2, (R0) + MOVW R1, 1(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_copy_end + +two_byte_offset_standalone: + CMPW $0x40, R2 + BLS two_byte_offset_short_standalone + CMPW $0x00000800, R1 + BHS long_offset_short_standalone + MOVD $0x00000001, R5 + ADD $16, R5, R5 + MOVWU R5, R5 + MOVB R1, 1(R0) + MOVWU R1, R6 + LSRW $0x08, R6, R6 + LSLW $0x05, R6, R6 + ORRW R6, R5, R5 + MOVB R5, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + SUBW $0x08, R2, R2 + + // emitRepeat + SUB $4, R2, R2 + MOVWU R2, R2 + JMP cant_repeat_two_offset_standalone_emit_copy_short_2b + +emit_repeat_again_standalone_emit_copy_short_2b: + MOVWU R2, R5 + SUB $4, R2, R2 + MOVWU R2, R2 + CMPW $0x08, R5 + BLS repeat_two_standalone_emit_copy_short_2b + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_standalone_emit_copy_short_2b + CMPW $0x00000800, R1 + BLO repeat_two_offset_standalone_emit_copy_short_2b + +cant_repeat_two_offset_standalone_emit_copy_short_2b: + CMPW $0x00000104, R2 + BLO repeat_three_standalone_emit_copy_short_2b + CMPW $0x00010100, R2 + BLO repeat_four_standalone_emit_copy_short_2b + CMPW $0x0100ffff, R2 + BLO repeat_five_standalone_emit_copy_short_2b + SUB $16842747, R2, R2 + MOVWU R2, R2 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + ADD $0x05, R3, R3 + JMP emit_repeat_again_standalone_emit_copy_short_2b + +repeat_five_standalone_emit_copy_short_2b: + SUB $65536, R2, R2 + MOVWU R2, R2 + MOVWU R2, R1 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ASRW $0x10, R1, R1 + MOVB R1, 4(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy_short_2b: + SUB $256, R2, R2 + MOVWU R2, R2 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ADD $0x04, R3, R3 + ADD $0x04, R0, R0 + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy_short_2b: + SUB $4, R2, R2 + MOVWU R2, R2 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R2, 2(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy_short_2b: + LSLW $0x02, R2, R2 + ORRW $0x01, R2, R2 + MOVH R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy_short_2b: + MOVD $0, R5 + ADD R2<<2, R5, R2 + ADD $1, R2, R2 + MOVWU R2, R2 + MOVB R1, 1(R0) + ASRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R2, R2 + MOVB R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +long_offset_short_standalone: + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R1, 1(R0) + SUB $60, R2, R2 + MOVWU R2, R2 + ADD $0x03, R0, R0 + ADD $0x03, R3, R3 + + // emitRepeat +emit_repeat_again_standalone_emit_copy_short: + MOVWU R2, R5 + SUB $4, R2, R2 + MOVWU R2, R2 + CMPW $0x08, R5 + BLS repeat_two_standalone_emit_copy_short + CMPW $0x0c, R5 + BHS cant_repeat_two_offset_standalone_emit_copy_short + CMPW $0x00000800, R1 + BLO repeat_two_offset_standalone_emit_copy_short + +cant_repeat_two_offset_standalone_emit_copy_short: + CMPW $0x00000104, R2 + BLO repeat_three_standalone_emit_copy_short + CMPW $0x00010100, R2 + BLO repeat_four_standalone_emit_copy_short + CMPW $0x0100ffff, R2 + BLO repeat_five_standalone_emit_copy_short + SUB $16842747, R2, R2 + MOVWU R2, R2 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + ADD $0x05, R3, R3 + JMP emit_repeat_again_standalone_emit_copy_short + +repeat_five_standalone_emit_copy_short: + SUB $65536, R2, R2 + MOVWU R2, R2 + MOVWU R2, R1 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ASRW $0x10, R1, R1 + MOVB R1, 4(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_copy_end + +repeat_four_standalone_emit_copy_short: + SUB $256, R2, R2 + MOVWU R2, R2 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R2, 2(R0) + ADD $0x04, R3, R3 + ADD $0x04, R0, R0 + JMP gen_emit_copy_end + +repeat_three_standalone_emit_copy_short: + SUB $4, R2, R2 + MOVWU R2, R2 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R2, 2(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + JMP gen_emit_copy_end + +repeat_two_standalone_emit_copy_short: + LSLW $0x02, R2, R2 + ORRW $0x01, R2, R2 + MOVH R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +repeat_two_offset_standalone_emit_copy_short: + MOVD $0, R5 + ADD R2<<2, R5, R2 + ADD $1, R2, R2 + MOVWU R2, R2 + MOVB R1, 1(R0) + ASRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R2, R2 + MOVB R2, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +two_byte_offset_short_standalone: + MOVWU R2, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R2 + BHS emit_copy_three_standalone + CMPW $0x00000800, R1 + BHS emit_copy_three_standalone + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R1, 1(R0) + LSRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R5, R5 + MOVB R5, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end + +emit_copy_three_standalone: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R0) + MOVH R1, 1(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + +gen_emit_copy_end: + MOVD R3, ret+40(FP) + RET + +// func emitCopyNoRepeat(dst []byte, offset int, length int) int +TEXT ·emitCopyNoRepeat(SB), NOSPLIT, $0-48 + MOVD $0, R3 + MOVD dst_base+0(FP), R0 + MOVD offset+24(FP), R1 + MOVD length+32(FP), R2 + + // emitCopy + CMPW $0x00010000, R1 + BLO two_byte_offset_standalone_snappy + +four_bytes_loop_back_standalone_snappy: + CMPW $0x40, R2 + BLS four_bytes_remain_standalone_snappy + MOVD $0xff, R16 + MOVB R16, (R0) + MOVW R1, 1(R0) + SUB $64, R2, R2 + MOVWU R2, R2 + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + CMPW $0x04, R2 + BLO four_bytes_remain_standalone_snappy + JMP four_bytes_loop_back_standalone_snappy + +four_bytes_remain_standalone_snappy: + TSTW R2, R2 + BEQ gen_emit_copy_end_snappy + MOVD $0, R5 + ADD R2<<2, R5, R2 + SUB $1, R2, R2 + MOVWU R2, R2 + MOVB R2, (R0) + MOVW R1, 1(R0) + ADD $0x05, R3, R3 + ADD $0x05, R0, R0 + JMP gen_emit_copy_end_snappy + +two_byte_offset_standalone_snappy: + CMPW $0x40, R2 + BLS two_byte_offset_short_standalone_snappy + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R1, 1(R0) + SUB $60, R2, R2 + MOVWU R2, R2 + ADD $0x03, R0, R0 + ADD $0x03, R3, R3 + JMP two_byte_offset_standalone_snappy + +two_byte_offset_short_standalone_snappy: + MOVWU R2, R5 + LSLW $0x02, R5, R5 + CMPW $0x0c, R2 + BHS emit_copy_three_standalone_snappy + CMPW $0x00000800, R1 + BHS emit_copy_three_standalone_snappy + SUB $15, R5, R5 + MOVWU R5, R5 + MOVB R1, 1(R0) + LSRW $0x08, R1, R1 + LSLW $0x05, R1, R1 + ORRW R1, R5, R5 + MOVB R5, (R0) + ADD $0x02, R3, R3 + ADD $0x02, R0, R0 + JMP gen_emit_copy_end_snappy + +emit_copy_three_standalone_snappy: + SUB $2, R5, R5 + MOVWU R5, R5 + MOVB R5, (R0) + MOVH R1, 1(R0) + ADD $0x03, R3, R3 + ADD $0x03, R0, R0 + +gen_emit_copy_end_snappy: + MOVD R3, ret+40(FP) + RET + +// func matchLen(a []byte, b []byte) int +// Requires: BMI +TEXT ·matchLen(SB), NOSPLIT, $0-56 + MOVD a_base+0(FP), R0 + MOVD b_base+24(FP), R1 + MOVD a_len+8(FP), R2 + + // matchLen + MOVD $0, R5 + +matchlen_loopback_16_standalone: + CMPW $0x10, R2 + BLO matchlen_match8_standalone + MOVD (R0)(R5), R3 + ADD R5, R0, R15 + MOVD 8(R15), R6 + MOVD (R1)(R5), R16 + EOR R16, R3, R3 + TST R3, R3 + BNE matchlen_bsf_8_standalone + ADD R5, R1, R15 + MOVD 8(R15), R16 + EOR R16, R6, R6 + TST R6, R6 + BNE matchlen_bsf_16standalone + SUB $16, R2, R2 + MOVWU R2, R2 + ADD $16, R5, R5 + MOVWU R5, R5 + JMP matchlen_loopback_16_standalone + +matchlen_bsf_16standalone: + RBIT R6, R6 + CLZ R6, R6 + ASR $0x03, R6, R6 + ADD R6, R5, R5 + ADD $8, R5, R5 + MOVWU R5, R5 + JMP gen_match_len_end + +matchlen_match8_standalone: + CMPW $0x08, R2 + BLO matchlen_match4_standalone + MOVD (R0)(R5), R3 + MOVD (R1)(R5), R16 + EOR R16, R3, R3 + TST R3, R3 + BNE matchlen_bsf_8_standalone + SUB $8, R2, R2 + MOVWU R2, R2 + ADD $8, R5, R5 + MOVWU R5, R5 + JMP matchlen_match4_standalone + +matchlen_bsf_8_standalone: + RBIT R3, R3 + CLZ R3, R3 + ASR $0x03, R3, R3 + ADD R3, R5, R5 + MOVWU R5, R5 + JMP gen_match_len_end + +matchlen_match4_standalone: + CMPW $0x04, R2 + BLO matchlen_match2_standalone + MOVWU (R0)(R5), R3 + MOVWU (R1)(R5), R16 + CMPW R3, R16 + BNE matchlen_match2_standalone + SUB $4, R2, R2 + MOVWU R2, R2 + ADD $4, R5, R5 + MOVWU R5, R5 + +matchlen_match2_standalone: + CMPW $0x01, R2 + BEQ matchlen_match1_standalone + BLO gen_match_len_end + MOVHU (R0)(R5), R16 + BFI $0, R16, $16, R3 + ADD R5, R1, R15 + MOVHU (R15), R15 + AND $0xffff, R3, R16 + CMP R16, R15 + BNE matchlen_match1_standalone + ADD $2, R5, R5 + MOVWU R5, R5 + SUBSW $0x02, R2, R2 + BEQ gen_match_len_end + +matchlen_match1_standalone: + MOVBU (R0)(R5), R16 + BFI $0, R16, $8, R3 + ADD R5, R1, R15 + MOVBU (R15), R15 + AND $0xff, R3, R16 + CMP R16, R15 + BNE gen_match_len_end + ADD $1, R5, R5 + MOVWU R5, R5 + +gen_match_len_end: + MOVD R5, ret+48(FP) + RET + +// func cvtLZ4BlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4BlockAsm(SB), NOSPLIT, $0-64 + MOVD $0, R5 + MOVD dst_base+0(FP), R0 + MOVD dst_len+8(FP), R1 + MOVD src_base+24(FP), R2 + MOVD src_len+32(FP), R3 + ADD R3, R2, R3 + ADD R1, R0, R1 + SUB $8, R1, R1 + MOVD $0, R6 + +lz4_s2_loop: + CMP R3, R2 + BHS lz4_s2_corrupt + CMP R1, R0 + BHS lz4_s2_dstfull + MOVBU (R2), R7 + MOVD R7, R8 + MOVD R7, R9 + LSR $0x04, R8, R8 + AND $0x0f, R9, R9 + CMP $0xf0, R7 + BLO lz4_s2_ll_end + +lz4_s2_ll_loop: + ADD $1, R2, R2 + CMP R3, R2 + BHS lz4_s2_corrupt + MOVBU (R2), R7 + ADD R7, R8, R8 + CMP $0xff, R7 + BEQ lz4_s2_ll_loop + +lz4_s2_ll_end: + ADD R8, R2, R7 + ADD $0x04, R9, R9 + CMP R3, R7 + BHS lz4_s2_corrupt + ADD $1, R2, R2 + ADD $1, R7, R7 + TST R8, R8 + BEQ lz4_s2_lits_done + ADD R8, R0, R10 + CMP R1, R10 + BHS lz4_s2_dstfull + ADD R8, R5, R5 + SUB $1, R8, R10 + MOVWU R10, R10 + CMPW $0x3c, R10 + BLO one_byte_lz4_s2 + CMPW $0x00000100, R10 + BLO two_bytes_lz4_s2 + CMPW $0x00010000, R10 + BLO three_bytes_lz4_s2 + CMPW $0x01000000, R10 + BLO four_bytes_lz4_s2 + MOVD $0xfc, R16 + MOVB R16, (R0) + MOVW R10, 1(R0) + ADD $0x05, R0, R0 + JMP memmove_long_lz4_s2 + +four_bytes_lz4_s2: + MOVWU R10, R11 + LSRW $0x10, R11, R11 + MOVD $0xf8, R16 + MOVB R16, (R0) + MOVH R10, 1(R0) + MOVB R11, 3(R0) + ADD $0x04, R0, R0 + JMP memmove_long_lz4_s2 + +three_bytes_lz4_s2: + MOVD $0xf4, R16 + MOVB R16, (R0) + MOVH R10, 1(R0) + ADD $0x03, R0, R0 + JMP memmove_long_lz4_s2 + +two_bytes_lz4_s2: + MOVD $0xf0, R16 + MOVB R16, (R0) + MOVB R10, 1(R0) + ADD $0x02, R0, R0 + CMPW $0x40, R10 + BLO memmove_lz4_s2 + JMP memmove_long_lz4_s2 + +one_byte_lz4_s2: + LSLW $0x02, R10, R16 + BFI $0, R16, $8, R10 + MOVB R10, (R0) + ADD $0x01, R0, R0 + +memmove_lz4_s2: + ADD R8, R0, R10 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_lz4_s2_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_lz4_s2_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_lz4_s2_memmove_move_17through32 + JMP emit_lit_memmove_lz4_s2_memmove_move_33through64 + +emit_lit_memmove_lz4_s2_memmove_move_8: + MOVD (R2), R11 + MOVD R11, (R0) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_8through16: + MOVD (R2), R11 + ADD R8, R2, R15 + MOVD -8(R15), R2 + MOVD R11, (R0) + ADD R8, R0, R15 + MOVD R2, -8(R15) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_17through32: + FMOVQ (R2), F0 + ADD R8, R2, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R0) + ADD R8, R0, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_lz4_s2 + +emit_lit_memmove_lz4_s2_memmove_move_33through64: + FMOVQ (R2), F0 + FMOVQ 16(R2), F1 + ADD R8, R2, R15 + FMOVQ -32(R15), F2 + ADD R8, R2, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R0) + FMOVQ F1, 16(R0) + ADD R8, R0, R15 + FMOVQ F2, -32(R15) + ADD R8, R0, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_lz4_s2: + MOVD R10, R0 + JMP lz4_s2_lits_emit_done + +memmove_long_lz4_s2: + ADD R8, R0, R10 + + // genMemMoveLong + MOVD R2, R11 + MOVD R0, R12 + MOVD R8, R13 + +emit_lit_memmove_long_lz4_s2large_big_loop_back: + FMOVQ (R11), F0 + FMOVQ 16(R11), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R11, R11 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_lz4_s2large_big_loop_back + ADD R8, R2, R15 + FMOVQ -32(R15), F0 + ADD R8, R2, R15 + FMOVQ -16(R15), F1 + ADD R8, R0, R15 + FMOVQ F0, -32(R15) + ADD R8, R0, R15 + FMOVQ F1, -16(R15) + MOVD R10, R0 + +lz4_s2_lits_emit_done: + MOVD R7, R2 + +lz4_s2_lits_done: + CMP R3, R2 + BNE lz4_s2_match + CMP $0x04, R9 + BEQ lz4_s2_done + JMP lz4_s2_corrupt + +lz4_s2_match: + ADD $2, R2, R7 + CMP R3, R7 + BHS lz4_s2_corrupt + MOVHU (R2), R8 + MOVD R7, R2 + TST R8, R8 + BEQ lz4_s2_corrupt + CMP R5, R8 + BHI lz4_s2_corrupt + CMP $0x13, R9 + BNE lz4_s2_ml_done + +lz4_s2_ml_loop: + MOVBU (R2), R7 + ADD $1, R2, R2 + ADD R7, R9, R9 + CMP R3, R2 + BHS lz4_s2_corrupt + CMP $0xff, R7 + BEQ lz4_s2_ml_loop + +lz4_s2_ml_done: + ADD R9, R5, R5 + CMP R6, R8 + BNE lz4_s2_docopy + + // emitRepeat +emit_repeat_again_lz4_s2: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2 + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2 + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2 + +cant_repeat_two_offset_lz4_s2: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2 + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2 + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2 + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2 + +repeat_five_lz4_s2: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4_s2_loop + +repeat_four_lz4_s2: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4_s2_loop + +repeat_three_lz4_s2: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4_s2_loop + +repeat_two_lz4_s2: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +lz4_s2_docopy: + MOVD R8, R6 + + // emitCopy + CMPW $0x40, R9 + BLS two_byte_offset_short_lz4_s2 + CMPW $0x00000800, R8 + BHS long_offset_short_lz4_s2 + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R8, 1(R0) + MOVWU R8, R10 + LSRW $0x08, R10, R10 + LSLW $0x05, R10, R10 + ORRW R10, R7, R7 + MOVB R7, (R0) + ADD $0x02, R0, R0 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + +emit_repeat_again_lz4_s2_emit_copy_short_2b: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2_emit_copy_short_2b + +cant_repeat_two_offset_lz4_s2_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2_emit_copy_short_2b + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2_emit_copy_short_2b + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2_emit_copy_short_2b + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2_emit_copy_short_2b + +repeat_five_lz4_s2_emit_copy_short_2b: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4_s2_loop + +repeat_four_lz4_s2_emit_copy_short_2b: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4_s2_loop + +repeat_three_lz4_s2_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4_s2_loop + +repeat_two_lz4_s2_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short_2b: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +long_offset_short_lz4_s2: + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R8, 1(R0) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R0, R0 + + // emitRepeat +emit_repeat_again_lz4_s2_emit_copy_short: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2_emit_copy_short + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2_emit_copy_short + +cant_repeat_two_offset_lz4_s2_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2_emit_copy_short + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2_emit_copy_short + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2_emit_copy_short + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2_emit_copy_short + +repeat_five_lz4_s2_emit_copy_short: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4_s2_loop + +repeat_four_lz4_s2_emit_copy_short: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4_s2_loop + +repeat_three_lz4_s2_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4_s2_loop + +repeat_two_lz4_s2_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +two_byte_offset_short_lz4_s2: + MOVWU R9, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R9 + BHS emit_copy_three_lz4_s2 + CMPW $0x00000800, R8 + BHS emit_copy_three_lz4_s2 + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R8, 1(R0) + LSRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R7, R7 + MOVB R7, (R0) + ADD $0x02, R0, R0 + JMP lz4_s2_loop + +emit_copy_three_lz4_s2: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R0) + MOVH R8, 1(R0) + ADD $0x03, R0, R0 + JMP lz4_s2_loop + +lz4_s2_done: + MOVD dst_base+0(FP), R1 + SUB R1, R0, R0 + MOVD R5, uncompressed+48(FP) + MOVD R0, dstUsed+56(FP) + RET + +lz4_s2_corrupt: + MOVD $0, R0 + SUB $1, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +lz4_s2_dstfull: + MOVD $0, R0 + SUB $2, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +// func cvtLZ4sBlockAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4sBlockAsm(SB), NOSPLIT, $0-64 + MOVD $0, R5 + MOVD dst_base+0(FP), R0 + MOVD dst_len+8(FP), R1 + MOVD src_base+24(FP), R2 + MOVD src_len+32(FP), R3 + ADD R3, R2, R3 + ADD R1, R0, R1 + SUB $8, R1, R1 + MOVD $0, R6 + +lz4s_s2_loop: + CMP R3, R2 + BHS lz4s_s2_corrupt + CMP R1, R0 + BHS lz4s_s2_dstfull + MOVBU (R2), R7 + MOVD R7, R8 + MOVD R7, R9 + LSR $0x04, R8, R8 + AND $0x0f, R9, R9 + CMP $0xf0, R7 + BLO lz4s_s2_ll_end + +lz4s_s2_ll_loop: + ADD $1, R2, R2 + CMP R3, R2 + BHS lz4s_s2_corrupt + MOVBU (R2), R7 + ADD R7, R8, R8 + CMP $0xff, R7 + BEQ lz4s_s2_ll_loop + +lz4s_s2_ll_end: + ADD R8, R2, R7 + ADD $0x03, R9, R9 + CMP R3, R7 + BHS lz4s_s2_corrupt + ADD $1, R2, R2 + ADD $1, R7, R7 + TST R8, R8 + BEQ lz4s_s2_lits_done + ADD R8, R0, R10 + CMP R1, R10 + BHS lz4s_s2_dstfull + ADD R8, R5, R5 + SUB $1, R8, R10 + MOVWU R10, R10 + CMPW $0x3c, R10 + BLO one_byte_lz4s_s2 + CMPW $0x00000100, R10 + BLO two_bytes_lz4s_s2 + CMPW $0x00010000, R10 + BLO three_bytes_lz4s_s2 + CMPW $0x01000000, R10 + BLO four_bytes_lz4s_s2 + MOVD $0xfc, R16 + MOVB R16, (R0) + MOVW R10, 1(R0) + ADD $0x05, R0, R0 + JMP memmove_long_lz4s_s2 + +four_bytes_lz4s_s2: + MOVWU R10, R11 + LSRW $0x10, R11, R11 + MOVD $0xf8, R16 + MOVB R16, (R0) + MOVH R10, 1(R0) + MOVB R11, 3(R0) + ADD $0x04, R0, R0 + JMP memmove_long_lz4s_s2 + +three_bytes_lz4s_s2: + MOVD $0xf4, R16 + MOVB R16, (R0) + MOVH R10, 1(R0) + ADD $0x03, R0, R0 + JMP memmove_long_lz4s_s2 + +two_bytes_lz4s_s2: + MOVD $0xf0, R16 + MOVB R16, (R0) + MOVB R10, 1(R0) + ADD $0x02, R0, R0 + CMPW $0x40, R10 + BLO memmove_lz4s_s2 + JMP memmove_long_lz4s_s2 + +one_byte_lz4s_s2: + LSLW $0x02, R10, R16 + BFI $0, R16, $8, R10 + MOVB R10, (R0) + ADD $0x01, R0, R0 + +memmove_lz4s_s2: + ADD R8, R0, R10 + + // genMemMoveShort + CMP $0x08, R8 + BLS emit_lit_memmove_lz4s_s2_memmove_move_8 + CMP $0x10, R8 + BLS emit_lit_memmove_lz4s_s2_memmove_move_8through16 + CMP $0x20, R8 + BLS emit_lit_memmove_lz4s_s2_memmove_move_17through32 + JMP emit_lit_memmove_lz4s_s2_memmove_move_33through64 + +emit_lit_memmove_lz4s_s2_memmove_move_8: + MOVD (R2), R11 + MOVD R11, (R0) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_8through16: + MOVD (R2), R11 + ADD R8, R2, R15 + MOVD -8(R15), R2 + MOVD R11, (R0) + ADD R8, R0, R15 + MOVD R2, -8(R15) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_17through32: + FMOVQ (R2), F0 + ADD R8, R2, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R0) + ADD R8, R0, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_lz4s_s2 + +emit_lit_memmove_lz4s_s2_memmove_move_33through64: + FMOVQ (R2), F0 + FMOVQ 16(R2), F1 + ADD R8, R2, R15 + FMOVQ -32(R15), F2 + ADD R8, R2, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R0) + FMOVQ F1, 16(R0) + ADD R8, R0, R15 + FMOVQ F2, -32(R15) + ADD R8, R0, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_lz4s_s2: + MOVD R10, R0 + JMP lz4s_s2_lits_emit_done + +memmove_long_lz4s_s2: + ADD R8, R0, R10 + + // genMemMoveLong + MOVD R2, R11 + MOVD R0, R12 + MOVD R8, R13 + +emit_lit_memmove_long_lz4s_s2large_big_loop_back: + FMOVQ (R11), F0 + FMOVQ 16(R11), F1 + FMOVQ F0, (R12) + FMOVQ F1, 16(R12) + ADD $0x20, R11, R11 + ADD $0x20, R12, R12 + SUB $0x20, R13, R13 + CMP $0x20, R13 + BHS emit_lit_memmove_long_lz4s_s2large_big_loop_back + ADD R8, R2, R15 + FMOVQ -32(R15), F0 + ADD R8, R2, R15 + FMOVQ -16(R15), F1 + ADD R8, R0, R15 + FMOVQ F0, -32(R15) + ADD R8, R0, R15 + FMOVQ F1, -16(R15) + MOVD R10, R0 + +lz4s_s2_lits_emit_done: + MOVD R7, R2 + +lz4s_s2_lits_done: + CMP R3, R2 + BNE lz4s_s2_match + CMP $0x03, R9 + BEQ lz4s_s2_done + JMP lz4s_s2_corrupt + +lz4s_s2_match: + CMP $0x03, R9 + BEQ lz4s_s2_loop + ADD $2, R2, R7 + CMP R3, R7 + BHS lz4s_s2_corrupt + MOVHU (R2), R8 + MOVD R7, R2 + TST R8, R8 + BEQ lz4s_s2_corrupt + CMP R5, R8 + BHI lz4s_s2_corrupt + CMP $0x12, R9 + BNE lz4s_s2_ml_done + +lz4s_s2_ml_loop: + MOVBU (R2), R7 + ADD $1, R2, R2 + ADD R7, R9, R9 + CMP R3, R2 + BHS lz4s_s2_corrupt + CMP $0xff, R7 + BEQ lz4s_s2_ml_loop + +lz4s_s2_ml_done: + ADD R9, R5, R5 + CMP R6, R8 + BNE lz4s_s2_docopy + + // emitRepeat +emit_repeat_again_lz4_s2: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2 + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2 + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2 + +cant_repeat_two_offset_lz4_s2: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2 + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2 + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2 + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2 + +repeat_five_lz4_s2: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4s_s2_loop + +repeat_four_lz4_s2: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4s_s2_loop + +repeat_three_lz4_s2: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4s_s2_loop + +repeat_two_lz4_s2: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +lz4s_s2_docopy: + MOVD R8, R6 + + // emitCopy + CMPW $0x40, R9 + BLS two_byte_offset_short_lz4_s2 + CMPW $0x00000800, R8 + BHS long_offset_short_lz4_s2 + MOVD $0x00000001, R7 + ADD $16, R7, R7 + MOVWU R7, R7 + MOVB R8, 1(R0) + MOVWU R8, R10 + LSRW $0x08, R10, R10 + LSLW $0x05, R10, R10 + ORRW R10, R7, R7 + MOVB R7, (R0) + ADD $0x02, R0, R0 + SUBW $0x08, R9, R9 + + // emitRepeat + SUB $4, R9, R9 + MOVWU R9, R9 + JMP cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + +emit_repeat_again_lz4_s2_emit_copy_short_2b: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2_emit_copy_short_2b + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2_emit_copy_short_2b + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2_emit_copy_short_2b + +cant_repeat_two_offset_lz4_s2_emit_copy_short_2b: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2_emit_copy_short_2b + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2_emit_copy_short_2b + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2_emit_copy_short_2b + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2_emit_copy_short_2b + +repeat_five_lz4_s2_emit_copy_short_2b: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4s_s2_loop + +repeat_four_lz4_s2_emit_copy_short_2b: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4s_s2_loop + +repeat_three_lz4_s2_emit_copy_short_2b: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4s_s2_loop + +repeat_two_lz4_s2_emit_copy_short_2b: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short_2b: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +long_offset_short_lz4_s2: + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R8, 1(R0) + SUB $60, R9, R9 + MOVWU R9, R9 + ADD $0x03, R0, R0 + + // emitRepeat +emit_repeat_again_lz4_s2_emit_copy_short: + MOVWU R9, R7 + SUB $4, R9, R9 + MOVWU R9, R9 + CMPW $0x08, R7 + BLS repeat_two_lz4_s2_emit_copy_short + CMPW $0x0c, R7 + BHS cant_repeat_two_offset_lz4_s2_emit_copy_short + CMPW $0x00000800, R8 + BLO repeat_two_offset_lz4_s2_emit_copy_short + +cant_repeat_two_offset_lz4_s2_emit_copy_short: + CMPW $0x00000104, R9 + BLO repeat_three_lz4_s2_emit_copy_short + CMPW $0x00010100, R9 + BLO repeat_four_lz4_s2_emit_copy_short + CMPW $0x0100ffff, R9 + BLO repeat_five_lz4_s2_emit_copy_short + SUB $16842747, R9, R9 + MOVWU R9, R9 + MOVD $0xfffb001d, R16 + MOVW R16, (R0) + MOVD $0xff, R16 + MOVB R16, 4(R0) + ADD $0x05, R0, R0 + JMP emit_repeat_again_lz4_s2_emit_copy_short + +repeat_five_lz4_s2_emit_copy_short: + SUB $65536, R9, R9 + MOVWU R9, R9 + MOVWU R9, R8 + MOVD $0x001d, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ASRW $0x10, R8, R8 + MOVB R8, 4(R0) + ADD $0x05, R0, R0 + JMP lz4s_s2_loop + +repeat_four_lz4_s2_emit_copy_short: + SUB $256, R9, R9 + MOVWU R9, R9 + MOVD $0x0019, R16 + MOVH R16, (R0) + MOVH R9, 2(R0) + ADD $0x04, R0, R0 + JMP lz4s_s2_loop + +repeat_three_lz4_s2_emit_copy_short: + SUB $4, R9, R9 + MOVWU R9, R9 + MOVD $0x0015, R16 + MOVH R16, (R0) + MOVB R9, 2(R0) + ADD $0x03, R0, R0 + JMP lz4s_s2_loop + +repeat_two_lz4_s2_emit_copy_short: + LSLW $0x02, R9, R9 + ORRW $0x01, R9, R9 + MOVH R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +repeat_two_offset_lz4_s2_emit_copy_short: + MOVD $0, R7 + ADD R9<<2, R7, R9 + ADD $1, R9, R9 + MOVWU R9, R9 + MOVB R8, 1(R0) + ASRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R9, R9 + MOVB R9, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +two_byte_offset_short_lz4_s2: + MOVWU R9, R7 + LSLW $0x02, R7, R7 + CMPW $0x0c, R9 + BHS emit_copy_three_lz4_s2 + CMPW $0x00000800, R8 + BHS emit_copy_three_lz4_s2 + SUB $15, R7, R7 + MOVWU R7, R7 + MOVB R8, 1(R0) + LSRW $0x08, R8, R8 + LSLW $0x05, R8, R8 + ORRW R8, R7, R7 + MOVB R7, (R0) + ADD $0x02, R0, R0 + JMP lz4s_s2_loop + +emit_copy_three_lz4_s2: + SUB $2, R7, R7 + MOVWU R7, R7 + MOVB R7, (R0) + MOVH R8, 1(R0) + ADD $0x03, R0, R0 + JMP lz4s_s2_loop + +lz4s_s2_done: + MOVD dst_base+0(FP), R1 + SUB R1, R0, R0 + MOVD R5, uncompressed+48(FP) + MOVD R0, dstUsed+56(FP) + RET + +lz4s_s2_corrupt: + MOVD $0, R0 + SUB $1, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +lz4s_s2_dstfull: + MOVD $0, R0 + SUB $2, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +// func cvtLZ4BlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4BlockSnappyAsm(SB), NOSPLIT, $0-64 + MOVD $0, R5 + MOVD dst_base+0(FP), R0 + MOVD dst_len+8(FP), R1 + MOVD src_base+24(FP), R2 + MOVD src_len+32(FP), R3 + ADD R3, R2, R3 + ADD R1, R0, R1 + SUB $8, R1, R1 + +lz4_snappy_loop: + CMP R3, R2 + BHS lz4_snappy_corrupt + CMP R1, R0 + BHS lz4_snappy_dstfull + MOVBU (R2), R6 + MOVD R6, R7 + MOVD R6, R8 + LSR $0x04, R7, R7 + AND $0x0f, R8, R8 + CMP $0xf0, R6 + BLO lz4_snappy_ll_end + +lz4_snappy_ll_loop: + ADD $1, R2, R2 + CMP R3, R2 + BHS lz4_snappy_corrupt + MOVBU (R2), R6 + ADD R6, R7, R7 + CMP $0xff, R6 + BEQ lz4_snappy_ll_loop + +lz4_snappy_ll_end: + ADD R7, R2, R6 + ADD $0x04, R8, R8 + CMP R3, R6 + BHS lz4_snappy_corrupt + ADD $1, R2, R2 + ADD $1, R6, R6 + TST R7, R7 + BEQ lz4_snappy_lits_done + ADD R7, R0, R9 + CMP R1, R9 + BHS lz4_snappy_dstfull + ADD R7, R5, R5 + SUB $1, R7, R9 + MOVWU R9, R9 + CMPW $0x3c, R9 + BLO one_byte_lz4_snappy + CMPW $0x00000100, R9 + BLO two_bytes_lz4_snappy + CMPW $0x00010000, R9 + BLO three_bytes_lz4_snappy + CMPW $0x01000000, R9 + BLO four_bytes_lz4_snappy + MOVD $0xfc, R16 + MOVB R16, (R0) + MOVW R9, 1(R0) + ADD $0x05, R0, R0 + JMP memmove_long_lz4_snappy + +four_bytes_lz4_snappy: + MOVWU R9, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R0) + MOVH R9, 1(R0) + MOVB R10, 3(R0) + ADD $0x04, R0, R0 + JMP memmove_long_lz4_snappy + +three_bytes_lz4_snappy: + MOVD $0xf4, R16 + MOVB R16, (R0) + MOVH R9, 1(R0) + ADD $0x03, R0, R0 + JMP memmove_long_lz4_snappy + +two_bytes_lz4_snappy: + MOVD $0xf0, R16 + MOVB R16, (R0) + MOVB R9, 1(R0) + ADD $0x02, R0, R0 + CMPW $0x40, R9 + BLO memmove_lz4_snappy + JMP memmove_long_lz4_snappy + +one_byte_lz4_snappy: + LSLW $0x02, R9, R16 + BFI $0, R16, $8, R9 + MOVB R9, (R0) + ADD $0x01, R0, R0 + +memmove_lz4_snappy: + ADD R7, R0, R9 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_lz4_snappy_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_lz4_snappy_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_lz4_snappy_memmove_move_17through32 + JMP emit_lit_memmove_lz4_snappy_memmove_move_33through64 + +emit_lit_memmove_lz4_snappy_memmove_move_8: + MOVD (R2), R10 + MOVD R10, (R0) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_8through16: + MOVD (R2), R10 + ADD R7, R2, R15 + MOVD -8(R15), R2 + MOVD R10, (R0) + ADD R7, R0, R15 + MOVD R2, -8(R15) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_17through32: + FMOVQ (R2), F0 + ADD R7, R2, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R0) + ADD R7, R0, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_lz4_snappy + +emit_lit_memmove_lz4_snappy_memmove_move_33through64: + FMOVQ (R2), F0 + FMOVQ 16(R2), F1 + ADD R7, R2, R15 + FMOVQ -32(R15), F2 + ADD R7, R2, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R0) + FMOVQ F1, 16(R0) + ADD R7, R0, R15 + FMOVQ F2, -32(R15) + ADD R7, R0, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_lz4_snappy: + MOVD R9, R0 + JMP lz4_snappy_lits_emit_done + +memmove_long_lz4_snappy: + ADD R7, R0, R9 + + // genMemMoveLong + MOVD R2, R10 + MOVD R0, R11 + MOVD R7, R12 + +emit_lit_memmove_long_lz4_snappylarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_lz4_snappylarge_big_loop_back + ADD R7, R2, R15 + FMOVQ -32(R15), F0 + ADD R7, R2, R15 + FMOVQ -16(R15), F1 + ADD R7, R0, R15 + FMOVQ F0, -32(R15) + ADD R7, R0, R15 + FMOVQ F1, -16(R15) + MOVD R9, R0 + +lz4_snappy_lits_emit_done: + MOVD R6, R2 + +lz4_snappy_lits_done: + CMP R3, R2 + BNE lz4_snappy_match + CMP $0x04, R8 + BEQ lz4_snappy_done + JMP lz4_snappy_corrupt + +lz4_snappy_match: + ADD $2, R2, R6 + CMP R3, R6 + BHS lz4_snappy_corrupt + MOVHU (R2), R7 + MOVD R6, R2 + TST R7, R7 + BEQ lz4_snappy_corrupt + CMP R5, R7 + BHI lz4_snappy_corrupt + CMP $0x13, R8 + BNE lz4_snappy_ml_done + +lz4_snappy_ml_loop: + MOVBU (R2), R6 + ADD $1, R2, R2 + ADD R6, R8, R8 + CMP R3, R2 + BHS lz4_snappy_corrupt + CMP $0xff, R6 + BEQ lz4_snappy_ml_loop + +lz4_snappy_ml_done: + ADD R8, R5, R5 + + // emitCopy +two_byte_offset_lz4_s2: + CMPW $0x40, R8 + BLS two_byte_offset_short_lz4_s2 + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R7, 1(R0) + SUB $60, R8, R8 + MOVWU R8, R8 + ADD $0x03, R0, R0 + CMP R1, R0 + BHS lz4_snappy_loop + JMP two_byte_offset_lz4_s2 + +two_byte_offset_short_lz4_s2: + MOVWU R8, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R8 + BHS emit_copy_three_lz4_s2 + CMPW $0x00000800, R7 + BHS emit_copy_three_lz4_s2 + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R7, 1(R0) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R6, R6 + MOVB R6, (R0) + ADD $0x02, R0, R0 + JMP lz4_snappy_loop + +emit_copy_three_lz4_s2: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R0) + MOVH R7, 1(R0) + ADD $0x03, R0, R0 + JMP lz4_snappy_loop + +lz4_snappy_done: + MOVD dst_base+0(FP), R1 + SUB R1, R0, R0 + MOVD R5, uncompressed+48(FP) + MOVD R0, dstUsed+56(FP) + RET + +lz4_snappy_corrupt: + MOVD $0, R0 + SUB $1, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +lz4_snappy_dstfull: + MOVD $0, R0 + SUB $2, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +// func cvtLZ4sBlockSnappyAsm(dst []byte, src []byte) (uncompressed int, dstUsed int) +// Requires: SSE2 +TEXT ·cvtLZ4sBlockSnappyAsm(SB), NOSPLIT, $0-64 + MOVD $0, R5 + MOVD dst_base+0(FP), R0 + MOVD dst_len+8(FP), R1 + MOVD src_base+24(FP), R2 + MOVD src_len+32(FP), R3 + ADD R3, R2, R3 + ADD R1, R0, R1 + SUB $8, R1, R1 + +lz4s_snappy_loop: + CMP R3, R2 + BHS lz4s_snappy_corrupt + CMP R1, R0 + BHS lz4s_snappy_dstfull + MOVBU (R2), R6 + MOVD R6, R7 + MOVD R6, R8 + LSR $0x04, R7, R7 + AND $0x0f, R8, R8 + CMP $0xf0, R6 + BLO lz4s_snappy_ll_end + +lz4s_snappy_ll_loop: + ADD $1, R2, R2 + CMP R3, R2 + BHS lz4s_snappy_corrupt + MOVBU (R2), R6 + ADD R6, R7, R7 + CMP $0xff, R6 + BEQ lz4s_snappy_ll_loop + +lz4s_snappy_ll_end: + ADD R7, R2, R6 + ADD $0x03, R8, R8 + CMP R3, R6 + BHS lz4s_snappy_corrupt + ADD $1, R2, R2 + ADD $1, R6, R6 + TST R7, R7 + BEQ lz4s_snappy_lits_done + ADD R7, R0, R9 + CMP R1, R9 + BHS lz4s_snappy_dstfull + ADD R7, R5, R5 + SUB $1, R7, R9 + MOVWU R9, R9 + CMPW $0x3c, R9 + BLO one_byte_lz4s_snappy + CMPW $0x00000100, R9 + BLO two_bytes_lz4s_snappy + CMPW $0x00010000, R9 + BLO three_bytes_lz4s_snappy + CMPW $0x01000000, R9 + BLO four_bytes_lz4s_snappy + MOVD $0xfc, R16 + MOVB R16, (R0) + MOVW R9, 1(R0) + ADD $0x05, R0, R0 + JMP memmove_long_lz4s_snappy + +four_bytes_lz4s_snappy: + MOVWU R9, R10 + LSRW $0x10, R10, R10 + MOVD $0xf8, R16 + MOVB R16, (R0) + MOVH R9, 1(R0) + MOVB R10, 3(R0) + ADD $0x04, R0, R0 + JMP memmove_long_lz4s_snappy + +three_bytes_lz4s_snappy: + MOVD $0xf4, R16 + MOVB R16, (R0) + MOVH R9, 1(R0) + ADD $0x03, R0, R0 + JMP memmove_long_lz4s_snappy + +two_bytes_lz4s_snappy: + MOVD $0xf0, R16 + MOVB R16, (R0) + MOVB R9, 1(R0) + ADD $0x02, R0, R0 + CMPW $0x40, R9 + BLO memmove_lz4s_snappy + JMP memmove_long_lz4s_snappy + +one_byte_lz4s_snappy: + LSLW $0x02, R9, R16 + BFI $0, R16, $8, R9 + MOVB R9, (R0) + ADD $0x01, R0, R0 + +memmove_lz4s_snappy: + ADD R7, R0, R9 + + // genMemMoveShort + CMP $0x08, R7 + BLS emit_lit_memmove_lz4s_snappy_memmove_move_8 + CMP $0x10, R7 + BLS emit_lit_memmove_lz4s_snappy_memmove_move_8through16 + CMP $0x20, R7 + BLS emit_lit_memmove_lz4s_snappy_memmove_move_17through32 + JMP emit_lit_memmove_lz4s_snappy_memmove_move_33through64 + +emit_lit_memmove_lz4s_snappy_memmove_move_8: + MOVD (R2), R10 + MOVD R10, (R0) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_8through16: + MOVD (R2), R10 + ADD R7, R2, R15 + MOVD -8(R15), R2 + MOVD R10, (R0) + ADD R7, R0, R15 + MOVD R2, -8(R15) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_17through32: + FMOVQ (R2), F0 + ADD R7, R2, R15 + FMOVQ -16(R15), F1 + FMOVQ F0, (R0) + ADD R7, R0, R15 + FMOVQ F1, -16(R15) + JMP memmove_end_copy_lz4s_snappy + +emit_lit_memmove_lz4s_snappy_memmove_move_33through64: + FMOVQ (R2), F0 + FMOVQ 16(R2), F1 + ADD R7, R2, R15 + FMOVQ -32(R15), F2 + ADD R7, R2, R15 + FMOVQ -16(R15), F3 + FMOVQ F0, (R0) + FMOVQ F1, 16(R0) + ADD R7, R0, R15 + FMOVQ F2, -32(R15) + ADD R7, R0, R15 + FMOVQ F3, -16(R15) + +memmove_end_copy_lz4s_snappy: + MOVD R9, R0 + JMP lz4s_snappy_lits_emit_done + +memmove_long_lz4s_snappy: + ADD R7, R0, R9 + + // genMemMoveLong + MOVD R2, R10 + MOVD R0, R11 + MOVD R7, R12 + +emit_lit_memmove_long_lz4s_snappylarge_big_loop_back: + FMOVQ (R10), F0 + FMOVQ 16(R10), F1 + FMOVQ F0, (R11) + FMOVQ F1, 16(R11) + ADD $0x20, R10, R10 + ADD $0x20, R11, R11 + SUB $0x20, R12, R12 + CMP $0x20, R12 + BHS emit_lit_memmove_long_lz4s_snappylarge_big_loop_back + ADD R7, R2, R15 + FMOVQ -32(R15), F0 + ADD R7, R2, R15 + FMOVQ -16(R15), F1 + ADD R7, R0, R15 + FMOVQ F0, -32(R15) + ADD R7, R0, R15 + FMOVQ F1, -16(R15) + MOVD R9, R0 + +lz4s_snappy_lits_emit_done: + MOVD R6, R2 + +lz4s_snappy_lits_done: + CMP R3, R2 + BNE lz4s_snappy_match + CMP $0x03, R8 + BEQ lz4s_snappy_done + JMP lz4s_snappy_corrupt + +lz4s_snappy_match: + CMP $0x03, R8 + BEQ lz4s_snappy_loop + ADD $2, R2, R6 + CMP R3, R6 + BHS lz4s_snappy_corrupt + MOVHU (R2), R7 + MOVD R6, R2 + TST R7, R7 + BEQ lz4s_snappy_corrupt + CMP R5, R7 + BHI lz4s_snappy_corrupt + CMP $0x12, R8 + BNE lz4s_snappy_ml_done + +lz4s_snappy_ml_loop: + MOVBU (R2), R6 + ADD $1, R2, R2 + ADD R6, R8, R8 + CMP R3, R2 + BHS lz4s_snappy_corrupt + CMP $0xff, R6 + BEQ lz4s_snappy_ml_loop + +lz4s_snappy_ml_done: + ADD R8, R5, R5 + + // emitCopy +two_byte_offset_lz4_s2: + CMPW $0x40, R8 + BLS two_byte_offset_short_lz4_s2 + MOVD $0xee, R16 + MOVB R16, (R0) + MOVH R7, 1(R0) + SUB $60, R8, R8 + MOVWU R8, R8 + ADD $0x03, R0, R0 + CMP R1, R0 + BHS lz4s_snappy_loop + JMP two_byte_offset_lz4_s2 + +two_byte_offset_short_lz4_s2: + MOVWU R8, R6 + LSLW $0x02, R6, R6 + CMPW $0x0c, R8 + BHS emit_copy_three_lz4_s2 + CMPW $0x00000800, R7 + BHS emit_copy_three_lz4_s2 + SUB $15, R6, R6 + MOVWU R6, R6 + MOVB R7, 1(R0) + LSRW $0x08, R7, R7 + LSLW $0x05, R7, R7 + ORRW R7, R6, R6 + MOVB R6, (R0) + ADD $0x02, R0, R0 + JMP lz4s_snappy_loop + +emit_copy_three_lz4_s2: + SUB $2, R6, R6 + MOVWU R6, R6 + MOVB R6, (R0) + MOVH R7, 1(R0) + ADD $0x03, R0, R0 + JMP lz4s_snappy_loop + +lz4s_snappy_done: + MOVD dst_base+0(FP), R1 + SUB R1, R0, R0 + MOVD R5, uncompressed+48(FP) + MOVD R0, dstUsed+56(FP) + RET + +lz4s_snappy_corrupt: + MOVD $0, R0 + SUB $1, R0, R5 + MOVD R5, uncompressed+48(FP) + RET + +lz4s_snappy_dstfull: + MOVD $0, R0 + SUB $2, R0, R5 + MOVD R5, uncompressed+48(FP) + RET diff --git a/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go b/src/vendor/github.com/klauspost/compress/s2/encodeblock_asm.go similarity index 98% rename from src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go rename to src/vendor/github.com/klauspost/compress/s2/encodeblock_asm.go index f43aa815..fb602efd 100644 --- a/src/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.go +++ b/src/vendor/github.com/klauspost/compress/s2/encodeblock_asm.go @@ -1,6 +1,6 @@ -// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_amd64.go -pkg=s2. DO NOT EDIT. +// Code generated by command: go run gen.go -out ../encodeblock_amd64.s -stubs ../encodeblock_asm.go -pkg=s2. DO NOT EDIT. -//go:build !appengine && !noasm && gc && !noasm +//go:build (amd64 || arm64) && !appengine && !noasm && gc && !noasm package s2 diff --git a/src/vendor/github.com/klauspost/compress/s2/index.go b/src/vendor/github.com/klauspost/compress/s2/index.go index fb7db253..a5e751a8 100644 --- a/src/vendor/github.com/klauspost/compress/s2/index.go +++ b/src/vendor/github.com/klauspost/compress/s2/index.go @@ -151,7 +151,7 @@ func (i *Index) reduce() { i.estBlockUncomp += i.estBlockUncomp * int64(removeN) } -func (i *Index) appendTo(b []byte, uncompTotal, compTotal int64) []byte { +func (i *Index) appendTo(b []byte, compTotal, uncompTotal int64) []byte { i.reduce() var tmp [binary.MaxVarintLen64]byte @@ -425,7 +425,7 @@ func IndexStream(r io.Reader) ([]byte, error) { _, err := io.ReadFull(r, buf[:4]) if err != nil { if err == io.EOF { - return i.appendTo(nil, i.TotalUncompressed, i.TotalCompressed), nil + return i.appendTo(nil, i.TotalCompressed, i.TotalUncompressed), nil } return nil, err } diff --git a/src/vendor/github.com/klauspost/compress/s2/lz4convert.go b/src/vendor/github.com/klauspost/compress/s2/lz4convert.go index 46ed908e..01b5fb5c 100644 --- a/src/vendor/github.com/klauspost/compress/s2/lz4convert.go +++ b/src/vendor/github.com/klauspost/compress/s2/lz4convert.go @@ -32,7 +32,7 @@ func (l *LZ4Converter) ConvertBlock(dst, src []byte) ([]byte, int, error) { s, d := 0, len(dst) dst = dst[:cap(dst)] - if !debug && hasAmd64Asm { + if !debug && hasAsm { res, sz := cvtLZ4BlockAsm(dst[d:], src) if res < 0 { const ( @@ -288,7 +288,7 @@ func (l *LZ4Converter) ConvertBlockSnappy(dst, src []byte) ([]byte, int, error) s, d := 0, len(dst) dst = dst[:cap(dst)] // Use assembly when possible - if !debug && hasAmd64Asm { + if !debug && hasAsm { res, sz := cvtLZ4BlockSnappyAsm(dst[d:], src) if res < 0 { const ( diff --git a/src/vendor/github.com/klauspost/compress/s2/lz4sconvert.go b/src/vendor/github.com/klauspost/compress/s2/lz4sconvert.go index 000f3971..7b4de58f 100644 --- a/src/vendor/github.com/klauspost/compress/s2/lz4sconvert.go +++ b/src/vendor/github.com/klauspost/compress/s2/lz4sconvert.go @@ -37,7 +37,7 @@ func (l *LZ4sConverter) ConvertBlock(dst, src []byte) ([]byte, int, error) { s, d := 0, len(dst) dst = dst[:cap(dst)] - if !debug && hasAmd64Asm { + if !debug && hasAsm { res, sz := cvtLZ4sBlockAsm(dst[d:], src) if res < 0 { const ( @@ -297,7 +297,7 @@ func (l *LZ4sConverter) ConvertBlockSnappy(dst, src []byte) ([]byte, int, error) s, d := 0, len(dst) dst = dst[:cap(dst)] // Use assembly when possible - if !debug && hasAmd64Asm { + if !debug && hasAsm { res, sz := cvtLZ4sBlockSnappyAsm(dst[d:], src) if res < 0 { const ( diff --git a/src/vendor/github.com/klauspost/compress/s2/reader.go b/src/vendor/github.com/klauspost/compress/s2/reader.go index 17443e2c..5c6cb4cf 100644 --- a/src/vendor/github.com/klauspost/compress/s2/reader.go +++ b/src/vendor/github.com/klauspost/compress/s2/reader.go @@ -451,9 +451,7 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e } // Writer var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for toWrite := range queue { entry := <-toWrite reUse <- toWrite @@ -480,7 +478,7 @@ func (r *Reader) DecodeConcurrent(w io.Writer, concurrent int) (written int64, e } aWritten += int64(n) } - }() + }) defer func() { if r.err != nil { diff --git a/src/vendor/github.com/klauspost/compress/s2/writer.go b/src/vendor/github.com/klauspost/compress/s2/writer.go index 09f1cff3..8077f2f6 100644 --- a/src/vendor/github.com/klauspost/compress/s2/writer.go +++ b/src/vendor/github.com/klauspost/compress/s2/writer.go @@ -139,11 +139,9 @@ func (w *Writer) Reset(writer io.Writer) { toWrite := make(chan chan result, w.concurrency) w.output = toWrite - w.writerWg.Add(1) // Start a writer goroutine that will write all output in order. - go func() { - defer w.writerWg.Done() + w.writerWg.Go(func() { // Get a queued write. for write := range toWrite { @@ -175,7 +173,7 @@ func (w *Writer) Reset(writer io.Writer) { // This can be used for synchronizing flushes. close(write) } - }() + }) } // Write satisfies the io.Writer interface. @@ -811,7 +809,7 @@ func (w *Writer) closeIndex(idx bool) ([]byte, error) { if w.pad <= 1 { compSize = w.written } - index = w.index.appendTo(w.ibuf[:0], w.uncompWritten, compSize) + index = w.index.appendTo(w.ibuf[:0], compSize, w.uncompWritten) // Count as written for padding. if w.appendIndex { w.written += int64(len(index)) diff --git a/src/vendor/github.com/klauspost/compress/zstd/blockdec.go b/src/vendor/github.com/klauspost/compress/zstd/blockdec.go index 2329e996..89b20d6a 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/blockdec.go +++ b/src/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -240,9 +240,11 @@ func (b *blockDec) decodeBuf(hist *history) error { b.dst[i] = v } hist.appendKeep(b.dst) + hist.decoders.consumeSyncLen(len(b.dst)) return nil case blockTypeRaw: hist.appendKeep(b.data) + hist.decoders.consumeSyncLen(len(b.data)) return nil case blockTypeCompressed: saved := b.dst @@ -400,8 +402,9 @@ func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err } } var err error - // Use our out buffer. - huff.MaxDecodedSize = litRegenSize + // Decoder.Decompress* uses cap(dst) for the size limit. Do not write + // MaxDecodedSize on hist.huffTree: with a trained dictionary that + // pointer aliases the shared dict.litEnc and concurrent DecodeAll races. if fourStreams { literals, err = huff.Decoder().Decompress4X(b.literalBuf[:0:litRegenSize], literals) } else { @@ -486,6 +489,7 @@ func (b *blockDec) decodeCompressed(hist *history) error { } if hist.decoders.nSeqs == 0 { b.dst = append(b.dst, hist.decoders.literals...) + hist.decoders.consumeSyncLen(len(hist.decoders.literals)) return nil } before := len(hist.decoders.out) @@ -673,10 +677,6 @@ func (b *blockDec) executeSequences(hist *history) error { hbytes := hist.b if len(hbytes) > hist.windowSize { hbytes = hbytes[len(hbytes)-hist.windowSize:] - // We do not need history anymore. - if hist.dict != nil { - hist.dict.content = nil - } } hist.decoders.windowSize = hist.windowSize hist.decoders.out = b.dst[:0] diff --git a/src/vendor/github.com/klauspost/compress/zstd/decoder.go b/src/vendor/github.com/klauspost/compress/zstd/decoder.go index c7e500f0..90ef3bb0 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/decoder.go +++ b/src/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -7,8 +7,11 @@ package zstd import ( "context" "encoding/binary" + "errors" "io" + "maps" "sync" + "sync/atomic" "github.com/klauspost/compress/zstd/internal/xxhash" ) @@ -20,7 +23,8 @@ import ( // A decoder can safely be re-used even if the previous stream failed. // To release the resources, you must call the Close() function on a decoder. type Decoder struct { - o decoderOptions + // publishedOptions contains the current immutable decoder options. + publishedOptions atomic.Pointer[decoderOptions] // Unreferenced decoders, ready for use. decoders chan *blockDec @@ -84,9 +88,10 @@ var ( func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { initPredefined() var d Decoder - d.o.setDefault() - for _, o := range opts { - err := o(&d.o) + var o decoderOptions + o.setDefault() + for _, opt := range opts { + err := opt(&o) if err != nil { return nil, err } @@ -99,17 +104,19 @@ func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { } // Initialize dict map if needed. - if d.o.dicts == nil { - d.o.dicts = make(map[uint32]*dict) + if o.dicts == nil { + o.dicts = make(map[uint32]*dict) } // Create decoders - d.decoders = make(chan *blockDec, d.o.concurrent) - for i := 0; i < d.o.concurrent; i++ { - dec := newBlockDec(d.o.lowMem) - dec.localFrame = newFrameDec(d.o) + d.decoders = make(chan *blockDec, o.concurrent) + for i := 0; i < o.concurrent; i++ { + dec := newBlockDec(o.lowMem) + dec.localFrame = newFrameDec(o) + dec.localFrame.o.dicts = nil d.decoders <- dec } + d.publishedOptions.Store(&o) if r == nil { return &d, nil @@ -171,6 +178,9 @@ func (d *Decoder) Reset(r io.Reader) error { d.drainOutput() d.syncStream.br.r = nil + if d.frame != nil { + d.frame.o.dicts = nil + } if r == nil { d.current.err = ErrDecoderNilInput if len(d.current.b) > 0 { @@ -180,8 +190,10 @@ func (d *Decoder) Reset(r io.Reader) error { return nil } + o := *d.publishedOptions.Load() + // If bytes buffer and < 5MB, do sync decoding anyway. - if bb, ok := r.(byter); ok && bb.Len() < d.o.decodeBufsBelow && !d.o.limitToCap { + if bb, ok := r.(byter); ok && bb.Len() < o.decodeBufsBelow && !o.limitToCap { bb2 := bb if debugDecoder { println("*bytes.Buffer detected, doing sync decode, len:", bb.Len()) @@ -193,18 +205,30 @@ func (d *Decoder) Reset(r io.Reader) error { } dst, err := d.DecodeAll(b, dst) - if err == nil { - err = io.EOF + if !errors.Is(err, ErrDecoderSizeExceeded) { + if err == nil { + err = io.EOF + } + // Save output buffer + d.syncStream.dstBuf = dst + d.current.b = dst + d.current.err = err + d.current.flushed = true + if debugDecoder { + println("sync decode to", len(dst), "bytes, err:", err) + } + return nil } - // Save output buffer - d.syncStream.dstBuf = dst - d.current.b = dst - d.current.err = err - d.current.flushed = true + // The output does not fit WithDecoderMaxMemory, which caps the total + // decoded size when decoding in memory. A Reader follows the + // streaming contract, where the option caps the window instead, so + // decode this input as a stream after all; the shortcut has not + // consumed the reader. Drop the oversized buffer rather than keep it + // for reuse. if debugDecoder { - println("sync decode to", len(dst), "bytes, err:", err) + println("sync decode exceeded max memory after", len(dst), "bytes; streaming instead") } - return nil + d.syncStream.dstBuf = nil } // Remove current block. d.stashDecoder() @@ -217,14 +241,16 @@ func (d *Decoder) Reset(r io.Reader) error { // Ensure no-one else is still running... d.streamWg.Wait() if d.frame == nil { - d.frame = newFrameDec(d.o) + d.frame = newFrameDec(o) + } else { + d.frame.setOptions(o) } - if d.o.concurrent == 1 { + if o.concurrent == 1 { return d.startSyncDecoder(r) } - d.current.output = make(chan decodeOutput, d.o.concurrent) + d.current.output = make(chan decodeOutput, o.concurrent) ctx, cancel := context.WithCancel(context.Background()) d.current.cancel = cancel d.streamWg.Add(1) @@ -238,13 +264,21 @@ func (d *Decoder) Reset(r io.Reader) error { // Options are applied on top of the existing options. // Some options cannot be changed on reset and will return an error. func (d *Decoder) ResetWithOptions(r io.Reader, opts ...DOption) error { - d.o.resetOpt = true - defer func() { d.o.resetOpt = false }() + if d.current.err == ErrDecoderClosed { + return d.current.err + } + next := *d.publishedOptions.Load() + next.dicts = maps.Clone(next.dicts) + next.resetOpt = true for _, o := range opts { - if err := o(&d.o); err != nil { + if err := o(&next); err != nil { + next.resetOpt = false + d.publishedOptions.Store(&next) return err } } + next.resetOpt = false + d.publishedOptions.Store(&next) return d.Reset(r) } @@ -324,6 +358,8 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { // Grab a block decoder and frame decoder. block := <-d.decoders frame := block.localFrame + o := *d.publishedOptions.Load() + frame.setOptions(o) initialSize := len(dst) defer func() { if debugDecoder { @@ -335,6 +371,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { frame.history.decoders.br.in = nil frame.history.decoders.br.cursor = 0 } + frame.o.dicts = nil d.decoders <- block }() frame.bBuf = input @@ -354,20 +391,20 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { if err = d.setDict(frame); err != nil { return nil, err } - if frame.WindowSize > d.o.maxWindowSize { + if frame.WindowSize > frame.o.maxWindowSize { if debugDecoder { - println("window size exceeded:", frame.WindowSize, ">", d.o.maxWindowSize) + println("window size exceeded:", frame.WindowSize, ">", frame.o.maxWindowSize) } return dst, ErrWindowSizeExceeded } if frame.FrameContentSize != fcsUnknown { - if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)-initialSize) { + if frame.FrameContentSize > frame.o.maxDecodedSize-uint64(len(dst)-initialSize) { if debugDecoder { - println("decoder size exceeded; fcs:", frame.FrameContentSize, "> mcs:", d.o.maxDecodedSize-uint64(len(dst)-initialSize), "len:", len(dst)) + println("decoder size exceeded; fcs:", frame.FrameContentSize, "> mcs:", frame.o.maxDecodedSize-uint64(len(dst)-initialSize), "len:", len(dst)) } return dst, ErrDecoderSizeExceeded } - if d.o.limitToCap && frame.FrameContentSize > uint64(cap(dst)-len(dst)) { + if frame.o.limitToCap && frame.FrameContentSize > uint64(cap(dst)-len(dst)) { if debugDecoder { println("decoder size exceeded; fcs:", frame.FrameContentSize, "> (cap-len)", cap(dst)-len(dst)) } @@ -380,14 +417,14 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { } } - if cap(dst) == 0 && !d.o.limitToCap { + if cap(dst) == 0 && !frame.o.limitToCap { // Allocate len(input) * 2 by default if nothing is provided // and we didn't get frame content size. size := min( // Cap to 1 MB. len(input)*2, 1<<20) - if uint64(size) > d.o.maxDecodedSize { - size = int(d.o.maxDecodedSize) + if uint64(size) > frame.o.maxDecodedSize { + size = int(frame.o.maxDecodedSize) } dst = make([]byte, 0, size) } @@ -396,7 +433,7 @@ func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { if err != nil { return dst, err } - if uint64(len(dst)-initialSize) > d.o.maxDecodedSize { + if uint64(len(dst)-initialSize) > frame.o.maxDecodedSize { return dst, ErrDecoderSizeExceeded } if len(frame.bBuf) == 0 { @@ -459,7 +496,7 @@ func (d *Decoder) nextBlock(blocking bool) (ok bool) { println("got", len(d.current.b), "bytes, error:", d.current.err, "data crc:", tmp) } - if d.o.ignoreChecksum { + if d.frame.o.ignoreChecksum { return true } @@ -497,7 +534,7 @@ func (d *Decoder) nextBlockSync() (ok bool) { if d.current.err != nil { return false } - if d.frame.WindowSize > d.o.maxDecodedSize || d.frame.WindowSize > d.o.maxWindowSize { + if d.frame.WindowSize > d.frame.o.maxDecodedSize || d.frame.WindowSize > d.frame.o.maxWindowSize { d.current.err = ErrDecoderSizeExceeded return false } @@ -546,11 +583,11 @@ func (d *Decoder) nextBlockSync() (ok bool) { // Update/Check CRC if d.frame.HasCheckSum { - if !d.o.ignoreChecksum { + if !d.frame.o.ignoreChecksum { d.frame.crc.Write(d.current.b) } if d.current.d.Last { - if !d.o.ignoreChecksum { + if !d.frame.o.ignoreChecksum { d.current.err = d.frame.checkCRC() } else { d.current.err = d.frame.consumeCRC() @@ -656,8 +693,8 @@ func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output ch defer d.streamWg.Done() br := readerWrapper{r: r} - var seqDecode = make(chan *blockDec, d.o.concurrent) - var seqExecute = make(chan *blockDec, d.o.concurrent) + var seqDecode = make(chan *blockDec, d.frame.o.concurrent) + var seqExecute = make(chan *blockDec, d.frame.o.concurrent) // Async 1: Decode sequences... go func() { @@ -858,9 +895,9 @@ decodeStream: if err == nil { err = d.setDict(frame) } - if err == nil && d.frame.WindowSize > d.o.maxWindowSize { + if err == nil && d.frame.WindowSize > d.frame.o.maxWindowSize { if debugDecoder { - println("decoder size exceeded, fws:", d.frame.WindowSize, "> mws:", d.o.maxWindowSize) + println("decoder size exceeded, fws:", d.frame.WindowSize, "> mws:", d.frame.o.maxWindowSize) } err = ErrDecoderSizeExceeded @@ -940,7 +977,7 @@ decodeStream: } func (d *Decoder) setDict(frame *frameDec) (err error) { - dict, ok := d.o.dicts[frame.DictionaryID] + dict, ok := frame.o.dicts[frame.DictionaryID] if ok { if debugDecoder { println("setting dict", frame.DictionaryID) diff --git a/src/vendor/github.com/klauspost/compress/zstd/dict.go b/src/vendor/github.com/klauspost/compress/zstd/dict.go index 4f1c4938..67f40e79 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/dict.go +++ b/src/vendor/github.com/klauspost/compress/zstd/dict.go @@ -296,40 +296,81 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { if offset > 3 { newOffsets[offset-3]++ } else { - newOffsets[uint32(o.Offsets[offset-1])]++ + // Repeat codes reference the training Offsets. Skip unset + // (zero) entries so they are not ranked as real offsets. + prev := o.Offsets[offset-1] + if prev > 0 { + newOffsets[uint32(prev)]++ + } } } } // Find most used offsets. var sortedOffsets []uint32 for k := range newOffsets { + if k == 0 { + continue + } sortedOffsets = append(sortedOffsets, k) } sort.Slice(sortedOffsets, func(i, j int) bool { a, b := sortedOffsets[i], sortedOffsets[j] - if a == b { + ca, cb := newOffsets[a], newOffsets[b] + if ca == cb { // Prefer the longer offset - return sortedOffsets[i] > sortedOffsets[j] + return a > b } - return newOffsets[sortedOffsets[i]] > newOffsets[sortedOffsets[j]] + return ca > cb }) - if len(sortedOffsets) > 3 { - if debug { - print("Offsets:") - for i, v := range sortedOffsets { - if i > 20 { - break - } - printf("[%d: %d],", v, newOffsets[v]) + if debug { + print("Offsets:") + for i, v := range sortedOffsets { + if i > 20 { + break } - println("") + printf("[%d: %d],", v, newOffsets[v]) + } + println("") + } + // Dictionary recent-offsets must be three positive values within the + // history. Ranked matches may be fewer (or empty when only unset + // repeat codes were seen), so fill remaining slots with defaults. + used := make(map[int]bool, 3) + var finalOffsets [3]int + nOff := 0 + for _, v := range sortedOffsets { + iv := int(v) + if iv <= 0 || iv > len(hist) || used[iv] { + continue + } + finalOffsets[nOff] = iv + used[iv] = true + nOff++ + if nOff == 3 { + break } - - sortedOffsets = sortedOffsets[:3] } - for i, v := range sortedOffsets { - o.Offsets[i] = int(v) + for _, def := range []int{1, 4, 8} { + if nOff == 3 { + break + } + if def <= len(hist) && !used[def] { + finalOffsets[nOff] = def + used[def] = true + nOff++ + } + } + for def := 1; nOff < 3 && def <= len(hist); def++ { + if !used[def] { + finalOffsets[nOff] = def + used[def] = true + nOff++ + } + } + if nOff < 3 { + return nil, fmt.Errorf("could not determine 3 valid dictionary offsets (history size %d)", len(hist)) } + o.Offsets = finalOffsets if debug { println("New repeat offsets", o.Offsets) } @@ -337,6 +378,9 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { if nUsed == 0 || seqs == 0 { return nil, fmt.Errorf("%d blocks, %d sequences found", nUsed, seqs) } + if litTotal == 0 { + return nil, errors.New("0 literals found") + } if debug { println("Sequences:", seqs, "Blocks:", nUsed, "Literals:", litTotal) } @@ -517,11 +561,10 @@ func BuildDict(o BuildDictOptions) ([]byte, error) { out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[1]))) out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[2]))) out.Write(hist) + if _, err := loadDict(out.Bytes()); err != nil { + return nil, fmt.Errorf("built dictionary failed validation: %w", err) + } if debug { - _, err := loadDict(out.Bytes()) - if err != nil { - panic(err) - } i, err := InspectDictionary(out.Bytes()) if err != nil { panic(err) diff --git a/src/vendor/github.com/klauspost/compress/zstd/framedec.go b/src/vendor/github.com/klauspost/compress/zstd/framedec.go index d88f067e..81d8b9c9 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/framedec.go +++ b/src/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -49,13 +49,16 @@ const ( ) func newFrameDec(o decoderOptions) *frameDec { + d := frameDec{} + d.setOptions(o) + return &d +} + +func (d *frameDec) setOptions(o decoderOptions) { if o.maxWindowSize > o.maxDecodedSize { o.maxWindowSize = o.maxDecodedSize } - d := frameDec{ - o: o, - } - return &d + d.o = o } // reset will read the frame header and prepare for block decoding. diff --git a/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s b/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s index 77ee3913..8ca913ea 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s +++ b/src/vendor/github.com/klauspost/compress/zstd/fse_decoder_arm64.s @@ -1,7 +1,7 @@ // Code generated by command: go run gen_fse.go -out ../fse_decoder.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. // EXPERIMENTAL arm64 output lowered from an amd64 avo program. -//go:build arm64 && !appengine && !noasm && gc && !noasm +//go:build arm64 && (!appengine && !noasm && gc && !noasm) // func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int TEXT ·buildDtable_asm(SB), $0-24 @@ -26,11 +26,10 @@ TEXT ·buildDtable_asm(SB), $0-24 JMP init_main_loop_condition init_main_loop: - ADD R8<<1, R1, R15 - MOVH (R15), R9 - AND $0xffff, R9, R15 + MOVH (R1)(R8<<1), R9 MOVD $-1, R16 AND $0xffff, R16, R16 + AND $0xffff, R9, R15 CMP R16, R15 BNE do_not_update_high_threshold ADD R7<<3, R5, R15 @@ -39,8 +38,7 @@ init_main_loop: MOVD $0x0000000000000001, R9 do_not_update_high_threshold: - ADD R8<<1, R3, R15 - MOVH R9, (R15) + MOVH R9, (R3)(R8<<1) ADD $1, R8, R8 init_main_loop_condition: @@ -49,12 +47,10 @@ init_main_loop_condition: // Spread symbols // Calculate table step - MOVD R0, R8 - LSR $0x01, R8, R8 - MOVD R0, R9 - LSR $0x03, R9, R9 - ADD R9, R8, R8 - ADD $3, R8, R8 + LSR $0x01, R0, R8 + LSR $0x03, R0, R9 + ADD R9, R8, R8 + ADD $3, R8, R8 // Fill add bits values SUB $1, R0, R9 @@ -64,8 +60,7 @@ init_main_loop_condition: spread_main_loop: MOVD $0, R12 - ADD R11<<1, R1, R15 - MOVH (R15), R13 + MOVH (R1)(R11<<1), R13 JMP spread_inner_loop_condition spread_inner_loop: @@ -102,11 +97,9 @@ spread_check_ok: build_table_main_table: ADD R6<<3, R5, R15 MOVBU 1(R15), R1 - ADD R1<<1, R3, R15 - MOVHU (R15), R7 + MOVHU (R3)(R1<<1), R7 ADD $1, R7, R8 - ADD R1<<1, R3, R15 - MOVH R8, (R15) + MOVH R8, (R3)(R1<<1) MOVD R7, R8 CLZ R8, R16 MOVD $63, R8 @@ -129,12 +122,10 @@ build_table_main_table: RET build_table_check1_ok: - AND $0xff, R1, R15 - AND $0xff, R1, R16 - TST R16, R15 + TST $0xff, R1 BNE build_table_check2_ok - AND $0xffff, R7, R15 AND $0xffff, R6, R16 + AND $0xffff, R7, R15 CMP R16, R15 BNE build_table_check2_ok MOVD ctx+8(FP), R0 diff --git a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go index fc40c820..9c0cbc16 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go +++ b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go @@ -52,6 +52,11 @@ func (d *Digest) Reset() { d.n = 0 } +// maxAsmSize bounds the input handed to a single writeBlocks call. Assembly is +// never preemptible, so an unbounded call holds every P in stop-the-world for +// its duration. Whole 32-byte blocks, so Write can feed it in pieces. +const maxAsmSize = 128 << 10 // 4096 whole 32-byte blocks + // Size always returns 8 bytes. func (d *Digest) Size() int { return 8 } @@ -83,6 +88,13 @@ func (d *Digest) Write(b []byte) (n int, err error) { d.n = 0 } + for len(b) >= maxAsmSize { + // Assembly is not preemptible, so hashing a large buffer in one call + // blocks every stop-the-world for the whole call. Feed it in chunks. + writeBlocks(d, b[:maxAsmSize]) + b = b[maxAsmSize:] + } + if len(b) >= 32 { // One or more full blocks left. nw := writeBlocks(d, b) diff --git a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s index ddb63aa9..e4c688ef 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s +++ b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s @@ -175,7 +175,11 @@ finalize: RET // func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 +// +// Deliberately not NOSPLIT: the stack check is the preemption point that lets a +// stop-the-world proceed between chunks. The frame must be >= abi.StackSmall +// (128), or the assembler marks this leaf NOSPLIT anyway and drops that check. +TEXT ·writeBlocks(SB), $128-40 // Load fixed primes needed for round. MOVQ ·primes+0(SB), prime1 MOVQ ·primes+8(SB), prime2 diff --git a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s index ae7d4d32..e88cc2fc 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s +++ b/src/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s @@ -163,7 +163,11 @@ finalize: RET // func writeBlocks(s *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 +// +// Deliberately not NOSPLIT: the stack check is the preemption point that lets a +// stop-the-world proceed between chunks. The frame must be >= abi.StackSmall +// (128), or the assembler marks this leaf NOSPLIT anyway and drops that check. +TEXT ·writeBlocks(SB), $128-40 LDP ·primes+0(SB), (prime1, prime2) // Load state. Assume v[1-4] are stored contiguously. diff --git a/src/vendor/github.com/klauspost/compress/zstd/seqdec.go b/src/vendor/github.com/klauspost/compress/zstd/seqdec.go index 0bfb0e43..d1a7732f 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/seqdec.go +++ b/src/vendor/github.com/klauspost/compress/zstd/seqdec.go @@ -99,6 +99,29 @@ func (s *sequenceDecs) initialize(br *bitReader, hist *history, out []byte) erro return nil } +// consumeSyncLen accounts for n bytes of frame output produced outside +// decodeSync. maxSyncLen bounds how much the frame may still produce and +// decodeSyncSimple compares it with the output buffer's slack to decide +// whether the extended 16-byte copies are safe. Blocks with sequences +// subtracted their output; raw blocks, RLE blocks and compressed blocks +// holding only literals did not, so a frame that opened with a raw block +// overstated its remaining size for every block after it and ran the +// bounds-exact copies for the rest of the frame. +// +// Zero means "no bound" and selects the conservative paths, so a block that +// meets or exceeds the bound lands there; the frame-size checks in +// runDecoder reject the excess afterwards. +func (s *sequenceDecs) consumeSyncLen(n int) { + if s.maxSyncLen == 0 { + return + } + if uint64(n) >= s.maxSyncLen { + s.maxSyncLen = 0 + return + } + s.maxSyncLen -= uint64(n) +} + func (s *sequenceDecs) freeDecoders() { if f := s.litLengths.fse; f != nil && !f.preDefined { fseDecoderPool.Put(f) diff --git a/src/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/src/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s index 3fc381c7..798d9402 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s +++ b/src/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -4,7 +4,7 @@ // func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_amd64(SB), $8-32 +TEXT ·sequenceDecs_decode_amd64(SB), $40-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -16,6 +16,14 @@ TEXT ·sequenceDecs_decode_amd64(SB), $8-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 + MOVQ (AX), CX + MOVQ CX, 8(SP) + MOVQ 24(AX), CX + MOVQ CX, 16(SP) + MOVQ 48(AX), CX + MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) MOVQ 104(AX), R10 MOVQ s+0(FP), AX MOVQ 144(AX), R11 @@ -55,46 +63,32 @@ sequenceDecs_decode_amd64_fill_check_overread: sequenceDecs_decode_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_of_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_amd64_of_update_zero: - MOVQ AX, 16(R10) + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, 16(R10) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_amd64_ml_update_zero: - MOVQ AX, 8(R10) + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, 8(R10) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -126,90 +120,76 @@ sequenceDecs_decode_amd64_fill_2_check_overread: sequenceDecs_decode_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_amd64_ll_update_zero: - MOVQ AX, (R10) + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, (R10) // Fill bitreader for state updates MOVQ R14, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_amd64_skip_update // Update Literal Length State MOVBQZX DI, R14 SHRL $0x10, DI - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R14 SHRL $0x10, R8 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R14 SHRL $0x10, R9 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decode_amd64_skip_update: @@ -290,8 +270,7 @@ sequenceDecs_decode_amd64_after_adjust: sequenceDecs_decode_amd64_match_len_ofs_ok: ADDQ $0x18, R10 - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decode_amd64_main_loop MOVQ s+0(FP), AX MOVQ R11, 144(AX) @@ -303,36 +282,54 @@ sequenceDecs_decode_amd64_match_len_ofs_ok: MOVQ SI, 32(AX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_amd64_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32 +TEXT ·sequenceDecs_decode_56_amd64(SB), $40-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -344,6 +341,14 @@ TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 + MOVQ (AX), CX + MOVQ CX, 8(SP) + MOVQ 24(AX), CX + MOVQ CX, 16(SP) + MOVQ 48(AX), CX + MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) MOVQ 104(AX), R10 MOVQ s+0(FP), AX MOVQ 144(AX), R11 @@ -383,132 +388,104 @@ sequenceDecs_decode_56_amd64_fill_check_overread: sequenceDecs_decode_56_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_of_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_56_amd64_of_update_zero: - MOVQ AX, 16(R10) + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, 16(R10) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_56_amd64_ml_update_zero: - MOVQ AX, 8(R10) + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, 8(R10) // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R15 - SHLQ CL, R15 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decode_56_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decode_56_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decode_56_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R15 - ADDQ R15, AX - -sequenceDecs_decode_56_amd64_ll_update_zero: - MOVQ AX, (R10) + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R15 + ADDQ R15, AX + MOVQ AX, (R10) // Fill bitreader for state updates MOVQ R14, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_56_amd64_skip_update // Update Literal Length State MOVBQZX DI, R14 SHRL $0x10, DI - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R14 SHRL $0x10, R8 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R14 SHRL $0x10, R9 - LEAQ (BX)(R14*1), CX + MOVQ BX, CX MOVQ DX, R15 - MOVQ CX, BX - ROLQ CL, R15 - MOVL $0x00000001, BP - MOVB R14, CL - SHLL CL, BP - DECL BP - ANDQ BP, R15 + SHLQ CL, R15 + SHRQ $0x01, R15 + ADDQ R14, BX + XORQ $0x3f, R14 + MOVQ R14, CX + SHRQ CL, R15 ADDQ R15, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decode_56_amd64_skip_update: @@ -589,8 +566,7 @@ sequenceDecs_decode_56_amd64_after_adjust: sequenceDecs_decode_56_amd64_match_len_ofs_ok: ADDQ $0x18, R10 - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decode_56_amd64_main_loop MOVQ s+0(FP), AX MOVQ R11, 144(AX) @@ -602,36 +578,54 @@ sequenceDecs_decode_56_amd64_match_len_ofs_ok: MOVQ SI, 32(AX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: BMI, BMI2, CMOV -TEXT ·sequenceDecs_decode_bmi2(SB), $8-32 +TEXT ·sequenceDecs_decode_bmi2(SB), $40-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -643,6 +637,14 @@ TEXT ·sequenceDecs_decode_bmi2(SB), $8-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 + MOVQ (CX), R9 + MOVQ R9, 8(SP) + MOVQ 24(CX), R9 + MOVQ R9, 16(SP) + MOVQ 48(CX), R9 + MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) MOVQ 104(CX), R9 MOVQ s+0(FP), CX MOVQ 144(CX), R10 @@ -753,8 +755,7 @@ sequenceDecs_decode_bmi2_fill_2_end: MOVQ R13, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R13 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_bmi2_skip_update LEAQ (SI)(DI*1), R14 ADDQ R8, R14 @@ -772,8 +773,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -783,8 +783,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -793,8 +792,7 @@ sequenceDecs_decode_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decode_bmi2_skip_update: @@ -875,8 +873,7 @@ sequenceDecs_decode_bmi2_after_adjust: sequenceDecs_decode_bmi2_match_len_ofs_ok: ADDQ $0x18, R9 - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decode_bmi2_main_loop MOVQ s+0(FP), CX MOVQ R10, 144(CX) @@ -888,36 +885,54 @@ sequenceDecs_decode_bmi2_match_len_ofs_ok: MOVQ BX, 32(CX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_bmi2_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_bmi2_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET // func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: BMI, BMI2, CMOV -TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32 +TEXT ·sequenceDecs_decode_56_bmi2(SB), $40-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -929,6 +944,14 @@ TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 + MOVQ (CX), R9 + MOVQ R9, 8(SP) + MOVQ 24(CX), R9 + MOVQ R9, 16(SP) + MOVQ 48(CX), R9 + MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) MOVQ 104(CX), R9 MOVQ s+0(FP), CX MOVQ 144(CX), R10 @@ -1010,8 +1033,7 @@ sequenceDecs_decode_56_bmi2_fill_end: MOVQ R13, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R13 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decode_56_bmi2_skip_update LEAQ (SI)(DI*1), R14 ADDQ R8, R14 @@ -1029,8 +1051,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -1040,8 +1061,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -1050,8 +1070,7 @@ sequenceDecs_decode_56_bmi2_fill_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decode_56_bmi2_skip_update: @@ -1132,8 +1151,7 @@ sequenceDecs_decode_56_bmi2_after_adjust: sequenceDecs_decode_56_bmi2_match_len_ofs_ok: ADDQ $0x18, R9 - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decode_56_bmi2_main_loop MOVQ s+0(FP), CX MOVQ R10, 144(CX) @@ -1145,30 +1163,48 @@ sequenceDecs_decode_56_bmi2_match_len_ofs_ok: MOVQ BX, 32(CX) // Return success + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000000, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_bmi2_error_match_len_ofs_mismatch: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000001, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_bmi2_error_match_len_too_big: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000002, ret+24(FP) RET // Return with match offset too long error + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000003, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000004, ret+24(FP) RET // Return with overread error error_overread: + MOVQ 32(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 96(CX) MOVQ $0x00000006, ret+24(FP) RET @@ -1203,9 +1239,11 @@ main_loop: MOVQ 8(AX), R13 // Copy literals - TESTQ R11, R11 - JZ check_offset - XORQ R14, R14 + MOVUPS (SI), X0 + MOVUPS X0, (BX) + CMPQ R11, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (SI)(R14*1), X0 @@ -1213,12 +1251,13 @@ copy_1: ADDQ $0x10, R14 CMPQ R14, R11 JB copy_1 - ADDQ R11, SI - ADDQ R11, BX - ADDQ R11, DI + +copy_1_end: + ADDQ R11, SI + ADDQ R11, BX + ADDQ R11, DI // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: LEAQ (DI)(R10*1), R11 CMPQ R12, R11 JG error_match_off_too_big @@ -1258,13 +1297,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), R11 - MOVB 2(R14), R12 - MOVW R11, (BX) - MOVB R12, 2(BX) - ADDQ R13, R14 - ADDQ R13, BX - JMP copy_4_end + MOVWQZX (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end copy_4_move_4through7: MOVL (R14), R11 @@ -1327,13 +1366,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (BX) - MOVB BP, 2(BX) - ADDQ R11, R14 - ADDQ R11, BX - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -1366,9 +1405,19 @@ copy_match: JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, DI - MOVQ BX, R12 + ADDQ R13, DI + MOVUPS (R11), X0 + MOVUPS X0, (BX) + CMPQ R13, $0x10 + JA copy_2_long + ADDQ R13, BX + JMP handle_loop + +copy_2_long: + LEAQ 16(BX), R12 ADDQ R13, BX + ADDQ $0x10, R11 + SUBQ $0x10, R13 copy_2: MOVUPS (R11), X0 @@ -1384,12 +1433,12 @@ copy_overlapping_match: ADDQ R13, DI copy_slow_3: - MOVB (R11), R12 - MOVB R12, (BX) - INCQ R11 - INCQ BX - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 handle_loop: ADDQ $0x18, AX @@ -1494,13 +1543,13 @@ copy_1_move_1or2: JMP copy_1_end copy_1_move_3: - MOVW (SI), R14 - MOVB 2(SI), R15 - MOVW R14, (BX) - MOVB R15, 2(BX) - ADDQ R11, SI - ADDQ R11, BX - JMP copy_1_end + MOVWQZX (SI), R14 + MOVB 2(SI), R15 + MOVW R14, (BX) + MOVB R15, 2(BX) + ADDQ R11, SI + ADDQ R11, BX + JMP copy_1_end copy_1_move_4through7: MOVL (SI), R14 @@ -1563,13 +1612,13 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), R11 - MOVB 2(R14), R12 - MOVW R11, (BX) - MOVB R12, 2(BX) - ADDQ R13, R14 - ADDQ R13, BX - JMP copy_4_end + MOVWQZX (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end copy_4_move_4through7: MOVL (R14), R11 @@ -1632,13 +1681,13 @@ copy_5_move_1or2: JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (BX) - MOVB BP, 2(BX) - ADDQ R11, R14 - ADDQ R11, BX - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 @@ -1707,13 +1756,13 @@ copy_2_move_1or2: JMP copy_2_end copy_2_move_3: - MOVW (R11), R12 - MOVB 2(R11), R14 - MOVW R12, (BX) - MOVB R14, 2(BX) - ADDQ R13, R11 - ADDQ R13, BX - JMP copy_2_end + MOVWQZX (R11), R12 + MOVB 2(R11), R14 + MOVW R12, (BX) + MOVB R14, 2(BX) + ADDQ R13, R11 + ADDQ R13, BX + JMP copy_2_end copy_2_move_4through7: MOVL (R11), R12 @@ -1740,12 +1789,12 @@ copy_overlapping_match: ADDQ R13, DI copy_slow_3: - MOVB (R11), R12 - MOVB R12, (BX) - INCQ R11 - INCQ BX - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 handle_loop: ADDQ $0x18, AX @@ -1784,7 +1833,7 @@ empty_seqs: // func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_amd64(SB), $96-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -1796,26 +1845,34 @@ TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 - XORQ CX, CX + MOVQ (AX), CX MOVQ CX, 8(SP) + MOVQ 24(AX), CX MOVQ CX, 16(SP) + MOVQ 48(AX), CX MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) + XORQ CX, CX + MOVQ CX, 40(SP) + MOVQ CX, 48(SP) + MOVQ CX, 56(SP) MOVQ 112(AX), R10 MOVQ 128(AX), CX - MOVQ CX, 32(SP) + MOVQ CX, 64(SP) MOVQ 144(AX), R11 MOVQ 136(AX), R12 MOVQ 200(AX), CX - MOVQ CX, 56(SP) + MOVQ CX, 88(SP) MOVQ 176(AX), CX - MOVQ CX, 48(SP) + MOVQ CX, 80(SP) MOVQ 184(AX), AX - MOVQ AX, 40(SP) - MOVQ 40(SP), AX - ADDQ AX, 48(SP) + MOVQ AX, 72(SP) + MOVQ 72(SP), AX + ADDQ AX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R10, 32(SP) + ADDQ R10, 64(SP) // outBase += outPosition ADDQ R12, R10 @@ -1853,46 +1910,32 @@ sequenceDecs_decodeSync_amd64_fill_check_overread: sequenceDecs_decodeSync_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_of_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_of_update_zero: - MOVQ AX, 8(SP) + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 40(SP) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_ml_update_zero: - MOVQ AX, 16(SP) + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -1924,96 +1967,82 @@ sequenceDecs_decodeSync_amd64_fill_2_check_overread: sequenceDecs_decodeSync_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_amd64_ll_update_zero: - MOVQ AX, 24(SP) + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 56(SP) // Fill bitreader for state updates MOVQ R13, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_amd64_skip_update // Update Literal Length State MOVBQZX DI, R13 SHRL $0x10, DI - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R13 SHRL $0x10, R8 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R13 SHRL $0x10, R9 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decodeSync_amd64_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ AX, $0x01 JBE sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -2022,7 +2051,7 @@ sequenceDecs_decodeSync_amd64_skip_update: JMP sequenceDecs_decodeSync_amd64_after_adjust sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_amd64_adjust_offset_nonzero @@ -2057,14 +2086,11 @@ sequenceDecs_decodeSync_amd64_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_amd64_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), AX - MOVQ 24(SP), CX - LEAQ (AX)(CX*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), AX + MOVQ 56(SP), CX MOVQ ctx+16(FP), R14 SUBQ CX, 104(R14) JS error_not_enough_literals @@ -2076,50 +2102,49 @@ sequenceDecs_decodeSync_amd64_after_adjust: JNZ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_amd64_match_len_ofs_ok: - MOVQ 24(SP), AX - MOVQ 8(SP), CX - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (AX)(R13*1), R14 + LEAQ 16(CX)(AX*1), R14 ADDQ R10, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ AX, AX - JZ check_offset - XORQ R14, R14 + MOVUPS (R11), X0 + MOVUPS X0, (R10) + CMPQ CX, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (R11)(R14*1), X0 MOVUPS X0, (R10)(R14*1) ADDQ $0x10, R14 - CMPQ R14, AX + CMPQ R14, CX JB copy_1 - ADDQ AX, R11 - ADDQ AX, R10 - ADDQ AX, R12 + +copy_1_end: + ADDQ CX, R11 + ADDQ CX, R10 + ADDQ CX, R12 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVQ R12, AX - ADDQ 40(SP), AX - CMPQ CX, AX + MOVQ R12, CX + ADDQ 72(SP), CX + CMPQ R13, CX JG error_match_off_too_big - CMPQ CX, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ CX, AX - SUBQ R12, AX + MOVQ R13, CX + SUBQ R12, CX JLS copy_match - MOVQ 48(SP), R14 - SUBQ AX, R14 - CMPQ R13, AX + MOVQ 80(SP), R14 + SUBQ CX, R14 + CMPQ AX, CX JG copy_all_from_history - MOVQ R13, AX - SUBQ $0x10, AX + MOVQ AX, CX + SUBQ $0x10, CX JB copy_4_small copy_4_loop: @@ -2127,54 +2152,54 @@ copy_4_loop: MOVUPS X0, (R10) ADDQ $0x10, R14 ADDQ $0x10, R10 - SUBQ $0x10, AX + SUBQ $0x10, CX JAE copy_4_loop - LEAQ 16(R14)(AX*1), R14 - LEAQ 16(R10)(AX*1), R10 + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R10)(CX*1), R10 MOVUPS -16(R14), X0 MOVUPS X0, -16(R10) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 - JMP copy_4_end + MOVWQZX (R14), CX + MOVB 2(R14), R13 + MOVW CX, (R10) + MOVB R13, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_4_end copy_4_move_4through7: - MOVL (R14), AX - MOVL -4(R14)(R13*1), CX - MOVL AX, (R10) - MOVL CX, -4(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVL (R14), CX + MOVL -4(R14)(AX*1), R13 + MOVL CX, (R10) + MOVL R13, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), AX - MOVQ -8(R14)(R13*1), CX - MOVQ AX, (R10) - MOVQ CX, -8(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVQ (R14), CX + MOVQ -8(R14)(AX*1), R13 + MOVQ CX, (R10) + MOVQ R13, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 copy_4_end: - ADDQ R13, R12 + ADDQ AX, R12 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ AX, R15 + MOVQ CX, R15 SUBQ $0x10, R15 JB copy_5_small @@ -2192,90 +2217,99 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(AX*1), BP + MOVB -1(R14)(CX*1), BP MOVB R15, (R10) - MOVB BP, -1(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVB BP, -1(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R10) - MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ CX, R14 + ADDQ CX, R10 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(AX*1), BP + MOVL -4(R14)(CX*1), BP MOVL R15, (R10) - MOVL BP, -4(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVL BP, -4(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(AX*1), BP + MOVQ -8(R14)(CX*1), BP MOVQ R15, (R10) - MOVQ BP, -8(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVQ BP, -8(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 copy_5_end: - ADDQ AX, R12 - SUBQ AX, R13 + ADDQ CX, R12 + SUBQ CX, AX // Copy match from the current buffer copy_match: - MOVQ R10, AX - SUBQ CX, AX + MOVQ R10, CX + SUBQ R13, CX // ml <= mo - CMPQ R13, CX + CMPQ AX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R12 - MOVQ R10, CX - ADDQ R13, R10 + ADDQ AX, R12 + MOVUPS (CX), X0 + MOVUPS X0, (R10) + CMPQ AX, $0x10 + JA copy_2_long + ADDQ AX, R10 + JMP handle_loop + +copy_2_long: + LEAQ 16(R10), R13 + ADDQ AX, R10 + ADDQ $0x10, CX + SUBQ $0x10, AX copy_2: - MOVUPS (AX), X0 - MOVUPS X0, (CX) - ADDQ $0x10, AX + MOVUPS (CX), X0 + MOVUPS X0, (R13) ADDQ $0x10, CX - SUBQ $0x10, R13 + ADDQ $0x10, R13 + SUBQ $0x10, AX JHI copy_2 JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R12 + ADDQ AX, R12 copy_slow_3: - MOVB (AX), CL - MOVB CL, (R10) - INCQ AX - INCQ R10 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (CX), R13 + MOVB R13, (R10) + INCQ CX + INCQ R10 + DECQ AX + JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_amd64_main_loop loop_finished: @@ -2284,6 +2318,13 @@ loop_finished: MOVB BL, 40(AX) MOVQ SI, 32(AX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R12, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R12, 136(AX) @@ -2297,7 +2338,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -2306,7 +2347,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_amd64_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -2314,7 +2355,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R12, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -2323,7 +2364,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -2336,9 +2377,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R12, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -2346,7 +2387,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: BMI, BMI2, CMOV, SSE -TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_bmi2(SB), $96-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -2358,26 +2399,34 @@ TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 - XORQ R9, R9 + MOVQ (CX), R9 MOVQ R9, 8(SP) + MOVQ 24(CX), R9 MOVQ R9, 16(SP) + MOVQ 48(CX), R9 MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) + XORQ R9, R9 + MOVQ R9, 40(SP) + MOVQ R9, 48(SP) + MOVQ R9, 56(SP) MOVQ 112(CX), R9 MOVQ 128(CX), R10 - MOVQ R10, 32(SP) + MOVQ R10, 64(SP) MOVQ 144(CX), R10 MOVQ 136(CX), R11 MOVQ 200(CX), R12 - MOVQ R12, 56(SP) + MOVQ R12, 88(SP) MOVQ 176(CX), R12 - MOVQ R12, 48(SP) + MOVQ R12, 80(SP) MOVQ 184(CX), CX - MOVQ CX, 40(SP) - MOVQ 40(SP), CX - ADDQ CX, 48(SP) + MOVQ CX, 72(SP) + MOVQ 72(SP), CX + ADDQ CX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R9, 32(SP) + ADDQ R9, 64(SP) // outBase += outPosition ADDQ R11, R9 @@ -2425,7 +2474,7 @@ sequenceDecs_decodeSync_bmi2_fill_end: MOVQ R8, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 8(SP) + MOVQ CX, 40(SP) // Update match length MOVQ $0x00000808, CX @@ -2438,7 +2487,7 @@ sequenceDecs_decodeSync_bmi2_fill_end: MOVQ DI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 16(SP) + MOVQ CX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ BX, $0x08 @@ -2480,14 +2529,13 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: MOVQ SI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 24(SP) + MOVQ CX, 56(SP) // Fill bitreader for state updates MOVQ R12, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R12 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_bmi2_skip_update LEAQ (SI)(DI*1), R13 ADDQ R8, R13 @@ -2505,8 +2553,7 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -2516,8 +2563,7 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -2526,14 +2572,13 @@ sequenceDecs_decodeSync_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decodeSync_bmi2_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ R12, $0x01 JBE sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -2542,7 +2587,7 @@ sequenceDecs_decodeSync_bmi2_skip_update: JMP sequenceDecs_decodeSync_bmi2_after_adjust sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_bmi2_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_bmi2_adjust_offset_nonzero @@ -2577,14 +2622,11 @@ sequenceDecs_decodeSync_bmi2_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_bmi2_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), CX - MOVQ 24(SP), R12 - LEAQ (CX)(R12*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), CX + MOVQ 56(SP), R12 MOVQ ctx+16(FP), R14 SUBQ R12, 104(R14) JS error_not_enough_literals @@ -2596,50 +2638,49 @@ sequenceDecs_decodeSync_bmi2_after_adjust: JNZ sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch sequenceDecs_decodeSync_bmi2_match_len_ofs_ok: - MOVQ 24(SP), CX - MOVQ 8(SP), R12 - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (CX)(R13*1), R14 + LEAQ 16(R12)(CX*1), R14 ADDQ R9, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ CX, CX - JZ check_offset - XORQ R14, R14 + MOVUPS (R10), X0 + MOVUPS X0, (R9) + CMPQ R12, $0x10 + JBE copy_1_end + MOVQ $0x00000010, R14 copy_1: MOVUPS (R10)(R14*1), X0 MOVUPS X0, (R9)(R14*1) ADDQ $0x10, R14 - CMPQ R14, CX + CMPQ R14, R12 JB copy_1 - ADDQ CX, R10 - ADDQ CX, R9 - ADDQ CX, R11 + +copy_1_end: + ADDQ R12, R10 + ADDQ R12, R9 + ADDQ R12, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVQ R11, CX - ADDQ 40(SP), CX - CMPQ R12, CX + MOVQ R11, R12 + ADDQ 72(SP), R12 + CMPQ R13, R12 JG error_match_off_too_big - CMPQ R12, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ R12, CX - SUBQ R11, CX + MOVQ R13, R12 + SUBQ R11, R12 JLS copy_match - MOVQ 48(SP), R14 - SUBQ CX, R14 - CMPQ R13, CX + MOVQ 80(SP), R14 + SUBQ R12, R14 + CMPQ CX, R12 JG copy_all_from_history - MOVQ R13, CX - SUBQ $0x10, CX + MOVQ CX, R12 + SUBQ $0x10, R12 JB copy_4_small copy_4_loop: @@ -2647,54 +2688,54 @@ copy_4_loop: MOVUPS X0, (R9) ADDQ $0x10, R14 ADDQ $0x10, R9 - SUBQ $0x10, CX + SUBQ $0x10, R12 JAE copy_4_loop - LEAQ 16(R14)(CX*1), R14 - LEAQ 16(R9)(CX*1), R9 + LEAQ 16(R14)(R12*1), R14 + LEAQ 16(R9)(R12*1), R9 MOVUPS -16(R14), X0 MOVUPS X0, -16(R9) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 - JMP copy_4_end + MOVWQZX (R14), R12 + MOVB 2(R14), R13 + MOVW R12, (R9) + MOVB R13, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_4_end copy_4_move_4through7: - MOVL (R14), CX - MOVL -4(R14)(R13*1), R12 - MOVL CX, (R9) - MOVL R12, -4(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVL (R14), R12 + MOVL -4(R14)(CX*1), R13 + MOVL R12, (R9) + MOVL R13, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), CX - MOVQ -8(R14)(R13*1), R12 - MOVQ CX, (R9) - MOVQ R12, -8(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVQ (R14), R12 + MOVQ -8(R14)(CX*1), R13 + MOVQ R12, (R9) + MOVQ R13, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 copy_4_end: - ADDQ R13, R11 + ADDQ CX, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ CX, R15 + MOVQ R12, R15 SUBQ $0x10, R15 JB copy_5_small @@ -2712,90 +2753,99 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(CX*1), BP + MOVB -1(R14)(R12*1), BP MOVB R15, (R9) - MOVB BP, -1(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVB BP, -1(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R9) - MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ R12, R14 + ADDQ R12, R9 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(CX*1), BP + MOVL -4(R14)(R12*1), BP MOVL R15, (R9) - MOVL BP, -4(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVL BP, -4(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(CX*1), BP + MOVQ -8(R14)(R12*1), BP MOVQ R15, (R9) - MOVQ BP, -8(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVQ BP, -8(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 copy_5_end: - ADDQ CX, R11 - SUBQ CX, R13 + ADDQ R12, R11 + SUBQ R12, CX // Copy match from the current buffer copy_match: - MOVQ R9, CX - SUBQ R12, CX + MOVQ R9, R12 + SUBQ R13, R12 // ml <= mo - CMPQ R13, R12 + CMPQ CX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R11 - MOVQ R9, R12 - ADDQ R13, R9 + ADDQ CX, R11 + MOVUPS (R12), X0 + MOVUPS X0, (R9) + CMPQ CX, $0x10 + JA copy_2_long + ADDQ CX, R9 + JMP handle_loop + +copy_2_long: + LEAQ 16(R9), R13 + ADDQ CX, R9 + ADDQ $0x10, R12 + SUBQ $0x10, CX copy_2: - MOVUPS (CX), X0 - MOVUPS X0, (R12) - ADDQ $0x10, CX + MOVUPS (R12), X0 + MOVUPS X0, (R13) ADDQ $0x10, R12 - SUBQ $0x10, R13 + ADDQ $0x10, R13 + SUBQ $0x10, CX JHI copy_2 JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R11 + ADDQ CX, R11 copy_slow_3: - MOVB (CX), R12 - MOVB R12, (R9) - INCQ CX - INCQ R9 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R12), R13 + MOVB R13, (R9) + INCQ R12 + INCQ R9 + DECQ CX + JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_bmi2_main_loop loop_finished: @@ -2804,6 +2854,13 @@ loop_finished: MOVB DL, 40(CX) MOVQ BX, 32(CX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R11, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R11, 136(AX) @@ -2817,7 +2874,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -2826,7 +2883,7 @@ sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_bmi2_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -2834,7 +2891,7 @@ sequenceDecs_decodeSync_bmi2_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R11, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -2843,7 +2900,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -2856,9 +2913,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R11, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -2866,7 +2923,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $96-32 MOVQ br+8(FP), CX MOVQ 24(CX), DX MOVBQZX 40(CX), BX @@ -2878,26 +2935,34 @@ TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 MOVQ 72(AX), DI MOVQ 80(AX), R8 MOVQ 88(AX), R9 - XORQ CX, CX + MOVQ (AX), CX MOVQ CX, 8(SP) + MOVQ 24(AX), CX MOVQ CX, 16(SP) + MOVQ 48(AX), CX MOVQ CX, 24(SP) + MOVQ 96(AX), CX + MOVQ CX, 32(SP) + XORQ CX, CX + MOVQ CX, 40(SP) + MOVQ CX, 48(SP) + MOVQ CX, 56(SP) MOVQ 112(AX), R10 MOVQ 128(AX), CX - MOVQ CX, 32(SP) + MOVQ CX, 64(SP) MOVQ 144(AX), R11 MOVQ 136(AX), R12 MOVQ 200(AX), CX - MOVQ CX, 56(SP) + MOVQ CX, 88(SP) MOVQ 176(AX), CX - MOVQ CX, 48(SP) + MOVQ CX, 80(SP) MOVQ 184(AX), AX - MOVQ AX, 40(SP) - MOVQ 40(SP), AX - ADDQ AX, 48(SP) + MOVQ AX, 72(SP) + MOVQ 72(SP), AX + ADDQ AX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R10, 32(SP) + ADDQ R10, 64(SP) // outBase += outPosition ADDQ R12, R10 @@ -2935,46 +3000,32 @@ sequenceDecs_decodeSync_safe_amd64_fill_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_end: // Update offset - MOVQ R9, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_of_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_of_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_of_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_of_update_zero: - MOVQ AX, 8(SP) + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 40(SP) // Update match length - MOVQ R8, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ml_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ml_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ml_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_ml_update_zero: - MOVQ AX, 16(SP) + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ SI, $0x08 @@ -3006,96 +3057,82 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_2_end: // Update literal length - MOVQ DI, AX - MOVQ BX, CX - MOVQ DX, R14 - SHLQ CL, R14 - MOVB AH, CL - SHRQ $0x20, AX - TESTQ CX, CX - JZ sequenceDecs_decodeSync_safe_amd64_ll_update_zero - ADDQ CX, BX - CMPQ BX, $0x40 - JA sequenceDecs_decodeSync_safe_amd64_ll_update_zero - CMPQ CX, $0x40 - JAE sequenceDecs_decodeSync_safe_amd64_ll_update_zero - NEGQ CX - SHRQ CL, R14 - ADDQ R14, AX - -sequenceDecs_decodeSync_safe_amd64_ll_update_zero: - MOVQ AX, 24(SP) + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + MOVBLZX AH, CX + SHRQ $0x20, AX + ADDQ CX, BX + XORQ $0x3f, CX + SHRQ CL, R14 + ADDQ R14, AX + MOVQ AX, 56(SP) // Fill bitreader for state updates MOVQ R13, (SP) MOVQ R9, AX SHRQ $0x08, AX MOVBQZX AL, AX - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_safe_amd64_skip_update // Update Literal Length State MOVBQZX DI, R13 SHRL $0x10, DI - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, DI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(DI*8), DI // Update Match Length State MOVBQZX R8, R13 SHRL $0x10, R8 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R8 // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(R8*8), R8 // Update Offset State MOVBQZX R9, R13 SHRL $0x10, R9 - LEAQ (BX)(R13*1), CX + MOVQ BX, CX MOVQ DX, R14 - MOVQ CX, BX - ROLQ CL, R14 - MOVL $0x00000001, R15 - MOVB R13, CL - SHLL CL, R15 - DECL R15 - ANDQ R15, R14 + SHLQ CL, R14 + SHRQ $0x01, R14 + ADDQ R13, BX + XORQ $0x3f, R13 + MOVQ R13, CX + SHRQ CL, R14 ADDQ R14, R9 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R9*8), R9 sequenceDecs_decodeSync_safe_amd64_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ AX, $0x01 JBE sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -3104,7 +3141,7 @@ sequenceDecs_decodeSync_safe_amd64_skip_update: JMP sequenceDecs_decodeSync_safe_amd64_after_adjust sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero @@ -3139,14 +3176,11 @@ sequenceDecs_decodeSync_safe_amd64_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_safe_amd64_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), AX - MOVQ 24(SP), CX - LEAQ (AX)(CX*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), AX + MOVQ 56(SP), CX MOVQ ctx+16(FP), R14 SUBQ CX, 104(R14) JS error_not_enough_literals @@ -3158,20 +3192,16 @@ sequenceDecs_decodeSync_safe_amd64_after_adjust: JNZ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: - MOVQ 24(SP), AX - MOVQ 8(SP), CX - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (AX)(R13*1), R14 + LEAQ (CX)(AX*1), R14 ADDQ R10, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ AX, AX + TESTQ CX, CX JZ check_offset - MOVQ AX, R14 + MOVQ CX, R14 SUBQ $0x10, R14 JB copy_1_small @@ -3189,70 +3219,70 @@ copy_1_loop: JMP copy_1_end copy_1_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_1_move_3 JB copy_1_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: MOVB (R11), R14 - MOVB -1(R11)(AX*1), R15 + MOVB -1(R11)(CX*1), R15 MOVB R14, (R10) - MOVB R15, -1(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVB R15, -1(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 JMP copy_1_end copy_1_move_3: - MOVW (R11), R14 - MOVB 2(R11), R15 - MOVW R14, (R10) - MOVB R15, 2(R10) - ADDQ AX, R11 - ADDQ AX, R10 - JMP copy_1_end + MOVWQZX (R11), R14 + MOVB 2(R11), R15 + MOVW R14, (R10) + MOVB R15, 2(R10) + ADDQ CX, R11 + ADDQ CX, R10 + JMP copy_1_end copy_1_move_4through7: MOVL (R11), R14 - MOVL -4(R11)(AX*1), R15 + MOVL -4(R11)(CX*1), R15 MOVL R14, (R10) - MOVL R15, -4(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVL R15, -4(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 JMP copy_1_end copy_1_move_8through16: MOVQ (R11), R14 - MOVQ -8(R11)(AX*1), R15 + MOVQ -8(R11)(CX*1), R15 MOVQ R14, (R10) - MOVQ R15, -8(R10)(AX*1) - ADDQ AX, R11 - ADDQ AX, R10 + MOVQ R15, -8(R10)(CX*1) + ADDQ CX, R11 + ADDQ CX, R10 copy_1_end: - ADDQ AX, R12 + ADDQ CX, R12 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVQ R12, AX - ADDQ 40(SP), AX - CMPQ CX, AX + MOVQ R12, CX + ADDQ 72(SP), CX + CMPQ R13, CX JG error_match_off_too_big - CMPQ CX, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ CX, AX - SUBQ R12, AX + MOVQ R13, CX + SUBQ R12, CX JLS copy_match - MOVQ 48(SP), R14 - SUBQ AX, R14 - CMPQ R13, AX + MOVQ 80(SP), R14 + SUBQ CX, R14 + CMPQ AX, CX JG copy_all_from_history - MOVQ R13, AX - SUBQ $0x10, AX + MOVQ AX, CX + SUBQ $0x10, CX JB copy_4_small copy_4_loop: @@ -3260,54 +3290,54 @@ copy_4_loop: MOVUPS X0, (R10) ADDQ $0x10, R14 ADDQ $0x10, R10 - SUBQ $0x10, AX + SUBQ $0x10, CX JAE copy_4_loop - LEAQ 16(R14)(AX*1), R14 - LEAQ 16(R10)(AX*1), R10 + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R10)(CX*1), R10 MOVUPS -16(R14), X0 MOVUPS X0, -16(R10) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), AX - MOVB 2(R14), CL - MOVW AX, (R10) - MOVB CL, 2(R10) - ADDQ R13, R14 - ADDQ R13, R10 - JMP copy_4_end + MOVWQZX (R14), CX + MOVB 2(R14), R13 + MOVW CX, (R10) + MOVB R13, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_4_end copy_4_move_4through7: - MOVL (R14), AX - MOVL -4(R14)(R13*1), CX - MOVL AX, (R10) - MOVL CX, -4(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVL (R14), CX + MOVL -4(R14)(AX*1), R13 + MOVL CX, (R10) + MOVL R13, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), AX - MOVQ -8(R14)(R13*1), CX - MOVQ AX, (R10) - MOVQ CX, -8(R10)(R13*1) - ADDQ R13, R14 - ADDQ R13, R10 + MOVQ (R14), CX + MOVQ -8(R14)(AX*1), R13 + MOVQ CX, (R10) + MOVQ R13, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 copy_4_end: - ADDQ R13, R12 + ADDQ AX, R12 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ AX, R15 + MOVQ CX, R15 SUBQ $0x10, R15 JB copy_5_small @@ -3325,141 +3355,140 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ AX, $0x03 + CMPQ CX, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ AX, $0x08 + CMPQ CX, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(AX*1), BP + MOVB -1(R14)(CX*1), BP MOVB R15, (R10) - MOVB BP, -1(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVB BP, -1(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R10) - MOVB BP, 2(R10) - ADDQ AX, R14 - ADDQ AX, R10 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ CX, R14 + ADDQ CX, R10 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(AX*1), BP + MOVL -4(R14)(CX*1), BP MOVL R15, (R10) - MOVL BP, -4(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVL BP, -4(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(AX*1), BP + MOVQ -8(R14)(CX*1), BP MOVQ R15, (R10) - MOVQ BP, -8(R10)(AX*1) - ADDQ AX, R14 - ADDQ AX, R10 + MOVQ BP, -8(R10)(CX*1) + ADDQ CX, R14 + ADDQ CX, R10 copy_5_end: - ADDQ AX, R12 - SUBQ AX, R13 + ADDQ CX, R12 + SUBQ CX, AX // Copy match from the current buffer copy_match: - MOVQ R10, AX - SUBQ CX, AX + MOVQ R10, CX + SUBQ R13, CX // ml <= mo - CMPQ R13, CX + CMPQ AX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R12 - MOVQ R13, CX - SUBQ $0x10, CX + ADDQ AX, R12 + MOVQ AX, R13 + SUBQ $0x10, R13 JB copy_2_small copy_2_loop: - MOVUPS (AX), X0 + MOVUPS (CX), X0 MOVUPS X0, (R10) - ADDQ $0x10, AX + ADDQ $0x10, CX ADDQ $0x10, R10 - SUBQ $0x10, CX + SUBQ $0x10, R13 JAE copy_2_loop - LEAQ 16(AX)(CX*1), AX - LEAQ 16(R10)(CX*1), R10 - MOVUPS -16(AX), X0 + LEAQ 16(CX)(R13*1), CX + LEAQ 16(R10)(R13*1), R10 + MOVUPS -16(CX), X0 MOVUPS X0, -16(R10) JMP copy_2_end copy_2_small: - CMPQ R13, $0x03 + CMPQ AX, $0x03 JE copy_2_move_3 JB copy_2_move_1or2 - CMPQ R13, $0x08 + CMPQ AX, $0x08 JB copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (AX), CL - MOVB -1(AX)(R13*1), R14 - MOVB CL, (R10) - MOVB R14, -1(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVB (CX), R13 + MOVB -1(CX)(AX*1), R14 + MOVB R13, (R10) + MOVB R14, -1(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 JMP copy_2_end copy_2_move_3: - MOVW (AX), CX - MOVB 2(AX), R14 - MOVW CX, (R10) - MOVB R14, 2(R10) - ADDQ R13, AX - ADDQ R13, R10 - JMP copy_2_end + MOVWQZX (CX), R13 + MOVB 2(CX), R14 + MOVW R13, (R10) + MOVB R14, 2(R10) + ADDQ AX, CX + ADDQ AX, R10 + JMP copy_2_end copy_2_move_4through7: - MOVL (AX), CX - MOVL -4(AX)(R13*1), R14 - MOVL CX, (R10) - MOVL R14, -4(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVL (CX), R13 + MOVL -4(CX)(AX*1), R14 + MOVL R13, (R10) + MOVL R14, -4(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 JMP copy_2_end copy_2_move_8through16: - MOVQ (AX), CX - MOVQ -8(AX)(R13*1), R14 - MOVQ CX, (R10) - MOVQ R14, -8(R10)(R13*1) - ADDQ R13, AX - ADDQ R13, R10 + MOVQ (CX), R13 + MOVQ -8(CX)(AX*1), R14 + MOVQ R13, (R10) + MOVQ R14, -8(R10)(AX*1) + ADDQ AX, CX + ADDQ AX, R10 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R12 + ADDQ AX, R12 copy_slow_3: - MOVB (AX), CL - MOVB CL, (R10) - INCQ AX - INCQ R10 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (CX), R13 + MOVB R13, (R10) + INCQ CX + INCQ R10 + DECQ AX + JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), AX - DECQ 96(AX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_safe_amd64_main_loop loop_finished: @@ -3468,6 +3497,13 @@ loop_finished: MOVB BL, 40(AX) MOVQ SI, 32(AX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R12, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R12, 136(AX) @@ -3481,7 +3517,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -3490,7 +3526,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -3498,7 +3534,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R12, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -3507,7 +3543,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -3520,9 +3556,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R12, 136(AX) MOVQ $0x00000005, ret+24(FP) @@ -3530,7 +3566,7 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: BMI, BMI2, CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $96-32 MOVQ br+8(FP), BX MOVQ 24(BX), AX MOVBQZX 40(BX), DX @@ -3542,26 +3578,34 @@ TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 MOVQ 72(CX), SI MOVQ 80(CX), DI MOVQ 88(CX), R8 - XORQ R9, R9 + MOVQ (CX), R9 MOVQ R9, 8(SP) + MOVQ 24(CX), R9 MOVQ R9, 16(SP) + MOVQ 48(CX), R9 MOVQ R9, 24(SP) + MOVQ 96(CX), R9 + MOVQ R9, 32(SP) + XORQ R9, R9 + MOVQ R9, 40(SP) + MOVQ R9, 48(SP) + MOVQ R9, 56(SP) MOVQ 112(CX), R9 MOVQ 128(CX), R10 - MOVQ R10, 32(SP) + MOVQ R10, 64(SP) MOVQ 144(CX), R10 MOVQ 136(CX), R11 MOVQ 200(CX), R12 - MOVQ R12, 56(SP) + MOVQ R12, 88(SP) MOVQ 176(CX), R12 - MOVQ R12, 48(SP) + MOVQ R12, 80(SP) MOVQ 184(CX), CX - MOVQ CX, 40(SP) - MOVQ 40(SP), CX - ADDQ CX, 48(SP) + MOVQ CX, 72(SP) + MOVQ 72(SP), CX + ADDQ CX, 80(SP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - ADDQ R9, 32(SP) + ADDQ R9, 64(SP) // outBase += outPosition ADDQ R11, R9 @@ -3609,7 +3653,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_end: MOVQ R8, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 8(SP) + MOVQ CX, 40(SP) // Update match length MOVQ $0x00000808, CX @@ -3622,7 +3666,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_end: MOVQ DI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 16(SP) + MOVQ CX, 48(SP) // Fill bitreader to have enough for the remaining CMPQ BX, $0x08 @@ -3664,14 +3708,13 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: MOVQ SI, CX SHRQ $0x20, CX ADDQ R14, CX - MOVQ CX, 24(SP) + MOVQ CX, 56(SP) // Fill bitreader for state updates MOVQ R12, (SP) MOVQ $0x00000808, CX BEXTRQ CX, R8, R12 - MOVQ ctx+16(FP), CX - CMPQ 96(CX), $0x00 + CMPQ 32(SP), $0x00 JZ sequenceDecs_decodeSync_safe_bmi2_skip_update LEAQ (SI)(DI*1), R13 ADDQ R8, R13 @@ -3689,8 +3732,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, R8 // Load ctx.ofTable - MOVQ ctx+16(FP), CX - MOVQ 48(CX), CX + MOVQ 24(SP), CX MOVQ (CX)(R8*8), R8 // Update Match Length State @@ -3700,8 +3742,7 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, DI // Load ctx.mlTable - MOVQ ctx+16(FP), CX - MOVQ 24(CX), CX + MOVQ 16(SP), CX MOVQ (CX)(DI*8), DI // Update Literal Length State @@ -3710,14 +3751,13 @@ sequenceDecs_decodeSync_safe_bmi2_fill_2_end: ADDQ CX, SI // Load ctx.llTable - MOVQ ctx+16(FP), CX - MOVQ (CX), CX + MOVQ 8(SP), CX MOVQ (CX)(SI*8), SI sequenceDecs_decodeSync_safe_bmi2_skip_update: // Adjust offset MOVQ s+0(FP), CX - MOVQ 8(SP), R13 + MOVQ 40(SP), R13 CMPQ R12, $0x01 JBE sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0 MOVUPS 144(CX), X0 @@ -3726,7 +3766,7 @@ sequenceDecs_decodeSync_safe_bmi2_skip_update: JMP sequenceDecs_decodeSync_safe_bmi2_after_adjust sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0: - CMPQ 24(SP), $0x00000000 + CMPQ 56(SP), $0x00000000 JNE sequenceDecs_decodeSync_safe_bmi2_adjust_offset_maybezero INCQ R13 JMP sequenceDecs_decodeSync_safe_bmi2_adjust_offset_nonzero @@ -3761,14 +3801,11 @@ sequenceDecs_decodeSync_safe_bmi2_adjust_skip: MOVQ R14, R13 sequenceDecs_decodeSync_safe_bmi2_after_adjust: - MOVQ R13, 8(SP) + MOVQ R13, 40(SP) // Check values - MOVQ 16(SP), CX - MOVQ 24(SP), R12 - LEAQ (CX)(R12*1), R14 - MOVQ s+0(FP), R15 - ADDQ R14, 256(R15) + MOVQ 48(SP), CX + MOVQ 56(SP), R12 MOVQ ctx+16(FP), R14 SUBQ R12, 104(R14) JS error_not_enough_literals @@ -3780,20 +3817,16 @@ sequenceDecs_decodeSync_safe_bmi2_after_adjust: JNZ sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_bmi2_match_len_ofs_ok: - MOVQ 24(SP), CX - MOVQ 8(SP), R12 - MOVQ 16(SP), R13 - // Check if we have enough space in s.out - LEAQ (CX)(R13*1), R14 + LEAQ (R12)(CX*1), R14 ADDQ R9, R14 - CMPQ R14, 32(SP) + CMPQ R14, 64(SP) JA error_not_enough_space // Copy literals - TESTQ CX, CX + TESTQ R12, R12 JZ check_offset - MOVQ CX, R14 + MOVQ R12, R14 SUBQ $0x10, R14 JB copy_1_small @@ -3811,70 +3844,70 @@ copy_1_loop: JMP copy_1_end copy_1_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_1_move_3 JB copy_1_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: MOVB (R10), R14 - MOVB -1(R10)(CX*1), R15 + MOVB -1(R10)(R12*1), R15 MOVB R14, (R9) - MOVB R15, -1(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVB R15, -1(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 JMP copy_1_end copy_1_move_3: - MOVW (R10), R14 - MOVB 2(R10), R15 - MOVW R14, (R9) - MOVB R15, 2(R9) - ADDQ CX, R10 - ADDQ CX, R9 - JMP copy_1_end + MOVWQZX (R10), R14 + MOVB 2(R10), R15 + MOVW R14, (R9) + MOVB R15, 2(R9) + ADDQ R12, R10 + ADDQ R12, R9 + JMP copy_1_end copy_1_move_4through7: MOVL (R10), R14 - MOVL -4(R10)(CX*1), R15 + MOVL -4(R10)(R12*1), R15 MOVL R14, (R9) - MOVL R15, -4(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVL R15, -4(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 JMP copy_1_end copy_1_move_8through16: MOVQ (R10), R14 - MOVQ -8(R10)(CX*1), R15 + MOVQ -8(R10)(R12*1), R15 MOVQ R14, (R9) - MOVQ R15, -8(R9)(CX*1) - ADDQ CX, R10 - ADDQ CX, R9 + MOVQ R15, -8(R9)(R12*1) + ADDQ R12, R10 + ADDQ R12, R9 copy_1_end: - ADDQ CX, R11 + ADDQ R12, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVQ R11, CX - ADDQ 40(SP), CX - CMPQ R12, CX + MOVQ R11, R12 + ADDQ 72(SP), R12 + CMPQ R13, R12 JG error_match_off_too_big - CMPQ R12, 56(SP) + CMPQ R13, 88(SP) JG error_match_off_too_big // Copy match from history - MOVQ R12, CX - SUBQ R11, CX + MOVQ R13, R12 + SUBQ R11, R12 JLS copy_match - MOVQ 48(SP), R14 - SUBQ CX, R14 - CMPQ R13, CX + MOVQ 80(SP), R14 + SUBQ R12, R14 + CMPQ CX, R12 JG copy_all_from_history - MOVQ R13, CX - SUBQ $0x10, CX + MOVQ CX, R12 + SUBQ $0x10, R12 JB copy_4_small copy_4_loop: @@ -3882,54 +3915,54 @@ copy_4_loop: MOVUPS X0, (R9) ADDQ $0x10, R14 ADDQ $0x10, R9 - SUBQ $0x10, CX + SUBQ $0x10, R12 JAE copy_4_loop - LEAQ 16(R14)(CX*1), R14 - LEAQ 16(R9)(CX*1), R9 + LEAQ 16(R14)(R12*1), R14 + LEAQ 16(R9)(R12*1), R9 MOVUPS -16(R14), X0 MOVUPS X0, -16(R9) JMP copy_4_end copy_4_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_4_move_3 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVW (R14), CX - MOVB 2(R14), R12 - MOVW CX, (R9) - MOVB R12, 2(R9) - ADDQ R13, R14 - ADDQ R13, R9 - JMP copy_4_end + MOVWQZX (R14), R12 + MOVB 2(R14), R13 + MOVW R12, (R9) + MOVB R13, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_4_end copy_4_move_4through7: - MOVL (R14), CX - MOVL -4(R14)(R13*1), R12 - MOVL CX, (R9) - MOVL R12, -4(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVL (R14), R12 + MOVL -4(R14)(CX*1), R13 + MOVL R12, (R9) + MOVL R13, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 JMP copy_4_end copy_4_move_8through16: - MOVQ (R14), CX - MOVQ -8(R14)(R13*1), R12 - MOVQ CX, (R9) - MOVQ R12, -8(R9)(R13*1) - ADDQ R13, R14 - ADDQ R13, R9 + MOVQ (R14), R12 + MOVQ -8(R14)(CX*1), R13 + MOVQ R12, (R9) + MOVQ R13, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 copy_4_end: - ADDQ R13, R11 + ADDQ CX, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVQ CX, R15 + MOVQ R12, R15 SUBQ $0x10, R15 JB copy_5_small @@ -3947,141 +3980,140 @@ copy_5_loop: JMP copy_5_end copy_5_small: - CMPQ CX, $0x03 + CMPQ R12, $0x03 JE copy_5_move_3 JB copy_5_move_1or2 - CMPQ CX, $0x08 + CMPQ R12, $0x08 JB copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: MOVB (R14), R15 - MOVB -1(R14)(CX*1), BP + MOVB -1(R14)(R12*1), BP MOVB R15, (R9) - MOVB BP, -1(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVB BP, -1(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_3: - MOVW (R14), R15 - MOVB 2(R14), BP - MOVW R15, (R9) - MOVB BP, 2(R9) - ADDQ CX, R14 - ADDQ CX, R9 - JMP copy_5_end + MOVWQZX (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ R12, R14 + ADDQ R12, R9 + JMP copy_5_end copy_5_move_4through7: MOVL (R14), R15 - MOVL -4(R14)(CX*1), BP + MOVL -4(R14)(R12*1), BP MOVL R15, (R9) - MOVL BP, -4(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVL BP, -4(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 JMP copy_5_end copy_5_move_8through16: MOVQ (R14), R15 - MOVQ -8(R14)(CX*1), BP + MOVQ -8(R14)(R12*1), BP MOVQ R15, (R9) - MOVQ BP, -8(R9)(CX*1) - ADDQ CX, R14 - ADDQ CX, R9 + MOVQ BP, -8(R9)(R12*1) + ADDQ R12, R14 + ADDQ R12, R9 copy_5_end: - ADDQ CX, R11 - SUBQ CX, R13 + ADDQ R12, R11 + SUBQ R12, CX // Copy match from the current buffer copy_match: - MOVQ R9, CX - SUBQ R12, CX + MOVQ R9, R12 + SUBQ R13, R12 // ml <= mo - CMPQ R13, R12 + CMPQ CX, R13 JA copy_overlapping_match // Copy non-overlapping match - ADDQ R13, R11 - MOVQ R13, R12 - SUBQ $0x10, R12 + ADDQ CX, R11 + MOVQ CX, R13 + SUBQ $0x10, R13 JB copy_2_small copy_2_loop: - MOVUPS (CX), X0 + MOVUPS (R12), X0 MOVUPS X0, (R9) - ADDQ $0x10, CX + ADDQ $0x10, R12 ADDQ $0x10, R9 - SUBQ $0x10, R12 + SUBQ $0x10, R13 JAE copy_2_loop - LEAQ 16(CX)(R12*1), CX - LEAQ 16(R9)(R12*1), R9 - MOVUPS -16(CX), X0 + LEAQ 16(R12)(R13*1), R12 + LEAQ 16(R9)(R13*1), R9 + MOVUPS -16(R12), X0 MOVUPS X0, -16(R9) JMP copy_2_end copy_2_small: - CMPQ R13, $0x03 + CMPQ CX, $0x03 JE copy_2_move_3 JB copy_2_move_1or2 - CMPQ R13, $0x08 + CMPQ CX, $0x08 JB copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (CX), R12 - MOVB -1(CX)(R13*1), R14 - MOVB R12, (R9) - MOVB R14, -1(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVB (R12), R13 + MOVB -1(R12)(CX*1), R14 + MOVB R13, (R9) + MOVB R14, -1(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 JMP copy_2_end copy_2_move_3: - MOVW (CX), R12 - MOVB 2(CX), R14 - MOVW R12, (R9) - MOVB R14, 2(R9) - ADDQ R13, CX - ADDQ R13, R9 - JMP copy_2_end + MOVWQZX (R12), R13 + MOVB 2(R12), R14 + MOVW R13, (R9) + MOVB R14, 2(R9) + ADDQ CX, R12 + ADDQ CX, R9 + JMP copy_2_end copy_2_move_4through7: - MOVL (CX), R12 - MOVL -4(CX)(R13*1), R14 - MOVL R12, (R9) - MOVL R14, -4(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVL (R12), R13 + MOVL -4(R12)(CX*1), R14 + MOVL R13, (R9) + MOVL R14, -4(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 JMP copy_2_end copy_2_move_8through16: - MOVQ (CX), R12 - MOVQ -8(CX)(R13*1), R14 - MOVQ R12, (R9) - MOVQ R14, -8(R9)(R13*1) - ADDQ R13, CX - ADDQ R13, R9 + MOVQ (R12), R13 + MOVQ -8(R12)(CX*1), R14 + MOVQ R13, (R9) + MOVQ R14, -8(R9)(CX*1) + ADDQ CX, R12 + ADDQ CX, R9 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADDQ R13, R11 + ADDQ CX, R11 copy_slow_3: - MOVB (CX), R12 - MOVB R12, (R9) - INCQ CX - INCQ R9 - DECQ R13 - JNZ copy_slow_3 + MOVBQZX (R12), R13 + MOVB R13, (R9) + INCQ R12 + INCQ R9 + DECQ CX + JNZ copy_slow_3 handle_loop: - MOVQ ctx+16(FP), CX - DECQ 96(CX) + DECQ 32(SP) JNS sequenceDecs_decodeSync_safe_bmi2_main_loop loop_finished: @@ -4090,6 +4122,13 @@ loop_finished: MOVB DL, 40(CX) MOVQ BX, 32(CX) + // s.seqSize += outPosition - ctx.outPosition + MOVQ ctx+16(FP), AX + MOVQ s+0(FP), CX + MOVQ R11, DX + SUBQ 136(AX), DX + ADDQ DX, 256(CX) + // Update the context MOVQ ctx+16(FP), AX MOVQ R11, 136(AX) @@ -4103,7 +4142,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch: - MOVQ 16(SP), AX + MOVQ 48(SP), AX MOVQ ctx+16(FP), CX MOVQ AX, 216(CX) MOVQ $0x00000001, ret+24(FP) @@ -4112,7 +4151,7 @@ sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big: MOVQ ctx+16(FP), AX - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ $0x00000002, ret+24(FP) RET @@ -4120,7 +4159,7 @@ sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVQ ctx+16(FP), AX - MOVQ 8(SP), CX + MOVQ 40(SP), CX MOVQ CX, 224(AX) MOVQ R11, 136(AX) MOVQ $0x00000003, ret+24(FP) @@ -4129,7 +4168,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) MOVQ $0x00000004, ret+24(FP) RET @@ -4142,9 +4181,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVQ ctx+16(FP), AX - MOVQ 24(SP), CX + MOVQ 56(SP), CX MOVQ CX, 208(AX) - MOVQ 16(SP), CX + MOVQ 48(SP), CX MOVQ CX, 216(AX) MOVQ R11, 136(AX) MOVQ $0x00000005, ret+24(FP) diff --git a/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s b/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s index a468e5fc..56391bfc 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s +++ b/src/vendor/github.com/klauspost/compress/zstd/seqdec_arm64.s @@ -1,22 +1,30 @@ // Code generated by command: go run gen.go -out ../seqdec.s -arch amd64,arm64 -pkg=zstd. DO NOT EDIT. // EXPERIMENTAL arm64 output lowered from an amd64 avo program. -//go:build arm64 && !appengine && !noasm && gc && !noasm +//go:build arm64 && (!appengine && !noasm && gc && !noasm) // func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_arm64(SB), $8-32 +TEXT ·sequenceDecs_decode_arm64(SB), $40-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 MOVD (R1), R0 MOVD 32(R1), R5 ADD R5, R0, R0 - MOVD R0, (RSP) + MOVD R0, 8(RSP) MOVD ctx+16(FP), R0 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 + MOVD (R0), R1 + MOVD R1, 16(RSP) + MOVD 24(R0), R1 + MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) MOVD 104(R0), R9 MOVD s+0(FP), R0 MOVD 144(R0), R10 @@ -24,13 +32,12 @@ TEXT ·sequenceDecs_decode_arm64(SB), $8-32 MOVD 160(R0), R12 sequenceDecs_decode_amd64_main_loop: - MOVD (RSP), R13 + MOVD 8(RSP), R13 // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decode_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -57,51 +64,32 @@ sequenceDecs_decode_amd64_fill_check_overread: sequenceDecs_decode_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_of_update_zero: MOVD R0, 16(R9) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_ml_update_zero: MOVD R0, 8(R9) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decode_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -128,97 +116,64 @@ sequenceDecs_decode_amd64_fill_2_check_overread: sequenceDecs_decode_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates - MOVD R13, (RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decode_amd64_skip_update + MOVD R13, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD 40(RSP), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_amd64_skip_update // Update Literal Length State MOVBU R6, R13 LSRW $0x10, R6, R6 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD 16(RSP), R1 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 LSRW $0x10, R7, R7 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD 24(RSP), R1 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 LSRW $0x10, R8, R8 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD 32(RSP), R1 + MOVD (R1)(R8<<3), R8 sequenceDecs_decode_amd64_skip_update: // Adjust offset @@ -303,10 +258,9 @@ sequenceDecs_decode_amd64_after_adjust: sequenceDecs_decode_amd64_match_len_ofs_ok: ADD $0x18, R9, R9 - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decode_amd64_main_loop MOVD s+0(FP), R0 MOVD R10, 144(R0) @@ -318,53 +272,79 @@ sequenceDecs_decode_amd64_match_len_ofs_ok: MOVD R5, 32(R0) // Return success + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000000, R16 MOVD R16, ret+24(FP) RET // Return with match length error sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000001, R16 MOVD R16, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_amd64_error_match_len_too_big: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) RET // Return with match offset too long error + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000003, R16 MOVD R16, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) RET // Return with overread error error_overread: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000006, R16 MOVD R16, ret+24(FP) RET // func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int // Requires: CMOV -TEXT ·sequenceDecs_decode_56_arm64(SB), $8-32 +TEXT ·sequenceDecs_decode_56_arm64(SB), $40-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 MOVD (R1), R0 MOVD 32(R1), R5 ADD R5, R0, R0 - MOVD R0, (RSP) + MOVD R0, 8(RSP) MOVD ctx+16(FP), R0 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 + MOVD (R0), R1 + MOVD R1, 16(RSP) + MOVD 24(R0), R1 + MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) MOVD 104(R0), R9 MOVD s+0(FP), R0 MOVD 144(R0), R10 @@ -372,13 +352,12 @@ TEXT ·sequenceDecs_decode_56_arm64(SB), $8-32 MOVD 160(R0), R12 sequenceDecs_decode_56_amd64_main_loop: - MOVD (RSP), R13 + MOVD 8(RSP), R13 // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decode_56_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R13, R13 MOVD (R13), R2 SUB R0, R5, R5 @@ -405,139 +384,88 @@ sequenceDecs_decode_56_amd64_fill_check_overread: sequenceDecs_decode_56_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_of_update_zero: MOVD R0, 16(R9) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_ml_update_zero: MOVD R0, 8(R9) // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R14 - LSL R1, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decode_56_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decode_56_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decode_56_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R14, R14 ADD R14, R0, R0 - -sequenceDecs_decode_56_amd64_ll_update_zero: MOVD R0, (R9) // Fill bitreader for state updates - MOVD R13, (RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decode_56_amd64_skip_update + MOVD R13, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD 40(RSP), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decode_56_amd64_skip_update // Update Literal Length State MOVBU R6, R13 LSRW $0x10, R6, R6 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD 16(RSP), R1 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R13 LSRW $0x10, R7, R7 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD 24(RSP), R1 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R13 LSRW $0x10, R8, R8 - ADD R13, R3, R1 - MOVD R2, R14 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R14, R14 - MOVD $0x00000001, R4 - MOVB R13, R1 - LSLW R1, R4, R4 - SUBW $1, R4, R4 - AND R4, R14, R14 + LSL R3, R2, R14 + LSR $0x01, R14, R14 + ADD R13, R3, R3 + EOR $0x3f, R13, R13 + LSR R13, R14, R14 ADD R14, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD 32(RSP), R1 + MOVD (R1)(R8<<3), R8 sequenceDecs_decode_56_amd64_skip_update: // Adjust offset @@ -622,10 +550,9 @@ sequenceDecs_decode_56_amd64_after_adjust: sequenceDecs_decode_56_amd64_match_len_ofs_ok: ADD $0x18, R9, R9 - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decode_56_amd64_main_loop MOVD s+0(FP), R0 MOVD R10, 144(R0) @@ -637,35 +564,53 @@ sequenceDecs_decode_56_amd64_match_len_ofs_ok: MOVD R5, 32(R0) // Return success + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000000, R16 MOVD R16, ret+24(FP) RET // Return with match length error sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000001, R16 MOVD R16, ret+24(FP) RET // Return with match too long error sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) RET // Return with match offset too long error + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000003, R16 MOVD R16, ret+24(FP) RET // Return with not enough literals error error_not_enough_literals: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) RET // Return with overread error error_overread: + MOVD 40(RSP), R0 + MOVD ctx+16(FP), R1 + MOVD R0, 96(R1) MOVD $0x00000006, R16 MOVD R16, ret+24(FP) RET @@ -705,24 +650,27 @@ main_loop: MOVD 8(R0), R12 // Copy literals - TST R10, R10 - BEQ check_offset - MOVD $0, R13 + FMOVQ (R5), F0 + FMOVQ F0, (R3) + CMP $0x10, R10 + BLS copy_1_end + MOVD $0x00000010, R13 copy_1: - ADD R13, R5, R15 - VLD1 (R15), [V0.B16] - ADD R13, R3, R15 - VST1 [V0.B16], (R15) - ADD $0x10, R13, R13 - CMP R10, R13 - BLO copy_1 - ADD R10, R5, R5 - ADD R10, R3, R3 - ADD R10, R6, R6 + ADD R13, R5, R15 + FMOVQ (R15), F0 + ADD R13, R3, R15 + FMOVQ F0, (R15) + ADD $0x10, R13, R13 + CMP R10, R13 + BLO copy_1 + +copy_1_end: + ADD R10, R5, R5 + ADD R10, R3, R3 + ADD R10, R6, R6 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: ADD R9, R6, R10 CMP R10, R11 BGT error_match_off_too_big @@ -742,21 +690,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R10, R10 - BHS copy_4_loop - ADD R10, R13, R13 - ADD $16, R13, R13 - ADD R10, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -766,13 +712,14 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVH (R13), R10 - MOVB 2(R13), R11 - MOVH R10, (R3) - MOVB R11, 2(R3) - ADD R12, R13, R13 - ADD R12, R3, R3 - JMP copy_4_end + MOVHU (R13), R10 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R11 + MOVH R10, (R3) + MOVB R11, 2(R3) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end copy_4_move_4through7: MOVWU (R13), R10 @@ -809,21 +756,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_5_end copy_5_small: CMP $0x03, R10 @@ -834,24 +779,27 @@ copy_5_small: JMP copy_5_move_8through16 copy_5_move_1or2: - MOVB (R13), R14 - ADD R10, R13, R15 - MOVB -1(R15), R4 - MOVB R14, (R3) - ADD R10, R3, R15 - MOVB R4, -1(R15) - ADD R10, R13, R13 - ADD R10, R3, R3 - JMP copy_5_end + MOVBU (R13), R16 + BFI $0, R16, $8, R14 + ADD R10, R13, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R4 + MOVB R14, (R3) + ADD R10, R3, R15 + MOVB R4, -1(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end copy_5_move_3: - MOVH (R13), R14 - MOVB 2(R13), R4 - MOVH R14, (R3) - MOVB R4, 2(R3) - ADD R10, R13, R13 - ADD R10, R3, R3 - JMP copy_5_end + MOVHU (R13), R14 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R4 + MOVH R14, (R3) + MOVB R4, 2(R3) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 @@ -888,30 +836,40 @@ copy_match: BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R6, R6 - MOVD R3, R11 - ADD R12, R3, R3 + ADD R12, R6, R6 + FMOVQ (R10), F0 + FMOVQ F0, (R3) + CMP $0x10, R12 + BHI copy_2_long + ADD R12, R3, R3 + JMP handle_loop + +copy_2_long: + ADD $16, R3, R11 + ADD R12, R3, R3 + ADD $0x10, R10, R10 + SUB $0x10, R12, R12 copy_2: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R11) - ADD $0x10, R10, R10 - ADD $0x10, R11, R11 - SUBS $0x10, R12, R12 - BHI copy_2 - JMP handle_loop + FMOVQ (R10), F0 + FMOVQ F0, (R11) + ADD $0x10, R10, R10 + ADD $0x10, R11, R11 + SUBS $0x10, R12, R12 + BHI copy_2 + JMP handle_loop // Copy overlapping match copy_overlapping_match: ADD R12, R6, R6 copy_slow_3: - MOVB (R10), R11 - MOVB R11, (R3) - ADD $1, R10, R10 - ADD $1, R3, R3 - SUBS $1, R12, R12 - BNE copy_slow_3 + MOVBU (R10), R11 + MOVB R11, (R3) + ADD $1, R10, R10 + ADD $1, R3, R3 + SUBS $1, R12, R12 + BNE copy_slow_3 handle_loop: ADD $0x18, R0, R0 @@ -991,21 +949,19 @@ main_loop: BLO copy_1_small copy_1_loop: - VLD1 (R5), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R5, R5 - ADD $0x10, R3, R3 - SUBS $0x10, R13, R13 - BHS copy_1_loop - ADD R13, R5, R5 - ADD $16, R5, R5 - ADD R13, R3, R3 - ADD $16, R3, R3 - ADD $-16, R5, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_1_end + FMOVQ (R5), F0 + FMOVQ F0, (R3) + ADD $0x10, R5, R5 + ADD $0x10, R3, R3 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R5, R5 + ADD $16, R5, R5 + ADD R13, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R5), F0 + FMOVQ F0, -16(R3) + JMP copy_1_end copy_1_small: CMP $0x03, R10 @@ -1016,24 +972,27 @@ copy_1_small: JMP copy_1_move_8through16 copy_1_move_1or2: - MOVB (R5), R13 - ADD R10, R5, R15 - MOVB -1(R15), R14 - MOVB R13, (R3) - ADD R10, R3, R15 - MOVB R14, -1(R15) - ADD R10, R5, R5 - ADD R10, R3, R3 - JMP copy_1_end + MOVBU (R5), R16 + BFI $0, R16, $8, R13 + ADD R10, R5, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R14 + MOVB R13, (R3) + ADD R10, R3, R15 + MOVB R14, -1(R15) + ADD R10, R5, R5 + ADD R10, R3, R3 + JMP copy_1_end copy_1_move_3: - MOVH (R5), R13 - MOVB 2(R5), R14 - MOVH R13, (R3) - MOVB R14, 2(R3) - ADD R10, R5, R5 - ADD R10, R3, R3 - JMP copy_1_end + MOVHU (R5), R13 + MOVBU 2(R5), R16 + BFI $0, R16, $8, R14 + MOVH R13, (R3) + MOVB R14, 2(R3) + ADD R10, R5, R5 + ADD R10, R3, R3 + JMP copy_1_end copy_1_move_4through7: MOVWU (R5), R13 @@ -1080,21 +1039,19 @@ check_offset: BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R10, R10 - BHS copy_4_loop - ADD R10, R13, R13 - ADD $16, R13, R13 - ADD R10, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R10, R10 + BHS copy_4_loop + ADD R10, R13, R13 + ADD $16, R13, R13 + ADD R10, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_4_end copy_4_small: CMP $0x03, R12 @@ -1104,13 +1061,14 @@ copy_4_small: JMP copy_4_move_8through16 copy_4_move_3: - MOVH (R13), R10 - MOVB 2(R13), R11 - MOVH R10, (R3) - MOVB R11, 2(R3) - ADD R12, R13, R13 - ADD R12, R3, R3 - JMP copy_4_end + MOVHU (R13), R10 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R11 + MOVH R10, (R3) + MOVB R11, 2(R3) + ADD R12, R13, R13 + ADD R12, R3, R3 + JMP copy_4_end copy_4_move_4through7: MOVWU (R13), R10 @@ -1147,21 +1105,19 @@ copy_all_from_history: BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R13, R13 - ADD $0x10, R3, R3 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R3, R3 - ADD $16, R3, R3 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R3) + ADD $0x10, R13, R13 + ADD $0x10, R3, R3 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R3) + JMP copy_5_end copy_5_small: CMP $0x03, R10 @@ -1172,24 +1128,27 @@ copy_5_small: JMP copy_5_move_8through16 copy_5_move_1or2: - MOVB (R13), R14 - ADD R10, R13, R15 - MOVB -1(R15), R4 - MOVB R14, (R3) - ADD R10, R3, R15 - MOVB R4, -1(R15) - ADD R10, R13, R13 - ADD R10, R3, R3 - JMP copy_5_end + MOVBU (R13), R16 + BFI $0, R16, $8, R14 + ADD R10, R13, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R4 + MOVB R14, (R3) + ADD R10, R3, R15 + MOVB R4, -1(R15) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end copy_5_move_3: - MOVH (R13), R14 - MOVB 2(R13), R4 - MOVH R14, (R3) - MOVB R4, 2(R3) - ADD R10, R13, R13 - ADD R10, R3, R3 - JMP copy_5_end + MOVHU (R13), R14 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R4 + MOVH R14, (R3) + MOVB R4, 2(R3) + ADD R10, R13, R13 + ADD R10, R3, R3 + JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 @@ -1232,21 +1191,19 @@ copy_match: BLO copy_2_small copy_2_loop: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R3) - ADD $0x10, R10, R10 - ADD $0x10, R3, R3 - SUBS $0x10, R11, R11 - BHS copy_2_loop - ADD R11, R10, R10 - ADD $16, R10, R10 - ADD R11, R3, R3 - ADD $16, R3, R3 - ADD $-16, R10, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R3, R15 - VST1 [V0.B16], (R15) - JMP copy_2_end + FMOVQ (R10), F0 + FMOVQ F0, (R3) + ADD $0x10, R10, R10 + ADD $0x10, R3, R3 + SUBS $0x10, R11, R11 + BHS copy_2_loop + ADD R11, R10, R10 + ADD $16, R10, R10 + ADD R11, R3, R3 + ADD $16, R3, R3 + FMOVQ -16(R10), F0 + FMOVQ F0, -16(R3) + JMP copy_2_end copy_2_small: CMP $0x03, R12 @@ -1257,24 +1214,27 @@ copy_2_small: JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (R10), R11 - ADD R12, R10, R15 - MOVB -1(R15), R13 - MOVB R11, (R3) - ADD R12, R3, R15 - MOVB R13, -1(R15) - ADD R12, R10, R10 - ADD R12, R3, R3 - JMP copy_2_end + MOVBU (R10), R16 + BFI $0, R16, $8, R11 + ADD R12, R10, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R13 + MOVB R11, (R3) + ADD R12, R3, R15 + MOVB R13, -1(R15) + ADD R12, R10, R10 + ADD R12, R3, R3 + JMP copy_2_end copy_2_move_3: - MOVH (R10), R11 - MOVB 2(R10), R13 - MOVH R11, (R3) - MOVB R13, 2(R3) - ADD R12, R10, R10 - ADD R12, R3, R3 - JMP copy_2_end + MOVHU (R10), R11 + MOVBU 2(R10), R16 + BFI $0, R16, $8, R13 + MOVH R11, (R3) + MOVB R13, 2(R3) + ADD R12, R10, R10 + ADD R12, R3, R3 + JMP copy_2_end copy_2_move_4through7: MOVWU (R10), R11 @@ -1305,12 +1265,12 @@ copy_overlapping_match: ADD R12, R6, R6 copy_slow_3: - MOVB (R10), R11 - MOVB R11, (R3) - ADD $1, R10, R10 - ADD $1, R3, R3 - SUBS $1, R12, R12 - BNE copy_slow_3 + MOVBU (R10), R11 + MOVB R11, (R3) + ADD $1, R10, R10 + ADD $1, R3, R3 + SUBS $1, R12, R12 + BNE copy_slow_3 handle_loop: ADD $0x18, R0, R0 @@ -1354,54 +1314,61 @@ empty_seqs: // func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_arm64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_arm64(SB), $96-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 MOVD (R1), R0 MOVD 32(R1), R5 ADD R5, R0, R0 - MOVD R0, (RSP) + MOVD R0, 8(RSP) MOVD ctx+16(FP), R0 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 - MOVD $0, R1 - MOVD R1, 8(RSP) + MOVD (R0), R1 MOVD R1, 16(RSP) + MOVD 24(R0), R1 MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) + MOVD $0, R1 + MOVD R1, 48(RSP) + MOVD R1, 56(RSP) + MOVD R1, 64(RSP) MOVD 112(R0), R9 MOVD 128(R0), R1 - MOVD R1, 32(RSP) + MOVD R1, 72(RSP) MOVD 144(R0), R10 MOVD 136(R0), R11 MOVD 200(R0), R1 - MOVD R1, 56(RSP) + MOVD R1, 96(RSP) MOVD 176(R0), R1 - MOVD R1, 48(RSP) + MOVD R1, 88(RSP) MOVD 184(R0), R0 - MOVD R0, 40(RSP) - MOVD 40(RSP), R0 - MOVD 48(RSP), R16 + MOVD R0, 80(RSP) + MOVD 80(RSP), R0 + MOVD 88(RSP), R16 ADD R0, R16, R16 - MOVD R16, 48(RSP) + MOVD R16, 88(RSP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - MOVD 32(RSP), R16 + MOVD 72(RSP), R16 ADD R9, R16, R16 - MOVD R16, 32(RSP) + MOVD R16, 72(RSP) // outBase += outPosition ADD R11, R9, R9 sequenceDecs_decodeSync_amd64_main_loop: - MOVD (RSP), R12 + MOVD 8(RSP), R12 // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decodeSync_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -1428,51 +1395,32 @@ sequenceDecs_decodeSync_amd64_fill_check_overread: sequenceDecs_decodeSync_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_of_update_zero: - MOVD R0, 8(RSP) + MOVD R0, 48(RSP) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_ml_update_zero: - MOVD R0, 16(RSP) + MOVD R0, 56(RSP) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -1499,113 +1447,78 @@ sequenceDecs_decodeSync_amd64_fill_2_check_overread: sequenceDecs_decodeSync_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_amd64_ll_update_zero: - MOVD R0, 24(RSP) + MOVD R0, 64(RSP) // Fill bitreader for state updates - MOVD R12, (RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decodeSync_amd64_skip_update + MOVD R12, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD 40(RSP), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_amd64_skip_update // Update Literal Length State MOVBU R6, R12 LSRW $0x10, R6, R6 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD 16(RSP), R1 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 LSRW $0x10, R7, R7 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD 24(RSP), R1 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 LSRW $0x10, R8, R8 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD 32(RSP), R1 + MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_amd64_skip_update: // Adjust offset - MOVD s+0(FP), R1 - MOVD 8(RSP), R12 - CMP $0x01, R0 - BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 - ADD $144, R1, R15 - VLD1 (R15), [V0.B16] - MOVD R12, 144(R1) - ADD $152, R1, R15 - VST1 [V0.B16], (R15) - JMP sequenceDecs_decodeSync_amd64_after_adjust + MOVD s+0(FP), R1 + MOVD 48(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 + FMOVQ 144(R1), F0 + MOVD R12, 144(R1) + FMOVQ F0, 152(R1) + JMP sequenceDecs_decodeSync_amd64_after_adjust sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: - MOVD 24(RSP), R16 + MOVD 64(RSP), R16 CMP $0x00000000, R16 BNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero ADD $1, R12, R12 @@ -1643,16 +1556,11 @@ sequenceDecs_decodeSync_amd64_adjust_skip: MOVD R13, R12 sequenceDecs_decodeSync_amd64_after_adjust: - MOVD R12, 8(RSP) + MOVD R12, 48(RSP) // Check values - MOVD 16(RSP), R0 - MOVD 24(RSP), R1 - ADD R1, R0, R13 - MOVD s+0(FP), R14 - MOVD 256(R14), R16 - ADD R13, R16, R16 - MOVD R16, 256(R14) + MOVD 56(RSP), R0 + MOVD 64(RSP), R1 MOVD ctx+16(FP), R13 MOVD 104(R13), R16 SUBS R1, R16, R16 @@ -1666,231 +1574,240 @@ sequenceDecs_decodeSync_amd64_after_adjust: BNE sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_amd64_match_len_ofs_ok: - MOVD 24(RSP), R0 - MOVD 8(RSP), R1 - MOVD 16(RSP), R12 - // Check if we have enough space in s.out - ADD R12, R0, R13 + ADD R0, R1, R13 + ADD $16, R13, R13 ADD R9, R13, R13 - MOVD 32(RSP), R16 + MOVD 72(RSP), R16 CMP R16, R13 BHI error_not_enough_space // Copy literals - TST R0, R0 - BEQ check_offset - MOVD $0, R13 + FMOVQ (R10), F0 + FMOVQ F0, (R9) + CMP $0x10, R1 + BLS copy_1_end + MOVD $0x00000010, R13 copy_1: - ADD R13, R10, R15 - VLD1 (R15), [V0.B16] - ADD R13, R9, R15 - VST1 [V0.B16], (R15) - ADD $0x10, R13, R13 - CMP R0, R13 - BLO copy_1 - ADD R0, R10, R10 - ADD R0, R9, R9 - ADD R0, R11, R11 + ADD R13, R10, R15 + FMOVQ (R15), F0 + ADD R13, R9, R15 + FMOVQ F0, (R15) + ADD $0x10, R13, R13 + CMP R1, R13 + BLO copy_1 + +copy_1_end: + ADD R1, R10, R10 + ADD R1, R9, R9 + ADD R1, R11, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) -check_offset: - MOVD R11, R0 - MOVD 40(RSP), R16 - ADD R16, R0, R0 - CMP R0, R1 + MOVD R11, R1 + MOVD 80(RSP), R16 + ADD R16, R1, R1 + CMP R1, R12 BGT error_match_off_too_big - MOVD 56(RSP), R16 - CMP R16, R1 + MOVD 96(RSP), R16 + CMP R16, R12 BGT error_match_off_too_big // Copy match from history - MOVD R1, R0 - SUBS R11, R0, R0 + MOVD R12, R1 + SUBS R11, R1, R1 BLS copy_match - MOVD 48(RSP), R13 - SUB R0, R13, R13 - CMP R0, R12 + MOVD 88(RSP), R13 + SUB R1, R13, R13 + CMP R1, R0 BGT copy_all_from_history - MOVD R12, R0 - SUBS $0x10, R0, R0 + MOVD R0, R1 + SUBS $0x10, R1, R1 BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 - BHS copy_4_loop - ADD R0, R13, R13 - ADD $16, R13, R13 - ADD R0, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R1, R1 + BHS copy_4_loop + ADD R1, R13, R13 + ADD $16, R13, R13 + ADD R1, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_4_end copy_4_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_4_move_3 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVH (R13), R0 - MOVB 2(R13), R1 - MOVH R0, (R9) - MOVB R1, 2(R9) - ADD R12, R13, R13 - ADD R12, R9, R9 - JMP copy_4_end + MOVHU (R13), R1 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R12 + MOVH R1, (R9) + MOVB R12, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_4_end copy_4_move_4through7: - MOVWU (R13), R0 - ADD R12, R13, R15 - MOVWU -4(R15), R1 - MOVW R0, (R9) - ADD R12, R9, R15 - MOVW R1, -4(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVWU (R13), R1 + ADD R0, R13, R15 + MOVWU -4(R15), R12 + MOVW R1, (R9) + ADD R0, R9, R15 + MOVW R12, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_8through16: - MOVD (R13), R0 - ADD R12, R13, R15 - MOVD -8(R15), R1 - MOVD R0, (R9) - ADD R12, R9, R15 - MOVD R1, -8(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVD (R13), R1 + ADD R0, R13, R15 + MOVD -8(R15), R12 + MOVD R1, (R9) + ADD R0, R9, R15 + MOVD R12, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 copy_4_end: - ADD R12, R11, R11 + ADD R0, R11, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVD R0, R14 + MOVD R1, R14 SUBS $0x10, R14, R14 BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_5_end copy_5_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_5_move_3 BLO copy_5_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: - MOVB (R13), R14 - ADD R0, R13, R15 - MOVB -1(R15), R4 - MOVB R14, (R9) - ADD R0, R9, R15 - MOVB R4, -1(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 - JMP copy_5_end + MOVBU (R13), R16 + BFI $0, R16, $8, R14 + ADD R1, R13, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R4 + MOVB R14, (R9) + ADD R1, R9, R15 + MOVB R4, -1(R15) + ADD R1, R13, R13 + ADD R1, R9, R9 + JMP copy_5_end copy_5_move_3: - MOVH (R13), R14 - MOVB 2(R13), R4 - MOVH R14, (R9) - MOVB R4, 2(R9) - ADD R0, R13, R13 - ADD R0, R9, R9 - JMP copy_5_end + MOVHU (R13), R14 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R4 + MOVH R14, (R9) + MOVB R4, 2(R9) + ADD R1, R13, R13 + ADD R1, R9, R9 + JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVWU -4(R15), R4 MOVW R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R4, -4(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_8through16: MOVD (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVD -8(R15), R4 MOVD R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R4, -8(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 copy_5_end: - ADD R0, R11, R11 - SUB R0, R12, R12 + ADD R1, R11, R11 + SUB R1, R0, R0 // Copy match from the current buffer copy_match: - MOVD R9, R0 - SUB R1, R0, R0 + MOVD R9, R1 + SUB R12, R1, R1 // ml <= mo - CMP R1, R12 + CMP R12, R0 BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R11, R11 - MOVD R9, R1 - ADD R12, R9, R9 + ADD R0, R11, R11 + FMOVQ (R1), F0 + FMOVQ F0, (R9) + CMP $0x10, R0 + BHI copy_2_long + ADD R0, R9, R9 + JMP handle_loop + +copy_2_long: + ADD $16, R9, R12 + ADD R0, R9, R9 + ADD $0x10, R1, R1 + SUB $0x10, R0, R0 copy_2: - VLD1 (R0), [V0.B16] - VST1 [V0.B16], (R1) - ADD $0x10, R0, R0 - ADD $0x10, R1, R1 - SUBS $0x10, R12, R12 - BHI copy_2 - JMP handle_loop + FMOVQ (R1), F0 + FMOVQ F0, (R12) + ADD $0x10, R1, R1 + ADD $0x10, R12, R12 + SUBS $0x10, R0, R0 + BHI copy_2 + JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADD R12, R11, R11 + ADD R0, R11, R11 copy_slow_3: - MOVB (R0), R1 - MOVB R1, (R9) - ADD $1, R0, R0 - ADD $1, R9, R9 - SUBS $1, R12, R12 - BNE copy_slow_3 + MOVBU (R1), R12 + MOVB R12, (R9) + ADD $1, R1, R1 + ADD $1, R9, R9 + SUBS $1, R0, R0 + BNE copy_slow_3 handle_loop: - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decodeSync_amd64_main_loop loop_finished: @@ -1899,6 +1816,16 @@ loop_finished: MOVB R3, 40(R0) MOVD R5, 32(R0) + // s.seqSize += outPosition - ctx.outPosition + MOVD ctx+16(FP), R0 + MOVD s+0(FP), R1 + MOVD R11, R2 + MOVD 136(R0), R16 + SUB R16, R2, R2 + MOVD 256(R1), R16 + ADD R2, R16, R16 + MOVD R16, 256(R1) + // Update the context MOVD ctx+16(FP), R0 MOVD R11, 136(R0) @@ -1913,7 +1840,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: - MOVD 16(RSP), R0 + MOVD 56(RSP), R0 MOVD ctx+16(FP), R1 MOVD R0, 216(R1) MOVD $0x00000001, R16 @@ -1923,7 +1850,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_amd64_error_match_len_too_big: MOVD ctx+16(FP), R0 - MOVD 16(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) @@ -1932,7 +1859,7 @@ sequenceDecs_decodeSync_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVD ctx+16(FP), R0 - MOVD 8(RSP), R1 + MOVD 48(RSP), R1 MOVD R1, 224(R0) MOVD R11, 136(R0) MOVD $0x00000003, R16 @@ -1942,7 +1869,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) @@ -1957,9 +1884,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) - MOVD 16(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD R11, 136(R0) MOVD $0x00000005, R16 @@ -1970,54 +1897,61 @@ error_not_enough_space: // func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int // Requires: CMOV, SSE -TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $64-32 +TEXT ·sequenceDecs_decodeSync_safe_arm64(SB), $96-32 MOVD br+8(FP), R1 MOVD 24(R1), R2 MOVBU 40(R1), R3 MOVD (R1), R0 MOVD 32(R1), R5 ADD R5, R0, R0 - MOVD R0, (RSP) + MOVD R0, 8(RSP) MOVD ctx+16(FP), R0 MOVD 72(R0), R6 MOVD 80(R0), R7 MOVD 88(R0), R8 - MOVD $0, R1 - MOVD R1, 8(RSP) + MOVD (R0), R1 MOVD R1, 16(RSP) + MOVD 24(R0), R1 MOVD R1, 24(RSP) + MOVD 48(R0), R1 + MOVD R1, 32(RSP) + MOVD 96(R0), R1 + MOVD R1, 40(RSP) + MOVD $0, R1 + MOVD R1, 48(RSP) + MOVD R1, 56(RSP) + MOVD R1, 64(RSP) MOVD 112(R0), R9 MOVD 128(R0), R1 - MOVD R1, 32(RSP) + MOVD R1, 72(RSP) MOVD 144(R0), R10 MOVD 136(R0), R11 MOVD 200(R0), R1 - MOVD R1, 56(RSP) + MOVD R1, 96(RSP) MOVD 176(R0), R1 - MOVD R1, 48(RSP) + MOVD R1, 88(RSP) MOVD 184(R0), R0 - MOVD R0, 40(RSP) - MOVD 40(RSP), R0 - MOVD 48(RSP), R16 + MOVD R0, 80(RSP) + MOVD 80(RSP), R0 + MOVD 88(RSP), R16 ADD R0, R16, R16 - MOVD R16, 48(RSP) + MOVD R16, 88(RSP) // Calculate pointer to s.out[cap(s.out)] (a past-end pointer) - MOVD 32(RSP), R16 + MOVD 72(RSP), R16 ADD R9, R16, R16 - MOVD R16, 32(RSP) + MOVD R16, 72(RSP) // outBase += outPosition ADD R11, R9, R9 sequenceDecs_decodeSync_safe_amd64_main_loop: - MOVD (RSP), R12 + MOVD 8(RSP), R12 // Fill bitreader to have enough for the offset and match length. CMP $0x08, R5 BLT sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -2044,51 +1978,32 @@ sequenceDecs_decodeSync_safe_amd64_fill_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_end: // Update offset MOVD R8, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_of_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_of_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_of_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_of_update_zero: - MOVD R0, 8(RSP) + MOVD R0, 48(RSP) // Update match length MOVD R7, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_ml_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_ml_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_ml_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_ml_update_zero: - MOVD R0, 16(RSP) + MOVD R0, 56(RSP) // Fill bitreader to have enough for the remaining CMP $0x08, R5 BLT sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte - MOVD R3, R0 - LSR $0x03, R0, R0 + LSR $0x03, R3, R0 SUB R0, R12, R12 MOVD (R12), R2 SUB R0, R5, R5 @@ -2115,113 +2030,78 @@ sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: sequenceDecs_decodeSync_safe_amd64_fill_2_end: // Update literal length MOVD R6, R0 - MOVD R3, R1 - MOVD R2, R13 - LSL R1, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 UBFX $8, R0, $8, R1 LSR $0x20, R0, R0 - TST R1, R1 - BEQ sequenceDecs_decodeSync_safe_amd64_ll_update_zero ADD R1, R3, R3 - CMP $0x40, R3 - BHI sequenceDecs_decodeSync_safe_amd64_ll_update_zero - CMP $0x40, R1 - BHS sequenceDecs_decodeSync_safe_amd64_ll_update_zero - NEG R1, R1 + EOR $0x3f, R1, R1 LSR R1, R13, R13 ADD R13, R0, R0 - -sequenceDecs_decodeSync_safe_amd64_ll_update_zero: - MOVD R0, 24(RSP) + MOVD R0, 64(RSP) // Fill bitreader for state updates - MOVD R12, (RSP) - MOVD R8, R0 - LSR $0x08, R0, R0 - MOVBU R0, R0 - MOVD ctx+16(FP), R1 - MOVD 96(R1), R16 - CMP $0x00, R16 - BEQ sequenceDecs_decodeSync_safe_amd64_skip_update + MOVD R12, 8(RSP) + UBFX $8, R8, $8, R0 + MOVD 40(RSP), R16 + CMP $0x00, R16 + BEQ sequenceDecs_decodeSync_safe_amd64_skip_update // Update Literal Length State MOVBU R6, R12 LSRW $0x10, R6, R6 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R6, R6 // Load ctx.llTable - MOVD ctx+16(FP), R1 - MOVD (R1), R1 - ADD R6<<3, R1, R15 - MOVD (R15), R6 + MOVD 16(RSP), R1 + MOVD (R1)(R6<<3), R6 // Update Match Length State MOVBU R7, R12 LSRW $0x10, R7, R7 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R7, R7 // Load ctx.mlTable - MOVD ctx+16(FP), R1 - MOVD 24(R1), R1 - ADD R7<<3, R1, R15 - MOVD (R15), R7 + MOVD 24(RSP), R1 + MOVD (R1)(R7<<3), R7 // Update Offset State MOVBU R8, R12 LSRW $0x10, R8, R8 - ADD R12, R3, R1 - MOVD R2, R13 - MOVD R1, R3 - NEG R1, R16 - ROR R16, R13, R13 - MOVD $0x00000001, R14 - MOVB R12, R1 - LSLW R1, R14, R14 - SUBW $1, R14, R14 - AND R14, R13, R13 + LSL R3, R2, R13 + LSR $0x01, R13, R13 + ADD R12, R3, R3 + EOR $0x3f, R12, R12 + LSR R12, R13, R13 ADD R13, R8, R8 // Load ctx.ofTable - MOVD ctx+16(FP), R1 - MOVD 48(R1), R1 - ADD R8<<3, R1, R15 - MOVD (R15), R8 + MOVD 32(RSP), R1 + MOVD (R1)(R8<<3), R8 sequenceDecs_decodeSync_safe_amd64_skip_update: // Adjust offset - MOVD s+0(FP), R1 - MOVD 8(RSP), R12 - CMP $0x01, R0 - BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 - ADD $144, R1, R15 - VLD1 (R15), [V0.B16] - MOVD R12, 144(R1) - ADD $152, R1, R15 - VST1 [V0.B16], (R15) - JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + MOVD s+0(FP), R1 + MOVD 48(RSP), R12 + CMP $0x01, R0 + BLS sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 + FMOVQ 144(R1), F0 + MOVD R12, 144(R1) + FMOVQ F0, 152(R1) + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: - MOVD 24(RSP), R16 + MOVD 64(RSP), R16 CMP $0x00000000, R16 BNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero ADD $1, R12, R12 @@ -2259,16 +2139,11 @@ sequenceDecs_decodeSync_safe_amd64_adjust_skip: MOVD R13, R12 sequenceDecs_decodeSync_safe_amd64_after_adjust: - MOVD R12, 8(RSP) + MOVD R12, 48(RSP) // Check values - MOVD 16(RSP), R0 - MOVD 24(RSP), R1 - ADD R1, R0, R13 - MOVD s+0(FP), R14 - MOVD 256(R14), R16 - ADD R13, R16, R16 - MOVD R16, 256(R14) + MOVD 56(RSP), R0 + MOVD 64(RSP), R1 MOVD ctx+16(FP), R13 MOVD 104(R13), R16 SUBS R1, R16, R16 @@ -2282,351 +2157,348 @@ sequenceDecs_decodeSync_safe_amd64_after_adjust: BNE sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: - MOVD 24(RSP), R0 - MOVD 8(RSP), R1 - MOVD 16(RSP), R12 - // Check if we have enough space in s.out - ADD R12, R0, R13 + ADD R0, R1, R13 ADD R9, R13, R13 - MOVD 32(RSP), R16 + MOVD 72(RSP), R16 CMP R16, R13 BHI error_not_enough_space // Copy literals - TST R0, R0 + TST R1, R1 BEQ check_offset - MOVD R0, R13 + MOVD R1, R13 SUBS $0x10, R13, R13 BLO copy_1_small copy_1_loop: - VLD1 (R10), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R10, R10 - ADD $0x10, R9, R9 - SUBS $0x10, R13, R13 - BHS copy_1_loop - ADD R13, R10, R10 - ADD $16, R10, R10 - ADD R13, R9, R9 - ADD $16, R9, R9 - ADD $-16, R10, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_1_end + FMOVQ (R10), F0 + FMOVQ F0, (R9) + ADD $0x10, R10, R10 + ADD $0x10, R9, R9 + SUBS $0x10, R13, R13 + BHS copy_1_loop + ADD R13, R10, R10 + ADD $16, R10, R10 + ADD R13, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R10), F0 + FMOVQ F0, -16(R9) + JMP copy_1_end copy_1_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_1_move_3 BLO copy_1_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_1_move_4through7 JMP copy_1_move_8through16 copy_1_move_1or2: - MOVB (R10), R13 - ADD R0, R10, R15 - MOVB -1(R15), R14 - MOVB R13, (R9) - ADD R0, R9, R15 - MOVB R14, -1(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 - JMP copy_1_end + MOVBU (R10), R16 + BFI $0, R16, $8, R13 + ADD R1, R10, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R14 + MOVB R13, (R9) + ADD R1, R9, R15 + MOVB R14, -1(R15) + ADD R1, R10, R10 + ADD R1, R9, R9 + JMP copy_1_end copy_1_move_3: - MOVH (R10), R13 - MOVB 2(R10), R14 - MOVH R13, (R9) - MOVB R14, 2(R9) - ADD R0, R10, R10 - ADD R0, R9, R9 - JMP copy_1_end + MOVHU (R10), R13 + MOVBU 2(R10), R16 + BFI $0, R16, $8, R14 + MOVH R13, (R9) + MOVB R14, 2(R9) + ADD R1, R10, R10 + ADD R1, R9, R9 + JMP copy_1_end copy_1_move_4through7: MOVWU (R10), R13 - ADD R0, R10, R15 + ADD R1, R10, R15 MOVWU -4(R15), R14 MOVW R13, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R14, -4(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 JMP copy_1_end copy_1_move_8through16: MOVD (R10), R13 - ADD R0, R10, R15 + ADD R1, R10, R15 MOVD -8(R15), R14 MOVD R13, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R14, -8(R15) - ADD R0, R10, R10 - ADD R0, R9, R9 + ADD R1, R10, R10 + ADD R1, R9, R9 copy_1_end: - ADD R0, R11, R11 + ADD R1, R11, R11 // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) check_offset: - MOVD R11, R0 - MOVD 40(RSP), R16 - ADD R16, R0, R0 - CMP R0, R1 + MOVD R11, R1 + MOVD 80(RSP), R16 + ADD R16, R1, R1 + CMP R1, R12 BGT error_match_off_too_big - MOVD 56(RSP), R16 - CMP R16, R1 + MOVD 96(RSP), R16 + CMP R16, R12 BGT error_match_off_too_big // Copy match from history - MOVD R1, R0 - SUBS R11, R0, R0 + MOVD R12, R1 + SUBS R11, R1, R1 BLS copy_match - MOVD 48(RSP), R13 - SUB R0, R13, R13 - CMP R0, R12 + MOVD 88(RSP), R13 + SUB R1, R13, R13 + CMP R1, R0 BGT copy_all_from_history - MOVD R12, R0 - SUBS $0x10, R0, R0 + MOVD R0, R1 + SUBS $0x10, R1, R1 BLO copy_4_small copy_4_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R0, R0 - BHS copy_4_loop - ADD R0, R13, R13 - ADD $16, R13, R13 - ADD R0, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_4_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R1, R1 + BHS copy_4_loop + ADD R1, R13, R13 + ADD $16, R13, R13 + ADD R1, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_4_end copy_4_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_4_move_3 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_4_move_4through7 JMP copy_4_move_8through16 copy_4_move_3: - MOVH (R13), R0 - MOVB 2(R13), R1 - MOVH R0, (R9) - MOVB R1, 2(R9) - ADD R12, R13, R13 - ADD R12, R9, R9 - JMP copy_4_end + MOVHU (R13), R1 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R12 + MOVH R1, (R9) + MOVB R12, 2(R9) + ADD R0, R13, R13 + ADD R0, R9, R9 + JMP copy_4_end copy_4_move_4through7: - MOVWU (R13), R0 - ADD R12, R13, R15 - MOVWU -4(R15), R1 - MOVW R0, (R9) - ADD R12, R9, R15 - MOVW R1, -4(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVWU (R13), R1 + ADD R0, R13, R15 + MOVWU -4(R15), R12 + MOVW R1, (R9) + ADD R0, R9, R15 + MOVW R12, -4(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 JMP copy_4_end copy_4_move_8through16: - MOVD (R13), R0 - ADD R12, R13, R15 - MOVD -8(R15), R1 - MOVD R0, (R9) - ADD R12, R9, R15 - MOVD R1, -8(R15) - ADD R12, R13, R13 - ADD R12, R9, R9 + MOVD (R13), R1 + ADD R0, R13, R15 + MOVD -8(R15), R12 + MOVD R1, (R9) + ADD R0, R9, R15 + MOVD R12, -8(R15) + ADD R0, R13, R13 + ADD R0, R9, R9 copy_4_end: - ADD R12, R11, R11 + ADD R0, R11, R11 JMP handle_loop JMP loop_finished copy_all_from_history: - MOVD R0, R14 + MOVD R1, R14 SUBS $0x10, R14, R14 BLO copy_5_small copy_5_loop: - VLD1 (R13), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R13, R13 - ADD $0x10, R9, R9 - SUBS $0x10, R14, R14 - BHS copy_5_loop - ADD R14, R13, R13 - ADD $16, R13, R13 - ADD R14, R9, R9 - ADD $16, R9, R9 - ADD $-16, R13, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_5_end + FMOVQ (R13), F0 + FMOVQ F0, (R9) + ADD $0x10, R13, R13 + ADD $0x10, R9, R9 + SUBS $0x10, R14, R14 + BHS copy_5_loop + ADD R14, R13, R13 + ADD $16, R13, R13 + ADD R14, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R13), F0 + FMOVQ F0, -16(R9) + JMP copy_5_end copy_5_small: - CMP $0x03, R0 + CMP $0x03, R1 BEQ copy_5_move_3 BLO copy_5_move_1or2 - CMP $0x08, R0 + CMP $0x08, R1 BLO copy_5_move_4through7 JMP copy_5_move_8through16 copy_5_move_1or2: - MOVB (R13), R14 - ADD R0, R13, R15 - MOVB -1(R15), R4 - MOVB R14, (R9) - ADD R0, R9, R15 - MOVB R4, -1(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 - JMP copy_5_end + MOVBU (R13), R16 + BFI $0, R16, $8, R14 + ADD R1, R13, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R4 + MOVB R14, (R9) + ADD R1, R9, R15 + MOVB R4, -1(R15) + ADD R1, R13, R13 + ADD R1, R9, R9 + JMP copy_5_end copy_5_move_3: - MOVH (R13), R14 - MOVB 2(R13), R4 - MOVH R14, (R9) - MOVB R4, 2(R9) - ADD R0, R13, R13 - ADD R0, R9, R9 - JMP copy_5_end + MOVHU (R13), R14 + MOVBU 2(R13), R16 + BFI $0, R16, $8, R4 + MOVH R14, (R9) + MOVB R4, 2(R9) + ADD R1, R13, R13 + ADD R1, R9, R9 + JMP copy_5_end copy_5_move_4through7: MOVWU (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVWU -4(R15), R4 MOVW R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVW R4, -4(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 JMP copy_5_end copy_5_move_8through16: MOVD (R13), R14 - ADD R0, R13, R15 + ADD R1, R13, R15 MOVD -8(R15), R4 MOVD R14, (R9) - ADD R0, R9, R15 + ADD R1, R9, R15 MOVD R4, -8(R15) - ADD R0, R13, R13 - ADD R0, R9, R9 + ADD R1, R13, R13 + ADD R1, R9, R9 copy_5_end: - ADD R0, R11, R11 - SUB R0, R12, R12 + ADD R1, R11, R11 + SUB R1, R0, R0 // Copy match from the current buffer copy_match: - MOVD R9, R0 - SUB R1, R0, R0 + MOVD R9, R1 + SUB R12, R1, R1 // ml <= mo - CMP R1, R12 + CMP R12, R0 BHI copy_overlapping_match // Copy non-overlapping match - ADD R12, R11, R11 - MOVD R12, R1 - SUBS $0x10, R1, R1 + ADD R0, R11, R11 + MOVD R0, R12 + SUBS $0x10, R12, R12 BLO copy_2_small copy_2_loop: - VLD1 (R0), [V0.B16] - VST1 [V0.B16], (R9) - ADD $0x10, R0, R0 - ADD $0x10, R9, R9 - SUBS $0x10, R1, R1 - BHS copy_2_loop - ADD R1, R0, R0 - ADD $16, R0, R0 - ADD R1, R9, R9 - ADD $16, R9, R9 - ADD $-16, R0, R15 - VLD1 (R15), [V0.B16] - ADD $-16, R9, R15 - VST1 [V0.B16], (R15) - JMP copy_2_end + FMOVQ (R1), F0 + FMOVQ F0, (R9) + ADD $0x10, R1, R1 + ADD $0x10, R9, R9 + SUBS $0x10, R12, R12 + BHS copy_2_loop + ADD R12, R1, R1 + ADD $16, R1, R1 + ADD R12, R9, R9 + ADD $16, R9, R9 + FMOVQ -16(R1), F0 + FMOVQ F0, -16(R9) + JMP copy_2_end copy_2_small: - CMP $0x03, R12 + CMP $0x03, R0 BEQ copy_2_move_3 BLO copy_2_move_1or2 - CMP $0x08, R12 + CMP $0x08, R0 BLO copy_2_move_4through7 JMP copy_2_move_8through16 copy_2_move_1or2: - MOVB (R0), R1 - ADD R12, R0, R15 - MOVB -1(R15), R13 - MOVB R1, (R9) - ADD R12, R9, R15 - MOVB R13, -1(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 - JMP copy_2_end + MOVBU (R1), R16 + BFI $0, R16, $8, R12 + ADD R0, R1, R15 + MOVBU -1(R15), R16 + BFI $0, R16, $8, R13 + MOVB R12, (R9) + ADD R0, R9, R15 + MOVB R13, -1(R15) + ADD R0, R1, R1 + ADD R0, R9, R9 + JMP copy_2_end copy_2_move_3: - MOVH (R0), R1 - MOVB 2(R0), R13 - MOVH R1, (R9) - MOVB R13, 2(R9) - ADD R12, R0, R0 - ADD R12, R9, R9 - JMP copy_2_end + MOVHU (R1), R12 + MOVBU 2(R1), R16 + BFI $0, R16, $8, R13 + MOVH R12, (R9) + MOVB R13, 2(R9) + ADD R0, R1, R1 + ADD R0, R9, R9 + JMP copy_2_end copy_2_move_4through7: - MOVWU (R0), R1 - ADD R12, R0, R15 + MOVWU (R1), R12 + ADD R0, R1, R15 MOVWU -4(R15), R13 - MOVW R1, (R9) - ADD R12, R9, R15 + MOVW R12, (R9) + ADD R0, R9, R15 MOVW R13, -4(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 JMP copy_2_end copy_2_move_8through16: - MOVD (R0), R1 - ADD R12, R0, R15 + MOVD (R1), R12 + ADD R0, R1, R15 MOVD -8(R15), R13 - MOVD R1, (R9) - ADD R12, R9, R15 + MOVD R12, (R9) + ADD R0, R9, R15 MOVD R13, -8(R15) - ADD R12, R0, R0 - ADD R12, R9, R9 + ADD R0, R1, R1 + ADD R0, R9, R9 copy_2_end: JMP handle_loop // Copy overlapping match copy_overlapping_match: - ADD R12, R11, R11 + ADD R0, R11, R11 copy_slow_3: - MOVB (R0), R1 - MOVB R1, (R9) - ADD $1, R0, R0 - ADD $1, R9, R9 - SUBS $1, R12, R12 - BNE copy_slow_3 + MOVBU (R1), R12 + MOVB R12, (R9) + ADD $1, R1, R1 + ADD $1, R9, R9 + SUBS $1, R0, R0 + BNE copy_slow_3 handle_loop: - MOVD ctx+16(FP), R0 - MOVD 96(R0), R16 + MOVD 40(RSP), R16 SUBS $1, R16, R16 - MOVD R16, 96(R0) + MOVD R16, 40(RSP) BPL sequenceDecs_decodeSync_safe_amd64_main_loop loop_finished: @@ -2635,6 +2507,16 @@ loop_finished: MOVB R3, 40(R0) MOVD R5, 32(R0) + // s.seqSize += outPosition - ctx.outPosition + MOVD ctx+16(FP), R0 + MOVD s+0(FP), R1 + MOVD R11, R2 + MOVD 136(R0), R16 + SUB R16, R2, R2 + MOVD 256(R1), R16 + ADD R2, R16, R16 + MOVD R16, 256(R1) + // Update the context MOVD ctx+16(FP), R0 MOVD R11, 136(R0) @@ -2649,7 +2531,7 @@ loop_finished: // Return with match length error sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: - MOVD 16(RSP), R0 + MOVD 56(RSP), R0 MOVD ctx+16(FP), R1 MOVD R0, 216(R1) MOVD $0x00000001, R16 @@ -2659,7 +2541,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: // Return with match too long error sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: MOVD ctx+16(FP), R0 - MOVD 16(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD $0x00000002, R16 MOVD R16, ret+24(FP) @@ -2668,7 +2550,7 @@ sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: // Return with match offset too long error error_match_off_too_big: MOVD ctx+16(FP), R0 - MOVD 8(RSP), R1 + MOVD 48(RSP), R1 MOVD R1, 224(R0) MOVD R11, 136(R0) MOVD $0x00000003, R16 @@ -2678,7 +2560,7 @@ error_match_off_too_big: // Return with not enough literals error error_not_enough_literals: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) MOVD $0x00000004, R16 MOVD R16, ret+24(FP) @@ -2693,9 +2575,9 @@ error_overread: // Return with not enough output space error error_not_enough_space: MOVD ctx+16(FP), R0 - MOVD 24(RSP), R1 + MOVD 64(RSP), R1 MOVD R1, 208(R0) - MOVD 16(RSP), R1 + MOVD 56(RSP), R1 MOVD R1, 216(R0) MOVD R11, 136(R0) MOVD $0x00000005, R16 diff --git a/src/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go b/src/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go index 55405f39..94559c45 100644 --- a/src/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go +++ b/src/vendor/github.com/klauspost/compress/zstd/seqdec_asm.go @@ -77,6 +77,36 @@ const errorNotEnoughSpace = 5 // error reported when bits are overread. const errorOverread = 6 +// useSafeDecodeSync reports whether decodeSyncSimple must use the bounds-exact +// ("safe") copy variants for the current buffer geometry. +// +// When the output and literal buffers have compressedBlockOverAlloc (16) +// bytes of slack past their logical use, the assembly may use extended +// memory copies that read and write in 16-byte blocks, overrunning the end +// of a literal run or match by up to 15 bytes; an empty literal run still +// copies one block, reading and writing the full 16 bytes of slack past +// its position. Otherwise it must use the bounds-exact ("safe") copies. +// This mirrors the analogous, always-dynamic selection in executeSimple below. +// +// The unsafe copies were disabled in #644 (2022) as a mitigation for a +// crash, but that crash's root cause — an unguarded bitReader overread that +// produced out-of-range match offsets/lengths — was fixed three days later +// in #645, which also added the fuzz corpus that has guarded this path since. +// See #1168. An asan-instrumented fuzz job (see .github/workflows/go.yml) +// covers the extended-copy path, which -race and plain fuzzing cannot. +func (s *sequenceDecs) useSafeDecodeSync() bool { + if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc { + return true + } + if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) { + return true + } + if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc { + return true + } + return false +} + // decode sequences from the stream with the provided history but without a dictionary. func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { if len(s.dict) > 0 { @@ -86,9 +116,7 @@ func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { return false, nil } - // FIXME: Using unsafe memory copies leads to rare, random crashes - // with fuzz testing. It is therefore disabled for now. - const useSafe = true + useSafe := s.useSafeDecodeSync() br := s.br diff --git a/src/vendor/github.com/mattn/go-colorable/colorable_windows.go b/src/vendor/github.com/mattn/go-colorable/colorable_windows.go index 426a409c..2e1f1ab1 100644 --- a/src/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/src/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -5,16 +5,15 @@ package colorable import ( "bytes" - syscall "golang.org/x/sys/windows" "io" - "math" "os" "strconv" "strings" "sync" + stdsyscall "syscall" "unsafe" - "github.com/mattn/go-isatty" + syscall "golang.org/x/sys/windows" ) const ( @@ -52,6 +51,12 @@ type coord struct { y short } +// param packs the two signed 16-bit coordinates into the DWORD passed by value +// to console APIs, without reading past the four-byte coord on 64-bit Windows. +func (c coord) param() uintptr { + return uintptr(uint16(c.x)) | uintptr(uint16(c.y))<<16 +} + type smallRect struct { left short top short @@ -105,14 +110,15 @@ func NewColorable(file *os.File) io.Writer { panic("nil passed instead of *os.File to NewColorable()") } - if isatty.IsTerminal(file.Fd()) { - var mode uint32 - if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { + fd := file.Fd() + var mode uint32 + if err := syscall.GetConsoleMode(syscall.Handle(fd), &mode); err == nil { + if mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { return file } var csbi consoleScreenBufferInfo - handle := syscall.Handle(file.Fd()) - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + handle := syscall.Handle(fd) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) return &writer{out: file, handle: handle, oldattr: csbi.attributes, curattr: csbi.attributes, oldpos: coord{0, 0}} } return file @@ -128,302 +134,31 @@ func NewColorableStderr() io.Writer { return NewColorable(os.Stderr) } -var color256 = map[int]int{ - 0: 0x000000, - 1: 0x800000, - 2: 0x008000, - 3: 0x808000, - 4: 0x000080, - 5: 0x800080, - 6: 0x008080, - 7: 0xc0c0c0, - 8: 0x808080, - 9: 0xff0000, - 10: 0x00ff00, - 11: 0xffff00, - 12: 0x0000ff, - 13: 0xff00ff, - 14: 0x00ffff, - 15: 0xffffff, - 16: 0x000000, - 17: 0x00005f, - 18: 0x000087, - 19: 0x0000af, - 20: 0x0000d7, - 21: 0x0000ff, - 22: 0x005f00, - 23: 0x005f5f, - 24: 0x005f87, - 25: 0x005faf, - 26: 0x005fd7, - 27: 0x005fff, - 28: 0x008700, - 29: 0x00875f, - 30: 0x008787, - 31: 0x0087af, - 32: 0x0087d7, - 33: 0x0087ff, - 34: 0x00af00, - 35: 0x00af5f, - 36: 0x00af87, - 37: 0x00afaf, - 38: 0x00afd7, - 39: 0x00afff, - 40: 0x00d700, - 41: 0x00d75f, - 42: 0x00d787, - 43: 0x00d7af, - 44: 0x00d7d7, - 45: 0x00d7ff, - 46: 0x00ff00, - 47: 0x00ff5f, - 48: 0x00ff87, - 49: 0x00ffaf, - 50: 0x00ffd7, - 51: 0x00ffff, - 52: 0x5f0000, - 53: 0x5f005f, - 54: 0x5f0087, - 55: 0x5f00af, - 56: 0x5f00d7, - 57: 0x5f00ff, - 58: 0x5f5f00, - 59: 0x5f5f5f, - 60: 0x5f5f87, - 61: 0x5f5faf, - 62: 0x5f5fd7, - 63: 0x5f5fff, - 64: 0x5f8700, - 65: 0x5f875f, - 66: 0x5f8787, - 67: 0x5f87af, - 68: 0x5f87d7, - 69: 0x5f87ff, - 70: 0x5faf00, - 71: 0x5faf5f, - 72: 0x5faf87, - 73: 0x5fafaf, - 74: 0x5fafd7, - 75: 0x5fafff, - 76: 0x5fd700, - 77: 0x5fd75f, - 78: 0x5fd787, - 79: 0x5fd7af, - 80: 0x5fd7d7, - 81: 0x5fd7ff, - 82: 0x5fff00, - 83: 0x5fff5f, - 84: 0x5fff87, - 85: 0x5fffaf, - 86: 0x5fffd7, - 87: 0x5fffff, - 88: 0x870000, - 89: 0x87005f, - 90: 0x870087, - 91: 0x8700af, - 92: 0x8700d7, - 93: 0x8700ff, - 94: 0x875f00, - 95: 0x875f5f, - 96: 0x875f87, - 97: 0x875faf, - 98: 0x875fd7, - 99: 0x875fff, - 100: 0x878700, - 101: 0x87875f, - 102: 0x878787, - 103: 0x8787af, - 104: 0x8787d7, - 105: 0x8787ff, - 106: 0x87af00, - 107: 0x87af5f, - 108: 0x87af87, - 109: 0x87afaf, - 110: 0x87afd7, - 111: 0x87afff, - 112: 0x87d700, - 113: 0x87d75f, - 114: 0x87d787, - 115: 0x87d7af, - 116: 0x87d7d7, - 117: 0x87d7ff, - 118: 0x87ff00, - 119: 0x87ff5f, - 120: 0x87ff87, - 121: 0x87ffaf, - 122: 0x87ffd7, - 123: 0x87ffff, - 124: 0xaf0000, - 125: 0xaf005f, - 126: 0xaf0087, - 127: 0xaf00af, - 128: 0xaf00d7, - 129: 0xaf00ff, - 130: 0xaf5f00, - 131: 0xaf5f5f, - 132: 0xaf5f87, - 133: 0xaf5faf, - 134: 0xaf5fd7, - 135: 0xaf5fff, - 136: 0xaf8700, - 137: 0xaf875f, - 138: 0xaf8787, - 139: 0xaf87af, - 140: 0xaf87d7, - 141: 0xaf87ff, - 142: 0xafaf00, - 143: 0xafaf5f, - 144: 0xafaf87, - 145: 0xafafaf, - 146: 0xafafd7, - 147: 0xafafff, - 148: 0xafd700, - 149: 0xafd75f, - 150: 0xafd787, - 151: 0xafd7af, - 152: 0xafd7d7, - 153: 0xafd7ff, - 154: 0xafff00, - 155: 0xafff5f, - 156: 0xafff87, - 157: 0xafffaf, - 158: 0xafffd7, - 159: 0xafffff, - 160: 0xd70000, - 161: 0xd7005f, - 162: 0xd70087, - 163: 0xd700af, - 164: 0xd700d7, - 165: 0xd700ff, - 166: 0xd75f00, - 167: 0xd75f5f, - 168: 0xd75f87, - 169: 0xd75faf, - 170: 0xd75fd7, - 171: 0xd75fff, - 172: 0xd78700, - 173: 0xd7875f, - 174: 0xd78787, - 175: 0xd787af, - 176: 0xd787d7, - 177: 0xd787ff, - 178: 0xd7af00, - 179: 0xd7af5f, - 180: 0xd7af87, - 181: 0xd7afaf, - 182: 0xd7afd7, - 183: 0xd7afff, - 184: 0xd7d700, - 185: 0xd7d75f, - 186: 0xd7d787, - 187: 0xd7d7af, - 188: 0xd7d7d7, - 189: 0xd7d7ff, - 190: 0xd7ff00, - 191: 0xd7ff5f, - 192: 0xd7ff87, - 193: 0xd7ffaf, - 194: 0xd7ffd7, - 195: 0xd7ffff, - 196: 0xff0000, - 197: 0xff005f, - 198: 0xff0087, - 199: 0xff00af, - 200: 0xff00d7, - 201: 0xff00ff, - 202: 0xff5f00, - 203: 0xff5f5f, - 204: 0xff5f87, - 205: 0xff5faf, - 206: 0xff5fd7, - 207: 0xff5fff, - 208: 0xff8700, - 209: 0xff875f, - 210: 0xff8787, - 211: 0xff87af, - 212: 0xff87d7, - 213: 0xff87ff, - 214: 0xffaf00, - 215: 0xffaf5f, - 216: 0xffaf87, - 217: 0xffafaf, - 218: 0xffafd7, - 219: 0xffafff, - 220: 0xffd700, - 221: 0xffd75f, - 222: 0xffd787, - 223: 0xffd7af, - 224: 0xffd7d7, - 225: 0xffd7ff, - 226: 0xffff00, - 227: 0xffff5f, - 228: 0xffff87, - 229: 0xffffaf, - 230: 0xffffd7, - 231: 0xffffff, - 232: 0x080808, - 233: 0x121212, - 234: 0x1c1c1c, - 235: 0x262626, - 236: 0x303030, - 237: 0x3a3a3a, - 238: 0x444444, - 239: 0x4e4e4e, - 240: 0x585858, - 241: 0x626262, - 242: 0x6c6c6c, - 243: 0x767676, - 244: 0x808080, - 245: 0x8a8a8a, - 246: 0x949494, - 247: 0x9e9e9e, - 248: 0xa8a8a8, - 249: 0xb2b2b2, - 250: 0xbcbcbc, - 251: 0xc6c6c6, - 252: 0xd0d0d0, - 253: 0xdadada, - 254: 0xe4e4e4, - 255: 0xeeeeee, -} - // `\033]0;TITLESTR\007` -func doTitleSequence(er *bytes.Reader) error { - var c byte - var err error - - c, err = er.ReadByte() - if err != nil { - return err +func doTitleSequence(data []byte) (int, error) { + if len(data) == 0 { + return 0, io.EOF } - if c != '0' && c != '2' { - return nil + if data[0] != '0' && data[0] != '2' { + return 1, nil } - c, err = er.ReadByte() - if err != nil { - return err + if len(data) < 2 { + return 1, io.EOF } - if c != ';' { - return nil + if data[1] != ';' { + return 2, nil } - title := make([]byte, 0, 80) - for { - c, err = er.ReadByte() - if err != nil { - return err - } - if c == 0x07 || c == '\n' { - break - } - title = append(title, c) + end := bytes.IndexAny(data[2:], "\a\n") + if end < 0 { + return len(data), io.EOF } - if len(title) > 0 { - title8, err := syscall.UTF16PtrFromString(string(title)) + if end > 0 { + title, err := syscall.UTF16PtrFromString(string(data[2 : 2+end])) if err == nil { - procSetConsoleTitle.Call(uintptr(unsafe.Pointer(title8))) + stdsyscall.SyscallN(procSetConsoleTitle.Addr(), uintptr(unsafe.Pointer(title))) } } - return nil + return end + 3, nil } // returns Atoi(s) unless s == "" in which case it returns def @@ -434,45 +169,58 @@ func atoiWithDefault(s string, def int) (int, error) { return strconv.Atoi(s) } +// splitParameters uses caller-provided storage for the usual short ANSI +// parameter lists, while still accepting arbitrarily long lists. +func splitParameters(s string, storage []string) []string { + n := strings.Count(s, ";") + 1 + if n > cap(storage) { + storage = make([]string, n) + } else { + storage = storage[:n] + } + for i := 0; i < n-1; i++ { + end := strings.IndexByte(s, ';') + storage[i] = s[:end] + s = s[end+1:] + } + storage[n-1] = s + return storage +} + // Write writes data on console func (w *writer) Write(data []byte) (n int, err error) { w.mutex.Lock() defer w.mutex.Unlock() - var csbi consoleScreenBufferInfo if w.rest.Len() == 0 && bytes.IndexByte(data, 0x1b) == -1 { w.out.Write(data) return len(data), nil } + var csbi consoleScreenBufferInfo handle := w.handle - var er *bytes.Reader + input := data if w.rest.Len() > 0 { - var rest bytes.Buffer - w.rest.WriteTo(&rest) + w.rest.Write(data) + input = w.rest.Bytes() w.rest.Reset() - rest.Write(data) - er = bytes.NewReader(rest.Bytes()) - } else { - er = bytes.NewReader(data) } - var plaintext bytes.Buffer + er := bytes.NewReader(input) loop: - for { - c1, err := er.ReadByte() - if err != nil { - plaintext.WriteTo(w.out) + for er.Len() > 0 { + remaining := input[len(input)-er.Len():] + escape := bytes.IndexByte(remaining, 0x1b) + if escape < 0 { + w.out.Write(remaining) break loop } - if c1 != 0x1b { - plaintext.WriteByte(c1) - continue - } - _, err = plaintext.WriteTo(w.out) - if err != nil { - break loop + if escape > 0 { + if n, err := w.out.Write(remaining[:escape]); err != nil || n != escape { + break loop + } } + er.Seek(int64(escape+1), io.SeekCurrent) c2, err := er.ReadByte() if err != nil { break loop @@ -482,26 +230,24 @@ loop: case '>': continue case ']': - w.rest.WriteByte(c1) - w.rest.WriteByte(c2) - er.WriteTo(&w.rest) - if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 { + if bytes.IndexByte(remaining[escape+2:], 0x07) == -1 { + w.rest.Write(remaining[escape:]) break loop } - er = bytes.NewReader(w.rest.Bytes()[2:]) - err := doTitleSequence(er) + consumed, err := doTitleSequence(remaining[escape+2:]) + er.Seek(int64(consumed), io.SeekCurrent) if err != nil { + w.rest.Write(remaining[escape:]) break loop } - w.rest.Reset() continue // https://github.com/mattn/go-colorable/issues/27 case '7': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) w.oldpos = csbi.cursorPosition continue case '8': - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), w.oldpos.param()) continue case 0x5b: // execute part after switch @@ -509,102 +255,103 @@ loop: continue } - w.rest.WriteByte(c1) - w.rest.WriteByte(c2) - er.WriteTo(&w.rest) - - var buf bytes.Buffer + // Keep complete sequences in the input slice. Only an unfinished + // sequence needs to be copied and retained for the next Write. + params := remaining[escape+2:] + var buf []byte var m byte - for i, c := range w.rest.Bytes()[2:] { + for i, c := range params { if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { m = c - er = bytes.NewReader(w.rest.Bytes()[2+i+1:]) - w.rest.Reset() + buf = params[:i] + er.Seek(int64(i+1), io.SeekCurrent) break } - buf.WriteByte(c) } if m == 0 { + w.rest.Write(remaining[escape:]) break loop } switch m { case 'A': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y -= short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'B': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'C': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'D': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x -= short(n) if csbi.cursorPosition.x < 0 { csbi.cursorPosition.x = 0 } - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'E': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = 0 csbi.cursorPosition.y += short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'F': - n, err = atoiWithDefault(buf.String(), 1) + n, err = atoiWithDefault(string(buf), 1) if err != nil { continue } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = 0 csbi.cursorPosition.y -= short(n) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'G': - n, err = strconv.Atoi(buf.String()) + n, err = strconv.Atoi(string(buf)) if err != nil { continue } if n < 1 { n = 1 } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.x = short(n - 1) - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'H', 'f': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) - if buf.Len() > 0 { - token := strings.Split(buf.String(), ";") + if len(buf) > 0 { + var storage [8]string + token := splitParameters(string(buf), storage[:]) switch len(token) { case 1: n1, err := strconv.Atoi(token[0]) if err != nil { continue } + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y = short(n1 - 1) case 2: + // Both coordinates are absolute; no console query is needed. n1, err := strconv.Atoi(token[0]) if err != nil { continue @@ -615,22 +362,25 @@ loop: } csbi.cursorPosition.x = short(n2 - 1) csbi.cursorPosition.y = short(n1 - 1) + default: + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) } } else { + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) csbi.cursorPosition.y = 0 } - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), csbi.cursorPosition.param()) case 'J': n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) + if len(buf) > 0 { + n, err = strconv.Atoi(string(buf)) if err != nil { continue } } var count, written dword var cursor coord - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) switch n { case 0: cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} @@ -642,17 +392,17 @@ loop: cursor = coord{x: csbi.window.left, y: csbi.window.top} count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x) } - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputCharacter.Addr(), uintptr(handle), uintptr(' '), uintptr(count), cursor.param(), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputAttribute.Addr(), uintptr(handle), uintptr(csbi.attributes), uintptr(count), cursor.param(), uintptr(unsafe.Pointer(&written))) case 'K': n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) + if len(buf) > 0 { + n, err = strconv.Atoi(string(buf)) if err != nil { continue } } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) var cursor coord var count, written dword switch n { @@ -666,31 +416,34 @@ loop: cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y} count = dword(csbi.size.x) } - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputCharacter.Addr(), uintptr(handle), uintptr(' '), uintptr(count), cursor.param(), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputAttribute.Addr(), uintptr(handle), uintptr(csbi.attributes), uintptr(count), cursor.param(), uintptr(unsafe.Pointer(&written))) case 'X': n := 0 - if buf.Len() > 0 { - n, err = strconv.Atoi(buf.String()) + if len(buf) > 0 { + n, err = strconv.Atoi(string(buf)) if err != nil { continue } } - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) var cursor coord var written dword cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} - procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) - procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(n), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputCharacter.Addr(), uintptr(handle), uintptr(' '), uintptr(n), cursor.param(), uintptr(unsafe.Pointer(&written))) + stdsyscall.SyscallN(procFillConsoleOutputAttribute.Addr(), uintptr(handle), uintptr(csbi.attributes), uintptr(n), cursor.param(), uintptr(unsafe.Pointer(&written))) case 'm': attr := w.curattr - cs := buf.String() + cs := string(buf) if cs == "" { - procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr)) - w.curattr = w.oldattr + if w.curattr != w.oldattr { + stdsyscall.SyscallN(procSetConsoleTextAttribute.Addr(), uintptr(handle), uintptr(w.oldattr)) + w.curattr = w.oldattr + } continue } - token := strings.Split(cs, ";") + var storage [8]string + token := splitParameters(cs, storage[:]) for i := 0; i < len(token); i++ { ns := token[i] if n, err = strconv.Atoi(ns); err == nil { @@ -724,9 +477,7 @@ loop: case n == 38: // set foreground color. if i < len(token)-2 && (token[i+1] == "5" || token[i+1] == "05") { if n256, err := strconv.Atoi(token[i+2]); err == nil { - if n256foreAttr == nil { - n256setup() - } + attr &= backgroundMask attr |= n256foreAttr[n256%len(n256foreAttr)] i += 2 @@ -766,11 +517,9 @@ loop: case n == 48: // set background color. if i < len(token)-2 && token[i+1] == "5" { if n256, err := strconv.Atoi(token[i+2]); err == nil { - if n256backAttr == nil { - n256setup() - } + attr &= foregroundMask - attr |= n256backAttr[n256%len(n256backAttr)] + attr |= (n256foreAttr[n256%len(n256foreAttr)] << 4) i += 2 } } else if len(token) == 5 && token[i+1] == "2" { @@ -822,233 +571,73 @@ loop: } } if attr != w.curattr { - procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr)) + stdsyscall.SyscallN(procSetConsoleTextAttribute.Addr(), uintptr(handle), uintptr(attr)) w.curattr = attr } case 'h': var ci consoleCursorInfo - cs := buf.String() + cs := string(buf) if cs == "5>" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procGetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) ci.visible = 0 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procSetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) } else if cs == "?25" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procGetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) ci.visible = 1 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procSetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) } else if cs == "?1049" { if w.althandle == 0 { - h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0) + h, _, _ := stdsyscall.SyscallN(procCreateConsoleScreenBuffer.Addr(), uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0) w.althandle = syscall.Handle(h) if w.althandle != 0 { handle = w.althandle - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) w.curattr = csbi.attributes } } } case 'l': var ci consoleCursorInfo - cs := buf.String() + cs := string(buf) if cs == "5>" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procGetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) ci.visible = 1 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procSetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) } else if cs == "?25" { - procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procGetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) ci.visible = 0 - procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci))) + stdsyscall.SyscallN(procSetConsoleCursorInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&ci))) } else if cs == "?1049" { if w.althandle != 0 { syscall.CloseHandle(w.althandle) w.althandle = 0 handle = w.handle - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) w.curattr = csbi.attributes } } case 's': - procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) + stdsyscall.SyscallN(procGetConsoleScreenBufferInfo.Addr(), uintptr(handle), uintptr(unsafe.Pointer(&csbi))) w.oldpos = csbi.cursorPosition case 'u': - procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) + stdsyscall.SyscallN(procSetConsoleCursorPosition.Addr(), uintptr(handle), w.oldpos.param()) } } return len(data), nil } -type consoleColor struct { - rgb int - red bool - green bool - blue bool - intensity bool -} - -func (c consoleColor) foregroundAttr() (attr word) { - if c.red { - attr |= foregroundRed - } - if c.green { - attr |= foregroundGreen - } - if c.blue { - attr |= foregroundBlue - } - if c.intensity { - attr |= foregroundIntensity - } - return -} - -func (c consoleColor) backgroundAttr() (attr word) { - if c.red { - attr |= backgroundRed - } - if c.green { - attr |= backgroundGreen - } - if c.blue { - attr |= backgroundBlue - } - if c.intensity { - attr |= backgroundIntensity - } - return -} - -var color16 = []consoleColor{ - {0x000000, false, false, false, false}, - {0x000080, false, false, true, false}, - {0x008000, false, true, false, false}, - {0x008080, false, true, true, false}, - {0x800000, true, false, false, false}, - {0x800080, true, false, true, false}, - {0x808000, true, true, false, false}, - {0xc0c0c0, true, true, true, false}, - {0x808080, false, false, false, true}, - {0x0000ff, false, false, true, true}, - {0x00ff00, false, true, false, true}, - {0x00ffff, false, true, true, true}, - {0xff0000, true, false, false, true}, - {0xff00ff, true, false, true, true}, - {0xffff00, true, true, false, true}, - {0xffffff, true, true, true, true}, -} - -type hsv struct { - h, s, v float32 -} - -func (a hsv) dist(b hsv) float32 { - dh := a.h - b.h - switch { - case dh > 0.5: - dh = 1 - dh - case dh < -0.5: - dh = -1 - dh - } - ds := a.s - b.s - dv := a.v - b.v - return float32(math.Sqrt(float64(dh*dh + ds*ds + dv*dv))) -} - -func toHSV(rgb int) hsv { - r, g, b := float32((rgb&0xFF0000)>>16)/256.0, - float32((rgb&0x00FF00)>>8)/256.0, - float32(rgb&0x0000FF)/256.0 - min, max := minmax3f(r, g, b) - h := max - min - if h > 0 { - if max == r { - h = (g - b) / h - if h < 0 { - h += 6 - } - } else if max == g { - h = 2 + (b-r)/h - } else { - h = 4 + (r-g)/h - } - } - h /= 6.0 - s := max - min - if max != 0 { - s /= max - } - v := max - return hsv{h: h, s: s, v: v} -} - -type hsvTable []hsv - -func toHSVTable(rgbTable []consoleColor) hsvTable { - t := make(hsvTable, len(rgbTable)) - for i, c := range rgbTable { - t[i] = toHSV(c.rgb) - } - return t -} - -func (t hsvTable) find(rgb int) consoleColor { - hsv := toHSV(rgb) - n := 7 - l := float32(5.0) - for i, p := range t { - d := hsv.dist(p) - if d < l { - l, n = d, i - } - } - return color16[n] -} - -func minmax3f(a, b, c float32) (min, max float32) { - if a < b { - if b < c { - return a, c - } else if a < c { - return a, b - } else { - return c, b - } - } else { - if a < c { - return b, c - } else if b < c { - return b, a - } else { - return c, a - } - } -} - -var n256foreAttr []word -var n256backAttr []word - -func n256setup() { - n256foreAttr = make([]word, 256) - n256backAttr = make([]word, 256) - t := toHSVTable(color16) - for i, rgb := range color256 { - c := t.find(rgb) - n256foreAttr[i] = c.foregroundAttr() - n256backAttr[i] = c.backgroundAttr() - } -} - // EnableColorsStdout enable colors if possible. func EnableColorsStdout(enabled *bool) func() { var mode uint32 h := os.Stdout.Fd() - if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 { - if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { + if r, _, _ := stdsyscall.SyscallN(procGetConsoleMode.Addr(), h, uintptr(unsafe.Pointer(&mode))); r != 0 { + if r, _, _ = stdsyscall.SyscallN(procSetConsoleMode.Addr(), h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { if enabled != nil { *enabled = true } return func() { - procSetConsoleMode.Call(h, uintptr(mode)) + stdsyscall.SyscallN(procSetConsoleMode.Addr(), h, uintptr(mode)) } } } diff --git a/src/vendor/github.com/mattn/go-colorable/colorable_windows_palette.go b/src/vendor/github.com/mattn/go-colorable/colorable_windows_palette.go new file mode 100644 index 00000000..349b0a82 --- /dev/null +++ b/src/vendor/github.com/mattn/go-colorable/colorable_windows_palette.go @@ -0,0 +1,25 @@ +//go:build windows && !appengine +// +build windows,!appengine + +package colorable + +// n256foreAttr maps the xterm palette to the nearest Windows console color. +// TestWindowsPalette verifies every entry against the HSV conversion. +var n256foreAttr = [256]word{ + 0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07, 0x08, 0x0c, 0x0a, 0x0e, 0x09, 0x0d, 0x0b, 0x0f, + 0x00, 0x01, 0x01, 0x01, 0x09, 0x09, 0x02, 0x03, 0x03, 0x03, 0x09, 0x09, 0x02, 0x03, 0x03, 0x03, + 0x0b, 0x0b, 0x02, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, + 0x0b, 0x0b, 0x0b, 0x0b, 0x04, 0x05, 0x05, 0x05, 0x09, 0x09, 0x06, 0x08, 0x08, 0x07, 0x09, 0x09, + 0x06, 0x08, 0x08, 0x01, 0x09, 0x09, 0x06, 0x07, 0x02, 0x03, 0x0b, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x04, 0x05, 0x05, 0x05, 0x0d, 0x0d, 0x06, 0x08, + 0x08, 0x07, 0x09, 0x09, 0x06, 0x08, 0x08, 0x07, 0x07, 0x09, 0x06, 0x07, 0x07, 0x07, 0x07, 0x09, + 0x0e, 0x0a, 0x07, 0x07, 0x07, 0x0b, 0x0e, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x04, 0x05, 0x05, 0x05, + 0x0d, 0x0d, 0x06, 0x07, 0x07, 0x07, 0x0d, 0x09, 0x06, 0x07, 0x07, 0x07, 0x07, 0x09, 0x06, 0x07, + 0x07, 0x07, 0x07, 0x0f, 0x0e, 0x0e, 0x07, 0x07, 0x07, 0x0f, 0x0e, 0x0a, 0x0a, 0x0f, 0x0f, 0x0f, + 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0c, 0x07, 0x07, + 0x07, 0x0f, 0x0e, 0x0e, 0x07, 0x07, 0x07, 0x0f, 0x0e, 0x0e, 0x07, 0x07, 0x07, 0x0f, 0x0e, 0x0e, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, + 0x0e, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0f, +} diff --git a/src/vendor/github.com/mattn/go-colorable/noncolorable.go b/src/vendor/github.com/mattn/go-colorable/noncolorable.go index 05d6f74b..4ddd5a7c 100644 --- a/src/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/src/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -17,36 +17,30 @@ func NewNonColorable(w io.Writer) io.Writer { // Write writes data on console func (w *NonColorable) Write(data []byte) (n int, err error) { - er := bytes.NewReader(data) - var plaintext bytes.Buffer -loop: - for { - c1, err := er.ReadByte() - if err != nil { - plaintext.WriteTo(w.out) - break loop + for offset := 0; offset < len(data); { + escape := bytes.IndexByte(data[offset:], 0x1b) + if escape < 0 { + w.out.Write(data[offset:]) + break } - if c1 != 0x1b { - plaintext.WriteByte(c1) - continue - } - _, err = plaintext.WriteTo(w.out) - if err != nil { - break loop + if escape > 0 { + if n, err := w.out.Write(data[offset : offset+escape]); err != nil || n != escape { + break + } } - c2, err := er.ReadByte() - if err != nil { - break loop + offset += escape + 1 + if offset == len(data) { + break } + c2 := data[offset] + offset++ if c2 != 0x5b { continue } - for { - c, err := er.ReadByte() - if err != nil { - break loop - } + for offset < len(data) { + c := data[offset] + offset++ if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { break } diff --git a/src/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/src/vendor/github.com/mattn/go-isatty/isatty_tiocgwinsz.go similarity index 62% rename from src/vendor/github.com/mattn/go-isatty/isatty_tcgets.go rename to src/vendor/github.com/mattn/go-isatty/isatty_tiocgwinsz.go index 0337d8cf..6aecf870 100644 --- a/src/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/src/vendor/github.com/mattn/go-isatty/isatty_tiocgwinsz.go @@ -8,8 +8,12 @@ package isatty import "golang.org/x/sys/unix" // IsTerminal return true if the file descriptor is terminal. +// TIOCGWINSZ is used instead of TCGETS because TCGETS shares its ioctl +// number with SNDCTL_TMR_TIMEBASE of the OSS sound API, so it may succeed +// (and even change the device mode) on non-tty devices. musl's isatty does +// the same. func IsTerminal(fd uintptr) bool { - _, err := unix.IoctlGetTermios(int(fd), unix.TCGETS) + _, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) return err == nil } diff --git a/src/vendor/github.com/molecule-man/go-brrr/.gitignore b/src/vendor/github.com/molecule-man/go-brrr/.gitignore new file mode 100644 index 00000000..944b90e5 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/.gitignore @@ -0,0 +1,39 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Code coverage profiles and other test artifacts +*.out +coverage.* +*.coverprofile +profile.cov + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# Build artifacts +/bin/ +/lib/ + +# Test and benchmark caches +.cache/ + +# env file +.env + +# Editor/IDE +# .idea/ +# .vscode/ diff --git a/src/vendor/github.com/molecule-man/go-brrr/.gitmodules b/src/vendor/github.com/molecule-man/go-brrr/.gitmodules new file mode 100644 index 00000000..1e0a3d17 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/.gitmodules @@ -0,0 +1,3 @@ +[submodule "brotli-ref"] + path = brotli-ref + url = git@github.com:google/brotli.git diff --git a/src/vendor/github.com/molecule-man/go-brrr/.golangci.yml b/src/vendor/github.com/molecule-man/go-brrr/.golangci.yml new file mode 100644 index 00000000..e061d21f --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/.golangci.yml @@ -0,0 +1,139 @@ +version: "2" + +run: + timeout: 5m + modules-download-mode: readonly + +linters: + enable: + # Enabled by default linters: + - errcheck # Check for unchecked errors + - govet # Reports suspicious constructs + - ineffassign # Detect ineffectual assignments + - staticcheck # Go static analysis (includes gosimple in v2) + - modernize # Suggest simplifications using modern Go features + - misspell # Finds commonly misspelled English words + - revive # Fast, configurable, extensible, flexible, and beautiful linter for Go + - unconvert # Remove unnecessary type conversions + - unparam # Find unused function parameters + # - dupl # Check for duplicate code + - gocritic # Highly extensible Go linter + - nilerr # Find code that returns nil even though it checks that error is not nil + - errorlint # Find misuses of errors + - prealloc # Find slice declarations that could potentially be pre-allocated + - decorder # Check declaration order and count of types, constants, variables and functions + - funcorder # Check function order within Go files + - depguard # Enforce import restrictions + - unused # Check for unused constants, variables, functions and types + - nolintlint # Find ill-formed or unnecessary nolint directives + + disable: + # Additional useful linters: + - bodyclose # Check if HTTP response body is closed + - gosec # Security-focused linter + + settings: + decorder: + dec-order: + - const + - var + - type + - func + disable-dec-order-check: false + disable-dec-num-check: true + disable-init-func-first-check: false + + gocritic: + enabled-tags: + - diagnostic + - style + - performance + disabled-checks: + - unnamedResult + + revive: + rules: + - name: exported + disabled: false + - name: package-comments + disabled: false + + depguard: + rules: + no-fmt: + list-mode: lax + files: + - "*.go" + - "!*_test.go" + deny: + - pkg: "fmt$" + desc: "use strconv, errors, or io instead of fmt" + + errcheck: + check-blank: false + check-type-assertions: false + + gosec: + excludes: + - G104 # Audit errors not checked (covered by errcheck) + + govet: + enable-all: true + disable: + - shadow + + exclusions: + generated: strict + rules: + # Exclude some linters from running on test files. + - path: _test\.go + linters: + - gosec + - gocritic + - decorder + - path: _test\.go + linters: + - govet + text: "fieldalignment" + + # C-ported Huffman table code: gosec's slice-bounds (G602) and + # int-overflow (G115) heuristics produce false positives here. + - path: entropy\.go + linters: + - gosec + - path: huffman\.go + linters: + - gosec + + # Allow panic in main package + - path: main\.go + linters: + - gocritic + text: "exitAfterDefer" + + # CGo files: dupImport is required (import "C" must be separate), + # and dupSubExpr false-positives on CGo return value comparisons. + - path: _cgo\.go + linters: + - gocritic + +formatters: + enable: + - gofmt # Check if code is formatted with gofmt + - goimports # Check import statements are formatted well + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + uniq-by-line: true + +output: + formats: + text: + path: stdout + print-linter-name: true + colors: true + sort-order: + - linter + - severity + - file diff --git a/src/vendor/github.com/molecule-man/go-brrr/.pre-commit-config.yaml b/src/vendor/github.com/molecule-man/go-brrr/.pre-commit-config.yaml new file mode 100644 index 00000000..3e7cf5ad --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/.pre-commit-config.yaml @@ -0,0 +1,38 @@ +fail_fast: false +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + args: + - --unsafe + - id: end-of-file-fixer + exclude: '\.bin$' + - id: trailing-whitespace + exclude: '\.bin$' + + - repo: local + hooks: + - id: embedmd + name: embedmd + entry: embedmd -d README.md + language: system + pass_filenames: false + stages: [pre-commit] + - id: lint + name: lint + entry: golangci-lint run ./... + types: [go] + language: system + pass_filenames: false + stages: [pre-commit] + - id: test + name: test + entry: go test -short ./... + types: [go] + language: system + pass_filenames: false + stages: [pre-commit] diff --git a/src/vendor/github.com/molecule-man/go-brrr/CONTRIBUTING.md b/src/vendor/github.com/molecule-man/go-brrr/CONTRIBUTING.md new file mode 100644 index 00000000..001d7ca5 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/CONTRIBUTING.md @@ -0,0 +1,199 @@ +# Contributing to go-brrr + +Thank you for your interest in go-brrr. This document explains how to submit a +change that the maintainer can review, benchmark, and merge. + +go-brrr is a performance-critical library. Most of the rules below exist to make +a performance claim reproducible. + +## Before you start + +Install the toolchain and the C reference library: + +```sh +make init +``` + +`make init` pulls the `brotli-ref` submodule, installs `benchstat` and +`embedmd`, and builds `lib/libbrotli_cref.a`. + +For a large optimization or an architectural change, open an issue or a draft +pull request first. Agree on the scope before you write the implementation. +This step protects your time, not only the review time. + +## Pull request scope + +**One pull request is one logical change.** + +Submit independent optimizations, refactorings, algorithm changes, and changes +to separate subsystems as separate pull requests. + +For a performance change: + +- Give each independently applicable optimization its own pull request. +- Explain the workload and code path that the change targets. +- If two changes depend on each other, submit them together. Explain the + dependency in the description. + +Small pull requests can be reviewed, benchmarked, reverted, and bisected +independently. A pull request with eight independent changes produces one +number. That number does not show which change wins and which change loses. + +The maintainer can ask you to split a large pull request before detailed +review. The maintainer can decline to review or merge a pull request until its +scope is smaller. + +Open the first pull request and wait for feedback before you write the next +one. This avoids wasted work. + +## Performance changes + +Explain the expected effect and its cause. State known trade-offs. + +You do not need to submit benchmark results. The maintainer measures performance +claims on dedicated hardware. The review includes microbenchmarks and the full +file corpus. + +### Local benchmarks + +You can use the repository harness to check your change before submission: + +```sh +# Compare the current worktree against main. Profiles: enc, dec, ench. +./scripts/bench-compare.sh enc dec +``` + +The script builds a before binary from `main` and an after binary from your +worktree. It interleaves the two processes, collects samples, and runs +`benchstat`. Investigate each result across relevant workloads and code +alignments. + +On a Linux machine with `sudo`, wrap the run in a denoise script. It disables +boost, sets the performance governor, and pins the run to one physical core: + +```sh +./scripts/denoise-amd.sh ./scripts/bench-compare.sh enc +# or, on Intel: +./scripts/denoise-intel.sh ./scripts/bench-compare.sh enc +``` + +To diff hardware counters for a hot loop, use: + +```sh +./scripts/perf-compare.sh 'BenchmarkMatchLenAtLong' +``` + +Useful environment variables: `COUNT`, `BENCHTIME`, `QUALITIES`, `PAYLOADS`, +`BASE_BRANCH`, `FUNCALIGNS`. + +Code alignment can shift benchmark results by several percent on amd64. Use +`FUNCALIGNS` to compare several alignments before you attribute a result to the +code change. + +## Correctness + +Performance never wins over correctness. Run these checks before you open a +pull request: + +```sh +go test ./... # with the SIMD paths +go test -tags purego ./... # with the generic paths +``` + +Both must pass. CI runs both. + +The compatibility tests compare the encoder output against the C reference +implementation, byte for byte. They need `lib/libbrotli_cref.a`. + +Test output must be clean. If a test expects an error, it must assert that +error. + +### Differential fuzzing + +The targets in `fuzz_cref_test.go` compare Go with Google's C reference: + +- `FuzzEncodeCRef` checks encoder equivalence and cross-decoding, including + chunked writes, flushes, and streaming reads. +- `FuzzDecodeCRef` compares acceptance and decoded bytes. It accounts for + trailing bytes: C ignores them, while Go returns `ErrExcessiveInput`. +- `FuzzCompoundDictCRef` checks encoding and decoding with a raw compound + dictionary. + +Encoder equivalence checks use a single write on both sides. Chunked writes +and flushes are checked by decoding with both implementations, since write +boundaries can change valid compressed output. + +At quality 10–11, small rounding differences between Go's `math.Log2` and +the C math library's `log2` can change the encoder's estimated costs and +command choices. These differences can affect multiple commands, so a small +byte or percentage allowance is not a correctness guarantee for arbitrary +inputs. Without a compound dictionary, quality 5–9 with windows above 16 +can also choose different matches in Go and C. + +For these settings, fuzzing requires exact decoded bytes from both decoders +but imposes no compressed-size limit. Other settings retain byte-for-byte +encoder comparisons. Compression-size limits in the fixed-corpus tests are +regression budgets for those workloads, not correctness rules for arbitrary +fuzz inputs. + +Build the pinned Google reference implementation, then explicitly enable +mutation fuzzing (ordinary `go test` only replays the seed corpus): + +```sh +git submodule update --init +make lib/libbrotli_cref.a +go test -run='^$' -fuzz='^FuzzDecodeCRef$' -fuzztime=5m -parallel=4 . +go test -tags=purego -run='^$' -fuzz='^FuzzEncodeCRef$' -fuzztime=5m -parallel=4 . +``` + +Use `-fuzz='^FuzzCompoundDictCRef$'` to run the dictionary target. Fuzzing +requires cgo and a C compiler, including with `-tags=purego`. Plaintext and +dictionary inputs are capped at 64 KiB, compressed inputs at 8 KiB; these +limits do not cap decoded output. Go saves failing inputs under +`testdata/fuzz//`. Minimize and commit them only when they add coverage +that is not already captured by a focused regression test or an intentional +seed. CI runs the seed corpus on every push. + +The `Nightly` workflow runs mutation fuzzing every night. On a failure it +uploads the failing inputs as an artifact. + +## Code style + +- Match the style of the file that you edit. +- Keep comments short. Explain why, not what. +- Do not write a comment about how the code changed. That belongs in git. +- Do not reformat lines that your change does not touch. + +## AI-assisted contributions + +You can use an AI tool to write code. The rules do not change: + +- You understand the code that you submit. +- You ran the tests yourself. +- You can answer questions about the design in review. + +Generated volume is not a contribution. A pull request that the author cannot +explain will be closed. + +## Review expectations + +A performance pull request takes a long time to review. The maintainer +benchmarks every change against a file corpus on dedicated hardware. This work +is serial and slow. + +A small, focused pull request gets reviewed faster than a large one. + +## What blocks a merge + +The maintainer will request changes in these cases: + +- The pull request contains several independent changes. +- The description does not explain the reason for the change. +- The `purego` build or the C reference compatibility tests fail. + +The maintainer can close the pull request if the author does not address the +request. + +## License + +go-brrr uses the MIT license. Your contribution goes under the same license. diff --git a/src/vendor/github.com/andybalholm/brotli/LICENSE b/src/vendor/github.com/molecule-man/go-brrr/LICENSE similarity index 79% rename from src/vendor/github.com/andybalholm/brotli/LICENSE rename to src/vendor/github.com/molecule-man/go-brrr/LICENSE index 33b7cdd2..48103a8d 100644 --- a/src/vendor/github.com/andybalholm/brotli/LICENSE +++ b/src/vendor/github.com/molecule-man/go-brrr/LICENSE @@ -1,4 +1,6 @@ -Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. +MIT License + +Copyright (c) 2026 Andrii Berezhynskyi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -7,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/vendor/github.com/molecule-man/go-brrr/Makefile b/src/vendor/github.com/molecule-man/go-brrr/Makefile new file mode 100644 index 00000000..5fbc19b9 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/Makefile @@ -0,0 +1,16 @@ +.PHONY: init +init: + git submodule update --init + go install golang.org/x/perf/cmd/benchstat@latest + go install github.com/campoy/embedmd@latest + $(MAKE) lib/libbrotli_cref.a + +lib/libbrotli_cref.a: testdata/build_libbrotli_cref.sh \ + $(wildcard brotli-ref/c/common/*.c) \ + $(wildcard brotli-ref/c/dec/*.c) \ + $(wildcard brotli-ref/c/enc/*.c) \ + $(wildcard brotli-ref/c/common/*.h) \ + $(wildcard brotli-ref/c/dec/*.h) \ + $(wildcard brotli-ref/c/enc/*.h) \ + $(wildcard brotli-ref/c/include/brotli/*.h) + testdata/build_libbrotli_cref.sh diff --git a/src/vendor/github.com/molecule-man/go-brrr/README.md b/src/vendor/github.com/molecule-man/go-brrr/README.md new file mode 100644 index 00000000..dd7a2256 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/README.md @@ -0,0 +1,205 @@ +![go brrr](assets/go-brrr-logo.jpg) + +# go-brrr - Brotli compression for Go + +[![CI](https://github.com/molecule-man/go-brrr/actions/workflows/ci.yml/badge.svg)](https://github.com/molecule-man/go-brrr/actions/workflows/ci.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/molecule-man/go-brrr.svg)](https://pkg.go.dev/github.com/molecule-man/go-brrr) +[![Go Report Card](https://goreportcard.com/badge/github.com/molecule-man/go-brrr)](https://goreportcard.com/report/github.com/molecule-man/go-brrr) +[![Version](https://img.shields.io/github/v/tag/molecule-man/go-brrr?sort=semver)](https://github.com/molecule-man/go-brrr/tags) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) + +Brotli compression library for Go (RFC 7932), with encoder and decoder support. + +## Highlights + +- **No C toolchain.** Builds with standard Go tooling. +- **Faster than other pure-Go brotli libraries** at every quality level we measure (see [Benchmarks](#benchmarks)). +- **Faster than CGO brotli** (cbrotli) in our benchmarks, for compression at q0-q11 and for one-shot decompression. +- **Compound dictionaries.** +- **Encoder tuning.** `LGWin` (window size) and `SizeHint` (expected total input size) are exposed via `WriterOptions`. `SizeHint` lets the encoder pick context modeling and hasher parameters tuned for the actual payload size. + +## Status + +The encoder and decoder are covered by compatibility tests and fuzzing. The public API is stable and follows semantic versioning. + +## Compatibility + +go-brrr implements Brotli RFC 7932 and is tested against the Brotli reference corpus. Encoded output is byte-compatible with the C reference implementation. + +## Compared to other Go brotli libraries + +| | go-brrr | [andybalholm](https://github.com/andybalholm/brotli) | [google/brotli/go/brotli](https://github.com/google/brotli/tree/master/go/brotli) | [cbrotli](https://github.com/google/brotli/tree/master/go/cbrotli) | +|---|---|---|---|---| +| Pure Go (no cgo) | ✓ | ✓ | ✓ | ✗ | +| Encoder | ✓ | ✓ | ✗ | ✓ | +| Decoder | ✓ | ✓ | ✓ | ✓ | +| Compound dictionaries (encode) | ✓ | ✗ | n/a | ✓ | +| Compound dictionaries (decode) | ✓ | ✗ | ✓ | ✓ | +| `LGWin` tuning | ✓ | ✓ | n/a | ✓ | +| `SizeHint` | ✓ | ✗ | n/a | ✗ | +| Writer `Reset` | ✓ | ✓ | n/a | ✗ | +| Reader `Reset` | ✓ | ✓ | ✗ | ✗ | + +If you're using `andybalholm/brotli`, go-brrr is a near drop-in upgrade with higher throughput on both compression and decompression, plus compound-dictionary and `SizeHint` support. If you're using `cbrotli`, go-brrr gives up cgo, adds multi-chunk compound dictionaries, and exposes poolable `Writer`/`Reader` instances. `cbrotli` has no `Reset`, so each stream allocates a fresh encoder/decoder state, which is noticeable on many-small-file workloads. + +## Install + +```sh +go get github.com/molecule-man/go-brrr +``` + +```go +import "github.com/molecule-man/go-brrr" +``` + +The import path is `github.com/molecule-man/go-brrr`; the package name is `brrr`. + +## Examples + +### Compression + +[embedmd]:# (example_test.go go /func Example_compress/ /^}/) +```go +func Example_compress() { + input := []byte("Hello, brotli!") + + var compressed bytes.Buffer + w, err := brrr.NewWriter(&compressed, 6) + if err != nil { + log.Fatal(err) + } + if _, err := w.Write(input); err != nil { + log.Fatal(err) + } + if err := w.Close(); err != nil { + log.Fatal(err) + } +} +``` + +More examples are available in [example_test.go](example_test.go) and the [Go package docs](https://pkg.go.dev/github.com/molecule-man/go-brrr#pkg-examples): round-trip compression and decompression, one-shot decompression, reusing writers and readers, pooling, and compound dictionaries. + +## When to use go-brrr + +The best use case for brotli is **static asset compression** - CSS, JS, HTML, fonts, WASM - where you compress once at build time and serve the result millions of times. Use **quality 11** for this: speed doesn't matter because you pay the cost once, and brotli q11 delivers ratios that neither gzip nor zstd can match. Every browser shipped since 2016 supports `Content-Encoding: br`. + +For on-the-fly compression, brotli q5–6 is a strong choice if you're already using zstd at its highest level: q5 is often **faster** with a **better ratio**, and q6 is only slightly slower with an even better ratio. At lower compression levels, zstd is significantly faster - if throughput is your priority and you don't need the best ratio, zstd is the better tool for the job. + +If you compress or decompress repeatedly (e.g. per request in a webserver), keep `*brrr.Writer` and `*brrr.Reader` instances in `sync.Pool`s and `Reset` each one into the next stream rather than allocating new instances each time. See the [compiled examples](example_test.go). + +## Implementation notes + +go-brrr is optimized for throughput. Some hot paths intentionally use larger functions, duplicated loops, and specialized code where benchmarks showed measurable wins. These choices stay local to performance-sensitive encoder and decoder internals; public APIs stay small and conventional. + +## Contributing + +Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before you start. + +The most important rules: + +- **One pull request is one logical change.** Independent optimizations go into separate pull requests, so each one can be benchmarked, reverted, and bisected on its own. +- **Explain the expected effect and its cause.** + +The maintainer measures every performance change against a file corpus on dedicated hardware. + +For a large optimization, open an issue first and agree on the scope. + +## Acknowledgments + +This library is a port of the [Brotli reference implementation](https://github.com/google/brotli) by the Brotli Authors, licensed under the MIT License. + +## Compression Speed vs Ratio + +All benchmarks were taken on the following setup with turboboost, etc, being +disabled via [denoise-amd.sh](scripts/denoise-amd.sh): + +``` +goos: linux +goarch: amd64 +cpu: AMD Ryzen 5 7535HS with Radeon Graphics +``` + +Compared against [klauspost/compress](https://github.com/klauspost/compress) zstd (pure Go) and stdlib gzip. Single CPU, no parallelism. These plots measure reused streaming encoders: the timed loop resets a warmed writer and discards compressed output, while ratio is measured from a warmup buffer. + +| Compression | Decompression | +|---|---| +| ![HTML 522KB](assets/gh_522KB_html.png) | ![HTML 522KB](assets/gh_522KB_html_decompress.png) | +| ![JS 187KB](assets/reactcore_187KB_js.png) | ![JS 187KB](assets/reactcore_187KB_js_decompress.png) | +| ![JSON 58KB](assets/github_events_58KB_json.png) | ![JSON 58KB](assets/github_events_58KB_json_decompress.png) | + +## Benchmarks + +Compared against other Go brotli libraries. **go-brrr** is the base in all comparisons. The smaller the number the better. + +- **andybalholm** - [github.com/andybalholm/brotli](https://github.com/andybalholm/brotli), pure Go encoder and decoder. +- **google-brotli** - [github.com/google/brotli/go/brotli](https://github.com/google/brotli/tree/master/go/brotli), Google's official pure Go decoder, transpiled from the Java reference. Decompression only, no encoder. +- **cbrotli** - [github.com/google/brotli/go/cbrotli](https://github.com/google/brotli/tree/master/go/cbrotli), Google's official cgo bindings to the C reference implementation. Including a cgo library in a pure Go comparison isn't apples-to-apples, but it is a useful comparison against Google's C implementation as exposed through its Go bindings. + +### One-shot Compression + +The table below measures end-to-end throughput through each package's public Go API for many independent brotli streams, not only the inner compression loop. Each payload is written as a complete stream with a fresh public writer instance so `cbrotli`, which has no resettable writer API, can be included. + +`go-brrr` still benefits from internal reuse in that shape: encoder arenas, hashers, hash tables, and scratch buffers are kept reusable through reset paths and internal `sync.Pool`s. That avoids repeated large allocations and zeroing, which matters for small and mid-size payloads. `cbrotli` uses the C reference encoder underneath, but each payload creates a new `BrotliEncoderState` through `cbrotli.NewWriter` and destroys it on `Close`, paying setup, teardown, cgo, and allocation costs for every stream. + +Read these rows as repeated complete-stream compression through the Go APIs. They are not a claim that every pure-Go hot path is faster than the C implementation. Part of the gap comes from per-stream setup and cgo cost in `cbrotli`. + + +| | go-brrr (sec/op) | andybalholm (sec/op) | cbrotli (sec/op) | +| --- | --- | --- | --- | +| CompressOneshot/q=0/payload=VariedPayloads | 6.342m ± 0% | 12.447m ± 1% +96.25% (p=0.000) | 6.868m ± 0% +8.29% (p=0.000) | +| CompressOneshot/q=1/payload=VariedPayloads | 9.530m ± 0% | 20.163m ± 0% +111.57% (p=0.000) | 10.824m ± 0% +13.58% (p=0.000) | +| CompressOneshot/q=2/payload=VariedPayloads | 14.74m ± 0% | 39.29m ± 5% +166.60% (p=0.000) | 18.09m ± 0% +22.76% (p=0.000) | +| CompressOneshot/q=3/payload=VariedPayloads | 15.89m ± 0% | 43.29m ± 5% +172.39% (p=0.000) | 20.94m ± 0% +31.77% (p=0.000) | +| CompressOneshot/q=4/payload=VariedPayloads | 25.07m ± 0% | 62.03m ± 2% +147.45% (p=0.000) | 30.13m ± 0% +20.19% (p=0.000) | +| CompressOneshot/q=5/payload=VariedPayloads | 35.77m ± 0% | 80.57m ± 1% +125.28% (p=0.000) | 47.34m ± 0% +32.37% (p=0.000) | +| CompressOneshot/q=6/payload=VariedPayloads | 43.44m ± 0% | 90.94m ± 1% +109.32% (p=0.000) | 54.76m ± 0% +26.05% (p=0.000) | +| CompressOneshot/q=7/payload=VariedPayloads | 50.07m ± 0% | 125.95m ± 1% +151.52% (p=0.000) | 107.23m ± 0% +114.15% (p=0.000) | +| CompressOneshot/q=8/payload=VariedPayloads | 58.44m ± 1% | 146.65m ± 1% +150.97% (p=0.000) | 82.10m ± 0% +40.49% (p=0.000) | +| CompressOneshot/q=9/payload=VariedPayloads | 73.59m ± 0% | 209.19m ± 1% +184.26% (p=0.000) | 232.63m ± 0% +216.11% (p=0.000) | +| CompressOneshot/q=10/payload=VariedPayloads | 814.9m ± 0% | 1346.7m ± 2% +65.27% (p=0.000) | 856.2m ± 1% +5.08% (p=0.000) | +| CompressOneshot/q=11/payload=VariedPayloads | 1.587 ± 0% | 3.365 ± 1% +112.05% (p=0.000) | 2.266 ± 0% +42.77% (p=0.000) | +| **geomean** | 48.10m | 110.7m +130.18% | 67.37m +40.05% | + + +*Streaming* uses `brrr.NewReader` + `io.ReadAll`; *one-shot* uses `brrr.Decompress` on a complete in-memory blob. + +### Streaming Decompression + +As cbrotli doesn't have the "resettable" API it's not included here. + + +| | go-brrr (sec/op) | andybalholm (sec/op) | diff | p | +| --- | --- | --- | --- | --- | +| Decompress/q=4/payload=VariedPayloads | 4.373m ± 0% | 9.593m ± 0% | +119.38% | 0.000 | +| Decompress/q=5/payload=VariedPayloads | 4.181m ± 0% | 9.183m ± 0% | +119.62% | 0.000 | +| Decompress/q=6/payload=VariedPayloads | 4.052m ± 0% | 8.914m ± 0% | +119.97% | 0.000 | +| Decompress/q=11/payload=VariedPayloads | 4.645m ± 0% | 8.925m ± 0% | +92.16% | 0.000 | +| **geomean** | 4.307m | 9.150m | +112.43% | | + + +### One-shot Decompression + + +| | go-brrr (sec/op) | andybalholm (sec/op) | cbrotli (sec/op) | google-brotli (sec/op) | +| --- | --- | --- | --- | --- | +| DecompressOneshot/q=4/payload=VariedPayloads | 4.549m ± 0% | 10.082m ± 0% +121.63% (p=0.000) | 5.286m ± 2% +16.21% (p=0.000) | 10.470m ± 0% +130.16% (p=0.000) | +| DecompressOneshot/q=5/payload=VariedPayloads | 4.433m ± 0% | 9.611m ± 0% +116.82% (p=0.000) | 5.023m ± 1% +13.32% (p=0.000) | 10.549m ± 0% +137.98% (p=0.000) | +| DecompressOneshot/q=6/payload=VariedPayloads | 4.318m ± 0% | 9.415m ± 0% +118.05% (p=0.000) | 4.936m ± 1% +14.31% (p=0.000) | 10.176m ± 0% +135.69% (p=0.000) | +| DecompressOneshot/q=11/payload=VariedPayloads | 4.904m ± 0% | 9.377m ± 0% +91.22% (p=0.000) | 6.534m ± 0% +33.25% (p=0.000 | **crashed** | +| **geomean** | 4.546m | 9.617m +111.57% | 5.410m +19.01% | 10.40m +134.59% | + + + +The `VariedPayloads` benchmark rotates through a heterogeneous mix of files, guarding against benchmark-shaped optimizations - wins that only show up when the same input is fed back-to-back should not move these rows. Payloads span small JSON API responses, mid-size HTML and JS bundles, and larger English prose, drawn from the [Brotli reference test corpus](https://github.com/google/brotli/tree/master/tests/testdata) and the local [testdata/](testdata/) directory. + +| File | Size | Source | +|-----------------------|-------:|------------| +| github_events_2k.json | 2.2 KB | testdata | +| github_events_5k.json | 5.2 KB | testdata | +| github_events_8k.json | 8.3 KB | testdata | +| asyoulik.txt | 122 KB | brotli-ref | +| alice29.txt | 149 KB | brotli-ref | +| gh_172KB.html | 167 KB | testdata | +| reactcore_187KB.js | 182 KB | testdata | +| lcet10.txt | 417 KB | brotli-ref | +| plrabn12.txt | 471 KB | brotli-ref | diff --git a/src/vendor/github.com/molecule-man/go-brrr/bitreader.go b/src/vendor/github.com/molecule-man/go-brrr/bitreader.go new file mode 100644 index 00000000..2bc24b92 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/bitreader.go @@ -0,0 +1,279 @@ +// Bit-level reading primitives for the decoder input stream. + +package brrr + +import "unsafe" + +// fastInputSlack is the minimum bytes of unconsumed input required for +// fast-path bit reading (162 bits + 11 bytes of margin for the 8-byte refill). +const fastInputSlack = 32 + +// bitReaderState is a snapshot of a bitReader, used to save and restore +// position for speculative reads that may need to be rolled back. +type bitReaderState struct { + pos int + val uint64 + bitPos uint +} + +// init resets the bit reader to a clean initial state. +func (br *bitReader) init() { + br.val = 0 + br.bitPos = 0 + br.input = nil + br.inputLen = 0 + br.pos = 0 + br.inputBase = nil + br.fastEnd = -1 // no input → always fail fast-path check +} + +// setInput sets the input buffer for the bit reader. The reader starts +// consuming from the beginning of data. +func (br *bitReader) setInput(data []byte) { + br.input = data + br.inputLen = len(data) + br.pos = 0 + br.inputBase = unsafe.Pointer(unsafe.SliceData(data)) + br.fastEnd = len(data) - fastInputSlack +} + +// warmup pulls bytes until the accumulator is non-empty. +// Returns false if data is required but there is no input available. +func (br *bitReader) warmup() bool { + if br.bitPos == 0 { + br.val = 0 + if !br.pullByte() { + return false + } + } + return true +} + +// saveState returns a snapshot of the current reader position. +func (br *bitReader) saveState() bitReaderState { + return bitReaderState{ + pos: br.pos, + val: br.val, + bitPos: br.bitPos, + } +} + +// restoreState restores the reader to a previously saved state. +func (br *bitReader) restoreState(s bitReaderState) { + br.pos = s.pos + br.val = s.val + br.bitPos = s.bitPos +} + +// availIn returns the number of unconsumed input bytes (excluding bits +// already loaded into the accumulator). +func (br *bitReader) availIn() int { + return br.inputLen - br.pos +} + +// availBits returns the number of valid bits in the accumulator. +func (br *bitReader) availBits() uint { + return br.bitPos +} + +// remainingBytes returns the number of unread bytes, including whole bytes +// buffered in the accumulator. Capped at 1<<30. +func (br *bitReader) remainingBytes() int { + const remainingCap = 1 << 30 + avail := br.availIn() + if avail > remainingCap { + return remainingCap + } + return avail + int(br.bitPos>>3) +} + +// checkInputAmount reports whether enough unconsumed input remains for +// fast-path bit reading. Uses precomputed fastEnd to avoid a subtraction. +func (br *bitReader) checkInputAmount() bool { + return br.pos <= br.fastEnd +} + +// fillBitWindow ensures that at least nBits+1 bits are available in the +// accumulator. If the accumulator has fewer than 32 valid bits, 4 bytes are +// loaded from input. nBits must be in the range [1..24]. +func (br *bitReader) fillBitWindow(nBits uint) { + _ = nBits // used for documentation; the 64-bit path handles up to 32 + if br.bitPos < 32 { + br.val |= uint64(*(*uint32)(unsafe.Add(br.inputBase, br.pos))) << br.bitPos + br.bitPos += 32 + br.pos += 4 + } +} + +// fillBitWindow16 ensures at least 17 bits are available. +func (br *bitReader) fillBitWindow16() { + br.fillBitWindow(17) +} + +// bitsUnmasked returns the raw accumulator value. The number of valid bits +// is given by availBits. +func (br *bitReader) bitsUnmasked() uint64 { + return br.val +} + +// getBits returns n bits from the accumulator without advancing. The +// accumulator is filled first if needed. +func (br *bitReader) getBits(n uint) uint64 { + br.fillBitWindow(n) + return br.val & bitMask(n) +} + +// dropBits discards the lowest n bits from the accumulator. +// n must be less than 64; in practice it is at most 15 (max Huffman code length). +// The & 63 mask is a no-op on the value but lets the compiler emit a plain +// shift instead of Go's safe-shift sequence (SHRQ+CMPQ+SBBQ+ANDQ → SHRQ). +func (br *bitReader) dropBits(n uint) { + br.bitPos -= n + br.val >>= n & 63 +} + +// takeBits returns the lowest n bits and discards them. +func (br *bitReader) takeBits(n uint) uint64 { + v := br.val & bitMask(n) + br.dropBits(n) + return v +} + +// readBits reads up to 24 bits from the input. The accumulator is filled +// first if needed. +func (br *bitReader) readBits(n uint) uint64 { + br.fillBitWindow(n) + return br.takeBits(n) +} + +// readBits32 reads up to 32 bits from the input. On 64-bit platforms this +// is identical to readBits. +func (br *bitReader) readBits32(n uint) uint64 { + br.fillBitWindow(n) + return br.takeBits(n) +} + +// pullByte loads one byte from input into the accumulator. Returns false +// if no input is available. +func (br *bitReader) pullByte() bool { + if br.pos >= br.inputLen { + return false + } + br.val |= uint64(br.input[br.pos]) << br.bitPos + br.bitPos += 8 + br.pos++ + return true +} + +// safeGetBits peeks at n bits, pulling bytes as needed. Returns the value +// and true on success, or 0 and false if insufficient input. +func (br *bitReader) safeGetBits(n uint) (uint64, bool) { + for br.bitPos < n { + if !br.pullByte() { + return 0, false + } + } + return br.val & bitMask(n), true +} + +// safeReadBits reads up to 24 bits, pulling bytes as needed. Returns the +// value and true on success, or 0 and false if insufficient input. +func (br *bitReader) safeReadBits(n uint) (uint64, bool) { + for br.bitPos < n { + if !br.pullByte() { + return 0, false + } + } + return br.takeBits(n), true +} + +// safeReadBits32 reads up to 32 bits, pulling bytes as needed. On 64-bit +// platforms this is identical to safeReadBits for n <= 24; for n > 24 it +// falls back to safeReadBits32Slow. +func (br *bitReader) safeReadBits32(n uint) (uint64, bool) { + if n <= 24 { + return br.safeReadBits(n) + } + return br.safeReadBits32Slow(n) +} + +// safeReadBits32Slow handles safe reads of more than 24 bits by splitting +// into two 16-bit reads with state save/restore on failure. +func (br *bitReader) safeReadBits32Slow(n uint) (uint64, bool) { + memento := br.saveState() + lowVal, ok := br.safeReadBits(16) + if !ok { + br.restoreState(memento) + return 0, false + } + highVal, ok := br.safeReadBits(n - 16) + if !ok { + br.restoreState(memento) + return 0, false + } + return lowVal | (highVal << 16), true +} + +// normalize clears any bits above bitPos in the accumulator (Spectre +// mitigation for cases where bytes are skipped without being loaded). +func (br *bitReader) normalize() { + if br.bitPos < 64 { + br.val &= bitMask(br.bitPos) + } +} + +// unload pushes unused whole bytes from the accumulator back into the +// unconsumed input by decrementing pos. +func (br *bitReader) unload() { + unusedBytes := br.bitPos >> 3 + unusedBits := unusedBytes << 3 + if unusedBytes > 0 { + br.pos -= int(unusedBytes) + } + br.bitPos -= unusedBits + br.normalize() +} + +// jumpToByteBoundary advances to the next byte boundary and verifies that +// any skipped padding bits are zero. Returns false if non-zero padding is +// found. +func (br *bitReader) jumpToByteBoundary() bool { + padBitsCount := br.bitPos & 0x7 + padBits := uint64(0) + if padBitsCount != 0 { + padBits = br.takeBits(padBitsCount) + } + br.normalize() + return padBits == 0 +} + +// dropBytes advances the byte position by n. The accumulator must be empty. +func (br *bitReader) dropBytes(n int) { + br.pos += n +} + +// copyBytes copies num bytes from the reader to dest. Drains the +// accumulator first, then copies directly from input. +func (br *bitReader) copyBytes(dest []byte) { + i := 0 + num := len(dest) + for br.bitPos >= 8 && i < num { + dest[i] = byte(br.val) + br.dropBits(8) + i++ + } + br.normalize() + if i < num { + copy(dest[i:], br.input[br.pos:br.pos+num-i]) + br.pos += num - i + } +} + +// bitMask returns a mask with the lowest n bits set. +// Uses shift-subtract instead of a table lookup to avoid a memory load +// and reduce L1 cache pressure in the decode hot path. +// The & 63 lets the compiler prove the shift is in-range, eliminating +// the Go overflow check. All callers pass n ≤ 24. +func bitMask(n uint) uint64 { + return (uint64(1) << (n & 63)) - 1 +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/brotli.go b/src/vendor/github.com/molecule-man/go-brrr/brotli.go new file mode 100644 index 00000000..f9a283c1 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/brotli.go @@ -0,0 +1,54 @@ +// Public package-level constants and option structs. + +package brrr + +// Compression level constants. +const ( + BestSpeed = 0 + BestCompression = 11 +) + +// Window size limits (RFC 7932 Section 9.1). +const ( + minLGWin = 10 + maxLGWin = 24 + defaultLGWin = 22 +) + +// WriterOptions configures advanced tuning knobs for the brotli encoder. +// The compression level is passed positionally to NewWriter / NewWriterOptions. +type WriterOptions struct { + // Dictionaries are compound dictionary chunks the encoder may reference + // as backward distances beyond the ring buffer, useful when inputs share + // content with a known corpus. Build each chunk once with + // [PrepareDictionary] and share the resulting *PreparedDictionary across + // any number of Writers. Up to 15 chunks are allowed and compound + // dictionaries require compression level >= 2. Dictionaries are preserved + // across Reset. + Dictionaries []*PreparedDictionary + + // LGWin sets the base-2 logarithm of the sliding window size (10–24). + // 0 selects the default (22). + LGWin int + + // SizeHint is the expected total input size in bytes. When set, the + // encoder uses it to make better decisions about context modeling and + // hasher selection for large inputs. 0 means unknown; the encoder will + // auto-estimate from the first Write call. + // + // SizeHint is advisory: a lower-than-actual value is safe in both + // correctness and compression ratio. The encoder transparently + // promotes its internal hasher to the unbounded variant if buffered + // input crosses the size-tuned threshold, preserving the bucket state + // that was learned under the small-hint dispatch. + SizeHint uint +} + +// ReaderOptions configures the brotli decoder. +type ReaderOptions struct { + // Dictionaries are compound dictionary chunks the decoder will use to + // resolve backward references beyond the ring buffer. They must match + // the dictionaries supplied to the encoder. Up to 15 chunks are allowed; + // each must be non-empty. Dictionaries are preserved across Reset. + Dictionaries [][]byte +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/decode.go b/src/vendor/github.com/molecule-man/go-brrr/decode.go new file mode 100644 index 00000000..cc79c60b --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/decode.go @@ -0,0 +1,2382 @@ +// Brotli decompression via a suspendable state machine (dec/decode.c). + +package brrr + +import ( + "errors" + "sync" + "unsafe" + + "github.com/molecule-man/go-brrr/internal/core" +) + +// Decoder-specific constants. +const ( + huffmanTableBits = 8 + huffmanTableMask = 0xFF + ringBufferWriteAheadSlack = 542 + maxAllowedDistance = 0x7FFFFFFC + + // symListBase is the offset into symbolListsArray that makes C-style + // negative indices in nextSymbol[] addressable. + symListBase = core.HuffmanMaxCodeLength + 1 +) + +// Static prefix code for the complex code length code lengths (RFC 7932 §3.5). +var codeLengthPrefixLength = [16]byte{ + 2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4, +} + +var codeLengthPrefixValue = [16]byte{ + 0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5, +} + +// ErrExcessiveInput reports bytes that follow finalized brotli stream. +var ErrExcessiveInput = errors.New("brotli: excessive input") + +// Sentinel errors returned by Decompress. +var errPadding = errors.New("brotli: non-zero padding bits") + +var decodeStatePool = sync.Pool{ + New: func() any { + s := new(decodeState) + s.init() + s.outChunks = chunkWriter{pool: &decodeChunkPool, size: decodeChunkSize} + return s + }, +} + +// decRingBufPool caches decoder ring buffer slices to reduce allocation +// pressure in streaming (Reader) decompression, where a new decodeState is +// created per Reader. The oneshot Decompress path already pools the entire +// decodeState (including its ring buffer). +var decRingBufPool sync.Pool + +var cmdLutPacked = packCmdLut() + +func packCmdLut() (t [core.AlphabetSizeInsertAndCopyLength]uint64) { + for i := range core.CmdLut { + e := &core.CmdLut[i] + t[i] = uint64(e.InsertLenExtraBits) | uint64(e.CopyLenExtraBits)<<8 | uint64(uint8(e.DistanceCode))<<16 | + uint64(e.Context)<<24 | uint64(e.InsertLenOffset)<<32 | uint64(e.CopyLenOffset)<<48 + } + return t +} + +func getDecRingBuf(size int) []byte { + if v := decRingBufPool.Get(); v != nil { + bp := v.(*[]byte) + if cap(*bp) >= size { + return (*bp)[:size] + } + // Wrong size — let GC reclaim it. + } + return make([]byte, size) +} + +func putDecRingBuf(buf []byte) { + if buf != nil { + b := buf[:cap(buf)] + decRingBufPool.Put(&b) + } +} + +// Decompress decodes the brotli-compressed data and returns the original bytes. +// +// It returns [ErrExcessiveInput] if bytes follow the stream. +func Decompress(data []byte) ([]byte, error) { + s := decodeStatePool.Get().(*decodeState) + s.initForReuse() + s.br.setInput(data) + s.sink = &s.outChunks + err := s.decodeAll() + s.sink = nil + if err != nil { + s.outChunks.discard() + decodeStatePool.Put(s) + return nil, err + } + out := s.outChunks.take() + decodeStatePool.Put(s) + return out, nil +} + +func (s *decodeState) decodeAll() error { + var output []byte + for { + switch s.decompressStream(&output) { + case decoderResultSuccess: + if s.excessiveInput() { + return ErrExcessiveInput + } + s.flushOutput(output) + return nil + case decoderResultError: + return s.err + case decoderResultNeedsMoreInput: + return decompressError("truncated input") + case decoderResultNeedsMoreOutput: + output = s.flushOutput(output) + } + } +} + +// decompressStream advances the decoder state machine. Returns a result +// indicating success, error, or that more input/output is needed. +func (s *decodeState) decompressStream(output *[]byte) decoderResult { + for { + switch s.state { + case decoderStateUninited: + if !s.br.warmup() { + return decoderResultNeedsMoreInput + } + if err := s.decodeWindowBits(); err != nil { + s.err = err + return decoderResultError + } + s.state = decoderStateInitialize + fallthrough + + case decoderStateInitialize: + s.maxBackwardDistance = (1 << s.windowBits) - core.WindowGap + allTrees := reuseHuffmanCodes(s.blockTypeTrees, 3*(huffmanMaxSize258+huffmanMaxSize26)) + s.blockTypeTrees = allTrees[:3*huffmanMaxSize258] + s.blockLenTrees = allTrees[3*huffmanMaxSize258:] + s.state = decoderStateMetablockBegin + fallthrough + + case decoderStateMetablockBegin: + s.metablockBegin() + s.state = decoderStateMetablockHeader + fallthrough + + case decoderStateMetablockHeader: + result := s.decodeMetaBlockLength() + if result != decoderResultSuccess { + return result + } + if s.isMetadata || s.isUncompressed { + if !s.br.jumpToByteBoundary() { + s.err = errPadding + return decoderResultError + } + } + if s.isMetadata { + s.state = decoderStateMetadata + break + } + if s.metaBlockRemainingLen == 0 { + s.state = decoderStateMetablockDone + break + } + s.calculateRingBufferSize() + if s.isUncompressed { + s.state = decoderStateUncompressed + break + } + s.state = decoderStateBeforeCompressedMetablockHeader + fallthrough + + case decoderStateBeforeCompressedMetablockHeader: + h := &s.headerArena + s.loopCounter = 0 + h.subLoopCounter = 0 + h.symbolLists = h.symbolListsArray[core.HuffmanMaxCodeLength+1:] + h.substateHuffman = huffmanNone + h.substateTreeGroup = treeGroupNone + h.substateContextMap = contextMapNone + s.state = decoderStateHuffmanCode0 + fallthrough + + case decoderStateHuffmanCode0: + if s.loopCounter >= 3 { + s.state = decoderStateMetablockHeader2 + break + } + result := s.decodeVarLenUint8(&s.numBlockTypes[s.loopCounter]) + if result != decoderResultSuccess { + return result + } + s.numBlockTypes[s.loopCounter]++ + if s.numBlockTypes[s.loopCounter] < 2 { + s.loopCounter++ + break + } + s.state = decoderStateHuffmanCode1 + fallthrough + + case decoderStateHuffmanCode1: + alphabetSize := s.numBlockTypes[s.loopCounter] + 2 + treeOffset := s.loopCounter * huffmanMaxSize258 + result := s.readHuffmanCode(alphabetSize, alphabetSize, + s.blockTypeTrees[treeOffset:], nil) + if result != decoderResultSuccess { + return result + } + s.state = decoderStateHuffmanCode2 + fallthrough + + case decoderStateHuffmanCode2: + treeOffset := s.loopCounter * huffmanMaxSize26 + result := s.readHuffmanCode(core.AlphabetSizeBlockCount, core.AlphabetSizeBlockCount, + s.blockLenTrees[treeOffset:], nil) + if result != decoderResultSuccess { + return result + } + s.state = decoderStateHuffmanCode3 + fallthrough + + case decoderStateHuffmanCode3: + treeOffset := s.loopCounter * huffmanMaxSize26 + bl, ok := safeReadBlockLength(s, s.blockLenTrees[treeOffset:]) + if !ok { + return decoderResultNeedsMoreInput + } + s.blockLength[s.loopCounter] = bl + s.loopCounter++ + s.state = decoderStateHuffmanCode0 + + case decoderStateMetablockHeader2: + bits, ok := s.br.safeReadBits(6) + if !ok { + return decoderResultNeedsMoreInput + } + s.distancePostfixBits = uint(bits & bitMask(2)) + bits >>= 2 + s.numDirectDistanceCodes = uint(bits) << s.distancePostfixBits + s.contextModes = reuseBytes(s.contextModes, int(s.numBlockTypes[0])) + s.loopCounter = 0 + s.state = decoderStateContextModes + fallthrough + + case decoderStateContextModes: + result := s.readContextModes() + if result != decoderResultSuccess { + return result + } + s.state = decoderStateContextMap1 + fallthrough + + case decoderStateContextMap1: + result := s.decodeContextMap(s.numBlockTypes[0]<= s.ringbufferSize { + continue + } + } + if s.metaBlockRemainingLen == 0 { + s.state = decoderStateMetablockDone + } else { + s.state = decoderStateCommandBegin + } + case decoderStateCommandPostWrite2: + s.state = decoderStateCommandPostWrapCopy + default: // CommandInnerWrite + if s.loopCounter == 0 { + if s.metaBlockRemainingLen == 0 { + s.state = decoderStateMetablockDone + } else { + s.state = decoderStateCommandPostDecodeLiterals + } + } else { + s.state = decoderStateCommandInner + } + } + + case decoderStateMetadata: + result := s.skipMetadataBlock() + if result != decoderResultSuccess { + return result + } + s.state = decoderStateMetablockDone + + case decoderStateUncompressed: + result := s.copyUncompressedBlock(output) + if result != decoderResultSuccess { + return result + } + s.state = decoderStateMetablockDone + + case decoderStateMetablockDone: + if s.metaBlockRemainingLen < 0 { + s.err = decompressError("negative remaining metablock length") + return decoderResultError + } + if !s.isLastMetablock { + s.state = decoderStateMetablockBegin + break + } + if !s.br.jumpToByteBoundary() { + s.err = errPadding + return decoderResultError + } + s.state = decoderStateDone + fallthrough + + case decoderStateDone: + return decoderResultSuccess + + default: + s.err = decompressError("unhandled decoder state") + return decoderResultError + } + } +} + +// pendingOutput aliases unread ring-buffer bytes until decoding resumes. +// writeRingBuffer handles bytes in the write-ahead slack. +func (s *decodeState) pendingOutput() []byte { + pos := min(s.pos, s.ringbufferSize) + flushed := int(s.partialPosOut) - int(s.rbRoundtrips)*s.ringbufferSize + if pos <= flushed { + return nil + } + return s.ringbuffer[flushed:pos] +} + +func (s *decodeState) consumeOutput(n int) { + s.partialPosOut += uint(n) +} + +func (s *decodeState) flushOutput(output []byte) []byte { + pending := s.pendingOutput() + if len(pending) == 0 { + return output + } + if s.sink != nil { + s.sink.write(pending) + } else { + output = append(output, pending...) + } + s.consumeOutput(len(pending)) + return output +} + +// writeRingBuffer flushes the ring buffer when it fills, appending to output. +func (s *decodeState) writeRingBuffer(output *[]byte) { + if s.pos >= s.ringbufferSize { + if s.ringbufferSize < 1<= newSize+ringBufferWriteAheadSlack { + s.ringbuffer = s.ringbuffer[:newSize+ringBufferWriteAheadSlack] + } else { + newBuf := getDecRingBuf(newSize + ringBufferWriteAheadSlack) + copy(newBuf, s.ringbuffer[:s.pos]) + putDecRingBuf(s.ringbuffer) + s.ringbuffer = newBuf + } + s.ringbufferSize = newSize + s.ringbufferMask = newSize - 1 + s.newRingbufferSize = newSize + } + if s.pos < s.ringbufferSize { + return + } + } + if s.sink != nil { + s.sink.write(s.ringbuffer[int(s.partialPosOut)-int(s.rbRoundtrips)*s.ringbufferSize : s.ringbufferSize]) + } else { + *output = append(*output, s.ringbuffer[int(s.partialPosOut)-int(s.rbRoundtrips)*s.ringbufferSize:s.ringbufferSize]...) + } + s.partialPosOut = s.rbRoundtrips*uint(s.ringbufferSize) + uint(s.ringbufferSize) + s.pos -= s.ringbufferSize + s.rbRoundtrips++ + if s.pos > 0 { + copy(s.ringbuffer, s.ringbuffer[s.ringbufferSize:s.ringbufferSize+s.pos]) + } + s.maxDistance = s.maxBackwardDistance + } +} + +// --- Window bits --- + +func (s *decodeState) decodeWindowBits() error { + br := &s.br + n := br.takeBits(1) + if n == 0 { + s.windowBits = 16 + return nil + } + n = br.takeBits(3) + if n != 0 { + s.windowBits = int(17+n) & 63 + return nil + } + n = br.takeBits(3) + if n == 1 { + return decompressError("invalid window bits") + } + if n != 0 { + s.windowBits = int(8+n) & 63 + return nil + } + s.windowBits = 17 + return nil +} + +// --- Variable-length uint8 --- + +func (s *decodeState) decodeVarLenUint8(value *uint) decoderResult { + br := &s.br + switch s.substateDecodeUint8 { + case decodeUint8None: + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + if bits == 0 { + *value = 0 + return decoderResultSuccess + } + fallthrough + + case decodeUint8Short: + bits, ok := br.safeReadBits(3) + if !ok { + s.substateDecodeUint8 = decodeUint8Short + return decoderResultNeedsMoreInput + } + if bits == 0 { + *value = 1 + s.substateDecodeUint8 = decodeUint8None + return decoderResultSuccess + } + // Use *value as temporary storage for nbits (must be persisted). + *value = uint(bits) + fallthrough + + case decodeUint8Long: + bits, ok := br.safeReadBits(*value) + if !ok { + s.substateDecodeUint8 = decodeUint8Long + return decoderResultNeedsMoreInput + } + *value = (1 << *value) + uint(bits) + s.substateDecodeUint8 = decodeUint8None + return decoderResultSuccess + } + s.err = decompressError("unreachable decodeVarLenUint8 state") + return decoderResultError +} + +// --- Metablock header --- + +func (s *decodeState) decodeMetaBlockLength() decoderResult { + br := &s.br + for { + switch s.substateMetablockHeader { + case metablockHeaderNone: + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + s.isLastMetablock = bits != 0 + s.metaBlockRemainingLen = 0 + s.isUncompressed = false + s.isMetadata = false + if !s.isLastMetablock { + s.substateMetablockHeader = metablockHeaderNibbles + break + } + s.substateMetablockHeader = metablockHeaderEmpty + fallthrough + + case metablockHeaderEmpty: + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + if bits != 0 { + // Empty last metablock. + s.substateMetablockHeader = metablockHeaderNone + return decoderResultSuccess + } + s.substateMetablockHeader = metablockHeaderNibbles + fallthrough + + case metablockHeaderNibbles: + bits, ok := br.safeReadBits(2) + if !ok { + return decoderResultNeedsMoreInput + } + s.sizeNibbles = int(bits + 4) + s.loopCounter = 0 + if bits == 3 { + s.isMetadata = true + s.substateMetablockHeader = metablockHeaderReserved + break + } + s.substateMetablockHeader = metablockHeaderSize + fallthrough + + case metablockHeaderSize: + i := s.loopCounter + for i < s.sizeNibbles { + bits, ok := br.safeReadBits(4) + if !ok { + s.loopCounter = i + return decoderResultNeedsMoreInput + } + if i+1 == s.sizeNibbles && s.sizeNibbles > 4 && bits == 0 { + s.err = decompressError("exuberant nibble") + return decoderResultError + } + s.metaBlockRemainingLen |= int(bits) << (i * 4) + i++ + } + s.substateMetablockHeader = metablockHeaderUncompressed + fallthrough + + case metablockHeaderUncompressed: + if !s.isLastMetablock { + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + s.isUncompressed = bits != 0 + } + s.metaBlockRemainingLen++ + s.substateMetablockHeader = metablockHeaderNone + return decoderResultSuccess + + case metablockHeaderReserved: + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + if bits != 0 { + s.err = decompressError("reserved bit set in metadata header") + return decoderResultError + } + s.substateMetablockHeader = metablockHeaderBytes + fallthrough + + case metablockHeaderBytes: + bits, ok := br.safeReadBits(2) + if !ok { + return decoderResultNeedsMoreInput + } + if bits == 0 { + s.substateMetablockHeader = metablockHeaderNone + return decoderResultSuccess + } + s.sizeNibbles = int(bits) + s.loopCounter = 0 + s.substateMetablockHeader = metablockHeaderMetadata + fallthrough + + case metablockHeaderMetadata: + i := s.loopCounter + for i < s.sizeNibbles { + bits, ok := br.safeReadBits(8) + if !ok { + s.loopCounter = i + return decoderResultNeedsMoreInput + } + if i+1 == s.sizeNibbles && s.sizeNibbles > 1 && bits == 0 { + s.err = decompressError("exuberant metadata nibble") + return decoderResultError + } + s.metaBlockRemainingLen |= int(bits) << (i * 8) + i++ + } + s.metaBlockRemainingLen++ + s.substateMetablockHeader = metablockHeaderNone + return decoderResultSuccess + + default: + s.err = decompressError("unreachable metablock header state") + return decoderResultError + } + } +} + +// --- Metadata skip --- + +func (s *decodeState) skipMetadataBlock() decoderResult { + br := &s.br + for s.metaBlockRemainingLen > 0 { + avail := br.remainingBytes() + if avail == 0 { + return decoderResultNeedsMoreInput + } + n := min(avail, s.metaBlockRemainingLen) + // Skip n bytes. + for range n { + if br.bitPos >= 8 { + br.dropBits(8) + } else { + br.pos++ + } + } + s.metaBlockRemainingLen -= n + } + return decoderResultSuccess +} + +// --- Ring buffer --- + +func (s *decodeState) calculateRingBufferSize() { + windowSize := 1 << s.windowBits + newSize := windowSize + if s.ringbufferSize == windowSize { + return + } + if s.isMetadata { + return + } + + outputSize := s.pos + s.metaBlockRemainingLen + minSize := s.ringbufferSize + if minSize == 0 { + minSize = 1024 + } + if minSize < outputSize { + minSize = outputSize + } + + if s.cannyRingbufferAllocation { + for (newSize >> 1) >= minSize { + newSize >>= 1 + } + } + s.newRingbufferSize = newSize +} + +func (s *decodeState) ensureRingBuffer() { + if s.ringbufferSize == s.newRingbufferSize { + return + } + newSize := s.newRingbufferSize + ringBufferWriteAheadSlack + if cap(s.ringbuffer) >= newSize { + s.ringbuffer = s.ringbuffer[:newSize] + } else { + newBuf := getDecRingBuf(newSize) + if s.ringbuffer != nil { + copy(newBuf, s.ringbuffer[:s.pos]) + putDecRingBuf(s.ringbuffer) + } + s.ringbuffer = newBuf + } + s.ringbuffer[s.newRingbufferSize-2] = 0 + s.ringbuffer[s.newRingbufferSize-1] = 0 + s.ringbufferSize = s.newRingbufferSize + s.ringbufferMask = s.newRingbufferSize - 1 +} + +// --- Uncompressed block --- + +func (s *decodeState) copyUncompressedBlock(output *[]byte) decoderResult { + s.ensureRingBuffer() + br := &s.br + for { + if s.substateUncompressed == uncompressedWrite { + s.writeRingBuffer(output) + s.substateUncompressed = uncompressedNone + continue + } + if s.metaBlockRemainingLen == 0 { + return decoderResultSuccess + } + avail := br.remainingBytes() + if avail == 0 { + return decoderResultNeedsMoreInput + } + n := min(avail, s.metaBlockRemainingLen) + if s.pos+n > s.ringbufferSize { + n = s.ringbufferSize - s.pos + } + br.copyBytes(s.ringbuffer[s.pos : s.pos+n]) + s.pos += n + s.metaBlockRemainingLen -= n + if s.pos >= s.ringbufferSize { + s.substateUncompressed = uncompressedWrite + return decoderResultNeedsMoreOutput + } + } +} + +// --- Block type switching --- + +// decodeBlockTypeAndLength reads a block type and new block length. +// Returns true if a block switch occurred (i.e., num_block_types > 1). +func (s *decodeState) decodeBlockTypeAndLength(safe bool, treeType int) bool { + maxBlockType := s.numBlockTypes[treeType] + if maxBlockType <= 1 { + return false + } + + typeTree := s.blockTypeTrees[treeType*huffmanMaxSize258:] + lenTree := s.blockLenTrees[treeType*huffmanMaxSize26:] + br := &s.br + rb := &s.blockTypeRB + + var blockType uint + if !safe { + br.fillBitWindow(16) + blockType = decodeSymbol(br.val, typeTree, br) + s.blockLength[treeType] = readBlockLength(lenTree, br) + } else { + memento := br.saveState() + var ok bool + blockType, ok = safeReadSymbol(typeTree, br) + if !ok { + return false + } + bl, ok := safeReadBlockLength(s, lenTree) + if !ok { + s.substateReadBlockLength = readBlockLengthNone + br.restoreState(memento) + return false + } + s.blockLength[treeType] = bl + } + + switch blockType { + case 1: + blockType = rb[treeType*2+1] + 1 + case 0: + blockType = rb[treeType*2] + default: + blockType -= 2 + } + if blockType >= maxBlockType { + blockType -= maxBlockType + } + rb[treeType*2] = rb[treeType*2+1] + rb[treeType*2+1] = blockType + return true +} + +// --- Trivial literal context detection --- + +func (s *decodeState) detectTrivialLiteralBlockTypes() { + s.trivialLiteralContexts = [8]uint32{} + for i := range s.numBlockTypes[0] { + offset := i << core.LiteralContextBits + sample := s.contextMap[offset] + trivial := true + for j := range uint(1 << core.LiteralContextBits) { + if s.contextMap[offset+j] != sample { + trivial = false + break + } + } + if trivial { + s.trivialLiteralContexts[i>>5] |= 1 << (i & 31) + } + } +} + +func (s *decodeState) prepareLiteralDecoding() { + blockType := s.blockTypeRB[1] + contextOffset := blockType << core.LiteralContextBits + s.contextMapSliceIdx = int(contextOffset) + trivial := s.trivialLiteralContexts[blockType>>5] + s.trivialLiteralContext = int((trivial >> (blockType & 31)) & 1) + s.literalHTree = s.literalHGroup.codes[s.literalHGroup.htrees[s.contextMap[s.contextMapSliceIdx]]:] + contextMode := s.contextModes[blockType] & 3 + s.contextLookup = core.ContextLookupTable[uint(contextMode)<<9:] + if s.trivialLiteralContext == 0 { + ctxMap := s.contextMap[s.contextMapSliceIdx:] + htrees := s.literalHGroup.htrees + codesBase := unsafe.Pointer(unsafe.SliceData(s.literalHGroup.codes)) + for ctx := range 64 { + offset := htrees[ctxMap[ctx]] + s.literalCodesOffsets[ctx] = offset + s.literalCodesPtrs[ctx] = unsafe.Add(codesBase, uintptr(offset)*4) + } + } +} + +// --- Compressed metablock header sub-functions --- + +// --- Context modes --- + +func (s *decodeState) readContextModes() decoderResult { + br := &s.br + i := s.loopCounter + for uint(i) < s.numBlockTypes[0] { + bits, ok := br.safeReadBits(2) + if !ok { + s.loopCounter = i + return decoderResultNeedsMoreInput + } + s.contextModes[i] = byte(bits) + i++ + } + s.loopCounter = i + return decoderResultSuccess +} + +// --- Context map --- + +func (s *decodeState) decodeContextMap(contextMapSize uint, contextMap *[]byte, numHTrees *uint) decoderResult { + br := &s.br + h := &s.headerArena + + for { + switch h.substateContextMap { + case contextMapNone: + result := s.decodeVarLenUint8(numHTrees) + if result != decoderResultSuccess { + return result + } + (*numHTrees)++ + + *contextMap = reuseBytes(*contextMap, int(contextMapSize)) + if *numHTrees <= 1 { + // Trivial context map: all zeros. + clear(*contextMap) + return decoderResultSuccess + } + h.substateContextMap = contextMapReadPrefix + fallthrough + + case contextMapReadPrefix: + bits, ok := br.safeGetBits(5) + if !ok { + return decoderResultNeedsMoreInput + } + if bits&1 != 0 { + h.maxRunLengthPrefix = uint(bits>>1) + 1 + br.dropBits(5) + } else { + h.maxRunLengthPrefix = 0 + br.dropBits(1) + } + alphabetSize := *numHTrees + h.maxRunLengthPrefix + h.substateHuffman = huffmanNone + h.substateContextMap = contextMapHuffman + // Save code for RLE decoding (h.code stores maxRunLengthPrefix). + h.code = h.maxRunLengthPrefix + _ = alphabetSize // used in next case + fallthrough + + case contextMapHuffman: + alphabetSize := *numHTrees + h.code + result := s.readHuffmanCode(alphabetSize, alphabetSize, + h.contextMapTable[:], nil) + if result != decoderResultSuccess { + return result + } + h.contextIndex = 0 + h.code = 0xFFFF // sentinel: no pending RLE + h.substateContextMap = contextMapDecode + fallthrough + + case contextMapDecode: + code := h.code + skipPreamble := code != 0xFFFF + for h.contextIndex < contextMapSize || skipPreamble { + if !skipPreamble { + var ok bool + code, ok = safeReadSymbol(h.contextMapTable[:], br) + if !ok { + h.code = 0xFFFF + return decoderResultNeedsMoreInput + } + if code == 0 { + (*contextMap)[h.contextIndex] = 0 + h.contextIndex++ + continue + } + if code > h.maxRunLengthPrefix { + (*contextMap)[h.contextIndex] = byte(code - h.maxRunLengthPrefix) + h.contextIndex++ + continue + } + } else { + skipPreamble = false + } + // RLE: zero-fill. + reps, ok := br.safeReadBits(code) + if !ok { + h.code = code + return decoderResultNeedsMoreInput + } + reps += 1 << code + if h.contextIndex+uint(reps) > contextMapSize { + s.err = decompressError("context map repeat overflow") + return decoderResultError + } + clear((*contextMap)[h.contextIndex : h.contextIndex+uint(reps)]) + h.contextIndex += uint(reps) + } + h.substateContextMap = contextMapTransform + fallthrough + + case contextMapTransform: + bits, ok := br.safeReadBits(1) + if !ok { + return decoderResultNeedsMoreInput + } + if bits != 0 { + s.inverseMoveToFrontTransform(*contextMap) + } + h.substateContextMap = contextMapNone + return decoderResultSuccess + + default: + s.err = decompressError("unreachable context map state") + return decoderResultError + } + } +} + +// inverseMoveToFrontTransform applies the inverse MTF transform in-place. +func (s *decodeState) inverseMoveToFrontTransform(v []byte) { + var list [256]byte + for i := range 256 { + list[i] = byte(i) + } + + upperBound := uint(0) + for i := range v { + idx := int(v[i]) + val := list[idx] + upperBound |= uint(idx) + v[i] = val + copy(list[1:idx+1], list[:idx]) + list[0] = val + } + s.mtfUpperBound = upperBound >> 2 +} + +// --- Huffman tree group decode --- + +func (s *decodeState) huffmanTreeGroupDecode(group *huffmanTreeGroup) decoderResult { + h := &s.headerArena + if h.substateTreeGroup != treeGroupLoop { + h.htreeIndex = 0 + h.next = 0 + h.substateTreeGroup = treeGroupLoop + } + for h.htreeIndex < int(group.numHTrees) { + var tableSize uint32 + result := s.readHuffmanCode(uint(group.alphabetSizeMax), uint(group.alphabetSizeLimit), + group.codes[h.next:], &tableSize) + if result != decoderResultSuccess { + return result + } + group.htrees[h.htreeIndex] = h.next + h.next += int(tableSize) + h.htreeIndex++ + } + h.substateTreeGroup = treeGroupNone + return decoderResultSuccess +} + +// --- Read Huffman code --- + +func (s *decodeState) readHuffmanCode(alphabetSizeMax, alphabetSizeLimit uint, table []core.HuffmanCode, optTableSize *uint32) decoderResult { + br := &s.br + h := &s.headerArena + + for { + switch h.substateHuffman { + case huffmanNone: + bits, ok := br.safeReadBits(2) + if !ok { + return decoderResultNeedsMoreInput + } + h.subLoopCounter = uint(bits) + if bits != 1 { + // Complex prefix code. + h.space = 32 + h.repeat = 0 + h.codeLengthHisto = [16]uint16{} + h.codeLengthCodeLengths = [core.AlphabetSizeCodeLengths]byte{} + h.substateHuffman = huffmanComplex + continue + } + fallthrough + + case huffmanSimpleSize: + bits, ok := br.safeReadBits(2) + if !ok { + h.substateHuffman = huffmanSimpleSize + return decoderResultNeedsMoreInput + } + h.symbol = uint(bits) // num_symbols (0..3 means 1..4) + h.subLoopCounter = 0 + fallthrough + + case huffmanSimpleRead: + result := s.readSimpleHuffmanSymbols(alphabetSizeMax, alphabetSizeLimit) + if result != decoderResultSuccess { + return result + } + fallthrough + + case huffmanSimpleBuild: + if h.symbol == 3 { + bits, ok := br.safeReadBits(1) + if !ok { + h.substateHuffman = huffmanSimpleBuild + return decoderResultNeedsMoreInput + } + h.symbol += uint(bits) + } + tableSize := core.BuildSimpleHuffmanTable(table, huffmanTableBits, + h.symbolListsArray[:4], uint32(h.symbol)) + if optTableSize != nil { + *optTableSize = tableSize + } + h.substateHuffman = huffmanNone + return decoderResultSuccess + + case huffmanComplex: + result := s.readCodeLengthCodeLengths() + if result != decoderResultSuccess { + return result + } + core.BuildCodeLengthsHuffmanTable(h.table[:], h.codeLengthCodeLengths[:], h.codeLengthHisto[:]) + h.codeLengthHisto = [16]uint16{} + + // Initialize symbol lists for core.BuildHuffmanTable. + h.symbolLists = h.symbolListsArray[:] + for i := 0; i <= core.HuffmanMaxCodeLength; i++ { + h.nextSymbol[i] = i - symListBase + h.symbolListsArray[i] = 0xFFFF + } + + h.symbol = 0 + h.prevCodeLen = core.InitialRepeatedCodeLength + h.repeat = 0 + h.repeatCodeLen = 0 + h.space = 32768 + h.substateHuffman = huffmanLengthSymbols + fallthrough + + case huffmanLengthSymbols: + result := s.readSymbolCodeLengths(alphabetSizeLimit) + if result != decoderResultSuccess { + return result + } + if h.space != 0 { + s.err = decompressError("huffman space not zero") + return decoderResultError + } + sl := core.SymbolList{Storage: h.symbolLists, Offset: symListBase} + tableSize := core.BuildHuffmanTable(table, huffmanTableBits, sl, h.codeLengthHisto[:]) + if optTableSize != nil { + *optTableSize = tableSize + } + h.substateHuffman = huffmanNone + return decoderResultSuccess + + default: + s.err = decompressError("unreachable huffman state") + return decoderResultError + } + } +} + +// readSimpleHuffmanSymbols reads 1..4 symbol values for simple Huffman codes. +func (s *decodeState) readSimpleHuffmanSymbols(alphabetSizeMax, alphabetSizeLimit uint) decoderResult { + br := &s.br + h := &s.headerArena + + maxBits := uint(0) + if alphabetSizeMax > 1 { + v := alphabetSizeMax - 1 + for v > 0 { + maxBits++ + v >>= 1 + } + } + + i := h.subLoopCounter + numSymbols := h.symbol + for i <= numSymbols { + v, ok := br.safeReadBits(maxBits) + if !ok { + h.subLoopCounter = i + h.substateHuffman = huffmanSimpleRead + return decoderResultNeedsMoreInput + } + if uint(v) >= alphabetSizeLimit { + s.err = decompressError("simple huffman alphabet overflow") + return decoderResultError + } + h.symbolListsArray[i] = uint16(v) + i++ + } + + // Check for duplicates. + for i := range numSymbols { + for k := i + 1; k <= numSymbols; k++ { + if h.symbolListsArray[i] == h.symbolListsArray[k] { + s.err = decompressError("duplicate simple huffman symbols") + return decoderResultError + } + } + } + + return decoderResultSuccess +} + +// readCodeLengthCodeLengths reads code length code lengths using the static +// prefix code (RFC 7932 §3.5). Can suspend and resume via h.subLoopCounter. +func (s *decodeState) readCodeLengthCodeLengths() decoderResult { + br := &s.br + h := &s.headerArena + numCodes := h.repeat + space := h.space + i := h.subLoopCounter + for i < core.AlphabetSizeCodeLengths { + codeLenIdx := core.CodeLengthCodeOrder[i] + ix, prefixAvailable := br.safeGetBits(4) + if !prefixAvailable { + avail := br.availBits() + if avail != 0 { + br.normalize() + ix = br.bitsUnmasked() & 0xF + } else { + ix = 0 + } + if uint(codeLengthPrefixLength[ix]) > avail { + h.subLoopCounter = i + h.repeat = numCodes + h.space = space + h.substateHuffman = huffmanComplex + return decoderResultNeedsMoreInput + } + } + v := codeLengthPrefixValue[ix] + br.dropBits(uint(codeLengthPrefixLength[ix])) + h.codeLengthCodeLengths[codeLenIdx] = v + if v != 0 { + space -= 32 >> v + numCodes++ + h.codeLengthHisto[v]++ + if space-1 >= 32 { + break + } + } + i++ + } + if numCodes != 1 && space != 0 { + s.err = decompressError("invalid code length code space") + return decoderResultError + } + return decoderResultSuccess +} + +// processSingleCodeLength processes a single code length symbol. +func (h *metablockHeaderArena) processSingleCodeLength(codeLen uint) { + h.repeat = 0 + if codeLen != 0 { + h.symbolListsArray[h.nextSymbol[codeLen]+symListBase] = uint16(h.symbol) + h.nextSymbol[codeLen] = int(h.symbol) + h.prevCodeLen = codeLen + h.space -= 32768 >> codeLen + h.codeLengthHisto[codeLen]++ + } + h.symbol++ +} + +// processRepeatedCodeLength processes a repeated code length (16 or 17). +func (h *metablockHeaderArena) processRepeatedCodeLength(codeLen, repeatDelta, alphabetSize uint) { + extraBits := uint(3) + newLen := uint(0) + if codeLen == core.RepeatPreviousCodeLength { + newLen = h.prevCodeLen + extraBits = 2 + } + if h.repeatCodeLen != newLen { + h.repeat = 0 + h.repeatCodeLen = newLen + } + oldRepeat := h.repeat + if h.repeat > 0 { + h.repeat -= 2 + h.repeat <<= extraBits + } + h.repeat += repeatDelta + 3 + delta := h.repeat - oldRepeat + if h.symbol+delta > alphabetSize { + h.symbol = alphabetSize + h.space = 0xFFFFF + return + } + if h.repeatCodeLen != 0 { + sym := h.symbol + last := sym + delta + next := h.nextSymbol[h.repeatCodeLen] + for sym < last { + h.symbolListsArray[next+symListBase] = uint16(sym) + next = int(sym) + sym++ + } + h.symbol = last + h.nextSymbol[h.repeatCodeLen] = next + h.space -= delta << (15 - h.repeatCodeLen) + h.codeLengthHisto[h.repeatCodeLen] += uint16(delta) + } else { + h.symbol += delta + } +} + +func (s *decodeState) readSymbolCodeLengths(alphabetSize uint) decoderResult { + br := &s.br + h := &s.headerArena + + if !br.warmup() { + return decoderResultNeedsMoreInput + } + + // Batched fast path: hoist bit reader state into locals and process + // single code lengths in a tight loop without per-symbol method calls. + if br.checkInputAmount() { + val := br.val + bitPos := br.bitPos + brPos := br.pos + inputBase := br.inputBase + tableBase := unsafe.Pointer(&h.table[0]) + symbol := h.symbol + + for symbol < alphabetSize && h.space > 0 { + // fillBitWindow inline + if bitPos < 32 { + if brPos > br.fastEnd { + break + } + val |= uint64(*(*uint32)(unsafe.Add(inputBase, brPos))) << bitPos + bitPos += 32 + brPos += 4 + } + + // Decode code length from table — the table has exactly 32 entries + // (1 << core.HuffmanMaxCodeLengthCodeLength), so masking with 0x1F is + // always in bounds. + raw := *(*uint32)(unsafe.Add(tableBase, (val&0x1F)*4)) + drop := uint(raw & 0xFF) + codeLen := uint(raw >> 16) + + bitPos -= drop + val >>= drop & 63 + + if codeLen >= core.RepeatPreviousCodeLength { + // Handle repeat code: inline processRepeatedCodeLength + // to avoid function call overhead and unnecessary br write-backs. + extraBits := uint(2) + newLen := uint(0) + if codeLen == core.RepeatPreviousCodeLength { + newLen = h.prevCodeLen + } else { + extraBits = 3 + } + repeatDelta := uint(val & bitMask(extraBits)) + bitPos -= extraBits + val >>= extraBits & 63 + + if h.repeatCodeLen != newLen { + h.repeat = 0 + h.repeatCodeLen = newLen + } + oldRepeat := h.repeat + if h.repeat > 0 { + h.repeat -= 2 + h.repeat <<= extraBits + } + h.repeat += repeatDelta + 3 + delta := h.repeat - oldRepeat + switch { + case symbol+delta > alphabetSize: + symbol = alphabetSize + h.space = 0xFFFFF + case newLen != 0: + last := symbol + delta + next := h.nextSymbol[newLen] + for symbol < last { + h.symbolListsArray[next+symListBase] = uint16(symbol) + next = int(symbol) + symbol++ + } + h.nextSymbol[newLen] = next + h.space -= delta << (15 - newLen) + h.codeLengthHisto[newLen] += uint16(delta) + default: + symbol += delta + } + + if brPos > br.fastEnd { + h.symbol = symbol + br.val = val + br.bitPos = bitPos + br.pos = brPos + goto slow + } + continue + } + + // processSingleCodeLength inline + h.repeat = 0 + if codeLen != 0 { + h.symbolListsArray[h.nextSymbol[codeLen]+symListBase] = uint16(symbol) + h.nextSymbol[codeLen] = int(symbol) + h.prevCodeLen = codeLen + h.space -= 32768 >> codeLen + h.codeLengthHisto[codeLen]++ + } + symbol++ + } + + h.symbol = symbol + br.val = val + br.bitPos = bitPos + br.pos = brPos + } + +slow: + for h.symbol < alphabetSize && h.space > 0 { + p := h.table[:] + if br.checkInputAmount() { + // Fast path. + br.fillBitWindow16() + entry := p[br.bitsUnmasked()&bitMask(core.HuffmanMaxCodeLengthCodeLength)] + br.dropBits(uint(entry.Bits)) + codeLen := uint(entry.Value) + if codeLen < core.RepeatPreviousCodeLength { + h.processSingleCodeLength(codeLen) + } else { + extraBits := uint(2) + if codeLen != core.RepeatPreviousCodeLength { + extraBits = 3 + } + repeatDelta := uint(br.bitsUnmasked() & bitMask(extraBits)) + br.dropBits(extraBits) + h.processRepeatedCodeLength(codeLen, repeatDelta, alphabetSize) + } + } else { + // Safe path. + availBits := br.availBits() + var bits uint64 + if availBits != 0 { + br.normalize() + bits = br.bitsUnmasked() + } + entry := p[bits&bitMask(core.HuffmanMaxCodeLengthCodeLength)] + if uint(entry.Bits) > availBits { + if !br.pullByte() { + return decoderResultNeedsMoreInput + } + continue + } + codeLen := uint(entry.Value) + if codeLen < core.RepeatPreviousCodeLength { + br.dropBits(uint(entry.Bits)) + h.processSingleCodeLength(codeLen) + } else { + extraBits := codeLen - 14 + repeatDelta := uint((bits >> uint(entry.Bits)) & bitMask(extraBits)) + if availBits < uint(entry.Bits)+extraBits { + if !br.pullByte() { + return decoderResultNeedsMoreInput + } + continue + } + br.dropBits(uint(entry.Bits) + extraBits) + h.processRepeatedCodeLength(codeLen, repeatDelta, alphabetSize) + } + } + } + return decoderResultSuccess +} + +// --- Distance LUT --- + +func (s *decodeState) calculateDistanceLut() { + b := &s.bodyArena + npostfix := s.distancePostfixBits + ndirect := s.numDirectDistanceCodes + alphabetSizeLimit := uint(s.distanceHGroup.alphabetSizeLimit) + + // Skip recomputation when the parameters haven't changed. + if b.cachedValid && + b.cachedPostfix == npostfix && + b.cachedDirect == ndirect && + b.cachedAlphabetSizeLim == alphabetSizeLimit { + return + } + + postfix := uint(1) << npostfix + + i := uint(core.NumDistanceShortCodes) + + // Fill direct codes. + for j := range ndirect { + b.distExtraBits[i] = 0 + b.distOffset[i] = j + 1 + i++ + } + + // Fill regular distance codes. + bits := uint(1) + half := uint(0) + for i < alphabetSizeLimit { + base := ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1 + for j := range postfix { + b.distExtraBits[i] = byte(bits) + b.distOffset[i] = base + j + i++ + } + bits += half + half ^= 1 + } + + b.cachedPostfix = npostfix + b.cachedDirect = ndirect + b.cachedAlphabetSizeLim = alphabetSizeLimit + b.cachedValid = true +} + +// copyOverlappingPattern fills n bytes at pos by repeating the dist-byte pattern +// that ends there, for dist < n. +// +// The first loop doubles the usable gap: after storing dist correct bytes the +// valid run behind p is twice as long, so once it reaches 16 every 16-byte load +// lies entirely inside already-final data and the second loop can run flat out. +// Both loops store 16 bytes at a time and so may write up to 15 bytes past +// pos+n, which the ring buffer's 542 bytes of slack absorb — the same contract +// the eager 16-byte store in processCommands already relies on. +func copyOverlappingPattern(base unsafe.Pointer, pos, dist, n int) { + p, end := pos, pos+n + for dist < 16 && p < end { + *(*[16]byte)(unsafe.Add(base, p)) = *(*[16]byte)(unsafe.Add(base, p-dist)) + p += dist + dist += dist + } + for p < end { + *(*[16]byte)(unsafe.Add(base, p)) = *(*[16]byte)(unsafe.Add(base, p-dist)) + p += 16 + } +} + +func (s *decodeState) processCommands() decoderResult { + br := &s.br + pos := s.pos + i := s.loopCounter + var cmdCode uint + var ok bool + var insertLenExtra uint64 + var literal uint + var p1, p2 byte + + // Dispatch to the correct entry point based on state. + switch s.state { + case decoderStateCommandInner: + goto commandInner + case decoderStateCommandPostDecodeLiterals: + goto commandPostDecodeLiterals + case decoderStateCommandPostWrapCopy: + goto commandPostWrapCopy + } + +commandBegin: + if s.blockLength[1] == 0 && s.numBlockTypes[1] > 1 { + if br.checkInputAmount() { + s.decodeBlockTypeAndLength(false, 1) + } else if !s.decodeBlockTypeAndLength(true, 1) { + s.state = decoderStateCommandBegin + s.pos = pos + return decoderResultNeedsMoreInput + } + s.htreeCommand = s.insertCopyHGroup.codes[s.insertCopyHGroup.htrees[s.blockTypeRB[3]]:] + } + + // Read command. + if br.checkInputAmount() { + val, bitPos := br.val, br.bitPos + val |= *(*uint64)(unsafe.Add(br.inputBase, br.pos)) << (bitPos & 63) + br.pos += int((63 - bitPos) >> 3) + bitPos |= 56 + // Inline command symbol decode with unsafe pointer arithmetic to + // avoid bounds checks on every command (same pattern as distanceSymbolEntryFast). + cmdTableBase := unsafe.Pointer(unsafe.SliceData(s.htreeCommand)) + idx := val & huffmanTableMask + raw := *(*uint32)(unsafe.Add(cmdTableBase, idx*4)) + cmdDrop := uint(raw & 0xFF) + cmdCode = uint(raw >> 16) + if cmdDrop > huffmanTableBits { + nbits := cmdDrop - huffmanTableBits + idx2 := idx + uint64(cmdCode) + ((val >> huffmanTableBits) & bitMask(nbits)) + raw = *(*uint32)(unsafe.Add(cmdTableBase, idx2*4)) + cmdDrop = huffmanTableBits + uint(raw&0xFF) + cmdCode = uint(raw >> 16) + } + + lut := *(*uint64)(unsafe.Add(unsafe.Pointer(&cmdLutPacked[0]), uintptr(cmdCode)*8)) + s.distanceCode = int(int8(lut >> 16)) + s.distanceContext = int(uint8(lut >> 24)) + s.distCodesOffset = s.distCodesCache[s.distanceContext&3] + i = int(uint16(lut >> 32)) + insertBits := uint(uint8(lut)) + copyBits := uint(uint8(lut >> 8)) + + // Combined drop + readBits for insertLenExtra + copyLenExtra: + // use local val/bitPos to avoid redundant stores/loads of br.val + // and br.bitPos across intervening struct writes. + val >>= cmdDrop & 63 + bitPos -= cmdDrop + + insertLenExtra = 0 + if insertBits != 0 { + insertLenExtra = val & bitMask(insertBits) + val >>= insertBits & 63 + bitPos -= insertBits + } + + val |= *(*uint64)(unsafe.Add(br.inputBase, br.pos)) << (bitPos & 63) + br.pos += int((63 - bitPos) >> 3) + bitPos |= 56 + copyExtra := val & bitMask(copyBits) + val >>= copyBits & 63 + bitPos -= copyBits + + br.val = val + br.bitPos = bitPos + + s.copyLength = int(lut>>48) + int(copyExtra) + } else { + cmdMemento := br.saveState() + cmdCode, ok = safeReadSymbol(s.htreeCommand, br) + if !ok { + s.state = decoderStateCommandBegin + s.pos = pos + return decoderResultNeedsMoreInput + } + s.safeCmdMemento = cmdMemento + + v := core.CmdLut[cmdCode] + s.distanceCode = int(v.DistanceCode) + s.distanceContext = int(v.Context) + s.distCodesOffset = s.distCodesCache[s.distanceContext] + i = int(v.InsertLenOffset) + + insertLenExtra = 0 + if v.InsertLenExtraBits != 0 { + insertLenExtra, ok = br.safeReadBits(uint(v.InsertLenExtraBits)) + if !ok { + br.restoreState(s.safeCmdMemento) + s.state = decoderStateCommandBegin + s.pos = pos + return decoderResultNeedsMoreInput + } + } + var val uint64 + val, ok = br.safeReadBits(uint(v.CopyLenExtraBits)) + if !ok { + br.restoreState(s.safeCmdMemento) + s.state = decoderStateCommandBegin + s.pos = pos + return decoderResultNeedsMoreInput + } + s.copyLength = int(v.CopyLenOffset) + int(val) + } + s.blockLength[1]-- + i += int(insertLenExtra) + + s.metaBlockRemainingLen -= i + if i == 0 { + goto commandPostDecodeLiterals + } + +commandInner: + // CommandInner: read i literal bytes. + if s.trivialLiteralContext != 0 { + for i > 0 { + if s.blockLength[0] == 0 && s.numBlockTypes[0] > 1 { + if br.checkInputAmount() { + s.decodeBlockTypeAndLength(false, 0) + } else if !s.decodeBlockTypeAndLength(true, 0) { + s.state = decoderStateCommandInner + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreInput + } + s.prepareLiteralDecoding() + if s.trivialLiteralContext == 0 { + goto commandInner + } + } + + // Batch decode: when we have enough input, ringbuffer space, + // and block length, decode multiple literals without per-symbol checks. + n := min(i, int(s.blockLength[0]), s.ringbufferSize-pos, (br.availIn()-8)/2) + if n == 1 { + // Decode one symbol here. The call overhead of + // decodeLiteralsBatch costs more than one symbol saves. + // n == 1 implies availIn >= 10, so the 4-byte load in + // fillBitWindow stays in bounds. + br.fillBitWindow(16) + s.ringbuffer[pos] = byte(decodeSymbol(br.val, s.literalHTree, br)) + pos++ + i-- + s.blockLength[0]-- + if pos == s.ringbufferSize { + s.state = decoderStateCommandInnerWrite + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + continue + } else if n > 1 { + decodeLiteralsBatch(s.ringbuffer[pos:], n, s.literalHTree, br) + pos += n + i -= n + s.blockLength[0] -= uint(n) + if pos == s.ringbufferSize { + s.state = decoderStateCommandInnerWrite + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + continue + } + + // Slow path: not enough input for batch, decode one symbol at a time. + if br.checkInputAmount() { + br.fillBitWindow(16) + literal = decodeSymbol(br.val, s.literalHTree, br) + } else { + literal, ok = safeReadSymbol(s.literalHTree, br) + if !ok { + s.state = decoderStateCommandInner + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreInput + } + } + s.ringbuffer[pos] = byte(literal) + s.blockLength[0]-- + pos++ + if pos == s.ringbufferSize { + s.state = decoderStateCommandInnerWrite + i-- + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + i-- + } + } else { + p1 = s.ringbuffer[(pos-1)&s.ringbufferMask] + p2 = s.ringbuffer[(pos-2)&s.ringbufferMask] + for i > 0 { + if s.blockLength[0] == 0 && s.numBlockTypes[0] > 1 { + if br.checkInputAmount() { + s.decodeBlockTypeAndLength(false, 0) + } else if !s.decodeBlockTypeAndLength(true, 0) { + s.state = decoderStateCommandInner + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreInput + } + s.prepareLiteralDecoding() + if s.trivialLiteralContext != 0 { + goto commandInner + } + } + + // Batch decode: when we have enough input, ringbuffer space, + // and block length, decode multiple context-dependent literals + // without per-symbol bounds checks. + n := min(i, int(s.blockLength[0]), s.ringbufferSize-pos, (br.availIn()-8)/2) + if n > 0 { + p1, p2 = decodeLiteralsContextBatch( + s.ringbuffer[pos:], n, + &s.literalCodesPtrs, + s.contextLookup, p1, p2, br, + ) + pos += n + i -= n + s.blockLength[0] -= uint(n) + if pos == s.ringbufferSize { + s.state = decoderStateCommandInnerWrite + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + continue + } + + ctx := s.contextLookup[p1] | s.contextLookup[256+int(p2)] + hc := s.literalHGroup.codes[s.literalCodesOffsets[ctx]:] + p2 = p1 + if br.checkInputAmount() { + br.fillBitWindow(16) + p1 = byte(decodeSymbol(br.val, hc, br)) + } else { + literal, ok = safeReadSymbol(hc, br) + if !ok { + s.state = decoderStateCommandInner + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreInput + } + p1 = byte(literal) + } + s.ringbuffer[pos] = p1 + s.blockLength[0]-- + pos++ + if pos == s.ringbufferSize { + s.state = decoderStateCommandInnerWrite + i-- + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + i-- + } + } + + if s.metaBlockRemainingLen <= 0 { + s.state = decoderStateMetablockDone + s.pos = pos + s.loopCounter = i + return decoderResultSuccess + } + +commandPostDecodeLiterals: + if s.distanceCode >= 0 { + // Implicit distance. + if s.distanceCode != 0 { + s.distanceContext = 0 + } else { + s.distanceContext = 1 + } + s.distRBIdx-- + s.distanceCode = s.distRB[s.distRBIdx&3] + } else { + // Read distance code. + if s.blockLength[2] == 0 && s.numBlockTypes[2] > 1 { + if br.checkInputAmount() { + s.decodeBlockTypeAndLength(false, 2) + } else if !s.decodeBlockTypeAndLength(true, 2) { + s.state = decoderStateCommandPostDecodeLiterals + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreInput + } + s.distContextMapSliceIdx = int(s.blockTypeRB[5]) << core.DistanceContextBits + s.updateDistCodesCache() + s.distCodesOffset = s.distCodesCache[s.distanceContext] + } + // Inlined fast path of readDistance to avoid function call overhead + // (readDistance exceeds the compiler's inlining budget). + if br.checkInputAmount() { + val, bitPos := br.val, br.bitPos + val |= *(*uint64)(unsafe.Add(br.inputBase, br.pos)) << (bitPos & 63) + br.pos += int((63 - bitPos) >> 3) + bitPos |= 56 + raw := distanceSymbolEntryFast(val, s.distanceHGroup.codes, s.distCodesOffset) + drop := uint(raw & 0xFF) + code := uint(raw >> 16) + if drop > huffmanTableBits { + code, drop = decodeDistanceSymbolSecondLevel(val, s.distanceHGroup.codes, s.distCodesOffset, code, drop) + } + // Combined dropBits + readBits32: use locals to avoid + // redundant stores/loads of br.val and br.bitPos. + val >>= drop & 63 + bitPos -= drop + s.blockLength[2]-- + s.distanceContext = 0 + if code&^0xF == 0 { + br.val = val + br.bitPos = bitPos + s.distanceCode = int(code) + s.takeDistanceFromRingBuffer() + } else { + b := &s.bodyArena + nExtra := uint(*(*byte)(unsafe.Add(unsafe.Pointer(&b.distExtraBits[0]), uintptr(code)))) + offset := *(*uint)(unsafe.Add(unsafe.Pointer(&b.distOffset[0]), uintptr(code)*unsafe.Sizeof(uint(0)))) + bits := val & bitMask(nExtra) + br.val = val >> (nExtra & 63) + br.bitPos = bitPos - nExtra + s.distanceCode = int(offset + uint(bits)< s.maxDistance { + if s.distanceCode > maxAllowedDistance { + s.err = decompressError("invalid backward reference distance") + return decoderResultError + } + + compoundSize := s.compoundDictSize() + + switch { + case s.distanceCode-s.maxDistance <= compoundSize: + // Compound dictionary reference. + address := compoundSize - (s.distanceCode - s.maxDistance) + if !s.compoundDict.initCopy(s, address, i) { + s.err = decompressError("invalid compound dictionary reference") + return decoderResultError + } + pos += s.compoundDict.copyTo(s, pos) + if pos >= s.ringbufferSize { + s.state = decoderStateCommandPostWrite1 + s.pos = pos + s.loopCounter = 0 + return decoderResultNeedsMoreOutput + } + + case i >= core.DictMinWordLength && i <= core.DictMaxWordLength: + // Static dictionary reference. + address := s.distanceCode - s.maxDistance - 1 - compoundSize + shift := uint(core.DictSizeBitsByLength[i]) + if shift == 0 { + s.err = decompressError("invalid static dictionary reference") + return decoderResultError + } + wordIdx := address & ((1 << shift) - 1) + transformIdx := address >> shift + if transformIdx >= core.NumTransforms { + s.err = decompressError("invalid dictionary transform") + return decoderResultError + } + offset := int(core.DictOffsetsByLength[i]) + wordIdx*i + word := core.DictData[offset : offset+i] + + // Compensate double distance-ring-buffer roll. + s.distRBIdx += s.distanceContext + + if transformIdx == int(core.TransformCutOffs[0]) { + copy(s.ringbuffer[pos:], word) + } else { + i = core.TransformDictionaryWord(s.ringbuffer[pos:], word, transformIdx) + // Omit transforms may produce an empty word; retain C's distance guard. + if i == 0 && s.distanceCode <= 120 { + s.err = decompressError("invalid dictionary transform") + return decoderResultError + } + } + pos += i + s.metaBlockRemainingLen -= i + if pos >= s.ringbufferSize { + s.state = decoderStateCommandPostWrite1 + s.pos = pos + s.loopCounter = 0 + return decoderResultNeedsMoreOutput + } + + default: + s.err = decompressError("invalid dictionary word length") + return decoderResultError + } + + if s.metaBlockRemainingLen <= 0 { + s.state = decoderStateMetablockDone + s.pos = pos + s.loopCounter = 0 + return decoderResultSuccess + } + goto commandBegin + } + + // Copy from ring buffer. + s.distRB[s.distRBIdx&3] = s.distanceCode + s.distRBIdx++ + s.metaBlockRemainingLen -= i + + { + srcStart := (pos - s.distanceCode) & s.ringbufferMask + dstEnd := pos + i + srcEnd := srcStart + i + + // Eagerly copy 16 bytes using direct pointer arithmetic. + // The ring buffer has 542 bytes of slack past ringbufferSize, + // so pos+16 and srcStart+16 are always within bounds. + base := unsafe.Pointer(unsafe.SliceData(s.ringbuffer)) + *(*[16]byte)(unsafe.Add(base, pos)) = *(*[16]byte)(unsafe.Add(base, srcStart)) + + if dstEnd >= s.ringbufferSize || srcEnd >= s.ringbufferSize { + // Wrapping — the byte loop is what yields to the state machine. + goto commandPostWrapCopy + } + if srcEnd > pos && dstEnd > srcStart { + // Overlapping but not wrapping. Only a source behind pos can be + // pattern-replicated; when the ring-buffer subtraction wrapped, + // srcStart is ahead of pos and the masked byte loop is still needed. + if dist := pos - srcStart; dist > 0 { + copyOverlappingPattern(base, pos, dist, i) + pos += i + goto postCopy + } + goto commandPostWrapCopy + } + + pos += i + if i > 16 { + // Use fixed-size 16-byte copies for sizes up to 96 to avoid + // the overhead of a memmove function call on moderate copies. + src16 := srcStart + 16 + dst16 := pos - i + 16 + *(*[16]byte)(unsafe.Add(base, dst16)) = *(*[16]byte)(unsafe.Add(base, src16)) + if i > 32 { + *(*[16]byte)(unsafe.Add(base, dst16+16)) = *(*[16]byte)(unsafe.Add(base, src16+16)) + if i > 48 { + *(*[16]byte)(unsafe.Add(base, dst16+32)) = *(*[16]byte)(unsafe.Add(base, src16+32)) + if i > 64 { + *(*[16]byte)(unsafe.Add(base, dst16+48)) = *(*[16]byte)(unsafe.Add(base, src16+48)) + if i > 80 { + *(*[16]byte)(unsafe.Add(base, dst16+64)) = *(*[16]byte)(unsafe.Add(base, src16+64)) + if i > 96 { + copy(s.ringbuffer[dst16+80:pos], s.ringbuffer[src16+80:srcEnd]) + } + } + } + } + } + } + + goto postCopy + } + +commandPostWrapCopy: + for i > 0 { + srcStart := (pos - s.distanceCode) & s.ringbufferMask + // Take the copy in chunks that stop at the ring-buffer end, so neither + // cursor wraps inside one. ringbufferMask is ringbufferSize-1, so both + // remainders are at least 1 and the loop always advances. + n := min(i, s.ringbufferSize-pos, s.ringbufferSize-srcStart) + if dist := pos - srcStart; dist > 0 { + if dist >= n { + copy(s.ringbuffer[pos:pos+n], s.ringbuffer[srcStart:srcStart+n]) + } else { + // Stores up to 15 bytes past pos+n, which cannot exceed + // ringbufferSize+15 and so stays inside the 542 bytes of slack. + copyOverlappingPattern(unsafe.Pointer(unsafe.SliceData(s.ringbuffer)), + pos, dist, n) + } + pos += n + i -= n + } else { + // The ring-buffer subtraction wrapped, putting the source ahead of + // pos; that has no contiguous run to copy, so step one byte. + s.ringbuffer[pos] = s.ringbuffer[srcStart] + pos++ + i-- + } + if pos == s.ringbufferSize { + s.state = decoderStateCommandPostWrite2 + s.pos = pos + s.loopCounter = i + return decoderResultNeedsMoreOutput + } + } + +postCopy: + + if s.metaBlockRemainingLen <= 0 { + s.state = decoderStateMetablockDone + s.pos = pos + s.loopCounter = i + return decoderResultSuccess + } + goto commandBegin +} + +// --- Distance reading --- + +func (s *decodeState) readDistance(br *bitReader) decoderResult { + b := &s.bodyArena + distTree := s.distanceHGroup.codes[s.distCodesOffset:] + + if br.checkInputAmount() { + br.fillBitWindow(16) + code := decodeSymbol(br.val, distTree, br) + s.blockLength[2]-- + s.distanceContext = 0 + if code&^0xF == 0 { + s.distanceCode = int(code) + s.takeDistanceFromRingBuffer() + return decoderResultSuccess + } + // After the first checkInputAmount (availIn >= 28) and one + // fillBitWindow (consuming at most 4 bytes), at least 24 bytes + // remain — enough for readBits32's inner fillBitWindow. + bits := br.readBits32(uint(b.distExtraBits[code])) + s.distanceCode = int(b.distOffset[code] + uint(bits)<> s.distanceCode + s.distanceCode = s.distRB[(s.distRBIdx-offset)&3] + s.distRBIdx -= s.distanceContext + } else { + indexDelta := 3 + base := s.distanceCode - 10 + if s.distanceCode < 10 { + base = s.distanceCode - 4 + } else { + indexDelta = 2 + } + delta := ((0x605142 >> (4 * base)) & 0xF) - 3 + s.distanceCode = s.distRB[(s.distRBIdx+indexDelta)&0x3] + delta + if s.distanceCode <= 0 { + s.distanceCode = 0x7FFFFFFF + } + } +} + +func (s *decodeState) excessiveInput() bool { + s.br.unload() + return s.br.availIn() > 0 +} + +// decompressError formats a decode-stage error. +func decompressError(msg string) error { + return errors.New("brotli: " + msg) +} + +// --- Huffman symbol reading --- + +// decodeSymbol decodes a Huffman symbol from the bit reader using a two-level table. +// Requires at least 15 bits available. +func decodeSymbol(bits uint64, table []core.HuffmanCode, br *bitReader) uint { + idx := bits & huffmanTableMask + entry := table[idx] + drop := uint(entry.Bits) + if drop > huffmanTableBits { + nbits := drop - huffmanTableBits + entry = table[idx+uint64(entry.Value)+((bits>>huffmanTableBits)&bitMask(nbits))] + // Second-level entry.Bits stores codeLen-rootBits; combine both drops + // into a single shift to reduce overhead on the hot path. + drop = huffmanTableBits + uint(entry.Bits) + } + br.dropBits(drop) + return uint(entry.Value) +} + +// distanceSymbolEntryFast loads the first-level distance Huffman table entry. +func distanceSymbolEntryFast(bits uint64, table []core.HuffmanCode, offset int) uint32 { + tableBase := unsafe.Add( + unsafe.Pointer(unsafe.SliceData(table)), + uintptr(offset)*unsafe.Sizeof(core.HuffmanCode{}), + ) + idx := bits & huffmanTableMask + return *(*uint32)(unsafe.Add(tableBase, idx*4)) +} + +// decodeDistanceSymbolSecondLevel decodes a second-level distance Huffman entry. +func decodeDistanceSymbolSecondLevel(bits uint64, table []core.HuffmanCode, offset int, code, drop uint) (uint, uint) { + tableBase := unsafe.Add( + unsafe.Pointer(unsafe.SliceData(table)), + uintptr(offset)*unsafe.Sizeof(core.HuffmanCode{}), + ) + nbits := drop - huffmanTableBits + idx := (bits & huffmanTableMask) + uint64(code) + ((bits >> huffmanTableBits) & bitMask(nbits)) + raw := *(*uint32)(unsafe.Add(tableBase, idx*4)) + return uint(raw >> 16), huffmanTableBits + uint(raw&0xFF) +} + +// decodeLiteralsBatch decodes n literal symbols from br into dst using table. +// It hoists the bitReader state into local variables to keep them in registers +// and avoid repeated struct field access on the hot path. +// The fill is on demand: a symbol consumes at most core.HuffmanMaxCodeLength +// bits, so bits are only loaded once fewer than that remain. One fill leaves +// ≥56 bits, which covers about nine to fourteen symbols at typical code +// lengths, so the branch is taken rarely and predicts well. +func decodeLiteralsBatch(dst []byte, n int, table []core.HuffmanCode, br *bitReader) { + val := br.val + bitPos := br.bitPos + brPos := br.pos + inputBase := br.inputBase + tableBase := unsafe.Pointer(unsafe.SliceData(table)) + + for j := range n { + if bitPos < core.HuffmanMaxCodeLength { + val |= *(*uint64)(unsafe.Add(inputBase, brPos)) << (bitPos & 63) + brPos += int((63 - bitPos) >> 3) + bitPos |= 56 + } + + idx := val & huffmanTableMask + raw := *(*uint32)(unsafe.Add(tableBase, idx*4)) + drop := uint(raw & 0xFF) + value := uint(raw >> 16) + if drop > huffmanTableBits { + nbits := drop - huffmanTableBits + idx2 := idx + uint64(value) + ((val >> huffmanTableBits) & bitMask(nbits)) + raw = *(*uint32)(unsafe.Add(tableBase, idx2*4)) + drop = huffmanTableBits + uint(raw&0xFF) + value = uint(raw >> 16) + } + bitPos -= drop + val >>= drop & 63 + dst[j] = byte(value) + } + + br.val = val + br.bitPos = bitPos + br.pos = brPos +} + +// decodeLiteralsContextBatch decodes n literals using context-dependent Huffman +// trees. It hoists bitReader state into locals and uses unsafe pointer arithmetic +// to avoid per-symbol bounds checks. Returns updated (p1, p2) context bytes. +func decodeLiteralsContextBatch( + dst []byte, n int, + ptrs *[64]unsafe.Pointer, + contextLookup []byte, p1, p2 byte, + br *bitReader, +) (byte, byte) { + val := br.val + bitPos := br.bitPos + brPos := br.pos + inputBase := br.inputBase + ctxBase := unsafe.Pointer(unsafe.SliceData(contextLookup)) + // Use an incrementing pointer instead of an index to avoid spilling the + // loop counter onto the stack — on x86-64 the shift in fillBitWindow + // requires CX, which would otherwise evict j every iteration. + dstPtr := unsafe.Pointer(unsafe.SliceData(dst)) + ptrsBase := unsafe.Pointer(ptrs) + c1, c2 := uint(p1), uint(p2) + + for n > 0 { + n-- + if bitPos < core.HuffmanMaxCodeLength { + val |= *(*uint64)(unsafe.Add(inputBase, brPos)) << (bitPos & 63) + brPos += int((63 - bitPos) >> 3) + bitPos |= 56 + } + + ctx := uint(*(*byte)(unsafe.Add(ctxBase, c1))) | uint(*(*byte)(unsafe.Add(ctxBase, 256+c2))) + tableBase := *(*unsafe.Pointer)(unsafe.Add(ptrsBase, uintptr(ctx)*unsafe.Sizeof(unsafe.Pointer(nil)))) + + // decodeSymbol inline + idx := val & huffmanTableMask + raw := *(*uint32)(unsafe.Add(tableBase, idx*4)) + drop := uint(raw & 0xFF) + value := uint(raw >> 16) + if drop > huffmanTableBits { + nbits := drop - huffmanTableBits + idx2 := idx + uint64(value) + ((val >> huffmanTableBits) & bitMask(nbits)) + raw = *(*uint32)(unsafe.Add(tableBase, idx2*4)) + drop = huffmanTableBits + uint(raw&0xFF) + value = uint(raw >> 16) + } + // dropBits inline + bitPos -= drop + val >>= drop & 63 + + c2 = c1 + c1 = value + *(*byte)(dstPtr) = byte(value) + dstPtr = unsafe.Add(dstPtr, 1) + } + + br.val = val + br.bitPos = bitPos + br.pos = brPos + return byte(c1), byte(c2) +} + +// safeDecodeSymbol is a fallback when fewer than 15 bits may be available. +func safeDecodeSymbol(table []core.HuffmanCode, br *bitReader) (uint, bool) { + availBits := br.availBits() + if availBits == 0 { + if table[0].Bits == 0 { + return uint(table[0].Value), true + } + return 0, false + } + br.normalize() + val := br.bitsUnmasked() + idx := val & huffmanTableMask + entry := table[idx] + if uint(entry.Bits) <= huffmanTableBits { + if uint(entry.Bits) <= availBits { + br.dropBits(uint(entry.Bits)) + return uint(entry.Value), true + } + return 0, false + } + if availBits <= huffmanTableBits { + return 0, false + } + sub := (val & bitMask(uint(entry.Bits))) >> huffmanTableBits + availBits -= huffmanTableBits + entry2 := table[idx+uint64(entry.Value)+sub] + if availBits < uint(entry2.Bits) { + return 0, false + } + br.dropBits(huffmanTableBits + uint(entry2.Bits)) + return uint(entry2.Value), true +} + +// safeReadSymbol tries the fast path (15 bits), falls back to safe decode. +func safeReadSymbol(table []core.HuffmanCode, br *bitReader) (uint, bool) { + val, ok := br.safeGetBits(15) + if ok { + return decodeSymbol(val, table, br), true + } + return safeDecodeSymbol(table, br) +} + +// --- Block length reading --- + +func readBlockLength(table []core.HuffmanCode, br *bitReader) uint { + br.fillBitWindow(16) + code := decodeSymbol(br.val, table, br) + nbits := core.BlockLengthNBits[code] + return uint(core.BlockLengthOffset[code]) + uint(br.readBits(uint(nbits))) +} + +func safeReadBlockLength(s *decodeState, table []core.HuffmanCode) (uint, bool) { + br := &s.br + var index uint + if s.substateReadBlockLength == readBlockLengthNone { + var ok bool + index, ok = safeReadSymbol(table, br) + if !ok { + return 0, false + } + } else { + index = s.blockLengthIndex + } + nbits := uint(core.BlockLengthNBits[index]) + bits, ok := br.safeReadBits(nbits) + if !ok { + s.blockLengthIndex = index + s.substateReadBlockLength = readBlockLengthSuffix + return 0, false + } + s.substateReadBlockLength = readBlockLengthNone + return uint(core.BlockLengthOffset[index]) + uint(bits), true +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/decode_state.go b/src/vendor/github.com/molecule-man/go-brrr/decode_state.go new file mode 100644 index 00000000..5281bb13 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/decode_state.go @@ -0,0 +1,627 @@ +// Decoder state machine types, enums, and initialization. + +package brrr + +import ( + "unsafe" + + "github.com/molecule-man/go-brrr/internal/core" + "github.com/molecule-man/go-brrr/internal/encoder" +) + +// Decoder-specific constants. +const ( + // Maximum block/metablock length (used as default when no block switching). + blockSizeCap = 1 << 24 + + // Maximum Huffman table sizes for the decoder, indexed by alphabet size. + huffmanMaxSize272 = 646 // for context map symbols (max 272) + huffmanMaxSize258 = 632 // for block type symbols (max 258) + huffmanMaxSize26 = 396 // for block count symbols (26) +) + +const ( + decoderResultError decoderResult = iota + decoderResultSuccess + decoderResultNeedsMoreInput + decoderResultNeedsMoreOutput +) + +const ( + decoderStateUninited decoderState = iota + decoderStateLargeWindowBits + decoderStateInitialize + decoderStateMetablockBegin + decoderStateMetablockHeader + decoderStateMetablockHeader2 + decoderStateContextModes + decoderStateCommandBegin + decoderStateCommandInner + decoderStateCommandPostDecodeLiterals + decoderStateCommandPostWrapCopy + decoderStateUncompressed + decoderStateMetadata + decoderStateCommandInnerWrite + decoderStateMetablockDone + decoderStateCommandPostWrite1 + decoderStateCommandPostWrite2 + decoderStateBeforeCompressedMetablockHeader + decoderStateHuffmanCode0 + decoderStateHuffmanCode1 + decoderStateHuffmanCode2 + decoderStateHuffmanCode3 + decoderStateContextMap1 + decoderStateContextMap2 + decoderStateTreeGroup + decoderStateBeforeCompressedMetablockBody + decoderStateDone +) + +const ( + metablockHeaderNone metablockHeaderState = iota + metablockHeaderEmpty + metablockHeaderNibbles + metablockHeaderSize + metablockHeaderUncompressed + metablockHeaderReserved + metablockHeaderBytes + metablockHeaderMetadata +) + +const ( + uncompressedNone uncompressedState = iota + uncompressedWrite +) + +const ( + treeGroupNone treeGroupState = iota + treeGroupLoop +) + +const ( + contextMapNone contextMapState = iota + contextMapReadPrefix + contextMapHuffman + contextMapDecode + contextMapTransform +) + +const ( + huffmanNone huffmanState = iota + huffmanSimpleSize + huffmanSimpleRead + huffmanSimpleBuild + huffmanComplex + huffmanLengthSymbols +) + +const ( + decodeUint8None decodeUint8State = iota + decodeUint8Short + decodeUint8Long +) + +const ( + readBlockLengthNone readBlockLengthState = iota + readBlockLengthSuffix +) + +// decoderResult indicates the outcome of a decode step. +type decoderResult int + +// decoderState enumerates the top-level states of the streaming decoder. +type decoderState int + +// metablockHeaderState enumerates states within metablock header parsing. +type metablockHeaderState int + +// uncompressedState enumerates states within uncompressed metablock processing. +type uncompressedState int + +// treeGroupState enumerates states within Huffman tree group decoding. +type treeGroupState int + +// contextMapState enumerates states within context map decoding. +type contextMapState int + +// huffmanState enumerates states within Huffman code reading. +type huffmanState int + +// decodeUint8State enumerates states within uint8 decoding. +type decodeUint8State int + +// readBlockLengthState enumerates states within block length reading. +type readBlockLengthState int + +// bitReader holds the bit-level reading state for the decoder input stream. +type bitReader struct { + inputBase unsafe.Pointer // cached base pointer for bounds-check-free loads + input []byte // full input buffer (set via setInput) + pos int // current byte position in input + val uint64 // pre-fetched bits + bitPos uint // number of valid bits in val + inputLen int // cached len(input) to avoid slice header reads + fastEnd int // inputLen - fastInputSlack; checkInputAmount is pos <= fastEnd +} + +// huffmanTreeGroup holds a collection of Huffman trees sharing the same +// alphabet size. Used by the decoder to store literal, insert-copy, and +// distance Huffman trees. +type huffmanTreeGroup struct { + htrees []int // indices into codes for each tree's root + codes []core.HuffmanCode // flat backing array for all trees + alphabetSizeMax uint16 + alphabetSizeLimit uint16 + numHTrees uint16 +} + +// metablockHeaderArena holds temporary state used during metablock header +// decoding. Reused across metablocks. +type metablockHeaderArena struct { + // List of heads of symbol chains. + symbolLists []uint16 + + substateTreeGroup treeGroupState + substateContextMap contextMapState + substateHuffman huffmanState + + subLoopCounter uint + + repeatCodeLen uint + prevCodeLen uint + + // For ReadHuffmanCode. + symbol uint + repeat uint + space uint + + // Huffman table for code length histograms. + table [32]core.HuffmanCode + symbolListsArray [core.HuffmanMaxCodeLength + 1 + core.AlphabetSizeInsertAndCopyLength]uint16 + // Tails of symbol chains. + nextSymbol [32]int + codeLengthCodeLengths [core.AlphabetSizeCodeLengths]byte + // Population counts for the code lengths. + codeLengthHisto [16]uint16 + + // For HuffmanTreeGroupDecode. + htreeIndex int + next int // index into codes slice + + // For DecodeContextMap. + contextIndex uint + maxRunLengthPrefix uint + code uint + contextMapTable [huffmanMaxSize272]core.HuffmanCode +} + +// metablockBodyArena holds temporary state used during metablock body +// decoding. Not used simultaneously with metablockHeaderArena. +type metablockBodyArena struct { + distExtraBits [core.NumHistogramDistanceSymbols]byte + distOffset [core.NumHistogramDistanceSymbols]uint + + // Cache key for calculateDistanceLut: skip recomputation when params match. + cachedPostfix uint + cachedDirect uint + cachedAlphabetSizeLim uint + cachedValid bool +} + +// decoderCompoundDictionary holds compound dictionary chunks for the decoder. +// The decoder uses these chunks as a virtual LZ77 prefix: backward references +// beyond the ring buffer are resolved against the concatenated chunk data. +type decoderCompoundDictionary struct { + chunks [16][]byte + chunkOffsets [17]int // cumulative byte offsets; chunkOffsets[0] = 0 + numChunks int + totalSize int + blockBits int // -1 until lazily initialized + blockMap [256]byte // maps address >> blockBits to chunk index + // Copy state for suspension across ringbuffer writes. + brIndex int + brOffset int + brLength int + brCopied int +} + +// attach appends a dictionary chunk. +// decodeState holds the full state of a streaming brotli decoder. +// +// Fields are ordered with all pointer-containing types first (slices, +// interfaces, structs embedding slices) to minimize the GC scan range. +type decodeState struct { + // Pointer-containing fields. + br bitReader + err error + ringbuffer []byte + htreeCommand []core.HuffmanCode // slice into insertCopyHGroup.codes + contextLookup []byte + distContextMap []byte + literalHTree []core.HuffmanCode // slice into literalHGroup.codes + contextMap []byte + contextModes []byte + blockTypeTrees []core.HuffmanCode + blockLenTrees []core.HuffmanCode + literalHGroup huffmanTreeGroup + insertCopyHGroup huffmanTreeGroup + distanceHGroup huffmanTreeGroup + compoundDict *decoderCompoundDictionary + sink *chunkWriter + outChunks chunkWriter + + // literalCodesPtrs caches a precomputed unsafe.Pointer for each of the + // 64 literal contexts. Each entry is codesBase + literalCodesOffsets[ctx]*4, + // eliminating a multiply and add from the critical path in + // decodeLiteralsContextBatch. Always populated alongside literalCodesOffsets + // by prepareLiteralDecoding; never zeroed by initForReuse. + // Placed here (in the pointer section) to keep all pointer-containing + // fields contiguous and avoid extending the GC scan range into the + // large scalar arrays. + literalCodesPtrs [64]unsafe.Pointer + + // In C these are a union; Go embeds both since they are never used + // simultaneously. headerArena contains a slice so it must precede + // scalar-only fields. + headerArena metablockHeaderArena + + // Scalar fields (no pointers beyond this point). + state decoderState + loopCounter int // reused for several disjoint loops + + // Temporary storage for remaining input during streaming. When the + // decoder runs out of input mid-operation, unread bytes from br.input + // are stashed here. The bitReader is then repointed at this buffer to + // resume decoding. 64 bits are enough to make progress in decoding. + bufferLength uint + buffer [8]byte + + pos int + maxBackwardDistance int + maxDistance int + ringbufferSize int + ringbufferMask int + distRBIdx int + distRB [4]int + safeCmdMemento bitReaderState // saved before safe command symbol read + metaBlockRemainingLen int + // Indices into contextMap and distContextMap slices. + contextMapSliceIdx int + distContextMapSliceIdx int + + // True if the literal context map histogram type always matches the block + // type, so context tracking is not needed (faster decoding). + trivialLiteralContext int + // Actual after command decode, before distance computation; then reused + // as a temporary variable. + distanceContext int + blockLength [3]uint + blockLengthIndex uint + numBlockTypes [3]uint + blockTypeRB [6]uint + distancePostfixBits uint + numDirectDistanceCodes uint + numDistHTrees uint + numLiteralHTrees uint + + // For partial write operations. + rbRoundtrips uint // how many times we wrapped around the ring buffer + partialPosOut uint // total output to the user + + // For InverseMoveToFrontTransform. + mtfUpperBound uint + + copyLength int + distanceCode int + + // States inside function calls. + substateMetablockHeader metablockHeaderState + substateUncompressed uncompressedState + substateDecodeUint8 decodeUint8State + substateReadBlockLength readBlockLengthState + + newRingbufferSize int + windowBits int + sizeNibbles int + + trivialLiteralContexts [8]uint32 // 256 bits + + isLastMetablock bool + isUncompressed bool + isMetadata bool + cannyRingbufferAllocation bool + distHTreeIndex byte + distCodesOffset int // cached s.distanceHGroup.htrees[distHTreeIndex] + + // distCodesCache maps each of the 4 distance contexts to the + // corresponding htrees offset for the current distance block type. + // Avoids two dependent memory loads (distContextMap → htrees) + // per command in processCommands. + distCodesCache [4]int + + // The C reference exposes BrotliDecoderSetMetadataCallbacks (decode.h) + // which lets callers receive metadata block contents via a start/chunk + // callback pair. The decoder already skips metadata blocks correctly; + // exposing their contents is a future enhancement. The idiomatic Go + // approach would be a MetadataHandler interface or io.Writer rather than + // C-style function pointers. + + bodyArena metablockBodyArena + + // literalCodesOffsets maps each of the 64 literal contexts to the + // corresponding codes offset for the current literal block type. + // Avoids two dependent memory loads (contextMap → htrees) + // per literal in the non-trivial context path of processCommands. + // Placed at end of struct to avoid shifting hot fields. + literalCodesOffsets [64]int +} + +func (g *huffmanTreeGroup) init(alphabetSizeMax, alphabetSizeLimit, ntrees uint16) { + maxTableSize := int(alphabetSizeLimit) + 376 + g.alphabetSizeMax = alphabetSizeMax + g.alphabetSizeLimit = alphabetSizeLimit + g.numHTrees = ntrees + g.codes = reuseHuffmanCodes(g.codes, int(ntrees)*maxTableSize) + g.htrees = reuseInts(g.htrees, int(ntrees)) +} + +func (cd *decoderCompoundDictionary) attach(data []byte) error { + if len(data) == 0 { + return encoder.ErrEmptyDict + } + if cd.numChunks == 15 { + return encoder.ErrTooManyDicts + } + cd.chunks[cd.numChunks] = data + cd.numChunks++ + cd.totalSize += len(data) + cd.chunkOffsets[cd.numChunks] = cd.totalSize + return nil +} + +// ensureInit lazily builds the block map for O(1) chunk lookup. +func (cd *decoderCompoundDictionary) ensureInit() { + if cd.blockBits != -1 { + return + } + blockBits := 8 + for (cd.totalSize-1)>>blockBits != 0 { + blockBits++ + } + blockBits -= 8 + cd.blockBits = blockBits + + cursor := 0 + index := 0 + for cursor < cd.totalSize { + for cd.chunkOffsets[index+1] < cursor { + index++ + } + cd.blockMap[cursor>>blockBits] = byte(index) + cursor += 1 << blockBits + } +} + +// initCopy sets up a copy operation from compound dictionary at address for +// length bytes. Updates the distance ring buffer and decrements +// metaBlockRemainingLen. Returns false if the address+length exceeds the +// total dictionary size. +func (cd *decoderCompoundDictionary) initCopy(s *decodeState, address, length int) bool { + cd.ensureInit() + index := int(cd.blockMap[address>>cd.blockBits]) + for address >= cd.chunkOffsets[index+1] { + index++ + } + if cd.totalSize < address+length { + return false + } + s.distRB[s.distRBIdx&3] = s.distanceCode + s.distRBIdx++ + s.metaBlockRemainingLen -= length + cd.brIndex = index + cd.brOffset = address - cd.chunkOffsets[index] + cd.brLength = length + cd.brCopied = 0 + return true +} + +// copyTo copies bytes from compound dictionary chunks into s.ringbuffer[pos:], +// handling chunk boundaries and stopping when the ringbuffer is full. +// Returns the number of bytes copied. +func (cd *decoderCompoundDictionary) copyTo(s *decodeState, pos int) int { + origPos := pos + for cd.brLength != cd.brCopied { + copySrc := cd.chunks[cd.brIndex][cd.brOffset:] + space := s.ringbufferSize - pos + remChunkLen := (cd.chunkOffsets[cd.brIndex+1] - cd.chunkOffsets[cd.brIndex]) - cd.brOffset + length := min(cd.brLength-cd.brCopied, min(remChunkLen, space)) + copy(s.ringbuffer[pos:], copySrc[:length]) + pos += length + cd.brOffset += length + cd.brCopied += length + if length == remChunkLen { + cd.brIndex++ + cd.brOffset = 0 + } + if pos == s.ringbufferSize { + break + } + } + return pos - origPos +} + +// init resets s to a clean initial state, ready to begin decoding. +func (s *decodeState) init() { + *s = decodeState{} + s.initDefaults() +} + +func (s *decodeState) initDefaults() { + + s.state = decoderStateUninited + s.cannyRingbufferAllocation = true + + s.distRB = [4]int{16, 15, 11, 4} + + s.mtfUpperBound = 63 +} + +func (s *decodeState) initForReuse() { + // Reset the decoder state for reuse, preserving heap-allocated backing + // arrays. Unlike the previous *s = decodeState{} approach, this avoids + // zeroing ~10 KB of arena arrays (headerArena.contextMapTable, + // headerArena.symbolListsArray, bodyArena, literalCodesOffsets) that are + // always fully initialized before being read. + + // Reset only the scalar bitReader fields that must be zero. + // inputBase and input are stale but will be overwritten by setInput + // before any read, so skipping those two pointer-bearing fields avoids + // two GC write barriers per Decompress call. + s.br.val = 0 + s.br.bitPos = 0 + s.br.pos = 0 + s.br.inputLen = 0 + s.br.fastEnd = 0 + s.err = nil + + // Nil out slices that are derived from preserved slices or set during + // decompression. The saved backing slices (ringbuffer, blockTypeTrees, + // contextMap, etc.) are kept; derived slices are re-derived later. + s.htreeCommand = nil + s.contextLookup = nil + s.literalHTree = nil + s.blockLenTrees = nil + s.compoundDict = nil + + // Zero the huffmanTreeGroup metadata (preserved slice headers stay). + s.literalHGroup.alphabetSizeMax = 0 + s.literalHGroup.alphabetSizeLimit = 0 + s.literalHGroup.numHTrees = 0 + s.insertCopyHGroup.alphabetSizeMax = 0 + s.insertCopyHGroup.alphabetSizeLimit = 0 + s.insertCopyHGroup.numHTrees = 0 + s.distanceHGroup.alphabetSizeMax = 0 + s.distanceHGroup.alphabetSizeLimit = 0 + s.distanceHGroup.numHTrees = 0 + + // Zero only the small scalar fields in headerArena; the large arrays + // (table, symbolListsArray, nextSymbol, codeLengthCodeLengths, + // codeLengthHisto, contextMapTable) are always initialized before use. + s.headerArena.symbolLists = nil + s.headerArena.substateTreeGroup = 0 + s.headerArena.substateContextMap = 0 + s.headerArena.substateHuffman = 0 + s.headerArena.subLoopCounter = 0 + s.headerArena.repeatCodeLen = 0 + s.headerArena.prevCodeLen = 0 + s.headerArena.symbol = 0 + s.headerArena.repeat = 0 + s.headerArena.space = 0 + s.headerArena.htreeIndex = 0 + s.headerArena.next = 0 + s.headerArena.contextIndex = 0 + s.headerArena.maxRunLengthPrefix = 0 + s.headerArena.code = 0 + + // Bulk-zero the contiguous scalar block (state through distCodesCache). + // This region contains no pointers, so raw memclr is safe. + // bodyArena and literalCodesOffsets are NOT zeroed — they are always + // fully written by calculateDistanceLut / prepareLiteralDecoding + // before being read. + start := unsafe.Pointer(&s.state) + size := uintptr(unsafe.Pointer(&s.distCodesCache)) - uintptr(start) + unsafe.Sizeof(s.distCodesCache) + clear(unsafe.Slice((*byte)(start), size)) + + s.initDefaults() +} + +// metablockBegin resets per-metablock state at the start of each metablock. +func (s *decodeState) metablockBegin() { + s.metaBlockRemainingLen = 0 + s.blockLength = [3]uint{blockSizeCap, blockSizeCap, blockSizeCap} + s.numBlockTypes = [3]uint{1, 1, 1} + s.blockTypeRB = [6]uint{1, 0, 1, 0, 1, 0} + s.contextMap = s.contextMap[:0] + s.contextModes = s.contextModes[:0] + s.distContextMap = s.distContextMap[:0] + s.contextMapSliceIdx = 0 + s.distContextMapSliceIdx = 0 + s.distHTreeIndex = 0 + s.distCodesOffset = 0 + s.distCodesCache = [4]int{} + // literalHTree and contextLookup are always overwritten by + // prepareLiteralDecoding before use — skipping the nil assignments here + // avoids two GC write barriers per metablock. + // literalHGroup/insertCopyHGroup/distanceHGroup .codes and .htrees are + // always overwritten by huffmanTreeGroup.init via reuseHuffmanCodes / + // reuseInts (which only check cap, not len) before use — skipping the + // [:0] reslices here avoids six more GC write barriers per metablock. +} + +// updateDistCodesCache fills distCodesCache with the htrees offset for each +// of the 4 distance contexts at the current distContextMapSliceIdx. +func (s *decodeState) updateDistCodesCache() { + base := s.distContextMapSliceIdx + for ctx := range s.distCodesCache { + idx := s.distContextMap[base+ctx] + s.distCodesCache[ctx] = s.distanceHGroup.htrees[idx] + } +} + +// stashTail copies unread bytes from br.input into the internal buffer +// for later resumption. Called when the decoder needs more input while +// reading directly from caller-supplied data. +func (s *decodeState) stashTail() { + s.br.unload() + avail := min(s.br.availIn(), len(s.buffer)) + copy(s.buffer[:avail], s.br.input[s.br.pos:s.br.pos+avail]) + s.bufferLength = uint(avail) +} + +// useStashedTail repoints the bitReader at the internal buffer so +// decoding can resume from the stashed tail bytes. +func (s *decodeState) useStashedTail() { + s.br.setInput(s.buffer[:s.bufferLength]) +} + +// compoundDictSize returns the total size of attached compound dictionaries, +// or 0 if none are attached. +func (s *decodeState) compoundDictSize() int { + if s.compoundDict == nil { + return 0 + } + return s.compoundDict.totalSize +} + +// attachCompoundDict appends a compound dictionary chunk to the decoder state. +// Lazily allocates the decoderCompoundDictionary on first call. +func (s *decodeState) attachCompoundDict(data []byte) error { + if s.compoundDict == nil { + s.compoundDict = &decoderCompoundDictionary{blockBits: -1} + } + return s.compoundDict.attach(data) +} + +// No explicit cleanup method is needed for decodeState: all resources are +// Go-managed (slices, pointers), and Reader.Close already zeroes the state. + +func reuseBytes(buf []byte, size int) []byte { + if cap(buf) >= size { + return buf[:size] + } + return make([]byte, size) +} + +func reuseInts(buf []int, size int) []int { + if cap(buf) >= size { + return buf[:size] + } + return make([]int, size) +} + +func reuseHuffmanCodes(buf []core.HuffmanCode, size int) []core.HuffmanCode { + if cap(buf) >= size { + return buf[:size] + } + return make([]core.HuffmanCode, size) +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/dictionary.go b/src/vendor/github.com/molecule-man/go-brrr/dictionary.go new file mode 100644 index 00000000..f957efbd --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/dictionary.go @@ -0,0 +1,27 @@ +package brrr + +import "github.com/molecule-man/go-brrr/internal/encoder" + +// PreparedDictionary is a compound dictionary chunk built once and shared +// across many Writers. See [WriterOptions.Dictionaries]. It is an opaque +// handle; build one with [PrepareDictionary]. +type PreparedDictionary struct { + impl *encoder.PreparedDictionary +} + +// PrepareDictionary builds an immutable [PreparedDictionary] from the given +// source bytes, suitable for use as a compound dictionary chunk via +// [WriterOptions.Dictionaries]. The returned dictionary may be shared across +// any number of Writers and goroutines. +// +// The returned dictionary keeps a reference to data; the caller must not +// mutate data while any Writer holding the dictionary is still in use. +// +// Returns an error if data is empty. +func PrepareDictionary(data []byte) (*PreparedDictionary, error) { + impl, err := encoder.PrepareDictionary(data) + if err != nil { + return nil, err + } + return &PreparedDictionary{impl: impl}, nil +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/doc.go b/src/vendor/github.com/molecule-man/go-brrr/doc.go new file mode 100644 index 00000000..30366235 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/doc.go @@ -0,0 +1,81 @@ +/* +Package brrr implements the Brotli compressed data format (RFC 7932). + +Brotli is a lossless compression algorithm that typically produces +better ratios than gzip and zstd at the cost of slower compression. +Decompression is fast at every quality level. Every major browser has +accepted Content-Encoding: br since 2016, which makes brotli a good +match for static web asset pipelines. + +# Basic usage + +Streaming compression through an io.Writer: + + var buf bytes.Buffer + w, err := brrr.NewWriter(&buf, 6) + if err != nil { + log.Fatal(err) + } + if _, err := w.Write(data); err != nil { + log.Fatal(err) + } + if err := w.Close(); err != nil { + log.Fatal(err) + } + +Streaming decompression through an io.Reader: + + r := brrr.NewReader(src) + if _, err := io.Copy(dst, r); err != nil { + log.Fatal(err) + } + +One-shot decompression of a complete in-memory blob: + + out, err := brrr.Decompress(compressed) + +# Key types + + - [Writer] implements io.WriteCloser and compresses data written to + an underlying io.Writer. Close must be called to finalize the + brotli stream. + - [Reader] implements io.Reader and decompresses a brotli stream + read from an underlying io.Reader. + - [Decompress] is a convenience function for one-shot decompression + of a complete in-memory blob. + +Writer and Reader both expose Reset methods, so the same instance can +be reused across payloads without reallocating per-call buffers. Both +also accept compound dictionaries — useful when the payloads share +content with a known corpus. The encoder takes pre-built +[PreparedDictionary] values via [WriterOptions.Dictionaries], so the +hash table is built once and may be shared across many Writers and +goroutines. The decoder takes raw dictionary bytes via +[ReaderOptions.Dictionaries]. + +# Choosing a quality level + +Quality controls the ratio/speed trade-off on a scale of 0 to 11: + + - Quality 0–1 use fast one-pass and two-pass encoders optimised for + throughput. + - Quality 2–9 use a streaming encoder that spends progressively more + work per byte for better ratios. + - Quality 10–11 use a Zopfli-style optimal-parsing encoder that + produces the best ratios but is orders of magnitude slower than + the lower levels. + +The canonical use case for brotli is static asset compression — CSS, +JS, HTML, fonts, WASM — where the data is compressed once at build +time and served many times; quality 11 is the right choice there. For +on-the-fly compression, quality 5–6 gives a good balance of speed and +ratio. + +# Compatibility + +Output is byte-compatible with the reference implementation at +https://github.com/google/brotli. Any conforming brotli decoder can +read streams produced by this package, and this package can decode +any valid brotli stream. +*/ +package brrr diff --git a/src/vendor/github.com/molecule-man/go-brrr/internal/core/cmdlut.go b/src/vendor/github.com/molecule-man/go-brrr/internal/core/cmdlut.go new file mode 100644 index 00000000..2442408e --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/internal/core/cmdlut.go @@ -0,0 +1,722 @@ +// Command symbol lookup table for the decoder (RFC 7932 Section 5). + +package core + +// CmdLut maps each of the 704 command symbols to its decoding parameters. +var CmdLut = [AlphabetSizeInsertAndCopyLength]CmdLutElement{ + {0x00, 0x00, 0, 0x00, 0x0000, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0000, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0000, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0000, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0000, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0000, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0000, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0000, 0x0009}, + {0x00, 0x00, 0, 0x00, 0x0001, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0001, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0001, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0001, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0001, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0001, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0001, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0001, 0x0009}, + {0x00, 0x00, 0, 0x00, 0x0002, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0002, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0002, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0002, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0002, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0002, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0002, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0002, 0x0009}, + {0x00, 0x00, 0, 0x00, 0x0003, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0003, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0003, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0003, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0003, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0003, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0003, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0003, 0x0009}, + {0x00, 0x00, 0, 0x00, 0x0004, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0004, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0004, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0004, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0004, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0004, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0004, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0004, 0x0009}, + {0x00, 0x00, 0, 0x00, 0x0005, 0x0002}, + {0x00, 0x00, 0, 0x01, 0x0005, 0x0003}, + {0x00, 0x00, 0, 0x02, 0x0005, 0x0004}, + {0x00, 0x00, 0, 0x03, 0x0005, 0x0005}, + {0x00, 0x00, 0, 0x03, 0x0005, 0x0006}, + {0x00, 0x00, 0, 0x03, 0x0005, 0x0007}, + {0x00, 0x00, 0, 0x03, 0x0005, 0x0008}, + {0x00, 0x00, 0, 0x03, 0x0005, 0x0009}, + {0x01, 0x00, 0, 0x00, 0x0006, 0x0002}, + {0x01, 0x00, 0, 0x01, 0x0006, 0x0003}, + {0x01, 0x00, 0, 0x02, 0x0006, 0x0004}, + {0x01, 0x00, 0, 0x03, 0x0006, 0x0005}, + {0x01, 0x00, 0, 0x03, 0x0006, 0x0006}, + {0x01, 0x00, 0, 0x03, 0x0006, 0x0007}, + {0x01, 0x00, 0, 0x03, 0x0006, 0x0008}, + {0x01, 0x00, 0, 0x03, 0x0006, 0x0009}, + {0x01, 0x00, 0, 0x00, 0x0008, 0x0002}, + {0x01, 0x00, 0, 0x01, 0x0008, 0x0003}, + {0x01, 0x00, 0, 0x02, 0x0008, 0x0004}, + {0x01, 0x00, 0, 0x03, 0x0008, 0x0005}, + {0x01, 0x00, 0, 0x03, 0x0008, 0x0006}, + {0x01, 0x00, 0, 0x03, 0x0008, 0x0007}, + {0x01, 0x00, 0, 0x03, 0x0008, 0x0008}, + {0x01, 0x00, 0, 0x03, 0x0008, 0x0009}, + {0x00, 0x01, 0, 0x03, 0x0000, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0000, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0000, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0000, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0000, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0000, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0000, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0000, 0x0036}, + {0x00, 0x01, 0, 0x03, 0x0001, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0001, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0001, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0001, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0001, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0001, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0001, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0001, 0x0036}, + {0x00, 0x01, 0, 0x03, 0x0002, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0002, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0002, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0002, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0002, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0002, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0002, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0002, 0x0036}, + {0x00, 0x01, 0, 0x03, 0x0003, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0003, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0003, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0003, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0003, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0003, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0003, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0003, 0x0036}, + {0x00, 0x01, 0, 0x03, 0x0004, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0004, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0004, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0004, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0004, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0004, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0004, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0004, 0x0036}, + {0x00, 0x01, 0, 0x03, 0x0005, 0x000a}, + {0x00, 0x01, 0, 0x03, 0x0005, 0x000c}, + {0x00, 0x02, 0, 0x03, 0x0005, 0x000e}, + {0x00, 0x02, 0, 0x03, 0x0005, 0x0012}, + {0x00, 0x03, 0, 0x03, 0x0005, 0x0016}, + {0x00, 0x03, 0, 0x03, 0x0005, 0x001e}, + {0x00, 0x04, 0, 0x03, 0x0005, 0x0026}, + {0x00, 0x04, 0, 0x03, 0x0005, 0x0036}, + {0x01, 0x01, 0, 0x03, 0x0006, 0x000a}, + {0x01, 0x01, 0, 0x03, 0x0006, 0x000c}, + {0x01, 0x02, 0, 0x03, 0x0006, 0x000e}, + {0x01, 0x02, 0, 0x03, 0x0006, 0x0012}, + {0x01, 0x03, 0, 0x03, 0x0006, 0x0016}, + {0x01, 0x03, 0, 0x03, 0x0006, 0x001e}, + {0x01, 0x04, 0, 0x03, 0x0006, 0x0026}, + {0x01, 0x04, 0, 0x03, 0x0006, 0x0036}, + {0x01, 0x01, 0, 0x03, 0x0008, 0x000a}, + {0x01, 0x01, 0, 0x03, 0x0008, 0x000c}, + {0x01, 0x02, 0, 0x03, 0x0008, 0x000e}, + {0x01, 0x02, 0, 0x03, 0x0008, 0x0012}, + {0x01, 0x03, 0, 0x03, 0x0008, 0x0016}, + {0x01, 0x03, 0, 0x03, 0x0008, 0x001e}, + {0x01, 0x04, 0, 0x03, 0x0008, 0x0026}, + {0x01, 0x04, 0, 0x03, 0x0008, 0x0036}, + {0x00, 0x00, -1, 0x00, 0x0000, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0000, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0000, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0000, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0000, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0000, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0000, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0000, 0x0009}, + {0x00, 0x00, -1, 0x00, 0x0001, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0001, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0001, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0001, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0001, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0001, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0001, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0001, 0x0009}, + {0x00, 0x00, -1, 0x00, 0x0002, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0002, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0002, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0002, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0002, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0002, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0002, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0002, 0x0009}, + {0x00, 0x00, -1, 0x00, 0x0003, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0003, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0003, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0003, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0003, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0003, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0003, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0003, 0x0009}, + {0x00, 0x00, -1, 0x00, 0x0004, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0004, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0004, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0004, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0004, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0004, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0004, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0004, 0x0009}, + {0x00, 0x00, -1, 0x00, 0x0005, 0x0002}, + {0x00, 0x00, -1, 0x01, 0x0005, 0x0003}, + {0x00, 0x00, -1, 0x02, 0x0005, 0x0004}, + {0x00, 0x00, -1, 0x03, 0x0005, 0x0005}, + {0x00, 0x00, -1, 0x03, 0x0005, 0x0006}, + {0x00, 0x00, -1, 0x03, 0x0005, 0x0007}, + {0x00, 0x00, -1, 0x03, 0x0005, 0x0008}, + {0x00, 0x00, -1, 0x03, 0x0005, 0x0009}, + {0x01, 0x00, -1, 0x00, 0x0006, 0x0002}, + {0x01, 0x00, -1, 0x01, 0x0006, 0x0003}, + {0x01, 0x00, -1, 0x02, 0x0006, 0x0004}, + {0x01, 0x00, -1, 0x03, 0x0006, 0x0005}, + {0x01, 0x00, -1, 0x03, 0x0006, 0x0006}, + {0x01, 0x00, -1, 0x03, 0x0006, 0x0007}, + {0x01, 0x00, -1, 0x03, 0x0006, 0x0008}, + {0x01, 0x00, -1, 0x03, 0x0006, 0x0009}, + {0x01, 0x00, -1, 0x00, 0x0008, 0x0002}, + {0x01, 0x00, -1, 0x01, 0x0008, 0x0003}, + {0x01, 0x00, -1, 0x02, 0x0008, 0x0004}, + {0x01, 0x00, -1, 0x03, 0x0008, 0x0005}, + {0x01, 0x00, -1, 0x03, 0x0008, 0x0006}, + {0x01, 0x00, -1, 0x03, 0x0008, 0x0007}, + {0x01, 0x00, -1, 0x03, 0x0008, 0x0008}, + {0x01, 0x00, -1, 0x03, 0x0008, 0x0009}, + {0x00, 0x01, -1, 0x03, 0x0000, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0000, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0000, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0000, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0000, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0000, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0000, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0000, 0x0036}, + {0x00, 0x01, -1, 0x03, 0x0001, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0001, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0001, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0001, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0001, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0001, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0001, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0001, 0x0036}, + {0x00, 0x01, -1, 0x03, 0x0002, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0002, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0002, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0002, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0002, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0002, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0002, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0002, 0x0036}, + {0x00, 0x01, -1, 0x03, 0x0003, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0003, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0003, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0003, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0003, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0003, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0003, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0003, 0x0036}, + {0x00, 0x01, -1, 0x03, 0x0004, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0004, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0004, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0004, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0004, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0004, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0004, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0004, 0x0036}, + {0x00, 0x01, -1, 0x03, 0x0005, 0x000a}, + {0x00, 0x01, -1, 0x03, 0x0005, 0x000c}, + {0x00, 0x02, -1, 0x03, 0x0005, 0x000e}, + {0x00, 0x02, -1, 0x03, 0x0005, 0x0012}, + {0x00, 0x03, -1, 0x03, 0x0005, 0x0016}, + {0x00, 0x03, -1, 0x03, 0x0005, 0x001e}, + {0x00, 0x04, -1, 0x03, 0x0005, 0x0026}, + {0x00, 0x04, -1, 0x03, 0x0005, 0x0036}, + {0x01, 0x01, -1, 0x03, 0x0006, 0x000a}, + {0x01, 0x01, -1, 0x03, 0x0006, 0x000c}, + {0x01, 0x02, -1, 0x03, 0x0006, 0x000e}, + {0x01, 0x02, -1, 0x03, 0x0006, 0x0012}, + {0x01, 0x03, -1, 0x03, 0x0006, 0x0016}, + {0x01, 0x03, -1, 0x03, 0x0006, 0x001e}, + {0x01, 0x04, -1, 0x03, 0x0006, 0x0026}, + {0x01, 0x04, -1, 0x03, 0x0006, 0x0036}, + {0x01, 0x01, -1, 0x03, 0x0008, 0x000a}, + {0x01, 0x01, -1, 0x03, 0x0008, 0x000c}, + {0x01, 0x02, -1, 0x03, 0x0008, 0x000e}, + {0x01, 0x02, -1, 0x03, 0x0008, 0x0012}, + {0x01, 0x03, -1, 0x03, 0x0008, 0x0016}, + {0x01, 0x03, -1, 0x03, 0x0008, 0x001e}, + {0x01, 0x04, -1, 0x03, 0x0008, 0x0026}, + {0x01, 0x04, -1, 0x03, 0x0008, 0x0036}, + {0x02, 0x00, -1, 0x00, 0x000a, 0x0002}, + {0x02, 0x00, -1, 0x01, 0x000a, 0x0003}, + {0x02, 0x00, -1, 0x02, 0x000a, 0x0004}, + {0x02, 0x00, -1, 0x03, 0x000a, 0x0005}, + {0x02, 0x00, -1, 0x03, 0x000a, 0x0006}, + {0x02, 0x00, -1, 0x03, 0x000a, 0x0007}, + {0x02, 0x00, -1, 0x03, 0x000a, 0x0008}, + {0x02, 0x00, -1, 0x03, 0x000a, 0x0009}, + {0x02, 0x00, -1, 0x00, 0x000e, 0x0002}, + {0x02, 0x00, -1, 0x01, 0x000e, 0x0003}, + {0x02, 0x00, -1, 0x02, 0x000e, 0x0004}, + {0x02, 0x00, -1, 0x03, 0x000e, 0x0005}, + {0x02, 0x00, -1, 0x03, 0x000e, 0x0006}, + {0x02, 0x00, -1, 0x03, 0x000e, 0x0007}, + {0x02, 0x00, -1, 0x03, 0x000e, 0x0008}, + {0x02, 0x00, -1, 0x03, 0x000e, 0x0009}, + {0x03, 0x00, -1, 0x00, 0x0012, 0x0002}, + {0x03, 0x00, -1, 0x01, 0x0012, 0x0003}, + {0x03, 0x00, -1, 0x02, 0x0012, 0x0004}, + {0x03, 0x00, -1, 0x03, 0x0012, 0x0005}, + {0x03, 0x00, -1, 0x03, 0x0012, 0x0006}, + {0x03, 0x00, -1, 0x03, 0x0012, 0x0007}, + {0x03, 0x00, -1, 0x03, 0x0012, 0x0008}, + {0x03, 0x00, -1, 0x03, 0x0012, 0x0009}, + {0x03, 0x00, -1, 0x00, 0x001a, 0x0002}, + {0x03, 0x00, -1, 0x01, 0x001a, 0x0003}, + {0x03, 0x00, -1, 0x02, 0x001a, 0x0004}, + {0x03, 0x00, -1, 0x03, 0x001a, 0x0005}, + {0x03, 0x00, -1, 0x03, 0x001a, 0x0006}, + {0x03, 0x00, -1, 0x03, 0x001a, 0x0007}, + {0x03, 0x00, -1, 0x03, 0x001a, 0x0008}, + {0x03, 0x00, -1, 0x03, 0x001a, 0x0009}, + {0x04, 0x00, -1, 0x00, 0x0022, 0x0002}, + {0x04, 0x00, -1, 0x01, 0x0022, 0x0003}, + {0x04, 0x00, -1, 0x02, 0x0022, 0x0004}, + {0x04, 0x00, -1, 0x03, 0x0022, 0x0005}, + {0x04, 0x00, -1, 0x03, 0x0022, 0x0006}, + {0x04, 0x00, -1, 0x03, 0x0022, 0x0007}, + {0x04, 0x00, -1, 0x03, 0x0022, 0x0008}, + {0x04, 0x00, -1, 0x03, 0x0022, 0x0009}, + {0x04, 0x00, -1, 0x00, 0x0032, 0x0002}, + {0x04, 0x00, -1, 0x01, 0x0032, 0x0003}, + {0x04, 0x00, -1, 0x02, 0x0032, 0x0004}, + {0x04, 0x00, -1, 0x03, 0x0032, 0x0005}, + {0x04, 0x00, -1, 0x03, 0x0032, 0x0006}, + {0x04, 0x00, -1, 0x03, 0x0032, 0x0007}, + {0x04, 0x00, -1, 0x03, 0x0032, 0x0008}, + {0x04, 0x00, -1, 0x03, 0x0032, 0x0009}, + {0x05, 0x00, -1, 0x00, 0x0042, 0x0002}, + {0x05, 0x00, -1, 0x01, 0x0042, 0x0003}, + {0x05, 0x00, -1, 0x02, 0x0042, 0x0004}, + {0x05, 0x00, -1, 0x03, 0x0042, 0x0005}, + {0x05, 0x00, -1, 0x03, 0x0042, 0x0006}, + {0x05, 0x00, -1, 0x03, 0x0042, 0x0007}, + {0x05, 0x00, -1, 0x03, 0x0042, 0x0008}, + {0x05, 0x00, -1, 0x03, 0x0042, 0x0009}, + {0x05, 0x00, -1, 0x00, 0x0062, 0x0002}, + {0x05, 0x00, -1, 0x01, 0x0062, 0x0003}, + {0x05, 0x00, -1, 0x02, 0x0062, 0x0004}, + {0x05, 0x00, -1, 0x03, 0x0062, 0x0005}, + {0x05, 0x00, -1, 0x03, 0x0062, 0x0006}, + {0x05, 0x00, -1, 0x03, 0x0062, 0x0007}, + {0x05, 0x00, -1, 0x03, 0x0062, 0x0008}, + {0x05, 0x00, -1, 0x03, 0x0062, 0x0009}, + {0x02, 0x01, -1, 0x03, 0x000a, 0x000a}, + {0x02, 0x01, -1, 0x03, 0x000a, 0x000c}, + {0x02, 0x02, -1, 0x03, 0x000a, 0x000e}, + {0x02, 0x02, -1, 0x03, 0x000a, 0x0012}, + {0x02, 0x03, -1, 0x03, 0x000a, 0x0016}, + {0x02, 0x03, -1, 0x03, 0x000a, 0x001e}, + {0x02, 0x04, -1, 0x03, 0x000a, 0x0026}, + {0x02, 0x04, -1, 0x03, 0x000a, 0x0036}, + {0x02, 0x01, -1, 0x03, 0x000e, 0x000a}, + {0x02, 0x01, -1, 0x03, 0x000e, 0x000c}, + {0x02, 0x02, -1, 0x03, 0x000e, 0x000e}, + {0x02, 0x02, -1, 0x03, 0x000e, 0x0012}, + {0x02, 0x03, -1, 0x03, 0x000e, 0x0016}, + {0x02, 0x03, -1, 0x03, 0x000e, 0x001e}, + {0x02, 0x04, -1, 0x03, 0x000e, 0x0026}, + {0x02, 0x04, -1, 0x03, 0x000e, 0x0036}, + {0x03, 0x01, -1, 0x03, 0x0012, 0x000a}, + {0x03, 0x01, -1, 0x03, 0x0012, 0x000c}, + {0x03, 0x02, -1, 0x03, 0x0012, 0x000e}, + {0x03, 0x02, -1, 0x03, 0x0012, 0x0012}, + {0x03, 0x03, -1, 0x03, 0x0012, 0x0016}, + {0x03, 0x03, -1, 0x03, 0x0012, 0x001e}, + {0x03, 0x04, -1, 0x03, 0x0012, 0x0026}, + {0x03, 0x04, -1, 0x03, 0x0012, 0x0036}, + {0x03, 0x01, -1, 0x03, 0x001a, 0x000a}, + {0x03, 0x01, -1, 0x03, 0x001a, 0x000c}, + {0x03, 0x02, -1, 0x03, 0x001a, 0x000e}, + {0x03, 0x02, -1, 0x03, 0x001a, 0x0012}, + {0x03, 0x03, -1, 0x03, 0x001a, 0x0016}, + {0x03, 0x03, -1, 0x03, 0x001a, 0x001e}, + {0x03, 0x04, -1, 0x03, 0x001a, 0x0026}, + {0x03, 0x04, -1, 0x03, 0x001a, 0x0036}, + {0x04, 0x01, -1, 0x03, 0x0022, 0x000a}, + {0x04, 0x01, -1, 0x03, 0x0022, 0x000c}, + {0x04, 0x02, -1, 0x03, 0x0022, 0x000e}, + {0x04, 0x02, -1, 0x03, 0x0022, 0x0012}, + {0x04, 0x03, -1, 0x03, 0x0022, 0x0016}, + {0x04, 0x03, -1, 0x03, 0x0022, 0x001e}, + {0x04, 0x04, -1, 0x03, 0x0022, 0x0026}, + {0x04, 0x04, -1, 0x03, 0x0022, 0x0036}, + {0x04, 0x01, -1, 0x03, 0x0032, 0x000a}, + {0x04, 0x01, -1, 0x03, 0x0032, 0x000c}, + {0x04, 0x02, -1, 0x03, 0x0032, 0x000e}, + {0x04, 0x02, -1, 0x03, 0x0032, 0x0012}, + {0x04, 0x03, -1, 0x03, 0x0032, 0x0016}, + {0x04, 0x03, -1, 0x03, 0x0032, 0x001e}, + {0x04, 0x04, -1, 0x03, 0x0032, 0x0026}, + {0x04, 0x04, -1, 0x03, 0x0032, 0x0036}, + {0x05, 0x01, -1, 0x03, 0x0042, 0x000a}, + {0x05, 0x01, -1, 0x03, 0x0042, 0x000c}, + {0x05, 0x02, -1, 0x03, 0x0042, 0x000e}, + {0x05, 0x02, -1, 0x03, 0x0042, 0x0012}, + {0x05, 0x03, -1, 0x03, 0x0042, 0x0016}, + {0x05, 0x03, -1, 0x03, 0x0042, 0x001e}, + {0x05, 0x04, -1, 0x03, 0x0042, 0x0026}, + {0x05, 0x04, -1, 0x03, 0x0042, 0x0036}, + {0x05, 0x01, -1, 0x03, 0x0062, 0x000a}, + {0x05, 0x01, -1, 0x03, 0x0062, 0x000c}, + {0x05, 0x02, -1, 0x03, 0x0062, 0x000e}, + {0x05, 0x02, -1, 0x03, 0x0062, 0x0012}, + {0x05, 0x03, -1, 0x03, 0x0062, 0x0016}, + {0x05, 0x03, -1, 0x03, 0x0062, 0x001e}, + {0x05, 0x04, -1, 0x03, 0x0062, 0x0026}, + {0x05, 0x04, -1, 0x03, 0x0062, 0x0036}, + {0x00, 0x05, -1, 0x03, 0x0000, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0000, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0000, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0000, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0000, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0000, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0000, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0000, 0x0846}, + {0x00, 0x05, -1, 0x03, 0x0001, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0001, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0001, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0001, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0001, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0001, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0001, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0001, 0x0846}, + {0x00, 0x05, -1, 0x03, 0x0002, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0002, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0002, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0002, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0002, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0002, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0002, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0002, 0x0846}, + {0x00, 0x05, -1, 0x03, 0x0003, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0003, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0003, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0003, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0003, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0003, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0003, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0003, 0x0846}, + {0x00, 0x05, -1, 0x03, 0x0004, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0004, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0004, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0004, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0004, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0004, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0004, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0004, 0x0846}, + {0x00, 0x05, -1, 0x03, 0x0005, 0x0046}, + {0x00, 0x05, -1, 0x03, 0x0005, 0x0066}, + {0x00, 0x06, -1, 0x03, 0x0005, 0x0086}, + {0x00, 0x07, -1, 0x03, 0x0005, 0x00c6}, + {0x00, 0x08, -1, 0x03, 0x0005, 0x0146}, + {0x00, 0x09, -1, 0x03, 0x0005, 0x0246}, + {0x00, 0x0a, -1, 0x03, 0x0005, 0x0446}, + {0x00, 0x18, -1, 0x03, 0x0005, 0x0846}, + {0x01, 0x05, -1, 0x03, 0x0006, 0x0046}, + {0x01, 0x05, -1, 0x03, 0x0006, 0x0066}, + {0x01, 0x06, -1, 0x03, 0x0006, 0x0086}, + {0x01, 0x07, -1, 0x03, 0x0006, 0x00c6}, + {0x01, 0x08, -1, 0x03, 0x0006, 0x0146}, + {0x01, 0x09, -1, 0x03, 0x0006, 0x0246}, + {0x01, 0x0a, -1, 0x03, 0x0006, 0x0446}, + {0x01, 0x18, -1, 0x03, 0x0006, 0x0846}, + {0x01, 0x05, -1, 0x03, 0x0008, 0x0046}, + {0x01, 0x05, -1, 0x03, 0x0008, 0x0066}, + {0x01, 0x06, -1, 0x03, 0x0008, 0x0086}, + {0x01, 0x07, -1, 0x03, 0x0008, 0x00c6}, + {0x01, 0x08, -1, 0x03, 0x0008, 0x0146}, + {0x01, 0x09, -1, 0x03, 0x0008, 0x0246}, + {0x01, 0x0a, -1, 0x03, 0x0008, 0x0446}, + {0x01, 0x18, -1, 0x03, 0x0008, 0x0846}, + {0x06, 0x00, -1, 0x00, 0x0082, 0x0002}, + {0x06, 0x00, -1, 0x01, 0x0082, 0x0003}, + {0x06, 0x00, -1, 0x02, 0x0082, 0x0004}, + {0x06, 0x00, -1, 0x03, 0x0082, 0x0005}, + {0x06, 0x00, -1, 0x03, 0x0082, 0x0006}, + {0x06, 0x00, -1, 0x03, 0x0082, 0x0007}, + {0x06, 0x00, -1, 0x03, 0x0082, 0x0008}, + {0x06, 0x00, -1, 0x03, 0x0082, 0x0009}, + {0x07, 0x00, -1, 0x00, 0x00c2, 0x0002}, + {0x07, 0x00, -1, 0x01, 0x00c2, 0x0003}, + {0x07, 0x00, -1, 0x02, 0x00c2, 0x0004}, + {0x07, 0x00, -1, 0x03, 0x00c2, 0x0005}, + {0x07, 0x00, -1, 0x03, 0x00c2, 0x0006}, + {0x07, 0x00, -1, 0x03, 0x00c2, 0x0007}, + {0x07, 0x00, -1, 0x03, 0x00c2, 0x0008}, + {0x07, 0x00, -1, 0x03, 0x00c2, 0x0009}, + {0x08, 0x00, -1, 0x00, 0x0142, 0x0002}, + {0x08, 0x00, -1, 0x01, 0x0142, 0x0003}, + {0x08, 0x00, -1, 0x02, 0x0142, 0x0004}, + {0x08, 0x00, -1, 0x03, 0x0142, 0x0005}, + {0x08, 0x00, -1, 0x03, 0x0142, 0x0006}, + {0x08, 0x00, -1, 0x03, 0x0142, 0x0007}, + {0x08, 0x00, -1, 0x03, 0x0142, 0x0008}, + {0x08, 0x00, -1, 0x03, 0x0142, 0x0009}, + {0x09, 0x00, -1, 0x00, 0x0242, 0x0002}, + {0x09, 0x00, -1, 0x01, 0x0242, 0x0003}, + {0x09, 0x00, -1, 0x02, 0x0242, 0x0004}, + {0x09, 0x00, -1, 0x03, 0x0242, 0x0005}, + {0x09, 0x00, -1, 0x03, 0x0242, 0x0006}, + {0x09, 0x00, -1, 0x03, 0x0242, 0x0007}, + {0x09, 0x00, -1, 0x03, 0x0242, 0x0008}, + {0x09, 0x00, -1, 0x03, 0x0242, 0x0009}, + {0x0a, 0x00, -1, 0x00, 0x0442, 0x0002}, + {0x0a, 0x00, -1, 0x01, 0x0442, 0x0003}, + {0x0a, 0x00, -1, 0x02, 0x0442, 0x0004}, + {0x0a, 0x00, -1, 0x03, 0x0442, 0x0005}, + {0x0a, 0x00, -1, 0x03, 0x0442, 0x0006}, + {0x0a, 0x00, -1, 0x03, 0x0442, 0x0007}, + {0x0a, 0x00, -1, 0x03, 0x0442, 0x0008}, + {0x0a, 0x00, -1, 0x03, 0x0442, 0x0009}, + {0x0c, 0x00, -1, 0x00, 0x0842, 0x0002}, + {0x0c, 0x00, -1, 0x01, 0x0842, 0x0003}, + {0x0c, 0x00, -1, 0x02, 0x0842, 0x0004}, + {0x0c, 0x00, -1, 0x03, 0x0842, 0x0005}, + {0x0c, 0x00, -1, 0x03, 0x0842, 0x0006}, + {0x0c, 0x00, -1, 0x03, 0x0842, 0x0007}, + {0x0c, 0x00, -1, 0x03, 0x0842, 0x0008}, + {0x0c, 0x00, -1, 0x03, 0x0842, 0x0009}, + {0x0e, 0x00, -1, 0x00, 0x1842, 0x0002}, + {0x0e, 0x00, -1, 0x01, 0x1842, 0x0003}, + {0x0e, 0x00, -1, 0x02, 0x1842, 0x0004}, + {0x0e, 0x00, -1, 0x03, 0x1842, 0x0005}, + {0x0e, 0x00, -1, 0x03, 0x1842, 0x0006}, + {0x0e, 0x00, -1, 0x03, 0x1842, 0x0007}, + {0x0e, 0x00, -1, 0x03, 0x1842, 0x0008}, + {0x0e, 0x00, -1, 0x03, 0x1842, 0x0009}, + {0x18, 0x00, -1, 0x00, 0x5842, 0x0002}, + {0x18, 0x00, -1, 0x01, 0x5842, 0x0003}, + {0x18, 0x00, -1, 0x02, 0x5842, 0x0004}, + {0x18, 0x00, -1, 0x03, 0x5842, 0x0005}, + {0x18, 0x00, -1, 0x03, 0x5842, 0x0006}, + {0x18, 0x00, -1, 0x03, 0x5842, 0x0007}, + {0x18, 0x00, -1, 0x03, 0x5842, 0x0008}, + {0x18, 0x00, -1, 0x03, 0x5842, 0x0009}, + {0x02, 0x05, -1, 0x03, 0x000a, 0x0046}, + {0x02, 0x05, -1, 0x03, 0x000a, 0x0066}, + {0x02, 0x06, -1, 0x03, 0x000a, 0x0086}, + {0x02, 0x07, -1, 0x03, 0x000a, 0x00c6}, + {0x02, 0x08, -1, 0x03, 0x000a, 0x0146}, + {0x02, 0x09, -1, 0x03, 0x000a, 0x0246}, + {0x02, 0x0a, -1, 0x03, 0x000a, 0x0446}, + {0x02, 0x18, -1, 0x03, 0x000a, 0x0846}, + {0x02, 0x05, -1, 0x03, 0x000e, 0x0046}, + {0x02, 0x05, -1, 0x03, 0x000e, 0x0066}, + {0x02, 0x06, -1, 0x03, 0x000e, 0x0086}, + {0x02, 0x07, -1, 0x03, 0x000e, 0x00c6}, + {0x02, 0x08, -1, 0x03, 0x000e, 0x0146}, + {0x02, 0x09, -1, 0x03, 0x000e, 0x0246}, + {0x02, 0x0a, -1, 0x03, 0x000e, 0x0446}, + {0x02, 0x18, -1, 0x03, 0x000e, 0x0846}, + {0x03, 0x05, -1, 0x03, 0x0012, 0x0046}, + {0x03, 0x05, -1, 0x03, 0x0012, 0x0066}, + {0x03, 0x06, -1, 0x03, 0x0012, 0x0086}, + {0x03, 0x07, -1, 0x03, 0x0012, 0x00c6}, + {0x03, 0x08, -1, 0x03, 0x0012, 0x0146}, + {0x03, 0x09, -1, 0x03, 0x0012, 0x0246}, + {0x03, 0x0a, -1, 0x03, 0x0012, 0x0446}, + {0x03, 0x18, -1, 0x03, 0x0012, 0x0846}, + {0x03, 0x05, -1, 0x03, 0x001a, 0x0046}, + {0x03, 0x05, -1, 0x03, 0x001a, 0x0066}, + {0x03, 0x06, -1, 0x03, 0x001a, 0x0086}, + {0x03, 0x07, -1, 0x03, 0x001a, 0x00c6}, + {0x03, 0x08, -1, 0x03, 0x001a, 0x0146}, + {0x03, 0x09, -1, 0x03, 0x001a, 0x0246}, + {0x03, 0x0a, -1, 0x03, 0x001a, 0x0446}, + {0x03, 0x18, -1, 0x03, 0x001a, 0x0846}, + {0x04, 0x05, -1, 0x03, 0x0022, 0x0046}, + {0x04, 0x05, -1, 0x03, 0x0022, 0x0066}, + {0x04, 0x06, -1, 0x03, 0x0022, 0x0086}, + {0x04, 0x07, -1, 0x03, 0x0022, 0x00c6}, + {0x04, 0x08, -1, 0x03, 0x0022, 0x0146}, + {0x04, 0x09, -1, 0x03, 0x0022, 0x0246}, + {0x04, 0x0a, -1, 0x03, 0x0022, 0x0446}, + {0x04, 0x18, -1, 0x03, 0x0022, 0x0846}, + {0x04, 0x05, -1, 0x03, 0x0032, 0x0046}, + {0x04, 0x05, -1, 0x03, 0x0032, 0x0066}, + {0x04, 0x06, -1, 0x03, 0x0032, 0x0086}, + {0x04, 0x07, -1, 0x03, 0x0032, 0x00c6}, + {0x04, 0x08, -1, 0x03, 0x0032, 0x0146}, + {0x04, 0x09, -1, 0x03, 0x0032, 0x0246}, + {0x04, 0x0a, -1, 0x03, 0x0032, 0x0446}, + {0x04, 0x18, -1, 0x03, 0x0032, 0x0846}, + {0x05, 0x05, -1, 0x03, 0x0042, 0x0046}, + {0x05, 0x05, -1, 0x03, 0x0042, 0x0066}, + {0x05, 0x06, -1, 0x03, 0x0042, 0x0086}, + {0x05, 0x07, -1, 0x03, 0x0042, 0x00c6}, + {0x05, 0x08, -1, 0x03, 0x0042, 0x0146}, + {0x05, 0x09, -1, 0x03, 0x0042, 0x0246}, + {0x05, 0x0a, -1, 0x03, 0x0042, 0x0446}, + {0x05, 0x18, -1, 0x03, 0x0042, 0x0846}, + {0x05, 0x05, -1, 0x03, 0x0062, 0x0046}, + {0x05, 0x05, -1, 0x03, 0x0062, 0x0066}, + {0x05, 0x06, -1, 0x03, 0x0062, 0x0086}, + {0x05, 0x07, -1, 0x03, 0x0062, 0x00c6}, + {0x05, 0x08, -1, 0x03, 0x0062, 0x0146}, + {0x05, 0x09, -1, 0x03, 0x0062, 0x0246}, + {0x05, 0x0a, -1, 0x03, 0x0062, 0x0446}, + {0x05, 0x18, -1, 0x03, 0x0062, 0x0846}, + {0x06, 0x01, -1, 0x03, 0x0082, 0x000a}, + {0x06, 0x01, -1, 0x03, 0x0082, 0x000c}, + {0x06, 0x02, -1, 0x03, 0x0082, 0x000e}, + {0x06, 0x02, -1, 0x03, 0x0082, 0x0012}, + {0x06, 0x03, -1, 0x03, 0x0082, 0x0016}, + {0x06, 0x03, -1, 0x03, 0x0082, 0x001e}, + {0x06, 0x04, -1, 0x03, 0x0082, 0x0026}, + {0x06, 0x04, -1, 0x03, 0x0082, 0x0036}, + {0x07, 0x01, -1, 0x03, 0x00c2, 0x000a}, + {0x07, 0x01, -1, 0x03, 0x00c2, 0x000c}, + {0x07, 0x02, -1, 0x03, 0x00c2, 0x000e}, + {0x07, 0x02, -1, 0x03, 0x00c2, 0x0012}, + {0x07, 0x03, -1, 0x03, 0x00c2, 0x0016}, + {0x07, 0x03, -1, 0x03, 0x00c2, 0x001e}, + {0x07, 0x04, -1, 0x03, 0x00c2, 0x0026}, + {0x07, 0x04, -1, 0x03, 0x00c2, 0x0036}, + {0x08, 0x01, -1, 0x03, 0x0142, 0x000a}, + {0x08, 0x01, -1, 0x03, 0x0142, 0x000c}, + {0x08, 0x02, -1, 0x03, 0x0142, 0x000e}, + {0x08, 0x02, -1, 0x03, 0x0142, 0x0012}, + {0x08, 0x03, -1, 0x03, 0x0142, 0x0016}, + {0x08, 0x03, -1, 0x03, 0x0142, 0x001e}, + {0x08, 0x04, -1, 0x03, 0x0142, 0x0026}, + {0x08, 0x04, -1, 0x03, 0x0142, 0x0036}, + {0x09, 0x01, -1, 0x03, 0x0242, 0x000a}, + {0x09, 0x01, -1, 0x03, 0x0242, 0x000c}, + {0x09, 0x02, -1, 0x03, 0x0242, 0x000e}, + {0x09, 0x02, -1, 0x03, 0x0242, 0x0012}, + {0x09, 0x03, -1, 0x03, 0x0242, 0x0016}, + {0x09, 0x03, -1, 0x03, 0x0242, 0x001e}, + {0x09, 0x04, -1, 0x03, 0x0242, 0x0026}, + {0x09, 0x04, -1, 0x03, 0x0242, 0x0036}, + {0x0a, 0x01, -1, 0x03, 0x0442, 0x000a}, + {0x0a, 0x01, -1, 0x03, 0x0442, 0x000c}, + {0x0a, 0x02, -1, 0x03, 0x0442, 0x000e}, + {0x0a, 0x02, -1, 0x03, 0x0442, 0x0012}, + {0x0a, 0x03, -1, 0x03, 0x0442, 0x0016}, + {0x0a, 0x03, -1, 0x03, 0x0442, 0x001e}, + {0x0a, 0x04, -1, 0x03, 0x0442, 0x0026}, + {0x0a, 0x04, -1, 0x03, 0x0442, 0x0036}, + {0x0c, 0x01, -1, 0x03, 0x0842, 0x000a}, + {0x0c, 0x01, -1, 0x03, 0x0842, 0x000c}, + {0x0c, 0x02, -1, 0x03, 0x0842, 0x000e}, + {0x0c, 0x02, -1, 0x03, 0x0842, 0x0012}, + {0x0c, 0x03, -1, 0x03, 0x0842, 0x0016}, + {0x0c, 0x03, -1, 0x03, 0x0842, 0x001e}, + {0x0c, 0x04, -1, 0x03, 0x0842, 0x0026}, + {0x0c, 0x04, -1, 0x03, 0x0842, 0x0036}, + {0x0e, 0x01, -1, 0x03, 0x1842, 0x000a}, + {0x0e, 0x01, -1, 0x03, 0x1842, 0x000c}, + {0x0e, 0x02, -1, 0x03, 0x1842, 0x000e}, + {0x0e, 0x02, -1, 0x03, 0x1842, 0x0012}, + {0x0e, 0x03, -1, 0x03, 0x1842, 0x0016}, + {0x0e, 0x03, -1, 0x03, 0x1842, 0x001e}, + {0x0e, 0x04, -1, 0x03, 0x1842, 0x0026}, + {0x0e, 0x04, -1, 0x03, 0x1842, 0x0036}, + {0x18, 0x01, -1, 0x03, 0x5842, 0x000a}, + {0x18, 0x01, -1, 0x03, 0x5842, 0x000c}, + {0x18, 0x02, -1, 0x03, 0x5842, 0x000e}, + {0x18, 0x02, -1, 0x03, 0x5842, 0x0012}, + {0x18, 0x03, -1, 0x03, 0x5842, 0x0016}, + {0x18, 0x03, -1, 0x03, 0x5842, 0x001e}, + {0x18, 0x04, -1, 0x03, 0x5842, 0x0026}, + {0x18, 0x04, -1, 0x03, 0x5842, 0x0036}, + {0x06, 0x05, -1, 0x03, 0x0082, 0x0046}, + {0x06, 0x05, -1, 0x03, 0x0082, 0x0066}, + {0x06, 0x06, -1, 0x03, 0x0082, 0x0086}, + {0x06, 0x07, -1, 0x03, 0x0082, 0x00c6}, + {0x06, 0x08, -1, 0x03, 0x0082, 0x0146}, + {0x06, 0x09, -1, 0x03, 0x0082, 0x0246}, + {0x06, 0x0a, -1, 0x03, 0x0082, 0x0446}, + {0x06, 0x18, -1, 0x03, 0x0082, 0x0846}, + {0x07, 0x05, -1, 0x03, 0x00c2, 0x0046}, + {0x07, 0x05, -1, 0x03, 0x00c2, 0x0066}, + {0x07, 0x06, -1, 0x03, 0x00c2, 0x0086}, + {0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6}, + {0x07, 0x08, -1, 0x03, 0x00c2, 0x0146}, + {0x07, 0x09, -1, 0x03, 0x00c2, 0x0246}, + {0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446}, + {0x07, 0x18, -1, 0x03, 0x00c2, 0x0846}, + {0x08, 0x05, -1, 0x03, 0x0142, 0x0046}, + {0x08, 0x05, -1, 0x03, 0x0142, 0x0066}, + {0x08, 0x06, -1, 0x03, 0x0142, 0x0086}, + {0x08, 0x07, -1, 0x03, 0x0142, 0x00c6}, + {0x08, 0x08, -1, 0x03, 0x0142, 0x0146}, + {0x08, 0x09, -1, 0x03, 0x0142, 0x0246}, + {0x08, 0x0a, -1, 0x03, 0x0142, 0x0446}, + {0x08, 0x18, -1, 0x03, 0x0142, 0x0846}, + {0x09, 0x05, -1, 0x03, 0x0242, 0x0046}, + {0x09, 0x05, -1, 0x03, 0x0242, 0x0066}, + {0x09, 0x06, -1, 0x03, 0x0242, 0x0086}, + {0x09, 0x07, -1, 0x03, 0x0242, 0x00c6}, + {0x09, 0x08, -1, 0x03, 0x0242, 0x0146}, + {0x09, 0x09, -1, 0x03, 0x0242, 0x0246}, + {0x09, 0x0a, -1, 0x03, 0x0242, 0x0446}, + {0x09, 0x18, -1, 0x03, 0x0242, 0x0846}, + {0x0a, 0x05, -1, 0x03, 0x0442, 0x0046}, + {0x0a, 0x05, -1, 0x03, 0x0442, 0x0066}, + {0x0a, 0x06, -1, 0x03, 0x0442, 0x0086}, + {0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6}, + {0x0a, 0x08, -1, 0x03, 0x0442, 0x0146}, + {0x0a, 0x09, -1, 0x03, 0x0442, 0x0246}, + {0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446}, + {0x0a, 0x18, -1, 0x03, 0x0442, 0x0846}, + {0x0c, 0x05, -1, 0x03, 0x0842, 0x0046}, + {0x0c, 0x05, -1, 0x03, 0x0842, 0x0066}, + {0x0c, 0x06, -1, 0x03, 0x0842, 0x0086}, + {0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6}, + {0x0c, 0x08, -1, 0x03, 0x0842, 0x0146}, + {0x0c, 0x09, -1, 0x03, 0x0842, 0x0246}, + {0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446}, + {0x0c, 0x18, -1, 0x03, 0x0842, 0x0846}, + {0x0e, 0x05, -1, 0x03, 0x1842, 0x0046}, + {0x0e, 0x05, -1, 0x03, 0x1842, 0x0066}, + {0x0e, 0x06, -1, 0x03, 0x1842, 0x0086}, + {0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6}, + {0x0e, 0x08, -1, 0x03, 0x1842, 0x0146}, + {0x0e, 0x09, -1, 0x03, 0x1842, 0x0246}, + {0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446}, + {0x0e, 0x18, -1, 0x03, 0x1842, 0x0846}, + {0x18, 0x05, -1, 0x03, 0x5842, 0x0046}, + {0x18, 0x05, -1, 0x03, 0x5842, 0x0066}, + {0x18, 0x06, -1, 0x03, 0x5842, 0x0086}, + {0x18, 0x07, -1, 0x03, 0x5842, 0x00c6}, + {0x18, 0x08, -1, 0x03, 0x5842, 0x0146}, + {0x18, 0x09, -1, 0x03, 0x5842, 0x0246}, + {0x18, 0x0a, -1, 0x03, 0x5842, 0x0446}, + {0x18, 0x18, -1, 0x03, 0x5842, 0x0846}, +} + +// CmdLutElement maps a command symbol to its insert/copy length parameters +// and distance context. +type CmdLutElement struct { + InsertLenExtraBits uint8 + CopyLenExtraBits uint8 + DistanceCode int8 + Context uint8 + InsertLenOffset uint16 + CopyLenOffset uint16 +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/internal/core/constants.go b/src/vendor/github.com/molecule-man/go-brrr/internal/core/constants.go new file mode 100644 index 00000000..1b53c09a --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/internal/core/constants.go @@ -0,0 +1,63 @@ +package core + +// Alphabet sizes from the brotli specification. +// https://datatracker.ietf.org/doc/html/rfc7932#section-3.3 +const ( + AlphabetSizeLiteral = 256 + AlphabetSizeInsertAndCopyLength = 704 + AlphabetSizeBlockCount = 26 + + // NumDistanceShortCodes is the number of distance short codes that reference + // the ring buffer of recent distances (RFC 7932 Section 4). + NumDistanceShortCodes = 16 + + // AlphabetSizeCodeLengths is the size of the code length alphabet + // (RFC 7932 Section 3.5): 18 = 16 literal lengths + repeat-previous (16) + // + repeat-zero (17). + AlphabetSizeCodeLengths = 18 + + // NumHistogramDistanceSymbols is the fixed histogram bin count used for + // distance histograms in the block splitter and histogram clustering. + // Matches BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS in the C reference. + NumHistogramDistanceSymbols = 544 + + // MaxDistanceBits is the maximum number of extra bits in a distance code + // (RFC 7932 Section 4). The distance alphabet size formula uses this as + // the MAXNBITS parameter. + MaxDistanceBits = 24 + + // WindowGap is the safety margin between the window size and the maximum + // backward distance. Reserves space for ring-buffer read-ahead in the + // streaming encoder. + WindowGap = 16 + + // RepeatPreviousCodeLength and InitialRepeatedCodeLength are entropy + // coding constants from RFC 7932 Section 3.5. + // https://datatracker.ietf.org/doc/html/rfc7932#section-3.5 + RepeatPreviousCodeLength = 16 // used for repeating previous non-zero code length + InitialRepeatedCodeLength = 8 // "code length of 8 is repeated" +) + +// CodeLengthCodeOrder is the order in which code length codes are transmitted +// (RFC 7932 section 3.5). +var CodeLengthCodeOrder = [...]byte{ + 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15, +} + +// BlockLengthOffset and BlockLengthNBits are block length prefix code ranges +// (RFC 7932 Section 6). Each entry is {offset, nbits}; the block length for +// code c is: +// +// offset[c] + ReadBits(nbits[c]) +var BlockLengthOffset = [AlphabetSizeBlockCount]uint32{ + 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, + 113, 145, 177, 209, 241, 305, 369, 497, 753, 1265, 2289, 4337, + 8433, 16625, +} + +// BlockLengthNBits is the extra-bit count for each block-length prefix code. +var BlockLengthNBits = [AlphabetSizeBlockCount]uint32{ + 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, + 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, + 13, 24, +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/internal/core/context.go b/src/vendor/github.com/molecule-man/go-brrr/internal/core/context.go new file mode 100644 index 00000000..b61753ac --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/internal/core/context.go @@ -0,0 +1,202 @@ +// Context modeling lookup tables for literal encoding (quality >= 5). +// +// Brotli uses four context modes to predict the next literal byte based on +// the two preceding bytes (p1, p2). The context ID feeds into the context +// map, which selects a Huffman tree for coding the next byte. +// +// The four modes are: +// +// - contextLSB6: context is the low 6 bits of p1 (p2 ignored). +// - contextMSB6: context is the high 6 bits of p1 (p2 ignored). +// - contextUTF8: second-order model tuned for UTF-8 text. For ASCII +// bytes the context encodes character class of p1 (16 classes) and +// broad class of p2 (4 classes), giving 64 contexts. For multi-byte +// sequences it distinguishes continuation vs. lead bytes. +// - contextSigned: second-order model tuned for signed integer data. +// Similar to MSB6 but with 8 buckets for p1 and 8 for p2. +// +// The context is computed as: +// +// context = contextLookupTable[mode<<9 + p1] | contextLookupTable[mode<<9 + 256 + p2] +// +// Each mode occupies 512 bytes in the table: 256 for the p1 contribution +// and 256 for the p2 contribution. The result is a 6-bit context ID (0..63). +// +// RFC 7932 Section 7.1. + +package core + +// Context mode constants. Each selects a 512-byte region of the lookup table. +const ( + ContextLSB6 = 0 + ContextMSB6 = 1 + ContextUTF8 = 2 + ContextSigned = 3 +) + +// Context bit widths for the two symbol categories that use context modeling. +const ( + LiteralContextBits = 6 // 64 literal contexts per block type + DistanceContextBits = 2 // 4 distance contexts per block type +) + +// ContextLookupTable maps (mode, p1, p2) triples to 6-bit context IDs. +// Layout: 4 modes x 512 bytes (256 for p1, 256 for p2). +var ContextLookupTable = [2048]byte{ + // contextLSB6, p1: identity mapping of low 6 bits. + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + + // contextLSB6, p2: all zeros (p2 doesn't contribute). + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + // contextMSB6, p1: high 6 bits (value >> 2). + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, + 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, + 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, + 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, + 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, + 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35, + 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, + 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, + 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, + 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, + 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, + 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59, + 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63, + + // contextMSB6, p2: all zeros (p2 doesn't contribute). + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + // contextUTF8, p1. + // ASCII range: 16 character classes mapped to context * 4. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12, + 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12, + 12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48, + 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12, + 12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56, + 60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0, + // Continuation byte range (128-191): alternating 0,1. + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, + // Lead byte range (192-255): alternating 2,3. + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + + // contextUTF8, p2. + // ASCII range: 4 broad classes (control/space=0, punct=1, upper/digit=2, lower=3). + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0, + // Continuation byte range (128-191): all zeros. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // Lead byte range (192-255): 0 for 192-207, 2 for 208-255. + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + + // contextSigned, p1: signed magnitude buckets (8 ranges * 8). + 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56, + + // contextSigned, p2: signed magnitude buckets (8 ranges). + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, +} + +// ContextLookup computes a 6-bit context ID from the two preceding bytes +// p1 (last) and p2 (second-to-last) for the given context mode. +func ContextLookup(mode uint, p1, p2 byte) byte { + lut := ContextLookupTable[mode<<9:] + return lut[p1] | lut[256+int(p2)] +} diff --git a/src/vendor/github.com/molecule-man/go-brrr/internal/core/dictionary.bin b/src/vendor/github.com/molecule-man/go-brrr/internal/core/dictionary.bin new file mode 100644 index 00000000..a585c0e2 --- /dev/null +++ b/src/vendor/github.com/molecule-man/go-brrr/internal/core/dictionary.bin @@ -0,0 +1,432 @@ +timedownlifeleftbackcodedatashowonlysitecityopenjustlikefreeworktextyearoverbodyloveformbookplaylivelinehelphomesidemorewordlongthemviewfindpagedaysfullheadtermeachareafromtruemarkableuponhighdatelandnewsevennextcasebothpostusedmadehandherewhatnameLinkblogsizebaseheldmakemainuser') +holdendswithNewsreadweresigntakehavegameseencallpathwellplusmenufilmpartjointhislistgoodneedwayswestjobsmindalsologorichuseslastteamarmyfoodkingwilleastwardbestfirePageknowaway.pngmovethanloadgiveselfnotemuchfeedmanyrockicononcelookhidediedHomerulehostajaxinfoclublawslesshalfsomesuchzone100%onescareTimeracebluefourweekfacehopegavehardlostwhenparkkeptpassshiproomHTMLplanTypedonesavekeepflaglinksoldfivetookratetownjumpthusdarkcardfilefearstaykillthatfallautoever.comtalkshopvotedeepmoderestturnbornbandfellroseurl(skinrolecomeactsagesmeetgold.jpgitemvaryfeltthensenddropViewcopy1.0"stopelseliestourpack.gifpastcss?graymean>rideshotlatesaidroadvar feeljohnrickportfast'UA-deadpoorbilltypeU.S.woodmust2px;Inforankwidewantwalllead[0];paulwavesure$('#waitmassarmsgoesgainlangpaid!-- lockunitrootwalkfirmwifexml"songtest20pxkindrowstoolfontmailsafestarmapscorerainflowbabyspansays4px;6px;artsfootrealwikiheatsteptriporg/lakeweaktoldFormcastfansbankveryrunsjulytask1px;goalgrewslowedgeid="sets5px;.js?40pxif (soonseatnonetubezerosentreedfactintogiftharm18pxcamehillboldzoomvoideasyringfillpeakinitcost3px;jacktagsbitsrolleditknewnearironfreddiskwentsoilputs/js/holyT22:ISBNT20:adamsees

json', 'contT21: RSSloopasiamoon

soulLINEfortcartT14:

80px!--<9px;T04:mike:46ZniceinchYorkricezh:ä'));puremageparatonebond:37Z_of_']);000,zh:çtankyardbowlbush:56ZJava30px +|} +%C3%:34ZjeffEXPIcashvisagolfsnowzh:équer.csssickmeatmin.binddellhirepicsrent:36ZHTTP-201fotowolfEND xbox:54ZBODYdick; +} +exit:35Zvarsbeat'});diet999;anne}}sonyguysfuckpipe|- +!002)ndow[1];[]; +Log salt + bangtrimbath){ +00px +});ko:ìfeesad> s:// [];tollplug(){ +{ + .js'200pdualboat.JPG); +}quot); + +'); + +} 201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037201320122011201020092008200720062005200420032002200120001999199819971996199519941993199219911990198919881987198619851984198319821981198019791978197719761975197419731972197119701969196819671966196519641963196219611960195919581957195619551954195319521951195010001024139400009999comomásesteestaperotodohacecadaañobiendíaasívidacasootroforosolootracualdijosidograntipotemadebealgoquéestonadatrespococasabajotodasinoaguapuesunosantediceluisellamayozonaamorpisoobraclicellodioshoracasiзанаомрарутанепоотизнодотожеонихНаеебымыВысовывоНообПолиниРФНеМытыОнимдаЗаДаНуОбтеИзейнуммТыужفيأنمامعكلأورديافىهولملكاولهبسالإنهيأيقدهلثمبهلوليبلايبكشيامأمنتبيلنحبهممشوشfirstvideolightworldmediawhitecloseblackrightsmallbooksplacemusicfieldorderpointvalueleveltableboardhousegroupworksyearsstatetodaywaterstartstyledeathpowerphonenighterrorinputabouttermstitletoolseventlocaltimeslargewordsgamesshortspacefocusclearmodelblockguideradiosharewomenagainmoneyimagenamesyounglineslatercolorgreenfront&watchforcepricerulesbeginaftervisitissueareasbelowindextotalhourslabelprintpressbuiltlinksspeedstudytradefoundsenseundershownformsrangeaddedstillmovedtakenaboveflashfixedoftenotherviewschecklegalriveritemsquickshapehumanexistgoingmoviethirdbasicpeacestagewidthloginideaswrotepagesusersdrivestorebreaksouthvoicesitesmonthwherebuildwhichearthforumthreesportpartyClicklowerlivesclasslayerentrystoryusagesoundcourtyour birthpopuptypesapplyImagebeinguppernoteseveryshowsmeansextramatchtrackknownearlybegansuperpapernorthlearngivennamedendedTermspartsGroupbrandusingwomanfalsereadyaudiotakeswhile.com/livedcasesdailychildgreatjudgethoseunitsneverbroadcoastcoverapplefilescyclesceneplansclickwritequeenpieceemailframeolderphotolimitcachecivilscaleenterthemetheretouchboundroyalaskedwholesincestock namefaithheartemptyofferscopeownedmightalbumthinkbloodarraymajortrustcanonunioncountvalidstoneStyleLoginhappyoccurleft:freshquitefilmsgradeneedsurbanfightbasishoverauto;route.htmlmixedfinalYour slidetopicbrownalonedrawnsplitreachRightdatesmarchquotegoodsLinksdoubtasyncthumballowchiefyouthnovel10px;serveuntilhandsCheckSpacequeryjamesequaltwice0,000Startpanelsongsroundeightshiftworthpostsleadsweeksavoidthesemilesplanesmartalphaplantmarksratesplaysclaimsalestextsstarswrong

thing.org/multiheardPowerstandtokensolid(thisbringshipsstafftriedcallsfullyfactsagentThis //-->adminegyptEvent15px;Emailtrue"crossspentblogsbox">notedleavechinasizesguestrobotheavytrue,sevengrandcrimesignsawaredancephase> + + +name=diegopage swiss--> + +#fff;">Log.com"treatsheet) && 14px;sleepntentfiledja:ãƒid="cName"worseshots-box-delta +<bears:48Z spendbakershops= "";php">ction13px;brianhellosize=o=%2F joinmaybe, fjsimg" ")[0]MTopBType"newlyDanskczechtrailknowsfaq">zh-cn10); +-1");type=bluestrulydavis.js';> + +form jesus100% menu. + +walesrisksumentddingb-likteachgif" vegasdanskeestishqipsuomisobredesdeentretodospuedeañosestátienehastaotrospartedondenuevohacerformamismomejormundoaquídíassóloayudafechatodastantomenosdatosotrassitiomuchoahoralugarmayorestoshorastenerantesfotosestaspaísnuevasaludforosmedioquienmesespoderchileserávecesdecirjoséestarventagrupohechoellostengoamigocosasnivelgentemismaairesjuliotemashaciafavorjuniolibrepuntobuenoautorabrilbuenatextomarzosaberlistaluegocómoenerojuegoperúhaberestoynuncamujervalorfueralibrogustaigualvotoscasosguíapuedosomosavisousteddebennochebuscafaltaeurosseriedichocursoclavecasasleónplazolargoobrasvistaapoyojuntotratavistocrearcampohemoscincocargopisosordenhacenáreadiscopedrocercapuedapapelmenorútilclarojorgecalleponertardenadiemarcasigueellassiglocochemotosmadreclaserestoniñoquedapasarbancohijosviajepabloéstevienereinodejarfondocanalnorteletracausatomarmanoslunesautosvillavendopesartipostengamarcollevapadreunidovamoszonasambosbandamariaabusomuchasubirriojavivirgradochicaallíjovendichaestantalessalirsuelopesosfinesllamabuscoéstalleganegroplazahumorpagarjuntadobleislasbolsabañohablaluchaÁreadicenjugarnotasvalleallácargadolorabajoestégustomentemariofirmacostofichaplatahogarartesleyesaquelmuseobasespocosmitadcielochicomiedoganarsantoetapadebesplayaredessietecortecoreadudasdeseoviejodeseaaguas"domaincommonstatuseventsmastersystemactionbannerremovescrollupdateglobalmediumfilternumberchangeresultpublicscreenchoosenormaltravelissuessourcetargetspringmodulemobileswitchphotosborderregionitselfsocialactivecolumnrecordfollowtitle>eitherlengthfamilyfriendlayoutauthorcreatereviewsummerserverplayedplayerexpandpolicyformatdoublepointsseriespersonlivingdesignmonthsforcesuniqueweightpeopleenergynaturesearchfigurehavingcustomoffsetletterwindowsubmitrendergroupsuploadhealthmethodvideosschoolfutureshadowdebatevaluesObjectothersrightsleaguechromesimplenoticesharedendingseasonreportonlinesquarebuttonimagesenablemovinglatestwinterFranceperiodstrongrepeatLondondetailformeddemandsecurepassedtoggleplacesdevicestaticcitiesstreamyellowattackstreetflighthiddeninfo">openedusefulvalleycausesleadersecretseconddamagesportsexceptratingsignedthingseffectfieldsstatesofficevisualeditorvolumeReportmuseummoviesparentaccessmostlymother" id="marketgroundchancesurveybeforesymbolmomentspeechmotioninsidematterCenterobjectexistsmiddleEuropegrowthlegacymannerenoughcareeransweroriginportalclientselectrandomclosedtopicscomingfatheroptionsimplyraisedescapechosenchurchdefinereasoncorneroutputmemoryiframepolicemodelsNumberduringoffersstyleskilledlistedcalledsilvermargindeletebetterbrowselimitsGlobalsinglewidgetcenterbudgetnowrapcreditclaimsenginesafetychoicespirit-stylespreadmakingneededrussiapleaseextentScriptbrokenallowschargedividefactormember-basedtheoryconfigaroundworkedhelpedChurchimpactshouldalwayslogo" bottomlist">){var prefixorangeHeader.push(couplegardenbridgelaunchReviewtakingvisionlittledatingButtonbeautythemesforgotSearchanchoralmostloadedChangereturnstringreloadMobileincomesupplySourceordersviewed courseAbout islandPhilipawardshandleimportOfficeregardskillsnationSportsdegreeweekly (e.g.behinddoctorloggedunitedbeyond-scaleacceptservedmarineFootercamera +_form"leavesstress" /> +.gif" onloadloaderOxfordsistersurvivlistenfemaleDesignsize="appealtext">levelsthankshigherforcedanimalanyoneAfricaagreedrecentPeople
wonderpricesturned|| {};main">inlinesundaywrap">failedcensusminutebeaconquotes150px|estateremoteemail"linkedright;signalformal1.htmlsignupprincefloat:.png" forum.AccesspaperssoundsextendHeightsliderUTF-8"& Before. WithstudioownersmanageprofitjQueryannualparamsboughtfamousgooglelongeri++) {israelsayingdecidehome">headerensurebranchpiecesblock;statedtop">boston.test(avatartested_countforumsschemaindex,filledsharesreaderalert(appearSubmitline">body"> +* TheThoughseeingjerseyNews +System DavidcancertablesprovedApril reallydriveritem">more">boardscolorscampusfirst || [];media.guitarfinishwidth:showedOther .php" assumelayerswilsonstoresreliefswedenCustomeasily your String + +Whiltaylorclear:resortfrenchthough") + "buyingbrandsMembername">oppingsector5px;">vspacepostermajor coffeemartinmaturehappenkansaslink">Images=falsewhile hspace0& + +In powerPolski-colorjordanBottomStart -count2.htmlnews">01.jpgOnline-rightmillerseniorISBN 00,000 guidesvalue)ectionrepair.xml" rights.html-blockregExp:hoverwithinvirginphones using + var >'); + + +bahasabrasilgalegomagyarpolskisrpskiردو中文简体繁體信息中国我们一个公司管理论坛可以服务时间个人产品自己企业查看工作联系没有网站所有评论中心文章用户首页作者技术问题相关下载搜索使用软件在线主题资料视频回复注册网络收藏内容推荐市场消息空间发布什么好友生活图片发展如果手机新闻最新方式北京提供关于更多这个系统知道游戏广告其他发表安全第一会员进行点击版权电子世界设计免费教育加入活动他们商品博客现在上海如何已经留言详细社区登录本站需要价格支持国际链接国家建设朋友阅读法律位置经济选择这样当前分类排行因为交易最后音乐不能通过行业科技可能设备合作大家社会研究专业全部项目这里还是开始情况电脑文件品牌帮助文化资源大学学习地址浏览投资工程要求怎么时候功能主要目前资讯城市方法电影招聘声明任何健康数据美国汽车介绍但是交流生产所以电话显示一些单位人员分析地图旅游工具学生系列网友帖子密码频道控制地区基本全国网上重要第二喜欢进入友情这些考试发现培训以上政府成为环境香港同时娱乐发送一定开发作品标准欢迎解决地方一下以及责任或者客户代表积分女人数码销售出现离线应用列表不同编辑统计查询不要有关机构很多播放组织政策直接能力来源時間看到热门关键专区非常英语百度希望美女比较知识规定建议部门意见精彩日本提高发言方面基金处理权限影片银行还有分享物品经营添加专家这种话题起来业务公告记录简介质量男人影响引用报告部分快速咨询时尚注意申请学校应该历史只是返回购买名称为了成功说明供应孩子专题程序一般會員只有其它保护而且今天窗口动态状态特别认为必须更新小说我們作为媒体包括那么一样国内是否根据电视学院具有过程由于人才出来不过正在明星故事关系标题商务输入一直基础教学了解建筑结果全球通知计划对于艺术相册发生真的建立等级类型经验实现制作来自标签以下原创无法其中個人一切指南关闭集团第三关注因此照片深圳商业广州日期高级最近综合表示专辑行为交通评价觉得精华家庭完成感觉安装得到邮件制度食品虽然转载报价记者方案行政人民用品东西提出酒店然后付款热点以前完全发帖设置领导工业医院看看经典原因平台各种增加材料新增之后职业效果今年论文我国告诉版主修改参与打印快乐机械观点存在精神获得利用继续你们这么模式语言能够雅虎操作风格一起科学体育短信条件治疗运动产业会议导航先生联盟可是問題结构作用调查資料自动负责农业访问实施接受讨论那个反馈加强女性范围服務休闲今日客服觀看参加的话一点保证图书有效测试移动才能决定股票不断需求不得办法之间采用营销投诉目标爱情摄影有些複製文学机会数字装修购物农村全面精品其实事情水平提示上市谢谢普通教师上传类别歌曲拥有创新配件只要时代資訊达到人生订阅老师展示心理贴子網站主題自然级别简单改革那些来说打开代码删除证券节目重点次數多少规划资金找到以后大全主页最佳回答天下保障现代检查投票小时沒有正常甚至代理目录公开复制金融幸福版本形成准备行情回到思想怎样协议认证最好产生按照服装广东动漫采购新手组图面板参考政治容易天地努力人们升级速度人物调整流行造成文字韩国贸易开展相關表现影视如此美容大小报道条款心情许多法规家居书店连接立即举报技巧奥运登入以来理论事件自由中华办公妈妈真正不错全文合同价值别人监督具体世纪团队创业承担增长有人保持商家维修台湾左右股份答案实际电信经理生命宣传任务正式特色下来协会只能当然重新內容指导运行日志賣家超过土地浙江支付推出站长杭州执行制造之一推广现场描述变化传统歌手保险课程医疗经过过去之前收入年度杂志美丽最高登陆未来加工免责教程版块身体重庆出售成本形式土豆出價东方邮箱南京求职取得职位相信页面分钟网页确定图例网址积极错误目的宝贝机关风险授权病毒宠物除了評論疾病及时求购站点儿童每天中央认识每个天津字体台灣维护本页个性官方常见相机战略应当律师方便校园股市房屋栏目员工导致突然道具本网结合档案劳动另外美元引起改变第四会计說明隐私宝宝规范消费共同忘记体系带来名字發表开放加盟受到二手大量成人数量共享区域女孩原则所在结束通信超级配置当时优秀性感房产遊戲出口提交就业保健程度参数事业整个山东情感特殊分類搜尋属于门户财务声音及其财经坚持干部成立利益考虑成都包装用戶比赛文明招商完整真是眼睛伙伴威望领域卫生优惠論壇公共良好充分符合附件特点不可英文资产根本明显密碼公众民族更加享受同学启动适合原来问答本文美食绿色稳定终于生物供求搜狐力量严重永远写真有限竞争对象费用不好绝对十分促进点评影音优势不少欣赏并且有点方向全新信用设施形象资格突破随着重大于是毕业智能化工完美商城统一出版打造產品概况用于保留因素中國存储贴图最愛长期口价理财基地安排武汉里面创建天空首先完善驱动下面不再诚信意义阳光英国漂亮军事玩家群众农民即可名稱家具动画想到注明小学性能考研硬件观看清楚搞笑首頁黄金适用江苏真实主管阶段註冊翻译权利做好似乎通讯施工狀態也许环保培养概念大型机票理解匿名cuandoenviarmadridbuscariniciotiempoporquecuentaestadopuedenjuegoscontraestánnombretienenperfilmaneraamigosciudadcentroaunquepuedesdentroprimerpreciosegúnbuenosvolverpuntossemanahabíaagostonuevosunidoscarlosequiponiñosmuchosalgunacorreoimagenpartirarribamaríahombreempleoverdadcambiomuchasfueronpasadolíneaparecenuevascursosestabaquierolibroscuantoaccesomiguelvarioscuatrotienesgruposseráneuropamediosfrenteacercademásofertacochesmodeloitalialetrasalgúncompracualesexistecuerposiendoprensallegarviajesdineromurciapodrápuestodiariopuebloquieremanuelpropiocrisisciertoseguromuertefuentecerrargrandeefectopartesmedidapropiaofrecetierrae-mailvariasformasfuturoobjetoseguirriesgonormasmismosúnicocaminositiosrazóndebidopruebatoledoteníajesúsesperococinaorigentiendacientocádizhablarseríalatinafuerzaestiloguerraentraréxitolópezagendavídeoevitarpaginametrosjavierpadresfácilcabezaáreassalidaenvíojapónabusosbienestextosllevarpuedanfuertecomúnclaseshumanotenidobilbaounidadestáseditarcreadoдлячтокакилиэтовсеегопритакещеужеКакбезбылониВсеподЭтотомчемнетлетразонагдемнеДляПринаснихтемктогодвоттамСШАмаяЧтовасвамемуТакдванамэтиэтуВамтехпротутнаддняВоттринейВаснимсамтотрубОнимирнееОООлицэтаОнанемдоммойдвеоносудकेहैकीसेकाकोऔरपरनेएककिभीइसकरतोहोआपहीयहयातकथाjagranआजजोअबदोगईजागएहमइनवहयेथेथीघरजबदीकईजीवेनईनएहरउसमेकमवोलेसबमईदेओरआमबसभरबनचलमनआगसीलीعلىإلىهذاآخرعددالىهذهصورغيركانولابينعرضذلكهنايومقالعليانالكنحتىقبلوحةاخرفقطعبدركنإذاكمااحدإلافيهبعضكيفبحثومنوهوأناجدالهاسلمعندليسعبرصلىمنذبهاأنهمثلكنتالاحيثمصرشرححولوفياذالكلمرةانتالفأبوخاصأنتانهاليعضووقدابنخيربنتلكمشاءوهيابوقصصومارقمأحدنحنعدمرأياحةكتبدونيجبمنهتحتجهةسنةيتمكرةغزةنفسبيتللهلناتلكقلبلماعنهأولشيءنورأمافيكبكلذاترتببأنهمسانكبيعفقدحسنلهمشعرأهلشهرقطرطلبprofileservicedefaulthimselfdetailscontentsupportstartedmessagesuccessfashioncountryaccountcreatedstoriesresultsrunningprocesswritingobjectsvisiblewelcomearticleunknownnetworkcompanydynamicbrowserprivacyproblemServicerespectdisplayrequestreservewebsitehistoryfriendsoptionsworkingversionmillionchannelwindow.addressvisitedweathercorrectproductedirectforwardyou canremovedsubjectcontrolarchivecurrentreadinglibrarylimitedmanagerfurthersummarymachineminutesprivatecontextprogramsocietynumberswrittenenabledtriggersourcesloadingelementpartnerfinallyperfectmeaningsystemskeepingculture",journalprojectsurfaces"expiresreviewsbalanceEnglishContentthroughPlease opinioncontactaverageprimaryvillageSpanishgallerydeclinemeetingmissionpopularqualitymeasuregeneralspeciessessionsectionwriterscounterinitialreportsfiguresmembersholdingdisputeearlierexpressdigitalpictureAnothermarriedtrafficleadingchangedcentralvictoryimages/reasonsstudiesfeaturelistingmust beschoolsVersionusuallyepisodeplayinggrowingobviousoverlaypresentactions</ul> +wrapperalreadycertainrealitystorageanotherdesktopofferedpatternunusualDigitalcapitalWebsitefailureconnectreducedAndroiddecadesregular & animalsreleaseAutomatgettingmethodsnothingPopularcaptionletterscapturesciencelicensechangesEngland=1&History = new CentralupdatedSpecialNetworkrequirecommentwarningCollegetoolbarremainsbecauseelectedDeutschfinanceworkersquicklybetweenexactlysettingdiseaseSocietyweaponsexhibit<!--Controlclassescoveredoutlineattacksdevices(windowpurposetitle="Mobile killingshowingItaliandroppedheavilyeffects-1']); +confirmCurrentadvancesharingopeningdrawingbillionorderedGermanyrelated</form>includewhetherdefinedSciencecatalogArticlebuttonslargestuniformjourneysidebarChicagoholidayGeneralpassage,"animatefeelingarrivedpassingnaturalroughly. + +The but notdensityBritainChineselack oftributeIreland" data-factorsreceivethat isLibraryhusbandin factaffairsCharlesradicalbroughtfindinglanding:lang="return leadersplannedpremiumpackageAmericaEdition]"Messageneed tovalue="complexlookingstationbelievesmaller-mobilerecordswant tokind ofFirefoxyou aresimilarstudiedmaximumheadingrapidlyclimatekingdomemergedamountsfoundedpioneerformuladynastyhow to SupportrevenueeconomyResultsbrothersoldierlargelycalling."AccountEdward segmentRobert effortsPacificlearnedup withheight:we haveAngelesnations_searchappliedacquiremassivegranted: falsetreatedbiggestbenefitdrivingStudiesminimumperhapsmorningsellingis usedreversevariant role="missingachievepromotestudentsomeoneextremerestorebottom:evolvedall thesitemapenglishway to AugustsymbolsCompanymattersmusicalagainstserving})(); +paymenttroubleconceptcompareparentsplayersregionsmonitor ''The winningexploreadaptedGalleryproduceabilityenhancecareers). The collectSearch ancientexistedfooter handlerprintedconsoleEasternexportswindowsChannelillegalneutralsuggest_headersigning.html">settledwesterncausing-webkitclaimedJusticechaptervictimsThomas mozillapromisepartieseditionoutside:false,hundredOlympic_buttonauthorsreachedchronicdemandssecondsprotectadoptedprepareneithergreatlygreateroverallimprovecommandspecialsearch.worshipfundingthoughthighestinsteadutilityquarterCulturetestingclearlyexposedBrowserliberal} catchProjectexamplehide();FloridaanswersallowedEmperordefenseseriousfreedomSeveral-buttonFurtherout of != nulltrainedDenmarkvoid(0)/all.jspreventRequestStephen + +When observe</h2> +Modern provide" alt="borders. + +For + +Many artistspoweredperformfictiontype ofmedicalticketsopposedCouncilwitnessjusticeGeorge Belgium...</a>twitternotablywaitingwarfare Other rankingphrasesmentionsurvivescholar</p> + Countryignoredloss ofjust asGeorgiastrange<head><stopped1']); +islandsnotableborder:list ofcarried100,000</h3> + severalbecomesselect wedding00.htmlmonarchoff theteacherhighly biologylife ofor evenrise of»plusonehunting(thoughDouglasjoiningcirclesFor theAncientVietnamvehiclesuch ascrystalvalue =Windowsenjoyeda smallassumed<a id="foreign All rihow theDisplayretiredhoweverhidden;battlesseekingcabinetwas notlook atconductget theJanuaryhappensturninga:hoverOnline French lackingtypicalextractenemieseven ifgeneratdecidedare not/searchbeliefs-image:locatedstatic.login">convertviolententeredfirst">circuitFinlandchemistshe was10px;">as suchdivided</span>will beline ofa greatmystery/index.fallingdue to railwaycollegemonsterdescentit withnuclearJewish protestBritishflowerspredictreformsbutton who waslectureinstantsuicidegenericperiodsmarketsSocial fishingcombinegraphicwinners<br /><by the NaturalPrivacycookiesoutcomeresolveSwedishbrieflyPersianso muchCenturydepictscolumnshousingscriptsnext tobearingmappingrevisedjQuery(-width:title">tooltipSectiondesignsTurkishyounger.match(})(); + +burningoperatedegreessource=Richardcloselyplasticentries</tr> +color:#ul id="possessrollingphysicsfailingexecutecontestlink toDefault<br /> +: true,chartertourismclassicproceedexplain</h1> +online.?xml vehelpingdiamonduse theairlineend -->).attr(readershosting#ffffffrealizeVincentsignals src="/ProductdespitediversetellingPublic held inJoseph theatreaffects<style>a largedoesn'tlater, ElementfaviconcreatorHungaryAirportsee theso thatMichaelSystemsPrograms, and width=e"tradingleft"> +personsGolden Affairsgrammarformingdestroyidea ofcase ofoldest this is.src = cartoonregistrCommonsMuslimsWhat isin manymarkingrevealsIndeed,equally/show_aoutdoorescape(Austriageneticsystem,In the sittingHe alsoIslandsAcademy + <!--Daniel bindingblock">imposedutilizeAbraham(except{width:putting).html(|| []; +DATA[ *kitchenmountedactual dialectmainly _blank'installexpertsif(typeIt also© ">Termsborn inOptionseasterntalkingconcerngained ongoingjustifycriticsfactoryits ownassaultinvitedlastinghis ownhref="/" rel="developconcertdiagramdollarsclusterphp?id=alcohol);})();using a><span>vesselsrevivalAddressamateurandroidallegedillnesswalkingcentersqualifymatchesunifiedextinctDefensedied in + <!-- customslinkingLittle Book ofeveningmin.js?are thekontakttoday's.html" target=wearingAll Rig; +})();raising Also, crucialabout">declare--> +<scfirefoxas muchappliesindex, s, but type = + +<!--towardsRecordsPrivateForeignPremierchoicesVirtualreturnsCommentPoweredinline;povertychamberLiving volumesAnthonylogin" RelatedEconomyreachescuttinggravitylife inChapter-shadowNotable</td> + returnstadiumwidgetsvaryingtravelsheld bywho arework infacultyangularwho hadairporttown of + +Some 'click'chargeskeywordit willcity of(this);Andrew unique checkedor more300px; return;rsion="pluginswithin herselfStationFederalventurepublishsent totensionactresscome tofingersDuke ofpeople,exploitwhat isharmonya major":"httpin his menu"> +monthlyofficercouncilgainingeven inSummarydate ofloyaltyfitnessand wasemperorsupremeSecond hearingRussianlongestAlbertalateralset of small">.appenddo withfederalbank ofbeneathDespiteCapitalgrounds), and percentit fromclosingcontainInsteadfifteenas well.yahoo.respondfighterobscurereflectorganic= Math.editingonline paddinga wholeonerroryear ofend of barrierwhen itheader home ofresumedrenamedstrong>heatingretainscloudfrway of March 1knowingin partBetweenlessonsclosestvirtuallinks">crossedEND -->famous awardedLicenseHealth fairly wealthyminimalAfricancompetelabel">singingfarmersBrasil)discussreplaceGregoryfont copursuedappearsmake uproundedboth ofblockedsaw theofficescoloursif(docuwhen heenforcepush(fuAugust UTF-8">Fantasyin mostinjuredUsuallyfarmingclosureobject defenceuse of Medical<body> +evidentbe usedkeyCodesixteenIslamic#000000entire widely active (typeofone cancolor =speakerextendsPhysicsterrain<tbody>funeralviewingmiddle cricketprophetshifteddoctorsRussell targetcompactalgebrasocial-bulk ofman and</td> + he left).val()false);logicalbankinghome tonaming Arizonacredits); +}); +founderin turnCollinsbefore But thechargedTitle">CaptainspelledgoddessTag -->Adding:but wasRecent patientback in=false&Lincolnwe knowCounterJudaismscript altered']); + has theunclearEvent',both innot all + +<!-- placinghard to centersort ofclientsstreetsBernardassertstend tofantasydown inharbourFreedomjewelry/about..searchlegendsis mademodern only ononly toimage" linear painterand notrarely acronymdelivershorter00&as manywidth="/* <![Ctitle =of the lowest picked escapeduses ofpeoples PublicMatthewtacticsdamagedway forlaws ofeasy to windowstrong simple}catch(seventhinfoboxwent topaintedcitizenI don'tretreat. Some ww."); +bombingmailto:made in. Many carries||{};wiwork ofsynonymdefeatsfavoredopticalpageTraunless sendingleft"><comScorAll thejQuery.touristClassicfalse" Wilhelmsuburbsgenuinebishops.split(global followsbody ofnominalContactsecularleft tochiefly-hidden-banner</li> + +. When in bothdismissExplorealways via thespañolwelfareruling arrangecaptainhis sonrule ofhe tookitself,=0&(calledsamplesto makecom/pagMartin Kennedyacceptsfull ofhandledBesides//--></able totargetsessencehim to its by common.mineralto takeways tos.org/ladvisedpenaltysimple:if theyLettersa shortHerbertstrikes groups.lengthflightsoverlapslowly lesser social </p> + it intoranked rate oful> + attemptpair ofmake itKontaktAntoniohaving ratings activestreamstrapped").css(hostilelead tolittle groups,Picture--> + + rows=" objectinverse<footerCustomV><\/scrsolvingChamberslaverywoundedwhereas!= 'undfor allpartly -right:Arabianbacked centuryunit ofmobile-Europe,is homerisk ofdesiredClintoncost ofage of become none ofp"Middle ead')[0Criticsstudios>©group">assemblmaking pressedwidget.ps:" ? rebuiltby someFormer editorsdelayedCanonichad thepushingclass="but arepartialBabylonbottom carrierCommandits useAs withcoursesa thirddenotesalso inHouston20px;">accuseddouble goal ofFamous ).bind(priests Onlinein Julyst + "gconsultdecimalhelpfulrevivedis veryr'+'iptlosing femalesis alsostringsdays ofarrivalfuture <objectforcingString(" /> + here isencoded. The balloondone by/commonbgcolorlaw of Indianaavoidedbut the2px 3pxjquery.after apolicy.men andfooter-= true;for usescreen.Indian image =family,http://  driverseternalsame asnoticedviewers})(); + is moreseasonsformer the newis justconsent Searchwas thewhy theshippedbr><br>width: height=made ofcuisineis thata very Admiral fixed;normal MissionPress, ontariocharsettry to invaded="true"spacingis mosta more totallyfall of}); + immensetime inset outsatisfyto finddown tolot of Playersin Junequantumnot thetime todistantFinnishsrc = (single help ofGerman law andlabeledforestscookingspace">header-well asStanleybridges/globalCroatia About [0]; + it, andgroupedbeing a){throwhe madelighterethicalFFFFFF"bottom"like a employslive inas seenprintermost ofub-linkrejectsand useimage">succeedfeedingNuclearinformato helpWomen'sNeitherMexicanprotein<table by manyhealthylawsuitdevised.push({sellerssimply Through.cookie Image(older">us.js"> Since universlarger open to!-- endlies in']); + marketwho is ("DOMComanagedone fortypeof Kingdomprofitsproposeto showcenter;made itdressedwere inmixtureprecisearisingsrc = 'make a securedBaptistvoting + var March 2grew upClimate.removeskilledway the</head>face ofacting right">to workreduceshas haderectedshow();action=book ofan area== "htt<header +<html>conformfacing cookie.rely onhosted .customhe wentbut forspread Family a meansout theforums.footage">MobilClements" id="as highintense--><!--female is seenimpliedset thea stateand hisfastestbesidesbutton_bounded"><img Infoboxevents,a youngand areNative cheaperTimeoutand hasengineswon the(mostlyright: find a -bottomPrince area ofmore ofsearch_nature,legallyperiod,land ofor withinducedprovingmissilelocallyAgainstthe wayk"px;"> +pushed abandonnumeralCertainIn thismore inor somename isand, incrownedISBN 0-createsOctobermay notcenter late inDefenceenactedwish tobroadlycoolingonload=it. TherecoverMembersheight assumes<html> +people.in one =windowfooter_a good reklamaothers,to this_cookiepanel">London,definescrushedbaptismcoastalstatus title" move tolost inbetter impliesrivalryservers SystemPerhapses and contendflowinglasted rise inGenesisview ofrising seem tobut in backinghe willgiven agiving cities.flow of Later all butHighwayonly bysign ofhe doesdiffersbattery&lasinglesthreatsintegertake onrefusedcalled =US&See thenativesby thissystem.head of:hover,lesbiansurnameand allcommon/header__paramsHarvard/pixel.removalso longrole ofjointlyskyscraUnicodebr /> +AtlantanucleusCounty,purely count">easily build aonclicka givenpointerh"events else { +ditionsnow the, with man whoorg/Webone andcavalryHe diedseattle00,000 {windowhave toif(windand itssolely m"renewedDetroitamongsteither them inSenatorUs</a><King ofFrancis-produche usedart andhim andused byscoringat hometo haverelatesibilityfactionBuffalolink"><what hefree toCity ofcome insectorscountedone daynervoussquare };if(goin whatimg" alis onlysearch/tuesdaylooselySolomonsexual - <a hrmedium"DO NOT France,with a war andsecond take a > + + +market.highwaydone inctivity"last">obligedrise to"undefimade to Early praisedin its for hisathleteJupiterYahoo! termed so manyreally s. The a woman?value=direct right" bicycleacing="day andstatingRather,higher Office are nowtimes, when a pay foron this-link">;borderaround annual the Newput the.com" takin toa brief(in thegroups.; widthenzymessimple in late{returntherapya pointbanninginks"> +();" rea place\u003Caabout atr> + ccount gives a<SCRIPTRailwaythemes/toolboxById("xhumans,watchesin some if (wicoming formats Under but hashanded made bythan infear ofdenoted/iframeleft involtagein eacha"base ofIn manyundergoregimesaction </p> +<ustomVa;></importsor thatmostly &re size="</a></ha classpassiveHost = WhetherfertileVarious=[];(fucameras/></td>acts asIn some> + +<!organis <br />Beijingcatalàdeutscheuropeueuskaragaeilgesvenskaespañamensajeusuariotrabajoméxicopáginasiempresistemaoctubreduranteañadirempresamomentonuestroprimeratravésgraciasnuestraprocesoestadoscalidadpersonanúmeroacuerdomúsicamiembroofertasalgunospaísesejemploderechoademásprivadoagregarenlacesposiblehotelessevillaprimeroúltimoeventosarchivoculturamujeresentradaanuncioembargomercadograndesestudiomejoresfebrerodiseñoturismocódigoportadaespaciofamiliaantoniopermiteguardaralgunaspreciosalguiensentidovisitastítuloconocersegundoconsejofranciaminutossegundatenemosefectosmálagasesiónrevistagranadacompraringresogarcíaacciónecuadorquienesinclusodeberámateriahombresmuestrapodríamañanaúltimaestamosoficialtambienningúnsaludospodemosmejorarpositionbusinesshomepagesecuritylanguagestandardcampaignfeaturescategoryexternalchildrenreservedresearchexchangefavoritetemplatemilitaryindustryservicesmaterialproductsz-index:commentssoftwarecompletecalendarplatformarticlesrequiredmovementquestionbuildingpoliticspossiblereligionphysicalfeedbackregisterpicturesdisabledprotocolaudiencesettingsactivityelementslearninganythingabstractprogressoverviewmagazineeconomictrainingpressurevarious <strong>propertyshoppingtogetheradvancedbehaviordownloadfeaturedfootballselectedLanguagedistanceremembertrackingpasswordmodifiedstudentsdirectlyfightingnortherndatabasefestivalbreakinglocationinternetdropdownpracticeevidencefunctionmarriageresponseproblemsnegativeprogramsanalysisreleasedbanner">purchasepoliciesregionalcreativeargumentbookmarkreferrerchemicaldivisioncallbackseparateprojectsconflicthardwareinterestdeliverymountainobtained= false;for(var acceptedcapacitycomputeridentityaircraftemployedproposeddomesticincludesprovidedhospitalverticalcollapseapproachpartnerslogo"><adaughterauthor" culturalfamilies/images/assemblypowerfulteachingfinisheddistrictcriticalcgi-bin/purposesrequireselectionbecomingprovidesacademicexerciseactuallymedicineconstantaccidentMagazinedocumentstartingbottom">observed: "extendedpreviousSoftwarecustomerdecisionstrengthdetailedslightlyplanningtextareacurrencyeveryonestraighttransferpositiveproducedheritageshippingabsolutereceivedrelevantbutton" violenceanywherebenefitslaunchedrecentlyalliancefollowedmultiplebulletinincludedoccurredinternal$(this).republic><tr><tdcongressrecordedultimatesolution<ul id="discoverHome</a>websitesnetworksalthoughentirelymemorialmessagescontinueactive">somewhatvictoriaWestern title="LocationcontractvisitorsDownloadwithout right"> +measureswidth = variableinvolvedvirginianormallyhappenedaccountsstandingnationalRegisterpreparedcontrolsaccuratebirthdaystrategyofficialgraphicscriminalpossiblyconsumerPersonalspeakingvalidateachieved.jpg" />machines</h2> + keywordsfriendlybrotherscombinedoriginalcomposedexpectedadequatepakistanfollow" valuable</label>relativebringingincreasegovernorplugins/List of Header">" name=" ("graduate</head> +commercemalaysiadirectormaintain;height:schedulechangingback to catholicpatternscolor: #greatestsuppliesreliable</ul> + <select citizensclothingwatching<li id="specificcarryingsentence<center>contrastthinkingcatch(e)southernMichael merchantcarouselpadding:interior.split("lizationOctober ){returnimproved--> + +coveragechairman.png" />subjectsRichard whateverprobablyrecoverybaseballjudgmentconnect..css" /> websitereporteddefault"/></a> +electricscotlandcreationquantity. ISBN 0did not instance-search-" lang="speakersComputercontainsarchivesministerreactiondiscountItalianocriteriastrongly: 'http:'script'coveringofferingappearedBritish identifyFacebooknumerousvehiclesconcernsAmericanhandlingdiv id="William provider_contentaccuracysection andersonflexibleCategorylawrence<script>layout="approved maximumheader"></table>Serviceshamiltoncurrent canadianchannels/themes//articleoptionalportugalvalue=""intervalwirelessentitledagenciesSearch" measuredthousandspending…new Date" size="pageNamemiddle" " /></a>hidden">sequencepersonaloverflowopinionsillinoislinks"> + <title>versionssaturdayterminalitempropengineersectionsdesignerproposal="false"Españolreleasessubmit" er"additionsymptomsorientedresourceright"><pleasurestationshistory.leaving border=contentscenter">. + +Some directedsuitablebulgaria.show();designedGeneral conceptsExampleswilliamsOriginal"><span>search">operatorrequestsa "allowingDocumentrevision. + +The yourselfContact michiganEnglish columbiapriorityprintingdrinkingfacilityreturnedContent officersRussian generate-8859-1"indicatefamiliar qualitymargin:0 contentviewportcontacts-title">portable.length eligibleinvolvesatlanticonload="default.suppliedpaymentsglossary + +After guidance</td><tdencodingmiddle">came to displaysscottishjonathanmajoritywidgets.clinicalthailandteachers<head> + affectedsupportspointer;toString</small>oklahomawill be investor0" alt="holidaysResourcelicensed (which . After considervisitingexplorerprimary search" android"quickly meetingsestimate;return ;color:# height=approval, " checked.min.js"magnetic></a></hforecast. While thursdaydvertiseéhasClassevaluateorderingexistingpatients Online coloradoOptions"campbell<!-- end</span><<br /> +_popups|sciences," quality Windows assignedheight: <b classle" value=" Companyexamples<iframe believespresentsmarshallpart of properly). + +The taxonomymuch of </span> +" data-srtuguêsscrollTo project<head> +attorneyemphasissponsorsfancyboxworld's wildlifechecked=sessionsprogrammpx;font- Projectjournalsbelievedvacationthompsonlightingand the special border=0checking</tbody><button Completeclearfix +<head> +article <sectionfindingsrole in popular Octoberwebsite exposureused to changesoperatedclickingenteringcommandsinformed numbers </div>creatingonSubmitmarylandcollegesanalyticlistingscontact.loggedInadvisorysiblingscontent"s")s. This packagescheckboxsuggestspregnanttomorrowspacing=icon.pngjapanesecodebasebutton">gamblingsuch as , while </span> missourisportingtop:1px .</span>tensionswidth="2lazyloadnovemberused in height="cript"> + </<tr><td height:2/productcountry include footer" <!-- title"></jquery.</form> +(简体)(繁體)hrvatskiitalianoromânătürkçeاردوtambiénnoticiasmensajespersonasderechosnacionalserviciocontactousuariosprogramagobiernoempresasanunciosvalenciacolombiadespuésdeportesproyectoproductopúbliconosotroshistoriapresentemillonesmediantepreguntaanteriorrecursosproblemasantiagonuestrosopiniónimprimirmientrasaméricavendedorsociedadrespectorealizarregistropalabrasinterésentoncesespecialmiembrosrealidadcórdobazaragozapáginassocialesbloqueargestiónalquilersistemascienciascompletoversióncompletaestudiospúblicaobjetivoalicantebuscadorcantidadentradasaccionesarchivossuperiormayoríaalemaniafunciónúltimoshaciendoaquellosediciónfernandoambientefacebooknuestrasclientesprocesosbastantepresentareportarcongresopublicarcomerciocontratojóvenesdistritotécnicaconjuntoenergíatrabajarasturiasrecienteutilizarboletínsalvadorcorrectatrabajosprimerosnegocioslibertaddetallespantallapróximoalmeríaanimalesquiénescorazónsecciónbuscandoopcionesexteriorconceptotodavíagaleríaescribirmedicinalicenciaconsultaaspectoscríticadólaresjusticiadeberánperíodonecesitamantenerpequeñorecibidatribunaltenerifecancióncanariasdescargadiversosmallorcarequieretécnicodeberíaviviendafinanzasadelantefuncionaconsejosdifícilciudadesantiguasavanzadatérminounidadessánchezcampañasoftonicrevistascontienesectoresmomentosfacultadcréditodiversassupuestofactoressegundospequeñaгодаеслиестьбылобытьэтомЕслитогоменявсехэтойдажебылигодуденьэтотбыласебяодинсебенадосайтфотонегосвоисвойигрытожевсемсвоюлишьэтихпокаднейдомамиралиботемухотядвухсетилюдиделомиретебясвоевидечегоэтимсчеттемыценысталведьтемеводытебевышенамитипатомуправлицаоднагодызнаюмогудругвсейидеткиноодноделаделесрокиюнявесьЕстьразанашиاللهالتيجميعخاصةالذيعليهجديدالآنالردتحكمصفحةكانتاللييكونشبكةفيهابناتحواءأكثرخلالالحبدليلدروساضغطتكونهناكساحةناديالطبعليكشكرايمكنمنهاشركةرئيسنشيطماذاالفنشبابتعبررحمةكافةيقولمركزكلمةأحمدقلبييعنيصورةطريقشاركجوالأخرىمعناابحثعروضبشكلمسجلبنانخالدكتابكليةبدونأيضايوجدفريقكتبتأفضلمطبخاكثرباركافضلاحلىنفسهأيامردودأنهاديناالانمعرضتعلمداخلممكن���������������������� +  + ÿÿÿÿ��������ÿÿÿÿ������������������ÿÿ������ÿÿ����������������resourcescountriesquestionsequipmentcommunityavailablehighlightDTD/xhtmlmarketingknowledgesomethingcontainerdirectionsubscribeadvertisecharacter" value="</select>Australia" class="situationauthorityfollowingprimarilyoperationchallengedevelopedanonymousfunction functionscompaniesstructureagreement" title="potentialeducationargumentssecondarycopyrightlanguagesexclusivecondition</form> +statementattentionBiography} else { +solutionswhen the Analyticstemplatesdangeroussatellitedocumentspublisherimportantprototypeinfluence»</effectivegenerallytransformbeautifultransportorganizedpublishedprominentuntil thethumbnailNational .focus();over the migrationannouncedfooter"> +exceptionless thanexpensiveformationframeworkterritoryndicationcurrentlyclassNamecriticismtraditionelsewhereAlexanderappointedmaterialsbroadcastmentionedaffiliate</option>treatmentdifferent/default.Presidentonclick="biographyotherwisepermanentFrançaisHollywoodexpansionstandards</style> +reductionDecember preferredCambridgeopponentsBusiness confusion> +<title>presentedexplaineddoes not worldwideinterfacepositionsnewspaper</table> +mountainslike the essentialfinancialselectionaction="/abandonedEducationparseInt(stabilityunable to +relationsNote thatefficientperformedtwo yearsSince thethereforewrapper">alternateincreasedBattle ofperceivedtrying tonecessaryportrayedelectionsElizabethdiscoveryinsurances.length;legendaryGeographycandidatecorporatesometimesservices.inheritedCommunityreligiouslocationsCommitteebuildingsthe worldno longerbeginningreferencecannot befrequencytypicallyinto the relative;recordingpresidentinitiallytechniquethe otherit can beexistenceunderlinethis timetelephoneitemscopepracticesadvantage);return For otherprovidingdemocracyboth the extensivesufferingsupportedcomputers functionpracticalsaid thatit may beEnglish +suspectedmargin: 0spiritual + +microsoftgraduallydiscussedhe becameexecutivejquery.jshouseholdconfirmedpurchasedliterallydestroyedup to thevariationremainingit is notcenturiesJapanese among thecompletedalgorithminterestsrebellionundefinedencourageresizableinvolvingsensitiveuniversalprovision(althoughfeaturingconducted), which continued-header">February numerous overflow:componentfragmentsexcellentcolspan="technicalnear the Advanced source ofexpressedHong Kong Facebookmultiple mechanismelevationoffensive + sponsoreddocument.or "there arethose whomovementsprocessesdifficultsubmittedrecommendconvincedpromoting" width=".replace(classicalcoalitionhis firstdecisionsassistantindicatedevolution-wrapper"enough toalong thedelivered--> + + +
Archbishop class="nobeing usedapproachesprivilegesnoscript> +results inmay be theEaster eggmechanismsreasonablePopulationCollectionselected">noscript> /index.phparrival of-jssdk'));managed toincompletecasualtiescompletionChristiansSeptember arithmeticproceduresmight haveProductionit appearsPhilosophyfriendshipleading togiving thetoward theguaranteeddocumentedcolor:#000video gamecommissionreflectingchange theassociatedsans-serifonkeypress; padding:He was theunderlyingtypically , and the srcElementsuccessivesince the should be networkingaccountinguse of thelower thanshows that + complaintscontinuousquantitiesastronomerhe did notdue to itsapplied toan averageefforts tothe futureattempt toTherefore,capabilityRepublicanwas formedElectronickilometerschallengespublishingthe formerindigenousdirectionssubsidiaryconspiracydetails ofand in theaffordablesubstancesreason forconventionitemtype="absolutelysupposedlyremained aattractivetravellingseparatelyfocuses onelementaryapplicablefound thatstylesheetmanuscriptstands for no-repeat(sometimesCommercialin Americaundertakenquarter ofan examplepersonallyindex.php? +percentagebest-knowncreating a" dir="ltrLieutenant +
is said tostructuralreferendummost oftena separate-> +
implementedcan be seenthere was ademonstratecontainer">connectionsthe Britishwas written!important;px; margin-followed byability to complicatedduring the immigrationalso called

as follows:merged withthrough thecommercial pointed outopportunityview of therequirementdivision ofprogramminghe receivedsetInterval">maintainingChristopherMuch of thewritings of" height="2size of theversion of mixture of between theExamples ofeducationalcompetitive onsubmit="director ofdistinctive/DTD XHTML relating totendency toprovince ofwhich woulddespite thescientific legislature.innerHTML allegationsAgriculturewas used inapproach tointelligentyears later,sans-serifdeterminingPerformanceappearances, which is foundationsabbreviatedhigher thans from the individual composed ofsupposed toclaims thatattributionfont-size:1elements ofHistorical his brotherat the timeanniversarygoverned byrelated to ultimately innovationsit is stillcan only bedefinitionstoGMTStringA number ofimg class="Eventually,was changedoccurred inneighboringdistinguishwhen he wasintroducingterrestrialMany of theargues thatan Americanconquest ofwidespread were killedscreen and In order toexpected todescendantsare locatedlegislativegenerations backgroundmost peopleyears afterthere is nothe highestfrequently they do notargued thatshowed thatpredominanttheologicalby the timeconsideringshort-livedcan be usedvery littleone of the had alreadyinterpretedcommunicatefeatures ofgovernment,entered the" height="3Independentpopulationslarge-scale. Although used in thedestructionpossibilitystarting intwo or moreexpressionssubordinatelarger thanhistory and +Continentaleliminatingwill not bepractice ofin front ofsite of theensure thatto create amississippipotentiallyoutstandingbetter thanwhat is nowsituated inmeta name="TraditionalsuggestionsTranslationthe form ofatmosphericideologicalenterprisescalculatingeast of theremnants ofpluginspage/index.php?remained intransformedHe was alsowas alreadystatisticalin favor ofMinistry ofmovement offormulationis required +question ofwas electedto become abecause of some peopleinspired bysuccessful a time whenmore commonamongst thean officialwidth:100%;technology,was adoptedto keep thesettlementslive birthsindex.html"Connecticutassigned to&times;account foralign=rightthe companyalways beenreturned toinvolvementBecause thethis period" name="q" confined toa result ofvalue="" />is actuallyEnvironment + +Conversely,> +
this is notthe presentif they areand finallya matter of +
+ +faster thanmajority ofafter whichcomparativeto maintainimprove theawarded theer" class="frameborderrestorationin the sameanalysis oftheir firstDuring the continentalsequence offunction(){font-size: work on the +adopted theproperty ofdirected byeffectivelywas broughtchildren ofProgramminglonger thanmanuscriptswar againstby means ofand most ofsimilar to proprietaryoriginatingprestigiousgrammaticalexperience.to make theIt was alsois found incompetitorsin the U.S.replace thebrought thecalculationfall of thethe generalpracticallyin honor ofreleased inresidentialand some ofking of thereaction to1st Earl ofculture andprincipally + they can beback to thesome of hisexposure toare similarform of theaddFavoritecitizenshippart in thepeople within practiceto continue&minus;approved by the first allowed theand for thefunctioningplaying thesolution toheight="0" in his bookmore than afollows thecreated thepresence in nationalistthe idea ofa characterwere forced class="btndays of thefeatured inshowing theinterest inin place ofturn of thethe head ofLord of thepoliticallyhas its ownEducationalapproval ofsome of theeach other,behavior ofand becauseand anotherappeared onrecorded inblack"may includethe world'scan lead torefers to aborder="0" government winning theresulted in while the Washington,the subjectcity in the>

+ reflect theto completebecame moreradioactiverejected bywithout anyhis father,which couldcopy of theto indicatea politicalaccounts ofconstitutesworked witherof his lifeaccompaniedclientWidthprevent theLegislativedifferentlytogether inhas severalfor anothertext of thefounded thee with the is used forchanged theusually theplace wherewhereas the> The currentthe site ofsubstantialexperience,in the Westthey shouldslovenčinacomentariosuniversidadcondicionesactividadesexperienciatecnologíaproducciónpuntuaciónaplicacióncontraseñacategoríasregistrarseprofesionaltratamientoregístratesecretaríaprincipalesprotecciónimportantesimportanciaposibilidadinteresantecrecimientonecesidadessuscribirseasociacióndisponiblesevaluaciónestudiantesresponsableresoluciónguadalajararegistradosoportunidadcomercialesfotografíaautoridadesingenieríatelevisióncompetenciaoperacionesestablecidosimplementeactualmentenavegaciónconformidadline-height:font-family:" : "http://applicationslink" href="specifically// +/index.html"window.open( !important;application/independence//www.googleorganizationautocompleterequirementsconservative
most notably/>
notification'undefined')Furthermore,believe thatinnerHTML = prior to thedramaticallyreferring tonegotiationsheadquartersSouth AfricaunsuccessfulPennsylvaniaAs a result, +
English (US)appendChild(transmissions. However, intelligence" tabindex="float:right;Commonwealthranging fromin which theat least onereproductionencyclopedia;font-size:1jurisdictionat that time">compensationchampionshipmedia="all" violation ofreference toreturn true;Strict//EN" transactionsinterventionverificationInformation difficultiesChampionshipcapabilities} + +Christianityfor example,Professionalrestrictionssuggest thatwas released(such as theremoveClass(unemploymentthe Americanstructure of/index.html published inspan class=""> + +f (document.border: 1px {font-size:1treatment of0" height="1modificationIndependencedivided intogreater thanachievementsestablishingJavaScript" neverthelesssignificanceBroadcasting> container"> +such as the influence ofa particularsrc='http://navigation" half of the substantial  advantage ofdiscovery offundamental metropolitanthe opposite" xml:lang="deliberatelyalign=centerevolution ofpreservationimprovementsbeginning inJesus ChristPublicationsdisagreementtext-align:r, function()similaritiesbody>is currentlyalphabeticalis sometimestype="image/many of the flow:hidden;available indescribe theexistence ofall over thethe Internet