예제 #1
0
 // TODO: This would be more efficient as a member of the other class
 // ie avoid the recursion
 public LinkedNode Insert(LinkedNode other)
 {
     // 'Next' should have a lower weight
     // we should return the lower weight
     if (other.Weight <= Weight)
     {
         // insert before
         if (Next != null)
         {
             Next.Prev = other;
             other.Next = Next;
         }
         Next = other;
         other.Prev = this;
         return other;
     } else
     {
         if (Prev == null)
         {
             // Insert after
             other.Prev = null;
             Prev = other;
             other.Next = this;
         } else
         {
             Prev.Insert(other);
         }
     }
     return this;
 }
        private static LinkedNode BuildList(byte[] primeData)
        {
            LinkedNode node = new LinkedNode(0x100, 1);

            node = node.Insert(new LinkedNode(0x101, 1));
            for (int i = 0; i < primeData.Length; i++)
            {
                if (primeData[i] != 0)
                {
                    node = node.Insert(new LinkedNode(i, primeData[i]));
                }
            }
            return(node);
        }
        private static LinkedNode Decode(BitStream input, LinkedNode head)
        {
            LinkedNode node = head;

            while (node.Child0 != null)
            {
                int num = input.ReadBits(1);
                if (num == -1)
                {
                    throw new Exception("Unexpected end of file");
                }
                node = (num == 0) ? node.Child0 : node.Child1;
            }
            return(node);
        }
예제 #4
0
        private static LinkedNode BuildList(byte[] primeData)
        {
            LinkedNode root;

            root = new LinkedNode(256, 1);
            root = root.Insert(new LinkedNode(257, 1));

            for (int i = 0; i < primeData.Length; i++)
            {
                if (primeData[i] != 0)
                {
                    root = root.Insert(new LinkedNode(i, primeData[i]));
                }
            }
            return(root);
        }
예제 #5
0
        public static MemoryStream Decompress(Stream data)
        {
            int comptype = data.ReadByte();

            if (comptype == 0)
            {
                throw new NotImplementedException("Compression type 0 is not currently supported");
            }

            LinkedNode tail = BuildList(sPrime[comptype]);
            LinkedNode head = BuildTree(tail);

            MemoryStream outputstream = new MemoryStream();
            BitStream    bitstream    = new BitStream(data);
            int          decoded;

            do
            {
                LinkedNode node = Decode(bitstream, head);
                decoded = node.DecompressedValue;
                switch (decoded)
                {
                case 256:
                    break;

                case 257:
                    int newvalue = bitstream.ReadBits(8);
                    outputstream.WriteByte((byte)newvalue);
                    tail = InsertNode(tail, newvalue);
                    break;

                default:
                    outputstream.WriteByte((byte)decoded);
                    break;
                }
            } while (decoded != 256);

            outputstream.Seek(0, SeekOrigin.Begin);
            return(outputstream);
        }
        private static LinkedNode InsertNode(LinkedNode tail, int decomp)
        {
            LinkedNode node  = tail;
            LinkedNode prev  = tail.Prev;
            LinkedNode node3 = new LinkedNode(node.DecompressedValue, node.Weight)
            {
                Parent = node
            };
            LinkedNode newNode = new LinkedNode(decomp, 0)
            {
                Parent = node
            };

            node.Child0  = newNode;
            tail.Next    = node3;
            node3.Prev   = tail;
            newNode.Prev = node3;
            node3.Next   = newNode;
            AdjustTree(newNode);
            AdjustTree(newNode);
            return(prev);
        }
        public static MemoryStream Decompress(Stream data)
        {
            int decompressedValue;
            int index = data.ReadByte();

            if (index == 0)
            {
                throw new NotImplementedException("Compression type 0 is not currently supported");
            }
            LinkedNode   tail   = BuildList(sPrime[index]);
            LinkedNode   head   = BuildTree(tail);
            MemoryStream stream = new MemoryStream();
            BitStream    input  = new BitStream(data);

            do
            {
                decompressedValue = Decode(input, head).DecompressedValue;
                switch (decompressedValue)
                {
                case 0x100:
                    break;

                case 0x101:
                {
                    int decomp = input.ReadBits(8);
                    stream.WriteByte((byte)decomp);
                    tail = InsertNode(tail, decomp);
                    break;
                }

                default:
                    stream.WriteByte((byte)decompressedValue);
                    break;
                }
            }while (decompressedValue != 0x100);
            stream.Seek(0L, SeekOrigin.Begin);
            return(stream);
        }
예제 #8
0
        private static LinkedNode BuildTree(LinkedNode tail)
        {
            LinkedNode current = tail;

            while (current != null)
            {
                LinkedNode child0 = current;
                LinkedNode child1 = current.Prev;
                if (child1 == null)
                {
                    break;
                }

                LinkedNode parent = new LinkedNode(0, child0.Weight + child1.Weight);
                parent.Child0 = child0;
                child0.Parent = parent;
                child1.Parent = parent;

                current.Insert(parent);
                current = current.Prev.Prev;
            }
            return(current);
        }
        private static LinkedNode BuildTree(LinkedNode tail)
        {
            LinkedNode node = tail;

            while (node != null)
            {
                LinkedNode node2 = node;
                LinkedNode prev  = node.Prev;
                if (prev == null)
                {
                    return(node);
                }
                LinkedNode other = new LinkedNode(0, node2.Weight + prev.Weight)
                {
                    Child0 = node2
                };
                node2.Parent = other;
                prev.Parent  = other;
                node.Insert(other);
                node = node.Prev.Prev;
            }
            return(node);
        }
