private void AddChild(ChunkNode child) { if (this.children == null) { this.children = new List <ChunkNode>(); } this.children.Add(child); }
public ChunkNode(ChunkNode parent, int command, int sourceOffset, int byteCount) { this.IsOptimal = true; this.command = command; this.sourceOffset = sourceOffset; this.byteCount = byteCount; this.compressedChunkSize = this.GetCompressedSize(); this.CompressedBufferSize = this.compressedChunkSize; if (parent != null) { this.parent = parent; this.parent.AddChild(this); this.CompressedBufferSize += this.parent.CompressedBufferSize; } }
public byte[] Compress(byte[] buffer) { ByteDictionary byteDictionary = new ByteDictionary(buffer); ChunkNodeCollection nodeCollection = new ChunkNodeCollection(); while (nodeCollection.Count > 0) { if (nodeCollection.IsNextNodeOptimal()) { KeyValuePair <int, ChunkNode> parentNode = nodeCollection.GetNextNode(); if (parentNode.Key < buffer.Length) { OptimalCompressor.CreateChildNodes(buffer, nodeCollection, parentNode.Key, parentNode.Value, byteDictionary); } } } ChunkNode bestNode = nodeCollection[buffer.Length]; return(bestNode.GetCompressedBuffer(buffer)); }
private static void CreateNodesFromCommand(int command, int byteCount, ChunkNodeCollection nodeCollection, int i, ChunkNode parentNode) { byteCount = Codec.GetValidatedSuperCommandSize(byteCount); if (byteCount > Codec.NormalCommandMax) { int reducedByteCount = Math.Min(byteCount, Codec.NormalCommandMax); nodeCollection.Add(i + reducedByteCount, new ChunkNode(parentNode, command, i, reducedByteCount)); } nodeCollection.Add(i + byteCount, new ChunkNode(parentNode, command, i, byteCount)); }
private static void CreateChildNodes(byte[] buffer, ChunkNodeCollection nodeCollection, int i, ChunkNode parentNode, ByteDictionary byteDictionary) { // NOTE: Command 5 (ie: the same as command 4 except it inverts each byte) // is not implemented, because it's almost never used. // Implementing it would complicate the code and slow down the compression for little to no benefit. // NOTE: Checking out command 0 every time (ie: putting it out of the if conditions) // can improve compression a tiny bit (like just one byte) in some rare cases, // but it's not worth the huge hit on compression speed. OptimalCompressor.CreateNodesFromBackCommands(nodeCollection, i, parentNode, byteDictionary); int command; int byteCount; if ((i + 1) < buffer.Length && buffer[i] == buffer[i + 1]) { command = 1; byteCount = OptimalCompressor.GetCommand1ByteCount(buffer, i); } else if ((i + 2) < buffer.Length && buffer[i] == buffer[i + 2]) { command = 2; byteCount = OptimalCompressor.GetCommand2ByteCount(buffer, i); } else if ((i + 1) < buffer.Length && ((buffer[i] + 1) & 0xFF) == buffer[i + 1]) { command = 3; byteCount = OptimalCompressor.GetCommand3ByteCount(buffer, i); } else { command = 0; byteCount = OptimalCompressor.GetCommand0ByteCount(buffer, i); } OptimalCompressor.CreateNodesFromCommand(command, byteCount, nodeCollection, i, parentNode); }
private static void CreateNodesFromBackCommands(ChunkNodeCollection nodeCollection, int i, ChunkNode parentNode, ByteDictionary byteDictionary) { Range[] ranges = byteDictionary.GetMaxBackRanges(i); if (ranges[0].Length > 0) { nodeCollection.Add(i + ranges[0].Length, new ChunkNode(parentNode, 4, ranges[0].Start, ranges[0].Length)); } if (ranges[1].Length > 0) { nodeCollection.Add(i + ranges[1].Length, new ChunkNode(parentNode, 4, ranges[1].Start, ranges[1].Length)); } if (ranges[2].Length > 0) { nodeCollection.Add(i + ranges[2].Length, new ChunkNode(parentNode, 6, i - ranges[2].Start, ranges[2].Length)); } if (ranges[3].Length > 0) { nodeCollection.Add(i + ranges[3].Length, new ChunkNode(parentNode, 6, i - ranges[3].Start, ranges[3].Length)); } }