예제 #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;
		}
예제 #2
0
        private static LinkedNode BuildList(byte[] PrimeData)
        {
            var 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);
        }
예제 #3
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 MpqParserException("Unexpected end of file");
                }

                node = bit == 0 ? node.Child0 : node.Child1;
            }
            return(node);
        }
예제 #4
0
        public static byte[] 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);

            return(outputstream.ToArray());
        }
예제 #5
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);
        }
예제 #6
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;
            }
        }
예제 #7
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 prev;
				// Go backwards thru the list looking for the insertion point
				LinkedNode 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;
			}
		}
예제 #8
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;
		}
예제 #9
0
		private static LinkedNode BuildTree(LinkedNode Tail)
		{
			LinkedNode current = Tail;

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

				var 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;
		}
예제 #10
0
		private static LinkedNode BuildList(byte[] PrimeData)
		{
		    var 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;
		}
예제 #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 MpqParserException("Unexpected end of file");

				node = bit == 0 ? node.Child0 : node.Child1;
			}
			return node;
		}