// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Diagnostics; namespace SharpCompress.Compressors.Deflate64; internal static class FastEncoderStatics { // static information for encoding, DO NOT MODIFY internal static ReadOnlySpan FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[] { 0xec, 0xbd, 0x07, 0x60, 0x1c, 0x49, 0x96, 0x25, 0x26, 0x2f, 0x6d, 0xca, 0x7b, 0x7f, 0x4a, 0xf5, 0x4a, 0xd7, 0xe0, 0x74, 0xa1, 0x08, 0x80, 0x60, 0x13, 0x24, 0xd8, 0x90, 0x40, 0x10, 0xec, 0xc1, 0x88, 0xcd, 0xe6, 0x92, 0xec, 0x1d, 0x69, 0x47, 0x23, 0x29, 0xab, 0x2a, 0x81, 0xca, 0x65, 0x56, 0x65, 0x5d, 0x66, 0x16, 0x40, 0xcc, 0xed, 0x9d, 0xbc, 0xf7, 0xde, 0x7b, 0xef, 0xbd, 0xf7, 0xde, 0x7b, 0xef, 0xbd, 0xf7, 0xba, 0x3b, 0x9d, 0x4e, 0x27, 0xf7, 0xdf, 0xff, 0x3f, 0x5c, 0x66, 0x64, 0x01, 0x6c, 0xf6, 0xce, 0x4a, 0xda, 0xc9, 0x9e, 0x21, 0x80, 0xaa, 0xc8, 0x1f, 0x3f, 0x7e, 0x7c, 0x1f, 0x3f, }; internal static ReadOnlySpan B_FINAL_FAST_ENCODER_TREE_STRUCTURE_DATA => new byte[] { 0xed, 0xbd, 0x07, 0x60, 0x1c, 0x49, 0x96, 0x25, 0x26, 0x2f, 0x6d, 0xca, 0x7b, 0x7f, 0x4a, 0xf5, 0x4a, 0xd7, 0xe0, 0x74, 0xa1, 0x08, 0x80, 0x60, 0x13, 0x24, 0xd8, 0x90, 0x40, 0x10, 0xec, 0xc1, 0x88, 0xcd, 0xe6, 0x92, 0xec, 0x1d, 0x69, 0x47, 0x23, 0x29, 0xab, 0x2a, 0x81, 0xca, 0x65, 0x56, 0x65, 0x5d, 0x66, 0x16, 0x40, 0xcc, 0xed, 0x9d, 0xbc, 0xf7, 0xde, 0x7b, 0xef, 0xbd, 0xf7, 0xde, 0x7b, 0xef, 0xbd, 0xf7, 0xba, 0x3b, 0x9d, 0x4e, 0x27, 0xf7, 0xdf, 0xff, 0x3f, 0x5c, 0x66, 0x64, 0x01, 0x6c, 0xf6, 0xce, 0x4a, 0xda, 0xc9, 0x9e, 0x21, 0x80, 0xaa, 0xc8, 0x1f, 0x3f, 0x7e, 0x7c, 0x1f, 0x3f, }; // Output a currentMatch with length matchLen (>= MIN_MATCH) and displacement matchPos // // Optimisation: unlike the other encoders, here we have an array of codes for each currentMatch // length (not just each currentMatch length slot), complete with all the extra bits filled in, in // a single array element. // // There are many advantages to doing this: // // 1. A single array lookup on g_FastEncoderLiteralCodeInfo, instead of separate array lookups // on g_LengthLookup (to get the length slot), g_FastEncoderLiteralTreeLength, // g_FastEncoderLiteralTreeCode, g_ExtraLengthBits, and g_BitMask // // 2. The array is an array of ULONGs, so no access penalty, unlike for accessing those USHORT // code arrays in the other encoders (although they could be made into ULONGs with some // modifications to the source). // // Note, if we could guarantee that codeLen <= 16 always, then we could skip an if statement here. // // A completely different optimisation is used for the distance codes since, obviously, a table for // all 8192 distances combining their extra bits is not feasible. The distance codeinfo table is // made up of code[], len[] and # extraBits for this code. // // The advantages are similar to the above; a ULONG array instead of a USHORT and BYTE array, better // cache locality, fewer memory operations. // // Encoding information for literal and Length. // The least 5 significant bits are the length // and the rest is the code bits. internal static readonly uint[] FAST_ENCODER_LITERAL_CODE_INFO = { 0x0000d7ee, 0x0004d7ee, 0x0002d7ee, 0x0006d7ee, 0x0001d7ee, 0x0005d7ee, 0x0003d7ee, 0x0007d7ee, 0x000037ee, 0x0000c7ec, 0x00000126, 0x000437ee, 0x000237ee, 0x000637ee, 0x000137ee, 0x000537ee, 0x000337ee, 0x000737ee, 0x0000b7ee, 0x0004b7ee, 0x0002b7ee, 0x0006b7ee, 0x0001b7ee, 0x0005b7ee, 0x0003b7ee, 0x0007b7ee, 0x000077ee, 0x000477ee, 0x000277ee, 0x000677ee, 0x000017ed, 0x000177ee, 0x00000526, 0x000577ee, 0x000023ea, 0x0001c7ec, 0x000377ee, 0x000777ee, 0x000217ed, 0x000063ea, 0x00000b68, 0x00000ee9, 0x00005beb, 0x000013ea, 0x00000467, 0x00001b68, 0x00000c67, 0x00002ee9, 0x00000768, 0x00001768, 0x00000f68, 0x00001ee9, 0x00001f68, 0x00003ee9, 0x000053ea, 0x000001e9, 0x000000e8, 0x000021e9, 0x000011e9, 0x000010e8, 0x000031e9, 0x000033ea, 0x000008e8, 0x0000f7ee, 0x0004f7ee, 0x000018e8, 0x000009e9, 0x000004e8, 0x000029e9, 0x000014e8, 0x000019e9, 0x000073ea, 0x0000dbeb, 0x00000ce8, 0x00003beb, 0x0002f7ee, 0x000039e9, 0x00000bea, 0x000005e9, 0x00004bea, 0x000025e9, 0x000027ec, 0x000015e9, 0x000035e9, 0x00000de9, 0x00002bea, 0x000127ec, 0x0000bbeb, 0x0006f7ee, 0x0001f7ee, 0x0000a7ec, 0x00007beb, 0x0005f7ee, 0x0000fbeb, 0x0003f7ee, 0x0007f7ee, 0x00000fee, 0x00000326, 0x00000267, 0x00000a67, 0x00000667, 0x00000726, 0x00001ce8, 0x000002e8, 0x00000e67, 0x000000a6, 0x0001a7ec, 0x00002de9, 0x000004a6, 0x00000167, 0x00000967, 0x000002a6, 0x00000567, 0x000117ed, 0x000006a6, 0x000001a6, 0x000005a6, 0x00000d67, 0x000012e8, 0x00000ae8, 0x00001de9, 0x00001ae8, 0x000007eb, 0x000317ed, 0x000067ec, 0x000097ed, 0x000297ed, 0x00040fee, 0x00020fee, 0x00060fee, 0x00010fee, 0x00050fee, 0x00030fee, 0x00070fee, 0x00008fee, 0x00048fee, 0x00028fee, 0x00068fee, 0x00018fee, 0x00058fee, 0x00038fee, 0x00078fee, 0x00004fee, 0x00044fee, 0x00024fee, 0x00064fee, 0x00014fee, 0x00054fee, 0x00034fee, 0x00074fee, 0x0000cfee, 0x0004cfee, 0x0002cfee, 0x0006cfee, 0x0001cfee, 0x0005cfee, 0x0003cfee, 0x0007cfee, 0x00002fee, 0x00042fee, 0x00022fee, 0x00062fee, 0x00012fee, 0x00052fee, 0x00032fee, 0x00072fee, 0x0000afee, 0x0004afee, 0x0002afee, 0x0006afee, 0x0001afee, 0x0005afee, 0x0003afee, 0x0007afee, 0x00006fee, 0x00046fee, 0x00026fee, 0x00066fee, 0x00016fee, 0x00056fee, 0x00036fee, 0x00076fee, 0x0000efee, 0x0004efee, 0x0002efee, 0x0006efee, 0x0001efee, 0x0005efee, 0x0003efee, 0x0007efee, 0x00001fee, 0x00041fee, 0x00021fee, 0x00061fee, 0x00011fee, 0x00051fee, 0x00031fee, 0x00071fee, 0x00009fee, 0x00049fee, 0x00029fee, 0x00069fee, 0x00019fee, 0x00059fee, 0x00039fee, 0x00079fee, 0x00005fee, 0x00045fee, 0x00025fee, 0x00065fee, 0x00015fee, 0x00055fee, 0x00035fee, 0x00075fee, 0x0000dfee, 0x0004dfee, 0x0002dfee, 0x0006dfee, 0x0001dfee, 0x0005dfee, 0x0003dfee, 0x0007dfee, 0x00003fee, 0x00043fee, 0x00023fee, 0x00063fee, 0x00013fee, 0x00053fee, 0x00033fee, 0x00073fee, 0x0000bfee, 0x0004bfee, 0x0002bfee, 0x0006bfee, 0x0001bfee, 0x0005bfee, 0x0003bfee, 0x0007bfee, 0x00007fee, 0x00047fee, 0x00027fee, 0x00067fee, 0x00017fee, 0x000197ed, 0x000397ed, 0x000057ed, 0x00057fee, 0x000257ed, 0x00037fee, 0x000157ed, 0x00077fee, 0x000357ed, 0x0000ffee, 0x0004ffee, 0x0002ffee, 0x0006ffee, 0x0001ffee, 0x00000084, 0x00000003, 0x00000184, 0x00000044, 0x00000144, 0x000000c5, 0x000002c5, 0x000001c5, 0x000003c6, 0x000007c6, 0x00000026, 0x00000426, 0x000003a7, 0x00000ba7, 0x000007a7, 0x00000fa7, 0x00000227, 0x00000627, 0x00000a27, 0x00000e27, 0x00000068, 0x00000868, 0x00001068, 0x00001868, 0x00000369, 0x00001369, 0x00002369, 0x00003369, 0x000006ea, 0x000026ea, 0x000046ea, 0x000066ea, 0x000016eb, 0x000036eb, 0x000056eb, 0x000076eb, 0x000096eb, 0x0000b6eb, 0x0000d6eb, 0x0000f6eb, 0x00003dec, 0x00007dec, 0x0000bdec, 0x0000fdec, 0x00013dec, 0x00017dec, 0x0001bdec, 0x0001fdec, 0x00006bed, 0x0000ebed, 0x00016bed, 0x0001ebed, 0x00026bed, 0x0002ebed, 0x00036bed, 0x0003ebed, 0x000003ec, 0x000043ec, 0x000083ec, 0x0000c3ec, 0x000103ec, 0x000143ec, 0x000183ec, 0x0001c3ec, 0x00001bee, 0x00009bee, 0x00011bee, 0x00019bee, 0x00021bee, 0x00029bee, 0x00031bee, 0x00039bee, 0x00041bee, 0x00049bee, 0x00051bee, 0x00059bee, 0x00061bee, 0x00069bee, 0x00071bee, 0x00079bee, 0x000167f0, 0x000367f0, 0x000567f0, 0x000767f0, 0x000967f0, 0x000b67f0, 0x000d67f0, 0x000f67f0, 0x001167f0, 0x001367f0, 0x001567f0, 0x001767f0, 0x001967f0, 0x001b67f0, 0x001d67f0, 0x001f67f0, 0x000087ef, 0x000187ef, 0x000287ef, 0x000387ef, 0x000487ef, 0x000587ef, 0x000687ef, 0x000787ef, 0x000887ef, 0x000987ef, 0x000a87ef, 0x000b87ef, 0x000c87ef, 0x000d87ef, 0x000e87ef, 0x000f87ef, 0x0000e7f0, 0x0002e7f0, 0x0004e7f0, 0x0006e7f0, 0x0008e7f0, 0x000ae7f0, 0x000ce7f0, 0x000ee7f0, 0x0010e7f0, 0x0012e7f0, 0x0014e7f0, 0x0016e7f0, 0x0018e7f0, 0x001ae7f0, 0x001ce7f0, 0x001ee7f0, 0x0005fff3, 0x000dfff3, 0x0015fff3, 0x001dfff3, 0x0025fff3, 0x002dfff3, 0x0035fff3, 0x003dfff3, 0x0045fff3, 0x004dfff3, 0x0055fff3, 0x005dfff3, 0x0065fff3, 0x006dfff3, 0x0075fff3, 0x007dfff3, 0x0085fff3, 0x008dfff3, 0x0095fff3, 0x009dfff3, 0x00a5fff3, 0x00adfff3, 0x00b5fff3, 0x00bdfff3, 0x00c5fff3, 0x00cdfff3, 0x00d5fff3, 0x00ddfff3, 0x00e5fff3, 0x00edfff3, 0x00f5fff3, 0x00fdfff3, 0x0003fff3, 0x000bfff3, 0x0013fff3, 0x001bfff3, 0x0023fff3, 0x002bfff3, 0x0033fff3, 0x003bfff3, 0x0043fff3, 0x004bfff3, 0x0053fff3, 0x005bfff3, 0x0063fff3, 0x006bfff3, 0x0073fff3, 0x007bfff3, 0x0083fff3, 0x008bfff3, 0x0093fff3, 0x009bfff3, 0x00a3fff3, 0x00abfff3, 0x00b3fff3, 0x00bbfff3, 0x00c3fff3, 0x00cbfff3, 0x00d3fff3, 0x00dbfff3, 0x00e3fff3, 0x00ebfff3, 0x00f3fff3, 0x00fbfff3, 0x0007fff3, 0x000ffff3, 0x0017fff3, 0x001ffff3, 0x0027fff3, 0x002ffff3, 0x0037fff3, 0x003ffff3, 0x0047fff3, 0x004ffff3, 0x0057fff3, 0x005ffff3, 0x0067fff3, 0x006ffff3, 0x0077fff3, 0x007ffff3, 0x0087fff3, 0x008ffff3, 0x0097fff3, 0x009ffff3, 0x00a7fff3, 0x00affff3, 0x00b7fff3, 0x00bffff3, 0x00c7fff3, 0x00cffff3, 0x00d7fff3, 0x00dffff3, 0x00e7fff3, 0x00effff3, 0x00f7fff3, 0x00fffff3, 0x0001e7f1, 0x0003e7f1, 0x0005e7f1, 0x0007e7f1, 0x0009e7f1, 0x000be7f1, 0x000de7f1, 0x000fe7f1, 0x0011e7f1, 0x0013e7f1, 0x0015e7f1, 0x0017e7f1, 0x0019e7f1, 0x001be7f1, 0x001de7f1, 0x001fe7f1, 0x0021e7f1, 0x0023e7f1, 0x0025e7f1, 0x0027e7f1, 0x0029e7f1, 0x002be7f1, 0x002de7f1, 0x002fe7f1, 0x0031e7f1, 0x0033e7f1, 0x0035e7f1, 0x0037e7f1, 0x0039e7f1, 0x003be7f1, 0x003de7f1, 0x000047eb, }; internal static readonly uint[] FAST_ENCODER_DISTANCE_CODE_INFO = { 0x00000f06, 0x0001ff0a, 0x0003ff0b, 0x0007ff0b, 0x0000ff19, 0x00003f18, 0x0000bf28, 0x00007f28, 0x00001f37, 0x00005f37, 0x00000d45, 0x00002f46, 0x00000054, 0x00001d55, 0x00000864, 0x00000365, 0x00000474, 0x00001375, 0x00000c84, 0x00000284, 0x00000a94, 0x00000694, 0x00000ea4, 0x000001a4, 0x000009b4, 0x00000bb5, 0x000005c4, 0x00001bc5, 0x000007d5, 0x000017d5, 0x00000000, 0x00000100, }; internal static readonly uint[] BIT_MASK = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, }; internal static readonly byte[] EXTRA_LENGTH_BITS = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, }; internal static readonly byte[] EXTRA_DISTANCE_BITS = { 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, 0, 0, }; internal const int NUM_CHARS = 256; internal const int NUM_LENGTH_BASE_CODES = 29; internal const int NUM_DIST_BASE_CODES = 30; internal const uint FAST_ENCODER_POST_TREE_BIT_BUF = 0x0022; internal const int FAST_ENCODER_POST_TREE_BIT_COUNT = 9; internal const uint NO_COMPRESSION_HEADER = 0x0; internal const int NO_COMPRESSION_HEADER_BIT_COUNT = 3; internal const uint B_FINAL_NO_COMPRESSION_HEADER = 0x1; internal const int B_FINAL_NO_COMPRESSION_HEADER_BIT_COUNT = 3; internal const int MAX_CODE_LEN = 16; private static readonly byte[] S_DIST_LOOKUP = CreateDistanceLookup(); private static byte[] CreateDistanceLookup() { var result = new byte[512]; // Generate the global slot tables which allow us to convert a distance // (0..32K) to a distance slot (0..29) // // Distance table // Extra Extra Extra // Code Bits Dist Code Bits Dist Code Bits Distance // ---- ---- ---- ---- ---- ------ ---- ---- -------- // 0 0 1 10 4 33-48 20 9 1025-1536 // 1 0 2 11 4 49-64 21 9 1537-2048 // 2 0 3 12 5 65-96 22 10 2049-3072 // 3 0 4 13 5 97-128 23 10 3073-4096 // 4 1 5,6 14 6 129-192 24 11 4097-6144 // 5 1 7,8 15 6 193-256 25 11 6145-8192 // 6 2 9-12 16 7 257-384 26 12 8193-12288 // 7 2 13-16 17 7 385-512 27 12 12289-16384 // 8 3 17-24 18 8 513-768 28 13 16385-24576 // 9 3 25-32 19 8 769-1024 29 13 24577-32768 // Initialize the mapping length (0..255) -> length code (0..28) //int length = 0; //for (code = 0; code < FastEncoderStatics.NumLengthBaseCodes-1; code++) { // for (int n = 0; n < (1 << FastEncoderStatics.ExtraLengthBits[code]); n++) // lengthLookup[length++] = (byte) code; //} //lengthLookup[length-1] = (byte) code; // Initialize the mapping dist (0..32K) -> dist code (0..29) var dist = 0; int code; for (code = 0; code < 16; code++) { for (var n = 0; n < (1 << EXTRA_DISTANCE_BITS[code]); n++) { result[dist++] = (byte)code; } } dist >>= 7; // from now on, all distances are divided by 128 for (; code < NUM_DIST_BASE_CODES; code++) { for (var n = 0; n < (1 << (EXTRA_DISTANCE_BITS[code] - 7)); n++) { result[256 + dist++] = (byte)code; } } return result; } // Return the position slot (0...29) of a match offset (0...32767) internal static int GetSlot(int pos) => S_DIST_LOOKUP[((pos) < 256) ? (pos) : (256 + ((pos) >> 7))]; // Reverse 'length' of the bits in code public static uint BitReverse(uint code, int length) { uint newCode = 0; Debug.Assert(length > 0 && length <= 16, "Invalid len"); do { newCode |= (code & 1); newCode <<= 1; code >>= 1; } while (--length > 0); return newCode >> 1; } }