Ejemplo n.º 1
0
		public static string Decode(Pair[] tree, BitArray data, int offset, int maxLength)
		{
			var sb = new StringBuilder();

			var start = tree.Length - 1;

			while (true)
			{
				var node = start;
				do
				{
					node = data[offset] == false
						? tree[node].Left
						: tree[node].Right;
					offset++;
				} while (node >= 0);

				var c = (ushort) (-1 - node);

				if (c == 0)
				{
					break;
				}

				sb.Append((char) c);

				if (sb.Length >= maxLength)
				{
					break;
				}
			}

			return sb.ToString();
		}
Ejemplo n.º 2
0
		public Pair[] GetPairs()
		{
			var pairs = new List<Pair>();
			var mapping = new Dictionary<Node, Pair>();

			var queue = new Queue<Node>();
			queue.Enqueue(_root);

			var root = new Pair();
			mapping.Add(_root, root);

			while (queue.Count > 0)
			{
				var node = queue.Dequeue();
				var pair = mapping[node];

				if (node.Left == null && node.Right == null)
				{
					throw new InvalidOperationException();
				}

				// ReSharper disable PossibleNullReferenceException
				if (node.Left.Left == null &&
					// ReSharper restore PossibleNullReferenceException
					node.Left.Right == null)
				{
					pair.Left = -1 - node.Left.Symbol;
				}
				else
				{
					var left = new Pair();
					mapping.Add(node.Left, left);
					pairs.Add(left);

					queue.Enqueue(node.Left);

					pair.Left = pairs.IndexOf(left);
				}

				if (node.Right.Left == null &&
					node.Right.Right == null)
				{
					pair.Right = -1 - node.Right.Symbol;
				}
				else
				{
					var right = new Pair();
					mapping.Add(node.Right, right);
					pairs.Add(right);

					queue.Enqueue(node.Right);

					pair.Right = pairs.IndexOf(right);
				}
			}

			pairs.Add(root);

			return pairs.ToArray();
		}
Ejemplo n.º 3
0
		public void Deserialize(Stream input)
		{
			var magic = input.ReadUInt32();

			if (magic != 0x666D726D && magic.Swap() != 0x666D726D)
			{
				throw new FormatException();
			}

			var endian = magic == 0x666D726D ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
			var version = input.ReadUInt32(endian);

			if (version != 1)
			{
				throw new FormatException();
			}

			Version = version;

			input.ReadInt32(endian);
			var maxValueLength = input.ReadInt32(endian);

			var stringTableSize = input.ReadUInt32(endian);
			var huffmanSize = input.ReadUInt32(endian);
			var indexSize = input.ReadUInt32(endian);
			var dataSize = input.ReadUInt32(endian);

			var strings = new List<KeyValuePair<uint, string>>();

			using (var data = input.ReadToMemoryStream(stringTableSize))
			{
				var localStringTableSize = data.ReadUInt32(endian);

				if (localStringTableSize != stringTableSize)
				{
					throw new FormatException();
				}

				var count = data.ReadUInt32(endian);

				var offsets = new List<KeyValuePair<uint, uint>>();

				for (uint i = 0; i < count; i++)
				{
					var hash = data.ReadUInt32(endian);
					var offset = data.ReadUInt32(endian);

					offsets.Add(new KeyValuePair<uint, uint>(hash, offset));
				}

				foreach (var kv in offsets)
				{
					var hash = kv.Key;
					var offset = kv.Value;

					data.Seek(8 + offset, SeekOrigin.Begin);
					var length = data.ReadUInt16(endian);
					var text = data.ReadString(length, Encoding.UTF8);

					if (text.HashCrc32() != hash)
					{
						throw new InvalidOperationException();
					}

					strings.Add(new KeyValuePair<uint, string>(hash, text));
				}
			}

			Pair[] huffmanTree;

			using (var data = input.ReadToMemoryStream(huffmanSize))
			{
				var count = data.ReadUInt16(endian);
				huffmanTree = new Pair[count];

				for (ushort i = 0; i < count; i++)
				{
					var left = data.ReadInt32(endian);
					var right = data.ReadInt32(endian);
					huffmanTree[i] = new Pair(left, right);
				}
			}

			using (var index = input.ReadToMemoryStream(indexSize))
			{
				var totalBits = input.ReadInt32(endian);
				var data = input.ReadBytes(dataSize);
				var bitArray = new BitArray(data)
				{
					Length = totalBits
				};

				var files = new List<KeyValuePair<string, uint>>();
				var fileCount = index.ReadUInt16(endian);

				for (ushort i = 0; i < fileCount; i++)
				{
					var nameIndex = index.ReadUInt16(endian);
					var name = strings[nameIndex].Value;
					var offset = index.ReadUInt32(endian);

					files.Add(new KeyValuePair<string, uint>(name, offset));
				}

				foreach (var fileInfo in files.OrderBy(f => f.Key))
				{
					var file = new FileEntry
					{
						Name = fileInfo.Key
					};

					index.Seek(fileInfo.Value, SeekOrigin.Begin);

					var sectionCount = index.ReadUInt16(endian);
					var sections = new List<KeyValuePair<string, uint>>();

					for (ushort i = 0; i < sectionCount; i++)
					{
						var nameIndex = index.ReadUInt16(endian);
						var name = strings[nameIndex].Value;
						var offset = index.ReadUInt32(endian);

						sections.Add(new KeyValuePair<string, uint>(name, offset));
					}

					foreach (var sectionInfo in sections.OrderBy(s => s.Key))
					{
						var section = new Dictionary<string, List<PropertyValue>>();

						index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin);
						var valueCount = index.ReadUInt16(endian);
						var values = new List<KeyValuePair<string, uint>>();

						for (ushort i = 0; i < valueCount; i++)
						{
							var nameIndex = index.ReadUInt16(endian);
							var name = strings[nameIndex].Value;
							var offset = index.ReadUInt32(endian);

							values.Add(new KeyValuePair<string, uint>(name, offset));
						}

						foreach (var valueInfo in values.OrderBy(v => v.Key))
						{
							var value = new List<PropertyValue>();

							index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin);
							var itemCount = index.ReadUInt16(endian);

							for (ushort i = 0; i < itemCount; i++)
							{
								var offset = index.ReadInt32(endian);

								var type = (offset & 0xE0000000) >> 29;
								
								switch (type)
								{
									case 1:
									{
										value.Add(new PropertyValue(1, null));

										break;
									}
									case 0:
									case 2:
									case 3:
									case 4:
									{
										offset &= 0x1fffffff;
										var text = Decoder.Decode(huffmanTree, bitArray, offset, maxValueLength);

										value.Add(new PropertyValue((int) type, text));

										break;
									}
									default:
									{
										throw new NotImplementedException();
									}
								}
							}

							section.Add(valueInfo.Key, value);
						}

						file.Sections.Add(sectionInfo.Key, section);
					}

					Files.Add(file);
				}
			}

			ByteOrder = endian;
		}