예제 #10
0
        private static LinkedNode InsertNode(LinkedNode tail, int decomp)
        {
            LinkedNode parent = tail;
            LinkedNode result = tail.Prev; // This will be the new tail after the tree is updated

            LinkedNode temp = new LinkedNode(parent.DecompressedValue, parent.Weight);
            temp.Parent = parent;

            LinkedNode newnode = new LinkedNode(decomp, 0);
            newnode.Parent = parent;

            parent.Child0 = newnode;

            tail.Next = temp;
            temp.Prev = tail;
            newnode.Prev = temp;
            temp.Next = newnode;

            AdjustTree(newnode);
            // TODO: For compression type 0, AdjustTree should be called
            // once for every value written and only once here
            AdjustTree(newnode);
            return result;
        }
예제 #11
0
        private static LinkedNode Decode(BitStream input, LinkedNode head)
        {
            LinkedNode node = head;

            while(node.Child0 != null)
            {
                int bit = input.ReadBits(1);
                if (bit == -1)
                    throw new Exception("Unexpected end of file");

                node = bit == 0 ? node.Child0 : node.Child1;
            }
            return node;
        }
예제 #12
0
        private static LinkedNode BuildTree(LinkedNode tail)
        {
            LinkedNode current = tail;

            while(current != null)
            {
                LinkedNode child0 = current;
                LinkedNode child1 = current.Prev;
                if (child1 == null) break;

                LinkedNode parent = new LinkedNode(0, child0.Weight + child1.Weight);
                parent.Child0 = child0;
                child0.Parent = parent;
                child1.Parent = parent;

                current.Insert(parent);
                current = current.Prev.Prev;
            }
            return current;
        }
예제 #13
0
        private static LinkedNode BuildList(byte[] primeData)
        {
            LinkedNode root;

            root = new LinkedNode(256, 1);
            root = root.Insert(new LinkedNode(257, 1));

            for(int i = 0; i < primeData.Length; i++)
            {
                if (primeData[i] != 0)
                    root = root.Insert(new LinkedNode(i, primeData[i]));
            }
            return root;
        }
예제 #14
0
        // This increases the weight of the new node and its antecendants
        // and adjusts the tree if needed
        private static void AdjustTree(LinkedNode newNode)
        {
            LinkedNode current = newNode;

            while (current != null)
            {
                current.Weight++;
                LinkedNode insertpoint;
                LinkedNode prev;
                // Go backwards thru the list looking for the insertion point
                insertpoint = current;
                while(true)
                {
                    prev = insertpoint.Prev;
                    if (prev == null) break;
                    if(prev.Weight >= current.Weight) break;
                    insertpoint = prev;
                }

                // No insertion point found
                if (insertpoint == current)
                {
                    current = current.Parent;
                    continue;
                }

                // The following code basicly swaps insertpoint with current

                // remove insert point
                if (insertpoint.Prev != null) insertpoint.Prev.Next = insertpoint.Next;
                insertpoint.Next.Prev = insertpoint.Prev;

                // Insert insertpoint after current
                insertpoint.Next = current.Next;
                insertpoint.Prev = current;
                if (current.Next != null) current.Next.Prev = insertpoint;
                current.Next = insertpoint;

                // remove current
                current.Prev.Next = current.Next;
                current.Next.Prev = current.Prev;

                // insert current after prev
                LinkedNode temp = prev.Next;
                current.Next = temp;
                current.Prev = prev;
                temp.Prev = current;
                prev.Next = current;

                // Set up parent/child links
                LinkedNode currentparent = current.Parent;
                LinkedNode insertparent = insertpoint.Parent;

                if (currentparent.Child0 == current)
                    currentparent.Child0 = insertpoint;

                if (currentparent != insertparent && insertparent.Child0 == insertpoint)
                    insertparent.Child0 = current;

                current.Parent = insertparent;
                insertpoint.Parent = currentparent;

                current = current.Parent;
            }
        }
예제 #15
0
        // This increases the weight of the new node and its antecendants
        // and adjusts the tree if needed
        private static void AdjustTree(LinkedNode newNode)
        {
            LinkedNode current = newNode;

            while (current != null)
            {
                current.Weight++;
                LinkedNode insertpoint;
                LinkedNode prev;
                // Go backwards thru the list looking for the insertion point
                insertpoint = current;
                while (true)
                {
                    prev = insertpoint.Prev;
                    if (prev == null)
                    {
                        break;
                    }
                    if (prev.Weight >= current.Weight)
                    {
                        break;
                    }
                    insertpoint = prev;
                }

                // No insertion point found
                if (insertpoint == current)
                {
                    current = current.Parent;
                    continue;
                }

                // The following code basicly swaps insertpoint with current

                // remove insert point
                if (insertpoint.Prev != null)
                {
                    insertpoint.Prev.Next = insertpoint.Next;
                }
                insertpoint.Next.Prev = insertpoint.Prev;

                // Insert insertpoint after current
                insertpoint.Next = current.Next;
                insertpoint.Prev = current;
                if (current.Next != null)
                {
                    current.Next.Prev = insertpoint;
                }
                current.Next = insertpoint;

                // remove current
                current.Prev.Next = current.Next;
                current.Next.Prev = current.Prev;

                // insert current after prev
                LinkedNode temp = prev.Next;
                current.Next = temp;
                current.Prev = prev;
                temp.Prev    = current;
                prev.Next    = current;

                // Set up parent/child links
                LinkedNode currentparent = current.Parent;
                LinkedNode insertparent  = insertpoint.Parent;

                if (currentparent.Child0 == current)
                {
                    currentparent.Child0 = insertpoint;
                }

                if (currentparent != insertparent && insertparent.Child0 == insertpoint)
                {
                    insertparent.Child0 = current;
                }

                current.Parent     = insertparent;
                insertpoint.Parent = currentparent;

                current = current.Parent;
            }
        }