예제 #1
0
        public byte[] Compress(byte[] input, int windowBits = 26, LZHPerformance mode = LZHPerformance.NORMAL)
        {
            switch (mode)
            {
            case LZHPerformance.L1_VeryFast: Matcher = new HashTable3(input, windowBits); LazyParse = false; break;

            case LZHPerformance.L2_VeryFast: Matcher = new HashTable3(input, windowBits); LazyParse = true;  break;

            case LZHPerformance.L3_Fast:     Matcher = new MetaHT3HC4(input, windowBits, 4); LazyParse = false; break;

            case LZHPerformance.L4_Fast:     Matcher = new MetaHT3HC4(input, windowBits, 4); LazyParse = true; break;

            case LZHPerformance.NORMAL:      Matcher = new MetaHT3HC4HC8(input, 26, 16); LazyParse = false; break;

            case LZHPerformance.BETTER:      Matcher = new MetaHT3HC4HC8(input, 26, 32); LazyParse = true; break;
            }

            int inputSize   = input.Length;
            int inputOffset = 0;

            Output         = new BitWriterFwd();
            CachedPosition = -1;
            CachedMatch    = default;
            SymbolFreqs    = new int[NUM_SYMBOLS];
            ChunkBuffer    = new ushort[Math.Min(inputSize, CHUNK_SIZE)];
            MatchEncodes   = new Queue <MatchData>();

            CalcChunkEnd(inputOffset, inputSize);
            while (true)
            {
                var  match          = FindBestMatch(inputOffset);
                bool matchAvailable = match.Benefit > 0;

                if (matchAvailable && LazyParse)
                {
                    var nextMatch = PeekNextMatch(inputOffset + 1);
                    if (nextMatch.Benefit > match.Benefit)
                    {
                        matchAvailable = false;
                    }
                }

                if (matchAvailable)
                {
                    if (match.Length > MAX_MATCH)
                    {
                        match.Length = MAX_MATCH;
                    }
                    EmitMatch(match.Length, match.Distance);
                    inputOffset += match.Length;
                }
                else     // No match available, emit literal
                {
                    EmitSymbol(input[inputOffset++]);
                }

                // Encode chunk if we've reached end of chunk
                if (inputOffset >= ChunkEnd)
                {
                    if (ChunkEnd == inputSize)
                    {
                        EmitSymbol(SYM_EOF);
                    }
                    else
                    {
                        EmitSymbol(SYM_NEWTREE);
                    }

                    EncodeChunk();
                    if (inputOffset >= inputSize)
                    {
                        break;
                    }

                    CalcChunkEnd(inputOffset, inputSize);
                }
            }
            return(Output.GetBuffer());
        }
예제 #2
0
        public void Encode(BitWriterFwd writer, int symbol)
        {
            var sym = Symbols[symbol];

            writer.WriteBits(sym.Code, sym.Length);
        }