Exemple #1
0
        private static List <State> GetStates(ReverseWindowReader data, int address)
        {
            var states = new List <State> {
                new State {
                    Command = new Command {
                        Simple = true, Value = data[address], CopySize = 1
                    },
                    Address = address
                }
            };

            for (int offset = 1; offset <= RingSize; offset++)
            {
                var cmd = TestCandidate(data, address, address - offset);

                if (cmd != null)
                {
                    states.Add(new State {
                        Command = cmd, Address = address
                    });
                }
            }

            return(states);
        }
Exemple #2
0
        private static Command TestCandidate(ReverseWindowReader data, int targetAddress, int sourceAddress)
        {
            if (data[targetAddress] != data[sourceAddress])
            {
                return(null);
            }

            var target = data.Branch(targetAddress);
            var source = data.Branch(sourceAddress);

            var count = 0;

            while (count < MaxCopySize)
            {
                if (target.Byte() != source.Byte())
                {
                    break;
                }

                count++;
            }

            if (count < MinCopySize)
            {
                return(null);
            }

            return(new Command {
                Simple = false,
                CopySize = count,
                Address = (sourceAddress - count + 1 + StartWriteAddress) % RingSize
            });
        }
Exemple #3
0
        public static byte[] CompressMax(byte[] target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            var data   = new ReverseWindowReader(target, 0);
            var states = new State[target.Length];

            for (int i = 0; i < target.Length; i++)
            {
                var   candidates = GetStates(data, i);
                State best       = null;
                foreach (var current in candidates)
                {
                    if (current.NextAddress < 0)
                    {
                        current.PathLength = current.Size;
                    }
                    else
                    {
                        // TODO: not checking states[] access for null because we want it to throw exception
                        current.PathLength = states[current.NextAddress].PathLength + current.Size;
                    }
                    if ((best == null) || (current.PathLength < best.PathLength))
                    {
                        best = current;
                    }
                }

                states[i] = best;
            }

            var step     = states[states.Length - 1];
            var commands = new List <Command> {
                step.Command
            };

            while (step.NextAddress >= 0)
            {
                step = states[step.NextAddress];
                commands.Add(step.Command);
            }

            return(CommandsToBytes(commands));
        }
Exemple #4
0
        public static byte[] Compress(byte[] target)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            var commands = new List <Command>();
            var address  = target.Length - 1;
            var data     = new ReverseWindowReader(target, address);

            while (address >= 0)
            {
                Command cmd    = null;
                var     offset = 1;
                while ((offset <= RingSize) && (cmd == null || cmd.CopySize < MaxCopySize))
                {
                    var testCommand = TestCandidate(data, address, address - offset);
                    if ((testCommand != null) && ((cmd == null) || (testCommand.CopySize > cmd.CopySize)))
                    {
                        cmd = testCommand;
                    }
                    offset++;
                }

                if (cmd == null)
                {
                    cmd = new Command {
                        Simple = true, Value = data[address]
                    };
                    address--;
                }
                else
                {
                    address -= cmd.CopySize;
                }

                commands.Add(cmd);
            }

            return(CommandsToBytes(commands));
        }